1 /*
2  *   XFrisk - The classic board game for X
3  *   Copyright (C) 1993-1999 Elan Feingold (elan@aetherworks.com)
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  *   $Id: network.c,v 1.6 1999/12/26 15:06:09 morphy Exp $
20  *
21  *   $Log: network.c,v $
22  *   Revision 1.6  1999/12/26 15:06:09  morphy
23  *   Doxygen comments
24  *   Added static qualifier to local functions
25  *   Miscellaneous editorial changes
26  *
27  */
28 
29 /**
30  * Messaging interface to/from the network.
31  */
32 
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netdb.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 
42 #include "riskgame.h"
43 #include "types.h"
44 #include "network.h"
45 #include "debug.h"
46 
47 /* Useful macro */
48 #define ReturnIfError(foo) if ((foo) <= 0) return (-1);
49 
50 /* Local prototypes */
51 static Int32 _NET_SendString(Int32 iSocket, CString strCString);
52 static Int32 _NET_SendLong(Int32 iSocket, Int32 iLong);
53 static Int32 _NET_RecvString(Int32 iSocket, CString *pstrCString);
54 static Int32 _NET_SocketRead(Int32 iSocket, void *ptr, Int32 iNumBytes);
55 static Int32 _NET_SocketWrite(Int32 iSocket, void *ptr, Int32 iNumBytes);
56 static Int32 _NET_RecvLong(Int32 iSocket, Int32 *piLong);
57 
58 /* Private to this routine */
59 static char strLogging[1024];
60 
61 
62 /**
63  * Send a message to the given socket, field by field.
64  *
65  * \bug void pointer
66  * \bug massive switch - case construct
67  *
68  * \b History:
69  * \arg 01.24.94  ESF  Created
70  * \arg 01.28.94  ESF  Added strFrom in MSG_MESSAGEPACKET.
71  * \arg 03.04.94  ESF  Changed MSG_UPDATE mesage.
72  * \arg 03.05.94  ESF  Added MSG_ENTERSTATE for fault tolerance.
73  * \arg 03.28.94  ESF  Added MSG_DEADPLAYER & MSG_ENDOFGAME.
74  * \arg 03.28.94  ESF  Changed MSG_REQUESTCARDS to ...CARD.
75  * \arg 03.29.94  ESF  Changed MSG_UPDATECARDS to MSG_EXCHANGECARDS.
76  * \arg 03.29.94  ESF  Changed uiReply to be an Int32.
77  * \arg 04.11.94  ESF  Added a player parameter to MSG_CARDPACKET.
78  * \arg 04.11.94  ESF  Added a killer paramter to MSG_DEADPLAYER.
79  * \arg 05.03.94  ESF  Added MSG_OBJ*UPDATE msgs.
80  * \arg 05.03.94  ESF  Removed MSG_REGISTERPLAYER and MSG_UPDATEARMIES.
81  * \arg 05.05.94  ESF  Added MSG_OBJ* msgs.
82  * \arg 05.12.94  ESF  Removed MSG_OBJ* msgs and added GAME messages.
83  * \arg 05.12.94  ESF  Added MSG_DEREGISTERCLIENT.
84  * \arg 05.12.94  ESF  Added MSG_DELETEMSGDST.
85  * \arg 05.13.94  ESF  Added MSG_STARTREGISTRATION.
86  * \arg 05.15.94  ESF  Added MSG_[FREE|ALLOC]PLAYER
87  * \arg 05.15.94  ESF  Removed MSG_DEADPLAYER.
88  * \arg 05.17.94  ESF  Added MSG_NETMESSAGE.
89  * \arg 07.27.94  ESF  Removed MSG_STARTREGISTRATION.
90  * \arg 07.31.94  ESF  Added MSG_NETPOPUP.
91  * \arg 08.03.94  ESF  Fixed to return error message.
92  * \arg 08.28.94  ESF  Added MSG_POPUPREGISTERBOX.
93  * \arg 09.31.94  ESF  Changed MSG_ENDOFGAME to take a string parameter.
94  * \arg 10.29.94  ESF  Added MSG_DICEROLL.
95  * \arg 10.30.94  ESF  Added MSG_PLACENOTIFY.
96  * \arg 10.30.94  ESF  Added MSG_ATTACKNOTIFY.
97  * \arg 10.30.94  ESF  Added MSG_MOVENOTIFY.
98  * \arg 01.17.95  ESF  Removed MSG_DELETEMSGDST.
99  * \arg 02.21.95  ESF  Added MSG_HELLO, MSG_VERSION.
100  * \arg 02.21.95  ESF  Modified MSG_REGISTERCLIENT to include type of client.
101  * \arg 02.23.95  ESF  Added MSG_OLDREGISTERCLIENT for backwards compatibility.
102  * \arg 02.23.95  ESF  Added MSG_SPECIESIDENT.
103  * \arg 24.08.95  JC   Added MSG_MISSION.
104  * \arg 28.08.95  JC   Added MSG_ENDOFMISSION and MSG_VICTORY.
105  * \arg 30.08.95  JC   Added MSG_FORCEEXCHANGECARDS.
106  */
NET_SendMessage(Int32 iSocket,Int32 iMessType,void * pvMessage)107 Int32 NET_SendMessage(Int32 iSocket, Int32 iMessType, void *pvMessage)
108 {
109   Int32 i;
110 
111   /* Send the message ID */
112   ReturnIfError(_NET_SendLong(iSocket, (Int32)iMessType));
113 
114   switch(iMessType)
115     {
116     case MSG_OLDREGISTERCLIENT:
117       {
118 	MsgOldRegisterClient *pmsgMess = (MsgOldRegisterClient *)pvMessage;
119 
120 	ReturnIfError(_NET_SendString(iSocket, pmsgMess->strClientAddress));
121       }
122       break;
123 
124     case MSG_REGISTERCLIENT:
125       {
126 	MsgRegisterClient *pmsgMess = (MsgRegisterClient *)pvMessage;
127 
128 	ReturnIfError(_NET_SendString(iSocket, pmsgMess->strClientAddress));
129 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iClientType));
130       }
131       break;
132 
133     case MSG_EXCHANGECARDS:
134       {
135 	MsgExchangeCards *pmsgMess = (MsgExchangeCards *)pvMessage;
136 
137 	for(i=0; i!=3; i++)
138 	  ReturnIfError(_NET_SendLong(iSocket, (Int32)pmsgMess->piCards[i]));
139       }
140       break;
141 
142     case MSG_CARDPACKET:
143       {
144 	MsgCardPacket *pmsgMess = (MsgCardPacket *)pvMessage;
145 
146 	ReturnIfError(_NET_SendLong(iSocket, (Int32)pmsgMess->iPlayer));
147 	ReturnIfError(_NET_SendLong(iSocket, (Int32)pmsgMess->cdCard));
148       }
149       break;
150 
151     case MSG_REPLYPACKET:
152       {
153 	MsgReplyPacket *pmsgMess = (MsgReplyPacket *)pvMessage;
154 
155 	ReturnIfError(_NET_SendLong(iSocket, (Int32)pmsgMess->iReply));
156       }
157       break;
158 
159     case MSG_SENDMESSAGE:
160       {
161 	MsgSendMessage *pmsgMess = (MsgSendMessage *)pvMessage;
162 
163 	ReturnIfError(_NET_SendString(iSocket, pmsgMess->strMessage));
164 	ReturnIfError(_NET_SendString(iSocket, pmsgMess->strDestination));
165       }
166       break;
167 
168     case MSG_MESSAGEPACKET:
169       {
170 	MsgMessagePacket *pmsgMess = (MsgMessagePacket *)pvMessage;
171 
172 	ReturnIfError(_NET_SendString(iSocket, pmsgMess->strMessage));
173 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iFrom));
174 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iTo));
175       }
176       break;
177 
178     case MSG_TURNNOTIFY:
179       {
180 	MsgTurnNotify *pmsgMess = (MsgTurnNotify *)pvMessage;
181 
182 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iPlayer));
183 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iClient));
184       }
185       break;
186 
187     case MSG_CLIENTIDENT:
188       {
189 	MsgClientIdent *pmsgMess = (MsgClientIdent *)pvMessage;
190 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iClientID));
191       }
192       break;
193 
194     case MSG_REQUESTCARD:
195       {
196 	MsgRequestCard *pmsgMess = (MsgRequestCard *)pvMessage;
197 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iPlayer));
198       }
199       break;
200 
201     case MSG_ENTERSTATE:
202       {
203 	MsgEnterState *pmsgMess = (MsgEnterState *)pvMessage;
204 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iState));
205       }
206       break;
207 
208     case MSG_OBJSTRUPDATE:
209       {
210 	MsgObjStrUpdate *pmsgMess = (MsgObjStrUpdate *)pvMessage;
211 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iField));
212 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iIndex1));
213 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iIndex2));
214 	ReturnIfError(_NET_SendString(iSocket, pmsgMess->strNewValue));
215       }
216       break;
217 
218     case MSG_OBJINTUPDATE:
219       {
220 	MsgObjIntUpdate *pmsgMess = (MsgObjIntUpdate *)pvMessage;
221 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iField));
222 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iIndex1));
223 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iIndex2));
224 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iNewValue));
225       }
226       break;
227 
228     case MSG_FREEPLAYER:
229       {
230 	MsgFreePlayer *pmsgMess = (MsgFreePlayer *)pvMessage;
231 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iPlayer));
232       }
233       break;
234 
235     /* These happen to be identical, so we can lump them. */
236     case MSG_NETMESSAGE:
237     case MSG_NETPOPUP:
238       {
239 	MsgNetMessage *pmsgMess = (MsgNetMessage *)pvMessage;
240 	ReturnIfError(_NET_SendString(iSocket, pmsgMess->strMessage));
241       }
242       break;
243 
244     case MSG_ENDOFMISSION:
245       {
246 	MsgEndOfMission *pmsgMess = (MsgEndOfMission *)pvMessage;
247 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iWinner));
248 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iTyp));
249 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iNum1));
250 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iNum2));
251       }
252       break;
253 
254     case MSG_VICTORY:
255       {
256 	MsgVictory *pmsgMess = (MsgVictory *)pvMessage;
257 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iWinner));
258       }
259       break;
260 
261     case MSG_DICEROLL:
262       {
263 	MsgDiceRoll *pmsgMess = (MsgDiceRoll *)pvMessage;
264 
265 	for (i=0; i!=3; i++)
266 	  ReturnIfError(_NET_SendLong(iSocket, pmsgMess->pAttackDice[i]));
267 
268 	for (i=0; i!=3; i++)
269 	  ReturnIfError(_NET_SendLong(iSocket, pmsgMess->pDefendDice[i]));
270 
271 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iDefendingPlayer));
272       }
273       break;
274 
275     case MSG_PLACENOTIFY:
276       {
277 	MsgPlaceNotify *pmsgMess = (MsgPlaceNotify *)pvMessage;
278 
279 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iCountry));
280       }
281       break;
282 
283     case MSG_ATTACKNOTIFY:
284       {
285 	MsgAttackNotify *pmsgMess = (MsgAttackNotify *)pvMessage;
286 
287 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iSrcCountry));
288 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iDstCountry));
289       }
290       break;
291 
292     case MSG_MOVENOTIFY:
293       {
294 	MsgMoveNotify *pmsgMess = (MsgMoveNotify *)pvMessage;
295 
296 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iSrcCountry));
297 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iDstCountry));
298       }
299       break;
300 
301     case MSG_VERSION:
302       {
303 	MsgVersion *pmsgMess = (MsgVersion *)pvMessage;
304 
305 	ReturnIfError(_NET_SendString(iSocket, pmsgMess->strVersion));
306       }
307       break;
308 
309     case MSG_SPECIESIDENT:
310       {
311 	MsgSpeciesIdent *pmsgMess = (MsgSpeciesIdent *)pvMessage;
312 
313 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iSpeciesID));
314       }
315       break;
316 
317     case MSG_FORCEEXCHANGECARDS:
318       {
319 	MsgForceExchangeCards *pmsgMess = (MsgForceExchangeCards *)pvMessage;
320 
321 	ReturnIfError(_NET_SendLong(iSocket, pmsgMess->iPlayer));
322       }
323 
324     case MSG_EXIT:
325     case MSG_STARTGAME:
326     case MSG_ENDTURN:
327     case MSG_DEREGISTERCLIENT:
328     case MSG_ALLOCPLAYER:
329     case MSG_POPUPREGISTERBOX:
330     case MSG_HELLO:
331     case MSG_MISSION:
332     case MSG_ENDOFGAME:
333       /* No parameters */
334       break;
335 
336     default:
337       printf("NETWORK: Illegal message!\n");
338     }
339 
340   return (1);
341 }
342 
343 
344 /**
345  * Receive one message from the network, field by field.
346  *
347  * \bug pointer to void pointer
348  * \bug massive switch - case construct
349  *
350  * \b History:
351  * \arg 01.24.94  ESF  Created.
352  * \arg 01.27.94  ESF  Fixed bug in MSG_MESSAGEPACKET case.
353  * \arg 01.28.94  ESF  Added strFrom in MSG_MESSAGEPACKET.
354  * \arg 03.04.94  ESF  Changed _UPDATE mesage.
355  * \arg 03.05.94  ESF  Added _ENTERSTATE for fault tolerance.
356  * \arg 03.28.94  ESF  Added MSG_DEADPLAYER & MSG_ENDOFGAME.
357  * \arg 03.28.94  ESF  Changed MSG_REQUESTCARDS to ...CARD.
358  * \arg 03.29.94  ESF  Changed MSG_UPDATECARDS to MSG_EXCHANGECARDS.
359  * \arg 03.29.94  ESF  Changed uiReply to be an Int32.
360  * \arg 04.11.94  ESF  Added a player parameter to MSG_CARDPACKET.
361  * \arg 04.11.94  ESF  Added a killer paramter to MSG_DEADPLAYER.
362  * \arg 05.03.94  ESF  Added MSG_OBJ*UPDATE msgs.
363  * \arg 05.03.94  ESF  Removed MSG_REGISTERPLAYER and MSG_UPDATEARMIES.
364  * \arg 05.05.94  ESF  Added MSG_OBJ* msgs.
365  * \arg 05.12.94  ESF  Removed MSG_OBJ* msgs and added GAME messages.
366  * \arg 05.12.94  ESF  Added MSG_DEREGISTERCLIENT.
367  * \arg 05.12.94  ESF  Added MSG_DELETEMSGDST.
368  * \arg 05.13.94  ESF  Added MSG_STARTREGISTRATION.
369  * \arg 05.15.94  ESF  Added MSG_[FREE|ALLOC]PLAYER
370  * \arg 05.15.94  ESF  Removed MSG_DEADPLAYER.
371  * \arg 05.17.94  ESF  Added MSG_NETMESSAGE.
372  * \arg 07.27.94  ESF  Removed MSG_STARTREGISTRATION.
373  * \arg 07.31.94  ESF  Added MSG_NETPOPUP.
374  * \arg 08.03.94  ESF  Fixed to return error message.
375  * \arg 08.28.94  ESF  Added MSG_POPUPREGISTERBOX.
376  * \arg 09.31.94  ESF  Changed MSG_ENDOFGAME to take a string parameter.
377  * \arg 10.29.94  ESF  Added MSG_DICEROLL.
378  * \arg 10.30.94  ESF  Added MSG_PLACENOTIFY.
379  * \arg 10.30.94  ESF  Added MSG_ATTACKNOTIFY.
380  * \arg 10.30.94  ESF  Added MSG_MOVENOTIFY.
381  * \arg 01.17.95  ESF  Removed MSG_DELETEMSGDST.
382  * \arg 02.21.95  ESF  Added MSG_HELLO, MSG_VERSION.
383  * \arg 02.21.95  ESF  Modified MSG_REGISTERCLIENT to include type of client.
384  * \arg 02.23.95  ESF  Added MSG_OLDREGISTERCLIENT.
385  * \arg 02.23.95  ESF  Added MSG_SPECIESIDENT.
386  * \arg 24.08.95  JC   Added MSG_MISSION.
387  * \arg 28.08.95  JC   Added MSG_ENDOFMISSION and MSG_VICTORY.
388  * \arg 30.08.95  JC   Added MSG_FORCEEXCHANGECARDS.
389  */
NET_RecvMessage(Int32 iSocket,Int32 * piMessType,void ** ppvMessage)390 Int32 NET_RecvMessage(Int32 iSocket, Int32 *piMessType, void **ppvMessage)
391 {
392   Int32 i;
393 
394   /* Get the message ID */
395   ReturnIfError(_NET_RecvLong(iSocket, (Int32 *)piMessType));
396 
397   switch(*piMessType)
398     {
399     case MSG_OLDREGISTERCLIENT:
400       {
401 	MsgOldRegisterClient *pmsgMess =
402 	  (MsgOldRegisterClient *)MEM_Alloc(sizeof(MsgOldRegisterClient));
403 
404 	ReturnIfError(_NET_RecvString(iSocket, &pmsgMess->strClientAddress));
405 
406 	*ppvMessage = (void *)pmsgMess;
407       }
408       break;
409 
410     case MSG_REGISTERCLIENT:
411       {
412 	MsgRegisterClient *pmsgMess =
413 	  (MsgRegisterClient *)MEM_Alloc(sizeof(MsgRegisterClient));
414 
415 	ReturnIfError(_NET_RecvString(iSocket, &pmsgMess->strClientAddress));
416 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iClientType));
417 
418 	*ppvMessage = (void *)pmsgMess;
419       }
420       break;
421 
422     case MSG_EXCHANGECARDS:
423       {
424 	MsgExchangeCards *pmsgMess =
425 	  (MsgExchangeCards *)MEM_Alloc(sizeof(MsgExchangeCards));
426 
427 	for(i=0; i!=3; i++)
428 	  ReturnIfError(_NET_RecvLong(iSocket,
429 				      (Int32 *)&pmsgMess->piCards[i]));
430 
431 	*ppvMessage = (void *)pmsgMess;
432       }
433       break;
434 
435     case MSG_CARDPACKET:
436       {
437 	MsgCardPacket *pmsgMess =
438 	  (MsgCardPacket *)MEM_Alloc(sizeof(MsgCardPacket));
439 
440 	ReturnIfError(_NET_RecvLong(iSocket, (Int32 *)&pmsgMess->iPlayer));
441 	ReturnIfError(_NET_RecvLong(iSocket, (Int32 *)&pmsgMess->cdCard));
442 
443 	*ppvMessage = (void *)pmsgMess;
444       }
445       break;
446 
447     case MSG_REPLYPACKET:
448       {
449 	MsgReplyPacket *pmsgMess =
450 	  (MsgReplyPacket *)MEM_Alloc(sizeof(MsgReplyPacket));
451 
452 	ReturnIfError(_NET_RecvLong(iSocket, (Int32 *)&pmsgMess->iReply));
453 
454 	*ppvMessage = (void *)pmsgMess;
455       }
456       break;
457 
458     case MSG_SENDMESSAGE:
459       {
460 	MsgSendMessage *pmsgMess =
461 	  (MsgSendMessage *)MEM_Alloc(sizeof(MsgSendMessage));
462 
463 	ReturnIfError(_NET_RecvString(iSocket, &pmsgMess->strMessage));
464 	ReturnIfError(_NET_RecvString(iSocket, &pmsgMess->strDestination));
465 
466 	*ppvMessage = (void *)pmsgMess;
467       }
468       break;
469 
470     case MSG_MESSAGEPACKET:
471       {
472 	MsgMessagePacket *pmsgMess =
473 	  (MsgMessagePacket *)MEM_Alloc(sizeof(MsgMessagePacket));
474 
475 	ReturnIfError(_NET_RecvString(iSocket, &pmsgMess->strMessage));
476 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iFrom));
477 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iTo));
478 
479 	*ppvMessage = (void *)pmsgMess;
480       }
481       break;
482 
483     case MSG_TURNNOTIFY:
484       {
485 	MsgTurnNotify *pmsgMess =
486 	  (MsgTurnNotify *)MEM_Alloc(sizeof(MsgTurnNotify));
487 
488 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iPlayer));
489 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iClient));
490 
491 	*ppvMessage = (void *)pmsgMess;
492       }
493       break;
494 
495     case MSG_CLIENTIDENT:
496       {
497 	MsgClientIdent *pmsgMess =
498 	  (MsgClientIdent *)MEM_Alloc(sizeof(MsgClientIdent));
499 
500 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iClientID));
501 	*ppvMessage = (void *)pmsgMess;
502       }
503       break;
504 
505     case MSG_REQUESTCARD:
506       {
507 	MsgRequestCard *pmsgMess =
508 	  (MsgRequestCard *)MEM_Alloc(sizeof(MsgRequestCard));
509 
510 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iPlayer));
511 	*ppvMessage = (void *)pmsgMess;
512       }
513       break;
514 
515     case MSG_ENTERSTATE:
516       {
517 	MsgEnterState *pmsgMess =
518 	  (MsgEnterState *)MEM_Alloc(sizeof(MsgEnterState));
519 
520 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iState));
521 	*ppvMessage = (void *)pmsgMess;
522       }
523       break;
524 
525     case MSG_OBJSTRUPDATE:
526       {
527 	MsgObjStrUpdate *pmsgMess =
528 	  (MsgObjStrUpdate *)MEM_Alloc(sizeof(MsgObjStrUpdate));
529 
530 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iField));
531 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iIndex1));
532 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iIndex2));
533 	ReturnIfError(_NET_RecvString(iSocket, &pmsgMess->strNewValue));
534 	*ppvMessage = (void *)pmsgMess;
535       }
536       break;
537 
538     case MSG_OBJINTUPDATE:
539       {
540 	MsgObjIntUpdate *pmsgMess =
541 	  (MsgObjIntUpdate *)MEM_Alloc(sizeof(MsgObjIntUpdate));
542 
543 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iField));
544 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iIndex1));
545 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iIndex2));
546 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iNewValue));
547 	*ppvMessage = (void *)pmsgMess;
548       }
549       break;
550 
551     case MSG_FREEPLAYER:
552       {
553 	MsgFreePlayer *pmsgMess =
554 	  (MsgFreePlayer *)MEM_Alloc(sizeof(MsgFreePlayer));
555 
556 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iPlayer));
557 	*ppvMessage = (void *)pmsgMess;
558       }
559       break;
560 
561     /* These happen to be identical, so we can lump them. */
562     case MSG_NETMESSAGE:
563     case MSG_NETPOPUP:
564       {
565 	MsgNetMessage *pmsgMess =
566 	  (MsgNetMessage *)MEM_Alloc(sizeof(MsgNetMessage));
567 
568 	ReturnIfError(_NET_RecvString(iSocket, &pmsgMess->strMessage));
569 	*ppvMessage = (void *)pmsgMess;
570       }
571       break;
572 
573     case MSG_ENDOFMISSION:
574       {
575 	MsgEndOfMission *pmsgMess =
576 	  (MsgEndOfMission *)MEM_Alloc(sizeof(MsgEndOfMission));
577 
578 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iWinner));
579 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iTyp));
580 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iNum1));
581 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iNum2));
582 	*ppvMessage = (void *)pmsgMess;
583       }
584       break;
585 
586     case MSG_VICTORY:
587       {
588 	MsgVictory *pmsgMess =
589 	  (MsgVictory *)MEM_Alloc(sizeof(MsgVictory));
590 
591 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iWinner));
592 	*ppvMessage = (void *)pmsgMess;
593       }
594       break;
595 
596     case MSG_DICEROLL:
597       {
598 	MsgDiceRoll *pmsgMess =
599 	  (MsgDiceRoll *)MEM_Alloc(sizeof(MsgDiceRoll));
600 
601     	for (i=0; i!=3; i++)
602 	  ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->pAttackDice[i]));
603 
604     	for (i=0; i!=3; i++)
605 	  ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->pDefendDice[i]));
606 
607 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iDefendingPlayer));
608 
609 	*ppvMessage = (void *)pmsgMess;
610       }
611       break;
612 
613     case MSG_PLACENOTIFY:
614       {
615 	MsgPlaceNotify *pmsgMess =
616 	  (MsgPlaceNotify *)MEM_Alloc(sizeof(MsgPlaceNotify));
617 
618 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iCountry));
619 
620 	*ppvMessage = (void *)pmsgMess;
621       }
622       break;
623 
624     case MSG_ATTACKNOTIFY:
625       {
626 	MsgAttackNotify *pmsgMess =
627 	  (MsgAttackNotify *)MEM_Alloc(sizeof(MsgAttackNotify));
628 
629 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iSrcCountry));
630 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iDstCountry));
631 
632 	*ppvMessage = (void *)pmsgMess;
633       }
634       break;
635 
636     case MSG_MOVENOTIFY:
637       {
638 	MsgMoveNotify *pmsgMess =
639 	  (MsgMoveNotify *)MEM_Alloc(sizeof(MsgMoveNotify));
640 
641 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iSrcCountry));
642 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iDstCountry));
643 
644 	*ppvMessage = (void *)pmsgMess;
645       }
646       break;
647 
648     case MSG_VERSION:
649       {
650 	MsgVersion *pmsgMess =
651 	  (MsgVersion *)MEM_Alloc(sizeof(MsgVersion));
652 
653 	ReturnIfError(_NET_RecvString(iSocket, &pmsgMess->strVersion));
654 
655 	*ppvMessage = (void *)pmsgMess;
656       }
657       break;
658 
659     case MSG_SPECIESIDENT:
660       {
661 	MsgSpeciesIdent *pmsgMess =
662 	  (MsgSpeciesIdent *)MEM_Alloc(sizeof(MsgSpeciesIdent));
663 
664 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iSpeciesID));
665 
666 	*ppvMessage = (void *)pmsgMess;
667       }
668       break;
669 
670     case MSG_FORCEEXCHANGECARDS:
671       {
672 	MsgForceExchangeCards *pmsgMess =
673 	  (MsgForceExchangeCards *)MEM_Alloc(sizeof(MsgForceExchangeCards));
674 
675 	ReturnIfError(_NET_RecvLong(iSocket, &pmsgMess->iPlayer));
676 
677 	*ppvMessage = (void *)pmsgMess;
678       }
679       break;
680 
681     case MSG_EXIT:
682     case MSG_STARTGAME:
683     case MSG_ENDTURN:
684     case MSG_DEREGISTERCLIENT:
685     case MSG_ALLOCPLAYER:
686     case MSG_POPUPREGISTERBOX:
687     case MSG_HELLO:
688     case MSG_MISSION:
689     case MSG_ENDOFGAME:
690       *ppvMessage = NULL;
691       break;
692 
693     default:
694       printf("NETWORK: Illegal message!\n");
695     }
696 
697   return (1);
698 }
699 
700 /************************************************************************
701  *  FUNCTION: _NET_SendString
702  *  HISTORY:
703  *     01.24.94  ESF  Created.
704  *     08.03.94  ESF  Fixed to return error message.
705  *     03.22.95  ESF  Added handling for NULL strings.
706  *  PURPOSE:
707  *  NOTES:
708  ************************************************************************/
_NET_SendString(Int32 iSocket,CString strCString)709 static Int32 _NET_SendString(Int32 iSocket, CString strCString)
710 {
711   Int32 iLength;
712 
713   /* Send the length and then the string itself */
714   if (strCString == NULL)
715     iLength = 0;
716   else
717     iLength = strlen(strCString)+1;
718 
719   ReturnIfError(_NET_SendLong(iSocket, (Int32)iLength));
720   return (_NET_SocketWrite(iSocket, (Char *)strCString, (Int32)iLength));
721 }
722 
723 
724 /**
725  * Send a long integer to the given socket.
726  *
727  * \b History:
728  *     01.24.94  ESF  Created
729  *     08.03.94  ESF  Fixed to return error message.
730  */
_NET_SendLong(Int32 iSocket,Int32 iLong)731 static Int32 _NET_SendLong(Int32 iSocket, Int32 iLong)
732 {
733   Int32 iData = htonl(iLong);
734 
735   return (_NET_SocketWrite(iSocket, &iData, sizeof(Int32)));
736 }
737 
738 
739 /**
740  * Receive a string from the given socket. First reads the length
741  * (32bit value), then the string data.
742  *
743  * \bug Assumes that a nul terminating byte is in the data stream
744  *
745  * \b History:
746  * \arg 01.24.94  ESF  Created
747  * \arg 08.03.94  ESF  Fixed to return error message.
748  * \arg 01.01.94  ESF  Added check for correct number of bytes read.
749  * \arg 03.22.95  ESF  Added handling for NULL strings.
750  */
_NET_RecvString(Int32 iSocket,CString * pstrCString)751 static Int32 _NET_RecvString(Int32 iSocket, CString *pstrCString)
752 {
753   Int32    iLength;
754   CString  strTemp;
755   Int32    iRet;
756 
757   /* Receive the length and then the byte stream */
758   ReturnIfError(_NET_RecvLong(iSocket, &iLength));
759 
760   if (iLength)
761     {
762       strTemp = (CString)MEM_Alloc(iLength);
763       iRet = _NET_SocketRead(iSocket, strTemp, iLength);
764 
765       /* Return an error if less than the string was read! */
766       if (iRet<0 || iRet!=iLength)
767 	iRet = -1;
768     }
769   else
770     {
771       iRet = -1;
772       strTemp = NULL;
773     }
774 
775   *pstrCString = strTemp;
776   return iRet;
777 }
778 
779 
780 /**
781  * Reads a 32bit value from the given socket.
782  *
783  * \b History:
784  * \arg 01.24.94  ESF  Created
785  * \arg 08.03.94  ESF  Fixed to return error message.
786  * \arg 01.01.94  ESF  Added check for correct number of bytes read.
787  */
_NET_RecvLong(Int32 iSocket,Int32 * piLong)788 static Int32 _NET_RecvLong(Int32 iSocket, Int32 *piLong)
789 {
790   Int32 iRet = _NET_SocketRead(iSocket, piLong, sizeof(Int32));
791 
792   /* Adjust for the network munging */
793   *piLong = ntohl(*piLong);
794 
795   /* Return an error if read returns an error or if the wrong number
796    * of bytes come across -- there should be sizeof(Int32) bytes!
797    */
798 
799   if (iRet<0 || iRet!=sizeof(Int32))
800     iRet = -1;
801 
802   return iRet;
803 }
804 
805 
806 /**
807  * Reads the given number of bytes from the given socket.
808  *
809  * \b History:
810  * \arg 01.01.95  ESF  Created.
811  * \arg 01.21.95  ESF  Fixed non-ANSIness.
812  */
_NET_SocketRead(Int32 iSocket,void * ptr,Int32 iNumBytes)813 static Int32 _NET_SocketRead(Int32 iSocket, void *ptr, Int32 iNumBytes)
814 {
815   Int32 iBytesLeft, iRet;
816 
817   /* We may have to do multiple read() calls here */
818   iBytesLeft = iNumBytes;
819 
820   while (iBytesLeft > 0)
821     {
822       iRet = read(iSocket, ptr, iBytesLeft);
823 
824       /* If an error occured, return */
825       if (iRet < 0)
826 	return iRet;
827       else if (iRet == 0)
828 	break; /* EOF */
829 
830       iBytesLeft  -= iRet;
831       ptr = (Byte *)ptr + iRet;
832     }
833 
834   /* Return the number of bytes read */
835   return (iNumBytes - iBytesLeft);
836 }
837 
838 
839 /**
840  * Write the given number of bytes to the given socket.
841  *
842  * \b History:
843  * \arg 01.24.94  ESF  Created
844  * \arg 08.03.94  ESF  Fixed to return error message.
845  * \arg 01.01.94  ESF  Added check for correct number of bytes read.
846  * \arg 01.21.95  ESF  Fixed non-ANSIness.
847  */
_NET_SocketWrite(Int32 iSocket,void * ptr,Int32 iNumBytes)848 static Int32 _NET_SocketWrite(Int32 iSocket, void *ptr, Int32 iNumBytes)
849 {
850   Int32 iBytesLeft, iRet;
851 
852   /* We may have to do multiple read() calls here */
853   iBytesLeft = iNumBytes;
854 
855   while (iBytesLeft > 0)
856     {
857       iRet = write(iSocket, ptr, iBytesLeft);
858 
859       /* If an error occured, return */
860       if (iRet < 0)
861 	return iRet;
862 
863       iBytesLeft  -= iRet;
864       ptr = (Byte *)ptr + iRet;
865     }
866 
867   /* Return the number of bytes read */
868   return (iNumBytes - iBytesLeft);
869 }
870 
871 
872 /**
873  * Free the memory allocated for the given message.
874  *
875  * \b History:
876  * \arg 06.24.94  ESF  Created
877  * \arg 07.31.94  ESF  Added MSG_NETPOPUP.
878  * \arg 09.31.94  ESF  Changed MSG_ENDOFGAME to take a string parameter.
879  * \arg 10.29.94  ESF  Added MSG_DICEROLL.
880  * \arg 10.30.94  ESF  Added MSG_PLACENOTIFY.
881  * \arg 10.30.94  ESF  Added MSG_ATTACKNOTIFY.
882  * \arg 10.30.94  ESF  Added MSG_MOVENOTIFY.
883  * \arg 01.17.95  ESF  Removed MSG_DELETEMSGDST.
884  * \arg 02.21.95  ESF  Added MSG_HELLO, MSG_VERSION.
885  * \arg 02.21.95  ESF  Modified MSG_REGISTERCLIENT to include type of client.
886  * \arg 02.23.95  ESF  Added MSG_OLDREGISTERCLIENT.
887  * \arg 02.23.95  ESF  Added MSG_SPECIESIDENT.
888  * \arg 24.08.95  JC   Added MSG_MISSION.
889  * \arg 30.08.95  JC   Added MSG_FORCEEXCHANGECARDS.
890  */
NET_DeleteMessage(Int32 iMessType,void * pvMessage)891 void NET_DeleteMessage(Int32 iMessType, void *pvMessage)
892 {
893   switch(iMessType)
894     {
895     case MSG_NOMESSAGE:
896       break;
897 
898     case MSG_OLDREGISTERCLIENT:
899       {
900 	MsgOldRegisterClient *pmsgMess = (MsgOldRegisterClient *)pvMessage;
901 	MEM_Free(pmsgMess->strClientAddress);
902 	MEM_Free(pmsgMess);
903       }
904       break;
905 
906     case MSG_REGISTERCLIENT:
907       {
908 	MsgRegisterClient *pmsgMess = (MsgRegisterClient *)pvMessage;
909 	MEM_Free(pmsgMess->strClientAddress);
910 	MEM_Free(pmsgMess);
911       }
912       break;
913 
914     case MSG_EXCHANGECARDS:
915       MEM_Free(pvMessage);
916       break;
917 
918     case MSG_CARDPACKET:
919       MEM_Free(pvMessage);
920       break;
921 
922     case MSG_REPLYPACKET:
923       MEM_Free(pvMessage);
924       break;
925 
926     case MSG_SENDMESSAGE:
927       {
928 	MsgSendMessage *pmsgMess = (MsgSendMessage *)pvMessage;
929 
930 	MEM_Free(pmsgMess->strMessage);
931 	MEM_Free(pmsgMess->strDestination);
932 	MEM_Free(pvMessage);
933       }
934       break;
935 
936     case MSG_MESSAGEPACKET:
937       {
938 	MsgMessagePacket *pmsgMess = (MsgMessagePacket *)pvMessage;
939 
940 	MEM_Free(pmsgMess->strMessage);
941 	MEM_Free(pvMessage);
942       }
943       break;
944 
945     case MSG_TURNNOTIFY:
946       MEM_Free(pvMessage);
947       break;
948 
949     case MSG_CLIENTIDENT:
950       MEM_Free(pvMessage);
951       break;
952 
953     case MSG_REQUESTCARD:
954       MEM_Free(pvMessage);
955       break;
956 
957     case MSG_ENTERSTATE:
958       MEM_Free(pvMessage);
959       break;
960 
961     case MSG_OBJSTRUPDATE:
962       {
963 	MsgObjStrUpdate *pmsgMess = (MsgObjStrUpdate*)pvMessage;
964 
965 	if (pmsgMess->strNewValue)
966 	  MEM_Free(pmsgMess->strNewValue);
967 	MEM_Free(pvMessage);
968       }
969       break;
970 
971     case MSG_OBJINTUPDATE:
972       MEM_Free(pvMessage);
973       break;
974 
975     case MSG_FREEPLAYER:
976       MEM_Free(pvMessage);
977       break;
978 
979     /* These happen to be identical, so we can lump them. */
980     case MSG_NETMESSAGE:
981     case MSG_NETPOPUP:
982       {
983 	MsgNetMessage *pmsgMess = (MsgNetMessage *)pvMessage;
984 	MEM_Free(pmsgMess->strMessage);
985 	MEM_Free(pvMessage);
986       }
987       break;
988 
989     case MSG_ENDOFMISSION:
990       MEM_Free(pvMessage);
991       break;
992 
993     case MSG_VICTORY:
994       MEM_Free(pvMessage);
995       break;
996 
997     case MSG_DICEROLL:
998       MEM_Free(pvMessage);
999       break;
1000 
1001     case MSG_PLACENOTIFY:
1002       MEM_Free(pvMessage);
1003       break;
1004 
1005     case MSG_ATTACKNOTIFY:
1006       MEM_Free(pvMessage);
1007       break;
1008 
1009     case MSG_MOVENOTIFY:
1010       MEM_Free(pvMessage);
1011       break;
1012 
1013     case MSG_VERSION:
1014       {
1015 	MsgVersion *pmsgMess = (MsgVersion *)pvMessage;
1016 	MEM_Free(pmsgMess->strVersion);
1017 	MEM_Free(pvMessage);
1018       }
1019       break;
1020 
1021     case MSG_SPECIESIDENT:
1022       MEM_Free(pvMessage);
1023       break;
1024 
1025     case MSG_FORCEEXCHANGECARDS:
1026       MEM_Free(pvMessage);
1027       break;
1028 
1029     case MSG_EXIT:
1030     case MSG_STARTGAME:
1031     case MSG_ENDTURN:
1032     case MSG_DEREGISTERCLIENT:
1033     case MSG_ALLOCPLAYER:
1034     case MSG_POPUPREGISTERBOX:
1035     case MSG_HELLO:
1036     case MSG_MISSION:
1037     case MSG_ENDOFGAME:
1038       /* No parameters */
1039       D_Assert(pvMessage == NULL, "Hum...this shouldn't happen.");
1040       break;
1041 
1042     default:
1043       D_Assert(FALSE, "Add case for a new message in NET_DeleteMessage!");
1044     }
1045 }
1046 
1047 
1048 /**
1049  * Set socket options for better performance.
1050  *
1051  * \b History:
1052  * \arg 01.22.95  ESF  Created.
1053  * \arg 02.27.95  ESF  Added SO_REUSEADDR.
1054  * \arg 17.08.95  JC   iOption -> &iOption.
1055  */
NET_SetCommLinkOptions(Int32 iSocket)1056 void NET_SetCommLinkOptions(Int32 iSocket)
1057 {
1058 #ifdef TCP_NODELAY
1059   {
1060     Int32 iOption = 1;
1061     if (setsockopt(iSocket, IPPROTO_TCP, TCP_NODELAY,
1062 		   (char *)&iOption, sizeof(iOption)) != 0)
1063       printf("NETWORK: Warning -- couldn't set TCP_NODELAY on CommLink!\n");
1064   }
1065 #endif
1066 #ifdef SO_REUSEADDR
1067   {
1068     Int32 iOption = 1;
1069     if (setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR,
1070 		   (char *)&iOption, sizeof(iOption)) != 0)
1071       printf("NETWORK: Warning -- couldn't set SO_REUSEADDR on CommLink!\n");
1072   }
1073 #endif
1074 }
1075 
1076 
1077 /**
1078  * Convert the given message to a human readable string for debugging.
1079  *
1080  * \b History:
1081  * \arg 03.19.95  ESF  Created.
1082  * \arg 24.08.95  JC   Added MSG_MISSION.
1083  * \arg 30.08.95  JC   Added MSG_FORCEEXCHANGECARDS.
1084  */
NET_MessageToString(Int32 iMessType,void * pvMessage)1085 CString NET_MessageToString(Int32 iMessType, void *pvMessage)
1086 {
1087   switch (iMessType)
1088     {
1089     case MSG_NOMESSAGE:
1090       snprintf(strLogging, sizeof(strLogging), "MsgNoMessage()");
1091       break;
1092 
1093     case MSG_OLDREGISTERCLIENT:
1094       snprintf(strLogging, sizeof(strLogging), "MsgOldRegisterClient(strClientAddress=\"%s\")",
1095 	      ((MsgOldRegisterClient *)pvMessage)->strClientAddress);
1096       break;
1097 
1098     case MSG_REGISTERCLIENT:
1099       snprintf(strLogging, sizeof(strLogging), "MsgRegisterClient(strClientAddress=\"%s\","
1100 	      " iClientType=%s)",
1101 	      ((MsgRegisterClient *)pvMessage)->strClientAddress,
1102 	      ((MsgRegisterClient *)pvMessage)->iClientType ==
1103 	      CLIENT_NORMAL ? "CLIENT_NORMAL" :
1104 	      ((MsgRegisterClient *)pvMessage)->iClientType ==
1105 	      CLIENT_AI ? "CLIENT_AI" :
1106 	      ((MsgRegisterClient *)pvMessage)->iClientType ==
1107 	      CLIENT_STRICTOBSERVER ? "CLIENT_STRICTOBSERVER" :
1108 	      "*Unknown*");
1109       break;
1110 
1111     case MSG_EXCHANGECARDS:
1112       snprintf(strLogging, sizeof(strLogging), "MsgExchangeCards(piCards={%d, %d, %d})",
1113 	      ((MsgExchangeCards *)pvMessage)->piCards[0],
1114 	      ((MsgExchangeCards *)pvMessage)->piCards[1],
1115 	      ((MsgExchangeCards *)pvMessage)->piCards[2]);
1116       break;
1117 
1118     case MSG_CARDPACKET:
1119       snprintf(strLogging, sizeof(strLogging), "MsgCardPacket(iPlayer=%d, iCard=%d)",
1120 	      ((MsgCardPacket *)pvMessage)->iPlayer,
1121 	      ((MsgCardPacket *)pvMessage)->cdCard);
1122       break;
1123 
1124     case MSG_REPLYPACKET:
1125       snprintf(strLogging, sizeof(strLogging), "MsgReplyPacket(iReply=%d)",
1126 	      ((MsgReplyPacket *)pvMessage)->iReply);
1127       break;
1128 
1129     case MSG_SENDMESSAGE:
1130       snprintf(strLogging, sizeof(strLogging), "MsgSendMessage(strMessage=\"%s\", "
1131 	      "strDestination=\"%s\")",
1132 	      ((MsgSendMessage *)pvMessage)->strMessage,
1133 	      ((MsgSendMessage *)pvMessage)->strDestination);
1134       break;
1135 
1136     case MSG_MESSAGEPACKET:
1137       snprintf(strLogging, sizeof(strLogging), "MsgMessagePacket(strMessage=\"%s\", "
1138 	      "iFrom=\"%d\", iTo=%d)",
1139 	      ((MsgMessagePacket *)pvMessage)->strMessage,
1140 	      ((MsgMessagePacket *)pvMessage)->iFrom,
1141 	      ((MsgMessagePacket *)pvMessage)->iTo);
1142       break;
1143 
1144     case MSG_TURNNOTIFY:
1145       snprintf(strLogging, sizeof(strLogging), "MsgTurnNotify(iPlayer=%d, iClient=%d)",
1146 	      ((MsgTurnNotify *)pvMessage)->iPlayer,
1147 	      ((MsgTurnNotify *)pvMessage)->iClient);
1148       break;
1149 
1150     case MSG_CLIENTIDENT:
1151       snprintf(strLogging, sizeof(strLogging), "MsgClientIdent(iClientID=%d)",
1152 	      ((MsgClientIdent *)pvMessage)->iClientID);
1153       break;
1154 
1155     case MSG_REQUESTCARD:
1156       snprintf(strLogging, sizeof(strLogging), "MsgRequestCard(iPlayer=%d)",
1157 	      ((MsgRequestCard *)pvMessage)->iPlayer);
1158       break;
1159 
1160     case MSG_ENTERSTATE:
1161       snprintf(strLogging, sizeof(strLogging), "MsgEnterState(iState=%d)",
1162 	      ((MsgEnterState *)pvMessage)->iState);
1163       break;
1164 
1165     case MSG_OBJSTRUPDATE:
1166       snprintf(strLogging, sizeof(strLogging), "ObjStrUpdate(iField=%d, iIndex=[%d, %d], "
1167 	      "strNewValue=\"%s\")",
1168 	      ((MsgObjStrUpdate *)pvMessage)->iField,
1169 	      ((MsgObjStrUpdate *)pvMessage)->iIndex1,
1170 	      ((MsgObjStrUpdate *)pvMessage)->iIndex2,
1171 	      ((MsgObjStrUpdate *)pvMessage)->strNewValue);
1172       break;
1173 
1174     case MSG_OBJINTUPDATE:
1175       snprintf(strLogging, sizeof(strLogging), "ObjIntUpdate(iField=%d, iIndex=[%d, %d], "
1176 	      "iNewValue=%d)",
1177 	      ((MsgObjIntUpdate *)pvMessage)->iField,
1178 	      ((MsgObjIntUpdate *)pvMessage)->iIndex1,
1179 	      ((MsgObjIntUpdate *)pvMessage)->iIndex2,
1180 	      ((MsgObjIntUpdate *)pvMessage)->iNewValue);
1181       break;
1182 
1183     case MSG_FREEPLAYER:
1184       snprintf(strLogging, sizeof(strLogging), "MsgFreePlayer(iPlayer=%d)",
1185 	      ((MsgFreePlayer *)pvMessage)->iPlayer);
1186       break;
1187 
1188     case MSG_NETMESSAGE:
1189       snprintf(strLogging, sizeof(strLogging), "MsgNetMessage(strMessage=\"%s\")",
1190 	      ((MsgNetMessage *)pvMessage)->strMessage);
1191       break;
1192 
1193     case MSG_NETPOPUP:
1194       snprintf(strLogging, sizeof(strLogging), "MsgNetPopup(strMessage=\"%s\")",
1195 	      ((MsgNetPopup *)pvMessage)->strMessage);
1196       break;
1197 
1198     case MSG_ENDOFMISSION:
1199       snprintf(strLogging, sizeof(strLogging), "MsgEndOfMission(iWinner=%d, iTyp=%d, iNum1=%d, iNum2=%d)",
1200 	      ((MsgEndOfMission *)pvMessage)->iWinner,
1201 	      ((MsgEndOfMission *)pvMessage)->iTyp,
1202 	      ((MsgEndOfMission *)pvMessage)->iNum1,
1203 	      ((MsgEndOfMission *)pvMessage)->iNum2);
1204       break;
1205 
1206     case MSG_VICTORY:
1207       snprintf(strLogging, sizeof(strLogging), "MsgVictory(iWinner=%d)",
1208 	      ((MsgVictory *)pvMessage)->iWinner);
1209       break;
1210 
1211     case MSG_ENDOFGAME:
1212       snprintf(strLogging, sizeof(strLogging), "MsgEndOfGame()");
1213       break;
1214 
1215     case MSG_DICEROLL:
1216       snprintf(strLogging, sizeof(strLogging), "MsgDiceRoll(iDefendingPlayer=%d, "
1217 	      "pAttackDice={%d, %d, %d}, pDefendDice={%d, %d, %d})",
1218 	      ((MsgDiceRoll *)pvMessage)->iDefendingPlayer,
1219 	      ((MsgDiceRoll *)pvMessage)->pAttackDice[0],
1220 	      ((MsgDiceRoll *)pvMessage)->pAttackDice[1],
1221 	      ((MsgDiceRoll *)pvMessage)->pAttackDice[2],
1222 	      ((MsgDiceRoll *)pvMessage)->pDefendDice[0],
1223 	      ((MsgDiceRoll *)pvMessage)->pDefendDice[1],
1224 	      ((MsgDiceRoll *)pvMessage)->pDefendDice[2]);
1225       break;
1226 
1227     case MSG_PLACENOTIFY:
1228       snprintf(strLogging, sizeof(strLogging), "MsgPlaceNotify(iCountry=%d)",
1229 	      ((MsgPlaceNotify *)pvMessage)->iCountry);
1230       break;
1231 
1232     case MSG_ATTACKNOTIFY:
1233       snprintf(strLogging, sizeof(strLogging), "MsgAttackNotify(iSrcCountry=%d, iDstCountry=%d)",
1234 	      ((MsgAttackNotify *)pvMessage)->iSrcCountry,
1235 	      ((MsgAttackNotify *)pvMessage)->iDstCountry);
1236       break;
1237 
1238     case MSG_MOVENOTIFY:
1239       snprintf(strLogging, sizeof(strLogging), "MsgMoveNotify(iSrcCountry=%d, iDstCountry=%d)",
1240 	      ((MsgMoveNotify *)pvMessage)->iSrcCountry,
1241 	      ((MsgMoveNotify *)pvMessage)->iDstCountry);
1242       break;
1243 
1244     case MSG_VERSION:
1245       snprintf(strLogging, sizeof(strLogging), "MsgVersion(strVersion=\"%s\")",
1246 	      ((MsgVersion *)pvMessage)->strVersion);
1247       break;
1248 
1249     case MSG_SPECIESIDENT:
1250       snprintf(strLogging, sizeof(strLogging), "MsgSpeciesIdent(iSpeciesID=%d)",
1251 	      ((MsgSpeciesIdent *)pvMessage)->iSpeciesID);
1252       break;
1253 
1254     case MSG_FORCEEXCHANGECARDS:
1255       snprintf(strLogging, sizeof(strLogging), "MsgForceExchangeCards(iPlayer=%d)",
1256 	      ((MsgForceExchangeCards *)pvMessage)->iPlayer);
1257       break;
1258 
1259     case MSG_EXIT:
1260       snprintf(strLogging, sizeof(strLogging), "MsgExit()");
1261       break;
1262 
1263     case MSG_STARTGAME:
1264       snprintf(strLogging, sizeof(strLogging), "MsgStartGame()");
1265       break;
1266 
1267     case MSG_ENDTURN:
1268       snprintf(strLogging, sizeof(strLogging), "MsgEndTurn()");
1269       break;
1270 
1271     case MSG_DEREGISTERCLIENT:
1272       snprintf(strLogging, sizeof(strLogging), "MsgDeregisterClient()");
1273       break;
1274 
1275     case MSG_ALLOCPLAYER:
1276       snprintf(strLogging, sizeof(strLogging), "MsgAllocPlayer()");
1277       break;
1278 
1279     case MSG_POPUPREGISTERBOX:
1280       snprintf(strLogging, sizeof(strLogging), "MsgPopupRegisterBox()");
1281       break;
1282 
1283     case MSG_HELLO:
1284       snprintf(strLogging, sizeof(strLogging), "MsgHello()");
1285       break;
1286 
1287     case MSG_MISSION:
1288       snprintf(strLogging, sizeof(strLogging), "MsgMission()");
1289       break;
1290 
1291     default:
1292       D_Assert(FALSE, "Add case to NET_StringToMessage!");
1293     }
1294 
1295   return strLogging;
1296 }
1297 
1298 /* EOF */
1299