Opened 13 years ago

Closed 11 years ago

Last modified 11 years ago

#165 closed Enhancement (fixed)

'smarter' NAT traversal detection

Reported by: jah Owned by:
Priority: Normal Milestone:
Component: libtransmission Version: 0.93
Severity: Normal Keywords: upnp nat-pmp traversal
Cc:

Description

If NAT traversal is enabled, and T manages to forward a port using one of the two protocols, it still tries to detect for devices on the other protocol, which is unnecessary as a device has already been found.

eg T finds an airport router and maps using nat-pmp, however it will still search for upnp devices, even though a mapping has already been created. Once a device is found, T should stop searching until the mapping is lost and it must look again.

Change History (7)

comment:1 Changed 12 years ago by mtolman

  • Milestone Sometime deleted
  • Priority changed from Low to Normal
  • Type changed from Defect to Bug Report
  • Version changed from 0.6 to 0.80

Not only does the UPNP not detect when the nat-pmp has mapped a port, but it doesn't even seem to remember when it maps one. It just keeps remapping over and over - every 60 seconds. This needs to be fixed.

comment:2 follow-up: Changed 12 years ago by mtolman

  • Component changed from Transmission to libtransmission
  • Keywords upnp added
  • Owner somebody deleted

Here's a grep of my logs. I'm not certain, but I think I know what is happening. The upnp pulse is called from the "shared" thread periodically. Even if it knows enough to set discovering=0, it calls watchSSDP( &upnp->devices, upnp->infd ); It needs to to, for various reasons - example: if there's more than one device on the network.

watchSSDP, recvSSDP, and parseSSDP do their thing, and since the logs contain "found upnp ssdp notify request" we know what path was followed. Which leads us back to watchSSDP around line 486 and deviceAdd() where "ii->lastcheck = 0" results in the already mapped device doing a "get" and "mapped", etc.

Now that we know what is happening, and sice the logs don't show T sending multiple discover messages, the question is - Where are all those notify requests coming from? Is it just the original request stuck in a buffer? Is the router broken and sending them?

Regardless, it needs to be fixed. I don't know enough about the upnp protocol or T's code to suggest where in the chain to add checks for already mapped devices, so I'll leave the fix to you guys. It might be as simple as making sure upnp->infd doesn't contain stale info.

I hope I've helped.

egrep '(nat|upnp|pmp)' t.log 
nat-pmp device is 192.168.1.2
nat-pmp set port 9090
upnp port changed from 0 to 9090
starting nat-pmp
nat-pmp create multicast socket 4
starting upnp
nat-pmp state idle -> add with port 9090
sending upnp ssdp discover message
nat-pmp not supported by device
nat-pmp state add -> nobodyhome on pulse
found upnp ssdp m-search response
new upnp device 192.168.1.154, port 8008, path /RootDevice.xml
upnp device 192.168.1.154: parse root failed
upnp device 192.168.1.154: error, state 1 -> error
sending upnp ssdp discover message
found upnp ssdp m-search response
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
sending upnp ssdp discover message
found upnp ssdp m-search response
found upnp ssdp notify request
new upnp device 192.168.1.2, port 5431, path /dyndev/uuid:000f-66cc-a8340000dadc
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device /dyndev/uuid:000f-66cc-a8340000dadc: found scpd "/dynsvc/WANIPConnection:1.xml" and soap "/uuid:000f-66cc-a8340200dadc/WANIPConnection:1"
upnp device 192.168.1.2: parsed root, state root -> scpd
upnp device 192.168.1.2: parsed scpd, state scpd -> ready
upnp device 192.168.1.2: want mapping, state ready -> get
upnp device 192.168.1.2: no mapping, state get -> add
upnp device 192.168.1.2: add attempt, state add -> get
upnp device 192.168.1.2: good mapping, state get -> mapped
upnp successful for port 9090
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: check mapping, state mapped -> get
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: good mapping, state get -> mapped
upnp successful for port 9090
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: check mapping, state mapped -> get
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: good mapping, state get -> mapped
upnp successful for port 9090
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: check mapping, state mapped -> get
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: good mapping, state get -> mapped
upnp successful for port 9090
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: check mapping, state mapped -> get
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: good mapping, state get -> mapped
upnp successful for port 9090
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: check mapping, state mapped -> get
upnp device 192.168.1.2: good mapping, state get -> mapped
upnp successful for port 9090
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: check mapping, state mapped -> get
upnp device 192.168.1.2: good mapping, state get -> mapped
upnp successful for port 9090
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
found upnp ssdp notify request
upnp device 192.168.1.2: check mapping, state mapped -> get
upnp device 192.168.1.2: good mapping, state get -> mapped
upnp successful for port 9090
stopping nat-pmp
stopping upnp
upnp device 192.168.1.2: stopping upnp, state mapped -> delete
forgetting upnp device 192.168.1.154
upnp device 192.168.1.2: deleted, state delete -> ready
forgetting upnp device 192.168.1.2

comment:3 in reply to: ↑ 2 Changed 12 years ago by joshe

Replying to mtolman:

Whenever a notify is seen we need to check the mapping since the device may have been reset. Unless Transmission is somehow triggering the frequent notify then it's behavior is correct.

comment:4 Changed 12 years ago by charles

  • Type changed from Bug Report to Enhancement

comment:5 Changed 11 years ago by sanmarcos

  • Version changed from 0.80 to 0.93

I can confirm this with 0.93

comment:6 Changed 11 years ago by tiennou

  • Resolution set to fixed
  • Status changed from new to closed

I'm closing this since we're undergoing major NAT-traversal code changes, and I'll try to tackle those issues at rewrite (like "60 seconds republish delay for UPnP is too low" and "don't bother mapping ports with a non-recognized protocol")

comment:7 Changed 11 years ago by tiennou

  • Keywords nat-pmp traversal added
Note: See TracTickets for help on using tickets.