source: trunk/libtransmission/shared.c @ 3796

Last change on this file since 3796 was 3796, checked in by charles, 15 years ago

Increase the intervals on timers that won't affect performance. This reduces most of Transmission's PowerTOP footprint.

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