source: trunk/libtransmission/shared.c @ 5193

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

first cut at adding i18n hooks into libtransmission.

  • Property svn:keywords set to Date Rev Author Id
File size: 5.7 KB
Line 
1/******************************************************************************
2 * $Id: shared.c 5193 2008-03-04 02:02:25Z 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
41struct tr_shared
42{
43    tr_handle * h;
44    tr_timer  * pulseTimer;
45
46    /* Incoming connections */
47    int bindPort;
48    int bindSocket;
49
50    /* port forwarding */
51    int isEnabled;
52    int publicPort;
53    tr_nat_traversal_status natStatus;
54    tr_upnp * upnp;
55    tr_natpmp  * natpmp;
56
57    int isShuttingDown;
58};
59
60#define NATKEY "Port Mapping: "
61
62/***
63****
64***/
65
66static const char*
67getNatStateStr( int state )
68{
69    switch( state )
70    {
71        case TR_NAT_TRAVERSAL_MAPPING:   return "mapping";
72        case TR_NAT_TRAVERSAL_MAPPED:    return "mapped";
73        case TR_NAT_TRAVERSAL_UNMAPPING: return "unmapping";
74        case TR_NAT_TRAVERSAL_UNMAPPED:  return "not mapped";
75        case TR_NAT_TRAVERSAL_ERROR:     return "error";
76    }
77
78    return "notfound";
79}
80
81static void
82natPulse( tr_shared * s )
83{
84    tr_nat_traversal_status status;
85    const int port = s->publicPort;
86    const int isEnabled = s->isEnabled && !s->isShuttingDown;
87
88    status = tr_natpmpPulse( s->natpmp, port, isEnabled );
89    if( status == TR_NAT_TRAVERSAL_ERROR )
90        status = tr_upnpPulse( s->upnp, port, isEnabled );
91    if( status != s->natStatus ) {
92        tr_inf( _( NATKEY "mapping state changed from '%s' to '%s'" ), getNatStateStr(s->natStatus), getNatStateStr(status) );
93        s->natStatus = status;
94    }
95}
96
97static void
98incomingPeersPulse( tr_shared * s )
99{
100    if( s->bindSocket >= 0 && ( s->bindPort != s->publicPort ) )
101    {
102        tr_inf( _( NATKEY "closing port %d" ), s->bindPort );
103        tr_netClose( s->bindSocket );
104        s->bindSocket = -1;
105    }
106
107    if( s->bindPort != s->publicPort )
108    {
109        int socket;
110        errno = 0;
111        socket = tr_netBindTCP( s->publicPort );
112        if( socket >= 0 ) {
113            tr_inf( _( NATKEY "opened port %d to listen for incoming peer connections" ), s->publicPort );
114            s->bindPort = s->publicPort;
115            s->bindSocket = socket;
116            listen( s->bindSocket, 5 );
117        } else {
118            tr_err( _( NATKEY "unable to open port %d to listen for incoming peer connections (errno is %d - %s)" ),
119                    s->publicPort, errno, tr_strerror(errno) );
120            s->bindPort = -1;
121            s->bindSocket = -1;
122        }
123    }
124   
125    for( ;; ) /* check for new incoming peer connections */   
126    {
127        int socket;
128        uint16_t port;
129        struct in_addr addr;
130
131        if( s->bindSocket < 0 )
132            break;
133
134        socket = tr_netAccept( s->bindSocket, &addr, &port );
135        if( socket < 0 )
136            break;
137
138        tr_peerMgrAddIncoming( s->h->peerMgr, &addr, port, socket );
139    }
140}
141
142static int
143sharedPulse( void * vshared )
144{
145    int keepPulsing = 1;
146    tr_shared * shared = vshared;
147
148    natPulse( shared );
149
150    if( !shared->isShuttingDown )
151    {
152        incomingPeersPulse( shared );
153    }
154    else if( ( shared->natStatus == TR_NAT_TRAVERSAL_ERROR ) || ( shared->natStatus == TR_NAT_TRAVERSAL_UNMAPPED ) )
155    {
156        tr_dbg( NATKEY "port mapping shut down" );
157        shared->h->shared = NULL;
158        tr_netClose( shared->bindSocket );
159        tr_natpmpClose( shared->natpmp );
160        tr_upnpClose( shared->upnp );
161        tr_free( shared );
162        keepPulsing = 0;
163    }
164
165    return keepPulsing;
166}
167
168/***
169****
170***/
171
172tr_shared *
173tr_sharedInit( tr_handle * h, int isEnabled, int publicPort )
174{
175    tr_shared * s = tr_new0( tr_shared, 1 );
176
177    s->h            = h;
178    s->publicPort   = publicPort;
179    s->bindPort     = -1;
180    s->bindSocket   = -1;
181    s->natpmp       = tr_natpmpInit();
182    s->upnp         = tr_upnpInit();
183    s->pulseTimer   = tr_timerNew( h, sharedPulse, s, 500 );
184    s->isEnabled    = isEnabled ? 1 : 0;
185    s->natStatus    = TR_NAT_TRAVERSAL_UNMAPPED;
186
187    return s;
188}
189
190void
191tr_sharedShuttingDown( tr_shared * s )
192{
193    s->isShuttingDown = 1;
194}
195
196void
197tr_sharedSetPort( tr_shared * s, int port )
198{
199    tr_torrent * tor;
200
201    s->publicPort = port;
202
203    for( tor = s->h->torrentList; tor; tor = tor->next )
204        tr_torrentChangeMyPort( tor );
205}
206
207int
208tr_sharedGetPublicPort( const tr_shared * s )
209{
210    return s->publicPort;
211}
212
213void
214tr_sharedTraversalEnable( tr_shared * s, int isEnabled )
215{
216    s->isEnabled = isEnabled;
217}
218
219int
220tr_sharedTraversalStatus( const tr_shared * s )
221{
222    return s->natStatus;
223}
Note: See TracBrowser for help on using the repository browser.