Beispiel #1
0
static wi_boolean_t _wi_settings_set_port(wi_settings_t *settings, wi_uinteger_t index, wi_string_t *name, wi_string_t *value) {
	struct servent		*servent;
	wi_uinteger_t		port;
	
	port = wi_string_uinteger(value);
	
	if(port > 65535) {
		wi_error_set_libwired_error(WI_ERROR_SETTINGS_INVALIDPORT);
		
		return false;
	}
	
	if(port == 0) {
		servent = getservbyname(wi_string_cstring(value), "tcp");
		
		if(!servent) {
			wi_error_set_libwired_error(WI_ERROR_SETTINGS_NOSUCHSERVICE);

			return false;
		}
		
		port = servent->s_port;
	}
	
	*(wi_uinteger_t *) settings->spec[index].setting = port;
	
	return true;
}
Beispiel #2
0
wi_terminal_t * wi_terminal_init_with_type(wi_terminal_t *terminal, wi_string_t *type) {
	char		*env;
	int			err, co, li;
	
	err = tgetent(NULL, wi_string_cstring(type));
	
	if(err <= 0) {
		if(err == 0)
			wi_error_set_libwired_error(WI_ERROR_TERMCAP_NOSUCHENTRY);
		else
			wi_error_set_libwired_error(WI_ERROR_TERMCAP_TERMINFONOTFOUND);

		wi_release(terminal);
		
		return NULL;
	}

	env = getenv("COLUMNS");
	co = env ? strtol(env, NULL, 10) : tgetnum("co");
	terminal->co = (co <= 0) ? 80 : co;

	env = getenv("LINES");
	li = env ? strtol(env, NULL, 10) : tgetnum("li");
	terminal->li = (li <= 0) ? 24 : li;

	terminal->ce = (char *) tgetstr("ce", NULL);
	terminal->cl = (char *) tgetstr("cl", NULL);
	terminal->cm = (char *) tgetstr("cm", NULL);
	terminal->cs = (char *) tgetstr("cs", NULL);
	
	terminal->scroll	= wi_make_range(0, terminal->li);
	terminal->buffers	= wi_array_init_with_capacity(wi_mutable_array_alloc(), 10);
	
	return terminal;
}
Beispiel #3
0
int wi_log_syslog_facility_with_name(wi_string_t *name) {
#if HAVE_SYSLOG_FACILITYNAMES
	const char		*cstring;
	int				i;
	
	cstring = wi_string_cstring(name);
	
	for(i = 0; facilitynames[i].c_name != NULL; i++) {
		if(strcmp(cstring, facilitynames[i].c_name) == 0)
			break;
	}

	if(!facilitynames[i].c_name) {
		wi_error_set_libwired_error(WI_ERROR_LOG_NOSUCHFACILITY);
		
		return -1;
	}

	return facilitynames[i].c_val;
#else
	wi_error_set_errno(ENOTSUP);
	
	return -1;
#endif
}
Beispiel #4
0
void wi_error_set_openssl_ssl_error_with_result(void *ssl, int result) {
	wi_error_t		*error;
	int				code;
	
	code = SSL_get_error(ssl, result);
	
	if(code == SSL_ERROR_SYSCALL) {
		if(ERR_peek_error() == 0) {
			if(result == 0)
				wi_error_set_libwired_error(WI_ERROR_SOCKET_EOF);
			else
				wi_error_set_errno(errno);
		} else {
			wi_error_set_openssl_error();
		}
	}
	else if(code == SSL_ERROR_SSL) {
		wi_error_set_openssl_error();
	} else {
		error = _wi_error_get_error();
		error->domain = WI_ERROR_DOMAIN_OPENSSL_SSL;
		error->code = code;

		wi_release(error->string);

		switch(error->code) {
			case SSL_ERROR_NONE:
				error->string = wi_retain(WI_STR("SSL: No error"));
				break;

			case SSL_ERROR_ZERO_RETURN:
				error->string = wi_retain(WI_STR("SSL: Zero return"));
				break;
				
			case SSL_ERROR_WANT_READ:
				error->string = wi_retain(WI_STR("SSL: Want read"));
				break;
				
			case SSL_ERROR_WANT_WRITE:
				error->string = wi_retain(WI_STR("SSL: Want write"));
				break;
				
			case SSL_ERROR_WANT_CONNECT:
				error->string = wi_retain(WI_STR("SSL: Want connect"));
				break;
				
			case SSL_ERROR_WANT_ACCEPT:
				error->string = wi_retain(WI_STR("SSL: Want accept"));
				break;
				
			case SSL_ERROR_WANT_X509_LOOKUP:
				error->string = wi_retain(WI_STR("SSL: Want X509 lookup"));
				break;
		}
	}
	
	ERR_clear_error();
}
Beispiel #5
0
void wi_error_set_openssl_ssl_error_with_result(void *ssl, int result) {
	wi_string_t		*string;
	int				code;
	
	code = SSL_get_error(ssl, result);
	
	if(code == SSL_ERROR_SYSCALL) {
		if(ERR_peek_error() == 0) {
			if(result == 0)
				wi_error_set_libwired_error(WI_ERROR_SOCKET_EOF);
			else
				wi_error_set_errno(errno);
		} else {
			wi_error_set_openssl_error();
		}
	}
	else if(code == SSL_ERROR_SSL) {
		wi_error_set_openssl_error();
	} else {
		switch(code) {
			case SSL_ERROR_NONE:
				string = WI_STR("SSL: No error");
				break;

			case SSL_ERROR_ZERO_RETURN:
				string = WI_STR("SSL: Zero return");
				break;
				
			case SSL_ERROR_WANT_READ:
				string = WI_STR("SSL: Want read");
				break;
				
			case SSL_ERROR_WANT_WRITE:
				string = WI_STR("SSL: Want write");
				break;
				
			case SSL_ERROR_WANT_CONNECT:
				string = WI_STR("SSL: Want connect");
				break;
				
			case SSL_ERROR_WANT_ACCEPT:
				string = WI_STR("SSL: Want accept");
				break;
				
			case SSL_ERROR_WANT_X509_LOOKUP:
				string = WI_STR("SSL: Want X509 lookup");
				break;
			
			default:
				string = NULL;
				break;
		}
		
		wi_error_set_error_with_string(WI_ERROR_DOMAIN_OPENSSL_SSL, code, string);
	}
	
	ERR_clear_error();
}
Beispiel #6
0
static wi_boolean_t _wi_settings_set_value(wi_settings_t *settings, wi_string_t *name, wi_string_t *value) {
	wi_uinteger_t	index;
	wi_boolean_t	result = false;
	
	index = _wi_settings_index_of_name(settings, name);
	
	if(index == WI_NOT_FOUND) {
		wi_error_set_libwired_error(WI_ERROR_SETTINGS_UNKNOWNSETTING);
		
		return false;
	}
	
	wi_log_debug(WI_STR("  %@ = %@"), name, value);
	
	switch(settings->spec[index].type) {
		case WI_SETTINGS_NUMBER:
			result = _wi_settings_set_number(settings, index, name, value);
			break;

		case WI_SETTINGS_BOOL:
			result = _wi_settings_set_bool(settings, index, name, value);
			break;

		case WI_SETTINGS_STRING:
			result = _wi_settings_set_string(settings, index, name, value);
			break;

		case WI_SETTINGS_STRING_ARRAY:
			result = _wi_settings_set_string_array(settings, index, name, value);
			break;

		case WI_SETTINGS_PATH:
			result = _wi_settings_set_path(settings, index, name, value);
			break;

		case WI_SETTINGS_USER:
			result = _wi_settings_set_user(settings, index, name, value);
			break;

		case WI_SETTINGS_GROUP:
			result = _wi_settings_set_group(settings, index, name, value);
			break;

		case WI_SETTINGS_PORT:
			result = _wi_settings_set_port(settings, index, name, value);
			break;
		
		case WI_SETTINGS_REGEXP:
			result = _wi_settings_set_regexp(settings, index, name, value);
			break;
		
		case WI_SETTINGS_TIME_INTERVAL:
			result = _wi_settings_set_time_interval(settings, index, name, value);
			break;
	}
	
	return result;
}
Beispiel #7
0
wi_boolean_t wi_socket_tls_set_ciphers(wi_socket_tls_t *tls, wi_string_t *ciphers) {
	if(SSL_CTX_set_cipher_list(tls->ssl_ctx, wi_string_cstring(ciphers)) != 1) {
		wi_error_set_libwired_error(WI_ERROR_SOCKET_NOVALIDCIPHER);

		return false;
	}
	
	return true;
}
Beispiel #8
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;
}
Beispiel #9
0
wi_cipher_t * wi_cipher_init_with_key(wi_cipher_t *cipher, wi_cipher_type_t type, wi_data_t *key, wi_data_t *iv) {
	if(!_wi_cipher_set_type(cipher, type)) {
		wi_error_set_libwired_error(WI_ERROR_CIPHER_CIPHERNOTSUPP);
		
		wi_release(cipher);
		
		return NULL;
	}
	
	return _wi_cipher_init_with_key(cipher, key, iv);
}
Beispiel #10
0
wi_cipher_t * wi_cipher_init_with_random_key(wi_cipher_t *cipher, wi_cipher_type_t type) {
	wi_data_t			*key, *iv;

	if(!_wi_cipher_set_type(cipher, type)) {
		wi_error_set_libwired_error(WI_ERROR_CIPHER_CIPHERNOTSUPP);
		
		wi_release(cipher);
		
		return NULL;
	}
	
	key = wi_data_with_random_bytes(wi_cipher_bits(cipher) / 8);
	iv = wi_data_with_random_bytes(wi_cipher_block_size(cipher));
	
	return _wi_cipher_init_with_key(cipher, key, iv);
}
Beispiel #11
0
wi_p7_message_t * wi_p7_message_init_with_bytes(wi_p7_message_t *p7_message, const void *bytes, wi_uinteger_t length, wi_p7_serialization_t serialization, wi_p7_spec_t *p7_spec) {
	p7_message->spec			= wi_retain(p7_spec);

	p7_message->binary_size		= length;
	p7_message->binary_capacity	= p7_message->binary_size;
	p7_message->binary_buffer	= wi_malloc(p7_message->binary_capacity);
	
	memcpy(p7_message->binary_buffer, bytes, p7_message->binary_size);
	
	wi_p7_message_deserialize(p7_message, WI_P7_BINARY);
	
	if(!p7_message->name) {
		wi_error_set_libwired_error(WI_ERROR_P7_UNKNOWNMESSAGE);
		
		wi_release(p7_message);
		
		return NULL;
	}

	return p7_message;
}
Beispiel #12
0
wi_boolean_t _wi_settings_set_group(wi_settings_t *settings, wi_uinteger_t index, wi_string_t *name, wi_string_t *value) {
	struct group		*group;
	uint32_t			gid;
	
	group = getgrnam(wi_string_cstring(value));
	
	if(!group) {
		gid = wi_string_uint32(value);
		
		if(gid != 0 || wi_is_equal(value, WI_STR("0")))
			group = getgrgid(wi_string_uint32(value));
	}

	if(!group) {
		wi_error_set_libwired_error(WI_ERROR_SETTINGS_NOSUCHGROUP);

		return false;
	}

	*(gid_t *) settings->spec[index].setting = group->gr_gid;
	
	return true;
}
Beispiel #13
0
wi_boolean_t _wi_settings_set_user(wi_settings_t *settings, wi_uinteger_t index, wi_string_t *name, wi_string_t *value) {
	struct passwd		*user;
	uint32_t			uid;
	
	user = getpwnam(wi_string_cstring(value));
	
	if(!user) {
		uid = wi_string_uint32(value);
		
		if(uid != 0 || wi_is_equal(value, WI_STR("0")))
			user = getpwuid(uid);
	}
	
	if(!user) {
		wi_error_set_libwired_error(WI_ERROR_SETTINGS_NOSUCHUSER);
		
		return false;
	}

	*(uid_t *) settings->spec[index].setting = user->pw_uid;
	
	return true;
}
Beispiel #14
0
static wi_boolean_t _wi_settings_parse_setting(wi_settings_t *settings, wi_string_t *string) {
	wi_array_t		*array;
	wi_string_t		*name, *value;
	wi_boolean_t	result = false;
	
	array = wi_string_components_separated_by_string(string, WI_STR("="));
	
	if(wi_array_count(array) != 2) {
		wi_error_set_libwired_error(WI_ERROR_SETTINGS_SYNTAXERROR);
		
		_wi_settings_log_error(settings, string);

		return false;
	}
	
	name	= wi_string_by_deleting_surrounding_whitespace(WI_ARRAY(array, 0));
	value	= wi_string_by_deleting_surrounding_whitespace(WI_ARRAY(array, 1));
	result	= _wi_settings_set_value(settings, name, value);
	
	if(!result)
		_wi_settings_log_error(settings, name);

	return result;
}
Beispiel #15
0
wi_boolean_t wi_config_read_file(wi_config_t *config) {
	wi_enumerator_t				*enumerator;
	wi_runtime_instance_t		*instance;
	wi_file_t					*file;
	wi_mutable_array_t			*array;
	wi_mutable_dictionary_t		*previous_values;
	wi_string_t					*string, *name, *value;
	wi_config_type_t			type;
	
	file = wi_file_for_reading(config->path);
	
	if(!file) {
		wi_log_err(WI_STR("Could not open %@: %m"),
			config->path);
		
		return false;
	}
	
	wi_log_info(WI_STR("Reading %@"), config->path);
	
	config->line = 0;
	
	wi_lock_lock(config->lock);
	
	previous_values = config->values;
	
	config->values = wi_dictionary_init(wi_mutable_dictionary_alloc());
	
	if(config->defaults) {
		enumerator = wi_dictionary_key_enumerator(config->defaults);
		
		while((name = wi_enumerator_next_data(enumerator))) {
//			instance = wi_mutable_copy(wi_dictionary_data_for_key(config->defaults, name));
			instance = wi_dictionary_data_for_key(config->defaults, name);
			if(wi_runtime_id(instance) == wi_array_runtime_id())
				instance = wi_autorelease(wi_mutable_copy(instance));
			wi_mutable_dictionary_set_data_for_key(config->values, instance, name);
//			wi_release(instance);
		}
	}
	
	while((string = wi_file_read_line(file))) {
		config->line++;

		if(wi_string_length(string) > 0 && !wi_string_has_prefix(string, WI_STR("#"))) {
			if(_wi_config_parse_string(config, string, &name, &value)) {
				instance = _wi_config_instance_for_setting(config, name, value, &type);
				
				if(instance) {
					wi_log_debug(WI_STR("  %@ = %@"), name, value);
					
					if(type == WI_CONFIG_STRINGLIST) {
						array = wi_dictionary_data_for_key(config->values, name);
						
						if(!array) {
							array = wi_mutable_array();
							
							wi_mutable_dictionary_set_data_for_key(config->values, array, name);
						}
						
						wi_mutable_array_add_data(array, instance);
					} else {
						wi_mutable_dictionary_set_data_for_key(config->values, instance, name);
					}
				} else {
					_wi_config_log_error(config, name);
				}
			} else {
				wi_error_set_libwired_error(WI_ERROR_SETTINGS_SYNTAXERROR);
				
				_wi_config_log_error(config, string);
			}
		}
	}
	
	enumerator = wi_dictionary_key_enumerator(config->values);
	
	while((name = wi_enumerator_next_data(enumerator))) {
		instance = wi_dictionary_data_for_key(config->values, name);
		
		if(!previous_values || !wi_is_equal(instance, wi_dictionary_data_for_key(previous_values, name)))
			wi_mutable_set_add_data(config->changes, name);
	}
	
	wi_release(previous_values);

	wi_lock_unlock(config->lock);

	return true;
}
Beispiel #16
0
static wi_runtime_instance_t * _wi_config_instance_for_setting(wi_config_t *config, wi_string_t *name, wi_string_t *value, wi_config_type_t *type) {
	struct passwd		*user;
	struct group		*group;
	struct servent		*servent;
	wi_uinteger_t		port;
	uint32_t			uid, gid;
	
	if(!wi_dictionary_contains_key(config->types, name)) {
		wi_error_set_libwired_error(WI_ERROR_SETTINGS_UNKNOWNSETTING);
		
		return NULL;
	}
	
	*type = wi_number_int32(wi_dictionary_data_for_key(config->types, name));
	
	switch(*type) {
		case WI_CONFIG_INTEGER:
			return wi_number_with_integer(wi_string_integer(value));
			break;
			
		case WI_CONFIG_BOOL:
			return wi_number_with_bool(wi_string_bool(value));
			break;
			
		case WI_CONFIG_STRING:
		case WI_CONFIG_STRINGLIST:
		case WI_CONFIG_PATH:
			return value;
			break;
			
		case WI_CONFIG_USER:
			user = getpwnam(wi_string_cstring(value));
			
			if(!user) {
				uid = wi_string_uint32(value);
				
				if(uid != 0 || wi_is_equal(value, WI_STR("0")))
					user = getpwuid(uid);
			}
			
			if(!user) {
				wi_error_set_libwired_error(WI_ERROR_SETTINGS_NOSUCHUSER);
				
				return NULL;
			}
			
			return wi_number_with_int32(user->pw_uid);
			break;
			
		case WI_CONFIG_GROUP:
			group = getgrnam(wi_string_cstring(value));
			
			if(!group) {
				gid = wi_string_uint32(value);
				
				if(gid != 0 || wi_is_equal(value, WI_STR("0")))
					group = getgrgid(gid);
			}
			
			if(!group) {
				wi_error_set_libwired_error(WI_ERROR_SETTINGS_NOSUCHGROUP);
				
				return NULL;
			}
			
			return wi_number_with_int32(group->gr_gid);
			break;
			
		case WI_CONFIG_PORT:
			port = wi_string_uinteger(value);
			
			if(port > 65535) {
				wi_error_set_libwired_error(WI_ERROR_SETTINGS_INVALIDPORT);
				
				return NULL;
			}
			
			if(port == 0) {
				servent = getservbyname(wi_string_cstring(value), "tcp");
				
				if(!servent) {
					wi_error_set_libwired_error(WI_ERROR_SETTINGS_NOSUCHSERVICE);
					
					return NULL;
				}
				
				port = servent->s_port;
			}
			
			return wi_number_with_int32(port);
			break;
			
		case WI_CONFIG_REGEXP:
			return wi_autorelease(wi_regexp_init_with_string(wi_regexp_alloc(), value));
			break;
			
		case WI_CONFIG_TIME_INTERVAL:
			return wi_number_with_double(wi_string_double(value));
			break;
	}
	
	return NULL;
}
Beispiel #17
0
static wi_boolean_t _wi_config_write_setting_to_file(wi_config_t *config, wi_string_t *name, wi_file_t *file) {
	wi_runtime_instance_t		*value;
	wi_config_type_t			type;
	struct passwd				*user;
	struct group				*group;
	wi_uinteger_t				i, count;
	
	if(!wi_dictionary_contains_key(config->types, name)) {
		wi_error_set_libwired_error(WI_ERROR_SETTINGS_UNKNOWNSETTING);

		return false;
	}
	
	type = wi_number_int32(wi_dictionary_data_for_key(config->types, name));
	value = wi_dictionary_data_for_key(config->values, name);
	
	if(!value)
		return false;
	
	switch(type) {
		case WI_CONFIG_INTEGER:
			wi_file_write_format(file, WI_STR("%@ = %d\n"), name, wi_number_integer(value));
			break;
			
		case WI_CONFIG_BOOL:
			wi_file_write_format(file, WI_STR("%@ = %@\n"), name, wi_number_bool(value) ? WI_STR("yes") : WI_STR("no"));
			break;
			
		case WI_CONFIG_STRING:
			wi_file_write_format(file, WI_STR("%@ = %@\n"), name, value);
			break;
			
		case WI_CONFIG_STRINGLIST:
			count = wi_array_count(value);
			
			for(i = 0; i < count; i++)
				wi_file_write_format(file, WI_STR("%@ = %@\n"), name, WI_ARRAY(value, i));
			break;
			
		case WI_CONFIG_PATH:
			wi_file_write_format(file, WI_STR("%@ = %@\n"), name, value);
			break;
			
		case WI_CONFIG_USER:
			user = getpwuid(wi_number_int32(value));
			
			if(user)
				wi_file_write_format(file, WI_STR("%@ = %s\n"), name, user->pw_name);
			else
				wi_file_write_format(file, WI_STR("%@ = %d\n"), name, wi_number_int32(value));
			break;
			
		case WI_CONFIG_GROUP:
			group = getgrgid(wi_number_int32(value));
			
			if(group)
				wi_file_write_format(file, WI_STR("%@ = %s\n"), name, group->gr_name);
			else
				wi_file_write_format(file, WI_STR("%@ = %d\n"), name, wi_number_int32(value));
			break;
			
		case WI_CONFIG_PORT:
			wi_file_write_format(file, WI_STR("%@ = %d\n"), name, wi_number_int32(value));
			break;
			
		case WI_CONFIG_REGEXP:
			wi_file_write_format(file, WI_STR("%@ = %@\n"), name, wi_regexp_string(value));
			break;
			
		case WI_CONFIG_TIME_INTERVAL:
			wi_file_write_format(file, WI_STR("%@ = %.2f\n"), name, wi_number_double(value));
			break;
	}
	
	return true;
}
Beispiel #18
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;
}
Beispiel #19
0
wi_integer_t wi_socket_write_buffer(wi_socket_t *socket, wi_time_interval_t timeout, const void *buffer, size_t length) {
	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);
	WI_ASSERT(socket->sd >= 0, "socket %@ should be valid", socket);
	
#ifdef HAVE_OPENSSL_SSL_H
	if(socket->ssl) {
		while(true) {
			if(timeout > 0.0) {
				state = wi_socket_wait_descriptor(socket->sd, timeout, false, true);

				if(state != WI_SOCKET_READY) {
					if(state == WI_SOCKET_TIMEOUT)
						wi_error_set_errno(ETIMEDOUT);
					
					return -1;
				}
			}

			ERR_clear_error();
			
			bytes = SSL_write(socket->ssl, buffer, length);

			if(bytes > 0) {
				break;
			} else {
				if(bytes < 0 && SSL_get_error(socket->ssl, bytes) == SSL_ERROR_WANT_WRITE)
					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) {
			if(timeout > 0.0) {
				state = wi_socket_wait_descriptor(socket->sd, timeout, false, true);

				if(state != WI_SOCKET_READY) {
					if(state == WI_SOCKET_TIMEOUT)
						wi_error_set_errno(ETIMEDOUT);
					
					return -1;
				}
			}

			bytes = write(socket->sd, buffer + offset, length - offset);
			
			if(bytes > 0) {
				offset += bytes;
			} else {
				if(bytes < 0)
					wi_error_set_errno(errno);
				else
					wi_error_set_libwired_error(WI_ERROR_SOCKET_EOF);
				
				return bytes;
			}
		}
		
		return offset;
#ifdef HAVE_OPENSSL_SSL_H
	}
#endif
	
	return 0;
}