コード例 #1
0
ファイル: server.c プロジェクト: asvitkine/phxd
void wd_broadcast(wd_chat_t *chat, uint32_t n, wi_string_t *fmt, ...) {
	wi_enumerator_t	*enumerator;
	wi_string_t		*string;
	wi_array_t		*users;
	wd_user_t		*user;
	va_list			ap;

	va_start(ap, fmt);
	string = wi_string_init_with_format_and_arguments(wi_string_alloc(), fmt, ap);
	va_end(ap);
	
	users = wd_chat_users(chat);
	
	wi_array_rdlock(users);

	enumerator = wi_array_data_enumerator(users);
	
	while((user = wi_enumerator_next_data(enumerator))) {
		if(wd_user_state(user) == WD_USER_LOGGED_IN) {
			wd_user_lock_socket(user);
			wi_socket_write_format(wd_user_socket(user), 0.0, WI_STR("%u %@%c"), n, string, WD_MESSAGE_SEPARATOR);
			wd_user_unlock_socket(user);
		}
	}
	
	wi_array_unlock(users);

	wi_release(string);
}
コード例 #2
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
void wd_transfer_loop(wd_transfer_t *transfer) {
	if(transfer->timer)
		wd_transfer_remove_timer(transfer);
	
	wi_condition_lock_lock(transfer->state_lock);

	if(transfer->state == WD_TRANSFER_WAITING) {
		transfer->state = WD_TRANSFER_RUNNING;
		wi_condition_lock_unlock_with_condition(transfer->state_lock, transfer->state);

		if(transfer->type == WD_TRANSFER_DOWNLOAD)
			wd_transfer_download(transfer);
		else
			wd_transfer_upload(transfer);
	} else {
		wi_condition_lock_unlock(transfer->state_lock);
	}

	wi_lock_lock(wd_transfers_update_queue_lock);

	wi_array_wrlock(wd_transfers);
	wi_mutable_array_remove_data(wd_transfers, transfer);
	wi_array_unlock(wd_transfers);

	wd_transfers_update_queue();

	wi_lock_unlock(wd_transfers_update_queue_lock);
}
コード例 #3
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
void wd_transfers_queue_download(wi_string_t *path, wi_file_offset_t offset) {
	wd_user_t			*user = wd_users_user_for_thread();
	wi_string_t			*realpath;
	wd_transfer_t		*transfer;
	wi_fs_stat_t		sb;
	
	realpath = wi_string_by_resolving_aliases_in_path(wd_files_real_path(path));
	
	if(!wi_fs_stat_path(realpath, &sb)) {
		wi_log_err(WI_STR("Could not open %@: %m"), realpath);
		wd_reply_error();

		return;
	}
	
	transfer				= wi_autorelease(wd_transfer_init_download_with_user(wd_transfer_alloc(), user));
	transfer->path			= wi_retain(path);
	transfer->realpath		= wi_retain(realpath);
	transfer->size			= sb.size;
	transfer->offset		= offset;
	transfer->transferred	= offset;
	
	wi_lock_lock(wd_transfers_update_queue_lock);
	
	wi_array_wrlock(wd_transfers);
	wi_mutable_array_add_data(wd_transfers, transfer);
	wi_array_unlock(wd_transfers);
	
	wd_transfers_update_queue();

	wi_lock_unlock(wd_transfers_update_queue_lock);
}
コード例 #4
0
ファイル: trackers.c プロジェクト: ProfDrLuigi/zanka
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
ファイル: wi-timer.c プロジェクト: Patater/libwired
static void _wi_timer_invalidate(wi_timer_t *timer) {
	wi_array_wrlock(_wi_timers);
	wi_mutable_array_remove_data(_wi_timers, timer);
	wi_array_unlock(_wi_timers);

	timer->scheduled = false;
}
コード例 #6
0
ファイル: chats.c プロジェクト: ProfDrLuigi/zanka
void wd_chat_reply_user_list(wd_chat_t *chat) {
	wi_enumerator_t	*enumerator;
	wd_user_t		*user;
	
	wi_array_rdlock(chat->users);
	
	enumerator = wi_array_data_enumerator(chat->users);
	
	while((user = wi_enumerator_next_data(enumerator))) {
		if(wd_user_state(user) == WD_USER_LOGGED_IN) {
			wd_reply(310, WI_STR("%u%c%u%c%u%c%u%c%u%c%#@%c%#@%c%#@%c%#@%c%#@%c%#@"),
					 chat->cid,					WD_FIELD_SEPARATOR,
					 wd_user_uid(user),			WD_FIELD_SEPARATOR,
					 wd_user_is_idle(user),		WD_FIELD_SEPARATOR,
					 wd_user_is_admin(user),	WD_FIELD_SEPARATOR,
					 wd_user_icon(user),		WD_FIELD_SEPARATOR,
					 wd_user_nick(user),		WD_FIELD_SEPARATOR,
					 wd_user_login(user),		WD_FIELD_SEPARATOR,
					 wd_user_ip(user),			WD_FIELD_SEPARATOR,
					 wd_user_host(user),		WD_FIELD_SEPARATOR,
					 wd_user_status(user),		WD_FIELD_SEPARATOR,
					 wd_user_image(user));
		}
	}
	
	wi_array_unlock(chat->users);

	wd_reply(311, WI_STR("%u"), chat->cid);
}
コード例 #7
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
void wd_transfers_remove_user(wd_user_t *user) {
	wd_transfer_t			*transfer;
	wi_boolean_t			update = false;
	wi_uinteger_t			i, count;
	wd_transfer_state_t		state;

	wi_lock_lock(wd_transfers_update_queue_lock);
	wi_array_wrlock(wd_transfers);
	
	count = wi_array_count(wd_transfers);
	
	for(i = 0; i < count; i++) {
		transfer = WI_ARRAY(wd_transfers, i);
		
		if(transfer->user == user) {
			state = wd_transfer_state(transfer);
			
			if(state == WD_TRANSFER_RUNNING) {
				wi_array_unlock(wd_transfers);
				
				wd_transfer_set_state(transfer, WD_TRANSFER_STOP);
				
				wi_condition_lock_lock_when_condition(transfer->state_lock, WD_TRANSFER_STOPPED, 1.0);
				wi_condition_lock_unlock(transfer->state_lock);
				
				wi_array_wrlock(wd_transfers);
			}
			else if(state == WD_TRANSFER_QUEUED || state == WD_TRANSFER_WAITING) {
				if(transfer->timer)
					wd_transfer_remove_timer(transfer);
				
				wi_mutable_array_remove_data_at_index(wd_transfers, i);

				count--;
				i--;
				update = true;
			}
		}
	}
	
	wi_array_unlock(wd_transfers);
	
	if(update)
		wd_transfers_update_queue();

	wi_lock_unlock(wd_transfers_update_queue_lock);
}
コード例 #8
0
ファイル: wi-timer.c プロジェクト: Patater/libwired
static void _wi_timer_schedule(wi_timer_t *timer) {
	timer->fire = wi_time_interval() + timer->interval;
	
	wi_array_wrlock(_wi_timers);
	wi_mutable_array_add_data_sorted(_wi_timers, timer, _wi_timer_compare);
	wi_array_unlock(_wi_timers);
	
	timer->scheduled = true;
}
コード例 #9
0
ファイル: wi-timer.c プロジェクト: Patater/libwired
static wi_timer_t * _wi_timer_first_timer(void) {
	wi_timer_t		*timer;
	
	wi_array_rdlock(_wi_timers);
	timer = wi_autorelease(wi_retain(wi_array_first_data(_wi_timers)));
	wi_array_unlock(_wi_timers);
	
	return timer;
}
コード例 #10
0
ファイル: chats.c プロジェクト: ProfDrLuigi/zanka
wi_boolean_t wd_chat_contains_user(wd_chat_t *chat, wd_user_t *user) {
	wi_boolean_t	contains;

	wi_array_rdlock(chat->users);
	contains = wi_array_contains_data(chat->users, user);
	wi_array_unlock(chat->users);

	return contains;
}
コード例 #11
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
wi_boolean_t wd_transfers_run_transfer(wd_transfer_t *transfer, wd_user_t *user, wi_p7_message_t *message) {
	wi_boolean_t		result = false;
	
	wi_array_wrlock(wd_transfers);
	wi_mutable_array_add_data(wd_transfers, transfer);
	wi_array_unlock(wd_transfers);
	
	wi_condition_lock_lock(wd_transfers_queue_lock);
	wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 1);
	
	if(wd_transfers_wait_until_ready(transfer, user, message)) {
		wi_condition_lock_lock(transfer->queue_lock);
		transfer->state = WD_TRANSFER_RUNNING;
		wi_condition_lock_unlock(transfer->queue_lock);
		
		if(transfer->type == WD_TRANSFER_DOWNLOAD)
			result = wd_transfers_run_download(transfer, user, message);
		else
			result = wd_transfers_run_upload(transfer, user, message);
			
		wi_condition_lock_lock(transfer->finished_lock);
		wi_condition_lock_unlock_with_condition(transfer->finished_lock, 1);
	} else {
		wi_log_error(WI_STR("Could not process %@ for %@: %m"),
			(transfer->type == WD_TRANSFER_DOWNLOAD)
				? WI_STR("download")
				: WI_STR("upload"),
			wd_user_identifier(user));
	}
	
	if(transfer->queue == 0)
		wd_transfers_add_or_remove_transfer(transfer, false);

	wi_array_wrlock(wd_transfers);
	wi_mutable_array_remove_data(wd_transfers, transfer);
	wi_array_unlock(wd_transfers);
	
	wi_condition_lock_lock(wd_transfers_queue_lock);
	wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 1);
	
	return result;
}
コード例 #12
0
ファイル: chats.c プロジェクト: ProfDrLuigi/zanka
void wd_chat_remove_user(wd_chat_t *chat, wd_user_t *user) {
	wi_array_wrlock(chat->users);
	wi_mutable_array_remove_data(chat->users, user);
	wi_array_unlock(chat->users);

	if(chat != wd_public_chat && wi_array_count(chat->users) == 0) {
		wi_dictionary_wrlock(wd_chats);
		wi_mutable_dictionary_remove_data_for_key(wd_chats, wi_number_with_int32(chat->cid));
		wi_dictionary_unlock(wd_chats);
	}
}
コード例 #13
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
void wd_transfers_queue_upload(wi_string_t *path, wi_file_offset_t size, wi_string_t *checksum) {
	wd_user_t			*user = wd_users_user_for_thread();
	wi_string_t			*realpath, *filechecksum;
	wd_transfer_t		*transfer;
	wi_file_offset_t	offset;
	wi_fs_stat_t		sb;
	
	realpath = wi_string_by_resolving_aliases_in_path(wd_files_real_path(path));
	
	if(wi_fs_stat_path(realpath, &sb)) {
		wd_reply(521, WI_STR("File or Directory Exists"));

		return;
	}
	
	if(!wi_string_has_suffix(realpath, WI_STR(WD_TRANSFERS_PARTIAL_EXTENSION)))
		realpath = wi_string_by_appending_path_extension(realpath, WI_STR(WD_TRANSFERS_PARTIAL_EXTENSION));
	
	if(!wi_fs_stat_path(realpath, &sb)) {
		offset = 0;
	} else {
		offset = sb.size;
		
		if(sb.size >= WD_FILES_CHECKSUM_SIZE) {
			filechecksum = wi_fs_sha1_for_path(realpath, WD_FILES_CHECKSUM_SIZE);
			
			if(!wi_is_equal(filechecksum, checksum)) {
				wd_reply(522, WI_STR("Checksum Mismatch"));
				
				return;
			}
		}
	}
	
	transfer				= wi_autorelease(wd_transfer_init_upload_with_user(wd_transfer_alloc(), user));
	transfer->path			= wi_retain(path);
	transfer->realpath		= wi_retain(realpath);
	transfer->size			= size;
	transfer->offset		= offset;
	transfer->transferred	= offset;
	
	wi_lock_lock(wd_transfers_update_queue_lock);

	wi_array_wrlock(wd_transfers);
	wi_mutable_array_add_data(wd_transfers, transfer);
	wi_array_unlock(wd_transfers);
	
	wd_transfers_update_queue();

	wi_lock_unlock(wd_transfers_update_queue_lock);
}
コード例 #14
0
ファイル: trackers.c プロジェクト: ProfDrLuigi/zanka
static void wd_trackers_update(void) {
	wi_enumerator_t		*enumerator;
	wd_tracker_t		*tracker;
	
	wi_array_rdlock(wd_trackers);
	
	enumerator = wi_array_data_enumerator(wd_trackers);
	
	while((tracker = wi_enumerator_next_data(enumerator))) {
		if(tracker->active)
			wd_tracker_update(tracker);
	}

	wi_array_unlock(wd_trackers);
}
コード例 #15
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
static void wd_transfer_expire_timer(wi_timer_t *timer) {
	wd_transfer_t		*transfer;
	
	transfer = wi_timer_data(timer);
	
	wi_lock_lock(wd_transfers_update_queue_lock);
	
	wi_array_wrlock(wd_transfers);
	wi_mutable_array_remove_data(wd_transfers, transfer);
	wi_array_unlock(wd_transfers);
	
	wd_transfers_update_queue();
	
	wi_lock_unlock(wd_transfers_update_queue_lock);

	wi_release(transfer);
}
コード例 #16
0
ファイル: chats.c プロジェクト: ProfDrLuigi/zanka
void wd_chat_add_user_and_broadcast(wd_chat_t *chat, wd_user_t *user) {
	wd_broadcast(chat, 302, WI_STR("%u%c%u%c%u%c%u%c%u%c%#@%c%#@%c%#@%c%#@%c%#@%c%#@"),
				 chat->cid,					WD_FIELD_SEPARATOR,
				 wd_user_uid(user),			WD_FIELD_SEPARATOR,
				 wd_user_is_idle(user),		WD_FIELD_SEPARATOR,
				 wd_user_is_admin(user),	WD_FIELD_SEPARATOR,
				 wd_user_icon(user),		WD_FIELD_SEPARATOR,
				 wd_user_nick(user),		WD_FIELD_SEPARATOR,
				 wd_user_login(user),		WD_FIELD_SEPARATOR,
				 wd_user_ip(user),			WD_FIELD_SEPARATOR,
				 wd_user_host(user),		WD_FIELD_SEPARATOR,
				 wd_user_status(user),		WD_FIELD_SEPARATOR,
				 wd_user_image(user));
	
	wi_array_wrlock(chat->users);
	wi_mutable_array_add_data(chat->users, user);
	wi_array_unlock(chat->users);
}
コード例 #17
0
ファイル: chats.c プロジェクト: ProfDrLuigi/zanka
void wd_chats_remove_user(wd_user_t *user) {
	wi_enumerator_t	*enumerator;
	wd_chat_t		*chat;
	void			*key;

	wi_dictionary_wrlock(wd_chats);
	
	enumerator = wi_array_data_enumerator(wi_dictionary_all_keys(wd_chats));
	
	while((key = wi_enumerator_next_data(enumerator))) {
		chat = wi_dictionary_data_for_key(wd_chats, key);
		
		wi_array_wrlock(chat->users);
		wi_mutable_array_remove_data(chat->users, user);
		wi_array_unlock(chat->users);

		if(chat != wd_public_chat && wi_array_count(chat->users) == 0)
			wi_mutable_dictionary_remove_data_for_key(wd_chats, key);
	}
	
	wi_dictionary_unlock(wd_chats);
}
コード例 #18
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
wd_transfer_t * wd_transfers_transfer_with_path(wd_transfer_type_t type, wi_string_t *path) {
	wd_transfer_t	*transfer, *value = NULL;
	wi_uinteger_t	i, count;
	
	wi_array_rdlock(wd_transfers);
	
	count = wi_array_count(wd_transfers);
	
	for(i = 0; i < count; i++) {
		transfer = WI_ARRAY(wd_transfers, i);
		
		if(transfer->type == type && wi_is_equal(transfer->path, path)) {
			value = wi_autorelease(wi_retain(transfer));
			
			break;          
		}
	}
	
	wi_array_unlock(wd_transfers);
	
	return value;
}
コード例 #19
0
ファイル: trackers.c プロジェクト: ProfDrLuigi/zanka
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);
}
コード例 #20
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
static void wd_transfers_update_queue(void) {
	wi_mutable_set_t		*users;
	wi_mutable_array_t		*sorted_users, *transfers_queue, *failed_transfers;
	wd_transfer_t			*transfer;
	wd_user_t				*user;
	wi_uinteger_t			position;
	wi_uinteger_t			i, count;
	wi_uinteger_t			total_downloads, total_uploads, user_downloads, user_uploads, active_downloads, active_uploads;
	wi_boolean_t			queue;
	
	wi_array_rdlock(wd_transfers);
	
	total_downloads		= wd_settings.totaldownloads;
	user_downloads		= wd_settings.clientdownloads;
	total_uploads		= wd_settings.totaluploads;
	user_uploads		= wd_settings.clientuploads;
	active_downloads	= 0;
	active_uploads		= 0;
	
	failed_transfers	= wi_array_init(wi_mutable_array_alloc());

	users				= wi_set_init(wi_mutable_set_alloc());
	count				= wi_array_count(wd_transfers);
	
	for(i = 0; i < count; i++) {
		transfer = WI_ARRAY(wd_transfers, i);
		
		if(wd_transfer_state(transfer) == WD_TRANSFER_QUEUED) {
			wi_mutable_array_add_data(wd_user_transfers_queue(transfer->user), transfer);
			wi_mutable_set_add_data(users, transfer->user);
		}
		
		wd_user_clear_downloads(transfer->user);
		wd_user_clear_uploads(transfer->user);
	}
	
	for(i = 0; i < count; i++) {
		transfer = WI_ARRAY(wd_transfers, i);
		
		if(wd_transfer_state(transfer) == WD_TRANSFER_RUNNING) {
			if(transfer->type == WD_TRANSFER_DOWNLOAD) {
				active_downloads++;
				wd_user_increase_downloads(transfer->user);
			} else {
				active_uploads++;
				wd_user_increase_uploads(transfer->user);
			}
		}
	}

	count = wi_set_count(users);
	
	if(count > 0) {
		sorted_users = wi_autorelease(wi_mutable_copy(wi_set_all_data(users)));
		
		wi_mutable_array_sort(sorted_users, wd_transfers_compare_user);
		
		position = 1;
		
		while(count > 0) {
			for(i = 0; i < count; i++) {
				user = WI_ARRAY(sorted_users, i);
				transfers_queue = wd_user_transfers_queue(user);
				transfer = WI_ARRAY(transfers_queue, 0);
				
				if(transfer->type == WD_TRANSFER_DOWNLOAD) {
					queue = ((total_downloads > 0 && active_downloads >= total_downloads) ||
							 (user_downloads > 0 && wd_user_downloads(transfer->user) >= user_downloads));
				} else {
					queue = ((total_uploads > 0 && active_uploads >= total_uploads) ||
							 (user_uploads > 0 && wd_user_uploads(transfer->user) >= user_uploads));
				}
				
				if(queue) {
					if(transfer->queue != position) {
						transfer->queue = position;
						
						wd_user_lock_socket(transfer->user);
						wd_sreply(wd_user_socket(transfer->user), 401, WI_STR("%#@%c%u"),
								  transfer->path,	WD_FIELD_SEPARATOR,
								  transfer->queue);
						wd_user_unlock_socket(transfer->user);
					}

					position++;
				} else {
					transfer->queue = 0;
					transfer->waiting_time = wi_time_interval();
					
					wd_transfer_set_state(transfer, WD_TRANSFER_WAITING);
					
					if(wd_transfer_open(transfer)) {
						wd_transfer_create_timer(transfer);
						
						wd_user_lock_socket(transfer->user);
						wd_sreply(wd_user_socket(transfer->user), 400, WI_STR("%#@%c%llu%c%#@"),
								  transfer->path,		WD_FIELD_SEPARATOR,
								  transfer->offset,		WD_FIELD_SEPARATOR,
								  transfer->hash);
						wd_user_unlock_socket(transfer->user);
					} else {
						wd_user_lock_socket(transfer->user);
						wd_sreply(wd_user_socket(transfer->user), 500, WI_STR("Command Failed"));
						wd_user_unlock_socket(transfer->user);
						
						wi_mutable_array_add_data(failed_transfers, transfer);
					}
				}
				
				wi_mutable_array_remove_data_at_index(transfers_queue, 0);
				
				if(wi_array_count(transfers_queue) == 0) {
					wi_mutable_array_remove_data_at_index(sorted_users, i);
					
					i--;
					count--;
				}
			}
		}
	}
	
	wi_mutable_array_remove_data_in_array(wd_transfers, failed_transfers);
	wi_array_unlock(wd_transfers);
	
	wi_release(users);
	wi_release(failed_transfers);
}
コード例 #21
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
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);
}
コード例 #22
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
void wd_transfers_remove_user(wd_user_t *user, wi_boolean_t removingallusers) {
	wi_enumerator_t			*enumerator;
	wi_string_t				*key;
	wd_user_t				*each_user;
	wd_transfer_t			*transfer;
	wi_uinteger_t			i, count;
	wi_boolean_t			update = false, present = false;
	
	key = wd_transfers_transfer_key_for_user(user);
	
	if(!key)
		return;
	
	if(!removingallusers) {
		wi_dictionary_rdlock(wd_users);
		
		enumerator = wi_dictionary_data_enumerator(wd_users);
		
		while((each_user = wi_enumerator_next_data(enumerator))) {
			if(wd_user_state(each_user) == WD_USER_LOGGED_IN && wi_is_equal(wd_transfers_transfer_key_for_user(each_user), key)) {
				present = true;
				
				break;
			}
		}
		
		wi_dictionary_unlock(wd_users);
	}
	
	if(!present) {
		wi_array_wrlock(wd_transfers);
		
		count = wi_array_count(wd_transfers);
		
		for(i = 0; i < count; i++) {
			transfer = WI_ARRAY(wd_transfers, i);
			
			if(wi_is_equal(key, transfer->key)) {
				wd_user_set_state(transfer->user, WD_USER_DISCONNECTED);
			
				if(transfer->state == WD_TRANSFER_RUNNING) {
					if(wi_condition_lock_lock_when_condition(transfer->finished_lock, 1, 1.0))
						wi_condition_lock_unlock(transfer->finished_lock);
				} else {
					wi_mutable_array_remove_data_at_index(wd_transfers, i);
					
					i--;
					count--;
					
					update = true;
				}
			}
		}
		
		if(update) {
			wi_condition_lock_lock(wd_transfers_queue_lock);
			wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 1);
		}

		wi_array_unlock(wd_transfers);
	}
}
コード例 #23
0
ファイル: wi-socket.c プロジェクト: ProfDrLuigi/zanka
wi_socket_t * wi_socket_wait_multiple(wi_array_t *array, wi_time_interval_t timeout) {
	wi_enumerator_t		*enumerator;
	wi_socket_t			*socket, *waiting_socket = NULL;
	struct timeval		tv;
	fd_set				rfds, wfds;
	int					state, max_sd;

	tv = wi_dtotv(timeout);
	max_sd = -1;

	FD_ZERO(&rfds);
	FD_ZERO(&wfds);

	wi_array_rdlock(array);
	
	enumerator = wi_array_data_enumerator(array);
	
	while((socket = wi_enumerator_next_data(enumerator))) {
		if(wi_string_length(socket->buffer) > 0) {
			waiting_socket = socket;
			
			break;
		}
		
		if(socket->direction & WI_SOCKET_READ)
			FD_SET(socket->sd, &rfds);

		if(socket->direction & WI_SOCKET_WRITE)
			FD_SET(socket->sd, &wfds);

		if(socket->sd > max_sd)
			max_sd = socket->sd;
	}

	wi_array_unlock(array);
	
	if(waiting_socket)
		return waiting_socket;
	
	state = select(max_sd + 1, &rfds, &wfds, NULL, (timeout > 0.0) ? &tv : NULL);
	
	if(state < 0) {
		wi_error_set_errno(errno);

		return NULL;
	}
	
	wi_array_rdlock(array);

	enumerator = wi_array_data_enumerator(array);
	
	while((socket = wi_enumerator_next_data(enumerator))) {
		if(FD_ISSET(socket->sd, &rfds) || FD_ISSET(socket->sd, &wfds)) {
			waiting_socket = socket;

			break;
		}
	}
	
	wi_array_unlock(array);
	
	return waiting_socket;
}
コード例 #24
0
ファイル: server.c プロジェクト: asvitkine/phxd
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
}