/* ============ WriteGame This will be called whenever the game goes to a new level, and when the user explicitly saves the game. Game information include cross level data, like multi level triggers, help computer info, and all client states. A single player death will automatically restore from the last save position. ============ */ void WriteGame (char *filename, qboolean autosave) { FILE *f; int i; char str[16]; if (!autosave) SaveClientData (); f = fopen (filename, "wb"); if (!f) gi.error ("Couldn't open %s", filename); memset (str, 0, sizeof(str)); strcpy (str, __DATE__); fwrite (str, sizeof(str), 1, f); game.autosaved = autosave; fwrite (&game, sizeof(game), 1, f); game.autosaved = false; for (i=0 ; i<game.maxclients ; i++) WriteClient (f, &game.clients[i]); fclose (f); }
/* * Writes the game struct into * a file. This is called when * ever the games goes to e new * level or the user saves the * game. Saved informations are: * - cross level data * - client states * - help computer info */ void WriteGame(const char *filename, qboolean autosave) { FILE *f; int i; char str_ver[32]; char str_game[32]; char str_os[32]; char str_arch[32]; if (!autosave) { SaveClientData(); } f = fopen(filename, "wb"); if (!f) { gi.error("Couldn't open %s", filename); } /* Savegame identification */ memset(str_ver, 0, sizeof(str_ver)); memset(str_game, 0, sizeof(str_game)); memset(str_os, 0, sizeof(str_os)); memset(str_arch, 0, sizeof(str_arch)); strncpy(str_ver, SAVEGAMEVER, sizeof(str_ver)); strncpy(str_game, GAMEVERSION, sizeof(str_game)); strncpy(str_os, OS, sizeof(str_os)); strncpy(str_arch, ARCH, sizeof(str_arch)); fwrite(str_ver, sizeof(str_ver), 1, f); fwrite(str_game, sizeof(str_game), 1, f); fwrite(str_os, sizeof(str_os), 1, f); fwrite(str_arch, sizeof(str_arch), 1, f); game.autosaved = autosave; fwrite(&game, sizeof(game), 1, f); game.autosaved = false; for (i = 0; i < game.maxclients; i++) { WriteClient(f, &game.clients[i]); } fclose(f); }
// // This is a special callback function used by the DLL for certain extra // functionality. Look at the API help for details. // BOOL WINAPI ServerSupportFunction(HCONN hConn, DWORD dwHSERequest, LPVOID lpvBuffer, LPDWORD lpdwSize, LPDWORD lpdwDataType){ TIsapiContext *c = (TIsapiContext *)hConn; char *lpszRespBuf; char * temp = NULL; DWORD dwBytes; BOOL bRet = TRUE; switch(dwHSERequest) { case (HSE_REQ_SEND_RESPONSE_HEADER) : lpszRespBuf = (char *)xmalloc(*lpdwSize);//+ 80);//accomodate our header if (!lpszRespBuf) return FALSE; wsprintf(lpszRespBuf,"%s", //HTTP_VER, /* Default response is 200 Ok */ //lpvBuffer?lpvBuffer:"200 Ok", /* Create a string for the time. */ //temp=MakeDateStr(), //SERVER_VERSION, /* If this exists, it is a pointer to a data buffer to be sent. */ lpdwDataType?(char *)lpdwDataType:NULL); if (temp) xfree(temp); dwBytes = strlen(lpszRespBuf); bRet = WriteClient(0, lpszRespBuf, &dwBytes, 0); xfree(lpszRespBuf); break; // // A real server would do cleanup here case (HSE_REQ_DONE_WITH_SESSION): SetEvent(c->waitEvent); //ExitThread(0); break; // // This sends a redirect (temporary) to the client. // The header construction is similar to RESPONSE_HEADER above. // case (HSE_REQ_SEND_URL_REDIRECT_RESP): lpszRespBuf = (char *)xmalloc(*lpdwSize +80) ; if (!lpszRespBuf) return FALSE; wsprintf(lpszRespBuf,"%s %s %s\r\n", HTTP_VER, "302 Moved Temporarily", (lpdwSize > 0)?lpvBuffer:0); xfree(temp); dwBytes = strlen(lpszRespBuf); bRet = WriteClient(0, lpszRespBuf, &dwBytes, 0); xfree(lpszRespBuf); break; default: return FALSE; break; } return bRet; }
int main (int argc, char **argv) { int listenPort = 5002; int listenFd; struct a_client *theClients=0; int nbClient=0; struct pollfd *fds=0; int maxClientFd=-1; long dataLen = 6 *1024 * 1024; long stopAfter = 0; void *buf = 0; int buflen = 0; struct timeval startTime; struct timeval endTime; initBuffer (&buf, &buflen); listenFd = socket (AF_INET, SOCK_STREAM, 0); if (listenFd < 0) { fprintf (stderr, "Unable to open socket ? errno %d\n",errno); exit (1); } if (argc >= 2) { listenPort = atoi (argv[1]); } if (argc >= 3) { dataLen= atoi (argv[2]); } if (argc >= 4) { stopAfter= atoi (argv[3]); } struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons (listenPort); addr.sin_addr.s_addr = INADDR_ANY; int status; status = bind (listenFd, (const struct sockaddr *) &addr, sizeof(addr)); if (status) { fprintf (stderr, "Unable to open bind ? errno %d\n",errno); exit (2); } status = listen (listenFd, 256); if (status) { fprintf (stderr, "Unable to open listen ? errno %d \n",errno); exit (3); } while (1) { fds = realloc (fds, sizeof (struct pollfd) * nbClient + 1 ); fds[0].fd = listenFd; fds[0].events = POLLIN; fds[0].revents = 0; int j = 1; int c =0; for (c=0; c <= maxClientFd ; c++) { if (theClients[c].sockfd >= 0) { if (theClients[c].writeLen < dataLen) { fds[j].fd = theClients[c].sockfd; fds[j].events = POLLOUT; fds[j].revents = 0; j++; } else { fds[j].fd = theClients[c].sockfd; fds[j].events = POLLIN; fds[j].revents = 0; j++; } } } printf ("%d: --> poll j=%d\n",time(NULL), j ); int ret = poll (fds, j, 29000 * 1000); printf ("%d: poll --> %d\n", time(NULL), ret); if (ret <= 0) { exit (0); } if (ret > 0) { int i=0; for (i=0; i < j; i++) { if ( fds[i].revents ) { if (i == 0) { // a new cnxion if ( fds[i].revents & POLLIN ) { int newFd = accept (listenFd, 0, 0); if (newFd >= 0) { if ( 0 == nbClient) { gettimeofday (&startTime, 0); } NewClient (newFd, &theClients, &nbClient, &maxClientFd); } } if ( fds[i].revents & POLLERR ) { exit (4); } } else { // a client printf ("Client %d revents %d \n", i, fds[i].revents ); gettimeofday (&endTime, 0); if ( fds[i].revents & POLLOUT ) { WriteClient (theClients, fds[i].fd, &nbClient, dataLen, buf, buflen, duration (&startTime, &endTime)); } if ( ( fds[i].revents & POLLHUP ) || ( fds[i].revents & POLLIN ) || ( fds[i].revents & POLLERR ) ) { gettimeofday (&endTime, 0); CloseClient (theClients, fds[i].fd, &nbClient, duration (&startTime, &endTime), dataLen); } if ( stopAfter && ( totalClients >= stopAfter )) { exit (0); } } } } } } }