*** empty log message ***
[chuck-blob.git] / v2 / util_network.c
blob27743f0b0bcb52011bc065e54a4e91bdf68a29cf
1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 U.S.A.
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // name: util_network.c
27 // desc: sockets
28 //
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
32 // originally randy_socket
33 // author: Peng Bi (pbi@cs.princeton.edu)
34 // Ge Wang (gewang@cs.princeton.edu)
35 // date: Winter 2003
36 //-----------------------------------------------------------------------------
37 #include "util_network.h"
38 #include "chuck_utils.h"
39 #include <stdio.h>
41 #if defined(__PLATFORM_WIN32__)
42 #include <winsock.h>
43 #else
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <sys/time.h>
47 #include <unistd.h>
48 #include <netinet/in.h>
49 #include <netinet/tcp.h>
50 #include <arpa/inet.h>
51 #include <netdb.h>
52 #endif
57 #ifdef __PLATFORM_WIN32__
58 static WSADATA g_wsd;
59 static int g_init = 0;
60 #endif
62 #ifndef socklen_t
63 #define socklen_t unsigned int
64 #endif
67 //-----------------------------------------------------------------------------
68 // name: struct ck_socket_
69 // desc: ...
70 //-----------------------------------------------------------------------------
71 struct ck_socket_
73 int sock;
74 int prot;
75 struct sockaddr_in sock_in;
76 socklen_t len;
82 //-----------------------------------------------------------------------------
83 // name: ck_udp_create()
84 // desc: create a udp socket
85 //-----------------------------------------------------------------------------
86 ck_socket ck_udp_create( )
88 ck_socket sock = NULL;
90 #ifdef __PLATFORM_WIN32__
91 // winsock init
92 if( g_init == 0 )
93 if( WSAStartup( MAKEWORD(1,1), &(g_wsd) ) != 0 &&
94 WSAStartup( MAKEWORD(1,0), &(g_wsd) ) != 0 )
96 fprintf( stderr, "[chuck]: cannot start winsock, networking disabled...\n" );
97 return NULL;
100 // count
101 g_init++;
102 #endif
104 sock = (ck_socket)checked_malloc( sizeof( struct ck_socket_ ) );
105 sock->sock = socket( AF_INET, SOCK_DGRAM, 0 );
106 sock->prot = SOCK_DGRAM;
108 return sock;
114 //-----------------------------------------------------------------------------
115 // name: ck_tcp_create()
116 // desc: create a tcp socket
117 //-----------------------------------------------------------------------------
118 ck_socket ck_tcp_create( int flags )
120 ck_socket sock = (ck_socket)checked_malloc( sizeof( struct ck_socket_ ) );
121 int nd = 1; int ru = 1;
123 #ifdef __PLATFORM_WIN32__
124 // winsock init
125 if( g_init == 0 )
126 if( WSAStartup( MAKEWORD(1,1), &(g_wsd) ) != 0 &&
127 WSAStartup( MAKEWORD(1,0), &(g_wsd) ) != 0 )
129 fprintf( stderr, "[chuck]: cannot start winsock, networking disabled...\n" );
130 return NULL;
133 // count
134 g_init++;
135 #endif
137 sock->sock = socket( AF_INET, SOCK_STREAM, 0 );
138 sock->prot = SOCK_STREAM;
140 if( flags )
141 setsockopt( sock->sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&ru, sizeof(ru) );
142 // setsockopt( sock->sock, SOL_SOCKET, SO_REUSEPORT, (const char *)&ru, sizeof(ru) );
143 setsockopt( sock->sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&nd, sizeof(nd) );
145 return sock;
151 //-----------------------------------------------------------------------------
152 // name: ck_connect2()
153 // desc: connect to a server
154 //-----------------------------------------------------------------------------
155 t_CKBOOL ck_connect2( ck_socket sock, const struct sockaddr * addr, int size )
157 int ret = connect( sock->sock, addr, size );
159 return ( ret >= 0 );
165 //-----------------------------------------------------------------------------
166 // name: ck_connect()
167 // desc: connect to a server
168 //-----------------------------------------------------------------------------
169 t_CKBOOL ck_connect( ck_socket sock, const char * hostname, int port )
171 int ret;
172 struct hostent * host;
174 #ifdef __PLATFORM_WIN32__
175 memset( &sock->sock_in, 0, sizeof(struct sockaddr_in) );
176 #else
177 bzero( &sock->sock_in, sizeof(struct sockaddr_in) );
178 #endif
180 sock->sock_in.sin_family = AF_INET;
181 sock->sock_in.sin_port = htons( (unsigned short)abs(port) );
182 // lookup name
183 host = gethostbyname( hostname );
184 if( !host )
186 sock->sock_in.sin_addr.s_addr = inet_addr( hostname );
187 if( sock->sock_in.sin_addr.s_addr == -1 )
188 return FALSE;
190 else
192 #ifdef __PLATFORM_WIN32__
193 memcpy( (char *)&sock->sock_in.sin_addr, host->h_addr, host->h_length );
194 #else
195 bcopy( host->h_addr, (char *)&sock->sock_in.sin_addr, host->h_length );
196 #endif
199 if( port < 0 )
200 return TRUE;
202 ret = ck_connect2( sock, (struct sockaddr *)&sock->sock_in,
203 sizeof( struct sockaddr_in ) );
205 return ( ret >= 0 );
211 //-----------------------------------------------------------------------------
212 // name: ck_bind()
213 // desc: bind to a port
214 //-----------------------------------------------------------------------------
215 t_CKBOOL ck_bind( ck_socket sock, int port )
217 int ret;
219 #ifdef __PLATFORM_WIN32__
220 memset( &sock->sock_in, 0, sizeof(struct sockaddr_in) );
221 #else
222 bzero( &sock->sock_in, sizeof(struct sockaddr_in) );
223 #endif
225 sock->sock_in.sin_family = AF_INET;
226 sock->sock_in.sin_port = htons( (unsigned short)port );
227 sock->sock_in.sin_addr.s_addr = htonl( INADDR_ANY );
229 ret = bind( sock->sock, (struct sockaddr *)&sock->sock_in,
230 sizeof(struct sockaddr_in));
232 return ( ret >= 0 );
238 //-----------------------------------------------------------------------------
239 // name: ck_listen()
240 // desc: ...
241 //-----------------------------------------------------------------------------
242 t_CKBOOL ck_listen( ck_socket sock, int backlog )
244 int ret;
246 if( sock->prot != SOCK_STREAM ) return FALSE;
247 ret = listen( sock->sock, backlog );
249 return ( ret >= 0 );
255 //-----------------------------------------------------------------------------
256 // name: ck_accept()
257 // desc: ...
258 //-----------------------------------------------------------------------------
259 ck_socket ck_accept( ck_socket sock )
261 ck_socket client;
262 int nd = 1;
264 if( sock->prot != SOCK_STREAM ) return NULL;
265 client = (ck_socket)checked_malloc( sizeof( struct ck_socket_ ) );
266 client->len = sizeof( client->sock_in );
267 client->sock = accept( sock->sock, (struct sockaddr *)&client->sock_in,
268 &client->len );
269 if( client->sock <= 0 ) goto error;
270 client->prot = SOCK_STREAM;
271 setsockopt( client->sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&nd, sizeof(nd) );
273 #ifdef __PLATFORM_WIN32__
274 g_init++;
275 #endif
277 return client;
279 error:
280 free( client );
281 return NULL;
287 //-----------------------------------------------------------------------------
288 // name: ck_send()
289 // desc: send a datagram
290 //-----------------------------------------------------------------------------
291 int ck_send( ck_socket sock, const char * buffer, int len )
293 return send( sock->sock, buffer, len, 0 );
299 //-----------------------------------------------------------------------------
300 // name: ck_send2()
301 // desc: send a datagram
302 //-----------------------------------------------------------------------------
303 int ck_send2( ck_socket sock, const char * buffer, int len )
305 return sendto( sock->sock, buffer, len, 0,
306 (struct sockaddr *)&sock->sock_in, sizeof(struct sockaddr_in) );
312 //-----------------------------------------------------------------------------
313 // name: ck_sendto()
314 // desc: send a datagram
315 //-----------------------------------------------------------------------------
316 int ck_sendto( ck_socket sock, const char * buffer, int len,
317 const struct sockaddr * to, int tolen )
319 if( sock->prot == SOCK_STREAM ) return 0;
320 else return sendto( sock->sock, buffer, len, 0, to, tolen );
326 //-----------------------------------------------------------------------------
327 // name: ck_recvfrom()
328 // desc: recv a datagram
329 //-----------------------------------------------------------------------------
330 int ck_recvfrom( ck_socket sock, char * buffer, int len,
331 struct sockaddr * from, int * fromlen )
333 if( sock->prot == SOCK_STREAM )
335 memset( buffer, 0, len );
336 return 0;
338 else return recvfrom( sock->sock, buffer, len, 0, from, (unsigned int *)fromlen );
344 //-----------------------------------------------------------------------------
345 // name: ck_recv()
346 // desc: recv a datagram
347 //-----------------------------------------------------------------------------
348 int ck_recv( ck_socket sock, char * buffer, int len )
350 if( sock->prot == SOCK_STREAM )
352 int ret;
353 int togo = len;
354 char * p = buffer;
355 while( togo > 0 )
357 ret = recv( sock->sock, p, togo, 0 );
358 if( ret < 0 ) return 0; // negative is an error message
359 if( ret == 0 ) return len - togo; // zero is end-of-transmission
360 togo -= ret;
361 p += ret;
363 return len;
365 else return recv( sock->sock, buffer, len, 0 );
371 //-----------------------------------------------------------------------------
372 // name: ck_recv2()
373 // desc: recv a datagram
374 //-----------------------------------------------------------------------------
375 int ck_recv2( ck_socket sock, char * buffer, int len )
377 struct sockaddr_in from;
378 unsigned int flen;
379 memset( &from, 0, sizeof(from) );
380 flen = sizeof(struct sockaddr_in);
381 return recvfrom( sock->sock, buffer, len, 0, (struct sockaddr *)&from, &flen );
387 //-----------------------------------------------------------------------------
388 // name: ck_send_timeout()
389 // desc: ...
390 //-----------------------------------------------------------------------------
391 int ck_send_timeout( ck_socket sock, long sec, long usec )
393 struct timeval t;
394 t.tv_sec = sec;
395 t.tv_usec = usec;
397 return 0 == setsockopt( sock->sock, SOL_SOCKET, SO_SNDTIMEO, (const char *)&t, sizeof(t) );
403 //-----------------------------------------------------------------------------
404 // name: ck_recv_timeout()
405 // desc: ...
406 //-----------------------------------------------------------------------------
407 int ck_recv_timeout( ck_socket sock, long sec, long usec )
409 struct timeval t;
410 t.tv_sec = sec;
411 t.tv_usec = usec;
413 return 0 == setsockopt( sock->sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&t, sizeof(t) );
419 //-----------------------------------------------------------------------------
420 // name: ck_close()
421 // close the socket
422 //-----------------------------------------------------------------------------
423 void ck_close( ck_socket sock )
425 if( !sock ) return;
427 #ifdef __PLATFORM_WIN32__
428 closesocket( sock->sock );
429 #else
430 close( sock->sock );
431 #endif
433 free( sock );
435 #ifdef __PLATFORM_WIN32__
436 // uncount
437 g_init--;
439 // close
440 if( g_init == 0 ) WSACleanup();
441 #endif