static wi_integer_t _wi_socket_read_buffer(wi_socket_t *socket, wi_time_interval_t timeout, void *buffer, size_t length) { wi_socket_state_t state; wi_integer_t bytes; #ifdef HAVE_OPENSSL_SSL_H if(socket->ssl) { if(timeout > 0.0 && SSL_pending(socket->ssl) == 0) { state = wi_socket_wait_descriptor(socket->sd, timeout, true, false); if(state != WI_SOCKET_READY) { if(state == WI_SOCKET_TIMEOUT) wi_error_set_errno(ETIMEDOUT); return -1; } } ERR_clear_error(); bytes = SSL_read(socket->ssl, buffer, length); if(bytes <= 0) { wi_error_set_openssl_ssl_error_with_result(socket->ssl, bytes); ERR_clear_error(); } return bytes; } else { #endif if(timeout > 0.0) { state = wi_socket_wait_descriptor(socket->sd, timeout, true, false); if(state != WI_SOCKET_READY) { if(state == WI_SOCKET_TIMEOUT) wi_error_set_errno(ETIMEDOUT); return -1; } } bytes = read(socket->sd, buffer, length); if(bytes <= 0) { if(bytes < 0) wi_error_set_errno(errno); else wi_error_set_libwired_error(WI_ERROR_SOCKET_EOF); } return bytes; #ifdef HAVE_OPENSSL_SSL_H } #endif return 0; }
wi_integer_t wi_socket_read_buffer(wi_socket_t *socket, wi_time_interval_t timeout, void *buffer, size_t length) { wi_time_interval_t interval; wi_socket_state_t state; wi_uinteger_t offset; wi_integer_t bytes; WI_ASSERT(buffer != NULL, "buffer of length %u should not be NULL", length); if(timeout > 0.0) { #ifdef HAVE_OPENSSL_SSL_H if(!socket->ssl || (socket->ssl && SSL_pending(socket->ssl) == 0)) { #endif state = wi_socket_wait_descriptor(socket->sd, timeout, true, false); if(state != WI_SOCKET_READY) { if(state == WI_SOCKET_TIMEOUT) wi_error_set_errno(ETIMEDOUT); return -1; } #ifdef HAVE_OPENSSL_SSL_H } #endif } interval = 0.0; #ifdef HAVE_OPENSSL_SSL_H if(socket->ssl) { do { bytes = SSL_read(socket->ssl, buffer, length); if(bytes <= 0) { if(bytes < 0 && SSL_get_error(socket->ssl, bytes) == SSL_ERROR_WANT_READ) { wi_thread_sleep(0.1); if(timeout > 0.0) { interval += 0.1; if(interval >= timeout) { wi_error_set_errno(ETIMEDOUT); break; } } } else { wi_error_set_openssl_ssl_error_with_result(socket->ssl, bytes); socket->broken = true; break; } } } while(bytes <= 0); return bytes; } else { #endif offset = 0; do { bytes = read(socket->sd, buffer + offset, length - offset); if(bytes <= 0) { if(bytes < 0) wi_error_set_errno(errno); else wi_error_set_libwired_error(WI_ERROR_SOCKET_EOF); return bytes; } offset += bytes; if(offset < length) { wi_thread_sleep(0.1); if(timeout > 0.0) { interval += 0.1; if(interval >= timeout) { wi_error_set_errno(ETIMEDOUT); return -1; } } } } while(offset < length); return offset; #ifdef HAVE_OPENSSL_SSL_H } #endif return 0; }
wi_boolean_t wi_socket_accept_tls(wi_socket_t *socket, wi_socket_tls_t *tls, wi_time_interval_t timeout) { wi_socket_state_t state; int err, result; wi_boolean_t blocking; socket->ssl = SSL_new(tls->ssl_ctx); if(!socket->ssl) { wi_error_set_openssl_error(); return false; } if(SSL_set_fd(socket->ssl, socket->sd) != 1) { wi_error_set_openssl_error(); return false; } if(!tls->private_key && tls->dh) { if(SSL_set_tmp_dh(socket->ssl, tls->dh) != 1) { wi_error_set_openssl_error(); return false; } } if(timeout > 0.0) { blocking = wi_socket_blocking(socket); if(blocking) wi_socket_set_blocking(socket, false); result = SSL_accept(socket->ssl); if(result != 1) { do { err = SSL_get_error(socket->ssl, result); if(err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) { wi_error_set_openssl_ssl_error_with_result(socket->ssl, result); return false; } state = wi_socket_wait_descriptor(socket->sd, 1.0, (err == SSL_ERROR_WANT_READ), (err == SSL_ERROR_WANT_WRITE)); if(state == WI_SOCKET_ERROR) break; else if(state == WI_SOCKET_READY) { result = SSL_accept(socket->ssl); if(result == 1) break; } timeout -= 1.0; } while(timeout >= 0.0); if(state == WI_SOCKET_ERROR) return false; if(timeout <= 0.0) { wi_error_set_errno(ETIMEDOUT); return false; } } if(blocking) wi_socket_set_blocking(socket, true); } else { result = SSL_accept(socket->ssl); if(result != 1) { wi_error_set_openssl_ssl_error_with_result(socket->ssl, result); return false; } } return true; }
wi_integer_t wi_socket_read_buffer(wi_socket_t *socket, wi_time_interval_t timeout, void *buffer, size_t length) { #ifdef HAVE_OPENSSL_SSL_H wi_socket_state_t state; #endif wi_uinteger_t offset; wi_integer_t bytes; WI_ASSERT(buffer != NULL, "buffer of length %u should not be NULL", length); WI_ASSERT(socket->sd >= 0, "socket %@ should be valid", socket); #ifdef HAVE_OPENSSL_SSL_H if(socket->ssl) { while(true) { if(timeout > 0.0 && SSL_pending(socket->ssl) == 0) { state = wi_socket_wait_descriptor(socket->sd, timeout, true, false); if(state != WI_SOCKET_READY) { if(state == WI_SOCKET_TIMEOUT) wi_error_set_errno(ETIMEDOUT); return -1; } } ERR_clear_error(); bytes = SSL_read(socket->ssl, buffer, length); if(bytes > 0) { break; } else { if(bytes < 0 && SSL_get_error(socket->ssl, bytes) == SSL_ERROR_WANT_READ) continue; wi_error_set_openssl_ssl_error_with_result(socket->ssl, bytes); break; } } ERR_clear_error(); return bytes; } else { #endif offset = 0; while(offset < length) { bytes = _wi_socket_read_buffer(socket, timeout, buffer + offset, length - offset); if(bytes <= 0) return -1; offset += bytes; } return offset; #ifdef HAVE_OPENSSL_SSL_H } #endif return 0; }