source: trunk/libtransmission/port-forwarding.c @ 11709

Last change on this file since 11709 was 11709, checked in by jordan, 11 years ago

Update the copyright year in the source code comments.

The Berne Convention says that the copyright year is moot, so instead of adding another year to each file as in previous years, I've removed the year altogether from the source code comments in libtransmission, gtk, qt, utils, daemon, and cli.

Juliusz's copyright notice in tr-dht and Johannes' copyright notice in tr-lpd have been left alone; it didn't seem appropriate to modify them.

  • Property svn:keywords set to Date Rev Author Id
File size: 5.2 KB
Line 
1/*
2 * This file Copyright (C) Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: port-forwarding.c 11709 2011-01-19 13:48:47Z jordan $
11 */
12
13#include <assert.h>
14#include <string.h>
15#include <stdio.h>
16
17#include <sys/types.h>
18
19#include <event2/event.h>
20
21#include "transmission.h"
22#include "natpmp.h"
23#include "net.h"
24#include "peer-io.h"
25#include "peer-mgr.h"
26#include "port-forwarding.h"
27#include "session.h"
28#include "torrent.h"
29#include "upnp.h"
30#include "utils.h"
31
32static const char *
33getKey( void ) { return _( "Port Forwarding" ); }
34
35struct tr_shared
36{
37    tr_bool               isEnabled;
38    tr_bool               isShuttingDown;
39    tr_bool               doPortCheck;
40
41    tr_port_forwarding    natpmpStatus;
42    tr_port_forwarding    upnpStatus;
43
44    tr_upnp             * upnp;
45    tr_natpmp           * natpmp;
46    tr_session          * session;
47
48    struct event        * timer;
49};
50
51/***
52****
53***/
54
55static const char*
56getNatStateStr( int state )
57{
58    switch( state )
59    {
60        case TR_PORT_MAPPING:   return _( "Starting" );
61        case TR_PORT_MAPPED:    return _( "Forwarded" );
62        case TR_PORT_UNMAPPING: return _( "Stopping" );
63        case TR_PORT_UNMAPPED:  return _( "Not forwarded" );
64        default:                return "???";
65    }
66}
67
68static void
69natPulse( tr_shared * s, tr_bool do_check )
70{
71    const tr_port private_peer_port = s->session->private_peer_port;
72    const int is_enabled = s->isEnabled && !s->isShuttingDown;
73    tr_port public_peer_port;
74    int oldStatus;
75    int newStatus;
76
77    if( s->natpmp == NULL )
78        s->natpmp = tr_natpmpInit( );
79    if( s->upnp == NULL )
80        s->upnp = tr_upnpInit( );
81
82    oldStatus = tr_sharedTraversalStatus( s );
83
84    s->natpmpStatus = tr_natpmpPulse( s->natpmp, private_peer_port, is_enabled, &public_peer_port );
85    if( s->natpmpStatus == TR_PORT_MAPPED )
86        s->session->public_peer_port = public_peer_port;
87
88    s->upnpStatus = tr_upnpPulse( s->upnp, private_peer_port, is_enabled, do_check );
89
90    newStatus = tr_sharedTraversalStatus( s );
91
92    if( newStatus != oldStatus )
93        tr_ninf( getKey( ), _( "State changed from \"%1$s\" to \"%2$s\"" ),
94                getNatStateStr( oldStatus ),
95                getNatStateStr( newStatus ) );
96}
97
98static void
99set_evtimer_from_status( tr_shared * s )
100{
101    int sec=0, msec=0;
102
103    /* when to wake up again */
104    switch( tr_sharedTraversalStatus( s ) )
105    {
106        case TR_PORT_MAPPED:
107            /* if we're mapped, everything is fine... check back in 20 minutes
108             * to renew the port forwarding if it's expired */
109            s->doPortCheck = TRUE;
110            sec = 60 * 20;
111            break;
112
113        case TR_PORT_ERROR:
114            /* some kind of an error. wait 60 seconds and retry */
115            sec = 60;
116            break;
117
118        default:
119            /* in progress. pulse frequently. */
120            msec = 333000;
121            break;
122    }
123
124    if( s->timer != NULL )
125        tr_timerAdd( s->timer, sec, msec );
126}
127
128static void
129onTimer( int fd UNUSED, short what UNUSED, void * vshared )
130{
131    tr_shared * s = vshared;
132
133    assert( s );
134    assert( s->timer );
135
136    /* do something */
137    natPulse( s, s->doPortCheck );
138    s->doPortCheck = FALSE;
139
140    /* set up the timer for the next pulse */
141    set_evtimer_from_status( s );
142}
143
144/***
145****
146***/
147
148tr_shared *
149tr_sharedInit( tr_session  * session )
150{
151    tr_shared * s = tr_new0( tr_shared, 1 );
152
153    s->session      = session;
154    s->isEnabled    = FALSE;
155    s->upnpStatus   = TR_PORT_UNMAPPED;
156    s->natpmpStatus = TR_PORT_UNMAPPED;
157
158#if 0
159    if( isEnabled )
160    {
161        s->timer = tr_new0( struct event, 1 );
162        evtimer_set( s->timer, onTimer, s );
163        tr_timerAdd( s->timer, 0, 333000 );
164    }
165#endif
166
167    return s;
168}
169
170static void
171stop_timer( tr_shared * s )
172{
173    if( s->timer != NULL )
174    {
175        event_free( s->timer );
176        s->timer = NULL;
177    }
178}
179
180static void
181stop_forwarding( tr_shared * s )
182{
183    tr_ninf( getKey( ), "%s", _( "Stopped" ) );
184    natPulse( s, FALSE );
185
186    tr_natpmpClose( s->natpmp );
187    s->natpmp = NULL;
188    s->natpmpStatus = TR_PORT_UNMAPPED;
189
190    tr_upnpClose( s->upnp );
191    s->upnp = NULL;
192    s->upnpStatus = TR_PORT_UNMAPPED;
193
194    stop_timer( s );
195}
196
197void
198tr_sharedClose( tr_session * session )
199{
200    tr_shared * s = session->shared;
201
202    s->isShuttingDown = TRUE;
203    stop_forwarding( s );
204    s->session->shared = NULL;
205    tr_free( s );
206}
207
208static void
209start_timer( tr_shared * s )
210{
211    s->timer = evtimer_new( s->session->event_base, onTimer, s );
212    set_evtimer_from_status( s );
213}
214
215void
216tr_sharedTraversalEnable( tr_shared * s, tr_bool isEnabled )
217{
218    if(( s->isEnabled = isEnabled ))
219        start_timer( s );
220    else
221        stop_forwarding( s );
222}
223
224void
225tr_sharedPortChanged( tr_session * session )
226{
227    tr_shared * s = session->shared;
228
229    if( s->isEnabled )
230    {
231        stop_timer( s );
232        natPulse( s, FALSE );
233        start_timer( s );
234    }
235}
236
237tr_bool
238tr_sharedTraversalIsEnabled( const tr_shared * s )
239{
240    return s->isEnabled;
241}
242
243int
244tr_sharedTraversalStatus( const tr_shared * s )
245{
246    return MAX( s->natpmpStatus, s->upnpStatus );
247}
Note: See TracBrowser for help on using the repository browser.