private void ConnectivityCheckTimerCallback(object state) { if (_upnpDeviceStatus == UPnPDeviceStatus.Identifying) { _upnpDevice = null; } InternetConnectivityStatus newInternetStatus = InternetConnectivityStatus.Identifying; UPnPDeviceStatus newUPnPStatus; if (_profile.EnableUPnP) { newUPnPStatus = UPnPDeviceStatus.Identifying; } else { newUPnPStatus = UPnPDeviceStatus.Disabled; } try { if (_profile.Proxy != null) { switch (_profile.Proxy.Type) { case NetProxyType.Http: newInternetStatus = InternetConnectivityStatus.HttpProxyInternetConnection; break; case NetProxyType.Socks5: newInternetStatus = InternetConnectivityStatus.Socks5ProxyInternetConnection; break; default: throw new NotSupportedException("Proxy type not supported."); } newUPnPStatus = UPnPDeviceStatus.Disabled; return; } NetworkInfo defaultNetworkInfo = NetUtilities.GetDefaultNetworkInfo(); if (defaultNetworkInfo == null) { //no internet available; newInternetStatus = InternetConnectivityStatus.NoInternetConnection; newUPnPStatus = UPnPDeviceStatus.Disabled; return; } if (!NetUtilities.IsPrivateIP(defaultNetworkInfo.LocalIP)) { //public ip so, direct internet connection available newInternetStatus = InternetConnectivityStatus.DirectInternetConnection; newUPnPStatus = UPnPDeviceStatus.Disabled; _localLiveIP = defaultNetworkInfo.LocalIP; return; } else { _localLiveIP = null; } if (newUPnPStatus == UPnPDeviceStatus.Disabled) { newInternetStatus = InternetConnectivityStatus.NatOrFirewalledInternetConnection; return; } //check for upnp device if (defaultNetworkInfo.LocalIP.AddressFamily == AddressFamily.InterNetworkV6) { newInternetStatus = InternetConnectivityStatus.NatOrFirewalledInternetConnection; newUPnPStatus = UPnPDeviceStatus.Disabled; return; } try { if ((_upnpDevice == null) || (!_upnpDevice.NetworkBroadcastAddress.Equals(defaultNetworkInfo.BroadcastIP))) { _upnpDevice = InternetGatewayDevice.Discover(defaultNetworkInfo.BroadcastIP, 2000); } newInternetStatus = InternetConnectivityStatus.NatInternetConnectionViaUPnPRouter; } catch { newInternetStatus = InternetConnectivityStatus.NatOrFirewalledInternetConnection; newUPnPStatus = UPnPDeviceStatus.DeviceNotFound; throw; } //find external ip from router try { _upnpExternalIP = _upnpDevice.GetExternalIPAddress(); if (_upnpExternalIP.ToString() == "0.0.0.0") { newInternetStatus = InternetConnectivityStatus.NoInternetConnection; newUPnPStatus = UPnPDeviceStatus.Disabled; return; //external ip not available so no internet connection available } else if (NetUtilities.IsPrivateIP(_upnpExternalIP)) { newUPnPStatus = UPnPDeviceStatus.ExternalIpPrivate; return; //no use of doing port forwarding for private upnp ip address } } catch { _upnpExternalIP = null; } //do upnp port forwarding for Bit Chat if (_upnpDevice.ForwardPort(ProtocolType.Tcp, _localPort, new IPEndPoint(defaultNetworkInfo.LocalIP, _localPort), "Bit Chat", true)) { newUPnPStatus = UPnPDeviceStatus.PortForwarded; } else { newUPnPStatus = UPnPDeviceStatus.PortForwardingFailed; } //do upnp port forwarding for DHT _upnpDevice.ForwardPort(ProtocolType.Udp, _dhtClient.LocalPort, new IPEndPoint(defaultNetworkInfo.LocalIP, _dhtClient.LocalPort), "Bit Chat DHT", true); } catch (Exception ex) { Debug.Write("ConnectionManager.ConnectivityCheckTimerCallback", ex); } finally { try { //validate change in status by performing tests if (_internetStatus != newInternetStatus) { switch (newInternetStatus) { case InternetConnectivityStatus.NoInternetConnection: _localLiveIP = null; _upnpExternalIP = null; _connectivityCheckExternalEP = null; break; case InternetConnectivityStatus.HttpProxyInternetConnection: case InternetConnectivityStatus.Socks5ProxyInternetConnection: if (!_profile.Proxy.IsProxyAvailable()) { newInternetStatus = InternetConnectivityStatus.NoInternetConnection; } _localLiveIP = null; _upnpExternalIP = null; _connectivityCheckExternalEP = null; break; default: if (WebUtilities.IsWebAccessible()) { switch (newInternetStatus) { case InternetConnectivityStatus.DirectInternetConnection: if (!DoWebCheckIncomingConnection(_localPort)) { _localLiveIP = null; } break; case InternetConnectivityStatus.NatOrFirewalledInternetConnection: if (!DoWebCheckIncomingConnection(_localPort)) { _connectivityCheckExternalEP = null; } break; case InternetConnectivityStatus.NatInternetConnectionViaUPnPRouter: break; default: _localLiveIP = null; _upnpExternalIP = null; _connectivityCheckExternalEP = null; break; } } else { newInternetStatus = InternetConnectivityStatus.NoInternetConnection; _localLiveIP = null; _upnpExternalIP = null; _connectivityCheckExternalEP = null; } break; } } if ((newInternetStatus == InternetConnectivityStatus.NatInternetConnectionViaUPnPRouter) && (_upnpDeviceStatus != newUPnPStatus) && (newUPnPStatus == UPnPDeviceStatus.PortForwarded)) { if (_upnpDeviceStatus == UPnPDeviceStatus.PortForwardedNotAccessible) { newUPnPStatus = UPnPDeviceStatus.PortForwardedNotAccessible; } else if (!DoWebCheckIncomingConnection(_localPort)) { newUPnPStatus = UPnPDeviceStatus.PortForwardedNotAccessible; } } if ((_internetStatus != newInternetStatus) || (_upnpDeviceStatus != newUPnPStatus)) { _internetStatus = newInternetStatus; _upnpDeviceStatus = newUPnPStatus; if (this.ExternalEndPoint == null) { //if no incoming connection possible if (_dhtClient.GetTotalNodes() < DhtClient.KADEMLIA_K) { _dhtSeedingTracker.LookupOnly = true; _dhtSeedingTracker.ScheduleUpdateNow(); //start finding dht nodes immediately } else { _dhtSeedingTracker.StopTracking(); //we have enough dht nodes and can stop seeding tracker } } else { _dhtSeedingTracker.LookupOnly = false; if (!_dhtSeedingTracker.IsTrackerRunning) { _dhtSeedingTracker.StartTracking(); //keep seeding tracker running for other peers to find dht bootstrap nodes } } InternetConnectivityStatusChanged?.Invoke(this, EventArgs.Empty); } //schedule next check if (_connectivityCheckTimer != null) { if ((_internetStatus == InternetConnectivityStatus.NoInternetConnection) || (_upnpDeviceStatus == UPnPDeviceStatus.DeviceNotFound) || (_upnpDeviceStatus == UPnPDeviceStatus.PortForwardingFailed)) { _connectivityCheckTimer.Change(10000, Timeout.Infinite); } else { _connectivityCheckTimer.Change(CONNECTIVITY_CHECK_TIMER_INTERVAL, Timeout.Infinite); } } } catch { } } }
private void UPnPTimerCallback(object state) { try { DefaultNetworkInfo defaultNetworkInfo = NetUtilities.GetDefaultNetworkInfo(); if (defaultNetworkInfo == null) { //no internet available; _upnpStatus = UPnPStatus.NoInternetConnection; return; } if (defaultNetworkInfo.IsPublicIP) { //public ip so no need to do port forwarding _upnpStatus = UPnPStatus.PortForwardingNotRequired; return; } IPEndPoint LocalNetworkEP = new IPEndPoint(defaultNetworkInfo.LocalIP, ((IPEndPoint)_tcpListener.LocalEndpoint).Port); try { if ((_upnp == null) || (!_upnp.NetworkBroadcastAddress.Equals(defaultNetworkInfo.BroadcastIP))) { _upnp = InternetGatewayDevice.Discover(defaultNetworkInfo.BroadcastIP, 30000); } } catch { _upnpStatus = UPnPStatus.UPnPDeviceNotFound; throw; } //find external ip from router try { IPAddress externalIP = _upnp.GetExternalIPAddress(); if (!_externalSelfEP.Address.Equals(externalIP)) { _externalSelfEP = new IPEndPoint(externalIP, _externalSelfEP.Port); } } catch { } int externalPort = LocalNetworkEP.Port; bool isTCPMapped = false; try { int loopCount = 0; while (true) { PortMappingEntry portMap = _upnp.GetSpecificPortMappingEntry(ProtocolType.Tcp, externalPort); if (portMap == null) { break; //port available } if (portMap.InternalEP.Equals(LocalNetworkEP)) { //port already mapped with us isTCPMapped = true; _upnpStatus = UPnPStatus.PortForwarded; break; } //find new port for mapping if (externalPort < ushort.MaxValue) { externalPort++; } else { externalPort = 1024; } if (loopCount > ushort.MaxValue) { return; } loopCount++; } } catch { } if (!isTCPMapped) { try { _upnp.AddPortMapping(ProtocolType.Tcp, externalPort, LocalNetworkEP, "BitChat - TCP"); if (_externalSelfEP.Port != externalPort) { _externalSelfEP = new IPEndPoint(_externalSelfEP.Address, externalPort); } _upnpStatus = UPnPStatus.PortForwarded; Debug.Write("BitChatClient.UPnPTimerCallback", "tcp port mapped " + externalPort); } catch { try { _upnp.DeletePortMapping(ProtocolType.Tcp, externalPort); _upnp.AddPortMapping(ProtocolType.Tcp, externalPort, LocalNetworkEP, "BitChat - TCP"); if (_externalSelfEP.Port != externalPort) { _externalSelfEP = new IPEndPoint(_externalSelfEP.Address, externalPort); } _upnpStatus = UPnPStatus.PortForwarded; Debug.Write("BitChat.UPnPTimerCallback", "tcp port mapped " + externalPort); } catch { } } } } catch (Exception ex) { Debug.Write("BitChat.UPnPTimerCallback", ex); } finally { if (_upnpTimer != null) { switch (_upnpStatus) { case Connections.UPnPStatus.UPnPDeviceNotFound: _upnpTimer.Change(10000, Timeout.Infinite); break; default: _upnpTimer.Change(UPNP_TIMER_INTERVAL, Timeout.Infinite); break; } } } }