source: trunk/libtransmission/net.c @ 1

Last change on this file since 1 was 1, checked in by root, 17 years ago

Import from 2005-10-26

File size: 5.0 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, i;
112    struct sockaddr_in sock;
113    int minPort, maxPort;
114
115    s = createSocket();
116    if( s < 0 )
117    {
118        return -1;
119    }
120
121    minPort = *port;
122    maxPort = minPort + 1000;
123    maxPort = MIN( maxPort, 65535 );
124
125    for( i = minPort; i <= maxPort; i++ )
126    {
127        memset( &sock, 0, sizeof( sock ) );
128        sock.sin_family      = AF_INET;
129        sock.sin_addr.s_addr = INADDR_ANY;
130        sock.sin_port        = htons( i );
131
132        if( !bind( s, (struct sockaddr *) &sock,
133                   sizeof( struct sockaddr_in ) ) )
134        {
135            break;
136        }
137    }
138
139    if( i > maxPort )
140    {
141        tr_netClose( s );
142        tr_err( "Could not bind any port from %d to %d",
143                minPort, maxPort );
144        return -1;
145    }
146   
147    tr_inf( "Binded port %d", i );
148    *port = i;
149    listen( s, 5 );
150
151    return s;
152}
153
154int tr_netAccept( int s, struct in_addr * addr, in_port_t * port )
155{
156    int t;
157    unsigned len;
158    struct sockaddr_in sock;
159
160    len = sizeof( sock );
161    t   = accept( s, (struct sockaddr *) &sock, &len );
162
163    if( t < 0 )
164    {
165        return -1;
166    }
167   
168    *addr = sock.sin_addr;
169    *port = sock.sin_port;
170
171    return makeSocketNonBlocking( t );
172}
173
174int tr_netSend( int s, uint8_t * buf, int size )
175{
176    int ret;
177
178    ret = send( s, buf, size, 0 );
179    if( ret < 0 )
180    {
181        if( errno == ENOTCONN || errno == EAGAIN || errno == EWOULDBLOCK )
182        {
183            ret = TR_NET_BLOCK;
184        }
185        else
186        {
187            ret = TR_NET_CLOSE;
188        }
189    }
190
191    return ret;
192}
193
194int tr_netRecv( int s, uint8_t * buf, int size )
195{
196    int ret;
197
198    ret = recv( s, buf, size, 0 );
199    if( ret < 0 )
200    {
201        if( errno == EAGAIN || errno == EWOULDBLOCK )
202        {
203            ret = TR_NET_BLOCK;
204        }
205        else
206        {
207            ret = TR_NET_CLOSE;
208        }
209    }
210    if( !ret )
211    {
212        ret = TR_NET_CLOSE;
213    }
214
215    return ret;
216}
217
218void tr_netClose( int s )
219{
220#ifdef BEOS_NETSERVER
221    closesocket( s );
222#else
223    close( s );
224#endif
225}
Note: See TracBrowser for help on using the repository browser.