source: trunk/libtransmission/shared.c @ 3105

Last change on this file since 3105 was 3105, checked in by livings124, 15 years ago

merge encryption branch to trunk (xcode project is still out of date)

  • Property svn:keywords set to Date Rev Author Id
File size: 7.9 KB
Line 
1/******************************************************************************
2 * $Id: shared.c 3105 2007-09-20 16:32:01Z livings124 $
3 *
4 * Copyright (c) 2005-2007 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 <assert.h>
26#include <stdlib.h>
27#include <string.h>
28#include <stdio.h>
29
30#include <sys/types.h>
31
32#include "transmission.h"
33#include "handshake.h"
34#include "natpmp.h"
35#include "net.h"
36#include "peer-io.h"
37#include "peer-mgr.h"
38#include "platform.h"
39#include "shared.h"
40#include "trevent.h"
41#include "upnp.h"
42#include "utils.h"
43
44struct tr_shared
45{
46    tr_handle    * h;
47    tr_lock      * lock;
48    tr_timer     * pulseTimer;
49
50    /* Incoming connections */
51    int publicPort;
52    int bindPort;
53    int bindSocket;
54
55    /* NAT-PMP/UPnP */
56    tr_natpmp_t  * natpmp;
57    tr_upnp_t    * upnp;
58};
59
60/***********************************************************************
61 * Local prototypes
62 **********************************************************************/
63static int SharedLoop( void * );
64static void SetPublicPort( tr_shared *, int );
65static void AcceptPeers( tr_shared * );
66
67
68/***********************************************************************
69 * tr_sharedInit
70 ***********************************************************************
71 *
72 **********************************************************************/
73tr_shared * tr_sharedInit( tr_handle * h )
74{
75    tr_shared * s = calloc( 1, sizeof( tr_shared ) );
76
77    s->h          = h;
78    s->lock       = tr_lockNew( );
79    s->publicPort = -1;
80    s->bindPort   = -1;
81    s->bindSocket = -1;
82    s->natpmp     = tr_natpmpInit();
83    s->upnp       = tr_upnpInit();
84    s->pulseTimer   = tr_timerNew( h, SharedLoop, s, 250 );
85
86    return s;
87}
88
89/***********************************************************************
90 * tr_sharedClose
91 ***********************************************************************
92 *
93 **********************************************************************/
94void tr_sharedClose( tr_shared * s )
95{
96fprintf( stderr, "deleting pulse tag\n" );
97    tr_timerFree( &s->pulseTimer );
98
99    tr_netClose( s->bindSocket );
100    tr_lockFree( s->lock );
101    tr_natpmpClose( s->natpmp );
102    tr_upnpClose( s->upnp );
103    free( s );
104}
105
106/**
107***
108**/
109
110void tr_sharedLock( tr_shared * s )
111{
112    tr_lockLock( s->lock );
113}
114void tr_sharedUnlock( tr_shared * s )
115{
116    tr_lockUnlock( s->lock );
117}
118
119/***********************************************************************
120 * tr_sharedSetPort
121 ***********************************************************************
122 *
123 **********************************************************************/
124void tr_sharedSetPort( tr_shared * s, int port )
125{
126#ifdef BEOS_NETSERVER
127    /* BeOS net_server seems to be unable to set incoming connections
128     * to non-blocking. Too bad. */
129    return;
130#endif
131
132    tr_sharedLock( s );
133
134    if( port == s->bindPort )
135    {
136        tr_sharedUnlock( s );
137        return;
138    }
139    s->bindPort = port;
140
141    /* Close the previous accept socket, if any */
142    if( s->bindSocket > -1 )
143    {
144        tr_netClose( s->bindSocket );
145    }
146
147    /* Create the new one */
148    /* XXX should handle failure here in a better way */
149    s->bindSocket = tr_netBindTCP( port );
150    if( 0 > s->bindSocket )
151    {
152        /* Notify the trackers */
153        SetPublicPort( s, 0 );
154        /* Remove the forwarding for the old port */
155        tr_natpmpRemoveForwarding( s->natpmp );
156        tr_upnpRemoveForwarding( s->upnp );
157    }
158    else
159    {
160        tr_inf( "Bound listening port %d", port );
161        listen( s->bindSocket, 5 );
162        if( port != s->publicPort )
163        {
164            /* Notify the trackers */
165            SetPublicPort( s, port );
166        }
167        /* Forward the new port */
168        tr_natpmpForwardPort( s->natpmp, port );
169        tr_upnpForwardPort( s->upnp, port );
170    }
171
172    tr_sharedUnlock( s );
173}
174
175int tr_sharedGetPublicPort( tr_shared * s )
176{
177    return s->publicPort;
178}
179
180/***********************************************************************
181 * tr_sharedTraversalEnable, tr_sharedTraversalStatus
182 ***********************************************************************
183 *
184 **********************************************************************/
185void tr_sharedTraversalEnable( tr_shared * s, int enable )
186{
187    if( enable )
188    {
189        tr_natpmpStart( s->natpmp );
190        tr_upnpStart( s->upnp );
191    }
192    else
193    {
194        tr_natpmpStop( s->natpmp );
195        tr_upnpStop( s->upnp );
196    }
197}
198
199int tr_sharedTraversalStatus( tr_shared * s )
200{
201    int statuses[] = {
202        TR_NAT_TRAVERSAL_MAPPED,
203        TR_NAT_TRAVERSAL_MAPPING,
204        TR_NAT_TRAVERSAL_UNMAPPING,
205        TR_NAT_TRAVERSAL_ERROR,
206        TR_NAT_TRAVERSAL_NOTFOUND,
207        TR_NAT_TRAVERSAL_DISABLED,
208        -1,
209    };
210    int natpmp, upnp, ii;
211
212    natpmp = tr_natpmpStatus( s->natpmp );
213    upnp = tr_upnpStatus( s->upnp );
214
215    for( ii = 0; 0 <= statuses[ii]; ii++ )
216    {
217        if( statuses[ii] == natpmp || statuses[ii] == upnp )
218        {
219            return statuses[ii];
220        }
221    }
222
223    assert( 0 );
224
225    return TR_NAT_TRAVERSAL_ERROR;
226
227}
228
229
230/***********************************************************************
231 * Local functions
232 **********************************************************************/
233
234/***********************************************************************
235 * SharedLoop
236 **********************************************************************/
237static int
238SharedLoop( void * vs )
239{
240    int newPort;
241    tr_shared * s = vs;
242
243    tr_sharedLock( s );
244
245    /* NAT-PMP and UPnP pulses */
246    newPort = -1;
247    tr_natpmpPulse( s->natpmp, &newPort );
248    if( 0 < newPort && newPort != s->publicPort )
249        SetPublicPort( s, newPort );
250    tr_upnpPulse( s->upnp );
251
252    /* Handle incoming connections */
253    AcceptPeers( s );
254
255    tr_sharedUnlock( s );
256
257    return TRUE;
258}
259
260/***********************************************************************
261 * SetPublicPort
262 **********************************************************************/
263static void SetPublicPort( tr_shared * s, int port )
264{
265    tr_handle * h = s->h;
266    tr_torrent * tor;
267
268    s->publicPort = port;
269
270    for( tor = h->torrentList; tor; tor = tor->next )
271        tr_torrentChangeMyPort( tor, port );
272}
273
274/***********************************************************************
275 * AcceptPeers
276 ***********************************************************************
277 * Check incoming connections and add the peers to our local list
278 **********************************************************************/
279
280static void
281AcceptPeers( tr_shared * s )
282{
283    for( ;; )
284    {
285        int socket;
286        struct in_addr addr;
287
288        if( s->bindSocket < 0 || !tr_peerMgrIsAcceptingConnections( s->h->peerMgr ) )
289            break;
290
291        socket = tr_netAccept( s->bindSocket, &addr, NULL );
292        if( socket < 0 )
293            break;
294
295        tr_peerMgrAddIncoming( s->h->peerMgr, &addr, socket );
296    }
297}
Note: See TracBrowser for help on using the repository browser.