ref: 222de35cb34603c9d81375978d5e91821126b2c3
dir: /Engine/src/mmulti.cpp/
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include "enet.h" //#include "buildqueue.h" #include <vector> //#define _DEBUG_NETWORKING_ extern "C" { #include "platform.h" #include "pragmas.h" #include "signal.h" #include "mmulti_stable.h" #define MAXPLAYERS 16 #define BAKSIZ 16384 #define SIMULATEERRORS 0 #define SHOWSENDPACKETS 0 #define SHOWGETPACKETS 0 #define PRINTERRORS 0 #define MAX_PLAYERS 16 #define BUILD_DEFAULT_UDP_PORT 1635 /* eh...why not? */ #define CLIENT_POLL_DELAY 5000 /* ms between pings at peer-to-peer startup. */ #define HEADER_PEER_GREETING 245 #define HEADER_PEER_READY 244 static int udpsocket = -1; static short udpport = BUILD_DEFAULT_UDP_PORT; #define updatecrc16(crc,dat) crc = (((crc<<8)&65535)^crctable[((((unsigned short)crc)>>8)&65535)^dat]) static long incnt[MAXPLAYERS], outcntplc[MAXPLAYERS], outcntend[MAXPLAYERS]; static char errorgotnum[MAXPLAYERS]; static char errorfixnum[MAXPLAYERS]; static char errorresendnum[MAXPLAYERS]; #if (PRINTERRORS) static char lasterrorgotnum[MAXPLAYERS]; #endif long crctable[256]; int tmpmax[8]; //addfaz variable addition (you could probs think of something better) unsigned int g_bAllPlayersFound = 0; static char lastpacket[576], inlastpacket = 0; static short lastpacketfrom, lastpacketleng; extern long totalclock; /* MUST EXTERN 1 ANNOYING VARIABLE FROM GAME */ static long timeoutcount = 60, resendagaincount = 4, lastsendtime[MAXPLAYERS]; static short bakpacketptr[MAXPLAYERS][256], bakpacketlen[MAXPLAYERS][256]; static char bakpacketbuf[BAKSIZ]; static long bakpacketplc = 0; short myconnectindex, numplayers; short connecthead, connectpoint2[MAXPLAYERS]; char syncstate = 0; unsigned char g_bWaitingForAllReady = 0; extern int _argc; extern char **_argv; #define MAXPACKETSIZE 2048 typedef struct { short intnum; /* communication between Game and the driver */ short command; /* 1-send, 2-get */ short other; /* dest for send, set by get (-1 = no packet) */ short numbytes; short myconnectindex; short numplayers; short gametype; /* gametype: 1-serial,2-modem,3-net */ short filler; char buffer[MAXPACKETSIZE]; long longcalladdress; } gcomtype; static gcomtype *gcom; gcomtype g_LastPersonalPacket; typedef struct { unsigned short other; unsigned int bufferSize; unsigned char buffer[MAXPACKETSIZE]; }PACKET; typedef std::vector<PACKET> PacketQueue; PacketQueue incommingPacketQueue; //typedef std::vector<PACKET> PacketQueue; enum ECommitCMDs { COMMIT_CMD_SEND = 1, COMMIT_CMD_GET = 2, COMMIT_CMD_SENDTOALL = 3, COMMIT_CMD_SENDTOALLOTHERS = 4, COMMIT_CMD_SCORE = 5, }; typedef enum { udpmode_peer, udpmode_server, udpmode_client } udpmodes; static udpmodes udpmode = udpmode_peer; enum EConnectionMode { CONN_MODE_CONNECTING = 0, CONN_MODE_GREETING = 1, CONN_MODE_WAITFORREADY = 2, CONN_MODE_CONNECTED = 3, CONN_MODE_DISCONNECTED = 4, }; EConnectionMode g_ConnMode = CONN_MODE_CONNECTING; typedef struct { unsigned int host; short port; unsigned short id; unsigned short peer_idx; unsigned short bHeardFrom; unsigned char bReady; } ADDRESS_STRUCT; ADDRESS_STRUCT allowed_addresses[MAX_PLAYERS]; /* only respond to these IPs. */ volatile int ctrlc_pressed = 0; static void siginthandler(int sigint) { ctrlc_pressed = 1; } typedef struct { unsigned char dummy1; /* so these don't confuse game after load. */ unsigned char dummy2; /* so these don't confuse game after load. */ unsigned char dummy3; /* so these don't confuse game after load. */ unsigned char header; /* always HEADER_PEER_GREETING (245). */ unsigned short id; } PacketPeerGreeting; // unique id for determining "myconnectindex" unsigned short my_id = 0; unsigned short g_nPlayerIDList[MAX_PLAYERS]; #define CONNECTION_DELAY 3000 #define INITIAL_CONNECTION_DELAY 50 #define INGAME_CONNECTION_DELAY 0 #define POLL_DELAY 1000 //ENetAddress address; ENetHost* g_Server = 0; //ENetEvent event; ENetPeer* g_Peers[MAX_PLAYERS]; short *g_other; char *g_bufptr; short g_nMessageLen; unsigned char g_bAllGreetingsIn = 0; // Prototypes int CreateServer(char* ip, int nPort, int nMaxPlayers); char *static_ipstring(int ip); char *read_whole_file(const char *cfgfile); char *get_token(char **ptr); int parse_ip(const char *str, int *ip); int parse_interface(char *str, int *ip, short *udpport); int parse_udp_config(const char *cfgfile, gcomtype *gcom); int connect_to_everyone(); void HandleEvent(ENetEvent *pEvent); unsigned int GetPeerIndex(ENetPeer* peer); unsigned int GetOtherIndex(ENetPeer* peer); void ServiceNetwork(); void Send_Peer_Gretting(); void Wait_For_Ready(); void cleanup(void); void stable_callcommit(void) { } void stable_initcrc(void) { } // Get CRC long stable_getcrc(char *buffer, short bufleng) { long i, j; j = 0; for(i=bufleng-1;i>=0;i--) updatecrc16(j,buffer[i]); return(j&65535); } void stable_initmultiplayers(char damultioption, char dacomrateoption, char dapriority) { long i; gcomtype *retval; int k; // DO NOT DO THIS - it screws up the networking //srand(enet_time_get_raw()); for (i = _argc - 1; i > 0; i--) { const char *arg = _argv[i]; char ch = *arg; if ((ch == '-') || (ch == '/')) { if (stricmp(arg + 1, "net") == 0) break; } } if ((i == 0) || (i+1 == _argc)) { numplayers = 1; myconnectindex = 0; connecthead = 0; connectpoint2[0] = -1; return; } // Zero out the peers buffer //memset(g_Peers, 0, MAX_PLAYERS); /* for(k = 0; k < MAX_PLAYERS-1; ++k) { g_Peers[k] = NULL; } */ if(enet_initialize() == -1) { printf("Error initializing ENet\n"); } atexit(cleanup); retval = (gcomtype *)malloc(sizeof (gcomtype)); if (retval != NULL) { int rc; char *cfgfile = _argv[i+1]; void (*oldsigint)(int); memset(retval, '\0', sizeof (gcomtype)); memset(allowed_addresses, '\0', sizeof (allowed_addresses)); udpsocket = -1; udpport = BUILD_DEFAULT_UDP_PORT; udpmode = udpmode_peer; oldsigint = signal(SIGINT, siginthandler); rc = parse_udp_config(cfgfile, retval); signal(SIGINT, oldsigint); if(!rc) { printf("Network transport initialization error!\n"); } gcom = retval; } else { printf("Error allocating gcomtype!\n"); } numplayers = gcom->numplayers; // myconnectindex = gcom->myconnectindex;//numplayers-1; #if (SIMULATEERRORS != 0) srand(myconnectindex*24572457+345356); #endif //g_Peers = (ENetPeer**)malloc(sizeof(ENetPeer*) * gcom->numplayers); connect_to_everyone(); connecthead = 0; for(i=0;i<numplayers-1;i++) { connectpoint2[i] = i+1; } connectpoint2[numplayers-1] = -1; for(i=0;i<numplayers;i++) { lastsendtime[i] = totalclock; } // Set our connection index myconnectindex = gcom->myconnectindex;//numplayers-1; } void stable_sendpacket(long other, char *bufptr, long messleng) { if(other == (myconnectindex)) { #ifdef _DEBUG_NETWORKING_ printf("Send Packet to myself %d : type: %d len: %d\n", other, bufptr[0], messleng); #endif memcpy(g_LastPersonalPacket.buffer, bufptr, messleng); g_LastPersonalPacket.numbytes = (short)messleng; g_LastPersonalPacket.command = 1; } else { #ifdef _DEBUG_NETWORKING_ printf("Send Packet to peer %d : type: %d len: %d\n", other, bufptr[0], messleng); #endif ENetPacket * packet = enet_packet_create (bufptr, sizeof(char) * messleng, ENET_PACKET_FLAG_RELIABLE);//ENET_PACKET_FLAG_RELIABLE //enet_peer_send (g_Peers[other], 0, packet); enet_peer_send (g_Peers[allowed_addresses[other].peer_idx], 0, packet); enet_host_flush(g_Server); } } void stable_setpackettimeout(long datimeoutcount, long daresendagaincount) { //NOT USED for anything other than '/f4' } void stable_uninitmultiplayers(void) { //kill networking /* if(g_Peers) { free(g_Peers); } */ incommingPacketQueue.clear(); enet_deinitialize(); } void cleanup(void) { stable_uninitmultiplayers(); } void stable_sendlogon(void) { } void stable_sendlogoff(void) { long i; char tempbuf[2]; tempbuf[0] = 255; tempbuf[1] = myconnectindex; for(i=connecthead;i>=0;i=connectpoint2[i]) if (i != myconnectindex) stable_sendpacket(i,tempbuf,2L); } int stable_getoutputcirclesize(void) { return 0; } void stable_setsocket(short newsocket) { } //------------------------------------------------- // // GetPacket // //------------------------------------------------- short stable_getpacket(short *other, char *bufptr) { ENetEvent event; g_nMessageLen = 0; //clear out the early packet buffer first if(incommingPacketQueue.size() > 0) { PacketQueue::iterator iter = incommingPacketQueue.begin(); if(iter != incommingPacketQueue.end() ) { g_nMessageLen = (*iter).bufferSize; *other = (*iter).other; memcpy(bufptr , (*iter).buffer, g_nMessageLen); // Delete this entry now that we're done with it. incommingPacketQueue.erase(iter); } } else if (enet_host_service (g_Server, & event, INGAME_CONNECTION_DELAY) > 0) { // setup the pointers. g_other = other; HandleEvent(&event); if(event.type == ENET_EVENT_TYPE_RECEIVE) { memcpy(bufptr, &lastpacket[0], g_nMessageLen); } }else // check to see if we have a packet of our own to deliver to ourselves. { if(g_LastPersonalPacket.command == 1) { *other = gcom->numplayers -1;//myconnectindex; memcpy(bufptr, &g_LastPersonalPacket.buffer[0], g_nMessageLen); //reset it g_LastPersonalPacket.command = 0; return g_LastPersonalPacket.numbytes; } } return g_nMessageLen; } void stable_flushpackets(void) { //STUB } void stable_genericmultifunction(long other, char *bufptr, long messleng, long command) { } // // // int connect_to_everyone() { ENetAddress address; ENetEvent event; int i; int bWaiting = 1; int bCreatedPeers = 0; while(bWaiting) { printf( (g_bAllPlayersFound) ? "." : "Waiting for connections...\n"); //wait for conencts to/from them if (enet_host_service (g_Server, & event, (bCreatedPeers == 1) ? CONNECTION_DELAY : INITIAL_CONNECTION_DELAY) > 0) { HandleEvent(&event); } //Create peer and connect to it //enet_address_set_host (& address, m_szAddr); if(bCreatedPeers == 0) { for(i = 0; i < gcom->numplayers-1; ++i) { ENetPeer *peer; char szHostName[64]; address.host = allowed_addresses[i].host; //ip; address.port = allowed_addresses[i].port; //m_nPort; enet_address_get_host(&address, szHostName, 64); printf("Creating peer: %s:%d\n", szHostName, address.port); g_Peers[i] = enet_host_connect (g_Server, & address, 2); if(g_Peers[i] == NULL) { printf("Error creating peer! \n"); //return 1; }else { allowed_addresses[i].peer_idx = i; } } bCreatedPeers = 1; } if(g_bAllPlayersFound == 1) { bWaiting = 0; } } printf("Negotiating connection order...\n"); Send_Peer_Gretting(); Wait_For_Ready(); return 0; } void Send_Peer_Gretting() { int i; g_ConnMode = CONN_MODE_GREETING; while (my_id == 0) /* player number is based on id, low to high. */ { my_id = (unsigned short)enet_time_get_raw();//(unsigned short) rand(); } printf("My client id is %d\n", my_id); for(i = 0; i < MAX_PLAYERS; ++i) { allowed_addresses[i].id = 0; } PacketPeerGreeting greetpacket; memset(&greetpacket, '\0', sizeof (greetpacket)); greetpacket.header = HEADER_PEER_GREETING; greetpacket.id = BUILDSWAP_INTEL16(my_id); // Create the greeting packet ENetPacket * packet = enet_packet_create (&greetpacket, sizeof(PacketPeerGreeting), ENET_PACKET_FLAG_RELIABLE);//ENET_PACKET_FLAG_RELIABLE printf("Broadcasting Greating...\n"); // Broadcast it to all the peers enet_host_broadcast(g_Server, 0, packet); // Flush the send buffer enet_host_flush(g_Server); while(CONN_MODE_GREETING == g_ConnMode) { ENetEvent event; if (enet_host_service (g_Server, & event, CONNECTION_DELAY) > 0) { int nAllIDsIn = 1; HandleEvent(&event); // are all the id's in yet? for(i = 0; i < (gcom->numplayers-1); ++i) { if(allowed_addresses[i].id == 0) { nAllIDsIn = 0; break; } } // add our ID to the list for sorting allowed_addresses[gcom->numplayers-1].id = my_id; //check the validity of the ID and sort them. if(nAllIDsIn == 1) { int iteration = 0; int k = 0; unsigned short nCurrentHigh = 0; printf("Sorting player IDs...\n"); for(iteration = 0; iteration < gcom->numplayers; ++iteration) { //g_nPlayerIDList[i] for(k = iteration+1; k < gcom->numplayers; ++k) { if(allowed_addresses[iteration].id == allowed_addresses[k].id) { printf("ERROR!!!!! Two players with the same Unique ID found, please restart...\n"); } else { // if it's valid, then goto sort it if(allowed_addresses[k].id > allowed_addresses[iteration].id) { //swap'm //unsigned short nTemp = allowed_addresses[iteration]; ADDRESS_STRUCT tempAddress; // Swap the positions memcpy(&tempAddress, &allowed_addresses[iteration], sizeof(ADDRESS_STRUCT)); memcpy(&allowed_addresses[iteration], &allowed_addresses[k], sizeof(ADDRESS_STRUCT)); memcpy(&allowed_addresses[k], &tempAddress, sizeof(ADDRESS_STRUCT)); } } } } // Find our slot printf("Finding our player index...\n"); for(i = 0; i < (gcom->numplayers); ++i) { printf("Index[%d] = %d\n", i, allowed_addresses[i].id); if(allowed_addresses[i].id == my_id) { gcom->myconnectindex = i; printf("You are player #%d\n", i); // We're all greated, switch to waiting for all ready g_ConnMode = CONN_MODE_WAITFORREADY; break; } } } } } } void Wait_For_Ready() { g_bWaitingForAllReady = gcom->numplayers-1; // Create the greeting packet unsigned char message = HEADER_PEER_READY; ENetPacket * packet = enet_packet_create (&message, sizeof(unsigned char), ENET_PACKET_FLAG_RELIABLE);//ENET_PACKET_FLAG_RELIABLE printf("Broadcasting Ready Packet...\n"); // Broadcast it to all the peers enet_host_broadcast(g_Server, 0, packet); // Flush the send buffer enet_host_flush(g_Server); //g_ConnMode = CONN_MODE_CONNECTED;//CONN_MODE_WAITFORREADY; while(g_bWaitingForAllReady > 0) { ENetEvent event; if (enet_host_service (g_Server, & event, CONNECTION_DELAY) > 0) { int i; HandleEvent(&event); g_bWaitingForAllReady = gcom->numplayers-1; for(i = 0; i < gcom->numplayers; ++i) { if(allowed_addresses[i].bReady == 1) { --g_bWaitingForAllReady; } } // Check to make sure we didn't subtract 1 from 0 to make 255. (unsigned char) if(g_bWaitingForAllReady > gcom->numplayers) { printf("Error: we have a problem with the waiting for ready packets...\n"); } } } printf("All players are ready. Start sending game data...\n"); g_ConnMode = CONN_MODE_CONNECTED; } void HandleEvent(ENetEvent *pEvent) { switch(pEvent->type) { case ENET_EVENT_TYPE_CONNECT: { //bServerConnected = true; ENetAddress address; int i; address.host = pEvent->peer->address.host; //ip; address.port = pEvent->peer->address.port; //m_nPort; char szHostName[64]; enet_address_get_host(&address, szHostName, 64); printf("Connection Established with: (%s)\n", szHostName); for(i = 0; i < gcom->numplayers-1; ++i) { if(allowed_addresses[i].host == address.host) { allowed_addresses[i].bHeardFrom = 1; } } for(i = 0; i < gcom->numplayers-1; ++i) { if(allowed_addresses[i].bHeardFrom == 0) { return; } } // All players have been found... YAY! g_bAllPlayersFound = 1; printf("All Players Connected...\n"); } break; case ENET_EVENT_TYPE_RECEIVE: { g_nMessageLen = (short)pEvent->packet->dataLength; switch(g_ConnMode) { case CONN_MODE_GREETING: { PacketPeerGreeting packet; unsigned int nPeerIndex; int i; if(pEvent->packet->data[0] != HEADER_PEER_GREETING) { printf("Invalid greeting!!!!\n"); } printf("Received greeting from (%x)...\n", pEvent->peer->address.host); memcpy(&packet, pEvent->packet->data, g_nMessageLen); if(packet.header == HEADER_PEER_GREETING) { // Find the peer's index nPeerIndex = GetPeerIndex(pEvent->peer); // Set the id for the peer //g_nPlayerIDList[nPeerIndex] = packet.id; allowed_addresses[nPeerIndex].id = packet.id; } } break; case CONN_MODE_WAITFORREADY: { if(pEvent->packet->data[0] == HEADER_PEER_READY) { allowed_addresses[GetOtherIndex(pEvent->peer)].bReady = 1; } else { printf("Invalid READY packet!!!\n"); } } break; case CONN_MODE_CONNECTED: default: { if(g_ConnMode != CONN_MODE_CONNECTED) { PACKET packet; packet.other = GetOtherIndex(pEvent->peer); packet.bufferSize = g_nMessageLen; memcpy(packet.buffer, pEvent->packet->data, g_nMessageLen); incommingPacketQueue.push_back(packet); printf("Saving early packet...\n"); break; } if(pEvent->packet->data[0] == 16) { printf("PACKET 16: len:[%d]\n", g_nMessageLen); } #ifdef _DEBUG_NETWORKING_LEVEL2_ printf("RECEIVE: type[%d] len:[%d]\n", pEvent->packet->data[0], g_nMessageLen); #endif memcpy(&lastpacket[0], pEvent->packet->data, g_nMessageLen); *g_other = GetOtherIndex(pEvent->peer); } break; } /*if(g_nMessageLen > 0) { switch(pEvent->packet->data[0]) { case HEADER_PEER_GREETING: { PacketPeerGreeting packet; unsigned int nPeerIndex; int i; printf("Received greeting from (%x)...\n", pEvent->peer->address.host); memcpy(&packet, pEvent->packet->data, g_nMessageLen); if(packet.header == HEADER_PEER_GREETING) { // Find the peer's index in the g_Peers[] array nPeerIndex = GetPeerIndex(pEvent->peer); // Set the id for the peer //g_nPlayerIDList[nPeerIndex] = packet.id; allowed_addresses[nPeerIndex].id = packet.id; } } break; case HEADER_PEER_READY: { unsigned int nOtherIndex; printf("Received ready from (%x)...\n", pEvent->peer->address.host); nOtherIndex = GetOtherIndex(pEvent->peer); allowed_addresses[nOtherIndex].bReady = 1; } break; default: { if((g_bWaitingForAllReady) || (g_ConnMode == CONN_MODE_GREETING)) { PACKET packet; packet.other = GetOtherIndex(pEvent->peer); packet.bufferSize = g_nMessageLen; memcpy(packet.buffer, pEvent->packet->data, g_nMessageLen); incommingPacketQueue.push_back(packet); printf("Saving early packet...\n"); break; } #ifdef _DEBUG_NETWORKING_LEVEL2_ printf("RECEIVE: type[%d] len:[%d]\n", pEvent->packet->data[0], g_nMessageLen); #endif memcpy(&lastpacket[0], pEvent->packet->data, g_nMessageLen); // find the correct index in the allowed_addresses[] array. *g_other = GetOtherIndex(pEvent->peer); } break; } } else { printf("Error: we received a Zero length packet!\n"); }*/ // Destroy the packet now that we're done with it. enet_packet_destroy (pEvent->packet); } break; case ENET_EVENT_TYPE_DISCONNECT: { printf("DISCONNECT: someone left!\n"); } break; default: { printf("Error: unknown event! : %d\n", pEvent->type); } break; } } unsigned int GetPeerIndex(ENetPeer* peer) { int i; for(i = 0; i < gcom->numplayers; ++i) { if(peer->address.host == allowed_addresses[i].host) { return allowed_addresses[i].peer_idx; //return i; } } printf("Error: GetPeerIndex failed to find the corrent index!\n"); return 0; } unsigned int GetOtherIndex(ENetPeer* peer) { int i; for(i = 0; i < gcom->numplayers; ++i) { if(peer->address.host == allowed_addresses[i].host) { return i;//allowed_addresses[i].peer_idx; //return i; } } printf("Error: GetOtherIndex failed to find the corrent index!\n"); return 0; } void ServiceNetwork() { ENetEvent event; if (enet_host_service (g_Server, & event, INGAME_CONNECTION_DELAY) > 0) { HandleEvent(&event); } } //************************************************************** //* Network Transport Functions //************************************************************** int CreateServer(char* ip, int nPort, int nMaxPlayers) { ENetAddress address; printf("Creating server of %d players on port %d.\n", nMaxPlayers, nPort); /* Bind the server to the default localhost. * A specific host address can be specified by * enet_address_set_host (& address, "x.x.x.x"); */ address.host = enet_address_set_host (& address, ip);//nIp;//ENET_HOST_ANY; /* Bind the server to port 1234. */ address.port = nPort; g_Server = enet_host_create (& address /* the address to bind the server host to */, nMaxPlayers /* allow up to 32 clients and/or outgoing connections */, 0 /* assume any amount of incoming bandwidth */, 0 /* assume any amount of outgoing bandwidth */); if (g_Server == NULL) { printf("Error creating server!\n"); return 1; } return 0; } //************************************************************** //* Network Config File Functions //************************************************************** #include "cache1d.h" /* kopen4load for cfg file. */ #include "display.h" /* getticks */ #define IPSEG1(ip) ((((unsigned int) ip) & 0xFF000000) >> 24) #define IPSEG2(ip) ((((unsigned int) ip) & 0x00FF0000) >> 16) #define IPSEG3(ip) ((((unsigned int) ip) & 0x0000FF00) >> 8) #define IPSEG4(ip) ((((unsigned int) ip) & 0x000000FF) ) char *static_ipstring(int ip) { static char s[16]; sprintf(s, "%u.%u.%u.%u", IPSEG1(ip), IPSEG2(ip), IPSEG3(ip), IPSEG4(ip)); return(s); } char *read_whole_file(const char *cfgfile) { char *buf; long len, rc; long handle; if (cfgfile == NULL) return(NULL); handle = kopen4load(cfgfile, 0); if (handle == -1) { printf("ERROR: Failed to open config file [%s].\n", cfgfile); return(NULL); } len = kfilelength(handle); buf = (char *) malloc(len + 2); if (!buf) { kclose(handle); return(NULL); } rc = kread(handle, buf, len); kclose(handle); if (rc != len) { free(buf); return(NULL); } buf[len] = '\0'; buf[len+1] = '\0'; return(buf); } char *get_token(char **ptr) { char *retval; char *p = *ptr; if (*p == '\0') return(NULL); while ((*p != '\0') && (isspace(*p))) p++; if (*p == '\0') /* nothing but whitespace. */ return(NULL); retval = p; while ((*p != '\0') && (!isspace(*p))) p++; *p = '\0'; *ptr = p + 1; /*printf("Got token [%s].\n", retval);*/ return(retval); } int parse_ip(const char *str, int *ip) { int ip1, ip2, ip3, ip4; if (stricmp(str, "any") == 0) { *ip = 0; return(1); } if (sscanf(str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) { printf("\"%s\" is not a valid IP address.\n", str); return(0); } /* we _should_ check that 0 <= ip? <= 255, but it'll fail later anyhow. */ *ip = ( ((ip1 & 0xFF) << 24) | ((ip2 & 0xFF) << 16) | ((ip3 & 0xFF) << 8) | ((ip4 & 0xFF) ) ); return(1); } int parse_interface(char *str, int *ip, short *udpport) { char *ptr = strchr(str, ':'); if (ptr) /* portnum specified? */ *ptr = '\0'; if (!parse_ip(str, ip)) return(0); *udpport = BUILD_DEFAULT_UDP_PORT; if (ptr != NULL) /* port specified? */ { ptr++; if (stricmp(ptr, "any") == 0) *udpport = 0; else *udpport = (short) atoi(ptr); } return(1); } int parse_udp_config(const char *cfgfile, gcomtype *gcom) { char *buf; char *tok; char *ptr; int ip = 0; /* interface */ int bcast = 0; buf = read_whole_file(cfgfile); /* we must free this. */ if (buf == NULL) return(0); ptr = buf; while ((tok = get_token(&ptr)) != NULL) { int bogus = 1; if (stricmp(tok, "interface") == 0) { if ( (tok = get_token(&ptr)) && (parse_interface(tok, &ip, &udpport)) ) { bogus = 0; } printf("Interface %s:%d chosen.\n", static_ipstring(ip), (int) udpport); } else if (stricmp(tok, "mode") == 0) { if ((tok = get_token(&ptr)) != NULL) { bogus = 0; if (stricmp(tok, "server") == 0) udpmode = udpmode_server; else if (stricmp(tok, "client") == 0) udpmode = udpmode_client; else if (stricmp(tok, "peer") == 0) udpmode = udpmode_peer; else bogus = 1; if (!bogus) printf("You want to be in [%s] mode\n", tok); } } else if (stricmp(tok, "broadcast") == 0) { if ((tok = get_token(&ptr)) != NULL) { bcast = atoi(tok); if (bcast > MAX_PLAYERS - 1) { printf("WARNING: Too many broadcast players.\n"); bcast = MAX_PLAYERS - 1; } bogus = 0; } } else if (stricmp(tok, "allow") == 0) { int host; short port=BUILD_DEFAULT_UDP_PORT; if ((tok = get_token(&ptr)) != NULL) { if (gcom->numplayers >= MAX_PLAYERS - 1) printf("WARNING: Too many allowed IP addresses.\n"); else if (parse_interface(tok, &host, &port)) { ENetAddress address; enet_address_set_host(&address, static_ipstring(host)); printf("Adding: %s:%d to the list of allowed addresses.\n", static_ipstring(host), port); allowed_addresses[gcom->numplayers].host = address.host; allowed_addresses[gcom->numplayers].port = port; gcom->numplayers++; bogus = 0; } } } if (bogus) printf("bogus token! [%s]\n", tok); } free(buf); // Create the server int ret = CreateServer(static_ipstring(ip), udpport, gcom->numplayers); gcom->numplayers++; //that's you if(ret == 0) { return 1; } return(0); } } // end extern "C" /* end of mmulti.cpp ... */