source: trunk/libtransmission/net.c @ 7154

Last change on this file since 7154 was 7154, checked in by charles, 12 years ago

(libT) yet another stab at getting bandwidth management under control. this version may suck less than previous attempts. It also breaks the mac build until someone adds iobuf.[ch] to xcode...

  • Property svn:keywords set to Date Rev Author Id
File size: 6.2 KB
Line 
1/******************************************************************************
2 * $Id: net.c 7154 2008-11-25 21:35:17Z charles $
3 *
4 * Copyright (c) 2005-2008 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#include <errno.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30#include <sys/types.h>
31
32#ifdef WIN32
33 #include <winsock2.h> /* inet_addr */
34#else
35 #include <arpa/inet.h> /* inet_addr */
36 #include <netdb.h>
37 #include <fcntl.h>
38#endif
39
40#include <evutil.h>
41
42#include "transmission.h"
43#include "fdlimit.h"
44#include "natpmp.h"
45#include "net.h"
46#include "peer-io.h"
47#include "platform.h"
48#include "utils.h"
49
50
51void
52tr_netInit( void )
53{
54    static int initialized = FALSE;
55
56    if( !initialized )
57    {
58#ifdef WIN32
59        WSADATA wsaData;
60        WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
61#endif
62        initialized = TRUE;
63    }
64}
65
66/***********************************************************************
67 * DNS resolution
68 *
69 * Synchronous "resolution": only works with character strings
70 * representing numbers expressed in the Internet standard `.' notation.
71 * Returns a non-zero value if an error occurs.
72 **********************************************************************/
73int
74tr_netResolve( const char *     address,
75               struct in_addr * addr )
76{
77    addr->s_addr = inet_addr( address );
78    return addr->s_addr == 0xFFFFFFFF;
79}
80
81/***********************************************************************
82 * TCP sockets
83 **********************************************************************/
84
85int
86tr_netSetTOS( int s,
87              int tos )
88{
89#ifdef IP_TOS
90    return setsockopt( s, IPPROTO_IP, IP_TOS, (char*)&tos, sizeof( tos ) );
91#else
92    return 0;
93#endif
94}
95
96static int
97makeSocketNonBlocking( int fd )
98{
99    if( fd >= 0 )
100    {
101#if defined( __BEOS__ )
102        int flags = 1;
103        if( setsockopt( fd, SOL_SOCKET, SO_NONBLOCK,
104                       &flags, sizeof( int ) ) < 0 )
105#else
106        if( evutil_make_socket_nonblocking( fd ) )
107#endif
108        {
109            tr_err( _( "Couldn't create socket: %s" ),
110                   tr_strerror( sockerrno ) );
111            tr_netClose( fd );
112            fd = -1;
113        }
114    }
115
116    return fd;
117}
118
119static int
120createSocket( int type )
121{
122    return makeSocketNonBlocking( tr_fdSocketCreate( type ) );
123}
124
125static void
126setSndBuf( tr_session * session, int fd )
127{
128    if( fd >= 0 )
129    {
130        const int sndbuf = session->so_sndbuf;
131        const int rcvbuf = session->so_rcvbuf;
132        setsockopt( fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof( sndbuf ) );
133        setsockopt( fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof( rcvbuf ) );
134    }
135}
136
137int
138tr_netOpenTCP( tr_session            * session,
139               const struct in_addr  * addr,
140               tr_port_t               port )
141{
142    int                s;
143    struct sockaddr_in sock;
144    const int          type = SOCK_STREAM;
145
146    if( ( s = createSocket( type ) ) < 0 )
147        return -1;
148
149    setSndBuf( session, s );
150
151    memset( &sock, 0, sizeof( sock ) );
152    sock.sin_family      = AF_INET;
153    sock.sin_addr.s_addr = addr->s_addr;
154    sock.sin_port        = port;
155
156    if( ( connect( s, (struct sockaddr *) &sock,
157                  sizeof( struct sockaddr_in ) ) < 0 )
158#ifdef WIN32
159      && ( sockerrno != WSAEWOULDBLOCK )
160#endif
161      && ( sockerrno != EINPROGRESS ) )
162    {
163        tr_err( _(
164                   "Couldn't connect socket %d to %s, port %d (errno %d - %s)" ),
165               s, inet_ntoa( *addr ), port,
166               sockerrno, tr_strerror( sockerrno ) );
167        tr_netClose( s );
168        s = -1;
169    }
170
171    tr_deepLog( __FILE__, __LINE__, NULL, "New OUTGOING connection %d (%s)",
172               s, tr_peerIoAddrStr( addr, port ) );
173
174    return s;
175}
176
177int
178tr_netBindTCP( int port )
179{
180    int                s;
181    struct sockaddr_in sock;
182    const int          type = SOCK_STREAM;
183
184#if defined( SO_REUSEADDR ) || defined( SO_REUSEPORT )
185    int                optval;
186#endif
187
188    if( ( s = createSocket( type ) ) < 0 )
189        return -1;
190
191#ifdef SO_REUSEADDR
192    optval = 1;
193    setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof( optval ) );
194#endif
195
196    memset( &sock, 0, sizeof( sock ) );
197    sock.sin_family      = AF_INET;
198    sock.sin_addr.s_addr = INADDR_ANY;
199    sock.sin_port        = htons( port );
200
201    if( bind( s, (struct sockaddr *) &sock,
202             sizeof( struct sockaddr_in ) ) )
203    {
204        tr_err( _( "Couldn't bind port %d: %s" ), port,
205               tr_strerror( sockerrno ) );
206        tr_netClose( s );
207        return -1;
208    }
209
210    tr_dbg(  "Bound socket %d to port %d", s, port );
211    return s;
212}
213
214int
215tr_netAccept( tr_session      * session,
216              int               b,
217              struct in_addr  * addr,
218              tr_port_t       * port )
219{
220    int fd = makeSocketNonBlocking( tr_fdSocketAccept( b, addr, port ) );
221    setSndBuf( session, fd );
222    return fd;
223}
224
225void
226tr_netClose( int s )
227{
228    tr_fdSocketClose( s );
229}
230
231void
232tr_netNtop( const struct in_addr * addr,
233            char *                 buf,
234            int                    len )
235{
236    const uint8_t * cast;
237
238    cast = (const uint8_t *)addr;
239    tr_snprintf( buf, len, "%hhu.%hhu.%hhu.%hhu",
240                 cast[0], cast[1], cast[2], cast[3] );
241}
242
Note: See TracBrowser for help on using the repository browser.