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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user