~ubuntu-branches/ubuntu/hardy/transmission/hardy-updates

« back to all changes in this revision

Viewing changes to libtransmission/net.c

  • Committer: Bazaar Package Importer
  • Author(s): Philipp Benner
  • Date: 2007-10-26 16:02:39 UTC
  • mto: This revision was merged to the branch mainline in revision 6.
  • Revision ID: james.westby@ubuntu.com-20071026160239-2c0agn7q1ken0xsp
Tags: upstream-0.90.dfsg
ImportĀ upstreamĀ versionĀ 0.90.dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
 * $Id: net.c 2614 2007-08-04 01:17:39Z joshe $
 
2
 * $Id: net.c 3335 2007-10-09 02:49:24Z charles $
3
3
 *
4
4
 * Copyright (c) 2005-2006 Transmission authors and contributors
5
5
 *
34
34
#include <fcntl.h>
35
35
#endif
36
36
 
 
37
#include <evutil.h>
 
38
 
37
39
#include "transmission.h"
38
40
#include "fdlimit.h"
39
41
#include "net.h"
57
59
 
58
60
/***********************************************************************
59
61
 * DNS resolution
60
 
 **********************************************************************/
61
 
 
62
 
/***********************************************************************
63
 
 * tr_netResolve
64
 
 ***********************************************************************
 
62
 * 
65
63
 * Synchronous "resolution": only works with character strings
66
64
 * representing numbers expressed in the Internet standard `.' notation.
67
65
 * Returns a non-zero value if an error occurs.
72
70
    return ( addr->s_addr == 0xFFFFFFFF );
73
71
}
74
72
 
75
 
static tr_thread_t  * resolveThread;
76
 
static tr_lock_t    * resolveLock;
77
 
static tr_cond_t    * resolveCond;
78
 
static volatile int   resolveDie;
79
 
static tr_resolve_t * resolveQueue;
80
 
 
81
 
static void resolveRelease ( tr_resolve_t * );
82
 
static void resolveFunc    ( void * );
83
 
 
84
 
struct tr_resolve_s
85
 
{
86
 
    tr_tristate_t  status;
87
 
    char           * address;
88
 
    struct in_addr addr;
89
 
 
90
 
    int            refcount;
91
 
    tr_resolve_t   * next;
92
 
};
93
 
 
94
 
/***********************************************************************
95
 
 * tr_netResolveThreadInit
96
 
 ***********************************************************************
97
 
 * Initializes the static variables used for resolution and launch the
98
 
 * gethostbyname thread.
99
 
 **********************************************************************/
100
 
void tr_netResolveThreadInit( void )
101
 
{
102
 
    resolveDie   = 0;
103
 
    resolveQueue = NULL;
104
 
    resolveLock = tr_lockNew( );
105
 
    resolveCond = tr_condNew( );
106
 
    resolveThread = tr_threadNew( resolveFunc, NULL, "resolve" );
107
 
}
108
 
 
109
 
/***********************************************************************
110
 
 * tr_netResolveThreadClose
111
 
 ***********************************************************************
112
 
 * Notices the gethostbyname thread that is should terminate. Doesn't
113
 
 * wait until it does, in case it is stuck in a resolution: we let it
114
 
 * die and clean itself up.
115
 
 **********************************************************************/
116
 
void tr_netResolveThreadClose( void )
117
 
{
118
 
    tr_lockLock( resolveLock );
119
 
    resolveDie = 1;
120
 
    tr_lockUnlock( resolveLock );
121
 
    tr_condSignal( resolveCond );
122
 
    tr_wait( 200 );
123
 
}
124
 
 
125
 
/***********************************************************************
126
 
 * tr_netResolveInit
127
 
 ***********************************************************************
128
 
 * Adds an address to the resolution queue.
129
 
 **********************************************************************/
130
 
tr_resolve_t * tr_netResolveInit( const char * address )
131
 
{
132
 
    tr_resolve_t * r = tr_new0( tr_resolve_t, 1 );
133
 
    r->status   = TR_NET_WAIT;
134
 
    r->address  = strdup( address );
135
 
    r->refcount = 2;
136
 
    r->next     = NULL;
137
 
 
138
 
    tr_lockLock( resolveLock );
139
 
    if( !resolveQueue )
140
 
    {
141
 
        resolveQueue = r;
142
 
    }
143
 
    else
144
 
    {
145
 
        tr_resolve_t * iter;
146
 
        for( iter = resolveQueue; iter->next; iter = iter->next );
147
 
        iter->next = r;
148
 
    }
149
 
    tr_lockUnlock( resolveLock );
150
 
    tr_condSignal( resolveCond );
151
 
 
152
 
    return r;
153
 
}
154
 
 
155
 
/***********************************************************************
156
 
 * tr_netResolvePulse
157
 
 ***********************************************************************
158
 
 * Checks the current status of a resolution.
159
 
 **********************************************************************/
160
 
tr_tristate_t tr_netResolvePulse( tr_resolve_t * r, struct in_addr * addr )
161
 
{
162
 
    tr_tristate_t ret;
163
 
 
164
 
    tr_lockLock( resolveLock );
165
 
    ret = r->status;
166
 
    if( ret == TR_NET_OK )
167
 
    {
168
 
        *addr = r->addr;
169
 
    }
170
 
    tr_lockUnlock( resolveLock );
171
 
 
172
 
    return ret;
173
 
}
174
 
 
175
 
/***********************************************************************
176
 
 * tr_netResolveClose
177
 
 ***********************************************************************
178
 
 * 
179
 
 **********************************************************************/
180
 
void tr_netResolveClose( tr_resolve_t * r )
181
 
{
182
 
    resolveRelease( r );
183
 
}
184
 
 
185
 
/***********************************************************************
186
 
 * resolveRelease
187
 
 ***********************************************************************
188
 
 * The allocated tr_resolve_t structures should be freed when
189
 
 * tr_netResolveClose was called *and* it was removed from the queue.
190
 
 * This can happen in any order, so we use a refcount to know we can
191
 
 * take it out.
192
 
 **********************************************************************/
193
 
static void resolveRelease( tr_resolve_t * r )
194
 
{
195
 
    if( --r->refcount < 1 )
196
 
    {
197
 
        free( r->address );
198
 
        free( r );
199
 
    }
200
 
}
201
 
 
202
 
/***********************************************************************
203
 
 * resolveFunc
204
 
 ***********************************************************************
205
 
 * Keeps waiting for addresses to resolve, and removes them from the
206
 
 * queue once resolution is done.
207
 
 **********************************************************************/
208
 
static void resolveFunc( void * arg UNUSED )
209
 
{
210
 
    tr_resolve_t * r;
211
 
    struct hostent * host;
212
 
 
213
 
    tr_lockLock( resolveLock );
214
 
 
215
 
    while( !resolveDie )
216
 
    {
217
 
        if( !( r = resolveQueue ) )
218
 
        {
219
 
            tr_condWait( resolveCond, resolveLock );
220
 
            continue;
221
 
        }
222
 
 
223
 
        /* Blocking resolution */
224
 
        tr_lockUnlock( resolveLock );
225
 
        host = gethostbyname( r->address );
226
 
        tr_lockLock( resolveLock );
227
 
 
228
 
        if( host )
229
 
        {
230
 
            memcpy( &r->addr, host->h_addr, host->h_length );
231
 
            r->status = TR_NET_OK;
232
 
        }
233
 
        else
234
 
        {
235
 
            r->status = TR_NET_ERROR;
236
 
        }
237
 
        
238
 
        resolveQueue = r->next;
239
 
        resolveRelease( r );
240
 
    }
241
 
 
242
 
    /* Clean up  */
243
 
    tr_lockUnlock( resolveLock );
244
 
    tr_lockFree( resolveLock );
245
 
    resolveLock = NULL;
246
 
    while( ( r = resolveQueue ) )
247
 
    {
248
 
        resolveQueue = r->next;
249
 
        resolveRelease( r );
250
 
    }
251
 
}
252
 
 
253
73
 
254
74
/***********************************************************************
255
75
 * TCP/UDP sockets
256
76
 **********************************************************************/
257
77
 
258
 
static int makeSocketNonBlocking( int s )
 
78
static int
 
79
makeSocketNonBlocking( int fd )
259
80
{
260
 
#ifdef WIN32
261
 
    unsigned long flags = 1;
262
 
    if( ioctlsocket( s, FIONBIO, &flags) == SOCKET_ERROR )
263
 
#elif defined(__BEOS__)
264
 
    int flags = 1;
265
 
    if( setsockopt( s, SOL_SOCKET, SO_NONBLOCK,
266
 
                    &flags, sizeof( int ) ) < 0 )
 
81
    if( fd >= 0 )
 
82
    {
 
83
#if defined(__BEOS__)
 
84
        int flags = 1;
 
85
        if( setsockopt( fd, SOL_SOCKET, SO_NONBLOCK,
 
86
                        &flags, sizeof( int ) ) < 0 )
267
87
#else
268
 
    int flags = 1;
269
 
    if( ( flags = fcntl( s, F_GETFL, 0 ) ) < 0 ||
270
 
        fcntl( s, F_SETFL, flags | O_NONBLOCK ) < 0 )
 
88
        if( evutil_make_socket_nonblocking( fd ) )
271
89
#endif
272
 
    {
273
 
        tr_err( "Couldn't set socket to non-blocking mode (%s)",
274
 
                strerror( sockerrno ) );
275
 
        tr_netClose( s );
276
 
        return -1;
 
90
        {
 
91
            tr_err( "Couldn't set socket to non-blocking mode (%s)",
 
92
                    strerror( sockerrno ) );
 
93
            tr_netClose( fd );
 
94
            fd = -1;
 
95
        }
277
96
    }
278
97
 
279
 
    return s;
 
98
    return fd;
280
99
}
281
100
 
282
 
static int createSocket( int type, int priority )
 
101
static int
 
102
createSocket( int type, int priority )
283
103
{
284
 
    int s;
285
 
    if( ( s = tr_fdSocketCreate( type, priority ) ) < 0 )
286
 
    {
287
 
        return -1;
288
 
    }
289
 
    return makeSocketNonBlocking( s );
 
104
    return makeSocketNonBlocking( tr_fdSocketCreate( type, priority ) );
290
105
}
291
106
 
292
107
static int
399
214
    if( bind( s, (struct sockaddr *) &sock,
400
215
               sizeof( struct sockaddr_in ) ) )
401
216
    {
402
 
        tr_err( "Couldn't bind port %d", port );
 
217
        tr_err( "Couldn't bind port %d: %s", port, strerror(sockerrno) );
403
218
        tr_netClose( s );
404
219
        return -1;
405
220
    }
420
235
}
421
236
 
422
237
 
423
 
int tr_netAccept( int b, struct in_addr * addr, tr_port_t * port )
 
238
int
 
239
tr_netAccept( int b, struct in_addr * addr, tr_port_t * port )
424
240
{
425
 
    int s;
426
 
    if( ( s = tr_fdSocketAccept( b, addr, port ) ) < 0 )
427
 
    {
428
 
        return -1;
429
 
    }
430
 
    return makeSocketNonBlocking( s );
 
241
    return makeSocketNonBlocking( tr_fdSocketAccept( b, addr, port ) );
431
242
}
432
243
 
433
244
int
469
280
    return ret;
470
281
}
471
282
 
472
 
void tr_netClose( int s )
 
283
void
 
284
tr_netClose( int s )
473
285
{
474
286
    tr_fdSocketClose( s );
475
287
}
476
288
 
477
 
void tr_netNtop( const struct in_addr * addr, char * buf, int len )
 
289
void
 
290
tr_netNtop( const struct in_addr * addr, char * buf, int len )
478
291
{
479
292
    const uint8_t * cast;
480
293