diff options
-rw-r--r-- | ChangeLog.asciidoc | 1 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.c | 108 |
2 files changed, 66 insertions, 43 deletions
diff --git a/ChangeLog.asciidoc b/ChangeLog.asciidoc index 658685ba8..cfb1107ad 100644 --- a/ChangeLog.asciidoc +++ b/ChangeLog.asciidoc @@ -70,6 +70,7 @@ http://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes] * alias: change default command for alias /beep to "/print -beep" * exec: add exec plugin: new command /exec and file exec.conf * guile: fix module used after unload of a script +* irc: fix truncated read on socket with SSL (bug #41558) * irc: add "#" before any channel in /join, even /join 0 (closes #20) * irc: display output of CAP LIST in server buffer * irc: fix colors in message with CTCP reply sent to another user diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index 44605dd4e..eac3ba5a7 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -2602,72 +2602,94 @@ irc_server_recv_cb (void *data, int fd) { struct t_irc_server *server; static char buffer[4096 + 2]; - int num_read; + int num_read, msgq_flush, end_recv; /* make C compiler happy */ (void) fd; server = (struct t_irc_server *)data; - if (!server) return WEECHAT_RC_ERROR; -#ifdef HAVE_GNUTLS - if (server->ssl_connected) - num_read = gnutls_record_recv (server->gnutls_sess, buffer, - sizeof (buffer) - 2); - else -#endif - num_read = recv (server->sock, buffer, sizeof (buffer) - 2, 0); + msgq_flush = 0; + end_recv = 0; - if (num_read > 0) - { - buffer[num_read] = '\0'; - irc_server_msgq_add_buffer (server, buffer); - irc_server_msgq_flush (); - } - else + while (!end_recv) { + end_recv = 1; + #ifdef HAVE_GNUTLS if (server->ssl_connected) + num_read = gnutls_record_recv (server->gnutls_sess, buffer, + sizeof (buffer) - 2); + else +#endif + num_read = recv (server->sock, buffer, sizeof (buffer) - 2, 0); + + if (num_read > 0) { - if ((num_read == 0) - || ((num_read != GNUTLS_E_AGAIN) && (num_read != GNUTLS_E_INTERRUPTED))) + buffer[num_read] = '\0'; + irc_server_msgq_add_buffer (server, buffer); + msgq_flush = 1; /* the flush will be done after the loop */ +#ifdef HAVE_GNUTLS + if (server->ssl_connected + && (gnutls_record_check_pending (server->gnutls_sess) > 0)) { - weechat_printf (server->buffer, - _("%s%s: reading data on socket: error %d %s"), - weechat_prefix ("error"), IRC_PLUGIN_NAME, - num_read, - (num_read == 0) ? _("(connection closed by peer)") : - gnutls_strerror (num_read)); - weechat_printf (server->buffer, - _("%s%s: disconnecting from server..."), - weechat_prefix ("network"), - IRC_PLUGIN_NAME); - irc_server_disconnect (server, !server->is_connected, 1); + /* + * if there are unread data in the gnutls buffers, + * go on with recv + */ + end_recv = 0; } +#endif } else -#endif { - if ((num_read == 0) - || ((errno != EAGAIN) && (errno != EWOULDBLOCK))) +#ifdef HAVE_GNUTLS + if (server->ssl_connected) { - weechat_printf (server->buffer, - _("%s%s: reading data on socket: error %d %s"), - weechat_prefix ("error"), IRC_PLUGIN_NAME, - errno, - (num_read == 0) ? _("(connection closed by peer)") : - strerror (errno)); - weechat_printf (server->buffer, - _("%s%s: disconnecting from server..."), - weechat_prefix ("network"), - IRC_PLUGIN_NAME); - irc_server_disconnect (server, !server->is_connected, 1); + if ((num_read == 0) + || ((num_read != GNUTLS_E_AGAIN) + && (num_read != GNUTLS_E_INTERRUPTED))) + { + weechat_printf (server->buffer, + _("%s%s: reading data on socket: error %d %s"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, + num_read, + (num_read == 0) ? _("(connection closed by peer)") : + gnutls_strerror (num_read)); + weechat_printf (server->buffer, + _("%s%s: disconnecting from server..."), + weechat_prefix ("network"), + IRC_PLUGIN_NAME); + irc_server_disconnect (server, !server->is_connected, 1); + } + } + else +#endif + { + if ((num_read == 0) + || ((errno != EAGAIN) && (errno != EWOULDBLOCK))) + { + weechat_printf (server->buffer, + _("%s%s: reading data on socket: error %d %s"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, + errno, + (num_read == 0) ? _("(connection closed by peer)") : + strerror (errno)); + weechat_printf (server->buffer, + _("%s%s: disconnecting from server..."), + weechat_prefix ("network"), + IRC_PLUGIN_NAME); + irc_server_disconnect (server, !server->is_connected, 1); + } } } } + if (msgq_flush) + irc_server_msgq_flush (); + return WEECHAT_RC_OK; } |