alanmcgovern / Mono.Nat

UPNP and NAT-PMP port forwarding for .NET
https://github.com/mono/Mono.Nat
MIT License
160 stars 156 forks source link

How to use it?) #14

Closed justscribe closed 4 years ago

justscribe commented 4 years ago

Hi,

I'm using MonoTorrent and want to clients can seed even if port not forwarded by it's router. I've tried to use this utility, but with no luck, I still can't connect with the specified port. Code example:

private async void DeviceFoundAsync(object sender, DeviceEventArgs e) {
            await _locker.WaitAsync();
            try {
                INatDevice device = e.Device;
                Mapping mapping = new Mapping(Protocol.Tcp, Core.TorrentClient.Port, Core.TorrentClient.Port);
                await device.CreatePortMapAsync(mapping);
                try {
                    Mapping m = await device.GetSpecificMappingAsync(Protocol.Tcp, Core.TorrentClient.Port);
                } catch {                    
                }
            } catch (Exception exc) {

            } finally {
                _locker.Release();
            }
        }

Is this is correct?

alanmcgovern commented 4 years ago

Yup!

There's no guarantee the users will have functional upnp or nat-pmp. It is possible for CreatePortMapAsync to throw an exception, so it should be wrapped in a try/catch too.

If you can add logging to see if any devices were discovered, and also if the port map was successful, that may help.

justscribe commented 4 years ago

Can it be somehow checked, if user can or can't use that upnp or nat-pmp functionality? And a strange thing, the DeviceFoundAsync handler never raised. I'm testing on my machine, seems NAT enabled in router settings: image

alanmcgovern commented 4 years ago

NAT Is not necessarily the same things as UPnP Port Forwarding or NAT-PMP. This is what my router has.

Screenshot 2019-12-05 at 10 45 53

My router also turns off 'NAT' when you enter 'Modem Mode'

Screenshot 2019-12-05 at 10 46 38

It's possible that your 'NAT' selector is related to that, rather than related to UPnP.

If you call NatUtility. StartDiscovery and no devices are found, then that's the best indicator there are no compatible devices. If other upnp/nat-pmp software can find a compatible device the there is a way to help diagnose the issue: https://smuxi.im/wiki/mono-nat/Debugging_the_reason_why_your_router_cannot_be_found

You could try enable that logging anyway and see what shows up in the logs.

justscribe commented 4 years ago

Found... It was disabled. image

justscribe commented 4 years ago

Another problem) Previously: Device Found, Type: UpnpNatDevice, Protocol: Upnp

05.12.2019 13:02:33> Error ActionFailed: PAL_UPNP_SOAP_E_ACTION_FAILED | Mono.Nat.MappingException: Error ActionFailed: PAL_UPNP_SOAP_E_ACTION_FAILED
   at Mono.Nat.Upnp.ResponseMessage.Decode(UpnpNatDevice device, String message)
   at Mono.Nat.Upnp.UpnpNatDevice.<DecodeMessageFromResponse>d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Mono.Nat.Upnp.UpnpNatDevice.<SendMessageAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Mono.Nat.Upnp.UpnpNatDevice.<CreatePortMapAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at SVitLAB.Net.NatWorker.<DeviceFoundAsync>d__6.MoveNext() in NatWorker.cs:line 59 | DeviceFoundAsync
alanmcgovern commented 4 years ago

The verbose logs may help diagnose this. UPnP is based on XML, and many manufacturers generate it differently/incorrectly and many routers have unusual quirks.

NAT-PMP is a binary format and, generally speaking, always works :(

alanmcgovern commented 4 years ago

In addition to that, can you try setting the Lifetime on the Mapping object to something like 7200 (2 hours)? Some routers fail when you pass a non-zero value, some fail when you pass a value of zero. Zero is supposed to mean 'indefinite' according to the spec.

justscribe commented 4 years ago
  1. There is no Verbose property=)
  2. With 7200 or 0 Lifetime error is the same.
  3. Issue resolved by setting "Allow users to configure" under UPnP to enabled in router. I think that may increase amount of seeds. Many depends from router default config. Thank you for help.
alanmcgovern commented 4 years ago

Ah awesome! Glad you got your router working :)

It would definitely be useful to ship upnp/nat-pmp support in some form, and if possible prompt users to manually enable upnp (or manually forward ports) if a client is unreachable.

justscribe commented 4 years ago

But if user already reachable, and we'll enable forwarding, can that bring some issues?

alanmcgovern commented 4 years ago

No, it shouldn't. If a manual port mapping was created by the user then the automatic upnp one will be ignored, or the CreatePortMap call will fail with an exception.

This could always be made an option the user can choose to disable. However I'd have it enabled by default