static bool8 NPClientReplyPhaseSpanTest (void) { uint8 mes[21]; int l = npclient.numplayers * 4 + 1; NPNotification("Client: Replying sending / receiving pad states test...", -1); for (int n = 0; n < 5; n++) { if (socket_read(npclient.socket, mes, l) != l) return (false); if (socket_write(npclient.socket, mes, 5) != 5) return (false); } NPNotification("Client: Replied sending / receiving pad states test.", -1); NPNotification("Client: Receiving phase span value from server...", -1); if (socket_read(npclient.socket, mes, 4) != 4) return (false); npclient.phasespan = READ_LONG(mes + 0); NPNotification(" phase span: %d (frames)", npclient.phasespan); NPNotification("Client: Received phase span value from server.", -1); return (true); }
bool8 NPServerStartServer (int port) { #ifndef SELF_TEST struct sockaddr_in address; #else struct sockaddr_un address; #endif int v = 1; NPNotification("Server: Starting server...", -1); #ifndef SELF_TEST if ((npserver.socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) #else if ((npserver.socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) #endif { NPError("Server: Failed to create listening socket.", 1001); return (false); } if ((setsockopt(npserver.socket, SOL_SOCKET, SO_REUSEADDR, (char *) &v, sizeof(v))) < 0) { NPError("Server: Failed to set socket option.", 1002); return (false); } memset(&address, 0, sizeof(address)); #ifndef SELF_TEST address.sin_family = AF_INET; address.sin_addr.s_addr = htonl(INADDR_ANY); address.sin_port = htons(port); #else address.sun_family = AF_UNIX; strcpy(address.sun_path, SOCK_NAME); #endif #ifndef SELF_TEST if ((bind(npserver.socket, (struct sockaddr *) &address, sizeof(address))) < 0) #else unlink(SOCK_NAME); if ((bind(npserver.socket, (struct sockaddr *) &address, sizeof(address))) < 0) #endif { NPError("Server: Failed to bind socket to port number.", 1003); return (false); } if ((listen(npserver.socket, NP_MAX_CLIENTS)) < 0) { NPError("Server: Failed to get new socket to listen.", 1004); return (false); } npplayer[0].socket = npserver.socket; NPNotification("Server: Started server.", -1); return (true); }
static void NPServerWaitStartReply (void) { struct timeval timeout; fd_set readfds; int maxfd; bool8 allok, flag[NP_MAX_PLAYERS]; NPNotification("Server: Waiting clients reply to start...", -1); allok = false; for (int c = 1; c <= NP_MAX_CLIENTS; c++) flag[c] = false; while (!allok) { FD_ZERO(&readfds); maxfd = 0; for (int c = 1; c <= NP_MAX_CLIENTS; c++) { if (npplayer[c].ready) { FD_SET(npplayer[c].socket, &readfds); if (maxfd < npplayer[c].socket) maxfd = npplayer[c].socket; } } timeout.tv_sec = 0; timeout.tv_usec = 50000; if (select(maxfd + 1, &readfds, NULL, NULL, &timeout) > 0) { for (int c = 1; c <= NP_MAX_CLIENTS; c++) { if (npplayer[c].ready) { if (FD_ISSET(npplayer[c].socket, &readfds)) { if (NPServerGetMesFromClient(c) == kNPClientStartWait) flag[c] = true; else NPServerShutdownClient(c); } } } } allok = true; for (int c = 1; c <= NP_MAX_CLIENTS; c++) if (npplayer[c].ready && !flag[c]) allok = false; } NPNotification("Server: All clients are ready to start netplay.", -1); }
static bool8 NPClientGetPlayerListFromServer (void) { if (!npclient.online) return (false); NPNotification("Client: Receiving player list from server...", -1); if (NPClientGetMesFromServer() != kNPServerPlayerWillSend) { NPError("Client: Failed to receive messsage from server.", 5701); return (false); } if (NPClientSendMesToServer(kNPClientPlayerWaiting) == false) { NPError("Client: Failed to send messsage to server.", 5702); return (false); } for (int i = 0; i < NP_MAX_PLAYERS; i++) { uint8 mes[10]; uint32 l; if (socket_read(npclient.socket, mes, 10) != 10) { NPError("Client: Failed to receive messsage from server.", 5703); return (false); } npcinfo[i].ready = READ_BYTE(mes + 1); npcinfo[i].player = READ_LONG(mes + 2); l = READ_LONG(mes + 6); if (l && (socket_read(npclient.socket, (uint8 *) npcinfo[i].name, l) != (int) l)) { NPError("Client: Failed to receive messsage from server.", 5704); return (false); } npcinfo[i].name[l] = 0; } npclient.numplayers = 0; for (int i = 0; i < NP_MAX_PLAYERS; i++) if (npcinfo[i].ready) npclient.numplayers++; NPNotification("Client: Received player list from server.", -1); NPNotification("Client: Number of players: %d", npclient.numplayers); return (true); }
static void * NPClientNetPlayThread (void *) { uint8 mes[NP_MAX_PLAYERS * 64 * 4 + 1]; uint8 count = 0; int l; NPNotification("Client: Entered pad thread.", -1); while (npclient.padloop) { sem_wait(csempad); l = npclient.numplayers * npclient.phasespan * 4 + 1; if (socket_read(npclient.socket, mes, l) != l) { npclient.exitsgn = true; sem_post(csememu); pthread_exit(NULL); } if ((mes[0] & 0xF) != count) NPNotification("Client: Warning: Failed to synchronize server.", -1); npclient.header = mes[0] & 0xF0; for (int i = 0; i < npclient.numplayers; i++) for (uint32 j = 0; j < npclient.phasespan; j++) npcrecvpad[i][j] = READ_LONG(mes + (i * npclient.phasespan + j) * 4 + 1); WRITE_BYTE(mes + 0, count); for (uint32 j = 0; j < npclient.phasespan; j++) WRITE_LONG(mes + j * 4 + 1, npcsendpad[j]); l = npclient.phasespan * 4 + 1; if (socket_write(npclient.socket, mes, l) != l) { npclient.exitsgn = true; sem_post(csememu); pthread_exit(NULL); } count = (count + 1) & 0xF; sem_post(csememu); } npclient.exitsgn = true; NPNotification("Client: Exited pad thread.", -1); return (NULL); }
static void * NPServerNetPlayThread (void *p) { uint8 mes[NP_MAX_PLAYERS * 64 * 4 + 1]; uint8 count = 0; int c = *((int *) p), l; NPNotification("Server: Entered pad thread for client %d.", c); while (npplayer[c].padloop) { sem_wait(sempad[c]); WRITE_BYTE(mes + 0, count | npserver.header); for (int i = 0; i < npserver.numplayers; i++) for (uint32 j = 0; j < npserver.phasespan; j++) WRITE_LONG(mes + (i * npserver.phasespan + j) * 4 + 1, npsendpad[i][j]); l = npserver.numplayers * npserver.phasespan * 4 + 1; if (socket_write(npplayer[c].socket, mes, l) != l) { NPServerShutdownClient(c); npplayer[c].exitsgn = true; sem_post(sememu[c]); pthread_exit(NULL); } l = npserver.phasespan * 4 + 1; if (socket_read(npplayer[c].socket, mes, l) != l) { NPServerShutdownClient(c); npplayer[c].exitsgn = true; sem_post(sememu[c]); pthread_exit(NULL); } for (uint32 j = 0; j < npserver.phasespan; j++) nprecvpad[npplayer[c].player][j] = READ_LONG(mes + j * 4 + 1); if ((mes[0] & 0xF) != count) NPNotification("Server: Warning: Failed to synchronize client %d.", c); count = (count + 1) & 0xF; sem_post(sememu[c]); } npplayer[c].exitsgn = true; NPNotification("Server: Exited pad thread for client %d.", c); return (NULL); }
static bool8 NPServerSendROMInfoToClient (int c) { if (!npplayer[c].online) return (false); NPNotification("Server: Sending ROM information to client %d...", c); if (NPServerSendMesToClient(c, kNPServerROMInfoWillSend) == false) { NPError("Server: Failed to send messsage to client.", 1301); return (false); } if (NPServerGetMesFromClient(c) != kNPClientROMInfoWaiting) { NPError("Server: Failed to receive messsage from client.", 1302); return (false); } uint8 mes[16]; uint32 l; char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; _splitpath(Memory.ROMFilename, drive, dir, fname, ext); l = strlen(fname); WRITE_LONG(mes + 0, Memory.ROMCRC32); WRITE_LONG(mes + 4, deviceSetting); WRITE_BYTE(mes + 8, 0); // reserved WRITE_BYTE(mes + 9, 0); // reserved WRITE_BYTE(mes + 10, 0); // reserved WRITE_BYTE(mes + 11, 0); // reserved WRITE_LONG(mes + 12, l); if (socket_write(npplayer[c].socket, mes, 16) != 16) { NPError("Server: Failed to send ROM information to client.", 1303); return (false); } if (socket_write(npplayer[c].socket, (uint8 *) fname, l) != (int) l) { NPError("Server: Failed to send ROM name to client.", 1304); return (false); } NPNotification("Server: Sent ROM information to client %d.", c); return (true); // next: kNPClientROMOpened }
static bool8 NPClientGetSRAMFromServer (void) { if (!npclient.online) return (false); NPNotification("Client: Receiving SRAM from server...", -1); if (NPClientGetMesFromServer() != kNPServerSRAMWillSend) { NPError("Client: Failed to receive messsage from server.", 5501); return (false); } if (NPClientSendMesToServer(kNPClientSRAMWaiting) == false) { NPError("Client: Failed to send messsage to server.", 5502); return (false); } uint8 mes[4]; uint32 sramsize; if (socket_read(npclient.socket, mes, 4) != 4) { NPError("Client: Failed to receive SRAM size from server.", 5503); return (false); } sramsize = READ_LONG(mes + 0); if (sramsize != (uint32) (Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0)) { NPError("Client: SRAM size mismatch.", 5504); return (false); } if (sramsize && (socket_read(npclient.socket, Memory.SRAM, sramsize) != (int) sramsize)) { NPError("Server: Failed to receive SRAM from server.", 5505); return (false); } if (NPClientSendMesToServer(kNPClientSRAMLoaded) == false) { NPError("Client: Failed to send messsage to server.", 5506); return (false); } NPNotification("Client: Received SRAM from server.", -1); return (true); }
static void * NPServerProcessThread (void *) { NPNotification("Server: Entered process thread.", -1); NPServerAllotPlayers(); NPServerSendPlayerList(); NPServerSetPhaseSpan(); NPServerWaitStartReply(); npserver.dialogprocess = kNPSDialogDone; NPNotification("Server: Exited process thread.", -1); return (NULL); }
static bool8 NPClientConnectToServer (int port) { #ifndef SELF_TEST struct sockaddr_in address; #else struct sockaddr_un address; #endif NPNotification("Client: Connecting to server...", -1); memset(&address, 0, sizeof(address)); #ifndef SELF_TEST address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(npclient.serverIP); address.sin_port = htons(port); #else address.sun_family = AF_UNIX; strcpy(address.sun_path, SOCK_NAME); #endif #ifndef SELF_TEST if (address.sin_addr.s_addr == INADDR_NONE) { NPError("Client: Server IP is invalid.", 5001); return (false); } #endif #ifndef SELF_TEST if ((npclient.socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) #else if ((npclient.socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) #endif { NPError("Client: Failed to create socket.", 5002); return (false); } if (connect(npclient.socket, (struct sockaddr *) &address, sizeof(address)) < 0) { NPError("Client: Failed to connect to server.", 5003); return (false); } npclient.online = true; NPNotification("Client: Connected to server.", -1); return (true); }
static bool8 NPClientGetROMInfoFromServer(void) { if (!npclient.online) return (false); NPNotification("Client: Receiving ROM information from server...", -1); if (NPClientGetMesFromServer() != kNPServerROMInfoWillSend) { NPError("Client: Failed to receive messsage from server.", 5201); return (false); } if (NPClientSendMesToServer(kNPClientROMInfoWaiting) == false) { NPError("Client: Failed to send messsage to server.", 5202); return (false); } uint8 mes[16]; uint32 l; if (socket_read(npclient.socket, mes, 16) != 16) { NPError("Client: Failed to receive ROM information from server.", 5203); return (false); } nprominfo.crc32 = READ_LONG(mes + 0); nprominfo.input = READ_LONG(mes + 4); //reserved1 = READ_BYTE(mes + 8); //reserved2 = READ_BYTE(mes + 9); //reserved3 = READ_BYTE(mes + 10); //reserved4 = READ_BYTE(mes + 11); l = READ_LONG(mes + 12); if (socket_read(npclient.socket, (uint8 *) nprominfo.fname, l) != (int) l) { NPError("Client: Failed to receive ROM name from server.", 5204); return (false); } nprominfo.fname[l] = 0; nprominfo.length = l; NPNotification("Client: Received ROM information from server.", -1); return (true); }
void NPClientDetachNetPlayThread (void) { NPNotification("Client: Detaching pad thread...", -1); npclient.padloop = true; npclient.exitsgn = false; csememu = sem_open(n_csememu, O_CREAT, 0600, 0); csempad = sem_open(n_csempad, O_CREAT, 0600, 0); pthread_create(&gamepadthread, NULL, NPClientNetPlayThread, NULL); pthread_detach(gamepadthread); NPNotification("Client: Detached pad thread.", -1); }
static int NPServerAcceptClient (int port) { #ifndef SELF_TEST struct sockaddr_in address; #else struct sockaddr_un address; #endif int newfd; int c; socklen_t l; NPNotification("Server: Accepting new client connection...", -1); for (c = 1; c <= NP_MAX_CLIENTS; c++) if (!npplayer[c].online) break; if (c > NP_MAX_CLIENTS) { NPError("Server: Maximum number of clients have already connected.", 1101); return (-1); } l = sizeof(address); memset(&address, 0, l); if ((newfd = accept(port, (struct sockaddr *) &address, &l)) < 0) { NPError("Server: Can't accept client connection.", 1102); return (-1); } npplayer[c].online = true; npplayer[c].socket = newfd; #ifndef SELF_TEST if (address.sin_family == AF_INET) strcpy(npplayer[c].ip, inet_ntoa(address.sin_addr)); else strcpy(npplayer[c].ip, "unknown"); #else strcpy(npplayer[c].ip, "Unix"); #endif NPNotification("Server: new client %d has connected.", c); return (c); }
static bool8 NPClientROMReadyToServer (void) { if (!npclient.online) return (false); NPNotification("Client: Sending ROM ready sign to server...", -1); if (NPClientSendMesToServer(kNPClientROMOpened) == false) { NPError("Client: Failed to send messsage to server.", 5401); return (false); } NPNotification("Client: Sent ROM ready sign to server.", -1); return (true); }
void NPClientDisconnect (void) { if (npclient.socket != -1) { NPNotification("Client: Disconnecting from server...", -1); close(npclient.socket); npclient.socket = -1; NPNotification("Client: Disconnected from server.", -1); } npclient.online = false; npclient.name[0] = 0; npclient.serverIP[0] = 0; }
static bool8 NPServerSendPlayerListToClient (int c) { if (!npplayer[c].online || !npplayer[c].ready) return (false); NPNotification("Server: Sending player list to client %d...", c); if (NPServerSendMesToClient(c, kNPServerPlayerWillSend) == false) { NPError("Server: Failed to send messsage to client.", 1601); return (false); } if (NPServerGetMesFromClient(c) != kNPClientPlayerWaiting) { NPError("Server: Failed to receive messsage from client.", 1602); return (false); } for (int i = 0; i < NP_MAX_PLAYERS; i++) { uint8 mes[10]; uint32 l; l = npplayer[i].ready ? strlen(npplayer[i].name) : 0; WRITE_BYTE(mes + 0, (i == c)); WRITE_BYTE(mes + 1, npplayer[i].ready); WRITE_LONG(mes + 2, npplayer[i].player); WRITE_LONG(mes + 6, l); if (socket_write(npplayer[c].socket, mes, 10) != 10) { NPError("Server: Failed to send name size to client.", 1603); return (false); } if (l && (socket_write(npplayer[c].socket, (uint8 *) npplayer[i].name, l) != (int) l)) { NPError("Server: Failed to send name to client.", 1604); return (false); } } NPNotification("Server: Sent player list to client %d.", c); return (true); }
static bool8 NPClientSendNameToServer (void) { if (!npclient.online) return (false); NPNotification("Client: Sending player name to server...", -1); if (NPClientGetMesFromServer() != kNPServerNameRequest) { NPError("Client: Failed to receive messsage from server.", 5101); return (false); } uint8 mes[4]; uint32 l; l = strlen(npclient.name); WRITE_LONG(mes + 0, l); if (socket_write(npclient.socket, mes, 4) != 4) { NPError("Client: Failed to send name size to server.", 5102); return (false); } if (socket_write(npclient.socket, (uint8 *) npclient.name, l) != (int) l) { NPError("Client: Failed to send name to server.", 5103); return (false); } if (NPClientGetMesFromServer() != kNPServerNameReceived) { NPError("Client: Failed to receive messsage from server.", 5104); return (false); } if (NPClientSendMesToServer(kNPClientNameSent) == false) { NPError("Client: Failed to send messsage to server.", 5105); return (false); } NPNotification("Client: Sent player name to server.", -1); return (true); }
static void * NPClientConnectThread (void *) { NPNotification("Client: Entered connection thread.", -1); if ((NPClientConnectToServer(NP_PORT) == false) || (NPClientSendNameToServer() == false) || (NPClientGetROMInfoFromServer() == false)) { NPClientDisconnect(); npclient.dialogprocess = kNPCDialogConnectFailed; return (NULL); } npclient.dialogprocess = kNPCDialogOpenBegin; NPNotification("Client: Exited connection thread.", -1); return (NULL); }
void NPClientStopNetPlayThread (void) { NPNotification("Client: Stopping pad thread...", -1); npclient.padloop = false; sem_post(csempad); sem_post(csememu); while (!npclient.exitsgn) sleep(0); sem_unlink(n_csememu); sem_unlink(n_csempad); sem_close(csememu); sem_close(csempad); NPNotification("Client: Stopped pad thread.", -1); }
static void * NPClientPrepareThread (void *) { NPNotification("Client: Entered preparing thread.", -1); if ((NPClientROMReadyToServer() == false) || (NPClientGetSRAMFromServer() == false) || (NPClientGetPlayerListFromServer() == false) || (NPClientReplyPhaseSpanTest() == false)) { NPClientDisconnect(); npclient.dialogprocess = kNPCDialogPrepareFailed; return (NULL); } npclient.dialogprocess = kNPCDialogShowList; NPNotification("Client: Exited preparing thread.", -1); return (NULL); }
static bool8 NPServerSendSRAMToClient (int c) { if (!npplayer[c].online) return (false); NPNotification("Server: Sending SRAM to client %d...", c); if (NPServerSendMesToClient(c, kNPServerSRAMWillSend) == false) { NPError("Server: Failed to send messsage to client.", 1401); return (false); } if (NPServerGetMesFromClient(c) != kNPClientSRAMWaiting) { NPError("Server: Failed to receive messsage from client.", 1402); return (false); } uint8 mes[4]; uint32 sramsize; sramsize = Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0; WRITE_LONG(mes + 0, sramsize); if (socket_write(npplayer[c].socket, mes, 4) != 4) { NPError("Server: Failed to send SRAM size to client.", 1403); return (false); } if (sramsize && (socket_write(npplayer[c].socket, Memory.SRAM, sramsize) != (int) sramsize)) { NPError("Server: Failed to send SRAM to client.", 1404); return (false); } NPNotification("Server: Sent SRAM to client %d.", c); return (true); // next: kNPClientSRAMLoaded }
static bool8 NPServerGetNameFromClient (int c) { if (!npplayer[c].online) return (false); NPNotification("Server: Receiving player name from client %d...", c); if (NPServerSendMesToClient(c, kNPServerNameRequest) == false) { NPError("Server: Failed to send messsage to client.", 1201); return (false); } uint8 mes[4]; uint32 l; if (socket_read(npplayer[c].socket, mes, 4) != 4) { NPError("Server: Failed to receive name size from client.", 1202); return (false); } l = READ_LONG(mes + 0); if (socket_read(npplayer[c].socket, (uint8 *) npplayer[c].name, l) != (int) l) { NPError("Server: Failed to receive name from client.", 1203); return (false); } npplayer[c].name[l] = 0; if (NPServerSendMesToClient(c, kNPServerNameReceived) == false) { NPError("Server: Failed to send messsage to client.", 1204); return (false); } NPNotification("Server: Received player name from client %d.", c); return (true); // next: kNPClientNameSent }
void NPServerDetachNetPlayThread (void) { NPNotification("Server: Detaching pad threads...", -1); for (int c = 1; c <= NP_MAX_CLIENTS; c++) { if (npplayer[c].ready) { npplayer[c].padloop = true; npplayer[c].exitsgn = false; sememu[c] = sem_open(n_sememu[c], O_CREAT, 0600, 0); sempad[c] = sem_open(n_sempad[c], O_CREAT, 0600, 0); pthread_create(&padthread[c], NULL, NPServerNetPlayThread, &(npplayer[c].client)); pthread_detach(padthread[c]); } } NPNotification("Server: Detached pad threads.", -1); }
static void NPServerShutdownClient (int c) { if (npplayer[c].online) { NPNotification("Server: Closing client %d connection...", c); if (npplayer[c].socket != -1) { close(npplayer[c].socket); npplayer[c].socket = -1; } npplayer[c].online = false; npplayer[c].ready = false; npplayer[c].client = 0; npplayer[c].player = 0; npplayer[c].ip[0] = 0; npplayer[c].name[0] = 0; NPNotification("Server: Client %d has disconnected.", c); } }
void NPServerStopServer (void) { NPNotification("Server: Stopping server...", -1); for (int c = 1; c <= NP_MAX_CLIENTS; c++) NPServerShutdownClient(c); npplayer[0].online = false; npplayer[0].ready = false; npplayer[0].socket = -1; npplayer[0].client = 0; npplayer[0].player = 0; npplayer[0].ip[0] = 0; npplayer[0].name[0] = 0; if (npserver.socket != -1) { close(npserver.socket); npserver.socket = -1; } NPNotification("Server: Stopped server.", -1); }
void NPServerStopNetPlayThread (void) { NPNotification("Server: Stopping pad threads...", -1); for (int c = 1; c <= NP_MAX_CLIENTS; c++) { if (npplayer[c].ready) { npplayer[c].padloop = false; sem_post(sempad[c]); while (!npplayer[c].exitsgn) sleep(0); sem_unlink(n_sememu[c]); sem_unlink(n_sempad[c]); sem_close(sememu[c]); sem_close(sempad[c]); } } NPNotification("Server: Stopped pad threads.", -1); }
bool8 NPClientNetPlayWaitStart (void) { NPNotification("Client: Waiting start flag...", -1); if (NPClientSendMesToServer(kNPClientStartWait) == false) { NPError("Client: Failed to send messsage to server.", 5801); return (false); } if (NPClientGetMesFromServer() != kNPServerStart) { NPError("Client: Failed to send messsage to server.", 5802); return (false); } npclient.phasecount = 0; npclient.header = 0; sem_post(csempad); NPNotification("Client: Netplay started.", -1); return (true); }
void NPServerStartClients (void) { NPNotification("Server: Sending start flag to clients...", -1); for (int c = 1; c <= NP_MAX_CLIENTS; c++) { if (npplayer[c].ready) { if (NPServerSendMesToClient(c, kNPServerStart) == false) NPServerShutdownClient(c); } } NPNotification("Server: Sent start flag to clients.", -1); npserver.phasecount = 0; npserver.header = 0; for (int c = 1; c <= NP_MAX_CLIENTS; c++) if (npplayer[c].ready) sem_post(sempad[c]); NPNotification("Server: Netplay started.", -1); }
static void NPServerAllotPlayers (void) { int n = 1; for (int c = 1; c <= NP_MAX_CLIENTS; c++) { if (npplayer[c].ready) { npplayer[c].client = c; npplayer[c].player = n++; } else NPServerShutdownClient(c); } npplayer[0].client = 0; npplayer[0].player = 0; npserver.numplayers = n; NPNotification("Server: Number of players: %d", n); }
static void * NPServerListenLoop (void *) { struct timeval timeout; fd_set readfds; int maxfd; NPNotification("Server: Entered listening loop.", -1); while (npserver.listenloop) { FD_ZERO(&readfds); maxfd = 0; if (npserver.socket != -1) { FD_SET(npserver.socket, &readfds); maxfd = npserver.socket; } for (int c = 1; c <= NP_MAX_CLIENTS; c++) { if (npplayer[c].online) { FD_SET(npplayer[c].socket, &readfds); if (maxfd < npplayer[c].socket) maxfd = npplayer[c].socket; } } timeout.tv_sec = 0; timeout.tv_usec = 50000; if (select(maxfd + 1, &readfds, NULL, NULL, &timeout) > 0) { for (int c = 1; c <= NP_MAX_CLIENTS; c++) { if (npplayer[c].online) { if (FD_ISSET(npplayer[c].socket, &readfds)) { switch (NPServerGetMesFromClient(c)) { case kNPClientNameSent: if (!NPServerSendROMInfoToClient(c)) NPServerShutdownClient(c); break; case kNPClientROMOpened: if (!NPServerSendSRAMToClient(c)) NPServerShutdownClient(c); break; case kNPClientSRAMLoaded: npplayer[c].ready = true; break; default: NPServerShutdownClient(c); break; } } } } if (FD_ISSET(npserver.socket, &readfds)) { int client; if ((client = NPServerAcceptClient(npserver.socket)) != -1) { if (!NPServerGetNameFromClient(client)) NPServerShutdownClient(client); } } } } NPNotification("Server: Exited listening loop.", -1); return (NULL); }