Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
0
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;
}