示例#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
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);
}
示例#3
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);
}
示例#4
0
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;
}
示例#5
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;
}
示例#6
0
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);
}
示例#7
0
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;
}
示例#8
0
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;
}
示例#9
0
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);
}
示例#10
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);
}
示例#11
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
}