diff --git a/nsock/src/nsock_core.c b/nsock/src/nsock_core.c index 7d896fb5e..ad9fcaab8 100644 --- a/nsock/src/nsock_core.c +++ b/nsock/src/nsock_core.c @@ -537,43 +537,50 @@ void handle_write_result(struct npool *ms, struct nevent *nse, enum nse_status s if (nse->writeinfo.written_so_far > 0) assert(bytesleft > 0); #if HAVE_OPENSSL - if (iod->ssl) + if (iod->ssl) { res = SSL_write(iod->ssl, str, bytesleft); + if (res == bytesleft) { + nse->event_done = 1; + nse->status = NSE_STATUS_SUCCESS; + } else if (res > 0) { + // This should never happen unless we set SSL_MODE_ENABLE_PARTIAL_WRITE + nse->writeinfo.written_so_far += res; + } else { // res <= 0 + int evclr, evset; + err = SSL_get_error(iod->ssl, res); + switch(err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + evclr = socket_count_dec_ssl_desire(nse); + evset = (err == SSL_ERROR_WANT_READ) ? + socket_count_read_inc(iod) : + socket_count_write_inc(iod); + update_events(iod, ms, nse, evset, evclr); + nse->sslinfo.ssl_desire = err; + break; + default: + assert(err != SSL_ERROR_NONE); + /* Unexpected error */ + nse->event_done = 1; + nse->status = NSE_STATUS_ERROR; + nse->errnum = EIO; + nsock_log_info("SSL_write() failed for reason %s on NSI %li", + ERR_error_string(err, NULL), iod->id); + break; + } + } + } else #endif + { res = ms->engine->io_operations->iod_write(ms, nse->iod->sd, str, bytesleft, 0, (struct sockaddr *)&nse->writeinfo.dest, (int)nse->writeinfo.destlen); - if (res == bytesleft) { - nse->event_done = 1; - nse->status = NSE_STATUS_SUCCESS; - } else if (res >= 0) { - nse->writeinfo.written_so_far += res; - } else { - assert(res == -1); - if (iod->ssl) { -#if HAVE_OPENSSL - err = SSL_get_error(iod->ssl, res); - if (err == SSL_ERROR_WANT_READ) { - int evclr; - - evclr = socket_count_dec_ssl_desire(nse); - socket_count_read_inc(iod); - update_events(iod, ms, nse, EV_READ, evclr); - nse->sslinfo.ssl_desire = err; - } else if (err == SSL_ERROR_WANT_WRITE) { - int evclr; - - evclr = socket_count_dec_ssl_desire(nse); - socket_count_write_inc(iod); - update_events(iod, ms, nse, EV_WRITE, evclr); - nse->sslinfo.ssl_desire = err; - } else { - /* Unexpected error */ - nse->event_done = 1; - nse->status = NSE_STATUS_ERROR; - nse->errnum = EIO; - } -#endif + if (res == bytesleft) { + nse->event_done = 1; + nse->status = NSE_STATUS_SUCCESS; + } else if (res >= 0) { + nse->writeinfo.written_so_far += res; } else { + assert(res == -1); err = socket_errno(); if (errcode_is_failure(err)) { nse->event_done = 1; @@ -714,30 +721,34 @@ static int do_actual_read(struct npool *ms, struct nevent *nse) { return fs_length(&nse->iobuf) - startlen; } - if (buflen == -1) { + if (buflen <= 0) { + int evclr, evset; err = SSL_get_error(iod->ssl, buflen); - if (err == SSL_ERROR_WANT_READ) { - int evclr; - - evclr = socket_count_dec_ssl_desire(nse); - socket_count_read_inc(iod); - update_events(iod, ms, nse, EV_READ, evclr); - nse->sslinfo.ssl_desire = err; - } else if (err == SSL_ERROR_WANT_WRITE) { - int evclr; - - evclr = socket_count_dec_ssl_desire(nse); - socket_count_write_inc(iod); - update_events(iod, ms, nse, EV_WRITE, evclr); - nse->sslinfo.ssl_desire = err; - } else { - /* Unexpected error */ - nse->event_done = 1; - nse->status = NSE_STATUS_ERROR; - nse->errnum = EIO; - nsock_log_info("SSL_read() failed for reason %s on NSI %li", - ERR_error_string(err, NULL), iod->id); - return -1; + switch (err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + evclr = socket_count_dec_ssl_desire(nse); + evset = (err == SSL_ERROR_WANT_READ) ? + socket_count_read_inc(iod) : + socket_count_write_inc(iod); + update_events(iod, ms, nse, evset, evclr); + nse->sslinfo.ssl_desire = err; + /* Not EOF! */ + buflen = 1; + break; + case SSL_ERROR_ZERO_RETURN: + /* EOF because of close_notify */ + buflen = 0; + break; + default: + assert(err != SSL_ERROR_NONE); + /* Unexpected error */ + nse->event_done = 1; + nse->status = NSE_STATUS_ERROR; + nse->errnum = EIO; + nsock_log_info("SSL_read() failed for reason %s on NSI %li", + ERR_error_string(err, NULL), iod->id); + return -1; } } #endif /* HAVE_OPENSSL */