/* * 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; }
/** * 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; }
/*リクエストを処理するに値する*/ 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; }