/* * file com_to_server.c - client's communication with server * * $Id: com_to_server.c,v 1.3 2004/05/14 10:00:33 alfie Exp $ * * Program XBLAST * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net) * * 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_to_server.h" #include "atom.h" #include "client.h" #include "com_stream.h" #include "net_tele.h" #include "net_socket.h" /* * local types */ typedef struct { XBCommStream stream; } XBCommToServer; /* * reply: data ist not available */ static void DataNotAvailable (XBCommStream *stream, const XBTelegram *tele) { XBTelegram *reply; reply = Net_CreateTelegram (XBT_COT_DataNotAvailable, Net_TeleID (tele), Net_TeleIOB (tele), NULL, 0); assert (reply != NULL); Net_SendTelegram (stream->sndQueue, reply); /* enable writing */ Socket_RegisterWrite (CommSocket (&stream->comm) ); } /* SendDataNotAvailable */ /* * */ static XBBool HandleRequestPlayerConfig (XBSndQueue *sndQueue, XBTeleIOB iob) { CFGGamePlayers cfgPlayers; assert (NULL != sndQueue); /* check player index */ if (iob >= NUM_LOCAL_PLAYER) { return XBFalse; } /* get player atom from config */ if (! RetrieveGamePlayers (CT_Local, atomClient, &cfgPlayers) ) { return XBFalse; } /* check player */ if (iob >= cfgPlayers.num) { return XBFalse; } if (ATOM_INVALID == cfgPlayers.player[iob]) { return XBFalse; } /* send config from database */ if (! SendPlayerConfig (CT_Local, sndQueue, XBT_COT_DataAvailable, iob, cfgPlayers.player[iob], XBFalse) ) { // XBCC return XBFalse; } /* that's all */ return XBTrue; } /* HandleRequestPlayerConfig */ /* * */ static XBBool HandleRequestGameConfig (XBSndQueue *sndQueue) { CFGGamePlayers cfgPlayers; assert (NULL != sndQueue); /* retrieve players config only */ (void) RetrieveGamePlayers (CT_Local, atomClient, &cfgPlayers); StoreGamePlayers (CT_Remote, atomLocal, &cfgPlayers); /* send filtered config from database */ if (! SendGameConfig (CT_Remote, sndQueue, XBT_COT_DataAvailable, 0, atomLocal) ) { return XBFalse; } /* that's all */ return XBTrue; } /* HandleRequestGameConfig */ /* * server requests data */ static XBCommResult HandleRequestData (XBCommStream *stream, const XBTelegram *tele) { XBBool dataSend = XBFalse; /* now retrieve data */ switch (Net_TeleID (tele)) { case XBT_ID_PlayerConfig: dataSend = HandleRequestPlayerConfig (stream->sndQueue, Net_TeleIOB (tele)); break; case XBT_ID_GameConfig: dataSend = HandleRequestGameConfig (stream->sndQueue); break; default: break; } if (dataSend) { Socket_RegisterWrite (CommSocket (&stream->comm) ); } else { DataNotAvailable (stream, tele); } /* enable writing */ return XCR_OK; } /* HandleRequestData */ /* * Reply data received */ static void DataReceived (XBCommStream *stream, const XBTelegram *tele) { } /* DataReceived */ /* * */ static XBCommResult HandleSendData (XBCommStream *stream, 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_GameConfig: Client_ReceiveGameConfig (iob, data); break; case XBT_ID_PlayerConfig: Client_ReceivePlayerConfig (iob >> 4, iob & 0x0F, data); break; case XBT_ID_LevelConfig: Client_ReceiveLevelConfig (iob, data); break; default: return XCR_OK; } /* achknowledge reception */ Socket_RegisterWrite (CommSocket (&stream->comm) ); return XCR_OK; } /* HandleSendData */ /* * */ static XBCommResult HandleActivate (XBCommStream *stream, 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; case XBT_ID_StartGame: Client_ReceiveStart (Net_TeleIOB (tele)); break; case XBT_ID_RandomSeed: if (NULL != data && 1 == sscanf (data, "%u", &value) ) { Client_ReceiveRandomSeed (value); } break; case XBT_ID_DgramPort: if (NULL != data && 1 == sscanf (data, "%u", &value) ) { Client_ReceiveDgramPort (Net_TeleIOB (tele), value); } break; case XBT_ID_Sync: Client_ReceiveSync (Net_TeleIOB (tele)); break; case XBT_ID_HostIsIn: Client_ReceiveHostState (Net_TeleIOB (tele), XBTrue); break; case XBT_ID_HostIsOut: Client_ReceiveHostState (Net_TeleIOB (tele), XBFalse); break; case XBT_ID_TeamChange: if (NULL != data && 1 == sscanf (data, "%u", &value) ) { Client_ReceiveTeamState (Net_TeleIOB (tele), value); } break; default: break; } return XCR_OK; } /* HandleSendData */ /* * */ static XBCommResult HandleSpontaneous (XBCommStream *stream, const XBTelegram *tele) { switch (Net_TeleID (tele)) { case XBT_ID_HostDisconnected: Client_ReceiveDisconnect (Net_TeleIOB (tele)); return XCR_OK; default: break; } return XCR_OK; } /* HandleSpontaneous */ /* * handle telegrams from server */ static XBCommResult HandleTelegram (XBCommStream *stream, const XBTelegram *tele) { switch (Net_TeleCOT (tele)) { /* server requests data from client */ case XBT_COT_RequestData: return HandleRequestData (stream, tele); /* server sends data to client */ case XBT_COT_SendData: return HandleSendData (stream, tele); /* server activate command on client */ case XBT_COT_Activate: return HandleActivate (stream, tele); /* server send spontaneous status change */ case XBT_COT_Spontaneous: return HandleSpontaneous (stream, tele); /* unknown cause of transmission */ default: return XCR_Error; } } /* HandleTelegram */ /* * */ static XBCommResult DeleteToServer (XBComm *comm) { /* delete communication */ Stream_CommFinish ((XBCommStream *) comm); /* free memory */ free (comm); /* inform application */ Client_SetDisconnected (); return XCR_OK; } /* DeleteToServer */ /* * */ static void ErrorToServer (XBCommStream *comm) { /* inform application */ Client_NotifyError (); } /* ErrorToServer */ /* * */ XBComm * C2S_CreateComm (const CFGGameHost *cfg) { XBSocket *pSocket; XBCommToServer *toServer; assert (cfg != NULL); /* create connection to server */ pSocket = Net_ConnectInet (cfg->name, cfg->port); if (NULL == pSocket) { return NULL; } /* create communication data structure */ toServer = calloc (1, sizeof (*toServer)); assert (NULL != toServer); /* set values */ Stream_CommInit (&toServer->stream, COMM_ToServer, pSocket, HandleTelegram, ErrorToServer, DeleteToServer); /* that'S all */ return &toServer->stream.comm; } /* CommCreateToServer */ /* * send random seed to client */ void C2S_SendDgramPort (XBComm *comm, unsigned short port) { XBCommStream *stream = (XBCommStream *) comm; char tmp[16]; /* sanity check */ assert (stream != NULL); assert (stream->sndQueue != NULL); /* send seed as ascii */ sprintf (tmp, "%hu", port); /* send data */ Socket_RegisterWrite (CommSocket (&stream->comm)); Net_SendTelegram (stream->sndQueue, Net_CreateTelegram (XBT_COT_Activate, XBT_ID_DgramPort, 0, tmp, strlen (tmp) + 1) ); } /* S2C_SendDgramPort */ /* * request synchronisation with server */ void C2S_Sync (XBComm *comm, XBNetworkEvent event) { XBCommStream *stream = (XBCommStream *) comm; assert (stream != NULL); assert (stream->sndQueue != NULL); Net_SendTelegram (stream->sndQueue, Net_CreateTelegram (XBT_COT_Spontaneous, XBT_ID_Sync, (XBTeleIOB) event, NULL, 0) ); Socket_RegisterWrite (CommSocket (&stream->comm) ); } /* C2S_Sync */ /* * return address of server in dot-represantation */ const char * C2S_ServerName (XBComm *comm) { return Net_RemoteName (comm->socket); } /* C2S_ServerName */ /* * return address of client (local host) in dot-represantation */ const char * C2S_ClientName (XBComm *comm) { return Net_LocalName (comm->socket); } /* C2S_ClientName */ /* * end of file com_to_server.c */