summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.asciidoc1
-rw-r--r--src/plugins/irc/irc-server.c108
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;
}