source: trunk/libtransmission/shared.c @ 4092

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

Use libnatpmp for port mapping. rewrite the upnp/natpmp manager.

NOTE: this will break the xpjets build until SoftwareElves? or a volunteer patches the xcode project file to make a libnatpmp library just like was done for libminiupnp.

  • Property svn:keywords set to Date Rev Author Id
File size: 4.7 KB
Line 
1/******************************************************************************
2 * $Id: shared.c 4092 2007-12-08 19:34:15Z 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 <string.h>
26#include <stdio.h>
27
28#include <sys/types.h>
29
30#include "transmission.h"
31#include "natpmp.h"
32#include "net.h"
33#include "peer-mgr.h"
34#include "shared.h"
35#include "trevent.h"
36#include "upnp.h"
37#include "utils.h"
38
39struct tr_shared
40{
41    tr_handle * h;
42    tr_timer  * pulseTimer;
43
44    /* Incoming connections */
45    int bindPort;
46    int bindSocket;
47
48    /* port forwarding */
49    int isEnabled;
50    int publicPort;
51    tr_nat_traversal_status natStatus;
52    tr_upnp * upnp;
53    tr_natpmp  * natpmp;
54
55    int isShuttingDown;
56};
57
58#define NATKEY "Port Mapping: "
59
60/***
61****
62***/
63
64static const char*
65getNatStateStr( int state )
66{
67    switch( state )
68    {
69        case TR_NAT_TRAVERSAL_MAPPING:   return "mapping";
70        case TR_NAT_TRAVERSAL_MAPPED:    return "mapped";
71        case TR_NAT_TRAVERSAL_UNMAPPING: return "unmapping";
72        case TR_NAT_TRAVERSAL_UNMAPPED:  return "unmapped";
73        case TR_NAT_TRAVERSAL_ERROR:     return "error";
74    }
75
76    return "notfound";
77}
78
79static void
80natPulse( tr_shared * s )
81{
82    tr_nat_traversal_status status;
83    const int port = s->publicPort;
84    const int isEnabled = s->isEnabled && !s->isShuttingDown;
85
86    status = tr_natpmpPulse( s->natpmp, port, isEnabled );
87    if( status == TR_NAT_TRAVERSAL_ERROR )
88        status = tr_upnpPulse( s->upnp, port, isEnabled );
89    if( status != s->natStatus ) {
90        tr_inf( NATKEY "mapping state changed from '%s' to '%s'", getNatStateStr(s->natStatus), getNatStateStr(status) );
91        s->natStatus = status;
92    }
93}
94
95static void
96checkForIncomingPeers( tr_shared * s )
97{
98    for( ;; )
99    {
100        int socket;
101        uint16_t port;
102        struct in_addr addr;
103
104        if( s->bindSocket < 0 )
105            break;
106
107        socket = tr_netAccept( s->bindSocket, &addr, &port );
108        if( socket < 0 )
109            break;
110
111        tr_peerMgrAddIncoming( s->h->peerMgr, &addr, port, socket );
112    }
113}
114
115static int
116sharedPulse( void * vshared )
117{
118    int keepPulsing = 1;
119    tr_shared * shared = vshared;
120
121    natPulse( shared );
122
123    if( !shared->isShuttingDown )
124    {
125        checkForIncomingPeers( shared );
126    }
127    else if( ( shared->natStatus == TR_NAT_TRAVERSAL_ERROR ) || ( shared->natStatus == TR_NAT_TRAVERSAL_UNMAPPED ) )
128    {
129        tr_dbg( NATKEY "port mapping shut down" );
130        shared->h->shared = NULL;
131        tr_netClose( shared->bindSocket );
132        tr_natpmpClose( shared->natpmp );
133        tr_upnpClose( shared->upnp );
134        tr_free( shared );
135        keepPulsing = 0;
136    }
137
138    return keepPulsing;
139}
140
141/***
142****
143***/
144
145tr_shared *
146tr_sharedInit( tr_handle * h )
147{
148    tr_shared * s = tr_new0( tr_shared, 1 );
149
150    s->h            = h;
151    s->publicPort   = -1;
152    s->bindPort     = -1;
153    s->bindSocket   = -1;
154    s->natpmp       = tr_natpmpInit();
155    s->upnp         = tr_upnpInit();
156    s->pulseTimer   = tr_timerNew( h, sharedPulse, s, 500 );
157    s->isEnabled    = 0;
158    s->natStatus    = TR_NAT_TRAVERSAL_UNMAPPED;
159
160    return s;
161}
162
163void
164tr_sharedShuttingDown( tr_shared * s )
165{
166    s->isShuttingDown = 1;
167}
168
169void
170tr_sharedSetPort( tr_shared * s, int port )
171{
172    tr_torrent * tor;
173
174    s->publicPort = port;
175
176    for( tor = s->h->torrentList; tor; tor = tor->next )
177        tr_torrentChangeMyPort( tor );
178}
179
180int
181tr_sharedGetPublicPort( const tr_shared * s )
182{
183    return s->publicPort;
184}
185
186void
187tr_sharedTraversalEnable( tr_shared * s, int isEnabled )
188{
189    s->isEnabled = isEnabled;
190}
191
192int
193tr_sharedTraversalStatus( const tr_shared * s )
194{
195    return s->natStatus;
196}
Note: See TracBrowser for help on using the repository browser.