source: trunk/libtransmission/net.c @ 26

Last change on this file since 26 was 26, checked in by root, 16 years ago

Update 2006-01-11

File size: 4.8 KB
Line 
1/******************************************************************************
2 * Copyright (c) 2005 Eric Petit
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 *****************************************************************************/
22
23#include "transmission.h"
24
25static int makeSocketNonBlocking( int s )
26{
27    int flags;
28
29#ifdef SYS_BEOS
30    flags = 1;
31    if( setsockopt( s, SOL_SOCKET, SO_NONBLOCK,
32                    &flags, sizeof( int ) ) < 0 )
33#else
34    if( ( flags = fcntl( s, F_GETFL, 0 ) ) < 0 ||
35        fcntl( s, F_SETFL, flags | O_NONBLOCK ) < 0 )
36#endif
37    {
38        tr_err( "Could not set socket to non-blocking mode (%s)",
39                strerror( errno ) );
40        tr_netClose( s );
41        return -1;
42    }
43
44    return s;
45}
46
47static int createSocket()
48{
49    int s;
50
51    s = socket( AF_INET, SOCK_STREAM, 0 );
52    if( s < 0 )
53    {
54        tr_err( "Could not create socket (%s)", strerror( errno ) );
55        return -1;
56    }
57
58    return makeSocketNonBlocking( s );
59}
60
61int tr_netResolve( char * address, struct in_addr * addr )
62{
63    struct hostent * host;
64
65    addr->s_addr = inet_addr( address );
66    if( addr->s_addr != 0xFFFFFFFF )
67    {
68        return 0;
69    }
70
71    if( !( host = gethostbyname( address ) ) )
72    {
73        tr_err( "Could not resolve (%s)", address );
74        return -1;
75    }
76    memcpy( addr, host->h_addr, host->h_length );
77
78    return 0;
79}
80
81int tr_netOpen( struct in_addr addr, in_port_t port )
82{
83    int s;
84    struct sockaddr_in sock;
85
86    s = createSocket();
87    if( s < 0 )
88    {
89        return -1;
90    }
91
92    memset( &sock, 0, sizeof( sock ) );
93    sock.sin_family      = AF_INET;
94    sock.sin_addr.s_addr = addr.s_addr;
95    sock.sin_port        = port;
96
97    if( connect( s, (struct sockaddr *) &sock,
98                 sizeof( struct sockaddr_in ) ) < 0 &&
99        errno != EINPROGRESS )
100    {
101        tr_err( "Could not connect socket (%s)", strerror( errno ) );
102        tr_netClose( s );
103        return -1;
104    }
105
106    return s;
107}
108
109int tr_netBind( int port )
110{
111    int s;
112    struct sockaddr_in sock;
113#ifdef SO_REUSEADDR
114    int optval;
115#endif
116
117    s = createSocket();
118    if( s < 0 )
119    {
120        return -1;
121    }
122
123#ifdef SO_REUSEADDR
124    optval = 1;
125    setsockopt( s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof( optval ) );
126#endif
127
128    memset( &sock, 0, sizeof( sock ) );
129    sock.sin_family      = AF_INET;
130    sock.sin_addr.s_addr = INADDR_ANY;
131    sock.sin_port        = htons( port );
132
133    if( bind( s, (struct sockaddr *) &sock,
134               sizeof( struct sockaddr_in ) ) )
135    {
136        tr_err( "Could not bind port %d", port );
137        tr_netClose( s );
138        return -1;
139    }
140   
141    tr_inf( "Binded port %d", port );
142    listen( s, 5 );
143
144    return s;
145}
146
147int tr_netAccept( int s, struct in_addr * addr, in_port_t * port )
148{
149    int t;
150    unsigned len;
151    struct sockaddr_in sock;
152
153    len = sizeof( sock );
154    t   = accept( s, (struct sockaddr *) &sock, &len );
155
156    if( t < 0 )
157    {
158        return -1;
159    }
160   
161    *addr = sock.sin_addr;
162    *port = sock.sin_port;
163
164    return makeSocketNonBlocking( t );
165}
166
167int tr_netSend( int s, uint8_t * buf, int size )
168{
169    int ret;
170
171    ret = send( s, buf, size, 0 );
172    if( ret < 0 )
173    {
174        if( errno == ENOTCONN || errno == EAGAIN || errno == EWOULDBLOCK )
175        {
176            ret = TR_NET_BLOCK;
177        }
178        else
179        {
180            ret = TR_NET_CLOSE;
181        }
182    }
183
184    return ret;
185}
186
187int tr_netRecv( int s, uint8_t * buf, int size )
188{
189    int ret;
190
191    ret = recv( s, buf, size, 0 );
192    if( ret < 0 )
193    {
194        if( errno == EAGAIN || errno == EWOULDBLOCK )
195        {
196            ret = TR_NET_BLOCK;
197        }
198        else
199        {
200            ret = TR_NET_CLOSE;
201        }
202    }
203    if( !ret )
204    {
205        ret = TR_NET_CLOSE;
206    }
207
208    return ret;
209}
210
211void tr_netClose( int s )
212{
213#ifdef BEOS_NETSERVER
214    closesocket( s );
215#else
216    close( s );
217#endif
218}
Note: See TracBrowser for help on using the repository browser.