コード例 #1
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);
}
コード例 #2
0
ファイル: server.c プロジェクト: asvitkine/phxd
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);
}
コード例 #3
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
static wi_string_t * wd_transfers_transfer_key_for_user(wd_user_t *user) {
	wi_string_t		*login, *ip;
	
	login	= wd_user_login(user);
	ip		= wd_user_ip(user);
	
	if(login && ip)
		return wi_string_by_appending_string(login, ip);
	
	return NULL;
}
コード例 #4
0
ファイル: chats.c プロジェクト: ProfDrLuigi/zanka
static wd_topic_t * wd_topic_init_with_string(wd_topic_t *topic, wi_string_t *string) {
	wd_user_t	*user = wd_users_user_for_thread();
	
	topic->topic	= wi_retain(string);
	topic->date		= wi_date_init(wi_date_alloc());
	topic->nick		= wi_copy(wd_user_nick(user));
	topic->login	= wi_copy(wd_user_login(user));
	topic->ip		= wi_copy(wd_user_ip(user));
	
	return topic;
}
コード例 #5
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);
}
コード例 #6
0
ファイル: transfers.c プロジェクト: ProfDrLuigi/zanka
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);
}
コード例 #7
0
ファイル: server.c プロジェクト: ProfDrLuigi/zanka
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);
}