int user_read(t_server *server, t_client *cl) { char buf[RSIZE]; char aligned[cl->rb->size + 1]; char *tmp; char *save; ssize_t retv; tmp = aligned; if ((retv = read(cl->fd, buf, RSIZE)) <= 0) return (disconnect_user(server, cl)); fill_ringbuffer(cl->rb, buf, retv); if ((tmp = get_buff(cl->rb)) == NULL) return (-1); save = tmp; while ((retv = get_char_pos(tmp, '\n')) != -1) { tmp[retv] = '\0'; if (process_input(server, cl, tmp) < -1) { queue_push(&cl->queue, "ko\n"); return (disconnect_user(server, cl)); } tmp = &tmp[retv + 1]; } update_ringbuffer(cl->rb, save, tmp); return (0); }
/*** login_time_out is the length of time someone can idle at login, user_idle_time is the length of time they can idle once logged in. Also ups users total login time. ***/ void check_idle_and_timeout(void) { UR_OBJECT user=user_first,next; int tm; set_crash(); /* Use while loop here instead of for loop for when user structure gets destructed, we may lose ->next link and crash the program */ while (user) { next=user->next; if (user->type==CLONE_TYPE) { user=next; continue; } user->total_login+=amsys->heartbeat; if (user->level>amsys->time_out_maxlevel) { user=next; continue; } tm=(int)(time(0) - user->last_input); if (user->login && tm>=amsys->login_idle_time) { write_user(user, login_timeout); disconnect_user(user); user=next; continue; } if (syspp->auto_afk && tm>=syspp->auto_afk_time && !user->afk && !user->login) { afk(user, auto_afk_mesg); user=next; continue; } if (user->warned) { if (tm<amsys->user_idle_time-60) { user->warned=0; continue; } if (tm>=amsys->user_idle_time) { write_user(user,"\n\n\07~FR~OL~LI*** You have been timed out. ***\n\n"); disconnect_user(user); user=next; continue; } } if ((!user->afk || (user->afk && amsys->time_out_afks)) && !user->login && !user->warned && tm>=amsys->user_idle_time-60) { #ifdef PUEBLO audioprompt(user, 4, 0); #endif vwrite_user(user,"\n\07~FY~OL~LI*** POZOR - Mas 1 minutu aby si nieco napisal%s lebo ta vydrbkam !***\n\n", grm_gnd(4, user->gender)); user->warned=1; } user=next; } }
void kick_user(client client, char *msg) { if (client.isAlive) { send(client.fd, recv_msg[KICKED], strlen(recv_msg[KICKED]), MSG_NOSIGNAL); send(client.fd, msg, strlen(msg), MSG_NOSIGNAL); disconnect_user(client); } }
int user_write(t_server *server, t_client *cl) { ssize_t wsize; ssize_t msglen; char *msg; msg = queue_front(cl->queue); msglen = strlen(msg); if ((wsize = write(cl->fd, msg, msglen)) <= 0) { perror(""); return (disconnect_user(server, cl)); } if (wsize < msglen) shift_msg(msg, wsize); else queue_pop(&cl->queue); 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; }
/* * Shoot another user... Fun! Fun! Fun! ;) */ void shoot_user(UR_OBJECT user) { UR_OBJECT user2; RM_OBJECT rm; int prob1, prob2; rm = get_room_full(amsys->default_shoot); if (!rm) { write_user(user, "There is nowhere that you can shoot.\n"); return; } if (user->room != rm) { vwrite_user(user, "Do not be shooting in a public place. Go to the ~OL%s~RS to play.\n", rm->name); return; } if (word_count < 2) { if (!user->bullets) { vwrite_room_except(rm, user, "%s~RS's gun goes *click* as they pull the trigger.\n", user->recap); write_user(user, "Your gun goes *click* as you pull the trigger.\n"); return; } vwrite_room_except(rm, user, "%s~RS fires their gun off into the air.\n", user->recap); write_user(user, "You fire your gun off into the air.\n"); --user->bullets; return; } prob1 = rand() % 100; prob2 = rand() % 100; user2 = get_user_name(user, word[1]); if (!user2) { write_user(user, notloggedon); return; } if (!user->vis) { write_user(user, "Be fair! At least make a decent target--do not be invisible!\n"); return; } if ((!user2->vis && user2->level < user->level) || user2->room != rm) { write_user(user, "You cannot see that person around here.\n"); return; } if (user == user2) { write_user(user, "Watch it! You might shoot yourself in the foot!\n"); return; } if (!user->bullets) { vwrite_room_except(rm, user, "%s~RS's gun goes *click* as they pull the trigger.\n", user->recap); write_user(user, "Your gun goes *click* as you pull the trigger.\n"); return; } if (prob1 > prob2) { vwrite_room(rm, "A bullet flies from %s~RS's gun and ~FR~OLhits~RS %s.\n", user->recap, user2->recap); --user->bullets; ++user->hits; --user2->hps; write_user(user2, "~FR~OLYou have been hit!\n"); write_user(user, "~FG~OLGood shot!\n"); if (user2->hps < 1) { ++user2->deaths; vwrite_user(user, "\nYou have won the shoot out, %s~RS is dead! You may now rejoice!\n", user2->recap); write_user(user2, "\nYou have received a fatal wound, and you feel your warm ~FRblood ~OLooze~RS out of you.\n"); write_user(user2, "The room starts to fade and grow grey...\n"); write_user(user2, "In the bleak mist of Death's shroud you see a man walk towards you.\n"); write_user(user2, "The man is wearing a tall black hat, and a wide grin...\n\n"); user2->hps = 5 * user2->level; write_syslog(SYSLOG, 1, "%s shot dead by %s\n", user2->name, user->name); disconnect_user(user2); ++user->kills; user->hps = user->hps + 5; return; } return; } vwrite_room(rm, "A bullet flies from %s~RS's gun and ~FG~OLmisses~RS %s~RS.\n", user->recap, user2->recap); --user->bullets; ++user->misses; write_user(user2, "~FGThat was a close shave!\n"); write_user(user, "~FRYou could not hit the side of a barn!\n"); }
/* * Delete a user */ void delete_user(UR_OBJECT user, int this_user) { char name[USER_NAME_LEN + 1]; UR_OBJECT u; if (this_user) { /* * User structure gets destructed in disconnect_user(), need to keep a * copy of the name */ strcpy(name, user->name); write_user(user, "\n~FR~LI~OLACCOUNT DELETED!\n"); vwrite_room_except(user->room, user, "~OL~LI%s commits suicide!\n", user->name); write_syslog(SYSLOG, 1, "%s SUICIDED.\n", name); disconnect_user(user); clean_files(name); rem_user_node(name); return; } if (word_count < 2) { write_user(user, "Usage: nuke <user>\n"); return; } *word[1] = toupper(*word[1]); if (!strcmp(word[1], user->name)) { write_user(user, "Trying to delete yourself is the eleventh sign of madness.\n"); return; } if (get_user(word[1])) { /* Safety measure just in case. Will have to .kill them first */ write_user(user, "You cannot delete a user who is currently logged on.\n"); return; } u = create_user(); if (!u) { vwrite_user(user, "%s: unable to create temporary user object.\n", syserror); write_syslog(SYSLOG | ERRLOG, 0, "ERROR: Unable to create temporary user object in delete_user().\n"); return; } strcpy(u->name, word[1]); if (!load_user_details(u)) { write_user(user, nosuchuser); destruct_user(u); destructed = 0; return; } if (u->level >= user->level) { write_user(user, "You cannot delete a user of an equal or higher level than yourself.\n"); destruct_user(u); destructed = 0; return; } clean_files(u->name); rem_user_node(u->name); vwrite_user(user, "\07~FR~OL~LIUser %s deleted!\n", u->name); write_syslog(SYSLOG, 1, "%s DELETED %s.\n", user->name, u->name); destruct_user(u); destructed = 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; }
/** * Logout User from Database * @param user User Node */ void logout_user(SceNetAdhocctlUserNode * user) { // Disconnect from Group if(user->group != NULL) disconnect_user(user); // Unlink Leftside (Beginning) if(user->prev == NULL) _db_user = user->next; // Unlink Leftside (Other) else user->prev->next = user->next; // Unlink Rightside if(user->next != NULL) user->next->prev = user->prev; // Close Stream close(user->stream); // Playing User if(user->game != NULL) { // Notify User uint8_t * ip = (uint8_t *)&user->resolver.ip; char safegamestr[10]; memset(safegamestr, 0, sizeof(safegamestr)); strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH); printf("%s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) stopped playing %s.\n", (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], safegamestr); // Fix Game Player Count user->game->playercount--; // Empty Game Node if(user->game->playercount == 0) { // Unlink Leftside (Beginning) if(user->game->prev == NULL) _db_game = user->game->next; // Unlink Leftside (Other) else user->game->prev->next = user->game->next; // Unlink Rightside if(user->game->next != NULL) user->game->next->prev = user->game->prev; // Free Game Node Memory free(user->game); } } // Unidentified User else { // Notify User uint8_t * ip = (uint8_t *)&user->resolver.ip; printf("Dropped Connection to %u.%u.%u.%u.\n", ip[0], ip[1], ip[2], ip[3]); } // Free Memory free(user); // Fix User Counter _db_user_count--; // Update Status Log update_status(); }