diff --git a/libtransmission/port-forwarding.c b/libtransmission/port-forwarding.c index a031f3c4e..18b3a6621 100644 --- a/libtransmission/port-forwarding.c +++ b/libtransmission/port-forwarding.c @@ -44,6 +44,7 @@ struct tr_shared tr_port publicPort; tr_timer * pulseTimer; + tr_timer * recheckTimer; tr_upnp * upnp; tr_natpmp * natpmp; @@ -83,7 +84,7 @@ getNatStateStr( int state ) } static void -natPulse( tr_shared * s ) +natPulse( tr_shared * s, tr_bool doPortCheck ) { const tr_port port = s->publicPort; const int isEnabled = s->isEnabled && !s->isShuttingDown; @@ -92,7 +93,7 @@ natPulse( tr_shared * s ) oldStatus = tr_sharedTraversalStatus( s ); s->natpmpStatus = tr_natpmpPulse( s->natpmp, port, isEnabled ); - s->upnpStatus = tr_upnpPulse( s->upnp, port, isEnabled ); + s->upnpStatus = tr_upnpPulse( s->upnp, port, isEnabled, doPortCheck ); newStatus = tr_sharedTraversalStatus( s ); if( newStatus != oldStatus ) @@ -186,10 +187,10 @@ incomingPeersPulse( tr_shared * s ) static int sharedPulse( void * vshared ) { - tr_bool keepPulsing = 1; + tr_bool keepPulsing = TRUE; tr_shared * shared = vshared; - natPulse( shared ); + natPulse( shared, FALSE ); if( !shared->isShuttingDown ) { @@ -199,18 +200,34 @@ sharedPulse( void * vshared ) { tr_ninf( getKey( ), _( "Stopped" ) ); tr_timerFree( &shared->pulseTimer ); + tr_timerFree( &shared->recheckTimer ); tr_socketListForEach( shared->bindSockets, &closeCb, shared ); tr_socketListFree( shared->bindSockets ); tr_natpmpClose( shared->natpmp ); tr_upnpClose( shared->upnp ); shared->session->shared = NULL; tr_free( shared ); - keepPulsing = 0; + keepPulsing = FALSE; } return keepPulsing; } +static int +recheckPulse( void * vshared ) +{ + tr_bool keepPulsing = TRUE; + tr_shared * shared = vshared; + + tr_ninf( getKey( ), _( "Checking to see if port %d is still open" ), shared->publicPort ); + natPulse( shared, TRUE ); + + if( shared->isShuttingDown ) + keepPulsing = FALSE; + + return keepPulsing; +} + /*** **** ***/ @@ -225,12 +242,12 @@ tr_sharedInit( tr_session * session, s->session = session; s->publicPort = publicPort; - s->shouldChange = TRUE; s->bindSockets = socks; s->shouldChange = TRUE; s->natpmp = tr_natpmpInit( ); s->upnp = tr_upnpInit( ); s->pulseTimer = tr_timerNew( session, sharedPulse, s, 1000 ); + s->recheckTimer = tr_timerNew( session, recheckPulse, s, 1000*60*20 ); /* 20 minutes */ s->isEnabled = isEnabled; s->upnpStatus = TR_PORT_UNMAPPED; s->natpmpStatus = TR_PORT_UNMAPPED; diff --git a/libtransmission/upnp.c b/libtransmission/upnp.c index dbf950e19..72ce3d02c 100644 --- a/libtransmission/upnp.c +++ b/libtransmission/upnp.c @@ -80,7 +80,8 @@ tr_upnpClose( tr_upnp * handle ) int tr_upnpPulse( tr_upnp * handle, int port, - int isEnabled ) + int isEnabled, + int doPortCheck ) { int ret; @@ -127,6 +128,24 @@ tr_upnpPulse( tr_upnp * handle, handle->state = TR_UPNP_UNMAP; } + if( isEnabled && handle->isMapped && doPortCheck ) + { + char portStr[8]; + char intPort[8]; + char intClient[16]; + int i; + + tr_snprintf( portStr, sizeof( portStr ), "%d", handle->port ); + i = UPNP_GetSpecificPortMappingEntry( handle->urls.controlURL, + handle->data.servicetype, portStr, + "TCP", intClient, intPort ); + if( i != UPNPCOMMAND_SUCCESS ) + { + tr_ninf( getKey( ), _( "Port %d isn't forwarded" ), handle->port ); + handle->isMapped = FALSE; + } + } + if( handle->state == TR_UPNP_UNMAP ) { char portStr[16]; diff --git a/libtransmission/upnp.h b/libtransmission/upnp.h index a6e2ce4ca..c5d220d05 100644 --- a/libtransmission/upnp.h +++ b/libtransmission/upnp.h @@ -25,6 +25,6 @@ void tr_upnpClose( tr_upnp * ); int tr_upnpPulse( tr_upnp *, int port, - int isEnabled ); - + int isEnabled, + int doPortCheck ); #endif