[Loudmouth] Receiving messages >1023 bytes with SSL active in Loudmouth

Jaymie Oehler joehler at oncron.net
Mon Jan 29 22:24:58 CET 2007


I was using the Loudmouth library to send and receive jabber messages 
when I ran into the following problem. With SSL enabled (openssl), a 
message of size greater than 1023 bytes would not be fully processed 
until the next message arrived. I triaged the problem and found that the 
first 1023 bytes of the message were being received and processed, but 
the connection_in_event function wasn't triggering again until the next 
message was received on the IO channel, even though there were more 
bytes available to process. My assumption is that this is because the 
g_io_channel* functions are being bypassed to perform the read and 
SSL_read is being called instead when SSL is enabled on the connection.

I fixed the problem by applying the following patch. I'd appreciate any 
comments on whether other's have seen similar behavior and on the 
correctness of the solution. If the solution is correct and could be 
added to the loudmouth distribution, I would appreciate it.

Thanks. Jaymie

--- lm-connection.orig.c 2007-01-29 14:06:37.000000000 -0600
+++ lm-connection.c 2007-01-29 15:03:59.000000000 -0600
@@ -1111,6 +1111,59 @@
lm_verbose ("Read: %d chars\n", (int)bytes_read);

lm_parser_parse (connection->parser, buf);
+
+ // If this connection is SSL, we need to check to make sure there 
isn't more data to read
+ // because this event won't trigger again until the next time new data 
is received... For big
+ // messages (over 1023 bytes, the size of the IN_BUFFER_SIZE-1), this 
means that the remainder
+ // of the message will sit unprocessed until the next message is 
received.
+ if (connection->ssl) {
+ status = _lm_ssl_read (connection->ssl,
+ buf, IN_BUFFER_SIZE - 1, &bytes_read);
+
+ while ((status == G_IO_STATUS_NORMAL) && (bytes_read > 0)) {
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "Continue to read packet - 
status: %d bytes_read: %d\n", status, bytes_read);
+ buf[bytes_read] = '\0';
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "\nRECV [%d]:\n",
+ (int)bytes_read);
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
+ "-----------------------------------\n");
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "'%s'\n", buf);
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
+ "-----------------------------------\n");
+
+ lm_verbose ("Read: %d chars\n", (int)bytes_read);
+
+ lm_parser_parse (connection->parser, buf);
+
+ status = _lm_ssl_read (connection->ssl,
+ buf, IN_BUFFER_SIZE - 1, &bytes_read);
+ }
+
+ // Check to see if there was an error - The non-error case would be 
where 0 bytes were read
+ // and a status of G_IO_STATUS_AGAIN was returned
+ if ((status != G_IO_STATUS_AGAIN) || (bytes_read != 0)) {
+ gint reason;
+
+ switch (status) {
+ case G_IO_STATUS_EOF:
+ reason = LM_DISCONNECT_REASON_HUP;
+ break;
+ case G_IO_STATUS_AGAIN:
+ return TRUE;
+ break;
+ case G_IO_STATUS_ERROR:
+ reason = LM_DISCONNECT_REASON_ERROR;
+ break;
+ default:
+ reason = LM_DISCONNECT_REASON_UNKNOWN;
+ }
+
+ connection_do_close (connection);
+ connection_signal_disconnect (connection, reason);
+
+ return FALSE;
+ }
+ }

return TRUE;
}


More information about the Loudmouth mailing list