/* * file com_from_central.c - handle communications with clients * * $Id: com_from_central.c,v 1.3 2004/05/14 10:00:33 alfie Exp $ * * Program XBLAST * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net) * Added by Koen De Raedt for central support * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2; or (at your option) * any later version * * This program is distributed in the hope that it will be entertaining, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "com_from_central.h" #include "central.h" #include "com_stream.h" #include "net_tele.h" #include "server.h" #include "cfg_level.h" /* * local types */ typedef struct { XBCommStream stream; unsigned serial; } XBCommFromCentral; /* * local variables */ static XBCommFromCentral *commList[MAX_HOSTS] = { /* this entry is never used (server) */ NULL, /* up to 5 clients can connect */ NULL, NULL, NULL, NULL, NULL, }; /* * */ static XBBool HandleRequestPlayerConfig (XBSndQueue *sndQueue, const char *line) { XBAtom atom; int i,j,k,l=0; assert (NULL != sndQueue); /* get player atom from config */ j=GetNumPlayerConfigs (CT_Central); for(i=0;i0) { // Dbg_Out("Sending player config of player %i\n", k); if (! SendPlayerConfig (CT_Central, sndQueue, XBT_COT_DataAvailable, 0, atom, XBFalse) ) { Dbg_Out("Unable to send player config of player %i\n", k); // return XBFalse; } else { l++; } } } /* that's all */ Dbg_Out("%i players send\n",l); /* data not available means no more entries */ Net_SendTelegram (sndQueue, Net_CreateTelegram (XBT_COT_DataNotAvailable, XBT_ID_PlayerConfig, 0, NULL, 0) ); /* send now */ return XBTrue; } /* HandleRequestPlayerConfig */ /* * server requests data */ static XBCommResult HandleRequestData (XBCommFromCentral *fromCentral, const XBTelegram *tele) { XBBool dataSend = XBFalse; const char *data; size_t len; data = Net_TeleData (tele, &len); /* now retrieve data */ switch (Net_TeleID (tele)) { case XBT_ID_PlayerConfig: Dbg_Out("Peer %i requests players\n",fromCentral->serial); dataSend = HandleRequestPlayerConfig (fromCentral->stream.sndQueue, data); break; default: break; } if (dataSend) { Socket_RegisterWrite (CommSocket (&commList[fromCentral->serial]->stream.comm)); } /* enable writing */ return XCR_OK; } /* HandleRequestData */ /* * */ static XBCommResult HandleSendData (XBCommFromCentral *fromCentral, const XBTelegram *tele) { const char *data; size_t len; XBTeleIOB iob; data = Net_TeleData (tele, &len); iob = Net_TeleIOB (tele); switch (Net_TeleID (tele)) { case XBT_ID_PlayerConfig: Central_ReceivePlayerConfig (fromCentral->serial, data); break; case XBT_ID_GameStat: Central_ReceiveGameStat (data); break; default: return XCR_OK; } /* achknowledge reception */ //Socket_RegisterWrite (CommSocket (&stream->comm) ); Socket_RegisterWrite (CommSocket (&commList[fromCentral->serial]->stream.comm)); return XCR_OK; } /* HandleSendData */ /* * */ static XBCommResult HandleActivate (XBCommFromCentral *fromCentral, const XBTelegram *tele) { const void *data; size_t len; // unsigned value; data = Net_TeleData (tele, &len); switch (Net_TeleID (tele)) { case XBT_ID_RequestDisconnect: /* just close the socket */ return XCR_Finished; default: break; } return XCR_OK; } /* HandleSendData */ /* * */ static XBCommResult HandleSpontaneous (XBCommFromCentral *fromCentral, const XBTelegram *tele) { switch (Net_TeleID (tele)) { case XBT_ID_HostDisconnected: Central_ReceiveDisconnect (fromCentral->serial); return XCR_OK; default: break; } return XCR_OK; } /* HandleSpontaneous */ /* * handle telegrams from users */ static XBCommResult HandleTelegram (XBCommStream *stream, const XBTelegram *tele) { XBCommFromCentral *fromCentral = (XBCommFromCentral *) stream; assert (fromCentral != NULL); switch (Net_TeleCOT (tele)) { /* user requests data from central */ case XBT_COT_RequestData: return HandleRequestData (fromCentral, tele); /* user sends data to central */ case XBT_COT_SendData: return HandleSendData (fromCentral, tele); /* server activate command on client */ case XBT_COT_Activate: return HandleActivate (fromCentral, tele); /* server send spontaneous status change */ case XBT_COT_Spontaneous: return HandleSpontaneous (fromCentral, tele); default: return XCR_Error; } } /* HandleTelegram */ /* * */ static XBCommResult DeleteFromCentral (XBComm *comm) { XBCommFromCentral *fromcentral = (XBCommFromCentral *) comm; assert (comm != NULL); assert (fromcentral == commList[fromcentral->serial]); /* unmark client */ commList[fromcentral->serial] = NULL; /* clean up */ Stream_CommFinish (&fromcentral->stream); /* make sure application is informed */ Central_ReceiveDisconnect (fromcentral->serial); /* free memory */ free (comm); return XCR_OK; } /* DeleteFromCentral */ /* * */ static void ErrorFromCentral (XBCommStream *comm) { XBCommFromCentral *fromcentral = (XBCommFromCentral *) comm; assert (fromcentral != NULL); Central_NotifyError (fromcentral->serial); } /* ErrorFromCentral */ /* * create listeneing communication */ XBComm * C2X_CreateComm (const XBSocket *socket) { unsigned serial; XBSocket *pSocket; XBCommFromCentral *fromcentral; assert (socket != NULL); /* get free serial */ for (serial = 1; serial < MAX_HOSTS; serial ++) { if (NULL == commList[serial]) { break; } } if (serial >= MAX_HOSTS) { return NULL; } /* create listen socket */ pSocket = Net_Accept (socket); if (NULL == pSocket) { return NULL; } /* create communication data structure */ fromcentral = calloc (1, sizeof (XBCommFromCentral) ); assert (NULL != fromcentral); /* set values */ Stream_CommInit (&fromcentral->stream, COMM_FromCentral, pSocket, HandleTelegram, ErrorFromCentral, DeleteFromCentral); fromcentral->serial = serial; /* add to inernal list */ commList[serial] = fromcentral; /* inform application */ Central_Accept (serial, Net_RemoteName (pSocket), Net_RemotePort (pSocket)); /* that's all */ return &fromcentral->stream.comm; } /* C2X_CreateComm */ /* * check if client is connected */ XBBool C2X_Connected (unsigned id) { assert (id > 0); assert (id < MAX_HOSTS); return (commList[id] != NULL); } /* C2X_Connected */ /* * send game config to client */ void C2X_SendPlayerConfig (unsigned id, unsigned hostId, int player, XBAtom atom) { XBTeleIOB iob; assert (id > 0); assert (id < MAX_HOSTS); assert (commList[id] != NULL); assert (commList[id]->stream.sndQueue != NULL); /* convert id and player ti iob */ iob = ((XBTeleIOB) hostId << 4) + (XBTeleIOB) player; /* send database section */ Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm)); SendPlayerConfig (CT_Remote, commList[id]->stream.sndQueue, XBT_COT_SendData, iob, atom, XBFalse); // XBCC not to central } /* C2X_SendPlayerConfig */ /* * send random seed to client */ void C2X_SendUserPID (unsigned id, int PID) { char tmp[16]; /* sanity check */ assert (id > 0); assert (id < MAX_HOSTS); assert (commList[id] != NULL); assert (commList[id]->stream.sndQueue != NULL); /* send seed as ascii */ sprintf (tmp, "%i", PID); /* send data */ Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm)); Net_SendTelegram (commList[id]->stream.sndQueue, Net_CreateTelegram (XBT_COT_DataAvailable, XBT_ID_PID, 0, tmp, strlen (tmp) + 1) ); } /* S2C_SendDgramPort */ /* * send disconnect message to client */ void C2X_HostDisconnected (unsigned id, unsigned hostID) { assert (id > 0); assert (id < MAX_HOSTS); assert (commList[id] != NULL); Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm)); Net_SendTelegram (commList[id]->stream.sndQueue, Net_CreateTelegram (XBT_COT_Spontaneous, XBT_ID_HostDisconnected, hostID, NULL, 0) ); } /* C2X_HostDisconnected */ /* * send request for disconnect to given client */ void C2X_Disconnect (unsigned id) { assert (id > 0); assert (id < MAX_HOSTS); assert (commList[id] != NULL); /* inform host about disconnect request */ Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm)); Net_SendTelegram (commList[id]->stream.sndQueue, Net_CreateTelegram (XBT_COT_Spontaneous, XBT_ID_HostDisconnected, 0, NULL, 0) ); Net_SendTelegram (commList[id]->stream.sndQueue, Net_CreateTelegram (XBT_COT_Activate, XBT_ID_RequestDisconnect, 0, NULL, 0) ); } /* C2X_Disconnect */ /* * hostname of client */ const char * C2X_HostName (unsigned id) { assert (id > 0); assert (id <= MAX_HOSTS); assert (commList[id] != NULL); /* get name from socket */ return Net_RemoteName (commList[id]->stream.comm.socket); } /* C2X_HostName */ /* * hostname of client */ const char * C2X_LocalName (unsigned id) { assert (id > 0); assert (id <= MAX_HOSTS); assert (commList[id] != NULL); /* get name from socket */ return Net_LocalName (commList[id]->stream.comm.socket); } /* C2X_LocalName */ /* * end of file com_from_central.c */