1
1

channel/transport: we now drain the outgoing send buffer when we ignore EAGAIN

When we ignore the EAGAIN from the transport layer within channel_write, we
now drain the outgoing transport layer buffer so that remainders in that
won't cause any problems in the next invoke of _libssh2_transport_write()
Этот коммит содержится в:
Daniel Stenberg 2010-04-15 01:12:22 +02:00
родитель 8b63dc9e59
Коммит 7f740368f4
3 изменённых файлов: 39 добавлений и 16 удалений

Просмотреть файл

@ -1979,6 +1979,17 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
while (buflen > 0) {
if (channel->write_state == libssh2_NB_state_allocated) {
/* drain the incoming flow first */
do
rc = _libssh2_transport_read(session);
while (rc > 0);
if(channel->local.window_size <= 0) {
/* there's no more room for data so we stop sending now */
break;
}
channel->write_bufwrite = buflen;
channel->write_s = channel->write_packet;
@ -1992,16 +2003,6 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
channel->write_s += 4;
}
/* drain the incoming flow first */
do
rc = _libssh2_transport_read(session);
while (rc > 0);
if(channel->local.window_size <= 0) {
/* there's no more room for data so we stop sending now */
break;
}
/* Don't exceed the remote end's limits */
/* REMEMBER local means local as the SOURCE of the data */
if (channel->write_bufwrite > channel->local.window_size) {
@ -2038,11 +2039,13 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
channel->write_s -
channel->write_packet);
if (rc == PACKET_EAGAIN) {
if(wrote)
/* some pieces of data was sent before the EAGAIN so
we return that amount! */
if(wrote) {
/* some pieces of data was sent before the EAGAIN so we
return that amount! As we ignore EAGAIN, we must drain
the outgoing transport buffer. */
_libssh2_transport_drain(session);
goto _channel_write_done;
}
return libssh2_error(session, rc,
"Unable to send channel data");
}

Просмотреть файл

@ -1,5 +1,5 @@
/* Copyright (C) 2007 The Written Word, Inc. All rights reserved.
* Copyright (C) 2009 by Daniel Stenberg
* Copyright (C) 2009-2010 by Daniel Stenberg
* Author: Daniel Stenberg <daniel@haxx.se>
*
* Redistribution and use in source and binary forms,
@ -600,6 +600,20 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
return PACKET_FAIL; /* we never reach this point */
}
/*
* _libssh2_transport_drain() empties the outgoing send buffer if there
* is any.
*/
void _libssh2_transport_drain(LIBSSH2_SESSION * session)
{
struct transportpacket *p = &session->packet;
if(p->outbuf) {
LIBSSH2_FREE(session, p->outbuf);
p->outbuf = NULL;
p->ototal_num = 0;
}
}
static int
send_existing(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len, ssize_t * ret)

Просмотреть файл

@ -2,7 +2,7 @@
#define __LIBSSH2_TRANSPORT_H
/* Copyright (C) 2007 The Written Word, Inc. All rights reserved.
* Copyright (C) 2009 by Daniel Stenberg
* Copyright (C) 2009-2010 by Daniel Stenberg
* Author: Daniel Stenberg <daniel@haxx.se>
*
* Redistribution and use in source and binary forms,
@ -77,4 +77,10 @@ int _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
*/
int _libssh2_transport_read(LIBSSH2_SESSION * session);
/*
* _libssh2_transport_drain() empties the outgoing send buffer if there
* is any.
*/
void _libssh2_transport_drain(LIBSSH2_SESSION *session);
#endif /* __LIBSSH2_TRANSPORT_H */