[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