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()
Этот коммит содержится в:
родитель
8b63dc9e59
Коммит
7f740368f4
@ -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 */
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user