1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-27 13:26:38 +02:00

irc: fix truncated read on socket with SSL (bug #41558)

If there are still data on socket with SSL
(if gnutls_record_check_pending(session) returns > 0), then call
gnutls_record_recv() again to read all available data.

The problem was that some data remained in the gnutls buffers and the recv
callback was not called any more (nothing available on raw socket).
This commit is contained in:
Sebastien Helleu
2014-03-18 13:27:18 +01:00
parent ffb0ec47c2
commit 387cc5048a
2 changed files with 69 additions and 46 deletions
+1
View File
@@ -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
+68 -46
View File
@@ -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)
{
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);
}
}
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)
|| ((errno != EAGAIN) && (errno != EWOULDBLOCK)))
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,
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 there are unread data in the gnutls buffers,
* go on with recv
*/
end_recv = 0;
}
#endif
}
else
{
#ifdef HAVE_GNUTLS
if (server->ssl_connected)
{
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;
}