Пример #1
0
void wi_test_runtime_pool(void) {
	wi_pool_t			*pool, *pool2;
	_wi_runtimetest_t	*runtimetest, *runtimetest2;
	
	_wi_runtimetest_deallocs = 0;
	
	pool = wi_pool_init(wi_pool_alloc());
	runtimetest = wi_retain(wi_autorelease(_wi_runtimetest_init_with_value(_wi_runtimetest_alloc(), 42)));
	wi_release(pool);
	WI_TEST_ASSERT_EQUALS(wi_retain_count(runtimetest), 1U, "");
	wi_release(runtimetest);

	pool = wi_pool_init(wi_pool_alloc());
	runtimetest = wi_retain(wi_autorelease(_wi_runtimetest_init_with_value(_wi_runtimetest_alloc(), 42)));
	wi_pool_drain(pool);
	WI_TEST_ASSERT_EQUALS(wi_retain_count(runtimetest), 1U, "");
	wi_release(pool);
	wi_release(runtimetest);
	
	pool = wi_pool_init(wi_pool_alloc());
	runtimetest = wi_retain(wi_autorelease(_wi_runtimetest_init_with_value(_wi_runtimetest_alloc(), 42)));
	pool2 = wi_pool_init(wi_pool_alloc());
	runtimetest2 = wi_retain(wi_autorelease(_wi_runtimetest_init_with_value(_wi_runtimetest_alloc(), 42)));
	wi_release(pool2);
	WI_TEST_ASSERT_EQUALS(wi_retain_count(runtimetest2), 1U, "");
	wi_release(pool);
	WI_TEST_ASSERT_EQUALS(wi_retain_count(runtimetest), 1U, "");
	wi_release(runtimetest);
	wi_release(runtimetest2);
}
Пример #2
0
static void wd_transfer_listen_thread(wi_runtime_instance_t *argument) {
	wi_pool_t			*pool;
	wi_socket_t			*socket;
	wi_address_t		*address;
	
	pool = wi_pool_init(wi_pool_alloc());

	while(wd_running) {
		wi_pool_drain(pool);

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

		if(!wi_thread_create_thread(wd_transfer_accept_thread, socket)) {
			wi_log_err(WI_STR("Could not create a transfer thread for %@: %m"),
				wi_address_string(address));
			
			continue;
		}
	}
	
	wi_release(pool);
}
Пример #3
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);
}
Пример #4
0
static void wd_trackers_register_thread(wi_runtime_instance_t *argument) {
	wi_pool_t			*pool;
	wi_enumerator_t		*enumerator;
	wi_number_t			*number = argument;
	wd_tracker_t		*tracker;
	wi_boolean_t		update;
	
	pool = wi_pool_init(wi_pool_alloc());
	update = wi_number_bool(number);
	
	wi_array_rdlock(wd_trackers);
	
	enumerator = wi_array_data_enumerator(wd_trackers);
	
	while((tracker = wi_enumerator_next_data(enumerator))) {
		wd_tracker_register(tracker);
		
		if(update && tracker->active)
			wd_tracker_update(tracker);
	}
	
	wi_array_unlock(wd_trackers);
	
	if(update)
		wi_timer_reschedule(wd_trackers_update_timer, WD_TRACKERS_UPDATE_INTERVAL);
	
	wi_release(pool);
}
Пример #5
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);
}
Пример #6
0
void wt_control_thread(wi_runtime_instance_t *argument) {
	wi_pool_t			*pool;
	wt_client_t			*client = argument;
	wi_string_t			*string;
	wi_socket_state_t	state;
	wi_uinteger_t		i = 0;
	
	pool = wi_pool_init(wi_pool_alloc());

	wt_client_set(client);

	while(client->state <= WT_CLIENT_STATE_SAID_HELLO) {
		do {
			state = wi_socket_wait(client->socket, 0.1);
		} while(state == WI_SOCKET_TIMEOUT && client->state <= WT_CLIENT_STATE_SAID_HELLO);

		if(client->state > WT_CLIENT_STATE_SAID_HELLO) {
			/* invalid state */
			break;
		}

		if(state == WI_SOCKET_ERROR) {
			if(wi_error_code() == EINTR) {
				/* got a signal */
				continue;
			} else {
				/* error in TCP communication */
				wi_log_err(WI_STR("Could not read from %@: %m"), client->ip);

				break;
			}
		}

		string = wi_socket_read_to_string(client->socket, 0.0, WI_STR(WT_MESSAGE_SEPARATOR_STR));

		if(!string || wi_string_length(string) == 0) {
			if(!string)
				wi_log_info(WI_STR("Could not read from %@: %m"), client->ip);
			
			break;
		}

		wt_parse_command(string);
		
		if(++i % 10 == 0)
			wi_pool_drain(pool);
	}

	wi_log_info(WI_STR("Disconnect from %@ after %.2fs"),
		client->ip,
		wi_time_interval() - client->connect_time);
	
	wi_release(pool);
}
Пример #7
0
static void _wi_timer_thread(wi_runtime_instance_t *argument) {
	wi_pool_t			*pool;
	wi_timer_t			*timer, *fire_timer;
	wi_time_interval_t	interval, diff;
	wi_boolean_t		locked;
	
	pool = wi_pool_init(wi_pool_alloc());
	
	while(true) {
		fire_timer	= NULL;
		locked		= true;
		interval	= wi_time_interval();
		timer		= _wi_timer_first_timer();

		if(!timer) {
			locked = wi_condition_lock_lock_when_condition(_wi_timer_lock, 1, 0.0);

			timer = _wi_timer_first_timer();
			interval = wi_time_interval();

			if(timer && timer->fire - interval <= _WI_TIMER_MINIMUM_INTERVAL)
				fire_timer = timer;
		} else {
			diff = timer->fire - interval;

			if(diff <= _WI_TIMER_MINIMUM_INTERVAL) {
				fire_timer = timer;

				locked = false;
			} else {
				locked = wi_condition_lock_lock_when_condition(_wi_timer_lock, 1, diff);
				
				if(!locked)
					fire_timer = _wi_timer_first_timer();
			} 
		}

		if(locked)
			wi_condition_lock_unlock_with_condition(_wi_timer_lock, 0);
		
		if(fire_timer) {
			_wi_timer_invalidate(fire_timer);
				
			wi_timer_fire(fire_timer);

			if(timer->repeats)
				_wi_timer_schedule(fire_timer);
		}
		
		wi_pool_drain(pool);
	}

	wi_release(pool);
}
Пример #8
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);
}
Пример #9
0
void wi_tests_run_test(const char *name, wi_run_test_func_t *function) {
    wi_pool_t                   *pool;
    wi_assert_handler_func_t    *handler;
    wi_time_interval_t          interval;
    
    if(_wi_tests_name) {
        if(wi_string_index_of_string(wi_string_with_utf8_string(name), _wi_tests_name, 0) == WI_NOT_FOUND)
            return;
    }
    
    if(wi_string_has_suffix(wi_string_with_utf8_string(name), WI_STR("initialize"))) {
        (*function)();
    } else {
        _wi_tests_current_test = _wi_test_init_with_function(_wi_test_alloc(), wi_string_with_utf8_string(name), function);
        
        handler = wi_assert_handler;
        wi_assert_handler = _wi_tests_assert_handler;
        
        interval = wi_time_interval();
        
        pool = wi_pool_init(wi_pool_alloc());

        if(setjmp(_wi_tests_jmp_buf) == 0)
            (*_wi_tests_current_test->function)();

        wi_release(pool);
        
        _wi_tests_current_test->interval = wi_time_interval() - interval;
        
        wi_assert_handler = handler;

        if(_wi_tests_current_test->passed) {
            wi_log_info(WI_STR("Test \"%@\" passed (%.3f seconds)"),
                _wi_tests_current_test->name, _wi_tests_current_test->interval);
            
            wi_tests_passed++;
        } else {
            wi_log_info(WI_STR("Test \"%@\" failed (%.3f seconds)"),
                _wi_tests_current_test->name, _wi_tests_current_test->interval);
            
            wi_tests_failed++;
        }
        
        wi_release(_wi_tests_current_test);
    }
}
Пример #10
0
static void wd_control_listen_thread(wi_runtime_instance_t *argument) {
	wi_pool_t			*pool;
	wi_socket_t			*socket;
	wi_address_t		*address;
	wi_string_t			*ip;
	wd_user_t			*user;
	
	pool = wi_pool_init(wi_pool_alloc());

	while(wd_running) {
		wi_pool_drain(pool);

		/* accept new user */
		socket = wi_socket_accept_multiple(wd_control_sockets, wd_control_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;
		}
		
		wi_socket_set_direction(socket, WI_SOCKET_READ);
		
		wi_log_info(WI_STR("Connect from %@"), ip);
		
		/* spawn a user thread */
		user = wd_user_with_socket(socket);

		if(!wi_thread_create_thread(wd_control_thread, user))
			wi_log_err(WI_STR("Could not create a thread for %@: %m"), ip);
	}
	
	wi_release(pool);
}
Пример #11
0
int main(int argc, const char **argv) {
	wi_pool_t		*pool;
	
	wi_initialize();
	wi_load(argc, argv);
	
	wi_log_plain = true;
	wi_log_level = WI_LOG_DEBUG;
	
	pool = wi_pool_init(wi_pool_alloc());

	wi_tests_start();
	
	wi_test_fixture_path = wi_string_by_appending_path_component(WI_STR(WI_TEST_ROOT), WI_STR("fixture"));
	
#include "test/testlist.inc"

	wi_tests_stop_and_report();
	
	wi_release(pool);
	
	return wi_tests_failed;
}
Пример #12
0
int main(int argc, const char **argv) {
	wi_pool_t			*pool;
	wi_string_t			*string;
	int					ch, facility;
	wi_boolean_t		no_chroot, test_config;

	/* init libwired */
	wi_initialize();
	wi_load(argc, argv);
	
	pool					= wi_pool_init(wi_pool_alloc());
	wi_log_startup			= true;
	wi_log_syslog			= true;
	wi_log_syslog_facility	= LOG_DAEMON;

	/* init core systems */
	wt_init_version();
	wt_status_lock			= wi_lock_init(wi_lock_alloc());
	wt_start_date			= wi_date_init(wi_date_alloc());
	
	/* set defaults */
	wi_root_path			= wi_string_init_with_cstring(wi_string_alloc(), WT_ROOT);
	wi_settings_config_path	= wi_string_init_with_cstring(wi_string_alloc(), WT_CONFIG_PATH);
	no_chroot				= false;
	test_config				= false;

	/* parse command line switches */
	while((ch = getopt(argc, (char * const *) argv, "46Dd:f:hi:L:ls:tuVv")) != -1) {
		switch(ch) {
			case '4':
				wt_address_family = WI_ADDRESS_IPV4;
				break;

			case '6':
				wt_address_family = WI_ADDRESS_IPV6;
				break;

			case 'D':
				wt_daemonize = false;
				wi_log_stderr = true;
				break;

			case 'd':
				wi_release(wi_root_path);
				wi_root_path = wi_string_init_with_cstring(wi_string_alloc(), optarg);
				break;

			case 'f':
				wi_release(wi_settings_config_path);
				wi_settings_config_path = wi_string_init_with_cstring(wi_string_alloc(), optarg);
				break;

			case 'i':
				wi_log_limit = wi_string_uint32(wi_string_with_cstring(optarg));
				break;

			case 'L':
				wi_log_syslog = false;
				wi_log_file = true;

				wi_release(wi_log_path);
				wi_log_path = wi_string_init_with_cstring(wi_string_alloc(), optarg);
				break;

			case 'l':
				wi_log_level++;
				break;

			case 's':
				string = wi_string_with_cstring(optarg);
				facility = wi_log_syslog_facility_with_name(string);
				
				if(facility < 0) {
					wi_log_err(WI_STR("Could not find syslog facility \"%@\": %m"),
						string);
				}
				
				wi_log_syslog_facility = facility;
				break;

			case 't':
				test_config = true;
				break;

			case 'u':
				no_chroot = true;
				break;

			case 'V':
			case 'v':
				wt_version();
				break;

			case '?':
			case 'h':
			default:
				wt_usage();
				break;
		}
	}
	
	/* open log */
	wi_log_open();

	/* init subsystems */
	wt_init_ssl();
	wt_init_clients();
	wt_init_servers();

	/* read the config file */
	wt_settings_chroot = !no_chroot;
	wt_init_settings();

	if(!wt_read_config())
		exit(1);

	/* change root directory */
	if(!no_chroot) {
		if(!wi_change_root())
			wi_log_err(WI_STR("Could not change root to %@: %m"), wi_root_path);
	}

	/* apply config */
	wt_apply_config();

	if(test_config) {
		printf("Config OK\n");

		exit(0);
	}

	/* dump command line */
	if(wi_log_level >= WI_LOG_DEBUG) {
		wi_log_debug(WI_STR("Started as %@ %@"),
			wi_process_path(wi_process()),
			wi_array_components_joined_by_string(wi_process_arguments(wi_process()), WI_STR(" ")));
	}

	/* init tracker */
	wi_log_info(WI_STR("Starting Wired Tracker version %@"), wt_version_string);
	wt_init_tracker();

	/* detach (don't chdir, don't close i/o channels) */
	if(wt_daemonize) {
		if(!wi_daemon())
			wi_log_err(WI_STR("Could not become a daemon: %m"));
	}

	/* switch user/group */
	wi_switch_user(wt_settings.user, wt_settings.group);
		
	/* create tracker threads after privilege drop */
	wt_init_signals();
	wt_block_signals();
	wt_schedule_servers();
	wt_fork_tracker();
	wt_write_pid();
	wt_write_status(true);
	wi_log_startup = false;
	
	wi_release(pool);
	pool = wi_pool_init(wi_pool_alloc());
	
	/* enter the signal handling thread in the main thread */
	wt_signal_thread(NULL);

	/* dropped out */
	wt_cleanup();
	wi_log_close();
	wi_release(pool);

	return 0;
}
Пример #13
0
int main(int argc, const char **argv) {
	wi_pool_t			*pool;
	wi_string_t			*homepath, *wirepath, *path, *component;
	wi_file_t			*file;	
	int					ch;

	/* init libwired */
	wi_initialize();
	wi_load(argc, argv);
	
	pool				= wi_pool_init(wi_pool_alloc());
	wi_log_callback		= wr_wi_log_callback;
	
	/* init core systems */
	wr_version_init();
	wr_start_date		= wi_date_init(wi_date_alloc());
	
	/* set defaults */
	wr_nick				= wi_retain(wi_user_name());
	homepath			= wi_user_home();
	wr_timestamp_format	= wi_retain(WI_STR("%H:%M"));

	/* parse command line switches */
	while((ch = getopt(argc, (char * const *) argv, "DhVv")) != -1) {
		switch(ch) {
			case 'D':
				wr_debug = true;

				wi_log_level = WI_LOG_DEBUG;
				wi_log_file = true;
				wi_log_path = WI_STR("wire.out");
				wi_log_callback = NULL;
				break;

			case 'V':
			case 'v':
				wr_version();
				break;

			case '?':
			case 'h':
			default:
				wr_usage();
				break;
		}
	}

	argc -= optind;
	argv += optind;

	/* open log */
	wi_log_open();
	
	/* create ~/.wire */
	wirepath = wi_string_by_appending_path_component(homepath, WI_STR(WR_WIRE_PATH));
	wi_file_create_directory(wirepath, 0700);
	
	/* init subsystems */
	wr_signals_init();
	wr_terminal_init();
	wr_readline_init();
	wr_chats_init();
	wr_windows_init();
	wr_client_init();
	wr_runloop_init();
	wr_users_init();
	wr_ignores_init();
	wr_files_init();
	wr_transfers_init();
	wr_servers_init();
	
	/* open default settings */
	path = wi_string_by_appending_path_component(homepath, WI_STR(WR_WIRE_CONFIG_PATH));
	file = wi_file_for_reading(path);

	if(file)
		wr_parse_file(file);
	else
		wr_printf_prefix(WI_STR("%@: %m"), path);

	/* read specified bookmark */
	if(*argv) {
		component	= wi_string_with_cstring(*argv);
		path		= wi_string_by_appending_path_component(wirepath, component);
		file		= wi_file_for_reading(path);

		if(file)
			wr_parse_file(file);
		else
			wr_printf_prefix(WI_STR("%@: %m"), path);
	}
	
	/* clean up pool after startup */
	wi_pool_drain(pool);
	
	/* enter event loop */
	wr_runloop_run();

	/* clean up */
	wr_cleanup();
	wi_release(pool);
	
	return 0;
}
Пример #14
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);
}
Пример #15
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);
}
Пример #16
0
void wd_control_thread(wi_runtime_instance_t *argument) {
	wi_pool_t		*pool;
	wd_client_t		*client = argument;
	wi_string_t		*string;
	unsigned int	i = 0;
	int				state;
	
	pool = wi_pool_init(wi_pool_alloc());

	wd_clients_add_client(client);
	wd_client_set(client);

	while(client->state <= WD_CLIENT_STATE_LOGGED_IN) {
		if(!pool)
			pool = wi_pool_init(wi_pool_alloc());
		
		if(client->buffer_offset == 0) {
			do {
				state = wi_socket_wait(client->socket, 0.1);
			} while(state == 0 && client->state <= WD_CLIENT_STATE_LOGGED_IN);
			
			if(client->state > WD_CLIENT_STATE_LOGGED_IN) {
				/* invalid state */
				break;
			}

			if(state < 0) {
				if(wi_error_code() == EINTR) {
					/* got a signal */
					continue;
				} else {
					/* error in TCP communication */
					wi_log_err(WI_STR("Could not read from %@: %m"), client->ip);

					break;
				}
			}
		}

		wd_client_lock_socket(client);
		string = wi_socket_read_to_string(client->socket, 0.0, WI_STR(WD_MESSAGE_SEPARATOR_STR));
		wd_client_unlock_socket(client);
		
		if(!string || wi_string_length(string) == 0) {
			if(!string)
				wi_log_info(WI_STR("Could not read from %@: %m"), client->ip);
			
			break;
		}

		wd_parse_command(string);
		
		if(++i % 10 == 0) {
			wi_release(pool);
			pool = NULL;
		}
	}
	
	/* announce parting if client disconnected by itself */
	if(client->state == WD_CLIENT_STATE_LOGGED_IN) {
		client->state = WD_CLIENT_STATE_DISCONNECTED;

		wd_broadcast_lock();
		wd_client_broadcast_leave(client, WD_PUBLIC_CID);
		wd_broadcast_unlock();
	}

	/* update status for clients logged in and above */
	if(client->state >= WD_CLIENT_STATE_LOGGED_IN) {
		wi_lock_lock(wd_status_lock);
		wd_current_users--;
		wd_write_status(true);
		wi_lock_unlock(wd_status_lock);
	}

	wi_log_info(WI_STR("Disconnect from %@"), client->ip);
	
	wi_socket_close(client->socket);
	
	wd_clients_remove_client(client);
	
	wi_release(pool);
}
Пример #17
0
int main(int argc, const char **argv) {
	wi_pool_t		*pool;
	wi_string_t		*user, *password;
	wi_url_t		*url;
	int				ch;
	
	wi_initialize();
	wi_load(argc, argv);
	
	wi_log_tool 	= true;
	wi_log_level 	= WI_LOG_DEBUG;
	
	pool			= wi_pool_init(wi_pool_alloc());
	
	user 			= WI_STR("guest");
	password		= WI_STR("");
	
	wc_spec			= wi_p7_spec_init_with_file(wi_p7_spec_alloc(), WI_STR("wired.xml"), WI_P7_CLIENT);
	
	while((ch = getopt(argc, (char * const *) argv, "D:U:c:p:u:")) != -1) {
		switch(ch) {
			case 'p':
				password = wi_string_with_cstring(optarg);
				break;
				
			case 'u':
				user = wi_string_with_cstring(optarg);
				break;
				
			case '?':
			case 'h':
			default:
				wc_usage();
				break;
		}
	}
	
	argc -= optind;
	argv += optind;
	
	if(argc != 1)
		wc_usage();
	
	url = wi_url_init_with_string(wi_url_alloc(), wi_string_with_cstring(argv[0]));
	wi_url_set_scheme(url, WI_STR("wired"));
	
	if(!url)
		wc_usage();
	
	wi_url_set_user(url, user);
	wi_url_set_password(url, password);
	
	if(wi_url_port(url) == 0)
		wi_url_set_port(url, 4871);
	
	if(!wi_url_is_valid(url))
		wc_usage();
	
	signal(SIGPIPE, SIG_IGN);
	
	wc_client(url);
	
	wi_release(pool);
	
	return 0;
}
Пример #18
0
int main(int argc, const char **argv) {
	wi_pool_t			*pool;
	wi_string_t			*user, *password, *root_path;
	wi_mutable_url_t	*url;
	int					ch;
	
	wi_initialize();
	wi_load(argc, argv);
	
	wi_log_tool 	= true;
	wi_log_level 	= WI_LOG_DEBUG;
	
	pool			= wi_pool_init(wi_pool_alloc());
	
	user 			= WI_STR("guest");
	password		= WI_STR("");
	root_path		= WI_STR(WD_ROOT);
	
	while((ch = getopt(argc, (char * const *) argv, "d:p:u:")) != -1) {
		switch(ch) {
			case 'd':
				root_path = wi_string_with_cstring(optarg);
				break;
				
			case 'p':
				password = wi_string_with_cstring(optarg);
				break;
				
			case 'u':
				user = wi_string_with_cstring(optarg);
				break;
				
			case '?':
			case 'h':
			default:
				wc_usage();
				break;
		}
	}
	
	argc -= optind;
	argv += optind;
	
	if(argc != 1)
		wc_usage();
	
	if(!wi_fs_change_directory(root_path))
		wi_log_fatal(WI_STR("Could not change directory to %@: %m"), root_path);
	
	wc_spec = wi_p7_spec_init_with_file(wi_p7_spec_alloc(), WI_STR("wired.xml"), WI_P7_CLIENT);
	
	if(!wc_spec)
		wi_log_fatal(WI_STR("Could not open wired.xml: %m"));
	
	url = wi_url_init_with_string(wi_mutable_url_alloc(), wi_string_with_cstring(argv[0]));
	wi_mutable_url_set_scheme(url, WI_STR("wired"));
	
	if(!url)
		wc_usage();
	
	wi_mutable_url_set_user(url, user);
	wi_mutable_url_set_password(url, password);
	
	if(wi_url_port(url) == 0)
		wi_mutable_url_set_port(url, 4871);
	
	if(!wi_url_is_valid(url))
		wc_usage();
	
	signal(SIGPIPE, SIG_IGN);
	
	wc_test(url, 10, WI_STR("/transfertest"));
	
	wi_release(pool);
	
	return 0;
}
Пример #19
0
static wi_boolean_t wd_transfer_download(wd_transfer_t *transfer) {
	wi_pool_t				*pool;
	wi_socket_t				*socket;
	wi_p7_socket_t			*p7_socket;
	wd_account_t			*account;
	char					buffer[WD_TRANSFER_BUFFER_SIZE];
	wi_socket_state_t		state;
	wi_time_interval_t		timeout, interval, speedinterval, statusinterval, accountinterval;
	wi_file_offset_t		sendbytes, speedbytes, statsbytes;
	wi_uinteger_t			i, transfers;
	ssize_t					readbytes;
	int						sd;
	wi_boolean_t			data, result;
	wd_user_state_t			user_state;
	
	interval				= wi_time_interval();
	speedinterval			= interval;
	statusinterval			= interval;
	accountinterval			= interval;
	speedbytes				= 0;
	statsbytes				= 0;
	i						= 0;
	socket					= wd_user_socket(transfer->user);
	sd						= wi_socket_descriptor(socket);
	p7_socket				= wd_user_p7_socket(transfer->user);
	account					= wd_user_account(transfer->user);
	data					= true;
	result					= true;
	
	wd_transfers_note_statistics(WD_TRANSFER_DOWNLOAD, WD_TRANSFER_STATISTICS_ADD, 0);
	
	wi_dictionary_rdlock(wd_transfers_user_downloads);
	
	transfers = (wi_integer_t) wi_dictionary_data_for_key(wd_transfers_user_downloads, transfer->key);
	
	wi_dictionary_unlock(wd_transfers_user_downloads);

	pool = wi_pool_init(wi_pool_alloc());
	
	wd_user_lock_socket(transfer->user);
	
	while(wd_user_state(transfer->user) == WD_USER_LOGGED_IN) {
		if(data && transfer->remainingdatasize == 0)
			data = false;
			  
		if(!data && transfer->remainingrsrcsize == 0)
			break;
		
		readbytes = read(data ? transfer->datafd : transfer->rsrcfd, buffer, sizeof(buffer));
		
		if(readbytes <= 0) {
			if(readbytes < 0) {
				wi_log_error(WI_STR("Could not read download from \"%@\": %m"),
					data ? transfer->realdatapath : transfer->realrsrcpath, strerror(errno));
			}
			
			result = false;
			break;
		}

		timeout = wi_time_interval();
		
		do {
			user_state		= wd_user_state(transfer->user);
			state			= wi_socket_wait_descriptor(sd, 0.1, false, true);
			
			if(state == WI_SOCKET_TIMEOUT) {
				if(wi_time_interval() - timeout >= 30.0)
					break;
			}
		} while(state == WI_SOCKET_TIMEOUT && user_state == WD_USER_LOGGED_IN);

		if(state == WI_SOCKET_ERROR || wi_time_interval() - timeout >= 30.0) {
			wi_log_error(WI_STR("Could not wait for download to %@: %@"),
				wd_user_identifier(transfer->user),
				(state == WI_SOCKET_ERROR) ? wi_error_string() : WI_STR("Timed out"));
			
			result = false;
			break;
		}
		
		if(user_state != WD_USER_LOGGED_IN) {
			result = false;
			break;
		}

		if(data) {
			sendbytes = (transfer->remainingdatasize < (wi_file_offset_t) readbytes)
				? transfer->remainingdatasize
				: (wi_file_offset_t) readbytes;
		} else {
			sendbytes = (transfer->remainingrsrcsize < (wi_file_offset_t) readbytes)
				? transfer->remainingrsrcsize
				: (wi_file_offset_t) readbytes;
		}
		
		if(!wi_p7_socket_write_oobdata(p7_socket, 30.0, buffer, sendbytes)) {
			wi_log_error(WI_STR("Could not write download to %@: %m"),
				wd_user_identifier(transfer->user));
			
			result = false;
			break;
		}
		
		if(data)
			transfer->remainingdatasize		-= sendbytes;
		else
			transfer->remainingrsrcsize		-= sendbytes;
		
		interval							= wi_time_interval();
		transfer->transferred				+= sendbytes;
		transfer->actualtransferred			+= sendbytes;
		speedbytes							+= sendbytes;
		statsbytes							+= sendbytes;
		transfer->speed						= speedbytes / (interval - speedinterval);

		wd_transfer_limit_speed(transfer,
								wd_transfers_total_download_speed,
								wd_account_transfer_download_speed_limit(account),
								wd_current_downloads,
								transfers,
								speedbytes,
								interval,
								speedinterval);
		
		if(interval - speedinterval > 30.0) {
			speedbytes = 0;
			speedinterval = interval;
		}

		if(interval - statusinterval > wd_current_downloads) {
			wd_transfers_note_statistics(WD_TRANSFER_DOWNLOAD, WD_TRANSFER_STATISTICS_DATA, statsbytes);

			statsbytes = 0;
			statusinterval = interval;
		}
		
		if(interval - accountinterval > 15.0) {
			account = wd_user_account(transfer->user);
			accountinterval = interval;

			wi_dictionary_rdlock(wd_transfers_user_downloads);
			
			transfers = (wi_integer_t) wi_dictionary_data_for_key(wd_transfers_user_downloads, transfer->key);
			
			wi_dictionary_unlock(wd_transfers_user_downloads);
		}
		
		if(++i % 1000 == 0)
			wi_pool_drain(pool);
	}
	
	wd_user_unlock_socket(transfer->user);
	
	wi_release(pool);

	wd_transfers_note_statistics(WD_TRANSFER_DOWNLOAD, WD_TRANSFER_STATISTICS_REMOVE, statsbytes);
	
	return result;
}
Пример #20
0
static void wd_transfers_queue_thread(wi_runtime_instance_t *argument) {
	wi_pool_t					*pool;
	wi_enumerator_t				*enumerator;
	wi_mutable_dictionary_t		*key_queues;
	wi_mutable_array_t			*key_queue, *keys;
	wi_string_t					*key;
	wd_transfer_t				*transfer;
	wd_account_t				*account;
	wi_uinteger_t				user_downloads, user_uploads, user_transfers;
	wi_uinteger_t				new_position, position, queue, i, count, longest_queue;
	
	pool = wi_pool_init(wi_pool_alloc());
	
	key_queues = wi_dictionary_init(wi_mutable_dictionary_alloc());
	
	while(true) {
		wi_mutable_dictionary_remove_all_data(key_queues);

		wi_condition_lock_lock_when_condition(wd_transfers_queue_lock, 1, 0.0);
		wi_array_rdlock(wd_transfers);
		
		longest_queue	= 0;
		enumerator		= wi_array_data_enumerator(wd_transfers);
		
		while((transfer = wi_enumerator_next_data(enumerator))) {
			wi_condition_lock_lock(transfer->queue_lock);
			
			if(transfer->state == WD_TRANSFER_QUEUED && transfer->queue != 0) {
				key_queue = wi_dictionary_data_for_key(key_queues, transfer->key);
				
				if(!key_queue) {
					key_queue = wi_mutable_array();
					
					wi_mutable_dictionary_set_data_for_key(key_queues, key_queue, transfer->key);
				}
				
				wi_mutable_array_add_data(key_queue, transfer);
				
				if(wi_array_count(key_queue) > longest_queue)
					longest_queue = wi_array_count(key_queue);
			}
			
			wi_condition_lock_unlock(transfer->queue_lock);
		}
		
		keys		= wi_autorelease(wi_mutable_copy(wi_dictionary_keys_sorted_by_value(key_queues, wd_transfers_queue_compare)));
		position	= 1;
		count		= wi_array_count(keys);
		
		while(longest_queue > 0) {
			for(i = 0; i < count; i++) {
				key			= WI_ARRAY(keys, i);
				key_queue	= wi_dictionary_data_for_key(key_queues, key);
				
				if(wi_array_count(key_queue) > 0) {
					transfer	= WI_ARRAY(key_queue, 0);
					account		= wd_user_account(transfer->user);

					wi_lock_lock(wd_transfers_status_lock);
					
					if(transfer->type == WD_TRANSFER_DOWNLOAD) {
						wi_dictionary_rdlock(wd_transfers_user_downloads);
						
						user_downloads	= wd_account_transfer_download_limit(account);
						user_transfers	= (wi_integer_t) wi_dictionary_data_for_key(wd_transfers_user_downloads, transfer->key);
						queue			= ((wd_transfers_total_downloads > 0 && wd_transfers_active_downloads >= wd_transfers_total_downloads) ||
										   (user_downloads > 0 && user_transfers >= user_downloads));

						wi_dictionary_unlock(wd_transfers_user_downloads);
					} else {
						wi_dictionary_rdlock(wd_transfers_user_uploads);
						
						user_uploads	= wd_account_transfer_upload_limit(account);
						user_transfers	= (wi_integer_t) wi_dictionary_data_for_key(wd_transfers_user_uploads, transfer->key);
						queue			= ((wd_transfers_total_uploads > 0 && wd_transfers_active_uploads >= wd_transfers_total_uploads) ||
										   (user_uploads > 0 && user_transfers >= user_uploads));

						wi_dictionary_unlock(wd_transfers_user_uploads);
					}
					
					wi_lock_unlock(wd_transfers_status_lock);
					
					if(queue)
						new_position = position++;
					else
						new_position = 0;
					
					if(new_position != (wi_uinteger_t) transfer->queue) {
						if(new_position == 0)
							wd_transfers_add_or_remove_transfer(transfer, true);
						
						wi_condition_lock_lock(transfer->queue_lock);
						transfer->queue = new_position;
						wi_condition_lock_unlock_with_condition(transfer->queue_lock, 1);
					}
					
					wi_mutable_array_remove_data_at_index(key_queue, 0);
				}
			}
				
			longest_queue--;
		}
		
		wi_array_unlock(wd_transfers);
		wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 0);
		
		wi_pool_drain(pool);
	}
	
	wi_release(key_queues);
	wi_release(pool);
}
Пример #21
0
int main(int argc, const char **argv) {
	wi_mutable_array_t		*arguments;
	wi_pool_t				*pool;
	wi_string_t				*string, *root_path;
	int						ch, facility;
	wi_boolean_t			test_config, daemonize, change_directory, switch_user;

	/* init libwired */
	wi_initialize();
	wi_load(argc, argv);
	
	pool					= wi_pool_init(wi_pool_alloc());
	wi_log_syslog			= true;
	wi_log_syslog_facility	= LOG_DAEMON;

	/* init core systems */
	wt_version_init();
	wt_status_lock			= wi_lock_init(wi_lock_alloc());
	wt_start_date			= wi_date_init(wi_date_alloc());
	
	/* set defaults */
	root_path				= WI_STR(WT_ROOT);
	wi_settings_config_path	= wi_string_init_with_cstring(wi_string_alloc(), WT_CONFIG_PATH);
	test_config				= false;
	daemonize				= true;
	change_directory		= true;
	switch_user				= true;

	/* init reexec argument list */
	arguments				= wi_array_init(wi_mutable_array_alloc());

	/* parse command line switches */
	while((ch = getopt(argc, (char * const *) argv, "46Dd:f:hi:L:ls:tuVvXx")) != -1) {
		switch(ch) {
			case '4':
				wt_address_family = WI_ADDRESS_IPV4;
				break;

			case '6':
				wt_address_family = WI_ADDRESS_IPV6;
				break;

			case 'D':
				daemonize = false;
				wi_log_stderr = true;
				break;

			case 'd':
				root_path = wi_string_with_cstring(optarg);
				break;

			case 'f':
				wi_release(wi_settings_config_path);
				wi_settings_config_path = wi_string_init_with_cstring(wi_string_alloc(), optarg);
				break;

			case 'i':
				wi_log_limit = wi_string_uint32(wi_string_with_cstring(optarg));
				break;

			case 'L':
				wi_log_syslog = false;
				wi_log_file = true;

				wi_release(wi_log_path);
				wi_log_path = wi_string_init_with_cstring(wi_string_alloc(), optarg);
				break;

			case 'l':
				wi_log_level++;
				break;

			case 's':
				string = wi_string_with_cstring(optarg);
				facility = wi_log_syslog_facility_with_name(string);
				
				if(facility < 0)
					wi_log_fatal(WI_STR("Could not find syslog facility \"%@\": %m"), string);
				
				wi_log_syslog_facility = facility;
				break;

			case 't':
				test_config = true;
				break;

			case 'u':
				break;

			case 'V':
			case 'v':
				wt_version();
				break;
				
			case 'X':
				daemonize = false;
				break;
				
			case 'x':
				daemonize = false;
				change_directory = false;
				switch_user = false;
				break;
			
			case '?':
			case 'h':
			default:
				wt_usage();
				break;
		}
		
		wi_mutable_array_add_data(arguments, wi_string_with_format(WI_STR("-%c"), ch));
		
		if(optarg)
			wi_mutable_array_add_data(arguments, wi_string_with_cstring(optarg));
	}
	
	/* detach */
	if(daemonize) {
		wi_mutable_array_add_data(arguments, WI_STR("-X"));
		
		switch(wi_fork()) {
			case -1:
				wi_log_fatal(WI_STR("Could not fork: %m"));
				break;
				
			case 0:
				if(!wi_execv(wi_string_with_cstring(argv[0]), arguments))
					wi_log_fatal(WI_STR("Could not execute %s: %m"), argv[0]);
				break;
				
				default:
				_exit(0);
				break;
		}
	}
	
	wi_release(arguments);
	
	/* change directory */
	if(change_directory) {
		if(!wi_fs_change_directory(root_path))
			wi_log_error(WI_STR("Could not change directory to %@: %m"), root_path);
	}
	
	/* open log */
	wi_log_open();

	/* init subsystems */
	wt_ssl_init();
	wt_clients_init();
	wt_servers_init();

	/* read the config file */
	wt_settings_init();

	if(!wt_settings_read_config())
		exit(1);

	/* apply settings */
	wt_settings_apply_settings();

	if(test_config) {
		printf("Config OK\n");

		exit(0);
	}

	/* dump command line */
	wi_log_info(WI_STR("Started as %@ %@"),
		wi_process_path(wi_process()),
		wi_array_components_joined_by_string(wi_process_arguments(wi_process()), WI_STR(" ")));

	/* init tracker */
	wi_log_info(WI_STR("Starting Wired Tracker version %@"), wt_version_string);
	wt_tracker_init();

	/* switch user/group */
	if(switch_user)
		wi_switch_user(wt_settings.user, wt_settings.group);
		
	/* create tracker threads after privilege drop */
	wt_signals_init();
	wt_block_signals();
	wt_servers_schedule();
	wt_tracker_create_threads();
	wt_write_pid();
	wt_write_status(true);
	
	/* clean up pool after startup */
	wi_pool_drain(pool);
	
	/* enter the signal handling thread in the main thread */
	wt_signal_thread(NULL);

	/* dropped out */
	wt_cleanup();
	wi_log_close();
	wi_release(pool);

	return 0;
}