void RPCServer::HandleSingleRequest(std::unique_ptr<Packet> request_packet) { bool success = false; if (ValidatePacket(request_packet->GetHeader())) { // Currently, all request types use the address/data_size wire format u32 address = 0; u32 data_size = 0; std::memcpy(&address, request_packet->GetPacketData().data(), sizeof(address)); std::memcpy(&data_size, request_packet->GetPacketData().data() + sizeof(address), sizeof(data_size)); switch (request_packet->GetPacketType()) { case PacketType::ReadMemory: if (data_size > 0 && data_size <= MAX_READ_SIZE) { HandleReadMemory(*request_packet, address, data_size); success = true; } break; case PacketType::WriteMemory: if (data_size > 0 && data_size <= MAX_PACKET_DATA_SIZE - (sizeof(u32) * 2)) { const u8* data = request_packet->GetPacketData().data() + (sizeof(u32) * 2); HandleWriteMemory(*request_packet, address, data, data_size); success = true; } break; default: break; } } if (!success) { // Send an empty reply, so as not to hang the client request_packet->SetPacketDataSize(0); request_packet->SendReply(); } }
int main(int argc, char *argv[]){ init_parse(); // Parses the commandline arguments parse_opts(argc, argv); // IE: ./server -cserver.cfg --name "My Server" // server config ReadServerCfg(cfg_file ? :"server.cfg"); // init sockets struct sockaddr_in newclient; unsigned char buffer[MAX_BUF]; int size; fd_set descriptor; //I don't know sock = create_socket(); bind_socket(&sock, INADDR_ANY, sv_hostport); // on termination atexit(&cleanup); signal(SIGABRT, &exit); signal(SIGTERM, &exit); signal(SIGINT, &exit); // initialize rest of stuff OnServerStart(); #ifndef _WIN32 // fps control const int inc = NS_PER_S / sv_fps; int frame = 0; int previous = 0; struct timespec current, next; clock_gettime(CLOCK_MONOTONIC, &next); #endif // timeval for select struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; //main loop while (1) { #ifndef _WIN32 frame++; next.tv_nsec += inc; while (next.tv_nsec > NS_PER_S) { //happens exactly once a second next.tv_nsec -= NS_PER_S; next.tv_sec++; fpsnow = frame - previous; previous = frame; OnSecond(); } #endif OnFrame(); FD_ZERO(&descriptor); FD_SET(sock, &descriptor); select(sock + 1, &descriptor, NULL, NULL, &timeout); if (FD_ISSET(sock, &descriptor)){ size = udp_receive(sock, buffer, MAX_BUF, &newclient); if (size < 3) { perror("Invalid packet! (size < 3)\n"); } else { stream *packet = init_stream(NULL); Stream.write(packet, buffer+2, size-2); // There's a chance that the guy left before all of the packet has been processed. while(1){ int id = IsPlayerKnown(newclient.sin_addr, newclient.sin_port); if (id){ if (ValidatePacket(buffer,id)){ PacketConfirmation(buffer,id); //If the numbering is even, send a confirmation player[id].lastpacket = mtime(); int pid = Stream.read_byte(packet); known_handler h = known_table[pid]; if (!h){ printf("Unhandled packet originating from %s (id:%d)\n", player[id].name, id); //stream *lolbuf = init_stream(NULL); //Stream.write(lolbuf, buffer, size); //unknown(lolbuf, pid); unknown(packet, pid); } else h(packet, id); } }else{ int pid = Stream.read_byte(packet); unknown_handler h = unknown_table[pid]; if (!h) unknown(packet, pid); else h(packet, &newclient); } if (EMPTY_STREAM(packet)){ free(packet); break; } } } } check_sendqueue(); #ifdef _WIN32 Sleep(1000 / sv_fps); //who cares about windows :D #else clock_gettime(CLOCK_MONOTONIC, ¤t); if (((current.tv_sec == next.tv_sec) && (current.tv_nsec < next.tv_nsec)) || (current.tv_sec < next.tv_sec)) { clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL); } else { next.tv_nsec = current.tv_nsec + (current.tv_sec - next.tv_sec) * NS_PER_S; } #endif } return EXIT_SUCCESS; }