Ejemplo n.º 1
0
static void wd_transfer_accept_thread(wi_runtime_instance_t *argument) {
	wi_pool_t			*pool;
	wi_socket_t			*socket = argument;
	wi_array_t			*arguments;
	wi_string_t			*ip, *string, *command;
	wd_transfer_t		*transfer;
	
	pool = wi_pool_init(wi_pool_alloc());
	
	ip = wi_address_string(wi_socket_address(socket));
	
	if(!wi_socket_accept_tls(socket, wd_transfer_socket_tls, 30.0)) {
		wi_log_err(WI_STR("Could not accept a connection for %@: %m"), ip);
		
		goto end;
	}
	
	if(!wi_socket_set_timeout(socket, 30.0))
		wi_log_warn(WI_STR("Could not set timeout for %@: %m"), ip);
	
	string = wi_socket_read_to_string(socket, 5.0, WI_STR(WD_MESSAGE_SEPARATOR_STR));
	
	if(!string || wi_string_length(string) == 0) {
		if(!string)
			wi_log_warn(WI_STR("Could not read from %@: %m"), ip);
		
		goto end;
	}
	
	wi_parse_wired_command(string, &command, &arguments);
	
	if(wi_is_equal(command, WI_STR("TRANSFER")) && wi_array_count(arguments) >= 1) {
		transfer = wd_transfers_transfer_with_hash(WI_ARRAY(arguments, 0));
		
		if(!transfer)
			goto end;
		
		if(!wi_is_equal(ip, wd_user_ip(transfer->user)))
			goto end;
		
		wi_lock_lock(transfer->socket_lock);
		
		if(!transfer->socket) {
			transfer->socket = wi_retain(socket);
			wi_lock_unlock(transfer->socket_lock);
		
			wd_transfer_loop(transfer);
		} else {
			wi_lock_unlock(transfer->socket_lock);
		}
	}

end:
	wi_socket_close(socket);

	wi_release(pool);
}
Ejemplo n.º 2
0
static void wd_control_accept_thread(wi_runtime_instance_t *argument) {
	wi_pool_t			*pool;
	wi_socket_t			*socket = argument;
	wi_string_t			*ip;
	wd_user_t			*user;
	
	pool = wi_pool_init(wi_pool_alloc());
	
	ip = wi_address_string(wi_socket_address(socket));
	
	if(!wi_socket_accept_tls(socket, wd_control_socket_tls, 30.0)) {
		wi_log_err(WI_STR("Could not accept a TLS connection for %@: %m"), ip);
		
		goto end;
	}
	
	if(!wi_socket_set_timeout(socket, 30.0))
		wi_log_warn(WI_STR("Could not set timeout for %@: %m"), ip);
	
	wi_socket_set_direction(socket, WI_SOCKET_READ);

	wi_log_info(WI_STR("Connect from %@"), ip);
	
	user = wd_user_with_socket(socket);

	wd_users_add_user(user);
	wd_users_set_user_for_thread(user);
	
	wd_command_loop_for_user(user);

end:
	wi_socket_close(socket);
	
	wi_release(pool);
}
Ejemplo n.º 3
0
void wt_write_servers(void) {
	static char				magic[] = WT_SERVER_MAGIC;
	static uint32_t			version = WT_SERVER_VERSION;
	FILE					*fp;
	wi_list_node_t			*node;
	wt_server_t				*server;
	wt_server_packed_t		server_packed;

	wi_lock_lock(wt_servers_lock);
	fp = fopen(wi_string_cstring(wt_settings.servers), "w");

	if(!fp) {
		wi_log_warn(WI_STR("Could not open %@: %s"),
			wt_settings.servers, strerror(errno));

		goto end;
	}

	fwrite(magic, 4, 1, fp);
	fwrite(&version, 4, 1, fp);

	wi_list_rdlock(wt_servers);
	WI_LIST_FOREACH(wt_servers, node, server) {
		server_packed = wt_server_packed(server);
		fwrite(&server_packed, sizeof(wt_server_packed_t), 1, fp);
	}
Ejemplo n.º 4
0
wi_runtime_instance_t * wi_autorelease(wi_runtime_instance_t *instance) {
	wi_pool_t			*pool;
	_wi_pool_array_t	*array, *new_array;
	
	if(!instance)
		return NULL;
	
	pool = _wi_pool_pool();

	if(!pool) {
		wi_log_warn(WI_STR("Instance %@ autoreleased with no pool in place - just leaking"), instance);

		return instance;
	}
	
	array = pool->array;
	
	if(array->length >= _WI_POOL_ARRAY_SIZE) {
		new_array = wi_malloc(sizeof(_wi_pool_array_t));
		new_array->next = array;
		
		array = new_array;
		pool->array = array;
	}
	
	array->instances[array->length] = instance;
	array->length++;
	
	return instance;
}
Ejemplo n.º 5
0
static void _wi_pool_remove_pool(wi_pool_t *pool) {
	_wi_pool_stack_t		*stack;
	wi_pool_t				*p;
	uint32_t				break_index, stack_index;
	int32_t					i;
	
	stack = _wi_pool_poolstack(&stack_index);
	
	if(!stack) {
		wi_log_warn(WI_STR("Orphaned pool in thread %@"), wi_thread_current_thread());
		
		return;
	}
	
	break_index = 0;
	
	for(i = stack->length - 1; i >= 0; --i) {
		p = stack->pools[i];
		
		if(p == pool) {
			stack->length	= i;
			break_index		= i;
		
			break;
		}
		
		wi_release(p);
	}
	
	if(break_index == 0)
		_wi_pool_remove_poolstack(stack, stack_index);
}
Ejemplo n.º 6
0
static void wi_test_fsevents_thread(wi_runtime_instance_t *instance) {
	wi_pool_t		*pool;
	
	pool = wi_pool_init(wi_pool_alloc());
	
	if(!wi_fsevents_run_with_timeout(wi_test_fsevents_fsevents, 1.0))
		wi_log_warn(WI_STR("wi_fsevents_run_with_timeout: %m"));
	
	wi_condition_lock_lock(wi_test_fsevents_lock);
	wi_condition_lock_unlock_with_condition(wi_test_fsevents_lock, 1);
	
	wi_release(pool);
}
Ejemplo n.º 7
0
static void wi_assert_default_handler(const char *file, unsigned int line, wi_string_t *fmt, ...) {
	wi_string_t		*string;
	va_list			ap;
	
	va_start(ap, fmt);
	string = wi_string_init_with_format_and_arguments(wi_string_alloc(), fmt, ap);
	va_end(ap);
	
	wi_log_warn(WI_STR("Assertion failed at %s:%u: %@"), file, line, string);
	
	wi_release(string);
	
	wi_crash();
}
Ejemplo n.º 8
0
static void _wi_tests_assert_handler(const char *file, unsigned int line, wi_string_t *fmt, ...) {
	wi_string_t		*string;
	va_list			ap;
	
	va_start(ap, fmt);
	string = wi_string_init_with_format_and_arguments(wi_string_alloc(), fmt, ap);
	va_end(ap);
	
	wi_log_warn(WI_STR("%@:%u: %@"), wi_string_last_path_component(wi_string_with_cstring(file)), line, string);
	
	wi_release(string);
	
	_wi_tests_current_test->passed = false;
	
	longjmp(_wi_tests_jmp_buf, 1);
}
Ejemplo n.º 9
0
static void wd_server_register_dnssd(void) {
	DNSServiceRef			service;
	DNSServiceErrorType		err;

	err = DNSServiceRegister(&service,
							 0,
							 kDNSServiceInterfaceIndexAny,
							 wi_string_cstring(wd_settings.name),
							 WD_DNSSD_NAME,
							 NULL,
							 NULL,
							 htons(wd_settings.port),
							 0,
							 NULL,
							 wd_server_register_dnssd_reply,
							 NULL);
	
	if(err != kDNSServiceErr_NoError)
		wi_log_warn(WI_STR("Could not register for DNS service discovery: %d"), err);
}
Ejemplo n.º 10
0
static void wt_update_servers(wi_timer_t *timer) {
	wi_enumerator_t		*enumerator;
	wt_server_t			*server;
	void				*key;
	wi_time_interval_t	interval, update;
	wi_boolean_t		changed = false;

	wi_dictionary_wrlock(wt_servers);
		
	if(wi_dictionary_count(wt_servers) > 0) {
		interval = wi_time_interval();

		enumerator = wi_array_data_enumerator(wi_dictionary_all_keys(wt_servers));
		
		while((key = wi_enumerator_next_data(enumerator))) {
			server = wi_dictionary_data_for_key(wt_servers, key);
			update = server->update_time > 0.0 ? server->update_time : server->register_time;
			
			if(interval - update > wt_settings.minupdatetime) {
				wi_log_warn(WI_STR("Deleting \"%@\" with URL %@: Last update %.0f seconds ago considered too slow"),
							server->name, server->url, interval - update);

				wt_servers_remove_stats_for_server(server);
				wi_dictionary_remove_data_for_key(wt_servers, key);
				
				changed = true;
			}
		}
	}

	wi_dictionary_unlock(wt_servers);

	if(changed) {
		wi_lock_lock(wt_status_lock);
		wt_write_status(true);
		wi_lock_unlock(wt_status_lock);

		wt_servers_write_file();
	}
}
Ejemplo n.º 11
0
void wt_servers_write_file(void) {
	static char				magic[] = WT_SERVER_MAGIC;
	static uint32_t			version = WT_SERVER_VERSION;
	FILE					*fp;
	wi_enumerator_t			*enumerator;
	wt_server_t				*server;
	wt_server_packed_t		server_packed;

	wi_lock_lock(wt_servers_lock);
	fp = fopen(wi_string_cstring(wt_settings.servers), "w");

	if(!fp) {
		wi_log_warn(WI_STR("Could not open %@: %s"),
			wt_settings.servers, strerror(errno));

		goto end;
	}

	fwrite(magic, 4, 1, fp);
	fwrite(&version, 4, 1, fp);

	wi_dictionary_rdlock(wt_servers);
	
	enumerator = wi_dictionary_data_enumerator(wt_servers);
	
	while((server = wi_enumerator_next_data(enumerator))) {
		server_packed = wt_server_packed(server);
		fwrite(&server_packed, sizeof(wt_server_packed_t), 1, fp);
	}

	wi_dictionary_unlock(wt_servers);

	fclose(fp);

end:
	wi_lock_unlock(wt_servers_lock);
}
Ejemplo n.º 12
0
static void wt_update_servers(wi_timer_t *timer) {
	wi_list_node_t		*node, *next_node;
	wt_server_t			*server;
	wi_time_interval_t	interval, update;
	unsigned int		count = 0;

	if(wi_list_count(wt_servers) > 0) {
		interval = wi_time_interval();

		wi_list_rdlock(wt_servers);
		for(node = wi_list_first_node(wt_servers); node; node = next_node) {
			next_node	= wi_list_node_next_node(node);
			server		= wi_list_node_data(node);
			update		= server->update_time > 0.0 ? server->update_time : server->register_time;

			if(interval - update > wt_settings.minupdatetime) {
				wi_log_warn(WI_STR("Deleting \"%@\" with URL %@: Last update %.0f seconds ago considered too slow"),
					server->name, server->url, interval - update);

				wt_server_stats_remove(server);
				wi_list_remove_node(wt_servers, node);

				count++;
			}
		}
		wi_list_unlock(wt_servers);

		if(count > 0) {
			wi_lock_lock(wt_status_lock);
			wt_write_status(true);
			wi_lock_unlock(wt_status_lock);

			wt_write_servers();
		}
	}
}
Ejemplo n.º 13
0
static void _wi_settings_log_error(wi_settings_t *settings, wi_string_t *name) {
	wi_log_warn(WI_STR("Could not interpret the setting \"%@\" at %@ line %d: %m"),
		name, settings->file, settings->line);
}
Ejemplo n.º 14
0
static void wd_transfer_upload(wd_transfer_t *transfer) {
	wi_pool_t				*pool;
	wi_string_t				*path;
	wd_account_t			*account;
	char					buffer[WD_TRANSFER_BUFFER_SIZE];
	wi_time_interval_t		timeout, interval, speedinterval, statusinterval, accountinterval;
	wi_socket_state_t		state;
	ssize_t					result, speedbytes, statsbytes;
	int						sd, bytes;

	pool = wi_pool_init(wi_pool_alloc());

	/* start upload */
	wi_log_info(WI_STR("Receiving \"%@\" from %@"),
		transfer->path,
		wd_user_identifier(transfer->user));
	
	wi_socket_set_direction(transfer->socket, WI_SOCKET_READ);

//	if(!wi_socket_set_blocking(transfer->socket, false))
//		wi_log_warn(WI_STR("Could not set non-blocking for %@: %m"), wd_user_ip(transfer->user));

	sd = wi_socket_descriptor(transfer->socket);
	speedinterval = statusinterval = accountinterval = wi_time_interval();
	speedbytes = statsbytes = 0;
	account = wd_user_account(transfer->user);

	/* update status */
	wi_lock_lock(wd_status_lock);
	wd_current_uploads++;
	wd_total_uploads++;
	wd_write_status(true);
	wi_lock_unlock(wd_status_lock);

	while(wd_transfer_state(transfer) == WD_TRANSFER_RUNNING && transfer->transferred < transfer->size) {
		/* wait to read */
		timeout = 0.0;
		
		do {
			state = wi_socket_wait_descriptor(sd, 0.1, true, false);
			
			if(state == WI_SOCKET_TIMEOUT) {
				timeout += 0.1;
				
				if(timeout >= 30.0)
					break;
			}
		} while(state == WI_SOCKET_TIMEOUT && wd_transfer_state(transfer) == WD_TRANSFER_RUNNING);
		
		if(state == WI_SOCKET_ERROR) {
			wi_log_err(WI_STR("Could not wait for upload from %@: %m"),
				wd_user_ip(transfer->user));

			break;
		}
		
		if(timeout >= 30.0) {
			wi_log_err(WI_STR("Timed out waiting to read upload from %@"),
				wd_user_ip(transfer->user));
			
			break;
		}

		/* read data */
		bytes = wi_socket_read_buffer(transfer->socket, 30.0, buffer, sizeof(buffer));
		
		if(bytes <= 0) {
			if(bytes < 0) {
				wi_log_err(WI_STR("Could not read upload from %@: %m"),
					wd_user_ip(transfer->user));
			}
			
			break;
		}
		
		if((wi_file_offset_t) bytes > transfer->size - transfer->transferred)
			bytes = transfer->size - transfer->transferred;

		/* write data */
		result = write(transfer->fd, buffer, bytes);
		
		if(result <= 0) {
			if(result < 0) {
				wi_log_err(WI_STR("Could not write upload to %@: %s"),
					transfer->realpath, strerror(errno));
			}
			
			break;
		}

		/* update counters */
		interval = wi_time_interval();
		transfer->transferred += bytes;
		speedbytes += bytes;
		statsbytes += bytes;

		/* update speed */
		transfer->speed = speedbytes / (interval - speedinterval);

		wd_transfer_limit_upload_speed(transfer, account, speedbytes, interval, speedinterval);
		
		if(interval - speedinterval > 30.0) {
			speedbytes = 0;
			speedinterval = interval;
		}

		/* update status */
		if(interval - statusinterval > wd_current_uploads) {
			wi_lock_lock(wd_status_lock);
			wd_uploads_traffic += statsbytes;
			wd_write_status(false);
			wi_lock_unlock(wd_status_lock);

			statsbytes = 0;
			statusinterval = interval;
		}
		
		/* update account */
		if(interval - accountinterval > 15.0) {
			account = wd_user_account(transfer->user);
			accountinterval = interval;
		}
		
		wi_pool_drain(pool);
	}

	wi_log_info(WI_STR("Received %@/%@ (%llu/%llu bytes) of \"%@\" from %@"),
		wd_files_string_for_bytes(transfer->transferred - transfer->offset),
		wd_files_string_for_bytes(transfer->size - transfer->offset),
		transfer->transferred - transfer->offset,
		transfer->size - transfer->offset,
		transfer->path,
		wd_user_identifier(transfer->user));

	/* update status */
	wd_transfer_set_state(transfer, WD_TRANSFER_STOPPED);
	
	wi_lock_lock(wd_status_lock);
	wd_current_uploads--;
	wd_uploads_traffic += statsbytes;
	wd_write_status(true);
	wi_lock_unlock(wd_status_lock);

	if(transfer->transferred == transfer->size) {
		path = wi_string_by_deleting_path_extension(transfer->realpath);

		if(wi_fs_rename_path(transfer->realpath, path)) {
			path = wi_string_by_appending_path_extension(transfer->path, WI_STR(WD_TRANSFERS_PARTIAL_EXTENSION));

			wd_files_move_comment(path, transfer->path);
		} else {
			wi_log_warn(WI_STR("Could not move %@ to %@: %m"),
				transfer->realpath, path);
		}
	}

	wi_release(pool);
}
Ejemplo n.º 15
0
static wi_boolean_t wd_transfers_run_upload(wd_transfer_t *transfer, wd_user_t *user, wi_p7_message_t *message) {
	wi_p7_message_t		*reply;
	wi_string_t			*path;
	wi_p7_uint32_t		transaction;
	wi_boolean_t		result;
	
	reply = wi_p7_message_with_name(WI_STR("wired.transfer.upload_ready"), wd_p7_spec);
	wi_p7_message_set_string_for_name(reply, transfer->path, WI_STR("wired.file.path"));
	wi_p7_message_set_oobdata_for_name(reply, transfer->dataoffset, WI_STR("wired.transfer.data_offset"));
	wi_p7_message_set_oobdata_for_name(reply, transfer->rsrcoffset, WI_STR("wired.transfer.rsrc_offset"));
	
	if(wi_p7_message_get_uint32_for_name(message, &transaction, WI_STR("wired.transaction")))
		wi_p7_message_set_uint32_for_name(reply, transaction, WI_STR("wired.transaction"));
	
	if(!wd_user_write_message(user, 30.0, reply)) {
		wi_log_error(WI_STR("Could not write message \"%@\" to %@: %m"),
			wi_p7_message_name(reply), wd_user_identifier(user));

		return false;
	}
	
	reply = wd_user_read_message(user, 30.0);
	
	if(!reply) {
		wi_log_warn(WI_STR("Could not read message from %@ while waiting for upload: %m"),
			wd_user_identifier(user));
		
		return false;
	}
	
	if(!wi_p7_spec_verify_message(wd_p7_spec, reply)) {
		wi_log_error(WI_STR("Could not verify message from %@ while waiting for upload: %m"),
			wd_user_identifier(user));
		wd_user_reply_error(user, WI_STR("wired.error.invalid_message"), reply);
		
		return false;
	}
	
	if(!wi_is_equal(wi_p7_message_name(reply), WI_STR("wired.transfer.upload"))) {
		wi_log_error(WI_STR("Could not accept message %@ from %@: Expected \"wired.transfer.upload\""),
			wi_p7_message_name(reply), wd_user_identifier(user));
		wd_user_reply_error(user, WI_STR("wired.error.invalid_message"), reply);
		
		return false;
	}
	
	wi_p7_message_get_uint64_for_name(reply, &transfer->remainingdatasize, WI_STR("wired.transfer.data"));
	wi_p7_message_get_uint64_for_name(reply, &transfer->remainingrsrcsize, WI_STR("wired.transfer.rsrc"));
	
	transfer->finderinfo = wi_retain(wi_p7_message_data_for_name(reply, WI_STR("wired.transfer.finderinfo")));
	
	wi_socket_set_interactive(wd_user_socket(user), false);
	
	result = wd_transfer_upload(transfer);

	wi_socket_set_interactive(wd_user_socket(user), true);

	if(transfer->transferred == transfer->datasize + transfer->rsrcsize) {
		path = wi_string_by_deleting_path_extension(transfer->realdatapath);
		
		if(wi_fs_rename_path(transfer->realdatapath, path)) {
			if(transfer->executable) {
				if(!wi_fs_set_mode_for_path(path, 0755))
					wi_log_error(WI_STR("Could not set mode for \"%@\": %m"), path);
			}
			
			wd_files_move_comment(transfer->realdatapath, path, NULL, NULL);
			wd_files_move_label(transfer->realdatapath, path, NULL, NULL);
			
			if(wi_data_length(transfer->finderinfo) > 0)
				wi_fs_set_finder_info_for_path(transfer->finderinfo, path);
			
			wd_index_add_file(path);
		} else {
			wi_log_error(WI_STR("Could not move \"%@\" to \"%@\": %m"),
				transfer->realdatapath, path);
		}
	
		wd_accounts_add_upload_statistics(wd_user_account(user), true, transfer->actualtransferred);
	} else {
		wd_accounts_add_upload_statistics(wd_user_account(user), false, transfer->actualtransferred);
	}
	
	return result;
}
Ejemplo n.º 16
0
void wd_server_init(void) {
	wi_enumerator_t			*enumerator;
	wi_array_t				*array, *addresses;
	wi_address_t			*address;
	wi_socket_t				*control_socket, *transfer_socket;
	wi_string_t				*ip, *string;
	wi_address_family_t		family;
	
	wd_control_sockets	= wi_array_init(wi_mutable_array_alloc());
	wd_transfer_sockets	= wi_array_init(wi_mutable_array_alloc());
	addresses			= wi_array_init(wi_mutable_array_alloc());

	if(wi_array_count(wd_settings.address) > 0) {
		/* listen on configured addresses */
		wi_array_rdlock(wd_settings.address);
		
		enumerator = wi_array_data_enumerator(wd_settings.address);
		
		while((string = wi_enumerator_next_data(enumerator))) {
			array = wi_host_addresses(wi_host_with_string(string));

			if(array)
				wi_mutable_array_add_data_from_array(addresses, array);
			else
				wi_log_err(WI_STR("Could not resolve \"%@\": %m"), string);
		}
		
		wi_array_unlock(wd_settings.address);
	} else {
		/* add wildcard addresses */
		wi_mutable_array_add_data(addresses, wi_address_wildcard_for_family(WI_ADDRESS_IPV6));
		wi_mutable_array_add_data(addresses, wi_address_wildcard_for_family(WI_ADDRESS_IPV4));
	}
	
	enumerator = wi_array_data_enumerator(addresses);
	
	while((address = wi_enumerator_next_data(enumerator))) {
		ip		= wi_address_string(address);
		family	= wi_address_family(address);

		/* force address family? */
		if(wd_address_family != WI_ADDRESS_NULL && family != wd_address_family)
			continue;
		
		/* create sockets */
		wi_address_set_port(address, wd_settings.port);
		control_socket = wi_autorelease(wi_socket_init_with_address(wi_socket_alloc(), address, WI_SOCKET_TCP));

		wi_address_set_port(address, wd_settings.port + 1);
		transfer_socket = wi_autorelease(wi_socket_init_with_address(wi_socket_alloc(), address, WI_SOCKET_TCP));
	
		if(!control_socket || !transfer_socket) {
			wi_log_warn(WI_STR("Could not create socket for %@: %m"), ip);
			
			continue;
		}

		/* listen on sockets */
		if(!wi_socket_listen(control_socket)) {
			wi_log_warn(WI_STR("Could not listen on %@ port %u: %m"),
				ip, wi_address_port(wi_socket_address(control_socket)));
			
			continue;
		}

		if(!wi_socket_listen(transfer_socket)) {
			wi_log_warn(WI_STR("Could not listen on %@ port %u: %m"),
				ip, wi_address_port(wi_socket_address(transfer_socket)));
			
			continue;
		}
		
		wi_socket_set_interactive(control_socket, true);
		wi_socket_set_interactive(transfer_socket, false);

		/* add to list of sockets */
		wi_mutable_array_add_data(wd_control_sockets, control_socket);
		wi_mutable_array_add_data(wd_transfer_sockets, transfer_socket);

		wi_log_info(WI_STR("Listening on %@ ports %d-%d"),
			ip, wd_settings.port, wd_settings.port + 1);
	}

	if(wi_array_count(wd_control_sockets) == 0 || wi_array_count(wd_transfer_sockets) == 0)
		wi_log_fatal(WI_STR("No addresses available for listening"));
	
	wi_release(addresses);
	
#ifdef HAVE_DNS_SD_H
	if(wd_settings.zeroconf)
		wd_server_register_dnssd();
#endif
}
Ejemplo n.º 17
0
void wt_read_servers(void) {
	FILE				*fp;
	wt_server_packed_t	server_packed;
	wt_server_t			*server;
	char				magic[5];
	wi_time_interval_t	interval, update;
	unsigned int		version, count = 0;

	wi_lock_lock(wt_servers_lock);
	fp = fopen(wi_string_cstring(wt_settings.servers), "r");

	if(!fp) {
		if(errno != ENOENT) {
			wi_log_err(WI_STR("Could not open %@: %s"),
				wt_settings.servers, strerror(errno));
		}

		goto end;
	}

	if(fread(&magic, 4, 1, fp) != 1 || strncmp(magic, WT_SERVER_MAGIC, 4) != 0) {
		wi_log_warn(WI_STR("Could not read %@: %s"), wt_settings.servers, "Not a server file");

		goto end;
	}

	if(fread(&version, 4, 1, fp) != 1 || version != WT_SERVER_VERSION) {
		wi_log_warn(WI_STR("Could not read %@: %s"), wt_settings.servers, "Wrong version");

		goto end;
	}

	wi_log_info(WI_STR("Reading %@"), wt_settings.servers);

	interval = wi_time_interval();

	wi_list_wrlock(wt_servers);
	while((fread(&server_packed, sizeof(wt_server_packed_t), 1, fp)) > 0) {
		update = server_packed.update_time > 0 ? server_packed.update_time : server_packed.register_time;

		if(interval - update < wt_settings.minupdatetime) {
			server = wt_server_init_with_packed(wt_server_alloc(), server_packed);

			wi_lock_lock(wt_status_lock);
			wt_current_servers++;
			wt_current_users += server->users;
			wt_current_files += server->files;
			wt_current_size += server->size;
			wi_lock_unlock(wt_status_lock);

			wi_list_append_data(wt_servers, server);
			wi_release(server);

			count++;
		}
	}
	wi_list_unlock(wt_servers);

	if(count > 0) {
		wi_lock_lock(wt_status_lock);
		wt_write_status(true);
		wi_lock_unlock(wt_status_lock);

		wi_log_info(WI_STR("Loaded %u %s from %@"),
			count,
			count == 1
				? "server"
				: "servers",
			wt_settings.servers);
	}

end:
	wi_lock_unlock(wt_servers_lock);
}
Ejemplo n.º 18
0
void wd_server_apply_settings(void) {
	wi_data_t		*data;
	wi_string_t		*hostname;

	/* reload banner */
	if(wd_settings.banner) {
		if(wd_settings.banner_changed) {
			data = wi_data_init_with_contents_of_file(wi_data_alloc(), wd_settings.banner);
			
			if(data) {
				wi_release(wd_banner);
				wd_banner = wi_retain(wi_data_base64(data));
			} else {
				wi_log_err(WI_STR("Could not open %@: %m"), wd_settings.banner);
			}

			wi_release(data);
		}
	} else {
		wi_release(wd_banner);
		wd_banner = NULL;
	}

	/* reload server name/description */
	if(wd_settings.name_changed || wd_settings.description_changed)
		wd_server_send_server_info(true);

	/* set SSL cipher list */
	if(wd_settings.controlcipher) {
		if(!wi_socket_tls_set_ciphers(wd_control_socket_tls, wd_settings.controlcipher)) {
			wi_log_err(WI_STR("Could not set TLS cipher list \"%@\": %m"),
				wd_settings.controlcipher);
		}
	}

	if(wd_settings.transfercipher) {
		if(!wi_socket_tls_set_ciphers(wd_transfer_socket_tls, wd_settings.transfercipher)) {
			wi_log_err(WI_STR("Could not set TLS cipher list \"%@\": %m"),
				wd_settings.transfercipher);
	   }
	}

	/* load SSL certificate */
	if(!wd_certificate && !wd_private_key) {
		if(wd_settings.certificate) {
			wd_private_key = wi_rsa_init_with_pem_file(wi_rsa_alloc(), wd_settings.certificate);
			
			if(!wd_private_key)
				wi_log_warn(WI_STR("Could not find RSA key in %@, creating one..."), wd_settings.certificate);
			
			wd_certificate = wi_x509_init_with_pem_file(wi_x509_alloc(), wd_settings.certificate);
			
			if(!wd_certificate)
				wi_log_warn(WI_STR("Could not find certificate in %@, creating one..."), wd_settings.certificate);
		}
		
		if(!wd_private_key) {
			wd_private_key = wi_rsa_init_with_bits(wi_rsa_alloc(), 1024);
			
			if(wd_private_key)
				wi_log_info(WI_STR("Created 1024-bit RSA key"));
			else
				wi_log_err(WI_STR("Could not create RSA key: %m"));
		}
		
		if(!wd_certificate) {
			hostname = wi_process_hostname(wi_process());
			wd_certificate = wi_x509_init_with_common_name(wi_x509_alloc(), wd_private_key, hostname);
			
			if(wd_certificate)
				wi_log_info(WI_STR("Created self-signed certificate for %@"), hostname);
			else
				wi_log_err(WI_STR("Could not create self-signed certificate: %m"));
		}
		
		if(!wi_socket_tls_set_private_key(wd_control_socket_tls, wd_private_key) ||
		   !wi_socket_tls_set_private_key(wd_transfer_socket_tls, wd_private_key)) {
			wi_log_err(WI_STR("Could not set TLS private key: %m"));
		}
		
		if(!wi_socket_tls_set_certificate(wd_control_socket_tls, wd_certificate) ||
		   !wi_socket_tls_set_certificate(wd_transfer_socket_tls, wd_certificate)) {
			wi_log_err(WI_STR("Could not set TLS certificate: %m"));
		}
	}
}
Ejemplo n.º 19
0
static void wt_cmd_register(wi_array_t *arguments) {
	wt_client_t					*client = wt_client();
	wi_enumerator_t				*enumerator;
	wi_array_t					*array;
	wi_address_t				*address, *hostaddress;
	wi_url_t					*url;
	wi_string_t					*hostname;
	wt_server_t					*server;
	wi_boolean_t				failed = false, passed;
	uint32_t					bandwidth;

	url			= wi_autorelease(wi_url_init_with_string(wi_url_alloc(), WI_ARRAY(arguments, 1)));
	hostname	= wi_url_host(url);
	address		= wi_socket_address(client->socket);
	
	if(!wi_url_is_valid(url)) {
		/* invalid URL */
		if(wt_settings.strictlookup) {
			wt_reply(503, WI_STR("Syntax Error"));
			wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ aborted: %s"),
				client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1),
				"Invalid URL");
			
			return;
		}
		
		failed = true;
		goto failed;
	}

	if(wi_ip_version(hostname) > 0) {
		/* hostname is numeric, compare with source address */
		if(!wi_is_equal(hostname, client->ip)) {
			/* IP mismatch */
			if(wt_settings.strictlookup) {
				wt_reply(530, WI_STR("Address Mismatch"));
				wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ denied: %s"),
					client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1),
					"IP mismatch");

				return;
			}

			failed = true;
			goto failed;
		}
	} else {
		/* hostname is symbolic */
		if(wt_settings.lookup) {
			/* look up and compare with source address */
			passed = false;
			array = wi_host_addresses(wi_host_with_string(hostname));
			
			if(array) {
				enumerator = wi_array_data_enumerator(array);
				
				while((hostaddress = wi_enumerator_next_data(enumerator))) {
					if(wi_is_equal(hostaddress, address)) {
						passed = true;
						
						break;
					}
				}
			}
			
			if(!passed) {
				/* lookup failed */
				if(wt_settings.strictlookup) {
					wt_reply(531, WI_STR("Address Mismatch"));
					wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ denied: %s"),
						client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1),
						"Lookup failed");
					
					return;
				}
				
				failed = true;
				goto failed;
			}
		}

		if(wt_settings.reverselookup) {
			/* reverse look up and compare to hostname */
			if(!wi_is_equal(wi_address_hostname(address), hostname)) {
				/* reverse lookup failed */
				if(wt_settings.strictlookup) {
					wt_reply(531, WI_STR("Address Mismatch"));
					wi_log_warn(WI_STR("Register from %@ as \"%@\" URL % denied: %@"),
						client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1),
						"Reverse lookup failed");

					return;
				}

				failed = true;
				goto failed;
			}
		}
	}

failed:
	/* get bandwidth */
	bandwidth = wi_string_uint32(WI_ARRAY(arguments, 3));

	/* bandwidth too low? */
	if(wt_settings.minbandwidth > 0 && bandwidth < wt_settings.minbandwidth) {
		wt_reply(516, WI_STR("Permission Denied"));
		wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ denied: Bandwidth %.0f Kbps considered too low"),
			client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1), bandwidth / 128.0);

		return;
	}

	/* bandwidth too high? */
	if(wt_settings.maxbandwidth > 0 && bandwidth > wt_settings.maxbandwidth) {
		wt_reply(516, WI_STR("Permission Denied"));
		wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ denied: Bandwidth %.0f Kbps considered too high"),
			client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1), bandwidth / 128.0);

		return;
	}

	/* is there an existing server from this host? */
	server = wt_servers_server_with_ip(client->ip);

	if(server) {
		if(server->port == wi_url_port(url)) {
			/* remove existing server in preparation for re-registration */
			wt_servers_remove_stats_for_server(server);
			wt_servers_remove_server(server);
		} else {
			/* multiple servers from the same IP allowed? */
			if(!wt_settings.allowmultiple) {
				wt_reply(530, WI_STR("Address Registered"));
				wi_log_warn(WI_STR("Register from %@ as \"%@\" URL %@ denied: %s"),
					client->ip, WI_ARRAY(arguments, 2), WI_ARRAY(arguments, 1),
					"A server from the same address is already registered");
				
				return;
			}
		}
	}
	
	/* rewrite URL if host verification failed */
	if(failed) {
		wi_url_set_scheme(url, WI_STR("wired"));
		wi_url_set_host(url, client->ip);

		if(wi_string_length(WI_ARRAY(arguments, 1)) == 0)
			wi_log_info(WI_STR("Rewriting URL to %@"), wi_url_string(url));
		else
			wi_log_info(WI_STR("Rewriting URL from %@ to %@"), WI_ARRAY(arguments, 1), wi_url_string(url));
	}

	/* create new server */
	server					= wt_server_init(wt_server_alloc());
	server->key				= wi_retain(wi_string_sha1(wi_autorelease(wi_string_init_random_string_with_length(wi_string_alloc(), 1024))));
	server->port			= wi_url_port(url);
	server->bandwidth		= bandwidth;
	server->register_time	= wi_time_interval();
	server->update_time		= 0.0;
	server->ip				= wi_retain(client->ip);
	server->category		= wt_servers_category_is_valid(WI_ARRAY(arguments, 0))
		? wi_retain(WI_ARRAY(arguments, 0))
		: wi_string_init(wi_string_alloc());
	server->name			= wi_retain(WI_ARRAY(arguments, 2));
	server->description		= wi_retain(WI_ARRAY(arguments, 4));
	server->url				= wi_copy(wi_url_string(url));

	wt_servers_add_server(server);
	wt_servers_add_stats_for_server(server);
	
	/* reply 700 */
	wt_reply(700, WI_STR("%@"), server->key);
	wi_log_info(WI_STR("Registered \"%@\" with URL %@"), server->name, server->url);
	wt_servers_write_file();
	wi_release(server);
}
Ejemplo n.º 20
0
static void wd_transfer_listen_thread(wi_runtime_instance_t *argument) {
	wi_pool_t			*pool;
	wi_socket_t			*socket;
	wi_address_t		*address;
	wi_array_t			*arguments;
	wi_string_t			*ip, *string, *command;
	wd_transfer_t		*transfer;
	
	pool = wi_pool_init(wi_pool_alloc());

	while(wd_running) {
		wi_pool_drain(pool);

		/* accept new connection */
		socket = wi_socket_accept_multiple(wd_transfer_sockets, wd_transfer_socket_context, 30.0, &address);
		
		if(!address) {
			wi_log_err(WI_STR("Could not accept a connection: %m"));
			
			continue;
		}
		
		ip = wi_address_string(address);
		
		if(!socket) {
			wi_log_err(WI_STR("Could not accept a connection for %@: %m"), ip);
			
			continue;
		}

		string = wi_socket_read_to_string(socket, 5.0, WI_STR(WD_MESSAGE_SEPARATOR_STR));
		
		if(!string || wi_string_length(string) == 0) {
			if(!string)
				wi_log_warn(WI_STR("Could not read from %@: %m"), ip);

			continue;
		}
		
		/* parse command */
		wi_parse_wired_command(string, &command, &arguments);
		
		if(wi_is_equal(command, WI_STR("TRANSFER")) && wi_array_count(arguments) >= 1) {
			/* get transfer by identifier */
			transfer = wd_transfers_transfer_with_hash(WI_ARRAY(arguments, 0));
			
			if(!transfer)
				continue;
			
			if(!wi_is_equal(ip, wd_user_ip(transfer->user)))
				continue;
			
			transfer->socket = wi_retain(socket);
			
			/* spawn a transfer thread */
			if(!wi_thread_create_thread(wd_transfer_thread, transfer))
				wi_log_err(WI_STR("Could not create a thread for %@: %m"), ip);
		}
	}
	
	wi_release(pool);
}
Ejemplo n.º 21
0
static void _wi_config_log_error(wi_config_t *config, wi_string_t *name) {
	wi_log_warn(WI_STR("Could not interpret the setting \"%@\" at %@ line %lu: %m"),
		name, config->path, config->line);
}
Ejemplo n.º 22
0
void wd_trackers_apply_settings(void) {
	wi_enumerator_t		*enumerator, *address_enumerator;
	wi_string_t			*string, *path;
	wi_url_t			*url;
	wi_address_t		*address;
	wd_tracker_t		*tracker;
	wi_uinteger_t		port;
	
	wi_array_wrlock(wd_trackers);
	wi_mutable_array_remove_all_data(wd_trackers);
	
	enumerator = wi_array_data_enumerator(wd_settings.tracker);
	
	while((string = wi_enumerator_next_data(enumerator))) {
		tracker	= wi_autorelease(wd_tracker_init(wd_tracker_alloc()));
		url		= wi_autorelease(wi_url_init_with_string(wi_url_alloc(), string));
		
		if(!wi_url_is_valid(url)) {
			wi_log_warn(WI_STR("Could not parse tracker URL \"%@\""),
				string);
			
			continue;
		}

		tracker->tls = wi_socket_tls_init_with_type(wi_socket_tls_alloc(), WI_SOCKET_TLS_CLIENT);
		
		if(!tracker->tls) {
			wi_log_warn(WI_STR("Could not create TLS context: %m"));
			
			continue;
		}

		if(wd_settings.controlcipher) {
			if(!wi_socket_tls_set_ciphers(tracker->tls, wd_settings.controlcipher)) {
				wi_log_err(WI_STR("Could not set TLS cipher list \"%@\": %m"),
					wd_settings.controlcipher);
				
				continue;
			}
		}

		path = wi_url_path(url);

		if(!path || wi_string_length(path) == 0)
			path = WI_STR("/");

		tracker->host		= wi_retain(wi_url_host(url));
		tracker->category	= wi_retain(wi_string_substring_from_index(path, 1));
		tracker->addresses	= wi_retain(wi_host_addresses(wi_host_with_string(tracker->host)));

		if(!tracker->addresses) {
			wi_log_warn(WI_STR("Could not resolve \"%@\": %m"), tracker->host);
			
			continue;
		}
		
		port = wi_url_port(url);

		if(port == 0)
			port = WD_TRACKER_PORT;

		address_enumerator = wi_array_data_enumerator(tracker->addresses);
		
		while((address = wi_enumerator_next_data(address_enumerator)))
			wi_address_set_port(address, port);
		
		wi_mutable_array_add_data(wd_trackers, tracker);
	}
	
	wi_array_unlock(wd_trackers);
}