static int natpmpPulse( ml_upnpmp_t * map ) { int ret; if( map->enabled && ( map->natpmpState == ML_NATPMP_DISCOVER ) ) { int val = initnatpmp( &map->natpmp, 0, 0 ); dbg_printf( "initnatpmp = %d\n", val ); val = sendpublicaddressrequest( &map->natpmp ); dbg_printf( "sendpublicaddressrequest = %d\n", val ); map->natpmpState = val < 0 ? ML_NATPMP_ERR : ML_NATPMP_RECV_PUB; map->natpmpDiscovered = 1; setCommandTime( map ); } if( ( map->natpmpState == ML_NATPMP_RECV_PUB ) && canSendCommand( map ) ) { natpmpresp_t response; const int val = readnatpmpresponseorretry( &map->natpmp, &response ); dbg_printf( "readnatpmpresponseorretry = %d\n", val ); if( val >= 0 ) { dbg_printf( "Found public address \"%s\"\n", inet_ntoa( response.pnu.publicaddress.addr ) ); map->natpmpState = ML_NATPMP_IDLE; } else if( val != NATPMP_TRYAGAIN ) { map->natpmpState = ML_NATPMP_ERR; } } if( ( map->natpmpState == ML_NATPMP_IDLE ) || ( map->natpmpState == ML_NATPMP_ERR ) ) { if( map->natpmpMapped && ( ! map->enabled ) ) map->natpmpState = ML_NATPMP_SEND_UNMAP; } if( ( map->natpmpState == ML_NATPMP_SEND_UNMAP ) && canSendCommand( map ) ) { const int val = sendnewportmappingrequest( &map->natpmp, NATPMP_PROTOCOL_TCP, map->intPort, map->extPort, 0 ); dbg_printf( "sendnewportmappingrequest = %d\n", val ); map->natpmpState = val < 0 ? ML_NATPMP_ERR : ML_NATPMP_RECV_UNMAP; setCommandTime( map ); } if( map->natpmpState == ML_NATPMP_RECV_UNMAP ) { natpmpresp_t resp; const int val = readnatpmpresponseorretry( &map->natpmp, &resp ); dbg_printf( "readnatpmpresponseorretry = %d\n", val ); if( val >= 0 ) { const int p = resp.pnu.newportmapping.privateport; dbg_printf( "no longer forwarding port %d\n", p ); if( map->extPort == p ) { map->extPort = 0; map->natpmpState = ML_NATPMP_IDLE; map->natpmpMapped = 0; } } else if( val != NATPMP_TRYAGAIN ) { map->natpmpState = ML_NATPMP_ERR; } } if( map->natpmpState == ML_NATPMP_IDLE ) { if( map->enabled && !map->natpmpMapped && map->natpmpDiscovered ) map->natpmpState = ML_NATPMP_SEND_MAP; else if( map->natpmpMapped && time(NULL) >= map->renewTime ) map->natpmpState = ML_NATPMP_SEND_MAP; } if( ( map->natpmpState == ML_NATPMP_SEND_MAP ) && canSendCommand( map ) ) { const int val = sendnewportmappingrequest( &map->natpmp, NATPMP_PROTOCOL_TCP, map->intPort, map->extPort, LIFETIME_SECS ); dbg_printf( "sendnewportmappingrequest = %d\n", val ); map->natpmpState = val < 0 ? ML_NATPMP_ERR : ML_NATPMP_RECV_MAP; setCommandTime( map ); } if( map->natpmpState == ML_NATPMP_RECV_MAP ) { natpmpresp_t resp; const int val = readnatpmpresponseorretry( &map->natpmp, &resp ); dbg_printf( "readnatpmpresponseorretry = %d\n", val ); if( val >= 0 ) { map->natpmpState = ML_NATPMP_IDLE; map->natpmpMapped = 1; map->renewTime = time(NULL) + LIFETIME_SECS; map->extPort = resp.pnu.newportmapping.privateport; dbg_printf( "Port %d forwarded successfully\n", map->extPort ); } else if( val != NATPMP_TRYAGAIN ) { map->natpmpState = ML_NATPMP_ERR; } } switch( map->natpmpState ) { case ML_NATPMP_IDLE: ret = map->natpmpMapped ? ML_PORT_MAPPED : ML_PORT_UNMAPPED; break; case ML_NATPMP_DISCOVER: ret = ML_PORT_UNMAPPED; break; case ML_NATPMP_RECV_PUB: case ML_NATPMP_SEND_MAP: case ML_NATPMP_RECV_MAP: ret = ML_PORT_MAPPING; break; case ML_NATPMP_SEND_UNMAP: case ML_NATPMP_RECV_UNMAP: ret = ML_PORT_UNMAPPING; break; default: ret = ML_PORT_ERROR; break; } return ret; }
int tr_natpmpPulse( struct tr_natpmp * nat, tr_port private_port, bool is_enabled, tr_port * public_port ) { int ret; if( is_enabled && ( nat->state == TR_NATPMP_DISCOVER ) ) { int val = initnatpmp( &nat->natpmp ); logVal( "initnatpmp", val ); val = sendpublicaddressrequest( &nat->natpmp ); logVal( "sendpublicaddressrequest", val ); nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_PUB; nat->has_discovered = true; setCommandTime( nat ); } if( ( nat->state == TR_NATPMP_RECV_PUB ) && canSendCommand( nat ) ) { natpmpresp_t response; const int val = readnatpmpresponseorretry( &nat->natpmp, &response ); logVal( "readnatpmpresponseorretry", val ); if( val >= 0 ) { char str[128]; evutil_inet_ntop( AF_INET, &response.pnu.publicaddress.addr, str, sizeof( str ) ); tr_ninf( getKey( ), _( "Found public address \"%s\"" ), str ); nat->state = TR_NATPMP_IDLE; } else if( val != NATPMP_TRYAGAIN ) { nat->state = TR_NATPMP_ERR; } } if( ( nat->state == TR_NATPMP_IDLE ) || ( nat->state == TR_NATPMP_ERR ) ) { if( nat->is_mapped && ( !is_enabled || ( nat->private_port != private_port ) ) ) nat->state = TR_NATPMP_SEND_UNMAP; } if( ( nat->state == TR_NATPMP_SEND_UNMAP ) && canSendCommand( nat ) ) { const int val = sendnewportmappingrequest( &nat->natpmp, NATPMP_PROTOCOL_TCP, nat->private_port, nat->public_port, 0 ); logVal( "sendnewportmappingrequest", val ); nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_UNMAP; setCommandTime( nat ); } if( nat->state == TR_NATPMP_RECV_UNMAP ) { natpmpresp_t resp; const int val = readnatpmpresponseorretry( &nat->natpmp, &resp ); logVal( "readnatpmpresponseorretry", val ); if( val >= 0 ) { const int private_port = resp.pnu.newportmapping.privateport; tr_ninf( getKey( ), _( "no longer forwarding port %d" ), private_port ); if( nat->private_port == private_port ) { nat->private_port = 0; nat->public_port = 0; nat->state = TR_NATPMP_IDLE; nat->is_mapped = false; } } else if( val != NATPMP_TRYAGAIN ) { nat->state = TR_NATPMP_ERR; } } if( nat->state == TR_NATPMP_IDLE ) { if( is_enabled && !nat->is_mapped && nat->has_discovered ) nat->state = TR_NATPMP_SEND_MAP; else if( nat->is_mapped && tr_time( ) >= nat->renew_time ) nat->state = TR_NATPMP_SEND_MAP; } if( ( nat->state == TR_NATPMP_SEND_MAP ) && canSendCommand( nat ) ) { const int val = sendnewportmappingrequest( &nat->natpmp, NATPMP_PROTOCOL_TCP, private_port, private_port, LIFETIME_SECS ); logVal( "sendnewportmappingrequest", val ); nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_MAP; setCommandTime( nat ); } if( nat->state == TR_NATPMP_RECV_MAP ) { natpmpresp_t resp; const int val = readnatpmpresponseorretry( &nat->natpmp, &resp ); logVal( "readnatpmpresponseorretry", val ); if( val >= 0 ) { nat->state = TR_NATPMP_IDLE; nat->is_mapped = true; nat->renew_time = tr_time( ) + ( resp.pnu.newportmapping.lifetime / 2 ); nat->private_port = resp.pnu.newportmapping.privateport; nat->public_port = resp.pnu.newportmapping.mappedpublicport; tr_ninf( getKey( ), _( "Port %d forwarded successfully" ), nat->private_port ); } else if( val != NATPMP_TRYAGAIN ) { nat->state = TR_NATPMP_ERR; } } switch( nat->state ) { case TR_NATPMP_IDLE: *public_port = nat->public_port; return nat->is_mapped ? TR_PORT_MAPPED : TR_PORT_UNMAPPED; break; case TR_NATPMP_DISCOVER: ret = TR_PORT_UNMAPPED; break; case TR_NATPMP_RECV_PUB: case TR_NATPMP_SEND_MAP: case TR_NATPMP_RECV_MAP: ret = TR_PORT_MAPPING; break; case TR_NATPMP_SEND_UNMAP: case TR_NATPMP_RECV_UNMAP: ret = TR_PORT_UNMAPPING; break; default: ret = TR_PORT_ERROR; break; } return ret; }
int tr_natpmpPulse( struct tr_natpmp * nat, int port, int isEnabled ) { int ret; if( isEnabled && ( nat->state == TR_NATPMP_DISCOVER ) ) { int val = initnatpmp( &nat->natpmp ); logVal( "initnatpmp", val ); val = sendpublicaddressrequest( &nat->natpmp ); logVal( "sendpublicaddressrequest", val ); nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_PUB; nat->hasDiscovered = 1; setCommandTime( nat ); } if( ( nat->state == TR_NATPMP_RECV_PUB ) && canSendCommand( nat ) ) { natpmpresp_t response; const int val = readnatpmpresponseorretry( &nat->natpmp, &response ); logVal( "readnatpmpresponseorretry", val ); if( val >= 0 ) { tr_ninf( getKey( ), _( "Found public address \"%s\"" ), inet_ntoa( response.pnu.publicaddress.addr ) ); nat->state = TR_NATPMP_IDLE; } else if( val != NATPMP_TRYAGAIN ) { nat->state = TR_NATPMP_ERR; } } if( ( nat->state == TR_NATPMP_IDLE ) || ( nat->state == TR_NATPMP_ERR ) ) { if( nat->isMapped && ( !isEnabled || ( nat->port != port ) ) ) nat->state = TR_NATPMP_SEND_UNMAP; } if( ( nat->state == TR_NATPMP_SEND_UNMAP ) && canSendCommand( nat ) ) { const int val = sendnewportmappingrequest( &nat->natpmp, NATPMP_PROTOCOL_TCP, nat->port, nat->port, 0 ); logVal( "sendnewportmappingrequest", val ); nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_UNMAP; setCommandTime( nat ); } if( nat->state == TR_NATPMP_RECV_UNMAP ) { natpmpresp_t resp; const int val = readnatpmpresponseorretry( &nat->natpmp, &resp ); logVal( "readnatpmpresponseorretry", val ); if( val >= 0 ) { const int p = resp.pnu.newportmapping.privateport; tr_ninf( getKey( ), _( "no longer forwarding port %d" ), p ); if( nat->port == p ) { nat->port = -1; nat->state = TR_NATPMP_IDLE; nat->isMapped = 0; } } else if( val != NATPMP_TRYAGAIN ) { nat->state = TR_NATPMP_ERR; } } if( nat->state == TR_NATPMP_IDLE ) { if( isEnabled && !nat->isMapped && nat->hasDiscovered ) nat->state = TR_NATPMP_SEND_MAP; else if( nat->isMapped && tr_time( ) >= nat->renewTime ) nat->state = TR_NATPMP_SEND_MAP; } if( ( nat->state == TR_NATPMP_SEND_MAP ) && canSendCommand( nat ) ) { const int val = sendnewportmappingrequest( &nat->natpmp, NATPMP_PROTOCOL_TCP, port, port, LIFETIME_SECS ); logVal( "sendnewportmappingrequest", val ); nat->state = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_MAP; setCommandTime( nat ); } if( nat->state == TR_NATPMP_RECV_MAP ) { natpmpresp_t resp; const int val = readnatpmpresponseorretry( &nat->natpmp, &resp ); logVal( "readnatpmpresponseorretry", val ); if( val >= 0 ) { nat->state = TR_NATPMP_IDLE; nat->isMapped = 1; nat->renewTime = tr_time( ) + LIFETIME_SECS; nat->port = resp.pnu.newportmapping.privateport; tr_ninf( getKey( ), _( "Port %d forwarded successfully" ), nat->port ); } else if( val != NATPMP_TRYAGAIN ) { nat->state = TR_NATPMP_ERR; } } switch( nat->state ) { case TR_NATPMP_IDLE: ret = nat->isMapped ? TR_PORT_MAPPED : TR_PORT_UNMAPPED; break; case TR_NATPMP_DISCOVER: ret = TR_PORT_UNMAPPED; break; case TR_NATPMP_RECV_PUB: case TR_NATPMP_SEND_MAP: case TR_NATPMP_RECV_MAP: ret = TR_PORT_MAPPING; break; case TR_NATPMP_SEND_UNMAP: case TR_NATPMP_RECV_UNMAP: ret = TR_PORT_UNMAPPING; break; default: ret = TR_PORT_ERROR; break; } return ret; }