]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/l_net/l_net.c
* fixed a warning and an error in the overflow check in l_net
[xonotic/netradiant.git] / libs / l_net / l_net.c
1 /*
2 Copyright (C) 1999-2007 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 #endif
88 #ifdef __linux__
89         return strcasecmp(addr1->ip, addr2->ip);
90 #endif
91 } //end of the function Net_AddressCompare
92 //===========================================================================
93 //
94 // Parameter:                           -
95 // Returns:                                     -
96 // Changes Globals:             -
97 //===========================================================================
98 void Net_SocketToAddress(socket_t *sock, address_t *address)
99 {
100         strcpy(address->ip, WINS_AddrToString(&sock->addr));
101 } //end of the function Net_SocketToAddress
102 //===========================================================================
103 //
104 // Parameter:                           -
105 // Returns:                                     -
106 // Changes Globals:             -
107 //===========================================================================
108 int Net_Send(socket_t *sock, netmessage_t *msg)
109 {
110         int size;
111
112         size = msg->size;
113         msg->size = 0;
114         NMSG_WriteLong(msg, size-4);
115         msg->size = size;
116         //WinPrint("Net_Send: message of size %d\n", sendmsg.size);
117         return WINS_Write(sock->socket, msg->data, msg->size, NULL);
118 } //end of the function Net_SendSocketReliable
119 //===========================================================================
120 // returns the number of bytes recieved
121 // -1 on error
122 //
123 // Parameter:                           -
124 // Returns:                                     -
125 // Changes Globals:             -
126 //===========================================================================
127 int Net_Receive(socket_t *sock, netmessage_t *msg)
128 {
129         int curread;
130
131         if (sock->remaining > 0)
132         {
133                 curread = WINS_Read(sock->socket, &sock->msg.data[sock->msg.size], sock->remaining, NULL);
134                 if (curread == -1)
135                 {
136                         WinPrint("Net_Receive: read error\n");
137                         return -1;
138                 } //end if
139                 sock->remaining -= curread;
140                 sock->msg.size += curread;
141                 if (sock->remaining <= 0)
142                 {
143                         sock->remaining = 0;
144                         memcpy(msg, &sock->msg, sizeof(netmessage_t));
145                         sock->msg.size = 0;
146                         return msg->size - 4;
147                 } //end if
148                 return 0;
149         } //end if
150         sock->msg.size = WINS_Read(sock->socket, sock->msg.data, 4, NULL);
151         if (sock->msg.size == 0) return 0;
152         if (sock->msg.size == -1)
153         {
154                 WinPrint("Net_Receive: size header read error\n");
155                 return -1;
156         } //end if
157         //WinPrint("Net_Receive: message size header %d\n", msg->size);
158         sock->msg.read = 0;
159         sock->remaining = NMSG_ReadLong(&sock->msg);
160         if (sock->remaining == 0) return 0;
161         if (sock->remaining < 0 || sock->remaining > MAX_NETMESSAGE)
162         {
163                 WinPrint("Net_Receive: invalid message size %d\n", sock->remaining);
164                 return -1;
165         } //end if
166         //try to read the message
167         curread = WINS_Read(sock->socket, &sock->msg.data[sock->msg.size], sock->remaining, NULL);
168         if (curread == -1)
169         {
170                 WinPrint("Net_Receive: read error\n");
171                 return -1;
172         } //end if
173         sock->remaining -= curread;
174         sock->msg.size += curread;
175         if (sock->remaining <= 0)
176         {
177                 sock->remaining = 0;
178                 memcpy(msg, &sock->msg, sizeof(netmessage_t));
179                 sock->msg.size = 0;
180                 return msg->size - 4;
181         } //end if
182         //the message has not been completely read yet
183 #ifdef _DEBUG
184   printf("++timo TODO: debug the Net_Receive on big size messages\n");
185 #endif
186         return 0;
187 } //end of the function Net_Receive
188 //===========================================================================
189 //
190 // Parameter:                           -
191 // Returns:                                     -
192 // Changes Globals:             -
193 //===========================================================================
194 socket_t *Net_AllocSocket(void)
195 {
196         socket_t *sock;
197
198         sock = (socket_t *) GetMemory(sizeof(socket_t));
199         memset(sock, 0, sizeof(socket_t));
200         return sock;
201 } //end of the function Net_AllocSocket
202 //===========================================================================
203 //
204 // Parameter:                           -
205 // Returns:                                     -
206 // Changes Globals:             -
207 //===========================================================================
208 void Net_FreeSocket(socket_t *sock)
209 {
210         FreeMemory(sock);
211 } //end of the function Net_FreeSocket
212 //===========================================================================
213 //
214 // Parameter:                           -
215 // Returns:                                     -
216 // Changes Globals:             -
217 //===========================================================================
218 socket_t *Net_Connect(address_t *address, int port)
219 {
220         int newsock;
221         socket_t *sock;
222         sockaddr_t sendaddr;
223
224         // see if we can resolve the host name
225         WINS_StringToAddr(address->ip, &sendaddr);
226
227   newsock = WINS_OpenReliableSocket(port);
228         if (newsock == -1) return NULL;
229
230         sock = Net_AllocSocket();
231         if (sock == NULL)
232         {
233                 WINS_CloseSocket(newsock);
234                 return NULL;
235         } //end if
236         sock->socket = newsock;
237
238         //connect to the host
239         if (WINS_Connect(newsock, &sendaddr) == -1)
240         {
241                 Net_FreeSocket(sock);
242                 WINS_CloseSocket(newsock);
243                 WinPrint("Net_Connect: error connecting\n");
244                 return NULL;
245         } //end if
246
247         memcpy(&sock->addr, &sendaddr, sizeof(sockaddr_t));
248         //now we can send messages
249         //
250         return sock;
251 } //end of the function Net_Connect
252
253 //===========================================================================
254 //
255 // Parameter:                           -
256 // Returns:                                     -
257 // Changes Globals:             -
258 //===========================================================================
259 socket_t *Net_ListenSocket(int port)
260 {
261         int newsock;
262         socket_t *sock;
263
264         newsock = WINS_OpenReliableSocket(port);
265         if (newsock == -1) return NULL;
266
267         if (WINS_Listen(newsock) == -1)
268         {
269                 WINS_CloseSocket(newsock);
270                 return NULL;
271         } //end if
272         sock = Net_AllocSocket();
273         if (sock == NULL)
274         {
275                 WINS_CloseSocket(newsock);
276                 return NULL;
277         } //end if
278         sock->socket = newsock;
279         WINS_GetSocketAddr(newsock, &sock->addr);
280         WinPrint("listen socket opened at %s\n", WINS_AddrToString(&sock->addr));
281         //
282         return sock;
283 } //end of the function Net_ListenSocket
284 //===========================================================================
285 //
286 // Parameter:                           -
287 // Returns:                                     -
288 // Changes Globals:             -
289 //===========================================================================
290 socket_t *Net_Accept(socket_t *sock)
291 {
292         int newsocket;
293         sockaddr_t sendaddr;
294         socket_t *newsock;
295
296         newsocket = WINS_Accept(sock->socket, &sendaddr);
297         if (newsocket == -1) return NULL;
298
299         newsock = Net_AllocSocket();
300         if (newsock == NULL)
301         {
302                 WINS_CloseSocket(newsocket);
303                 return NULL;
304         } //end if
305         newsock->socket = newsocket;
306         memcpy(&newsock->addr, &sendaddr, sizeof(sockaddr_t));
307         //
308         return newsock;
309 } //end of the function Net_Accept
310 //===========================================================================
311 //
312 // Parameter:                           -
313 // Returns:                                     -
314 // Changes Globals:             -
315 //===========================================================================
316 void Net_Disconnect(socket_t *sock)
317 {
318         WINS_CloseSocket(sock->socket);
319         Net_FreeSocket(sock);
320 } //end of the function Net_Disconnect
321 //===========================================================================
322 //
323 // Parameter:                           -
324 // Returns:                                     -
325 // Changes Globals:             -
326 //===========================================================================
327 void Net_StringToAddress(char *string, address_t *address)
328 {
329         strcpy(address->ip, string);
330 } //end of the function Net_StringToAddress
331 //===========================================================================
332 //
333 // Parameter:                           -
334 // Returns:                                     -
335 // Changes Globals:             -
336 //===========================================================================
337 void Net_MyAddress(address_t *address)
338 {
339         strcpy(address->ip, WINS_MyAddress());
340 } //end of the function Net_MyAddress
341 //===========================================================================
342 //
343 // Parameter:                           -
344 // Returns:                                     -
345 // Changes Globals:             -
346 //===========================================================================
347 int Net_Setup(void)
348 {
349         if( !WINS_Init() )
350                 return qfalse;
351
352         //
353         WinPrint("my address is %s\n", WINS_MyAddress());
354         //
355         return qtrue;
356 } //end of the function Net_Setup
357 //===========================================================================
358 //
359 // Parameter:                           -
360 // Returns:                                     -
361 // Changes Globals:             -
362 //===========================================================================
363 void Net_Shutdown(void)
364 {
365         WINS_Shutdown();
366 } //end of the function Net_Shutdown
367 //===========================================================================
368 //
369 // Parameter:                           -
370 // Returns:                                     -
371 // Changes Globals:             -
372 //===========================================================================
373 void NMSG_Clear(netmessage_t *msg)
374 {
375         msg->size = 4;
376 } //end of the function NMSG_Clear
377 //===========================================================================
378 //
379 // Parameter:                           -
380 // Returns:                                     -
381 // Changes Globals:             -
382 //===========================================================================
383 void NMSG_WriteChar (netmessage_t *msg, int c)
384 {
385         if (c < -128 || c > 127)
386                 WinPrint("NMSG_WriteChar: range error\n");
387
388         if (msg->size >= MAX_NETMESSAGE)
389         {
390                 WinPrint("NMSG_WriteChar: overflow\n");
391                 return;
392         } //end if
393         msg->data[msg->size] = c;
394         msg->size++;
395 } //end of the function NMSG_WriteChar
396 //===========================================================================
397 //
398 // Parameter:                           -
399 // Returns:                                     -
400 // Changes Globals:             -
401 //===========================================================================
402 void NMSG_WriteByte(netmessage_t *msg, int c)
403 {
404         if (c < -128 || c > 127)
405                 WinPrint("NMSG_WriteByte: range error\n");
406
407         if (msg->size + 1 >= MAX_NETMESSAGE)
408         {
409                 WinPrint("NMSG_WriteByte: overflow\n");
410                 return;
411         } //end if
412         msg->data[msg->size] = c;
413         msg->size++;
414 } //end of the function NMSG_WriteByte
415 //===========================================================================
416 //
417 // Parameter:                           -
418 // Returns:                                     -
419 // Changes Globals:             -
420 //===========================================================================
421 void NMSG_WriteShort(netmessage_t *msg, int c)
422 {
423         if (c < ((short)0x8000) || c > (short)0x7fff)
424                 WinPrint("NMSG_WriteShort: range error");
425
426         if (msg->size + 2 >= MAX_NETMESSAGE)
427         {
428                 WinPrint("NMSG_WriteShort: overflow\n");
429                 return;
430         } //end if
431         msg->data[msg->size] = c&0xff;
432         msg->data[msg->size+1] = c>>8;
433         msg->size += 2;
434 } //end of the function NMSG_WriteShort
435 //===========================================================================
436 //
437 // Parameter:                           -
438 // Returns:                                     -
439 // Changes Globals:             -
440 //===========================================================================
441 void NMSG_WriteLong(netmessage_t *msg, int c)
442 {
443         if (msg->size + 4 >= MAX_NETMESSAGE)
444         {
445                 WinPrint("NMSG_WriteLong: overflow\n");
446                 return;
447         } //end if
448         msg->data[msg->size] = c&0xff;
449         msg->data[msg->size+1] = (c>>8)&0xff;
450         msg->data[msg->size+2] = (c>>16)&0xff;
451         msg->data[msg->size+3] = c>>24;
452         msg->size += 4;
453 } //end of the function NMSG_WriteLong
454 //===========================================================================
455 //
456 // Parameter:                           -
457 // Returns:                                     -
458 // Changes Globals:             -
459 //===========================================================================
460 void NMSG_WriteFloat(netmessage_t *msg, float c)
461 {
462         if (msg->size + 4 >= MAX_NETMESSAGE)
463         {
464                 WinPrint("NMSG_WriteLong: overflow\n");
465                 return;
466         } //end if
467         msg->data[msg->size] = *((int *)&c)&0xff;
468         msg->data[msg->size+1] = (*((int *)&c)>>8)&0xff;
469         msg->data[msg->size+2] = (*((int *)&c)>>16)&0xff;
470         msg->data[msg->size+3] = *((int *)&c)>>24;
471         msg->size += 4;
472 } //end of the function NMSG_WriteFloat
473 //===========================================================================
474 //
475 // Parameter:                           -
476 // Returns:                                     -
477 // Changes Globals:             -
478 //===========================================================================
479 void NMSG_WriteString(netmessage_t *msg, char *string)
480 {
481         if (msg->size + strlen(string) + 1 >= MAX_NETMESSAGE)
482         {
483                 WinPrint("NMSG_WriteString: overflow\n");
484                 return;
485         } //end if
486         memcpy(&msg->data[msg->size], string, strlen(string) + 1);
487         msg->size += strlen(string) + 1;
488 } //end of the function NMSG_WriteString
489 //===========================================================================
490 //
491 // Parameter:                           -
492 // Returns:                                     -
493 // Changes Globals:             -
494 //===========================================================================
495 void NMSG_ReadStart(netmessage_t *msg)
496 {
497         msg->readoverflow = qfalse;
498         msg->read = 4;
499 } //end of the function NMSG_ReadStart
500 //===========================================================================
501 //
502 // Parameter:                           -
503 // Returns:                                     -
504 // Changes Globals:             -
505 //===========================================================================
506 int NMSG_ReadChar(netmessage_t *msg)
507 {
508         if (msg->read + 1 > msg->size)
509         {
510                 msg->readoverflow = qtrue;
511                 WinPrint("NMSG_ReadChar: read overflow\n");
512                 return 0;
513         } //end if
514         msg->read++;
515         return msg->data[msg->read-1];
516 } //end of the function NMSG_ReadChar
517 //===========================================================================
518 //
519 // Parameter:                           -
520 // Returns:                                     -
521 // Changes Globals:             -
522 //===========================================================================
523 int NMSG_ReadByte(netmessage_t *msg)
524 {
525         if (msg->read + 1 > msg->size)
526         {
527                 msg->readoverflow = qtrue;
528                 WinPrint("NMSG_ReadByte: read overflow\n");
529                 return 0;
530         } //end if
531         msg->read++;
532         return msg->data[msg->read-1];
533 } //end of the function NMSG_ReadByte
534 //===========================================================================
535 //
536 // Parameter:                           -
537 // Returns:                                     -
538 // Changes Globals:             -
539 //===========================================================================
540 int NMSG_ReadShort(netmessage_t *msg)
541 {
542         int c;
543
544         if (msg->read + 2 > msg->size)
545         {
546                 msg->readoverflow = qtrue;
547                 WinPrint("NMSG_ReadShort: read overflow\n");
548                 return 0;
549         } //end if
550         c = (short)(msg->data[msg->read] + (msg->data[msg->read+1]<<8));
551         msg->read += 2;
552         return c;
553 } //end of the function NMSG_ReadShort
554 //===========================================================================
555 //
556 // Parameter:                           -
557 // Returns:                                     -
558 // Changes Globals:             -
559 //===========================================================================
560 int NMSG_ReadLong(netmessage_t *msg)
561 {
562         int c;
563
564         if (msg->read + 4 > msg->size)
565         {
566                 msg->readoverflow = qtrue;
567                 WinPrint("NMSG_ReadLong: read overflow\n");
568                 return 0;
569         } //end if
570         c = msg->data[msg->read]
571                 + (msg->data[msg->read+1]<<8)
572                 + (msg->data[msg->read+2]<<16)
573                 + (msg->data[msg->read+3]<<24);
574         msg->read += 4;
575         return c;
576 } //end of the function NMSG_ReadLong
577 //===========================================================================
578 //
579 // Parameter:                           -
580 // Returns:                                     -
581 // Changes Globals:             -
582 //===========================================================================
583 float NMSG_ReadFloat(netmessage_t *msg)
584 {
585         int c;
586
587         if (msg->read + 4 > msg->size)
588         {
589                 msg->readoverflow = qtrue;
590                 WinPrint("NMSG_ReadLong: read overflow\n");
591                 return 0;
592         } //end if
593         c = msg->data[msg->read]
594                 + (msg->data[msg->read+1]<<8)
595                 + (msg->data[msg->read+2]<<16)
596                 + (msg->data[msg->read+3]<<24);
597         msg->read += 4;
598         return *(float *)&c;
599 } //end of the function NMSG_ReadFloat
600 //===========================================================================
601 //
602 // Parameter:                           -
603 // Returns:                                     -
604 // Changes Globals:             -
605 //===========================================================================
606 char *NMSG_ReadString(netmessage_t *msg)
607 {
608         static char     string[2048];
609         int l, c;
610
611         l = 0;
612         do
613         {
614                 if (msg->read + 1 > msg->size)
615                 {
616                         msg->readoverflow = qtrue;
617                         WinPrint("NMSG_ReadString: read overflow\n");
618                         string[l] = 0;
619                         return string;
620                 } //end if
621                 c = msg->data[msg->read];
622                 msg->read++;
623                 if (c == 0) break;
624                 string[l] = c;
625                 l++;
626         } while (l < sizeof(string)-1);
627         string[l] = 0;
628         return string;
629 } //end of the function NMSG_ReadString