diff --git a/Makefile.homebrew b/Makefile.homebrew index f57f6495..05fd8dcf 100644 --- a/Makefile.homebrew +++ b/Makefile.homebrew @@ -11,6 +11,7 @@ LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem ifeq ($(USE_UPNP),yes) LDFLAGS += -ldl CXXFLAGS += -DUSE_UPNP + LDLIBS += -lminiupnpc endif # OSX Notes diff --git a/Makefile.osx b/Makefile.osx index f9372c8f..8d6a1c65 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -13,6 +13,11 @@ endif ifeq ($(USE_UPNP),yes) LDFLAGS += -ldl CXXFLAGS += -DUSE_UPNP +ifeq ($(USE_STATIC),yes) + LDLIBS += /usr/local/lib/libminiupnpc.a +else + LDLIBS += -lminiupnpc +endif endif ifeq ($(USE_AESNI),1) diff --git a/UPnP.cpp b/UPnP.cpp index 6a46ee77..20244786 100644 --- a/UPnP.cpp +++ b/UPnP.cpp @@ -22,49 +22,49 @@ namespace i2p { namespace transport { - UPnP::UPnP () : m_IsRunning(false), m_Thread (nullptr), m_Timer (m_Service) - { - } + UPnP::UPnP () : m_IsRunning(false), m_Thread (nullptr), m_Timer (m_Service) + { + } - void UPnP::Stop () - { + void UPnP::Stop () + { if (m_IsRunning) { - LogPrint(eLogInfo, "UPnP: stopping"); - m_IsRunning = false; + LogPrint(eLogInfo, "UPnP: stopping"); + m_IsRunning = false; m_Timer.cancel (); m_Service.stop (); - if (m_Thread) - { - m_Thread->join (); - m_Thread.reset (nullptr); - } + if (m_Thread) + { + m_Thread->join (); + m_Thread.reset (nullptr); + } CloseMapping (); - Close (); + Close (); } - } + } - void UPnP::Start() - { + void UPnP::Start() + { m_IsRunning = true; - LogPrint(eLogInfo, "UPnP: starting"); + LogPrint(eLogInfo, "UPnP: starting"); m_Service.post (std::bind (&UPnP::Discover, this)); std::unique_lock l(m_StartedMutex); - m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this))); + m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this))); m_Started.wait_for (l, std::chrono::seconds (5)); // 5 seconds maximum - } - - UPnP::~UPnP () - { - Stop (); - } + } - void UPnP::Run () - { + UPnP::~UPnP () + { + Stop (); + } + + void UPnP::Run () + { while (m_IsRunning) { try - { + { m_Service.run (); // Discover failed break; // terminate the thread @@ -73,127 +73,127 @@ namespace transport { LogPrint (eLogError, "UPnP: runtime exception: ", ex.what ()); PortMapping (); - } - } - } - - void UPnP::Discover () - { - int nerror = 0; + } + } + } + + void UPnP::Discover () + { + int nerror = 0; #if MINIUPNPC_API_VERSION >= 14 - m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, 2, &nerror); + m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, 2, &nerror); #else - m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror); + m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror); #endif { - // notify satrting thread + // notify satrting thread std::unique_lock l(m_StartedMutex); m_Started.notify_all (); - } - - int r; - r = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr)); - if (r == 1) - { - r = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) - { - LogPrint (eLogError, "UPnP: UPNP_GetExternalIPAddress() returned ", r); - return; - } - else - { - if (!m_externalIPAddress[0]) - { - LogPrint (eLogError, "UPnP: GetExternalIPAddress() failed."); - return; - } - } - } - else - { - LogPrint (eLogError, "UPnP: GetValidIGD() failed."); - return; } - // UPnP discovered + int r; + r = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr)); + if (r == 1) + { + r = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress); + if(r != UPNPCOMMAND_SUCCESS) + { + LogPrint (eLogError, "UPnP: UPNP_GetExternalIPAddress() returned ", r); + return; + } + else + { + if (!m_externalIPAddress[0]) + { + LogPrint (eLogError, "UPnP: GetExternalIPAddress() failed."); + return; + } + } + } + else + { + LogPrint (eLogError, "UPnP: GetValidIGD() failed."); + return; + } + + // UPnP discovered LogPrint (eLogDebug, "UPnP: ExternalIPAddress is ", m_externalIPAddress); - i2p::context.UpdateAddress (boost::asio::ip::address::from_string (m_externalIPAddress)); + i2p::context.UpdateAddress (boost::asio::ip::address::from_string (m_externalIPAddress)); // port mapping PortMapping (); - } + } void UPnP::PortMapping () { const auto& a = context.GetRouterInfo().GetAddresses(); for (const auto& address : a) - { - if (!address->host.is_v6 ()) - TryPortMapping (address); - } + { + if (!address->host.is_v6 ()) + TryPortMapping (address); + } m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes m_Timer.async_wait ([this](const boost::system::error_code& ecode) - { - if (ecode != boost::asio::error::operation_aborted) - PortMapping (); - }); + { + if (ecode != boost::asio::error::operation_aborted) + PortMapping (); + }); - } + } void UPnP::CloseMapping () { const auto& a = context.GetRouterInfo().GetAddresses(); for (const auto& address : a) - { - if (!address->host.is_v6 ()) - CloseMapping (address); - } - } + { + if (!address->host.is_v6 ()) + CloseMapping (address); + } + } - void UPnP::TryPortMapping (std::shared_ptr address) - { - std::string strType (GetProto (address)), strPort (std::to_string (address->port)); - int r; - std::string strDesc; i2p::config::GetOption("upnp.name", strDesc); - r = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0, "0"); - if (r!=UPNPCOMMAND_SUCCESS) - { - LogPrint (eLogError, "UPnP: AddPortMapping (", m_NetworkAddr, ":", strPort, ") failed with code ", r); - return; - } - else - { - LogPrint (eLogDebug, "UPnP: Port Mapping successful. (", m_NetworkAddr ,":", strPort, " type ", strType, " -> ", m_externalIPAddress ,":", strPort ,")"); - return; - } - } + void UPnP::TryPortMapping (std::shared_ptr address) + { + std::string strType (GetProto (address)), strPort (std::to_string (address->port)); + int r; + std::string strDesc; i2p::config::GetOption("upnp.name", strDesc); + r = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0, "0"); + if (r!=UPNPCOMMAND_SUCCESS) + { + LogPrint (eLogError, "UPnP: AddPortMapping (", m_NetworkAddr, ":", strPort, ") failed with code ", r); + return; + } + else + { + LogPrint (eLogDebug, "UPnP: Port Mapping successful. (", m_NetworkAddr ,":", strPort, " type ", strType, " -> ", m_externalIPAddress ,":", strPort ,")"); + return; + } + } - void UPnP::CloseMapping (std::shared_ptr address) - { - std::string strType (GetProto (address)), strPort (std::to_string (address->port)); - int r = 0; - r = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), 0); - LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", r); - } + void UPnP::CloseMapping (std::shared_ptr address) + { + std::string strType (GetProto (address)), strPort (std::to_string (address->port)); + int r = 0; + r = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), 0); + LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", r); + } - void UPnP::Close () - { - freeUPNPDevlist (m_Devlist); - m_Devlist = 0; - FreeUPNPUrls (&m_upnpUrls); - } + void UPnP::Close () + { + freeUPNPDevlist (m_Devlist); + m_Devlist = 0; + FreeUPNPUrls (&m_upnpUrls); + } std::string UPnP::GetProto (std::shared_ptr address) { switch (address->transportStyle) - { - case i2p::data::RouterInfo::eTransportNTCP: - return "TCP"; - break; - case i2p::data::RouterInfo::eTransportSSU: - default: - return "UDP"; - } + { + case i2p::data::RouterInfo::eTransportNTCP: + return "TCP"; + break; + case i2p::data::RouterInfo::eTransportSSU: + default: + return "UDP"; + } } } }