Ok - I can't see what would reset the WSAGetLastError - but clearly we shouldn't be relying on it not being reset that many calls after the actual write call. I'm thinking I will instead rewrite the logic so that the EAGAIN and EWOULDBLOCK handling is in the TcpConnection code itself. I checked the TlsConnection class and it handles these similar conditions within the subclass.
Here is a copy of the two new functions for you to try out:
int
TcpConnection::write( const char* buf, const int count )
{
//DebugLog (<< "Writing " << buf); // Note: this can end up writing garbage to the logs following the message for non-null terminated buffers
assert(buf);
assert(count > 0);
#if defined(WIN32)
int bytesWritten = ::send(getSocket(), buf, count, 0);
#else
int bytesWritten = ::write(getSocket(), buf, count);
#endif
if (bytesWritten == INVALID_SOCKET)
{
int e = getErrno();
//setFailureReason(TransportFailure::ConnectionException, e+1000);
{
// TCP buffers are backed up - we couldn't write anything - but we shouldn't treat this an error - return we wrote 0 bytes
return 0;
}
InfoLog (<< "Failed write on " << getSocket() << " " << strerror(e));
Transport::error(e);
return -1;
}
return bytesWritten;
}
int
Connection::performWrite()
{
....
int nBytes = write(data.data() + mSendPos,int(data.size() - mSendPos));
//DebugLog (<< "Tried to send " << data.size() - mSendPos << " bytes, sent " << nBytes << " bytes");
if (nBytes < 0)
{
//fail(data.transactionId);
InfoLog(<< "Write failed on socket: " << this->getSocket() << ", closing connection");
return -1;
}
else if (nBytes == 0)
{
// Nothing was written - likely socket buffers are backed up and EWOULDBLOCK was returned
// no need to do calculations in else statement
return 0;
}
else
{
// Safe because of the conditional above ( < 0 ).
Data::size_type bytesWritten = static_cast<Data::size_type>(nBytes);
mSendPos += bytesWritten;
if (mSendPos == data.size())
{
mSendPos = 0;
removeFrontOutstandingSend();
}
return bytesWritten;
}
}
Scott