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