portability fixes
[xonotic/netradiant.git] / libs / l_net / l_net.c
1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 //====================================================================
23 //
24 // Name:                        l_net.c
25 // Function:            -
26 // Programmer:          MrElusive
27 // Last update:         -
28 // Tab size:            3
29 // Notes:
30 //====================================================================
31
32 #include <stdio.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include "l_net.h"
37 #include "l_net_wins.h"
38
39 #define GetMemory malloc
40 #define FreeMemory free
41
42 #define qtrue   1
43 #define qfalse  0
44
45 #ifdef _DEBUG
46 void WinPrint(char *str, ...)
47 {
48         va_list argptr;
49   char text[4096];
50
51   va_start (argptr,str);
52         vsprintf (text, str, argptr);
53         va_end (argptr);
54
55   printf(text);
56 }
57 #else
58 void WinPrint(char *str, ...)
59 {
60 }
61 #endif
62
63 //===========================================================================
64 //
65 // Parameter:                           -
66 // Returns:                                     -
67 // Changes Globals:             -
68 //===========================================================================
69 void Net_SetAddressPort(address_t *address, int port)
70 {
71         sockaddr_t addr;
72
73         WINS_StringToAddr(address->ip, &addr);
74         WINS_SetSocketPort(&addr, port);
75         strcpy(address->ip, WINS_AddrToString(&addr));
76 } //end of the function Net_SetAddressPort
77 //===========================================================================
78 //
79 // Parameter:                           -
80 // Returns:                                     -
81 // Changes Globals:             -
82 //===========================================================================
83 int Net_AddressCompare(address_t *addr1, address_t *addr2)
84 {
85 #ifdef WIN32
86   return _stricmp(addr1->ip, addr2->ip);
87 #else
88   return strcasecmp(addr1->ip, addr2->ip);
89 #endif
90 } //end of the function Net_AddressCompare
91 //===========================================================================
92 //
93 // Parameter:                           -
94 // Returns:                                     -
95 // Changes Globals:             -
96 //===========================================================================
97 void Net_SocketToAddress(socket_t *sock, address_t *address)
98 {
99         strcpy(address->ip, WINS_AddrToString(&sock->addr));
100 } //end of the function Net_SocketToAddress
101 //===========================================================================
102 //
103 // Parameter:                           -
104 // Returns:                                     -
105 // Changes Globals:             -
106 //===========================================================================
107 int Net_Send(socket_t *sock, netmessage_t *msg)
108 {
109         int size;
110
111         size = msg->size;
112         msg->size = 0;
113         NMSG_WriteLong(msg, size-4);
114         msg->size = size;
115         //WinPrint("Net_Send: message of size %d\n", sendmsg.size);
116         return WINS_Write(sock->socket, msg->data, msg->size, NULL);
117 } //end of the function Net_SendSocketReliable
118 //===========================================================================
119 // returns the number of bytes recieved
120 // -1 on error
121 //
122 // Parameter:                           -
123 // Returns:                                     -
124 // Changes Globals:             -
125 //===========================================================================
126 int Net_Receive(socket_t *sock, netmessage_t *msg)
127 {
128         int curread;
129
130         if (sock->remaining > 0)
131         {
132                 curread = WINS_Read(sock->socket, &sock->msg.data[sock->msg.size], sock->remaining, NULL);
133                 if (curread == -1)
134                 {
135                         WinPrint("Net_Receive: read error\n");
136                         return -1;
137                 } //end if
138                 sock->remaining -= curread;
139                 sock->msg.size += curread;
140                 if (sock->remaining <= 0)
141                 {
142                         sock->remaining = 0;
143                         memcpy(msg, &sock->msg, sizeof(netmessage_t));
144                         sock->msg.size = 0;
145                         return msg->size - 4;
146                 } //end if
147                 return 0;
148         } //end if
149         sock->msg.size = WINS_Read(sock->socket, sock->msg.data, 4, NULL);
150         if (sock->msg.size == 0) return 0;
151         if (sock->msg.size == -1)
152         {
153                 WinPrint("Net_Receive: size header read error\n");
154                 return -1;
155         } //end if
156         //WinPrint("Net_Receive: message size header %d\n", msg->size);
157         sock->msg.read = 0;
158         sock->remaining = NMSG_ReadLong(&sock->msg);
159         if (sock->remaining == 0) return 0;
160         if (sock->remaining < 0 || sock->remaining > MAX_NETMESSAGE)
161         {
162                 WinPrint("Net_Receive: invalid message size %d\n", sock->remaining);
163                 return -1;
164         } //end if
165         //try to read the message
166         curread = WINS_Read(sock->socket, &sock->msg.data[sock->msg.size], sock->remaining, NULL);
167         if (curread == -1)
168         {
169                 WinPrint("Net_Receive: read error\n");
170                 return -1;
171         } //end if
172         sock->remaining -= curread;
173         sock->msg.size += curread;
174         if (sock->remaining <= 0)
175         {
176                 sock->remaining = 0;
177                 memcpy(msg, &sock->msg, sizeof(netmessage_t));
178                 sock->msg.size = 0;
179                 return msg->size - 4;
180         } //end if
181         //the message has not been completely read yet
182 #ifdef _DEBUG
183   printf("++timo TODO: debug the Net_Receive on big size messages\n");
184 #endif
185         return 0;
186 } //end of the function Net_Receive
187 //===========================================================================
188 //
189 // Parameter:                           -
190 // Returns:                                     -
191 // Changes Globals:             -
192 //===========================================================================
193 socket_t *Net_AllocSocket(void)
194 {
195         socket_t *sock;
196
197         sock = (socket_t *) GetMemory(sizeof(socket_t));
198         memset(sock, 0, sizeof(socket_t));
199         return sock;
200 } //end of the function Net_AllocSocket
201 //===========================================================================
202 //
203 // Parameter:                           -
204 // Returns:                                     -
205 // Changes Globals:             -
206 //===========================================================================
207 void Net_FreeSocket(socket_t *sock)
208 {
209         FreeMemory(sock);
210 } //end of the function Net_FreeSocket
211 //===========================================================================
212 //
213 // Parameter:                           -
214 // Returns:                                     -
215 // Changes Globals:             -
216 //===========================================================================
217 socket_t *Net_Connect(address_t *address, int port)
218 {
219         int newsock;
220         socket_t *sock;
221         sockaddr_t sendaddr;
222
223         // see if we can resolve the host name
224         WINS_StringToAddr(address->ip, &sendaddr);
225
226   newsock = WINS_OpenReliableSocket(port);
227         if (newsock == -1) return NULL;
228
229         sock = Net_AllocSocket();
230         if (sock == NULL)
231         {
232                 WINS_CloseSocket(newsock);
233                 return NULL;
234         } //end if
235         sock->socket = newsock;
236
237         //connect to the host
238         if (WINS_Connect(newsock, &sendaddr) == -1)
239         {
240                 Net_FreeSocket(sock);
241                 WINS_CloseSocket(newsock);
242                 WinPrint("Net_Connect: error connecting\n");
243                 return NULL;
244         } //end if
245
246         memcpy(&sock->addr, &sendaddr, sizeof(sockaddr_t));
247         //now we can send messages
248         //
249         return sock;
250 } //end of the function Net_Connect
251
252 //===========================================================================
253 //
254 // Parameter:                           -
255 // Returns:                                     -
256 // Changes Globals:             -
257 //===========================================================================
258 socket_t *Net_ListenSocket(int port)
259 {
260         int newsock;
261         socket_t *sock;
262
263         newsock = WINS_OpenReliableSocket(port);
264         if (newsock == -1) return NULL;
265
266         if (WINS_Listen(newsock) == -1)
267         {
268                 WINS_CloseSocket(newsock);
269                 return NULL;
270         } //end if
271         sock = Net_AllocSocket();
272         if (sock == NULL)
273         {
274                 WINS_CloseSocket(newsock);
275                 return NULL;
276         } //end if
277         sock->socket = newsock;
278         WINS_GetSocketAddr(newsock, &sock->addr);
279         WinPrint("listen socket opened at %s\n", WINS_AddrToString(&sock->addr));
280         //
281         return sock;
282 } //end of the function Net_ListenSocket
283 //===========================================================================
284 //
285 // Parameter:                           -
286 // Returns:                                     -
287 // Changes Globals:             -
288 //===========================================================================
289 socket_t *Net_Accept(socket_t *sock)
290 {
291         int newsocket;
292         sockaddr_t sendaddr;
293         socket_t *newsock;
294
295         newsocket = WINS_Accept(sock->socket, &sendaddr);
296         if (newsocket == -1) return NULL;
297
298         newsock = Net_AllocSocket();
299         if (newsock == NULL)
300         {
301                 WINS_CloseSocket(newsocket);
302                 return NULL;
303         } //end if
304         newsock->socket = newsocket;
305         memcpy(&newsock->addr, &sendaddr, sizeof(sockaddr_t));
306         //
307         return newsock;
308 } //end of the function Net_Accept
309 //===========================================================================
310 //
311 // Parameter:                           -
312 // Returns:                                     -
313 // Changes Globals:             -
314 //===========================================================================
315 void Net_Disconnect(socket_t *sock)
316 {
317         WINS_CloseSocket(sock->socket);
318         Net_FreeSocket(sock);
319 } //end of the function Net_Disconnect
320 //===========================================================================
321 //
322 // Parameter:                           -
323 // Returns:                                     -
324 // Changes Globals:             -
325 //===========================================================================
326 void Net_StringToAddress(char *string, address_t *address)
327 {
328         strcpy(address->ip, string);
329 } //end of the function Net_StringToAddress
330 //===========================================================================
331 //
332 // Parameter:                           -
333 // Returns:                                     -
334 // Changes Globals:             -
335 //===========================================================================
336 void Net_MyAddress(address_t *address)
337 {
338         strcpy(address->ip, WINS_MyAddress());
339 } //end of the function Net_MyAddress
340 //===========================================================================
341 //
342 // Parameter:                           -
343 // Returns:                                     -
344 // Changes Globals:             -
345 //===========================================================================
346 int Net_Setup(void)
347 {
348         WINS_Init();
349         //
350         WinPrint("my address is %s\n", WINS_MyAddress());
351         //
352         return qtrue;
353 } //end of the function Net_Setup
354 //===========================================================================
355 //
356 // Parameter:                           -
357 // Returns:                                     -
358 // Changes Globals:             -
359 //===========================================================================
360 void Net_Shutdown(void)
361 {
362         WINS_Shutdown();
363 } //end of the function Net_Shutdown
364 //===========================================================================
365 //
366 // Parameter:                           -
367 // Returns:                                     -
368 // Changes Globals:             -
369 //===========================================================================
370 void NMSG_Clear(netmessage_t *msg)
371 {
372         msg->size = 4;
373 } //end of the function NMSG_Clear
374 //===========================================================================
375 //
376 // Parameter:                           -
377 // Returns:                                     -
378 // Changes Globals:             -
379 //===========================================================================
380 void NMSG_WriteChar (netmessage_t *msg, int c)
381 {
382         if (c < -128 || c > 127)
383                 WinPrint("NMSG_WriteChar: range error\n");
384
385         if (msg->size >= MAX_NETMESSAGE)
386         {
387                 WinPrint("NMSG_WriteChar: overflow\n");
388                 return;
389         } //end if
390         msg->data[msg->size] = c;
391         msg->size++;
392 } //end of the function NMSG_WriteChar
393 //===========================================================================
394 //
395 // Parameter:                           -
396 // Returns:                                     -
397 // Changes Globals:             -
398 //===========================================================================
399 void NMSG_WriteByte(netmessage_t *msg, int c)
400 {
401         if (c < -128 || c > 127)
402                 WinPrint("NMSG_WriteByte: range error\n");
403
404         if (msg->size + 1 >= MAX_NETMESSAGE)
405         {
406                 WinPrint("NMSG_WriteByte: overflow\n");
407                 return;
408         } //end if
409         msg->data[msg->size] = c;
410         msg->size++;
411 } //end of the function NMSG_WriteByte
412 //===========================================================================
413 //
414 // Parameter:                           -
415 // Returns:                                     -
416 // Changes Globals:             -
417 //===========================================================================
418 void NMSG_WriteShort(netmessage_t *msg, int c)
419 {
420         if (c < ((short)0x8000) || c > (short)0x7fff)
421                 WinPrint("NMSG_WriteShort: range error");
422
423         if (msg->size + 2 >= MAX_NETMESSAGE)
424         {
425                 WinPrint("NMSG_WriteShort: overflow\n");
426                 return;
427         } //end if
428         msg->data[msg->size] = c&0xff;
429         msg->data[msg->size+1] = c>>8;
430         msg->size += 2;
431 } //end of the function NMSG_WriteShort
432 //===========================================================================
433 //
434 // Parameter:                           -
435 // Returns:                                     -
436 // Changes Globals:             -
437 //===========================================================================
438 void NMSG_WriteLong(netmessage_t *msg, int c)
439 {
440         if (msg->size + 4 >= MAX_NETMESSAGE)
441         {
442                 WinPrint("NMSG_WriteLong: overflow\n");
443                 return;
444         } //end if
445         msg->data[msg->size] = c&0xff;
446         msg->data[msg->size+1] = (c>>8)&0xff;
447         msg->data[msg->size+2] = (c>>16)&0xff;
448         msg->data[msg->size+3] = c>>24;
449         msg->size += 4;
450 } //end of the function NMSG_WriteLong
451 //===========================================================================
452 //
453 // Parameter:                           -
454 // Returns:                                     -
455 // Changes Globals:             -
456 //===========================================================================
457 void NMSG_WriteFloat(netmessage_t *msg, float c)
458 {
459         if (msg->size + 4 >= MAX_NETMESSAGE)
460         {
461                 WinPrint("NMSG_WriteLong: overflow\n");
462                 return;
463         } //end if
464         msg->data[msg->size] = *((int *)&c)&0xff;
465         msg->data[msg->size+1] = (*((int *)&c)>>8)&0xff;
466         msg->data[msg->size+2] = (*((int *)&c)>>16)&0xff;
467         msg->data[msg->size+3] = *((int *)&c)>>24;
468         msg->size += 4;
469 } //end of the function NMSG_WriteFloat
470 //===========================================================================
471 //
472 // Parameter:                           -
473 // Returns:                                     -
474 // Changes Globals:             -
475 //===========================================================================
476 void NMSG_WriteString(netmessage_t *msg, char *string)
477 {
478         if (msg->size + strlen(string) + 1 >= MAX_NETMESSAGE)
479         {
480                 WinPrint("NMSG_WriteString: overflow\n");
481                 return;
482         } //end if
483         strcpy(&msg->data[msg->size], string);
484         msg->size += strlen(string) + 1;
485 } //end of the function NMSG_WriteString
486 //===========================================================================
487 //
488 // Parameter:                           -
489 // Returns:                                     -
490 // Changes Globals:             -
491 //===========================================================================
492 void NMSG_ReadStart(netmessage_t *msg)
493 {
494         msg->readoverflow = qfalse;
495         msg->read = 4;
496 } //end of the function NMSG_ReadStart
497 //===========================================================================
498 //
499 // Parameter:                           -
500 // Returns:                                     -
501 // Changes Globals:             -
502 //===========================================================================
503 int NMSG_ReadChar(netmessage_t *msg)
504 {
505         if (msg->size + 1 > msg->size)
506         {
507                 msg->readoverflow = qtrue;
508                 WinPrint("NMSG_ReadChar: read overflow\n");
509                 return 0;
510         } //end if
511         msg->read++;
512         return msg->data[msg->read-1];
513 } //end of the function NMSG_ReadChar
514 //===========================================================================
515 //
516 // Parameter:                           -
517 // Returns:                                     -
518 // Changes Globals:             -
519 //===========================================================================
520 int NMSG_ReadByte(netmessage_t *msg)
521 {
522         if (msg->read + 1 > msg->size)
523         {
524                 msg->readoverflow = qtrue;
525                 WinPrint("NMSG_ReadByte: read overflow\n");
526                 return 0;
527         } //end if
528         msg->read++;
529         return msg->data[msg->read-1];
530 } //end of the function NMSG_ReadByte
531 //===========================================================================
532 //
533 // Parameter:                           -
534 // Returns:                                     -
535 // Changes Globals:             -
536 //===========================================================================
537 int NMSG_ReadShort(netmessage_t *msg)
538 {
539         int c;
540
541         if (msg->read + 2 > msg->size)
542         {
543                 msg->readoverflow = qtrue;
544                 WinPrint("NMSG_ReadShort: read overflow\n");
545                 return 0;
546         } //end if
547         c = (short)(msg->data[msg->read] + (msg->data[msg->read+1]<<8));
548         msg->read += 2;
549         return c;
550 } //end of the function NMSG_ReadShort
551 //===========================================================================
552 //
553 // Parameter:                           -
554 // Returns:                                     -
555 // Changes Globals:             -
556 //===========================================================================
557 int NMSG_ReadLong(netmessage_t *msg)
558 {
559         int c;
560
561         if (msg->read + 4 > msg->size)
562         {
563                 msg->readoverflow = qtrue;
564                 WinPrint("NMSG_ReadLong: read overflow\n");
565                 return 0;
566         } //end if
567         c = msg->data[msg->read]
568                 + (msg->data[msg->read+1]<<8)
569                 + (msg->data[msg->read+2]<<16)
570                 + (msg->data[msg->read+3]<<24);
571         msg->read += 4;
572         return c;
573 } //end of the function NMSG_ReadLong
574 //===========================================================================
575 //
576 // Parameter:                           -
577 // Returns:                                     -
578 // Changes Globals:             -
579 //===========================================================================
580 float NMSG_ReadFloat(netmessage_t *msg)
581 {
582         int c;
583
584         if (msg->read + 4 > msg->size)
585         {
586                 msg->readoverflow = qtrue;
587                 WinPrint("NMSG_ReadLong: read overflow\n");
588                 return 0;
589         } //end if
590         c = msg->data[msg->read]
591                 + (msg->data[msg->read+1]<<8)
592                 + (msg->data[msg->read+2]<<16)
593                 + (msg->data[msg->read+3]<<24);
594         msg->read += 4;
595         return *(float *)&c;
596 } //end of the function NMSG_ReadFloat
597 //===========================================================================
598 //
599 // Parameter:                           -
600 // Returns:                                     -
601 // Changes Globals:             -
602 //===========================================================================
603 char *NMSG_ReadString(netmessage_t *msg)
604 {
605         static char     string[2048];
606         int l, c;
607         
608         l = 0;
609         do
610         {
611                 if (msg->read + 1 > msg->size)
612                 {
613                         msg->readoverflow = qtrue;
614                         WinPrint("NMSG_ReadString: read overflow\n");
615                         string[l] = 0;
616                         return string;
617                 } //end if
618                 c = msg->data[msg->read];
619                 msg->read++;
620                 if (c == 0) break;
621                 string[l] = c;
622                 l++;
623         } while (l < sizeof(string)-1);
624         string[l] = 0;
625         return string;
626 } //end of the function NMSG_ReadString