1 /*
2 * file com_to_client.c - handle communications with clients
3 *
4 * $Id: com_to_client.c,v 1.19 2006/02/09 21:21:23 fzago Exp $
5 *
6 * Program XBLAST
7 * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2; or (at your option)
12 * any later version
13 *
14 * This program is distributed in the hope that it will be entertaining,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include "xblast.h"
25
26 /*
27 * local types
28 */
29 typedef struct
30 {
31 XBCommStream stream;
32 unsigned serial;
33 } XBCommToClient;
34
35 /*
36 * local variables
37 */
38
39 /* streams to clients */
40 static XBCommToClient *commList[MAX_HOSTS] = {
41 /* this entry is never used (server) */
42 NULL,
43 /* up to 5 clients can connect */
44 NULL, NULL, NULL, NULL, NULL,
45 };
46
47 /************
48 * handlers *
49 ************/
50
51 /*
52 * data received from a client
53 */
54 static XBCommResult
HandleDataAvailable(XBCommToClient * toClient,const XBTelegram * tele)55 HandleDataAvailable (XBCommToClient * toClient, const XBTelegram * tele)
56 {
57 const void *data;
58 size_t len;
59
60 assert (toClient != NULL);
61 /* get telegramm data */
62 data = Net_TeleData (tele, &len);
63 switch (Net_TeleID (tele)) {
64 case XBT_ID_GameConfig:
65 Dbg_S2C ("received game config line\n");
66 Server_ReceiveGameConfig (toClient->serial, data);
67 break;
68 case XBT_ID_PlayerConfig:
69 Dbg_S2C ("received player config line\n");
70 Server_ReceivePlayerConfig (toClient->serial, (int)Net_TeleIOB (tele), data);
71 break;
72 default:
73 Dbg_S2C ("received game config line\n");
74 return Server_StreamEvent (toClient->serial, XBSC_IDInvalid) ? XCR_Error : XCR_OK;
75 }
76 return XCR_OK;
77 } /* HandleDataAvailable */
78
79 /*
80 * data not available on client
81 */
82 static XBCommResult
HandleDataNotAvailable(XBCommToClient * toClient,const XBTelegram * tele)83 HandleDataNotAvailable (XBCommToClient * toClient, const XBTelegram * tele)
84 {
85 switch (Net_TeleID (tele)) {
86 case XBT_ID_GameConfig:
87 Dbg_S2C ("host #%u has no game config data!\n", toClient->serial);
88 return Server_StreamEvent (toClient->serial, XBSC_MissingData) ? XCR_Error : XCR_OK;
89 default:
90 Dbg_S2C ("host #%u has no data of unrecognized type!\n", toClient->serial);
91 return Server_StreamEvent (toClient->serial, XBSC_IDInvalid) ? XCR_Error : XCR_OK;
92 }
93 return XCR_OK;
94 } /* HandleDataAvailable */
95
96 /*
97 * received client request
98 */
99 static XBCommResult
HandleActivate(XBCommToClient * toClient,const XBTelegram * tele)100 HandleActivate (XBCommToClient * toClient, const XBTelegram * tele)
101 {
102 const char *data;
103 size_t len;
104 unsigned iob;
105 unsigned value;
106
107 assert (toClient != NULL);
108 assert (tele != NULL);
109 /* get telegramm data */
110 data = Net_TeleData (tele, &len);
111 iob = Net_TeleIOB (tele);
112 switch (Net_TeleID (tele)) {
113 case XBT_ID_DgramPort:
114 /* inform application */
115 if (NULL != data && 1 == sscanf (data, "%u", &value)) {
116 Server_ReceiveDgramPort (toClient->serial, value);
117 Dbg_S2C ("received dgram port ftrom host #%u\n", toClient->serial);
118 }
119 else {
120 Dbg_S2C ("host #%u has no data of unrecognized type!\n", toClient->serial);
121 return Server_StreamEvent (toClient->serial, XBSC_DataInvalid) ? XCR_Error : XCR_OK;
122 }
123 return XCR_OK;
124 case XBT_ID_LevelConfig:
125 Dbg_S2C ("receive level check from host #%u\n", toClient->serial);
126 Server_ReceiveLevelCheck (toClient->serial, iob);
127 return XCR_OK;
128 case XBT_ID_WinnerTeam:
129 Dbg_S2C ("receive winner team from host #%u\n", toClient->serial);
130 Server_ReceiveWinnerTeam (toClient->serial, iob);
131 return XCR_OK;
132 case XBT_ID_HostChangeReq:
133 if (len == 2) {
134 Dbg_S2C ("host #%u requests host state change\n", toClient->serial);
135 Server_ReceiveHostStateReq (toClient->serial, data[0], data[1]);
136 }
137 else {
138 Dbg_S2C ("host #%u sends invalid host request data!\n", toClient->serial);
139 return Server_StreamEvent (toClient->serial, XBSC_DataInvalid) ? XCR_Error : XCR_OK;
140 }
141 return XCR_OK;
142 case XBT_ID_TeamChangeReq:
143 if (len == 3) {
144 Dbg_S2C ("host #%u requests team state change\n", toClient->serial);
145 Server_ReceiveTeamStateReq (toClient->serial, data[0], data[1], data[2]);
146 }
147 else {
148 Dbg_S2C ("host #%u sends invalid team request data!\n", toClient->serial);
149 return Server_StreamEvent (toClient->serial, XBSC_DataInvalid) ? XCR_Error : XCR_OK;
150 }
151 return XCR_OK;
152 default:
153 Dbg_S2C ("unrecognized request from host #%u!\n", toClient->serial);
154 return Server_StreamEvent (toClient->serial, XBSC_IDInvalid) ? XCR_Error : XCR_OK;
155 }
156 return XCR_OK;
157 } /* HandleActivate */
158
159 /*
160 * client sends info
161 */
162 static XBCommResult
HandleSpontaneous(XBCommToClient * toClient,const XBTelegram * tele)163 HandleSpontaneous (XBCommToClient * toClient, const XBTelegram * tele)
164 {
165 const char *data;
166 size_t len;
167 XBTeleIOB iob;
168 XBChat *chat;
169 unsigned value;
170
171 assert (toClient != NULL);
172 data = Net_TeleData (tele, &len);
173 iob = Net_TeleIOB (tele);
174 /* get telegramm data */
175 switch (Net_TeleID (tele)) {
176 case XBT_ID_Sync:
177 Dbg_S2C ("receiving sync from host #%u\n", toClient->serial);
178 Server_ReceiveSync (toClient->serial, iob);
179 return XCR_OK;
180 case XBT_ID_HostChange:
181 if (NULL != data && 1 == sscanf (data, "%u", &value)) {
182 Dbg_S2C ("REMOVE! receiving host change from host #%u\n", toClient->serial);
183 /* Server_ReceiveHostState (toClient->serial, value ); */
184 }
185 return XCR_OK;
186 case XBT_ID_Chat:
187 chat = Chat_UnpackData (data, len, iob);
188 if (NULL != chat) {
189 Dbg_S2C ("receiving chat from host #%u", toClient->serial);
190 Server_ReceiveChat (chat);
191 }
192 else {
193 Dbg_S2C ("invalid chat received from host #%u", toClient->serial);
194 return Server_StreamEvent (toClient->serial, XBSC_IDInvalid) ? XCR_Error : XCR_OK;
195 }
196 return XCR_OK;
197 default:
198 Dbg_S2C ("invalid info received from host #%u", toClient->serial);
199 return Server_StreamEvent (toClient->serial, XBSC_IDInvalid) ? XCR_Error : XCR_OK;
200 }
201 return XCR_OK;
202 } /* HandleSpontaneous */
203
204 /*
205 * handle telegrams from server
206 */
207 static XBCommResult
HandleTelegram(XBCommStream * stream,const XBTelegram * tele)208 HandleTelegram (XBCommStream * stream, const XBTelegram * tele)
209 {
210 XBCommToClient *toClient = (XBCommToClient *) stream;
211
212 assert (toClient != NULL);
213 switch (Net_TeleCOT (tele)) {
214 /* client sends requested data */
215 case XBT_COT_DataAvailable:
216 return HandleDataAvailable (toClient, tele);
217 /* client has not requested data */
218 case XBT_COT_DataNotAvailable:
219 return HandleDataNotAvailable (toClient, tele);
220 /* client command has arrived */
221 case XBT_COT_Activate:
222 return HandleActivate (toClient, tele);
223 /* client message has arrived */
224 case XBT_COT_Spontaneous:
225 return HandleSpontaneous (toClient, tele);
226 default:
227 Dbg_S2C ("invalid cot received from host #%u", toClient->serial);
228 return Server_StreamEvent (toClient->serial, XBSC_COTInvalid) ? XCR_Error : XCR_OK;
229 }
230 return XCR_OK;
231 } /* HandleTelegram */
232
233 /*
234 * delete handler: triggered by eof and parse errors
235 * always called from com_base.c
236 */
237 static XBCommResult
DeleteToClient(XBComm * comm)238 DeleteToClient (XBComm * comm)
239 {
240 XBCommToClient *toClient = (XBCommToClient *) comm;
241 assert (comm != NULL);
242 /* unmark client */
243 commList[toClient->serial] = NULL;
244 /* clean up */
245 Stream_CommFinish (&toClient->stream);
246 free (comm);
247 return XCR_OK;
248 } /* DeleteToClient */
249
250 /*
251 * handle stream events
252 */
253 static XBBool
EventToClient(XBCommStream * comm,const XBStreamEvent ev)254 EventToClient (XBCommStream * comm, const XBStreamEvent ev)
255 {
256 XBCommToClient *toClient = (XBCommToClient *) comm;
257 XBServerConstants code;
258 assert (toClient != NULL);
259 switch (ev) {
260 case XBST_IOREAD:
261 code = XBSC_IOError;
262 break;
263 case XBST_IOWRITE:
264 code = XBSC_IOError;
265 break;
266 case XBST_EOF:
267 code = XBSC_UnexpectedEOF;
268 break;
269 case XBST_WAIT:
270 code = XBSC_StreamWaiting;
271 break;
272 case XBST_BUSY:
273 code = XBSC_StreamBusy;
274 break;
275 case XBST_CLOSE:
276 code = XBSC_StreamClosed;
277 break;
278 default:
279 return XBFalse;
280 }
281 return Server_StreamEvent (toClient->serial, code);
282 } /* EventToClient */
283
284 /***************
285 * constructor *
286 ***************/
287
288 /*
289 * create stream to client on valid socket
290 */
291 XBComm *
S2C_CreateComm(const XBSocket * socket)292 S2C_CreateComm (const XBSocket * socket)
293 {
294 unsigned serial;
295 XBSocket *pSocket;
296 XBCommToClient *toClient;
297
298 assert (socket != NULL);
299 Dbg_S2C ("client connected to listen socket!\n");
300 /* get free serial */
301 for (serial = 1; serial < MAX_HOSTS; serial++) {
302 if (NULL == commList[serial]) {
303 break;
304 }
305 }
306 if (serial >= MAX_HOSTS) {
307 Dbg_S2C ("failed to assign valid id, disconnecting\n");
308 return NULL;
309 }
310 Dbg_S2C ("Assigned id #%u\n", serial);
311 /* create listen socket */
312 pSocket = Net_Accept (socket);
313 if (NULL == pSocket) {
314 Dbg_S2C ("failed to create reply socket\n");
315 return NULL;
316 }
317 /* create communication data structure */
318 toClient = calloc (1, sizeof (XBCommToClient));
319 assert (NULL != toClient);
320 /* set values */
321 Stream_CommInit (&toClient->stream, COMM_ToClient, pSocket, HandleTelegram, EventToClient,
322 DeleteToClient);
323 toClient->serial = serial;
324 /* add to internal list */
325 commList[serial] = toClient;
326 Dbg_S2C ("stream to host #%u accepted\n", serial);
327 /* inform application */
328 Server_Accept (serial, Net_RemoteName (pSocket), Net_RemotePort (pSocket));
329 /* that's all */
330 return &toClient->stream.comm;
331 } /* S2C_CreateComm */
332
333 /******************
334 * get local data *
335 ******************/
336
337 /*
338 * check if client is connected
339 */
340 XBBool
S2C_Connected(unsigned id)341 S2C_Connected (unsigned id)
342 {
343 assert (id > 0);
344 assert (id < MAX_HOSTS);
345 return (commList[id] != NULL);
346 } /* S2C_Connected */
347
348 /*
349 * output all connected clients
350 */
351 void
S2C_ShowConnected(void)352 S2C_ShowConnected (void)
353 {
354 unsigned id;
355 Dbg_S2C ("Connected client id's: ");
356 for (id = 1; id < MAX_HOSTS; id++) {
357 if (S2C_Connected (id)) {
358 Dbg_Out ("%i ", id);
359 }
360 }
361 Dbg_Out ("\n");
362 } /* S2C_Connected */
363
364 /*
365 * hostname of client
366 */
367 const char *
S2C_HostName(unsigned id)368 S2C_HostName (unsigned id)
369 {
370 assert (id > 0);
371 assert (id <= MAX_HOSTS);
372 assert (commList[id] != NULL);
373 /* get name from socket */
374 return Net_RemoteName (commList[id]->stream.comm.socket);
375 } /* S2C_HostName */
376
377 /*
378 * hostname of client
379 */
380 const char *
S2C_LocalName(unsigned id)381 S2C_LocalName (unsigned id)
382 {
383 assert (id > 0);
384 assert (id <= MAX_HOSTS);
385 assert (commList[id] != NULL);
386 /* get name from socket */
387 return Net_LocalName (commList[id]->stream.comm.socket);
388 } /* S2C_LocalName */
389
390 /**************
391 * queue data *
392 **************/
393
394 /*
395 * queue game config to client
396 */
397 void
S2C_SendGameConfig(unsigned id,unsigned hostID,XBAtom atom)398 S2C_SendGameConfig (unsigned id, unsigned hostID, XBAtom atom)
399 {
400 assert (id > 0);
401 assert (id <= MAX_HOSTS);
402 assert (commList[id] != NULL);
403 assert (commList[id]->stream.sndQueue != NULL);
404 /* send database section */
405 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
406 SendGameConfig (CT_Remote, commList[id]->stream.sndQueue, XBT_COT_SendData, (XBTeleIOB) hostID,
407 atom);
408 Dbg_S2C ("queued game config to host #%u\n", id);
409 } /* S2C_SendGameConfig */
410
411 /*
412 * queue player config to client
413 */
414 void
S2C_SendPlayerConfig(unsigned id,unsigned hostId,int player,XBAtom atom)415 S2C_SendPlayerConfig (unsigned id, unsigned hostId, int player, XBAtom atom)
416 {
417 XBTeleIOB iob;
418
419 assert (id > 0);
420 assert (id < MAX_HOSTS);
421 assert (commList[id] != NULL);
422 assert (commList[id]->stream.sndQueue != NULL);
423 /* convert id and player to iob */
424 iob = ((XBTeleIOB) hostId << 4) + (XBTeleIOB) player;
425 /* send database section */
426 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
427 SendPlayerConfig (CT_Remote, commList[id]->stream.sndQueue, XBT_COT_SendData, iob, atom,
428 XBFalse);
429 Dbg_S2C ("queued single player config to host #%u\n", id);
430 } /* S2C_SendPlayerConfig */
431
432 /*
433 * queue dgram port to client
434 */
435 void
S2C_SendDgramPort(unsigned id,unsigned short port)436 S2C_SendDgramPort (unsigned id, unsigned short port)
437 {
438 char tmp[16];
439
440 /* sanity check */
441 assert (id > 0);
442 assert (id <= MAX_HOSTS);
443 assert (commList[id] != NULL);
444 assert (commList[id]->stream.sndQueue != NULL);
445 /* send seed as ascii */
446 sprintf (tmp, "%hu", port);
447 /* send data */
448 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
449 Net_SendTelegram (commList[id]->stream.sndQueue,
450 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_DgramPort, id, tmp,
451 strlen (tmp) + 1));
452 Dbg_S2C ("queued dgram port to host #%u\n", id);
453 } /* S2C_SendDgramPort */
454
455 /*
456 * queue game config request to client
457 */
458 void
S2C_QueryGameConfig(unsigned id)459 S2C_QueryGameConfig (unsigned id)
460 {
461 assert (id > 0);
462 assert (id < MAX_HOSTS);
463 assert (commList[id] != NULL);
464 assert (commList[id]->stream.sndQueue != NULL);
465 /* send request */
466 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
467 Net_SendTelegram (commList[id]->stream.sndQueue,
468 Net_CreateTelegram (XBT_COT_RequestData, XBT_ID_GameConfig, 0, NULL, 0));
469 Dbg_S2C ("queued game config request to host #%u\n", id);
470 } /* S2C_QueryGameConfig */
471
472 /*
473 * queue player config request to client
474 */
475 void
S2C_QueryPlayerConfig(unsigned id,int player)476 S2C_QueryPlayerConfig (unsigned id, int player)
477 {
478 assert (id > 0);
479 assert (id < MAX_HOSTS);
480 assert (commList[id] != NULL);
481 assert (commList[id]->stream.sndQueue != NULL);
482 assert (player < NUM_LOCAL_PLAYER);
483 /* send request */
484 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
485 Net_SendTelegram (commList[id]->stream.sndQueue,
486 Net_CreateTelegram (XBT_COT_RequestData, XBT_ID_PlayerConfig,
487 (XBTeleIOB) player, NULL, 0));
488 Dbg_S2C ("queued player config request to host #%u\n", id);
489 } /* S2C_QueryPlayerConfig */
490
491 /*
492 * queue host state to client
493 */
494 void
S2C_SendHostState(unsigned id,unsigned hostID,unsigned state)495 S2C_SendHostState (unsigned id, unsigned hostID, unsigned state)
496 {
497 char tmp[16];
498
499 assert (id > 0);
500 assert (id < MAX_HOSTS);
501 assert (commList[id] != NULL);
502 sprintf (tmp, "%hu", state);
503 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
504 Net_SendTelegram (commList[id]->stream.sndQueue,
505 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_HostChange, (XBTeleIOB) hostID,
506 tmp, strlen (tmp) + 1));
507 Dbg_S2C ("queued host state to host #%u:%u to host #%u\n", hostID, state, id);
508 } /* S2C_SendHostState */
509
510 /*
511 * queue team state to client
512 */
513 void
S2C_SendTeamState(unsigned id,unsigned host,unsigned player,XBTeamState team)514 S2C_SendTeamState (unsigned id, unsigned host, unsigned player, XBTeamState team)
515 {
516 char tmp[16];
517 unsigned hpid;
518 assert (id > 0);
519 assert (id < MAX_HOSTS);
520 assert (commList[id] != NULL);
521 /* version <2_10_2 cannot handle XBTS_Out, send invalid */
522 if (team == XBTS_Out && !Version_AtLeast (id, &Ver_2_10_2)) {
523 team = XBTS_Invalid;
524 }
525 sprintf (tmp, "%hu", team);
526 hpid = (host * NUM_LOCAL_PLAYER) + (player & 0xFF);
527 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
528 Net_SendTelegram (commList[id]->stream.sndQueue,
529 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_TeamChange, (XBTeleIOB) hpid,
530 tmp, strlen (tmp) + 1));
531 Dbg_S2C ("queued team state to host #%u\n", id);
532 } /* S2C_SendTeamState */
533
534 /*
535 * queue host state request to client
536 */
537 void
S2C_SendHostStateReq(unsigned id,unsigned who,unsigned hostID,unsigned state)538 S2C_SendHostStateReq (unsigned id, unsigned who, unsigned hostID, unsigned state)
539 {
540 unsigned char tmp[2];
541 assert (id > 0);
542 assert (id < MAX_HOSTS);
543 assert (commList[id] != NULL);
544 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
545 tmp[0] = hostID & 0xff;
546 tmp[1] = state & 0xff;
547 Net_SendTelegram (commList[id]->stream.sndQueue,
548 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_HostChangeReq,
549 (XBTeleIOB) who & 0xFF, tmp, sizeof (tmp)));
550 Dbg_S2C ("queued host state request #%u:#%u->%u to host #%u\n", who, hostID, state, id);
551 } /* S2C_SendHostStateReq */
552
553 /*
554 * queue team state to client
555 */
556 void
S2C_SendTeamStateReq(unsigned id,unsigned who,unsigned hostID,unsigned player,XBTeamState team)557 S2C_SendTeamStateReq (unsigned id, unsigned who, unsigned hostID, unsigned player, XBTeamState team)
558 {
559 unsigned char tmp[3];
560 assert (id > 0);
561 assert (id < MAX_HOSTS);
562 assert (commList[id] != NULL);
563 /* version < 2_10_2 cannot handle XBTS_Out, send invalid */
564 if (team == XBTS_Out && !Version_AtLeast (id, &Ver_2_10_2)) {
565 team = XBTS_Invalid;
566 }
567 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
568 tmp[0] = hostID & 0xff;
569 tmp[1] = player & 0xff;
570 tmp[2] = team & 0xff;
571 Net_SendTelegram (commList[id]->stream.sndQueue,
572 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_TeamChangeReq,
573 (XBTeleIOB) who & 0xFF, tmp, sizeof (tmp)));
574 Dbg_S2C ("queued team state request to host #%u:#%u(%u)->%u to host #%u\n", who, hostID, player,
575 team, id);
576
577 } /* S2C_SendTeamStateReq */
578
579 /*
580 * send a chat line to th:tp from fh:fp
581 */
582 void
S2C_SendChat(unsigned id,XBChat * chat)583 S2C_SendChat (unsigned id, XBChat * chat)
584 {
585 unsigned iob;
586 char *data;
587 size_t len;
588 /* sanity check */
589 assert (id > 0);
590 assert (id < MAX_HOSTS);
591 assert (commList[id] != NULL);
592 assert (chat != NULL);
593 /* pack chat data */
594 len = Chat_PackData (chat, &data, &iob);
595 /* prepare for writing */
596 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
597 Net_SendTelegram (commList[id]->stream.sndQueue,
598 Net_CreateTelegram (XBT_COT_SendData, XBT_ID_Chat, iob, data, len));
599 Dbg_S2C ("queued chat to host #%u\n", id);
600 } /* S2C_SendChat */
601
602 /*
603 * queue disconnect message to client
604 */
605 void
S2C_HostDisconnected(unsigned id,unsigned hostID)606 S2C_HostDisconnected (unsigned id, unsigned hostID)
607 {
608 assert (id > 0);
609 assert (id < MAX_HOSTS);
610 assert (commList[id] != NULL);
611
612 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
613 Net_SendTelegram (commList[id]->stream.sndQueue,
614 Net_CreateTelegram (XBT_COT_Spontaneous, XBT_ID_HostDisconnected, hostID,
615 NULL, 0));
616 Dbg_S2C ("queued disconnect info to host #%u\n", id);
617 } /* S2C_HostDisconnected */
618
619 /*
620 * queue request for disconnect to given client
621 */
622 void
S2C_Disconnect(unsigned id)623 S2C_Disconnect (unsigned id)
624 {
625 assert (id > 0);
626 assert (id < MAX_HOSTS);
627 assert (commList[id] != NULL);
628
629 /* inform host about disconnect request */
630 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
631 Net_SendTelegram (commList[id]->stream.sndQueue,
632 Net_CreateTelegram (XBT_COT_Spontaneous, XBT_ID_HostDisconnected, 0, NULL,
633 0));
634 Net_SendTelegram (commList[id]->stream.sndQueue,
635 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_RequestDisconnect, 0, NULL, 0));
636 Dbg_S2C ("queued disconnect sequence to host #%u\n", id);
637 /* free slot, prepare to finish */
638 commList[id]->stream.prepFinish = XBTrue;
639 commList[id] = NULL;
640 } /* S2C_Disconnect */
641
642 /*
643 * queue start game signal to client
644 */
645 void
S2C_StartGame(unsigned id)646 S2C_StartGame (unsigned id)
647 {
648 assert (id > 0);
649 assert (id < MAX_HOSTS);
650 assert (commList[id] != NULL);
651
652 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
653 Net_SendTelegram (commList[id]->stream.sndQueue,
654 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_StartGame, (XBTeleIOB) id, NULL,
655 0));
656 Dbg_S2C ("queued start of game to host #%u\n", id);
657 } /* S2C_StartGame */
658
659 /*
660 * queue sync to client
661 */
662 void
S2C_Sync(unsigned id,XBNetworkEvent event)663 S2C_Sync (unsigned id, XBNetworkEvent event)
664 {
665 assert (id > 0);
666 assert (id < MAX_HOSTS);
667 assert (commList[id] != NULL);
668
669 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
670 Net_SendTelegram (commList[id]->stream.sndQueue,
671 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_Sync, (XBTeleIOB) event, NULL,
672 0));
673 Dbg_S2C ("queued sync #%u to host #%u\n", event, id);
674 } /* S2C_Sync */
675
676 /*
677 * queue random seed to client
678 */
679 void
S2C_SendRandomSeed(unsigned id,unsigned seed)680 S2C_SendRandomSeed (unsigned id, unsigned seed)
681 {
682 char tmp[16];
683
684 /* sanity check */
685 assert (id > 0);
686 assert (id <= MAX_HOSTS);
687 assert (commList[id] != NULL);
688 assert (commList[id]->stream.sndQueue != NULL);
689 /* send seed as ascii */
690 sprintf (tmp, "%u", seed);
691 /* send data */
692 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
693 Net_SendTelegram (commList[id]->stream.sndQueue,
694 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_RandomSeed, 0, tmp,
695 strlen (tmp) + 1));
696 Dbg_S2C ("queued random seed to host #%u\n", id);
697 } /* S2C_SendRandomSeed */
698
699 /*
700 * queue level data to client
701 */
702 void
S2C_SendLevelConfig(unsigned id,const DBRoot * level)703 S2C_SendLevelConfig (unsigned id, const DBRoot * level)
704 {
705 assert (id > 0);
706 assert (id <= MAX_HOSTS);
707 assert (commList[id] != NULL);
708 assert (commList[id]->stream.sndQueue != NULL);
709 /* send database section */
710 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
711 SendLevelConfig (commList[id]->stream.sndQueue, XBT_COT_SendData, level);
712 Dbg_S2C ("queued level config to host #%u\n", id);
713 } /* S2C_SendLevelConfig */
714
715 /*
716 * queue level activation to client
717 */
718 void
S2C_SendLevelActivate(unsigned id)719 S2C_SendLevelActivate (unsigned id)
720 {
721 assert (id > 0);
722 assert (id < MAX_HOSTS);
723 assert (commList[id] != NULL);
724 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
725 Net_SendTelegram (commList[id]->stream.sndQueue,
726 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_LevelConfig, (XBTeleIOB) 1, NULL,
727 0));
728 Dbg_S2C ("queued level activation to host #%u\n", id);
729 } /* S2C_SendLevelActivate */
730
731 /*
732 * queue level reset to client
733 */
734 void
S2C_SendLevelReset(unsigned id)735 S2C_SendLevelReset (unsigned id)
736 {
737 assert (id > 0);
738 assert (id < MAX_HOSTS);
739 assert (commList[id] != NULL);
740
741 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
742 Net_SendTelegram (commList[id]->stream.sndQueue,
743 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_LevelConfig, (XBTeleIOB) 0, NULL,
744 0));
745 Dbg_S2C ("queued level reset to host #%u\n", id);
746 } /* S2C_SendLevelReset */
747
748 /*
749 * queue async notification to client
750 */
751 void
S2C_SendLevelAsync(unsigned id)752 S2C_SendLevelAsync (unsigned id)
753 {
754 XBNetworkEvent ev = XBNW_SyncLevelResult;
755 assert (id > 0);
756 assert (id < MAX_HOSTS);
757 assert (commList[id] != NULL);
758
759 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
760 Net_SendTelegram (commList[id]->stream.sndQueue,
761 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_Async, (XBTeleIOB) ev, NULL, 0));
762 Dbg_S2C ("queued level async to host #%u\n", id);
763 } /* S2C_SendLevelAsync */
764
765 /*
766 * queue level sync to client
767 */
768 void
S2C_SendLevelSync(unsigned id)769 S2C_SendLevelSync (unsigned id)
770 {
771 XBNetworkEvent ev = XBNW_SyncLevelResult;
772 assert (id > 0);
773 assert (id < MAX_HOSTS);
774 assert (commList[id] != NULL);
775
776 Socket_RegisterWrite (CommSocket (&commList[id]->stream.comm));
777 Net_SendTelegram (commList[id]->stream.sndQueue,
778 Net_CreateTelegram (XBT_COT_Activate, XBT_ID_Sync, (XBTeleIOB) ev, NULL, 0));
779 Dbg_S2C ("queued level sync to host #%u\n", id);
780 } /* S2C_SendLevelSync */
781
782 /*
783 * end of file com_to_client.c
784 */
785