* FIXME. This will have to be done better when we * start managing multiple sockets (e.g. SSH port * forwarding), because if we get CONNRESET while * trying to write a particular forwarded socket * then it isn't necessarily the end of the world. * Ideally I'd like to pass the error code back to * somewhere the next select_result() will see it, * but that might be hard. Perhaps I should pass it * back to be queued in the Windows front end bit.
* ASSUMPTION: * * I'm assuming here that if a TCP connection is * reset or aborted once established, we will be * notified by a select event rather than a * CONNABORTED or CONNRESET from send(). In other * words, I'm assuming CONNABORTED and CONNRESET * don't come back from a _nonblocking_ send(), * because the local side doesn't know they've * happened until it waits for a response to its * TCP segment - so the error will arrive * asynchronously. * * If I'm wrong, this will be a really nasty case, * because we can't necessarily call plug_closing() * without having to make half the SSH code * reentrant; so instead we'll have to schedule a * call to plug_closing() for some suitable future * time.
void try_send(Actual_Socket s){    while (s->sending_oob || bufchain_size(&s->output_data) > 0) {	int nsent;	DWORD err;	void *data;	int len, urgentflag;	if (s->sending_oob) {	    urgentflag = MSG_OOB;	    len = s->sending_oob;	    data = &s->oobdata;	} else {	    urgentflag = 0;	    bufchain_prefix(&s->output_data, &data, &len);	}	nsent = send(s->s, data, len, urgentflag);	noise_ultralight(nsent);	if (nsent <= 0) {	    err = (nsent < 0 ? WSAGetLastError() : 0);	    if ((err < WSABASEERR && nsent < 0) || err == WSAEWOULDBLOCK) {		/*		 * Perfectly normal: we've sent all we can for the moment.		 * 		 * (Some WinSock send() implementations can return		 * <0 but leave no sensible error indication -		 * WSAGetLastError() is called but returns zero or		 * a small number - so we check that case and treat		 * it just like WSAEWOULDBLOCK.)		 */		s->writable = FALSE;		return;	    } else if (nsent == 0 ||		       err == WSAECONNABORTED || err == WSAECONNRESET) {		/*		 * FIXME. This will have to be done better when we		 * start managing multiple sockets (e.g. SSH port		 * forwarding), because if we get CONNRESET while		 * trying to write a particular forwarded socket		 * then it isn't necessarily the end of the world.		 * Ideally I'd like to pass the error code back to		 * somewhere the next select_result() will see it,		 * but that might be hard. Perhaps I should pass it		 * back to be queued in the Windows front end bit.		 */		fatalbox(winsock_error_string(err));	    } else {		fatalbox(winsock_error_string(err));	    }	} else {	    if (s->sending_oob) {		if (nsent < len) {		    memmove(s->oobdata, s->oobdata+nsent, len-nsent);		    s->sending_oob = len - nsent;		} else {		    s->sending_oob = 0;		}	    } else {		bufchain_consume(&s->output_data, nsent);	    }	}    }}