/*********************************************** CloseConnection Call this function to close any used and/or open port. Params none Return (bitwise) UTE_SUCCESS - success UTE_ERROR - failed 1 - client socket shutdown failed 2 - client socket close failed 3 - server socket shutdown failed 4 - server socket close failed ************************************************/ int CUT_WSThread::CloseConnection(){ int rt = UTE_SUCCESS; //if the socket is not open then just return if(m_clientSocket != INVALID_SOCKET){ if(m_nSockType == SOCK_STREAM){ if(SocketShutDown(m_clientSocket, 2) == SOCKET_ERROR){ rt = UTE_ERROR; //1 } } if(SocketClose(m_clientSocket) == SOCKET_ERROR){ rt = UTE_ERROR; //2 } } //clear the socket variables m_clientSocket = INVALID_SOCKET; strcpy(m_szAddress, ""); return OnError(rt); }
/* Primary "game" logic. Basically: 1. Set up a "server" listen socket 2. Initialize the client structures 3. Enter a main loop a. Let the gcd code think / do callbacks b. Check for a new connection on the server socket and create a new client c. Check for data on the client sockets d. Check for disconnects on the client sockets 4. Disconnect remaining players and exit */ int test_main(int argc, char **argv) { client_t clients[MAXCLIENTS]; SOCKET ssock; struct sockaddr_in saddr; int saddrlen = sizeof(saddr); fd_set set; struct timeval timeout = {0,0}; int error; int i,len; int quit = 0; char buf[512]; unsigned short port; GSIACResult result; // check that the game's backend is available GSIStartAvailableCheck(MY_GAMENAME); while((result = GSIAvailableCheckThink()) == GSIACWaiting) msleep(5); if(result != GSIACAvailable) { printf("The backend is not available\n"); return 1; } /* Initialize the gcd system with the gameid you have been assigned */ if(gcd_init(MY_GAMEID) != 0) { printf("Error initializing\n"); return 1; } SocketStartUp(); ssock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; i = 0; // initialize here just to prevent compiler error for(port = PORT ; port < (PORT + 100) ; port++) { saddr.sin_port = htons(port); i = bind(ssock, (struct sockaddr *)&saddr, sizeof(saddr)); if(gsiSocketIsNotError(i)) break; } if (gsiSocketIsError(i)) { printf("Unable to bind to any of the ports %d through %d (%d)\n",PORT, port - 1, GOAGetLastError(ssock)); return 1; } listen(ssock, SOMAXCONN); for (i = 0 ; i < MAXCLIENTS ; i++) clients[i].sock = INVALID_SOCKET; printf("Running on port %d... press any key to quit\n", port); while (!quit) { //main loop msleep(10); gcd_think(); #ifdef _WIN32 quit = _kbhit(); #else //on other systems, you gotta kill it hard #endif FD_ZERO ( &set ); FD_SET ( ssock, &set ); for (i = 0 ; i < MAXCLIENTS ; i++) if (clients[i].sock != INVALID_SOCKET) FD_SET(clients[i].sock , &set); error = select(FD_SETSIZE, &set, NULL, NULL, &timeout); if (/*gsiSocketIsError(ret) ||*/ 0 == error) continue; //new connection if (FD_ISSET(ssock, &set)) { for (i = 0 ; i < MAXCLIENTS ; i++) if (clients[i].sock == INVALID_SOCKET) { clients[i].sock = accept(ssock, (struct sockaddr *)&(clients[i].saddr), &saddrlen); listen(ssock,SOMAXCONN); strcpy(clients[i].challenge,randomchallenge(8)); len = sprintf(buf,"c:%s",clients[i].challenge); send(clients[i].sock ,buf, len,0); //send a challenge clients[i].auth = 0; printf("Client %d connected\n",i); break; } } //client data for (i = 0 ; i < MAXCLIENTS ; i++) if (clients[i].sock != INVALID_SOCKET && FD_ISSET(clients[i].sock, &set)) { len = recv(clients[i].sock,buf, 512, 0); if (len <= 0) //the client disconnected { printf("Client %d disconnected\n",i); closesocket(clients[i].sock); clients[i].sock = INVALID_SOCKET; if (clients[i].auth) //if they were authorized gcd_disconnect_user(MY_GAMEID, i); continue; } buf[len] = 0; if (buf[0] == 'r' && buf[1] == ':' && clients[i].auth == 0) //challenge response { printf("Client %d said %s\n",i,buf); clients[i].auth = 1; gcd_authenticate_user(MY_GAMEID, i,clients[i].saddr.sin_addr.s_addr, clients[i].challenge, buf+2, ClientAuthorize, ClientRefreshAuthorize, clients); } else if (buf[0] == 'p' && buf[1] == ':' && clients[i].auth == 1) // ison proof response { //gcd_send_reauth_response needs to know the sesskey (so keymaster can find the task) // and fromaddr (so gcdkey knows which keymaster to respond to) if (len > 11) { char hintstr[9]; int hint = 0; memcpy(hintstr, buf+2, 8); // first 8 characters are the hint hintstr[8] = '\0'; hint = atoi(hintstr); printf("Client %d prooved %d, %s\n",i,hint,buf+10); gcd_process_reauth(MY_GAMEID, i, hint, buf+10); } } } } gcd_disconnect_all(MY_GAMEID); gcd_shutdown(); SocketShutDown(); printf("All done!\n"); return 0; GSI_UNUSED(argv); GSI_UNUSED(argc); }
int test_main(int argc, char **argv) { char data[256]; int len; char cdkey[64]; char server[64]; char port[64]; char response[RESPONSE_SIZE]; SOCKET s; struct sockaddr_in saddr; while(1) { //get the server IP and a CD Key printf("Server to connect to [%s]: ",DEFAULT_SERVER); readstring(server); if (server[0]==0 || server[0]=='\n') strcpy(server,DEFAULT_SERVER); printf("Port to connect to [%d]: ",DEFAULT_PORT); readstring(port); if (port[0]=='\0' || port[0]=='\n') sprintf(port,"%d", DEFAULT_PORT); printf("Enter your CD Key [%s]: ", DEFAULT_KEY); readstring(cdkey); if (cdkey[0]==0 || cdkey[0]=='\n') strcpy(cdkey,DEFAULT_KEY); /* normally we would verify the CD Key (mathematically) at this point, if (!ValidateKey(cdkey)) return; */ /* create a TCP socket to connect to the server, obviously you would connect with whatever protocol your game uses (TCP/UDP/DPlay/etc) */ SocketStartUp(); s = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = inet_addr(server); saddr.sin_port = htons((unsigned short)atoi(port)); if (gsiSocketIsError(connect(s,(struct sockaddr *)&saddr,sizeof(saddr)))) { printf("Error connecting to server\n"); getchar(); continue; } /* Once we are connected, there is a "handshake" where the server sends a "challenge" in the form "c:challenge", and we send a response in the for "r:response". How you do this is again, completely up to you */ len = recv(s,data,BUFSIZE-1,0); if (len <= 0) { printf("Error connecting to server\n"); getchar(); continue; } data[len] = 0; // compute the response based on the challenge (which starts at data[2]) gcd_compute_response(cdkey, data+2, response, CDResponseMethod_NEWAUTH); // send the response back to the server printf("Got: %s\nSending: %s\n",data, response); sprintf(data,"r:%s",response); send(s,data,strlen(data),0); // enter our main loop and wait for data while (1) { len = recv(s,data,BUFSIZE-1,0); if (len <= 0) { printf("Server Disconnected\n"); getchar(); //goto start; break; } data[len] = 0; // Keep a watch for reauthentication requests // In this case, the sample server sends "r:<challenge>" // and the client sample responds with "p:<response>" // Your game should use it's own message types and headers. if (data[0] == 'r' && data[1] == ':') { char hint[9]; memcpy(hint, data+2, 8); // 8 characters are a hint hint[8] = '\0'; printf("Got reauth: %s, %s\n",hint, data+10); gcd_compute_response(cdkey, data+10, response, CDResponseMethod_REAUTH); sprintf(data, "p:%s%s", hint, response); send(s,data,strlen(data),0); printf("Sending: %s\n", response); } else printf("Got: %s\n", data); } } // goto start; SocketShutDown(); return 0; GSI_UNUSED(argv); GSI_UNUSED(argc); }