/*
 * Authors: Weiyan Lin
 * Purpose: It checks the arguments and run the program or
 *	    test 
 * 
 * Expected input: 1)[port number]
 *		     enter transaction mode and input command
 *		     using keyboard
 *		   2)[port number] < [file]
 *	             enter transaction mode and use file as
 *	             input command
 *
 e* Implementation details: Check the arguments are provided.
 * Run the corresponding mode.
 */
int main(int argc, char *argv[])
{

		if (argc >= 2 && strcmp(argv[1], "test") == 0)
		{
				testall();
				return 0;
		}
		machine *p_machine=malloc(sizeof(machine));
		memset(p_machine,0,sizeof(machine));
		mode_startup(p_machine);
		register_tcp_handlers();
		prepare_generic_socket(argc, argv, AF_INET, AI_PASSIVE, SOCK_STREAM, IPPROTO_TCP);
		if (listen(sock, 1) < 0)
		{
				vending_exit_with_error("listen failed",p_machine);
		}
		while(!stop)
		{

				struct ser_tran *torecv=malloc(sizeof(struct ser_tran));
				exit_torecv = torecv;
				memset(torecv,0,sizeof(struct ser_tran));
				receive_center(p_machine, torecv);
				connect_user(p_machine, torecv,argc,argv);
				sleep(2);
				free(torecv);		
		}

		//	free all the p_machine information
		int i;
		for (i=0; i <99; i++)
		{
				if ( p_machine->ptr_bg[i] != NULL)
				{       
						//if seq_num exists, get the address from pointer array
						free(p_machine->ptr_bg[i]);
				}

		}

		for(i=0;i<p_machine->item_num;i++)
		{
				free(p_machine->item[i].label);
		}	
		free(p_machine->item);	
		fclose(p_machine->log);	
		free(p_machine);
		cleanup();
		return 0;
}
Beispiel #2
0
/**
 * Server Main Loop
 * @param server Server Listening Socket
 * @return OS Error Code
 */
int server_loop(int server)
{
	// Set Running Status
	_status = 1;
	
	// Create Empty Status Logfile
	update_status();
	
	// Handling Loop
	while(_status == 1)
	{
		// Login Block
		{
			// Login Result
			int loginresult = 0;
			
			// Login Processing Loop
			do
			{
				// Prepare Address Structure
				struct sockaddr_in addr;
				socklen_t addrlen = sizeof(addr);
				memset(&addr, 0, sizeof(addr));
				
				// Accept Login Requests
				// loginresult = accept4(server, (struct sockaddr *)&addr, &addrlen, SOCK_NONBLOCK);
				
				// Alternative Accept Approach (some Linux Kernel don't support the accept4 Syscall... wtf?)
				loginresult = accept(server, (struct sockaddr *)&addr, &addrlen);
				if(loginresult != -1)
				{
					// Switch Socket into Non-Blocking Mode
					change_blocking_mode(loginresult, 1);
				}
				
				// Login User (Stream)
				if(loginresult != -1) login_user_stream(loginresult, addr.sin_addr.s_addr);
			} while(loginresult != -1);
		}
		
		// Receive Data from Users
		SceNetAdhocctlUserNode * user = _db_user;
		while(user != NULL)
		{
			// Next User (for safe delete)
			SceNetAdhocctlUserNode * next = user->next;
			
			// Receive Data from User
			int recvresult = recv(user->stream, user->rx + user->rxpos, sizeof(user->rx) - user->rxpos, 0);
			
			// Connection Closed or Timed Out
			if(recvresult == 0 || (recvresult == -1 && errno != EAGAIN && errno != EWOULDBLOCK) || get_user_state(user) == USER_STATE_TIMED_OUT)
			{
				// Logout User
				logout_user(user);
			}
			
			// Received Data (or leftovers in RX-Buffer)
			else if(recvresult > 0 || user->rxpos > 0)
			{
				// New Incoming Data
				if(recvresult > 0)
				{
					// Move RX Pointer
					user->rxpos += recvresult;
					
					// Update Death Clock
					user->last_recv = time(NULL);
				}
				
				// Waiting for Login Packet
				if(get_user_state(user) == USER_STATE_WAITING)
				{
					// Valid Opcode
					if(user->rx[0] == OPCODE_LOGIN)
					{
						// Enough Data available
						if(user->rxpos >= sizeof(SceNetAdhocctlLoginPacketC2S))
						{
							// Clone Packet
							SceNetAdhocctlLoginPacketC2S packet = *(SceNetAdhocctlLoginPacketC2S *)user->rx;
							
							// Remove Packet from RX Buffer
							clear_user_rxbuf(user, sizeof(SceNetAdhocctlLoginPacketC2S));
							
							// Login User (Data)
							login_user_data(user, &packet);
						}
					}
					
					// Invalid Opcode
					else
					{
						// Notify User
						uint8_t * ip = (uint8_t *)&user->resolver.ip;
						printf("Invalid Opcode 0x%02X in Waiting State from %u.%u.%u.%u.\n", user->rx[0], ip[0], ip[1], ip[2], ip[3]);
						
						// Logout User
						logout_user(user);
					}
				}
				
				// Logged-In User
				else if(get_user_state(user) == USER_STATE_LOGGED_IN)
				{
					// Ping Packet
					if(user->rx[0] == OPCODE_PING)
					{
						// Delete Packet from RX Buffer
						clear_user_rxbuf(user, 1);
					}
					
					// Group Connect Packet
					else if(user->rx[0] == OPCODE_CONNECT)
					{
						// Enough Data available
						if(user->rxpos >= sizeof(SceNetAdhocctlConnectPacketC2S))
						{
							// Cast Packet
							SceNetAdhocctlConnectPacketC2S * packet = (SceNetAdhocctlConnectPacketC2S *)user->rx;
							
							// Clone Group Name
							SceNetAdhocctlGroupName group = packet->group;
							
							// Remove Packet from RX Buffer
							clear_user_rxbuf(user, sizeof(SceNetAdhocctlConnectPacketC2S));
							
							// Change Game Group
							connect_user(user, &group);
						}
					}
					
					// Group Disconnect Packet
					else if(user->rx[0] == OPCODE_DISCONNECT)
					{
						// Remove Packet from RX Buffer
						clear_user_rxbuf(user, 1);
						
						// Leave Game Group
						disconnect_user(user);
					}
					
					// Network Scan Packet
					else if(user->rx[0] == OPCODE_SCAN)
					{
						// Remove Packet from RX Buffer
						clear_user_rxbuf(user, 1);
						
						// Send Network List
						send_scan_results(user);
					}
					
					// Chat Text Packet
					else if(user->rx[0] == OPCODE_CHAT)
					{
						// Enough Data available
						if(user->rxpos >= sizeof(SceNetAdhocctlChatPacketC2S))
						{
							// Cast Packet
							SceNetAdhocctlChatPacketC2S * packet = (SceNetAdhocctlChatPacketC2S *)user->rx;
							
							// Clone Buffer for Message
							char message[64];
							memset(message, 0, sizeof(message));
							strncpy(message, packet->message, sizeof(message) - 1);
							
							// Remove Packet from RX Buffer
							clear_user_rxbuf(user, sizeof(SceNetAdhocctlChatPacketC2S));
							
							// Spread Chat Message
							spread_message(user, message);
						}
					}
					
					// Invalid Opcode
					else
					{
						// Notify User
						uint8_t * ip = (uint8_t *)&user->resolver.ip;
						printf("Invalid Opcode 0x%02X in Logged-In State from %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u).\n", user->rx[0], (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3]);

						// Logout User
						logout_user(user);
					}
				}
			}
			
			// Move Pointer
			user = next;
		}
		
		// Prevent needless CPU Overload (1ms Sleep)
		usleep(1000);
	}
	
	// Free User Database Memory
	free_database();
	
	// Close Server Socket
	close(server);
	
	// Return Success
	return 0;
}
Beispiel #3
0
/*リクエストを処理するに値する*/
int connection_do_request(CONNECTION_DATA* con,int content_length){
	FILE* log_file;
	TCPsocket* c_sock = &con->socket;
	char* recv;
	int idx = 0;
	int size;
	int total_size = 0;
	USER_INFO* info;
	CRYPT* crypt;
	//リクエスト関係
	Uint32 user_id;
	Uint32 action_code;
	//非暗号化データ
	user_id = NetUtl_recvInt(c_sock);
	idx+=4;
	action_code = NetUtl_recvInt(c_sock);
	idx+=4;
	content_length -= idx;
	idx = 0;
	//この時点でユーザ検索
	info = get_user(user_id);
	if(info == null){//ユーザが見つからない
		char ch;
		int size = 0;
		log_file = lock_log_file();
		time_output();
		ip_output(con->ip);
		fprintf(log_file,"User NOT FOUND ID:%08x\n",user_id);
		unlock_log_file();
		//最後まで受信しないと、エラーになりがち。
		while(size < content_length && SDLNet_TCP_Recv(*c_sock, &ch, 1) == 1){
			size++;
		}
		return false;
	}

	//接続
	if(!connect_user(info)){
		char ch;
		int size = 0;
		//ログ
		log_file = lock_log_file();
		time_output();
		ip_output(con->ip);
		fprintf(log_file,"(%s)Already connected.\n",info->name);
		unlock_log_file();
		//最後まで受信しないと、エラーになりがち。
		while(size < content_length && SDLNet_TCP_Recv(*c_sock, &ch, 1) == 1){
			size++;
		}
		return false;
	}

	//鍵を使うと宣言
	crypt = &info->crypt;
	startCrypt(crypt);

	//暗号化データ受信
	recv = malloc(content_length);
	while((size = recvCrypt(crypt,c_sock,
					&recv[total_size],content_length-total_size)) > 0){
		total_size += size;
		if(total_size >= content_length){
			break;
		}
	}
	//サイズがあわない。
	if(total_size < content_length){
		log_file = lock_log_file();
		time_output();
		ip_output(con->ip);
		fprintf(log_file,"(%s)Invalid Size Request.\n",info->name);
		unlock_log_file();
		//処理
		free(recv);
		disconnect_user(info);
		//KICKED
		connection_return_req_data_header(con,CONNECTION_ACTION_KICKED);
		return false;
	}

	//リクエスト完成
	if(!init_request(&con->request,info,action_code,recv,total_size)){
		log_file = lock_log_file();
		time_output();
		ip_output(con->ip);
		fprintf(log_file,"(%s)Invalid Request.\n",info->name);
		unlock_log_file();
		//処理
		free_request(&con->request);
		disconnect_user(info);
		//KICKED
		connection_return_req_data_header(con,CONNECTION_ACTION_KICKED);
		return false;
	}
	//スイッチ
	switch_request(con);
	disconnect_user(info);
	free_request(&con->request);
	return true;
}