| |
| #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 ... */ |
| |
| |