source: trunk/libtransmission/shared.c @ 5547

Last change on this file since 5547 was 5547, checked in by charles, 14 years ago

remove a debugging printf

  • Property svn:keywords set to Date Rev Author Id
File size: 6.1 KB
Line 
1/******************************************************************************
2 * $Id: shared.c 5547 2008-04-06 17:12:15Z 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 <string.h>
27#include <stdio.h>
28
29#include <sys/types.h>
30
31#include "transmission.h"
32#include "natpmp.h"
33#include "net.h"
34#include "peer-mgr.h"
35#include "shared.h"
36#include "torrent.h"
37#include "trevent.h"
38#include "upnp.h"
39#include "utils.h"
40
41static const char * getKey( void ) { return _( "Port Forwarding" ); }
42
43struct tr_shared
44{
45    tr_handle * h;
46    tr_timer  * pulseTimer;
47
48    /* Incoming connections */
49    int bindPort;
50    int bindSocket;
51
52    /* port forwarding */
53    int isEnabled;
54    int publicPort;
55    tr_nat_traversal_status natStatus;
56    tr_upnp * upnp;
57    tr_natpmp  * natpmp;
58
59    int isShuttingDown;
60};
61
62/***
63****
64***/
65
66static const char*
67getNatStateStr( int state )
68{
69    switch( state )
70    {
71        /* we're in the process of trying to set up port forwarding */
72        case TR_NAT_TRAVERSAL_MAPPING:   return _( "Starting" );
73        /* we've successfully forwarded the port */
74        case TR_NAT_TRAVERSAL_MAPPED:    return _( "Forwarded" );
75        /* we're cancelling the port forwarding */
76        case TR_NAT_TRAVERSAL_UNMAPPING: return _( "Stopping" );
77        /* the port isn't forwarded */
78        case TR_NAT_TRAVERSAL_UNMAPPED:  return _( "Not forwarded" );
79        case TR_NAT_TRAVERSAL_ERROR:     return "???";
80    }
81
82    return "notfound";
83}
84
85static void
86natPulse( tr_shared * s )
87{
88    tr_nat_traversal_status status;
89    const int port = s->publicPort;
90    const int isEnabled = s->isEnabled && !s->isShuttingDown;
91
92    status = tr_natpmpPulse( s->natpmp, port, isEnabled );
93    if( status == TR_NAT_TRAVERSAL_ERROR )
94        status = tr_upnpPulse( s->upnp, port, isEnabled );
95    if( status != s->natStatus ) {
96        tr_ninf( getKey(), _( "State changed from \"%s\" to \"%s\"" ), getNatStateStr(s->natStatus), getNatStateStr(status) );
97        s->natStatus = status;
98        if( status == TR_NAT_TRAVERSAL_ERROR )
99            tr_nerr( getKey(), _( "Port forwarding failed." ) );
100    }
101}
102
103static void
104incomingPeersPulse( tr_shared * s )
105{
106    if( s->bindSocket >= 0 && ( s->bindPort != s->publicPort ) )
107    {
108        tr_ninf( getKey(), _( "Closing port %d" ), s->bindPort );
109        tr_netClose( s->bindSocket );
110        s->bindSocket = -1;
111    }
112
113    if( ( s->publicPort > 0 ) && ( s->bindPort != s->publicPort ) )
114    {
115        int socket;
116        errno = 0;
117        socket = tr_netBindTCP( s->publicPort );
118        if( socket >= 0 ) {
119            tr_ninf( getKey(), _( "Opened port %d to listen for incoming peer connections" ), s->publicPort );
120            s->bindPort = s->publicPort;
121            s->bindSocket = socket;
122            listen( s->bindSocket, 5 );
123        } else {
124            tr_nerr( getKey(), _( "Couldn't open port %d to listen for incoming peer connections (errno %d - %s)" ),
125                     s->publicPort, errno, tr_strerror(errno) );
126            s->bindPort = -1;
127            s->bindSocket = -1;
128        }
129    }
130   
131    for( ;; ) /* check for new incoming peer connections */   
132    {
133        int socket;
134        uint16_t port;
135        struct in_addr addr;
136
137        if( s->bindSocket < 0 )
138            break;
139
140        socket = tr_netAccept( s->bindSocket, &addr, &port );
141        if( socket < 0 )
142            break;
143
144        tr_peerMgrAddIncoming( s->h->peerMgr, &addr, port, socket );
145    }
146}
147
148static int
149sharedPulse( void * vshared )
150{
151    int keepPulsing = 1;
152    tr_shared * shared = vshared;
153
154    natPulse( shared );
155
156    if( !shared->isShuttingDown )
157    {
158        incomingPeersPulse( shared );
159    }
160    else
161    {
162        tr_ninf( getKey(), _( "Stopped" ) );
163        tr_timerFree( &shared->pulseTimer );
164        tr_netClose( shared->bindSocket );
165        tr_natpmpClose( shared->natpmp );
166        tr_upnpClose( shared->upnp );
167        shared->h->shared = NULL;
168        tr_free( shared );
169        keepPulsing = 0;
170    }
171
172    return keepPulsing;
173}
174
175/***
176****
177***/
178
179tr_shared *
180tr_sharedInit( tr_handle * h, int isEnabled, int publicPort )
181{
182    tr_shared * s = tr_new0( tr_shared, 1 );
183
184    s->h            = h;
185    s->publicPort   = publicPort;
186    s->bindPort     = -1;
187    s->bindSocket   = -1;
188    s->natpmp       = tr_natpmpInit();
189    s->upnp         = tr_upnpInit();
190    s->pulseTimer   = tr_timerNew( h, sharedPulse, s, 500 );
191    s->isEnabled    = isEnabled ? 1 : 0;
192    s->natStatus    = TR_NAT_TRAVERSAL_UNMAPPED;
193
194    return s;
195}
196
197void
198tr_sharedShuttingDown( tr_shared * s )
199{
200    s->isShuttingDown = 1;
201}
202
203void
204tr_sharedSetPort( tr_shared * s, int port )
205{
206    tr_torrent * tor;
207
208    s->publicPort = port;
209
210    for( tor = s->h->torrentList; tor; tor = tor->next )
211        tr_torrentChangeMyPort( tor );
212}
213
214int
215tr_sharedGetPublicPort( const tr_shared * s )
216{
217    return s->publicPort;
218}
219
220void
221tr_sharedTraversalEnable( tr_shared * s, int isEnabled )
222{
223    s->isEnabled = isEnabled;
224}
225
226int
227tr_sharedTraversalStatus( const tr_shared * s )
228{
229    return s->natStatus;
230}
Note: See TracBrowser for help on using the repository browser.