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