1 /*
2 * file com_to_central.c - handle communications with centrals
3 *
4 * $Id: com_to_central.c,v 1.7 2006/02/09 21:21:23 fzago Exp $
5 *
6 * Program XBLAST
7 * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8 * Added by Koen De Raedt for central support
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published
12 * by the Free Software Foundation; either version 2; or (at your option)
13 * any later version
14 *
15 * This program is distributed in the hope that it will be entertaining,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
18 * Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25 #include "xblast.h"
26
27 /*
28 * local types
29 */
30 typedef struct
31 {
32 XBCommStream stream;
33 } XBCommToCentral;
34
35 /*
36 * local variables
37 */
38
39 /*
40 * central sends data
41 */
42 static XBCommResult
HandleDataAvailable(XBCommStream * toCentral,const XBTelegram * tele)43 HandleDataAvailable (XBCommStream * toCentral, const XBTelegram * tele)
44 {
45 const void *data;
46 size_t len;
47 assert (toCentral != NULL);
48 /* get telegramm data */
49 data = Net_TeleData (tele, &len);
50 switch (Net_TeleID (tele)) {
51 case XBT_ID_PlayerConfig:
52 /* Dbg_X2C("receiving player config from central\n"); */
53 User_ReceivePlayerConfig (data);
54 break;
55 case XBT_ID_PID:
56 Dbg_X2C ("receiving pid from central\n");
57 User_ReceivePlayerPID (data);
58 break;
59 default:
60 Dbg_X2C ("unsupported ID received for DataAvailable\n");
61 return User_EventToCentral (XBE2C_InvalidID);;
62 }
63 return XCR_OK;
64 } /* HandleDataAvailable */
65
66 /*
67 * central sends end of data
68 */
69 static XBCommResult
HandleDataNotAvailable(XBCommStream * toCentral,const XBTelegram * tele)70 HandleDataNotAvailable (XBCommStream * toCentral, const XBTelegram * tele)
71 {
72 switch (Net_TeleID (tele)) {
73 case XBT_ID_PlayerConfig:
74 Dbg_X2C ("No more players, disconnecting\n");
75 User_NoMorePlayers ();
76 break;
77 case XBT_ID_PID:
78 break;
79 default:
80 Dbg_X2C ("unsupported ID received for DataNotAvailable\n");
81 return User_EventToCentral (XBE2C_InvalidID);;
82 }
83 return XCR_OK;
84 } /* HandleDataAvailable */
85
86 /*
87 * handle telegrams from central
88 */
89 static XBCommResult
HandleTelegram(XBCommStream * stream,const XBTelegram * tele)90 HandleTelegram (XBCommStream * stream, const XBTelegram * tele)
91 {
92 assert (stream != NULL);
93 switch (Net_TeleCOT (tele)) {
94 /* central sends requested data */
95 case XBT_COT_DataAvailable:
96 return HandleDataAvailable (stream, tele);
97 /* central has not requested data */
98 case XBT_COT_DataNotAvailable:
99 return HandleDataNotAvailable (stream, tele);
100 default:
101 Dbg_X2C ("unsupported CoT received\n");
102 return User_EventToCentral (XBE2C_InvalidCot);;
103 }
104 } /* HandleTelegram */
105
106 /*
107 * delete handler
108 */
109 static XBCommResult
DeleteToCentral(XBComm * comm)110 DeleteToCentral (XBComm * comm)
111 {
112 /* delete stream */
113 Stream_CommFinish ((XBCommStream *) comm);
114 /* delete structure */
115 free (comm);
116 Dbg_X2C ("tcp connection to central removed\n");
117 return XCR_OK;
118 } /* DeleteToCentral */
119
120 /*
121 * handle stream events
122 */
123 static XBBool
EventToCentral(XBCommStream * comm,const XBStreamEvent ev)124 EventToCentral (XBCommStream * comm, const XBStreamEvent ev)
125 {
126 switch (ev) {
127 case XBST_IOREAD:
128 Dbg_X2C ("read error from central\n");
129 return User_EventToCentral (XBE2C_IORead);
130 case XBST_IOWRITE:
131 Dbg_X2C ("write error to central\n");
132 return User_EventToCentral (XBE2C_IOWrite);
133 case XBST_EOF:
134 Dbg_X2C ("eof from central\n");
135 return User_EventToCentral (XBE2C_UnexpectedEOF);
136 case XBST_WAIT:
137 Dbg_X2C ("all data sent to central\n");
138 return User_EventToCentral (XBE2C_StreamWaiting);
139 case XBST_BUSY:
140 /* Dbg_X2C("data waits to be sent to central\n"); */
141 return User_EventToCentral (XBE2C_StreamBusy);
142 case XBST_CLOSE:
143 Dbg_X2C ("connection to central has been removed\n");
144 (void)User_EventToCentral (XBE2C_StreamClosed);
145 return XBFalse;
146 default:
147 Dbg_X2C ("unknown stream event on socket to central, ignoring\n");
148 return XBFalse;
149 }
150 } /* EventToCentral */
151
152 /*
153 * create a tcp connection to central
154 */
155 XBComm *
X2C_CreateComm(const CFGCentralSetup * cfg)156 X2C_CreateComm (const CFGCentralSetup * cfg)
157 {
158 XBSocket *pSocket;
159 XBCommToCentral *toCentral;
160
161 assert (cfg != NULL);
162 /* create connection to server */
163 pSocket = Net_ConnectInet (cfg->name, cfg->port);
164 if (NULL == pSocket) {
165 Dbg_X2C ("failed to create tcp socket\n");
166 return NULL;
167 }
168 Dbg_X2C ("tcp connection to central %s:%u established\n", cfg->name, cfg->port);
169 /* create communication data structure */
170 toCentral = calloc (1, sizeof (*toCentral));
171 assert (NULL != toCentral);
172 /* set values */
173 Stream_CommInit (&toCentral->stream, COMM_ToCentral, pSocket, HandleTelegram, EventToCentral,
174 DeleteToCentral);
175 /* that's all */
176 return &toCentral->stream.comm;
177 } /* CommCreateToServer */
178
179 /**************
180 * local data *
181 **************/
182
183 /*
184 * return remote address in dot-representation
185 */
186 const char *
X2C_CentralName(XBComm * comm)187 X2C_CentralName (XBComm * comm)
188 {
189 return Net_RemoteName (comm->socket);
190 } /* X2C_CentralName */
191
192 /*
193 * return local address in dot-representation
194 */
195 const char *
X2C_LocalName(XBComm * comm)196 X2C_LocalName (XBComm * comm)
197 {
198 return Net_LocalName (comm->socket);
199 } /* X2C_LocalName */
200
201 /**************
202 * queue data *
203 **************/
204
205 /*
206 * query player config from central
207 */
208 void
X2C_QueryPlayerConfig(XBComm * comm)209 X2C_QueryPlayerConfig (XBComm * comm)
210 {
211 XBCommStream *stream = (XBCommStream *) comm;
212
213 /* sanity check */
214 assert (stream != NULL);
215 assert (stream->sndQueue != NULL);
216 /* send data */
217 Socket_RegisterWrite (CommSocket (&stream->comm));
218 Net_SendTelegram (stream->sndQueue,
219 Net_CreateTelegram (XBT_COT_RequestData, XBT_ID_PlayerConfig, 0, NULL, 0));
220 Dbg_X2C ("queued player query to central\n");
221 } /* X2C_QueryPlayerConfig */
222
223 /*
224 * send game config to central
225 */
226 void
X2C_SendPlayerConfig(XBComm * comm,XBAtom atom)227 X2C_SendPlayerConfig (XBComm * comm, XBAtom atom)
228 {
229 XBCommStream *stream = (XBCommStream *) comm;
230
231 /* sanity check */
232 assert (stream != NULL);
233 assert (stream->sndQueue != NULL);
234 /* send database section */
235 Socket_RegisterWrite (CommSocket (&stream->comm));
236 SendPlayerConfig (CT_Local, stream->sndQueue, XBT_COT_SendData, 0, atom, XBTrue);
237 Dbg_X2C ("queued player config to central\n");
238 } /* X2C_SendPlayerConfig */
239
240 /*
241 * send game config to central
242 */
243 void
X2C_SendGameStat(XBComm * comm,int numPlayers,int * PID,int * Score)244 X2C_SendGameStat (XBComm * comm, int numPlayers, int *PID, int *Score)
245 {
246 XBCommStream *stream = (XBCommStream *) comm;
247 char tmp[256];
248 int i;
249 /* sanity check */
250 assert (stream != NULL);
251 assert (stream->sndQueue != NULL);
252 /* queue data */
253 memcpy (tmp, &numPlayers, 4);
254 for (i = 0; i < numPlayers; i++) {
255 memcpy (tmp + 4 + i * 8, PID + i, 4);
256 memcpy (tmp + 8 + i * 8, Score + i, 4);
257 }
258 Socket_RegisterWrite (CommSocket (&stream->comm));
259 Net_SendTelegram (stream->sndQueue,
260 Net_CreateTelegram (XBT_COT_SendData, XBT_ID_GameStat, 0, tmp,
261 4 + numPlayers * 8));
262 Dbg_X2C ("queued game stat to central\n");
263 } /* X2C_SendGameStat */
264
265 /*
266 * send request for disconnect to central
267 */
268 void
X2C_SendDisconnect(XBComm * comm)269 X2C_SendDisconnect (XBComm * comm)
270 {
271 XBCommStream *stream = (XBCommStream *) comm;
272
273 /* inform host about disconnect request */
274 Socket_RegisterWrite (CommSocket (&stream->comm));
275 Net_SendTelegram (stream->sndQueue,
276 Net_CreateTelegram (XBT_COT_Spontaneous, XBT_ID_HostDisconnected, 0, NULL,
277 0));
278 Net_SendTelegram (stream->sndQueue,
279 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_RequestDisconnect, 0, NULL, 0));
280 /* clear the communication, prepare for automatic shutdown */
281 stream->prepFinish = XBTrue;
282 Dbg_X2C ("queued disconnect sequence to central\n");
283 } /* X2C_SendDisconnect */
284
285 /*
286 * end of file com_to_central.c
287 */
288