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