mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-07-25 23:45:49 -04:00
Fix compilation with libupnp-1.8.x
This commit is contained in:
parent
3c5ac8b6e6
commit
650c5f1fa8
14 changed files with 255 additions and 217 deletions
1741
libretroshare/src/rs_upnp/UPnPBase.cpp
Normal file
1741
libretroshare/src/rs_upnp/UPnPBase.cpp
Normal file
File diff suppressed because it is too large
Load diff
619
libretroshare/src/rs_upnp/UPnPBase.h
Normal file
619
libretroshare/src/rs_upnp/UPnPBase.h
Normal file
|
@ -0,0 +1,619 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/upnp: UPnPBase.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright (c) 2004-2009 Marcelo Roberto Jimenez ( phoenix@amule.org ) *
|
||||
* Copyright (c) 2006-2009 aMule Team ( admin@amule.org / http://www.amule.org)*
|
||||
* Copyright (c) 2009-2010 Retroshare Team *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
|
||||
#include <upnp/upnp.h>
|
||||
#include <upnp/upnptools.h>
|
||||
#include <upnp/upnpdebug.h>
|
||||
|
||||
#include "util/rsthreads.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <util/rsthreads.h>
|
||||
|
||||
#ifdef UPNP_C
|
||||
std::string stdEmptyString;
|
||||
#else // UPNP_C
|
||||
extern std::string stdEmptyString;
|
||||
#endif // UPNP_C
|
||||
|
||||
|
||||
/**
|
||||
* Case insensitive std::string comparison
|
||||
*/
|
||||
bool stdStringIsEqualCI(
|
||||
const std::string &s1,
|
||||
const std::string &s2);
|
||||
|
||||
|
||||
class CUPnPPortMapping
|
||||
{
|
||||
private:
|
||||
std::string m_ex_port;
|
||||
std::string m_in_port;
|
||||
std::string m_protocol;
|
||||
std::string m_enabled;
|
||||
std::string m_description;
|
||||
std::string m_key;
|
||||
|
||||
public:
|
||||
CUPnPPortMapping(
|
||||
int ex_port = 0,
|
||||
int in_port = 0,
|
||||
const std::string &protocol = stdEmptyString,
|
||||
bool enabled = false,
|
||||
const std::string &description = stdEmptyString);
|
||||
~CUPnPPortMapping() {}
|
||||
|
||||
const std::string &getExPort() const
|
||||
{ return m_ex_port; }
|
||||
const std::string &getInPort() const
|
||||
{ return m_in_port; }
|
||||
const std::string &getProtocol() const
|
||||
{ return m_protocol; }
|
||||
const std::string &getEnabled() const
|
||||
{ return m_enabled; }
|
||||
const std::string &getDescription() const
|
||||
{ return m_description; }
|
||||
const std::string &getKey() const
|
||||
{ return m_key; }
|
||||
};
|
||||
|
||||
|
||||
class CUPnPControlPoint;
|
||||
|
||||
|
||||
class CUPnPLib
|
||||
{
|
||||
public:
|
||||
static const std::string &UPNP_ROOT_DEVICE;
|
||||
static const std::string &UPNP_DEVICE_IGW;
|
||||
static const std::string &UPNP_DEVICE_WAN;
|
||||
static const std::string &UPNP_DEVICE_WAN_CONNECTION;
|
||||
static const std::string &UPNP_DEVICE_LAN;
|
||||
static const std::string &UPNP_SERVICE_LAYER3_FORWARDING;
|
||||
static const std::string &UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG;
|
||||
static const std::string &UPNP_SERVICE_WAN_IP_CONNECTION;
|
||||
static const std::string &UPNP_SERVICE_WAN_PPP_CONNECTION;
|
||||
CUPnPControlPoint &m_ctrlPoint;
|
||||
|
||||
public:
|
||||
explicit CUPnPLib(CUPnPControlPoint &ctrlPoint);
|
||||
~CUPnPLib() {}
|
||||
|
||||
// Convenience function so we don't have to write explicit calls
|
||||
// to char2unicode every time
|
||||
std::string GetUPnPErrorMessage(int code) const;
|
||||
|
||||
// Convenience function to avoid repetitive processing of error
|
||||
// messages
|
||||
std::string processUPnPErrorMessage(const std::string &messsage,
|
||||
int code,
|
||||
const DOMString errorString,
|
||||
const IXML_Document* doc) const;
|
||||
|
||||
// Processing response to actions
|
||||
void ProcessActionResponse(
|
||||
const IXML_Document* RespDoc,
|
||||
const std::string& actionName ) const;
|
||||
|
||||
// IXML_Element
|
||||
IXML_Element* Element_GetRootElement(const IXML_Document* doc) const;
|
||||
IXML_Element *Element_GetFirstChild(
|
||||
IXML_Element *parent) const;
|
||||
IXML_Element *Element_GetNextSibling(
|
||||
IXML_Element *child) const;
|
||||
const DOMString Element_GetTag(
|
||||
IXML_Element *element) const;
|
||||
const std::string Element_GetTextValue(
|
||||
IXML_Element *element) const;
|
||||
const std::string Element_GetChildValueByTag(
|
||||
IXML_Element *element,
|
||||
const DOMString tag) const;
|
||||
IXML_Element *Element_GetFirstChildByTag(
|
||||
IXML_Element *element,
|
||||
const DOMString tag) const;
|
||||
IXML_Element *Element_GetNextSiblingByTag(
|
||||
IXML_Element *element,
|
||||
const DOMString tag) const;
|
||||
const std::string Element_GetAttributeByTag(
|
||||
IXML_Element *element,
|
||||
const DOMString tag) const;
|
||||
};
|
||||
|
||||
|
||||
class CUPnPControlPoint;
|
||||
|
||||
/*
|
||||
* Even though we can retrieve the upnpLib handler from the upnpControlPoint,
|
||||
* we must pass it separetly at this point, because the class CUPnPControlPoint
|
||||
* must be declared after.
|
||||
*
|
||||
* CUPnPLib can only be removed from the constructor once we agree to link to
|
||||
* UPnPLib explicitly, making this dlopen() stuff unnecessary.
|
||||
*/
|
||||
template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
|
||||
class CXML_List : public std::map<const std::string, T *>
|
||||
{
|
||||
public:
|
||||
CXML_List(
|
||||
const CUPnPControlPoint &upnpControlPoint,
|
||||
CUPnPLib &upnpLib,
|
||||
IXML_Element *parent,
|
||||
const std::string &url);
|
||||
~CXML_List();
|
||||
};
|
||||
|
||||
|
||||
template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
|
||||
CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::CXML_List(
|
||||
const CUPnPControlPoint &upnpControlPoint,
|
||||
CUPnPLib &upnpLib,
|
||||
IXML_Element *parent,
|
||||
const std::string &url)
|
||||
{
|
||||
IXML_Element *elementList =
|
||||
upnpLib.Element_GetFirstChildByTag(parent, XML_LIST_NAME);
|
||||
unsigned int i = 0;
|
||||
for ( IXML_Element *element = upnpLib.Element_GetFirstChildByTag(elementList, XML_ELEMENT_NAME);
|
||||
element;
|
||||
element = upnpLib.Element_GetNextSiblingByTag(element, XML_ELEMENT_NAME)) {
|
||||
// Add a new element to the element list
|
||||
T *upnpElement = new T(upnpControlPoint, upnpLib, element, url);
|
||||
(*this)[upnpElement->GetKey()] = upnpElement;
|
||||
++i;
|
||||
}
|
||||
std::cerr << "\n " << XML_LIST_NAME << ": " <<
|
||||
i << " " << XML_ELEMENT_NAME << "s.";
|
||||
}
|
||||
|
||||
|
||||
template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
|
||||
CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::~CXML_List()
|
||||
{
|
||||
typename CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::iterator it;
|
||||
for(it = this->begin(); it != this->end(); ++it) {
|
||||
delete (*it).second;
|
||||
}
|
||||
}
|
||||
|
||||
extern const char s_argument[];
|
||||
extern const char s_argumentList[];
|
||||
extern const char s_action[];
|
||||
extern const char s_actionList[];
|
||||
extern const char s_allowedValue[];
|
||||
extern const char s_allowedValueList[];
|
||||
extern const char s_stateVariable[];
|
||||
extern const char s_serviceStateTable[];
|
||||
extern const char s_service[];
|
||||
extern const char s_serviceList[];
|
||||
extern const char s_device[];
|
||||
extern const char s_deviceList[];
|
||||
|
||||
#ifdef UPNP_C
|
||||
const char s_argument[] = "argument";
|
||||
const char s_argumentList[] = "argumentList";
|
||||
const char s_action[] = "action";
|
||||
const char s_actionList[] = "actionList";
|
||||
const char s_allowedValue[] = "allowedValue";
|
||||
const char s_allowedValueList[] = "allowedValueList";
|
||||
const char s_stateVariable[] = "stateVariable";
|
||||
const char s_serviceStateTable[] = "serviceStateTable";
|
||||
const char s_service[] = "service";
|
||||
const char s_serviceList[] = "serviceList";
|
||||
const char s_device[] = "device";
|
||||
const char s_deviceList[] = "deviceList";
|
||||
#endif // UPNP_C
|
||||
|
||||
|
||||
class CUPnPArgument;
|
||||
typedef CXML_List<CUPnPArgument, s_argument, s_argumentList> ArgumentList;
|
||||
class CUPnPAction;
|
||||
typedef CXML_List<CUPnPAction, s_action, s_actionList> ActionList;
|
||||
class CUPnPStateVariable;
|
||||
typedef CXML_List<CUPnPStateVariable, s_stateVariable, s_serviceStateTable> ServiceStateTable;
|
||||
class CUPnPAllowedValue;
|
||||
typedef CXML_List<CUPnPAllowedValue, s_allowedValue, s_allowedValueList> AllowedValueList;
|
||||
class CUPnPService;
|
||||
typedef CXML_List<CUPnPService, s_service, s_serviceList> ServiceList;
|
||||
class CUPnPDevice;
|
||||
typedef CXML_List<CUPnPDevice, s_device, s_deviceList> DeviceList;
|
||||
|
||||
|
||||
class CUPnPError
|
||||
{
|
||||
private:
|
||||
IXML_Element *m_root;
|
||||
const std::string m_ErrorCode;
|
||||
const std::string m_ErrorDescription;
|
||||
public:
|
||||
CUPnPError(
|
||||
const CUPnPLib &upnpLib,
|
||||
IXML_Document *errorDoc);
|
||||
~CUPnPError() {}
|
||||
const std::string &getErrorCode() const
|
||||
{ return m_ErrorCode; }
|
||||
const std::string &getErrorDescription() const
|
||||
{ return m_ErrorDescription; }
|
||||
};
|
||||
|
||||
|
||||
class CUPnPArgument
|
||||
{
|
||||
private:
|
||||
const CUPnPControlPoint &m_UPnPControlPoint;
|
||||
const std::string m_name;
|
||||
const std::string m_direction;
|
||||
bool m_retval;
|
||||
const std::string m_relatedStateVariable;
|
||||
|
||||
public:
|
||||
CUPnPArgument(
|
||||
const CUPnPControlPoint &upnpControlPoint,
|
||||
CUPnPLib &upnpLib,
|
||||
IXML_Element *argument,
|
||||
const std::string &SCPDURL);
|
||||
~CUPnPArgument() {}
|
||||
const std::string &GetName() const
|
||||
{ return m_name; }
|
||||
const std::string &GetDirection() const
|
||||
{ return m_direction; }
|
||||
bool GetRetVal() const
|
||||
{ return m_retval; }
|
||||
const std::string &GetRelatedStateVariable() const
|
||||
{ return m_relatedStateVariable; }
|
||||
const std::string &GetKey() const
|
||||
{ return m_name; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CUPnPAction
|
||||
{
|
||||
private:
|
||||
const CUPnPControlPoint &m_UPnPControlPoint;
|
||||
ArgumentList m_ArgumentList;
|
||||
const std::string m_name;
|
||||
|
||||
public:
|
||||
CUPnPAction(
|
||||
const CUPnPControlPoint &upnpControlPoint,
|
||||
CUPnPLib &upnpLib,
|
||||
IXML_Element *action,
|
||||
const std::string &SCPDURL);
|
||||
~CUPnPAction() {}
|
||||
const std::string &GetName() const
|
||||
{ return m_name; }
|
||||
const std::string &GetKey() const
|
||||
{ return m_name; }
|
||||
const ArgumentList &GetArgumentList() const
|
||||
{ return m_ArgumentList; }
|
||||
};
|
||||
|
||||
|
||||
class CUPnPAllowedValue
|
||||
{
|
||||
private:
|
||||
const CUPnPControlPoint &m_UPnPControlPoint;
|
||||
const std::string m_allowedValue;
|
||||
|
||||
public:
|
||||
CUPnPAllowedValue(
|
||||
const CUPnPControlPoint &upnpControlPoint,
|
||||
CUPnPLib &upnpLib,
|
||||
IXML_Element *allowedValue,
|
||||
const std::string &SCPDURL);
|
||||
~CUPnPAllowedValue() {}
|
||||
const std::string &GetAllowedValue() const
|
||||
{ return m_allowedValue; }
|
||||
const std::string &GetKey() const
|
||||
{ return m_allowedValue; }
|
||||
};
|
||||
|
||||
|
||||
class CUPnPStateVariable
|
||||
{
|
||||
private:
|
||||
const CUPnPControlPoint &m_UPnPControlPoint;
|
||||
AllowedValueList m_AllowedValueList;
|
||||
const std::string m_name;
|
||||
const std::string m_dataType;
|
||||
const std::string m_defaultValue;
|
||||
const std::string m_sendEvents;
|
||||
|
||||
public:
|
||||
CUPnPStateVariable(
|
||||
const CUPnPControlPoint &upnpControlPoint,
|
||||
CUPnPLib &upnpLib,
|
||||
IXML_Element *stateVariable,
|
||||
const std::string &URLBase);
|
||||
~CUPnPStateVariable() {}
|
||||
const std::string &GetNname() const
|
||||
{ return m_name; }
|
||||
const std::string &GetDataType() const
|
||||
{ return m_dataType; }
|
||||
const std::string &GetDefaultValue() const
|
||||
{ return m_defaultValue; }
|
||||
const std::string &GetKey() const
|
||||
{ return m_name; }
|
||||
const AllowedValueList &GetAllowedValueList() const
|
||||
{ return m_AllowedValueList; }
|
||||
};
|
||||
|
||||
|
||||
class CUPnPSCPD
|
||||
{
|
||||
private:
|
||||
const CUPnPControlPoint &m_UPnPControlPoint;
|
||||
ActionList m_ActionList;
|
||||
ServiceStateTable m_ServiceStateTable;
|
||||
const std::string m_SCPDURL;
|
||||
|
||||
public:
|
||||
CUPnPSCPD(
|
||||
const CUPnPControlPoint &upnpControlPoint,
|
||||
CUPnPLib &upnpLib,
|
||||
IXML_Element *scpd,
|
||||
const std::string &SCPDURL);
|
||||
~CUPnPSCPD() {}
|
||||
const ActionList &GetActionList() const
|
||||
{ return m_ActionList; }
|
||||
const ServiceStateTable &GetServiceStateTable() const
|
||||
{ return m_ServiceStateTable; }
|
||||
};
|
||||
|
||||
|
||||
class CUPnPArgumentValue
|
||||
{
|
||||
private:
|
||||
std::string m_argument;
|
||||
std::string m_value;
|
||||
|
||||
public:
|
||||
CUPnPArgumentValue();
|
||||
CUPnPArgumentValue(const std::string &argument, const std::string &value);
|
||||
~CUPnPArgumentValue() {}
|
||||
|
||||
const std::string &GetArgument() const { return m_argument; }
|
||||
const std::string &GetValue() const { return m_value; }
|
||||
const std::string &SetArgument(const std::string& argument) { return m_argument = argument; }
|
||||
const std::string &SetValue(const std::string &value) { return m_value = value; }
|
||||
};
|
||||
|
||||
|
||||
class CUPnPService
|
||||
{
|
||||
private:
|
||||
const CUPnPControlPoint &m_UPnPControlPoint;
|
||||
CUPnPLib &m_upnpLib;
|
||||
const std::string m_serviceType;
|
||||
const std::string m_serviceId;
|
||||
const std::string m_SCPDURL;
|
||||
const std::string m_controlURL;
|
||||
const std::string m_eventSubURL;
|
||||
std::string m_absSCPDURL;
|
||||
std::string m_absControlURL;
|
||||
std::string m_absEventSubURL;
|
||||
int m_timeout;
|
||||
Upnp_SID m_SID;
|
||||
std::auto_ptr<CUPnPSCPD> m_SCPD;
|
||||
|
||||
public:
|
||||
std::map<std::string, std::string> propertyMap;
|
||||
CUPnPService(
|
||||
const CUPnPControlPoint &upnpControlPoint,
|
||||
CUPnPLib &upnpLib,
|
||||
IXML_Element *service,
|
||||
const std::string &URLBase);
|
||||
~CUPnPService();
|
||||
|
||||
const std::string &GetServiceType() const
|
||||
{ return m_serviceType; }
|
||||
const std::string &GetServiceId() const
|
||||
{ return m_serviceId; }
|
||||
const std::string &GetSCPDURL() const
|
||||
{ return m_SCPDURL; }
|
||||
const std::string &GetAbsSCPDURL() const
|
||||
{ return m_absSCPDURL; }
|
||||
const std::string &GetControlURL() const
|
||||
{ return m_controlURL; }
|
||||
const std::string &GetEventSubURL() const
|
||||
{ return m_eventSubURL; }
|
||||
const std::string &GetAbsControlURL() const
|
||||
{ return m_absControlURL; }
|
||||
const std::string &GetAbsEventSubURL() const
|
||||
{ return m_absEventSubURL; }
|
||||
int GetTimeout() const
|
||||
{ return m_timeout; }
|
||||
void SetTimeout(int t)
|
||||
{ m_timeout = t; }
|
||||
int *GetTimeoutAddr()
|
||||
{ return &m_timeout; }
|
||||
char *GetSID()
|
||||
{ return m_SID; }
|
||||
void SetSID(const char *s)
|
||||
{ memcpy(m_SID, s, sizeof(Upnp_SID)); }
|
||||
const std::string &GetKey() const
|
||||
{ return m_serviceId; }
|
||||
bool IsSubscribed() const
|
||||
{ return m_SCPD.get() != NULL; }
|
||||
void SetSCPD(CUPnPSCPD *SCPD)
|
||||
{ m_SCPD.reset(SCPD); }
|
||||
|
||||
bool Execute(
|
||||
const std::string &ActionName,
|
||||
const std::vector<CUPnPArgumentValue> &ArgValue) const;
|
||||
const std::string GetStateVariable(
|
||||
const std::string &stateVariableName);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class CUPnPDevice
|
||||
{
|
||||
private:
|
||||
const CUPnPControlPoint &m_UPnPControlPoint;
|
||||
|
||||
// Please, lock these lists before use
|
||||
DeviceList m_DeviceList;
|
||||
ServiceList m_ServiceList;
|
||||
|
||||
const std::string m_deviceType;
|
||||
const std::string m_friendlyName;
|
||||
const std::string m_manufacturer;
|
||||
const std::string m_manufacturerURL;
|
||||
const std::string m_modelDescription;
|
||||
const std::string m_modelName;
|
||||
const std::string m_modelNumber;
|
||||
const std::string m_modelURL;
|
||||
const std::string m_serialNumber;
|
||||
const std::string m_UDN;
|
||||
const std::string m_UPC;
|
||||
std::string m_presentationURL;
|
||||
|
||||
public:
|
||||
CUPnPDevice(
|
||||
const CUPnPControlPoint &upnpControlPoint,
|
||||
CUPnPLib &upnpLib,
|
||||
IXML_Element *device,
|
||||
const std::string &URLBase);
|
||||
~CUPnPDevice() {}
|
||||
|
||||
const std::string &GetUDN() const
|
||||
{ return m_UDN; }
|
||||
const std::string &GetDeviceType() const
|
||||
{ return m_deviceType; }
|
||||
const std::string &GetFriendlyName() const
|
||||
{ return m_friendlyName; }
|
||||
const std::string &GetPresentationURL() const
|
||||
{ return m_presentationURL; }
|
||||
const std::string &GetKey() const
|
||||
{ return m_UDN; }
|
||||
};
|
||||
|
||||
|
||||
class CUPnPRootDevice : public CUPnPDevice
|
||||
{
|
||||
private:
|
||||
const CUPnPControlPoint &m_UPnPControlPoint;
|
||||
const std::string m_URLBase;
|
||||
const std::string m_location;
|
||||
int m_expires;
|
||||
|
||||
public:
|
||||
CUPnPRootDevice(
|
||||
const CUPnPControlPoint &upnpControlPoint,
|
||||
CUPnPLib &upnpLib,
|
||||
IXML_Element *rootDevice,
|
||||
const std::string &OriginalURLBase,
|
||||
const std::string &FixedURLBase,
|
||||
const char *location,
|
||||
int expires);
|
||||
~CUPnPRootDevice() {}
|
||||
|
||||
const std::string &GetURLBase() const
|
||||
{ return m_URLBase; }
|
||||
const std::string &GetLocation() const
|
||||
{ return m_location; }
|
||||
int GetExpires() const
|
||||
{ return m_expires; }
|
||||
void SetExpires(int expires)
|
||||
{ m_expires = expires; }
|
||||
};
|
||||
|
||||
|
||||
typedef std::map<const std::string, CUPnPRootDevice *> RootDeviceMap;
|
||||
typedef std::map<const std::string, CUPnPService *> ServiceMap;
|
||||
typedef std::map<const std::string, CUPnPPortMapping> PortMappingMap;
|
||||
|
||||
|
||||
class CUPnPControlPoint
|
||||
{
|
||||
private:
|
||||
// upnp stuff
|
||||
CUPnPLib m_upnpLib;
|
||||
UpnpClient_Handle m_UPnPClientHandle;
|
||||
RootDeviceMap m_RootDeviceMap;
|
||||
ServiceMap m_ServiceMap;
|
||||
PortMappingMap m_ActivePortMappingsMap;
|
||||
RsMutex m_RootDeviceListMutex;
|
||||
bool m_IGWDeviceDetected;
|
||||
RsMutex m_WaitForSearchTimeoutMutex;
|
||||
|
||||
public:
|
||||
CUPnPService *m_WanService;
|
||||
std::string m_getStateVariableLastResult;
|
||||
static CUPnPControlPoint *s_CtrlPoint;
|
||||
explicit CUPnPControlPoint(unsigned short udpPort);
|
||||
~CUPnPControlPoint();
|
||||
char* getInternalIpAddress();
|
||||
std::string getExternalAddress();
|
||||
void Subscribe(CUPnPService &service);
|
||||
void Unsubscribe(CUPnPService &service);
|
||||
bool AddPortMappings(
|
||||
std::vector<CUPnPPortMapping> &upnpPortMapping);
|
||||
bool DeletePortMappings(
|
||||
std::vector<CUPnPPortMapping> &upnpPortMapping);
|
||||
|
||||
UpnpClient_Handle GetUPnPClientHandle() const
|
||||
{ return m_UPnPClientHandle; }
|
||||
|
||||
bool GetIGWDeviceDetected() const
|
||||
{ return m_IGWDeviceDetected; }
|
||||
void SetIGWDeviceDetected(bool b)
|
||||
{ m_IGWDeviceDetected = b; }
|
||||
bool WanServiceDetected() const
|
||||
{ return !m_ServiceMap.empty(); }
|
||||
void SetWanService(CUPnPService *service)
|
||||
{ m_WanService = service; }
|
||||
|
||||
// Callback function
|
||||
static int Callback(
|
||||
Upnp_EventType EventType, const void* Event, void* Cookie );
|
||||
void OnEventReceived(const std::string &Sid,
|
||||
int EventKey,
|
||||
const IXML_Document* ChangedVariables);
|
||||
|
||||
private:
|
||||
void AddRootDevice(
|
||||
IXML_Element *rootDevice,
|
||||
const std::string &urlBase,
|
||||
const char *location,
|
||||
int expires);
|
||||
void RemoveRootDevice(
|
||||
const char *udn);
|
||||
void RefreshPortMappings();
|
||||
bool PrivateAddPortMapping(
|
||||
CUPnPPortMapping &upnpPortMapping);
|
||||
bool PrivateDeletePortMapping(
|
||||
CUPnPPortMapping &upnpPortMapping);
|
||||
bool PrivateGetExternalIpAdress();
|
||||
};
|
||||
|
||||
// File_checked_for_headers
|
82
libretroshare/src/rs_upnp/upnp18_retrocompat.h
Normal file
82
libretroshare/src/rs_upnp/upnp18_retrocompat.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*******************************************************************************
|
||||
* libupnp-1.8.x -> libupnp-1.6.x retrocompatibility header *
|
||||
* *
|
||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "upnp/upnp.h"
|
||||
|
||||
|
||||
#if UPNP_VERSION < 10800
|
||||
|
||||
using UpnpDiscovery = Upnp_Discovery;
|
||||
using UpnpEvent = Upnp_Event;
|
||||
using UpnpEventSubscribe = Upnp_Event_Subscribe;
|
||||
using UpnpActionComplete = Upnp_Action_Complete;
|
||||
using UpnpStateVarComplete = Upnp_State_Var_Complete;
|
||||
|
||||
#endif // UPNP_VERSION < 10800
|
||||
|
||||
#if UPNP_VERSION < 10624
|
||||
|
||||
static inline int UpnpDiscovery_get_Expires(const Upnp_Discovery* disc) noexcept
|
||||
{ return disc->Expires; }
|
||||
|
||||
static inline const char* UpnpDiscovery_get_DeviceID_cstr(
|
||||
const Upnp_Discovery* disc ) noexcept
|
||||
{ return disc->DeviceId; }
|
||||
|
||||
static inline const char* UpnpDiscovery_get_DeviceType_cstr(
|
||||
const Upnp_Discovery* disc ) noexcept
|
||||
{ return disc->DeviceType; }
|
||||
|
||||
static inline const char* UpnpDiscovery_get_Location_cstr(
|
||||
const Upnp_Discovery* disc ) noexcept
|
||||
{ return disc->Location; }
|
||||
|
||||
static inline const char* UpnpEvent_get_SID_cstr(const UpnpEvent* ev) noexcept
|
||||
{ return ev->Sid; }
|
||||
|
||||
static inline int UpnpEvent_get_EventKey(const UpnpEvent* ev) noexcept
|
||||
{ return ev->EventKey; }
|
||||
|
||||
static inline const IXML_Document* UpnpEvent_get_ChangedVariables(
|
||||
const UpnpEvent* ev) noexcept { return ev->ChangedVariables; }
|
||||
|
||||
static inline int UpnpEventSubscribe_get_ErrCode(const UpnpEventSubscribe* evs)
|
||||
noexcept { return evs->ErrCode; }
|
||||
|
||||
static inline const char* UpnpEventSubscribe_get_PublisherUrl_cstr(
|
||||
const UpnpEventSubscribe* evs ) noexcept { return evs->PublisherUrl; }
|
||||
|
||||
static inline int UpnpActionComplete_get_ErrCode(const UpnpActionComplete* evc)
|
||||
noexcept { return evc->ErrCode; }
|
||||
|
||||
static inline const IXML_Document* UpnpActionComplete_get_ActionResult(
|
||||
const UpnpActionComplete* evc ) noexcept { return evc->ActionResult; }
|
||||
|
||||
static inline int UpnpStateVarComplete_get_ErrCode(
|
||||
const UpnpStateVarComplete* esvc) noexcept { return esvc->ErrCode; }
|
||||
|
||||
static inline const char* UpnpStateVarComplete_get_StateVarName_cstr(
|
||||
const UpnpStateVarComplete* esvc) noexcept { return esvc->StateVarName; }
|
||||
|
||||
static inline const char* UpnpStateVarComplete_get_CurrentVal_cstr(
|
||||
const UpnpStateVarComplete* esvc) noexcept { return esvc->CurrentVal; }
|
||||
|
||||
#endif // UPNP_VERSION < 10624
|
466
libretroshare/src/rs_upnp/upnphandler_linux.cc
Normal file
466
libretroshare/src/rs_upnp/upnphandler_linux.cc
Normal file
|
@ -0,0 +1,466 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/upnp: upnphandler_linux.cc *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2007-2018 Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
/* This stuff is actually C */
|
||||
|
||||
#include "rs_upnp/upnphandler_linux.h"
|
||||
|
||||
#include "util/rsnet.h"
|
||||
|
||||
bool upnphandler::initUPnPState()
|
||||
{
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::initUPnPState" << std::endl;
|
||||
#endif
|
||||
cUPnPControlPoint = new CUPnPControlPoint(2000);
|
||||
|
||||
bool IGWDetected = cUPnPControlPoint->GetIGWDeviceDetected();
|
||||
|
||||
if (IGWDetected) {
|
||||
/* MODIFY STATE */
|
||||
dataMtx.lock(); /* LOCK MUTEX */
|
||||
upnpState = RS_UPNP_S_READY;
|
||||
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::initUPnPState cUPnPControlPoint internal ip adress : ";
|
||||
std::cerr << cUPnPControlPoint->getInternalIpAddress() << std::endl;
|
||||
#endif
|
||||
|
||||
//const char ipaddr = cUPnPControlPoint->getInternalIpAddress().c_str();
|
||||
inet_aton(cUPnPControlPoint->getInternalIpAddress(), &(upnp_iaddr.sin_addr));
|
||||
upnp_iaddr.sin_port = htons(iport);
|
||||
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::initUPnPState READY" << std::endl;
|
||||
#endif
|
||||
dataMtx.unlock(); /* UNLOCK MUTEX */
|
||||
|
||||
} else {
|
||||
upnpState = RS_UPNP_S_UNAVAILABLE;
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::initUPnPState UNAVAILABLE" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class upnpThreadData
|
||||
{
|
||||
public:
|
||||
upnphandler *handler;
|
||||
bool start;
|
||||
bool stop;
|
||||
};
|
||||
|
||||
/* Thread routines */
|
||||
extern "C" void* doSetupUPnP(void* p)
|
||||
{
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "doSetupUPnP Creating upnp thread." << std::endl;
|
||||
#endif
|
||||
upnpThreadData *data = (upnpThreadData *) p;
|
||||
if ((!data) || (!data->handler))
|
||||
{
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
/* publish it! */
|
||||
if (data -> stop)
|
||||
{
|
||||
data->handler->shutdown_upnp();
|
||||
}
|
||||
|
||||
if (data -> start)
|
||||
{
|
||||
data->handler->initUPnPState();
|
||||
data->handler->start_upnp();
|
||||
}
|
||||
|
||||
delete data;
|
||||
pthread_exit(NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool upnphandler::background_setup_upnp(bool start, bool stop)
|
||||
{
|
||||
pthread_t tid;
|
||||
|
||||
/* launch thread */
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "background_setup_upnp Creating upnp thread." << std::endl;
|
||||
#endif
|
||||
upnpThreadData *data = new upnpThreadData();
|
||||
data->handler = this;
|
||||
data->start = start;
|
||||
data->stop = stop;
|
||||
|
||||
if(! pthread_create(&tid, 0, &doSetupUPnP, (void *) data))
|
||||
{
|
||||
pthread_detach(tid); /* so memory is reclaimed in linux */
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete data ;
|
||||
std::cerr << "(EE) Could not start background upnp thread!" << std::endl;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
bool upnphandler::start_upnp()
|
||||
{
|
||||
if (!(upnpState >= RS_UPNP_S_READY))
|
||||
{
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::start_upnp() Not Ready" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_in localAddr;
|
||||
{
|
||||
RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */
|
||||
|
||||
/* if we're to load -> load */
|
||||
/* select external ports */
|
||||
eport_curr = eport;
|
||||
if (!eport_curr)
|
||||
{
|
||||
/* use local port if eport is zero */
|
||||
eport_curr = iport;
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::start_upnp() Using LocalPort for extPort." << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!eport_curr)
|
||||
{
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::start_upnp() Invalid eport ... " << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/* our port */
|
||||
char in_addr[256];
|
||||
char in_port1[256];
|
||||
|
||||
upnp_iaddr.sin_port = htons(iport);
|
||||
localAddr = upnp_iaddr;
|
||||
uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr);
|
||||
snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port));
|
||||
snprintf(in_addr, 256, "%d.%d.%d.%d",
|
||||
((linaddr >> 24) & 0xff),
|
||||
((linaddr >> 16) & 0xff),
|
||||
((linaddr >> 8) & 0xff),
|
||||
((linaddr >> 0) & 0xff));
|
||||
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "Attempting Redirection: InAddr: " << in_addr;
|
||||
std::cerr << " InPort: " << in_port1;
|
||||
std::cerr << " ePort: " << eport_curr;
|
||||
std::cerr << " eProt: " << "TCP and UDP";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
//first of all, build the mappings
|
||||
std::vector<CUPnPPortMapping> upnpPortMapping1;
|
||||
CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "TCP", true, "tcp retroshare redirection");
|
||||
upnpPortMapping1.push_back(cUPnPPortMapping1);
|
||||
std::vector<CUPnPPortMapping> upnpPortMapping2;
|
||||
CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "UDP", true, "udp retroshare redirection");
|
||||
upnpPortMapping2.push_back(cUPnPPortMapping2);
|
||||
|
||||
//attempt to remove formal port redirection rules
|
||||
cUPnPControlPoint->DeletePortMappings(upnpPortMapping1);
|
||||
cUPnPControlPoint->DeletePortMappings(upnpPortMapping2);
|
||||
|
||||
//add new rules
|
||||
bool res = cUPnPControlPoint->AddPortMappings(upnpPortMapping1);
|
||||
bool res2 = cUPnPControlPoint->AddPortMappings(upnpPortMapping2);
|
||||
|
||||
struct sockaddr_storage extAddr;
|
||||
bool extAddrResult = getExternalAddress(extAddr);
|
||||
|
||||
{
|
||||
RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */
|
||||
|
||||
if (extAddrResult && (res || res2)) {
|
||||
upnpState = RS_UPNP_S_ACTIVE;
|
||||
} else {
|
||||
upnpState = RS_UPNP_S_TCP_AND_FAILED;
|
||||
}
|
||||
|
||||
toStart = false;
|
||||
}
|
||||
|
||||
return (upnpState == RS_UPNP_S_ACTIVE);
|
||||
|
||||
}
|
||||
|
||||
bool upnphandler::shutdown_upnp()
|
||||
{
|
||||
RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */
|
||||
|
||||
/* always attempt this (unless no port number) */
|
||||
if (eport_curr > 0 && eport > 0 && (upnpState >= RS_UPNP_S_ACTIVE))
|
||||
{
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr;
|
||||
std::cerr << " Prot: TCP";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
std::vector<CUPnPPortMapping> upnpPortMapping1;
|
||||
CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, 0, "TCP", true, "tcp redirection");
|
||||
upnpPortMapping1.push_back(cUPnPPortMapping1);
|
||||
cUPnPControlPoint->DeletePortMappings(upnpPortMapping1);
|
||||
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr;
|
||||
std::cerr << " Prot: UDP";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
std::vector<CUPnPPortMapping> upnpPortMapping2;
|
||||
CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, 0, "UDP", true, "udp redirection");
|
||||
upnpPortMapping2.push_back(cUPnPPortMapping2);
|
||||
cUPnPControlPoint->DeletePortMappings(upnpPortMapping2);
|
||||
|
||||
//destroy the upnp object
|
||||
cUPnPControlPoint->~CUPnPControlPoint();
|
||||
cUPnPControlPoint=NULL ;
|
||||
} else {
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::shutdown_upnp() : avoid upnp connection for shutdonws because probably a net flag went down." << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
//stopping os ok, set starting to true for next net reset
|
||||
toStop = false;
|
||||
toStart = true;
|
||||
upnpState = RS_UPNP_S_UNINITIALISED;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/************************ External Interface *****************************
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
upnphandler::upnphandler()
|
||||
:
|
||||
upnpState(RS_UPNP_S_UNINITIALISED), dataMtx("upupState"),
|
||||
cUPnPControlPoint(NULL),
|
||||
toEnable(false), toStart(false), toStop(false),
|
||||
iport(0),eport(0), eport_curr(0)
|
||||
{
|
||||
}
|
||||
|
||||
upnphandler::~upnphandler()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* RsIface */
|
||||
void upnphandler::enable(bool active)
|
||||
{
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::enable called with argument active : " << active << std::endl;
|
||||
std::cerr << "toEnable : " << toEnable << std::endl;
|
||||
std::cerr << "toStart : " << toStart << std::endl;
|
||||
#endif
|
||||
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
if (active != toEnable)
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
toStart = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
toStop = true;
|
||||
}
|
||||
}
|
||||
toEnable = active;
|
||||
|
||||
bool start = toStart;
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
|
||||
if (start)
|
||||
{
|
||||
/* make background thread to startup UPnP */
|
||||
background_setup_upnp(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void upnphandler::shutdown()
|
||||
{
|
||||
/* blocking call to shutdown upnp */
|
||||
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::shutdown() called." << std::endl;
|
||||
#endif
|
||||
shutdown_upnp();
|
||||
}
|
||||
|
||||
|
||||
void upnphandler::restart()
|
||||
{
|
||||
/* non-blocking call to shutdown upnp, and startup again. */
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << "upnphandler::restart() called." << std::endl;
|
||||
#endif
|
||||
background_setup_upnp(true, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool upnphandler::getEnabled()
|
||||
{
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
|
||||
bool on = toEnable;
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
|
||||
return on;
|
||||
}
|
||||
|
||||
bool upnphandler::getActive()
|
||||
{
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr <<"upnphandler::getActive() result : " << (upnpState == RS_UPNP_S_ACTIVE) << std::endl;
|
||||
#endif
|
||||
|
||||
bool on = (upnpState == RS_UPNP_S_ACTIVE);
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
|
||||
return on;
|
||||
}
|
||||
|
||||
/* the address that the listening port is on */
|
||||
void upnphandler::setInternalPort(unsigned short iport_in)
|
||||
{
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
if (iport != iport_in)
|
||||
{
|
||||
iport = iport_in;
|
||||
if ((toEnable) &&
|
||||
(upnpState == RS_UPNP_S_ACTIVE))
|
||||
{
|
||||
toStop = true;
|
||||
toStart = true;
|
||||
}
|
||||
}
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
}
|
||||
|
||||
void upnphandler::setExternalPort(unsigned short eport_in)
|
||||
{
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
/* flag both shutdown/start -> for restart */
|
||||
if (eport != eport_in)
|
||||
{
|
||||
eport = eport_in;
|
||||
if ((toEnable) &&
|
||||
(upnpState == RS_UPNP_S_ACTIVE))
|
||||
{
|
||||
toStop = true;
|
||||
toStart = true;
|
||||
}
|
||||
}
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
}
|
||||
|
||||
/* as determined by uPnP */
|
||||
bool upnphandler::getInternalAddress(struct sockaddr_storage &addr)
|
||||
{
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
|
||||
bool valid = (upnpState >= RS_UPNP_S_ACTIVE);
|
||||
|
||||
// copy to universal addr.
|
||||
sockaddr_storage_clear(addr);
|
||||
sockaddr_storage_setipv4(addr, &upnp_iaddr);
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool upnphandler::getExternalAddress(struct sockaddr_storage &addr)
|
||||
{
|
||||
std::string externalAdress = cUPnPControlPoint->getExternalAddress();
|
||||
|
||||
if(!externalAdress.empty() && externalAdress != "")
|
||||
{
|
||||
const char* externalIPAddress = externalAdress.c_str();
|
||||
|
||||
#ifdef UPNP_DEBUG
|
||||
std::cerr << " upnphandler::getExternalAddress() : " << externalIPAddress;
|
||||
std::cerr << ":" << eport_curr;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
sockaddr_clear(&upnp_eaddr);
|
||||
inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr));
|
||||
upnp_eaddr.sin_family = AF_INET;
|
||||
upnp_eaddr.sin_port = htons(eport_curr);
|
||||
|
||||
// copy to universal addr.
|
||||
sockaddr_storage_clear(addr);
|
||||
sockaddr_storage_setipv4(addr, &upnp_eaddr);
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
103
libretroshare/src/rs_upnp/upnphandler_linux.h
Normal file
103
libretroshare/src/rs_upnp/upnphandler_linux.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/upnp: upnphandler_linux.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2007-2018 Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef _RS_UPNP_IFACE_H
|
||||
#define _RS_UPNP_IFACE_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* platform independent networking... */
|
||||
#include "pqi/pqinetwork.h"
|
||||
#include "pqi/pqiassist.h"
|
||||
|
||||
#include "util/rsthreads.h"
|
||||
|
||||
#include <upnp/upnp.h>
|
||||
#include "rs_upnp/UPnPBase.h"
|
||||
|
||||
#define RS_UPNP_S_UNINITIALISED 0
|
||||
#define RS_UPNP_S_UNAVAILABLE 1
|
||||
#define RS_UPNP_S_READY 2
|
||||
#define RS_UPNP_S_TCP_AND_FAILED 3
|
||||
//#define RS_UPNP_S_UDP_FAILED 4
|
||||
#define RS_UPNP_S_ACTIVE 5
|
||||
|
||||
class upnphandler: public pqiNetAssistFirewall
|
||||
{
|
||||
public:
|
||||
|
||||
upnphandler();
|
||||
virtual ~upnphandler();
|
||||
|
||||
/* External Interface (pqiNetAssistFirewall) */
|
||||
virtual void enable(bool active);
|
||||
virtual void shutdown();
|
||||
virtual void restart();
|
||||
|
||||
virtual bool getEnabled();
|
||||
virtual bool getActive();
|
||||
|
||||
virtual void setInternalPort(unsigned short iport_in);
|
||||
virtual void setExternalPort(unsigned short eport_in);
|
||||
virtual bool getInternalAddress(struct sockaddr_storage &addr);
|
||||
virtual bool getExternalAddress(struct sockaddr_storage &addr);
|
||||
|
||||
/* TO IMPLEMENT: New Port Forward interface to support as many ports as necessary */
|
||||
virtual bool requestPortForward(const PortForwardParams & /* params */) { return false; }
|
||||
virtual bool statusPortForward(const uint32_t /* fwdId */, PortForwardParams & /*params*/) { return false; }
|
||||
|
||||
/* Public functions - for background thread operation,
|
||||
* but effectively private from rest of RS, as in derived class
|
||||
*/
|
||||
unsigned int upnpState;
|
||||
|
||||
bool start_upnp();
|
||||
bool shutdown_upnp();
|
||||
|
||||
bool initUPnPState();
|
||||
|
||||
/* Mutex for data below */
|
||||
RsMutex dataMtx;
|
||||
|
||||
private:
|
||||
|
||||
CUPnPControlPoint *cUPnPControlPoint;
|
||||
|
||||
bool background_setup_upnp(bool, bool);
|
||||
|
||||
|
||||
bool toEnable; /* overall on/off switch */
|
||||
bool toStart; /* if set start forwarding */
|
||||
bool toStop; /* if set stop forwarding */
|
||||
|
||||
unsigned short iport;
|
||||
unsigned short eport; /* config */
|
||||
unsigned short eport_curr; /* current forwarded */
|
||||
|
||||
/* info from upnp */
|
||||
struct sockaddr_in upnp_iaddr;
|
||||
struct sockaddr_in upnp_eaddr;
|
||||
};
|
||||
|
||||
/* info from upnp */
|
||||
int CtrlPointCallbackEventHandler(Upnp_EventType ,void* , void*);
|
||||
|
||||
#endif /* _RS_UPNP_IFACE_H */
|
683
libretroshare/src/rs_upnp/upnphandler_miniupnp.cc
Normal file
683
libretroshare/src/rs_upnp/upnphandler_miniupnp.cc
Normal file
|
@ -0,0 +1,683 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/upnp: upnphandler_miniupnp.cc *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2007-2018 Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
// Windows / Mac version.
|
||||
/* This stuff is actually C */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
/* This stuff is actually C */
|
||||
|
||||
#include "upnp/upnphandler_miniupnp.h"
|
||||
#include "upnp/upnputil.h"
|
||||
|
||||
class uPnPConfigData
|
||||
{
|
||||
public:
|
||||
struct UPNPDev * devlist;
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
char lanaddr[16]; /* my ip address on the LAN */
|
||||
};
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "util/rsnet.h"
|
||||
|
||||
bool upnphandler::initUPnPState()
|
||||
{
|
||||
/* allocate memory */
|
||||
uPnPConfigData *upcd = new uPnPConfigData;
|
||||
#if MINIUPNPC_API_VERSION >= 14 //1.9 2015/07/23
|
||||
/* $Id: miniupnpc.h,v 1.44 2015/07/23 20:40:10 nanard Exp $ */
|
||||
//upnpDiscover(int delay, const char * multicastif,
|
||||
// const char * minissdpdsock, int sameport,
|
||||
// int ipv6, unsigned char ttl,
|
||||
// int * error);
|
||||
unsigned char ttl = 2; /* defaulting to 2 */
|
||||
upcd->devlist = upnpDiscover(2000, NULL,
|
||||
NULL, 0,
|
||||
0, ttl,
|
||||
NULL);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= 8 //1.5 2011/04/18
|
||||
/* $Id: miniupnpc.h,v 1.41 2015/05/22 10:23:48 nanard Exp $ */
|
||||
/* $Id: miniupnpc.h,v 1.23 2011/04/11 08:21:46 nanard Exp $ */
|
||||
//upnpDiscover(int delay, const char * multicastif,
|
||||
// const char * minissdpdsock, int sameport,
|
||||
// int ipv6,
|
||||
// int * error);
|
||||
upcd->devlist = upnpDiscover(2000, NULL,
|
||||
NULL, 0,
|
||||
0,
|
||||
NULL);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= 6//1.5 2011/03/14
|
||||
/* $Id: miniupnpc.h,v 1.21 2011/03/14 13:37:12 nanard Exp $ */
|
||||
//upnpDiscover(int delay, const char * multicastif,
|
||||
// const char * minissdpdsock, int sameport,
|
||||
// int * error);
|
||||
upcd->devlist = upnpDiscover(2000, NULL,
|
||||
NULL, 0,
|
||||
NULL);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -4//1.1 2008/09/25
|
||||
/* $Id: miniupnpc.h,v 1.20 2011/02/07 16:46:05 nanard Exp $ */
|
||||
/* $Id: miniupnpc.h,v 1.18 2008/09/25 18:02:50 nanard Exp $ */
|
||||
//upnpDiscover(int delay, const char * multicastif,
|
||||
// const char * minissdpdsock, int sameport);
|
||||
upcd->devlist = upnpDiscover(2000, NULL,
|
||||
NULL, 0);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19
|
||||
/* $Id: miniupnpc.h,v 1.17 2007/12/19 14:58:54 nanard Exp $ */
|
||||
//upnpDiscover(int delay, const char * multicastif,
|
||||
// const char * minissdpdsock);
|
||||
upcd->devlist = upnpDiscover(2000, NULL,
|
||||
NULL);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -6//1.0 2007/10/16
|
||||
/* $Id: miniupnpc.h,v 1.15 2007/10/16 15:07:32 nanard Exp $ */
|
||||
//LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif);
|
||||
upcd->devlist = upnpDiscover(2000, NULL);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
/* $Id: miniupnpc.h,v 1.14 2007/10/01 13:42:52 nanard Exp $ */
|
||||
/* $Id: miniupnpc.h,v 1.9 2006/09/04 09:30:17 nanard Exp $ */
|
||||
//struct UPNPDev * upnpDiscover(int);
|
||||
upcd->devlist = upnpDiscover(2000);
|
||||
#else
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
//2006/09/04 to 2007/10/01 => -7//Start return struct UPNPDev * for upnpDiscover
|
||||
//2007/10/16 => -6 upnpDiscover
|
||||
//2007/12/19 => -5 upnpDiscover
|
||||
//2008/09/25 => -4 upnpDiscover
|
||||
//2009/04/17 => -3 UPNP_AddPortMapping
|
||||
//2010/12/09 => -2 //struct IGDdatas_service CIF;
|
||||
//2011/02/15 => -1 UPNP_AddPortMapping
|
||||
//2011/03/14 => 6 //Start of MINIUPNPC_API_VERSION
|
||||
#endif//>=-7
|
||||
#endif//>=-6
|
||||
#endif//>=-5
|
||||
#endif//>=-4
|
||||
#endif//>=6
|
||||
#endif//>=8
|
||||
#endif//>=14
|
||||
|
||||
if(upcd->devlist)
|
||||
{
|
||||
struct UPNPDev * device;
|
||||
printf("List of UPNP devices found on the network :\n");
|
||||
for(device=upcd->devlist;device;device=device->pNext)
|
||||
{
|
||||
printf("\n desc: %s\n st: %s\n",
|
||||
device->descURL, device->st);
|
||||
}
|
||||
putchar('\n');
|
||||
if(UPNP_GetValidIGD(upcd->devlist, &(upcd->urls),
|
||||
&(upcd->data), upcd->lanaddr,
|
||||
sizeof(upcd->lanaddr)))
|
||||
{
|
||||
printf("Found valid IGD : %s\n",
|
||||
upcd->urls.controlURL);
|
||||
printf("Local LAN ip address : %s\n",
|
||||
upcd->lanaddr);
|
||||
|
||||
/* MODIFY STATE */
|
||||
dataMtx.lock(); /* LOCK MUTEX */
|
||||
|
||||
/* convert to ipaddress. */
|
||||
inet_aton(upcd->lanaddr, &(upnp_iaddr.sin_addr));
|
||||
upnp_iaddr.sin_port = htons(iport);
|
||||
|
||||
upnpState = RS_UPNP_S_READY;
|
||||
if (upnpConfig)
|
||||
{
|
||||
delete upnpConfig;
|
||||
}
|
||||
upnpConfig = upcd; /* */
|
||||
|
||||
dataMtx.unlock(); /* UNLOCK MUTEX */
|
||||
|
||||
|
||||
/* done -> READY */
|
||||
return 1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
|
||||
}
|
||||
|
||||
|
||||
freeUPNPDevlist(upcd->devlist);
|
||||
upcd->devlist = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "No IGD UPnP Device found on the network !\n");
|
||||
}
|
||||
|
||||
/* MODIFY STATE */
|
||||
dataMtx.lock(); /* LOCK MUTEX */
|
||||
|
||||
upnpState = RS_UPNP_S_UNAVAILABLE;
|
||||
delete upcd;
|
||||
upnpConfig = NULL;
|
||||
|
||||
dataMtx.unlock(); /* UNLOCK MUTEX */
|
||||
|
||||
/* done, FAILED -> NOT AVAILABLE */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool upnphandler::printUPnPState()
|
||||
{
|
||||
std::cerr << "upnphandler::printUPnPState() ... locking";
|
||||
std::cerr << std::endl;
|
||||
|
||||
RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */
|
||||
|
||||
std::cerr << "upnphandler::printUPnPState() ... locked";
|
||||
std::cerr << std::endl;
|
||||
|
||||
uPnPConfigData *config = upnpConfig;
|
||||
if ((upnpState >= RS_UPNP_S_READY) && (config))
|
||||
{
|
||||
DisplayInfos(&(config -> urls), &(config->data));
|
||||
GetConnectionStatus(&(config -> urls), &(config->data));
|
||||
ListRedirections(&(config -> urls), &(config->data));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "UPNP not Ready" << std::endl;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool upnphandler::checkUPnPActive()
|
||||
{
|
||||
RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */
|
||||
|
||||
uPnPConfigData *config = upnpConfig;
|
||||
if ((upnpState > RS_UPNP_S_READY) && (config))
|
||||
{
|
||||
char eprot1[] = "TCP";
|
||||
char eprot2[] = "UDP";
|
||||
|
||||
char in_addr[256];
|
||||
char in_port1[256];
|
||||
char in_port2[256];
|
||||
char eport1[256];
|
||||
char eport2[256];
|
||||
|
||||
struct sockaddr_in localAddr = upnp_iaddr;
|
||||
uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr);
|
||||
|
||||
snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port));
|
||||
snprintf(in_port2, 256, "%d", ntohs(localAddr.sin_port));
|
||||
|
||||
snprintf(in_addr, 256, "%d.%d.%d.%d",
|
||||
((linaddr >> 24) & 0xff),
|
||||
((linaddr >> 16) & 0xff),
|
||||
((linaddr >> 8) & 0xff),
|
||||
((linaddr >> 0) & 0xff));
|
||||
|
||||
snprintf(eport1, 256, "%d", eport_curr);
|
||||
snprintf(eport2, 256, "%d", eport_curr);
|
||||
|
||||
std::cerr << "upnphandler::checkUPnPState()";
|
||||
std::cerr << " Checking Redirection: InAddr: " << in_addr;
|
||||
std::cerr << " InPort: " << in_port1;
|
||||
std::cerr << " ePort: " << eport1;
|
||||
std::cerr << " eProt: " << eprot1;
|
||||
std::cerr << std::endl;
|
||||
|
||||
|
||||
bool tcpOk = TestRedirect(&(config -> urls), &(config->data),
|
||||
in_addr, in_port1, eport1, eprot1);
|
||||
bool udpOk = TestRedirect(&(config -> urls), &(config->data),
|
||||
in_addr, in_port2, eport2, eprot2);
|
||||
|
||||
if ((!tcpOk) || (!udpOk))
|
||||
{
|
||||
std::cerr << "upnphandler::checkUPnPState() ... Redirect Expired, restarting";
|
||||
std::cerr << std::endl;
|
||||
|
||||
toStop = true;
|
||||
toStart = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class upnpThreadData
|
||||
{
|
||||
public:
|
||||
upnphandler *handler;
|
||||
bool start;
|
||||
bool stop;
|
||||
};
|
||||
|
||||
/* Thread routines */
|
||||
extern "C" void* doSetupUPnP(void* p)
|
||||
{
|
||||
upnpThreadData *data = (upnpThreadData *) p;
|
||||
if ((!data) || (!data->handler))
|
||||
{
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
/* publish it! */
|
||||
if (data -> stop)
|
||||
{
|
||||
data->handler->shutdown_upnp();
|
||||
}
|
||||
|
||||
if (data -> start)
|
||||
{
|
||||
data->handler->initUPnPState();
|
||||
data->handler->start_upnp();
|
||||
}
|
||||
|
||||
data->handler->printUPnPState();
|
||||
|
||||
delete data;
|
||||
pthread_exit(NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool upnphandler::background_setup_upnp(bool start, bool stop)
|
||||
{
|
||||
pthread_t tid;
|
||||
|
||||
/* launch thread */
|
||||
upnpThreadData *data = new upnpThreadData();
|
||||
data->handler = this;
|
||||
data->start = start;
|
||||
data->stop = stop;
|
||||
|
||||
if(!pthread_create(&tid, 0, &doSetupUPnP, (void *) data))
|
||||
{
|
||||
pthread_detach(tid); /* so memory is reclaimed in linux */
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete data ;
|
||||
std::cerr << "(EE) Failed to start upnp thread." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
bool upnphandler::start_upnp()
|
||||
{
|
||||
RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */
|
||||
|
||||
uPnPConfigData *config = upnpConfig;
|
||||
if (!((upnpState >= RS_UPNP_S_READY) && (config)))
|
||||
{
|
||||
std::cerr << "upnphandler::start_upnp() Not Ready";
|
||||
std::cerr << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
char eprot1[] = "TCP";
|
||||
char eprot2[] = "UDP";
|
||||
|
||||
/* if we're to load -> load */
|
||||
/* select external ports */
|
||||
eport_curr = eport;
|
||||
if (!eport_curr)
|
||||
{
|
||||
/* use local port if eport is zero */
|
||||
eport_curr = iport;
|
||||
std::cerr << "Using LocalPort for extPort!";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
if (!eport_curr)
|
||||
{
|
||||
std::cerr << "Invalid eport ... ";
|
||||
std::cerr << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* our port */
|
||||
char in_addr[256];
|
||||
char in_port1[256];
|
||||
char in_port2[256];
|
||||
char eport1[256];
|
||||
char eport2[256];
|
||||
|
||||
upnp_iaddr.sin_port = htons(iport);
|
||||
struct sockaddr_in localAddr = upnp_iaddr;
|
||||
uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr);
|
||||
|
||||
snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port));
|
||||
snprintf(in_port2, 256, "%d", ntohs(localAddr.sin_port));
|
||||
snprintf(in_addr, 256, "%d.%d.%d.%d",
|
||||
((linaddr >> 24) & 0xff),
|
||||
((linaddr >> 16) & 0xff),
|
||||
((linaddr >> 8) & 0xff),
|
||||
((linaddr >> 0) & 0xff));
|
||||
|
||||
snprintf(eport1, 256, "%d", eport_curr);
|
||||
snprintf(eport2, 256, "%d", eport_curr);
|
||||
|
||||
std::cerr << "Attempting Redirection: InAddr: " << in_addr;
|
||||
std::cerr << " InPort: " << in_port1;
|
||||
std::cerr << " ePort: " << eport1;
|
||||
std::cerr << " eProt: " << eprot1;
|
||||
std::cerr << std::endl;
|
||||
|
||||
if (!SetRedirectAndTest(&(config -> urls), &(config->data),
|
||||
in_addr, in_port1, eport1, eprot1,
|
||||
NULL /*leaseDuration*/, "RetroShare_TCP" /*description*/,
|
||||
0))
|
||||
{
|
||||
upnpState = RS_UPNP_S_TCP_FAILED;
|
||||
}
|
||||
else if (!SetRedirectAndTest(&(config -> urls), &(config->data),
|
||||
in_addr, in_port2, eport2, eprot2,
|
||||
NULL /*leaseDuration*/, "RetroShare_UDP" /*description*/,
|
||||
0))
|
||||
{
|
||||
upnpState = RS_UPNP_S_UDP_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
upnpState = RS_UPNP_S_ACTIVE;
|
||||
}
|
||||
|
||||
|
||||
/* now store the external address */
|
||||
char externalIPAddress[32];
|
||||
UPNP_GetExternalIPAddress(config -> urls.controlURL,
|
||||
#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
|
||||
config->data.first.servicetype,
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
config->data.servicetype,
|
||||
#else
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
#endif
|
||||
#endif
|
||||
externalIPAddress);
|
||||
|
||||
sockaddr_clear(&upnp_eaddr);
|
||||
|
||||
if(externalIPAddress[0])
|
||||
{
|
||||
std::cerr << "Stored External address: " << externalIPAddress;
|
||||
std::cerr << ":" << eport_curr;
|
||||
std::cerr << std::endl;
|
||||
|
||||
inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr));
|
||||
upnp_eaddr.sin_family = AF_INET;
|
||||
upnp_eaddr.sin_port = htons(eport_curr);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "FAILED To get external Address";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
toStart = false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool upnphandler::shutdown_upnp()
|
||||
{
|
||||
RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */
|
||||
|
||||
uPnPConfigData *config = upnpConfig;
|
||||
if (!((upnpState >= RS_UPNP_S_READY) && (config)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char eprot1[] = "TCP";
|
||||
char eprot2[] = "UDP";
|
||||
|
||||
/* always attempt this (unless no port number) */
|
||||
if (eport_curr > 0)
|
||||
{
|
||||
|
||||
char eport1[256];
|
||||
char eport2[256];
|
||||
|
||||
snprintf(eport1, 256, "%d", eport_curr);
|
||||
snprintf(eport2, 256, "%d", eport_curr);
|
||||
|
||||
std::cerr << "Attempting To Remove Redirection: port: " << eport1;
|
||||
std::cerr << " Prot: " << eprot1;
|
||||
std::cerr << std::endl;
|
||||
|
||||
RemoveRedirect(&(config -> urls), &(config->data),
|
||||
eport1, eprot1);
|
||||
|
||||
|
||||
std::cerr << "Attempting To Remove Redirection: port: " << eport2;
|
||||
std::cerr << " Prot: " << eprot2;
|
||||
std::cerr << std::endl;
|
||||
|
||||
RemoveRedirect(&(config -> urls), &(config->data),
|
||||
eport2, eprot2);
|
||||
|
||||
upnpState = RS_UPNP_S_READY;
|
||||
toStop = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/************************ External Interface *****************************
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
upnphandler::upnphandler()
|
||||
: dataMtx("upnpState"), toEnable(false), toStart(false), toStop(false),
|
||||
eport(0), eport_curr(0),
|
||||
upnpState(RS_UPNP_S_UNINITIALISED),
|
||||
upnpConfig(NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
upnphandler::~upnphandler()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* RsIface */
|
||||
void upnphandler::enable(bool active)
|
||||
{
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
|
||||
if (active != toEnable)
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
toStart = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
toStop = true;
|
||||
}
|
||||
}
|
||||
toEnable = active;
|
||||
|
||||
bool start = toStart;
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
|
||||
if (start)
|
||||
{
|
||||
/* make background thread to startup UPnP */
|
||||
background_setup_upnp(true, false);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void upnphandler::shutdown()
|
||||
{
|
||||
/* blocking call to shutdown upnp */
|
||||
|
||||
shutdown_upnp();
|
||||
}
|
||||
|
||||
|
||||
void upnphandler::restart()
|
||||
{
|
||||
/* non-blocking call to shutdown upnp, and startup again. */
|
||||
background_setup_upnp(true, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool upnphandler::getEnabled()
|
||||
{
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
|
||||
bool on = toEnable;
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
|
||||
return on;
|
||||
}
|
||||
|
||||
bool upnphandler::getActive()
|
||||
{
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
|
||||
bool on = (upnpState == RS_UPNP_S_ACTIVE);
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
|
||||
return on;
|
||||
}
|
||||
|
||||
/* the address that the listening port is on */
|
||||
void upnphandler::setInternalPort(unsigned short iport_in)
|
||||
{
|
||||
// std::cerr << "UPnPHandler::setInternalAddress() pre Lock!" << std::endl;
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
// std::cerr << "UPnPHandler::setInternalAddress() postLock!" << std::endl;
|
||||
|
||||
std::cerr << "UPnPHandler::setInternalPort(" << iport_in << ") current port: ";
|
||||
std::cerr << iport << std::endl;
|
||||
|
||||
if (iport != iport_in)
|
||||
{
|
||||
iport = iport_in;
|
||||
if ((toEnable) &&
|
||||
(upnpState == RS_UPNP_S_ACTIVE))
|
||||
{
|
||||
toStop = true;
|
||||
toStart = true;
|
||||
}
|
||||
}
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
}
|
||||
|
||||
void upnphandler::setExternalPort(unsigned short eport_in)
|
||||
{
|
||||
// std::cerr << "UPnPHandler::getExternalPort() pre Lock!" << std::endl;
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
// std::cerr << "UPnPHandler::getExternalPort() postLock!" << std::endl;
|
||||
|
||||
std::cerr << "UPnPHandler::setExternalPort(" << eport_in << ") current port: ";
|
||||
std::cerr << eport << std::endl;
|
||||
|
||||
/* flag both shutdown/start -> for restart */
|
||||
if (eport != eport_in)
|
||||
{
|
||||
eport = eport_in;
|
||||
if ((toEnable) &&
|
||||
(upnpState == RS_UPNP_S_ACTIVE))
|
||||
{
|
||||
toStop = true;
|
||||
toStart = true;
|
||||
}
|
||||
}
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
}
|
||||
|
||||
/* as determined by uPnP */
|
||||
bool upnphandler::getInternalAddress(struct sockaddr_storage &addr)
|
||||
{
|
||||
// std::cerr << "UPnPHandler::getInternalAddress() pre Lock!" << std::endl;
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
// std::cerr << "UPnPHandler::getInternalAddress() postLock!" << std::endl;
|
||||
|
||||
std::cerr << "UPnPHandler::getInternalAddress()" << std::endl;
|
||||
|
||||
// copy to universal addr.
|
||||
sockaddr_storage_clear(addr);
|
||||
sockaddr_storage_setipv4(addr, &upnp_iaddr);
|
||||
|
||||
bool valid = (upnpState >= RS_UPNP_S_ACTIVE);
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool upnphandler::getExternalAddress(struct sockaddr_storage &addr)
|
||||
{
|
||||
// std::cerr << "UPnPHandler::getExternalAddress() pre Lock!" << std::endl;
|
||||
dataMtx.lock(); /*** LOCK MUTEX ***/
|
||||
// std::cerr << "UPnPHandler::getExternalAddress() postLock!" << std::endl;
|
||||
|
||||
std::cerr << "UPnPHandler::getExternalAddress()" << std::endl;
|
||||
|
||||
// copy to universal addr.
|
||||
sockaddr_storage_clear(addr);
|
||||
sockaddr_storage_setipv4(addr, &upnp_eaddr);
|
||||
|
||||
bool valid = (upnpState == RS_UPNP_S_ACTIVE);
|
||||
|
||||
dataMtx.unlock(); /*** UNLOCK MUTEX ***/
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
131
libretroshare/src/rs_upnp/upnphandler_miniupnp.h
Normal file
131
libretroshare/src/rs_upnp/upnphandler_miniupnp.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/upnp: upnphandler_miniupnp.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2007-2018 Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
//windows/osx (miniupnpc) implementation
|
||||
#ifndef _RS_UPNP_IFACE_H
|
||||
#define _RS_UPNP_IFACE_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
/* platform independent networking... */
|
||||
#include "pqi/pqinetwork.h"
|
||||
#include "pqi/pqiassist.h"
|
||||
|
||||
#include "util/rsthreads.h"
|
||||
|
||||
class upnpentry
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
std::string id;
|
||||
struct sockaddr_in addr;
|
||||
unsigned int flags;
|
||||
int status;
|
||||
int lastTs;
|
||||
};
|
||||
|
||||
class upnpforward
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
unsigned int flags;
|
||||
struct sockaddr_in iaddr;
|
||||
struct sockaddr_in eaddr;
|
||||
int status;
|
||||
int lastTs;
|
||||
};
|
||||
|
||||
|
||||
#define RS_UPNP_S_UNINITIALISED 0
|
||||
#define RS_UPNP_S_UNAVAILABLE 1
|
||||
#define RS_UPNP_S_READY 2
|
||||
#define RS_UPNP_S_TCP_FAILED 3
|
||||
#define RS_UPNP_S_UDP_FAILED 4
|
||||
#define RS_UPNP_S_ACTIVE 5
|
||||
|
||||
class uPnPConfigData;
|
||||
|
||||
class upnphandler: public pqiNetAssistFirewall
|
||||
{
|
||||
public:
|
||||
|
||||
upnphandler();
|
||||
virtual ~upnphandler();
|
||||
|
||||
/* External Interface (pqiNetAssistFirewall) */
|
||||
virtual void enable(bool active);
|
||||
virtual void shutdown();
|
||||
virtual void restart();
|
||||
|
||||
virtual bool getEnabled();
|
||||
virtual bool getActive();
|
||||
|
||||
virtual void setInternalPort(unsigned short iport_in);
|
||||
virtual void setExternalPort(unsigned short eport_in);
|
||||
virtual bool getInternalAddress(struct sockaddr_storage &addr);
|
||||
virtual bool getExternalAddress(struct sockaddr_storage &addr);
|
||||
|
||||
/* TO IMPLEMENT: New Port Forward interface to support as many ports as necessary */
|
||||
virtual bool requestPortForward(const PortForwardParams &/*params*/) { return false; }
|
||||
virtual bool statusPortForward(const uint32_t /*fwdId*/, PortForwardParams &/*params*/) { return false; }
|
||||
|
||||
/* Public functions - for background thread operation,
|
||||
* but effectively private from rest of RS, as in derived class
|
||||
*/
|
||||
|
||||
bool start_upnp();
|
||||
bool shutdown_upnp();
|
||||
|
||||
bool initUPnPState();
|
||||
bool printUPnPState();
|
||||
|
||||
private:
|
||||
|
||||
bool background_setup_upnp(bool, bool);
|
||||
bool checkUPnPActive();
|
||||
|
||||
/* Mutex for data below */
|
||||
RsMutex dataMtx;
|
||||
|
||||
bool toEnable; /* overall on/off switch */
|
||||
bool toStart; /* if set start forwarding */
|
||||
bool toStop; /* if set stop forwarding */
|
||||
|
||||
unsigned short iport;
|
||||
unsigned short eport; /* config */
|
||||
unsigned short eport_curr; /* current forwarded */
|
||||
|
||||
/* info from upnp */
|
||||
unsigned int upnpState;
|
||||
uPnPConfigData *upnpConfig;
|
||||
|
||||
struct sockaddr_in upnp_iaddr;
|
||||
struct sockaddr_in upnp_eaddr;
|
||||
|
||||
/* active port forwarding */
|
||||
std::list<upnpforward> activeForwards;
|
||||
|
||||
};
|
||||
|
||||
#endif /* _RS_UPNP_IFACE_H */
|
86
libretroshare/src/rs_upnp/upnptest.cc
Normal file
86
libretroshare/src/rs_upnp/upnptest.cc
Normal file
|
@ -0,0 +1,86 @@
|
|||
//this file use miniupnp
|
||||
|
||||
#include "upnp/upnphandler.h"
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
int id = argc % 3;
|
||||
|
||||
/*********
|
||||
char *fhash1 = "3509426505463458576487";
|
||||
char *hash2 = "1549879882341985914515";
|
||||
char *hash3 = "8743598543269526505434";
|
||||
|
||||
int port1 = 8754;
|
||||
int port2 = 2355;
|
||||
int port3 = 6621;
|
||||
**********/
|
||||
|
||||
std::cerr << "Starting dhttest Id: " << id << std::endl;
|
||||
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||
#ifndef WINDOWS_SYS
|
||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||
#else
|
||||
// Windows Networking Init.
|
||||
WORD wVerReq = MAKEWORD(2,2);
|
||||
WSADATA wsaData;
|
||||
|
||||
if (0 != WSAStartup(wVerReq, &wsaData))
|
||||
{
|
||||
std::cerr << "Failed to Startup Windows Networking";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Started Windows Networking";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||
|
||||
#ifdef PTW32_STATIC_LIB
|
||||
pthread_win32_process_attach_np();
|
||||
#endif
|
||||
|
||||
|
||||
upnphandler upnp;
|
||||
|
||||
upnp.setInternalPort(12122);
|
||||
|
||||
for(int i = 0; 1; i++)
|
||||
{
|
||||
|
||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||
#ifndef WINDOWS_SYS
|
||||
sleep(1);
|
||||
#else
|
||||
|
||||
Sleep(1000);
|
||||
#endif
|
||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||
|
||||
if (i % 120 == 10)
|
||||
{
|
||||
/* start up a forward */
|
||||
upnp.enable(true);
|
||||
|
||||
}
|
||||
|
||||
if (i % 120 == 60)
|
||||
{
|
||||
/* shutdown a forward */
|
||||
upnp.restart();
|
||||
}
|
||||
|
||||
if (i % 120 == 100)
|
||||
{
|
||||
/* shutdown a forward */
|
||||
upnp.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
611
libretroshare/src/rs_upnp/upnputil.c
Normal file
611
libretroshare/src/rs_upnp/upnputil.c
Normal file
|
@ -0,0 +1,611 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/upnp: upnputil.c *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* From MiniUPnPc, re-licensed with permission *
|
||||
* *
|
||||
* Copyright (c) 2005-2016, Thomas BERNARD *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
//this file uses miniupnp
|
||||
//From https://github.com/miniupnp/miniupnp/blob/master/miniupnpc/upnpc.c
|
||||
|
||||
#include "upnp/upnputil.h"
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18
|
||||
#include "util/rstime.h"
|
||||
#endif
|
||||
|
||||
/* protofix() checks if protocol is "UDP" or "TCP"
|
||||
* returns NULL if not */
|
||||
const char * protofix(const char * proto)
|
||||
{
|
||||
static const char proto_tcp[4] = { 'T', 'C', 'P', 0};
|
||||
static const char proto_udp[4] = { 'U', 'D', 'P', 0};
|
||||
int i, b;
|
||||
for(i=0, b=1; i<4; i++)
|
||||
b = b && ( (proto[i] == proto_tcp[i])
|
||||
|| (proto[i] == (proto_tcp[i] | 32)) );
|
||||
if(b)
|
||||
return proto_tcp;
|
||||
for(i=0, b=1; i<4; i++)
|
||||
b = b && ( (proto[i] == proto_udp[i])
|
||||
|| (proto[i] == (proto_udp[i] | 32)) );
|
||||
if(b)
|
||||
return proto_udp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DisplayInfos(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
char externalIPAddress[40];
|
||||
char connectionType[64];
|
||||
char status[64];
|
||||
char lastconnerr[64];
|
||||
unsigned int uptime;
|
||||
unsigned int brUp, brDown;
|
||||
time_t timenow, timestarted; // Don't use rstime_t here or ctime break on windows
|
||||
int r;
|
||||
#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
|
||||
const char * servicetype = data->first.servicetype;
|
||||
const char * servicetype_CIF = data->CIF.servicetype;
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
const char * servicetype = data->servicetype;
|
||||
const char * servicetype_CIF = data->servicetype_CIF;
|
||||
#else
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
#endif//>=-7
|
||||
#endif//>=-2
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= -3//1.0 2009/04/17
|
||||
if(UPNP_GetConnectionTypeInfo(urls->controlURL,
|
||||
servicetype,
|
||||
connectionType) != UPNPCOMMAND_SUCCESS)
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
UPNP_GetConnectionTypeInfo(urls->controlURL, servicetype,
|
||||
connectionType);
|
||||
if(connectionType[0])
|
||||
#endif//>=-7
|
||||
#endif//>=-3
|
||||
printf("GetConnectionTypeInfo failed.\n");
|
||||
else
|
||||
printf("Connection Type : %s\n", connectionType);
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18
|
||||
if(UPNP_GetStatusInfo(urls->controlURL, servicetype,
|
||||
status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS)
|
||||
printf("GetStatusInfo failed.\n");
|
||||
else
|
||||
printf("Status : %s, uptime=%us, LastConnectionError : %s\n",
|
||||
status, uptime, lastconnerr);
|
||||
timenow = time(NULL);
|
||||
timestarted = timenow - uptime;
|
||||
printf(" Time started : %s", ctime(×tarted));
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
UPNP_GetStatusInfo(urls->controlURL, servicetype,
|
||||
status, &uptime, lastconnerr);
|
||||
printf("Status : %s, uptime=%u, LastConnectionError : %s\n",
|
||||
status, uptime, lastconnerr);
|
||||
#endif//>=-7
|
||||
#endif//>=-4
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18
|
||||
if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, servicetype_CIF,
|
||||
&brDown, &brUp) != UPNPCOMMAND_SUCCESS) {
|
||||
printf("GetLinkLayerMaxBitRates failed.\n");
|
||||
} else {
|
||||
printf("MaxBitRateDown : %u bps", brDown);
|
||||
if(brDown >= 1000000) {
|
||||
printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10);
|
||||
} else if(brDown >= 1000) {
|
||||
printf(" (%u Kbps)", brDown / 1000);
|
||||
}
|
||||
printf(" MaxBitRateUp %u bps", brUp);
|
||||
if(brUp >= 1000000) {
|
||||
printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10);
|
||||
} else if(brUp >= 1000) {
|
||||
printf(" (%u Kbps)", brUp / 1000);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF,
|
||||
servicetype_CIF,
|
||||
&brDown, &brUp);
|
||||
printf("MaxBitRateDown : %u bps MaxBitRateUp %u bps\n", brDown, brUp);
|
||||
#endif//>=-7
|
||||
#endif//>=-4
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19
|
||||
r = UPNP_GetExternalIPAddress(urls->controlURL,
|
||||
servicetype,
|
||||
externalIPAddress);
|
||||
if(r != UPNPCOMMAND_SUCCESS) {
|
||||
printf("GetExternalIPAddress failed. (errorcode=%d)\n", r);
|
||||
} else {
|
||||
printf("ExternalIPAddress = %s\n", externalIPAddress);
|
||||
}
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
UPNP_GetExternalIPAddress(urls->controlURL,
|
||||
servicetype,
|
||||
externalIPAddress);
|
||||
if(externalIPAddress[0])
|
||||
printf("ExternalIPAddress = %s\n", externalIPAddress);
|
||||
else
|
||||
printf("GetExternalIPAddress failed.\n");
|
||||
#endif//>=-7
|
||||
#endif//>=-4
|
||||
}
|
||||
|
||||
void GetConnectionStatus(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
|
||||
#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
|
||||
const char * servicetype_CIF = data->CIF.servicetype;
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
const char * servicetype_CIF = data->servicetype_CIF;
|
||||
#else
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
#endif//>=-7
|
||||
#endif//>=-2
|
||||
|
||||
DisplayInfos(urls, data);
|
||||
bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, servicetype_CIF);
|
||||
bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, servicetype_CIF);
|
||||
packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, servicetype_CIF);
|
||||
packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, servicetype_CIF);
|
||||
printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
|
||||
printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
|
||||
}
|
||||
|
||||
void ListRedirections(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
int r;
|
||||
int i = 0;
|
||||
char index[6];
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
char extPort[6];
|
||||
char protocol[4];
|
||||
char desc[80];
|
||||
char enabled[6];
|
||||
char rHost[64];
|
||||
char duration[16];
|
||||
#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
|
||||
const char * servicetype = data->first.servicetype;
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
const char * servicetype = data->servicetype;
|
||||
#else
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
#endif//>=-7
|
||||
#endif//>=-2
|
||||
|
||||
/*unsigned int num=0;
|
||||
UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num);
|
||||
printf("PortMappingNumberOfEntries : %u\n", num);*/
|
||||
do {
|
||||
snprintf(index, 6, "%d", i);
|
||||
rHost[0] = '\0'; enabled[0] = '\0';
|
||||
duration[0] = '\0'; desc[0] = '\0';
|
||||
extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
|
||||
r = UPNP_GetGenericPortMappingEntry(urls->controlURL,
|
||||
servicetype,
|
||||
index,
|
||||
extPort, intClient, intPort,
|
||||
protocol, desc, enabled,
|
||||
rHost, duration);
|
||||
if(r==0)
|
||||
printf("%02d - %s %5s->%s:%-5s"
|
||||
"\tenabled=%s leaseDuration=%s\n"
|
||||
" desc='%s' rHost='%s'\n",
|
||||
i, protocol, extPort, intClient, intPort,
|
||||
enabled, duration,
|
||||
desc, rHost);
|
||||
else
|
||||
printf("GetGenericPortMappingEntry() returned %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
i++;
|
||||
} while(r==0);
|
||||
}
|
||||
|
||||
/* Test function
|
||||
* 1 - get connection type
|
||||
* 2 - get extenal ip address
|
||||
* 3 - Add port mapping
|
||||
* 4 - get this port mapping from the IGD */
|
||||
int SetRedirectAndTest(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * iaddr,
|
||||
const char * iport,
|
||||
const char * eport,
|
||||
const char * proto,
|
||||
const char * leaseDuration,
|
||||
const char * description,
|
||||
int addAny)
|
||||
{
|
||||
char externalIPAddress[40];
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
char reservedPort[6];
|
||||
char duration[16];
|
||||
int r;
|
||||
int ok = 1;
|
||||
#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
|
||||
const char * servicetype = data->first.servicetype;
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
const char * servicetype = data->servicetype;
|
||||
#else
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(!iaddr || !iport || !eport || !proto)
|
||||
{
|
||||
fprintf(stderr, "Wrong arguments\n");
|
||||
return 0;
|
||||
}
|
||||
proto = protofix(proto);
|
||||
if(!proto)
|
||||
{
|
||||
fprintf(stderr, "invalid protocol\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19
|
||||
r = UPNP_GetExternalIPAddress(urls->controlURL,
|
||||
servicetype,
|
||||
externalIPAddress);
|
||||
if(r != UPNPCOMMAND_SUCCESS)
|
||||
printf("GetExternalIPAddress failed. (errorcode=%d)\n", r);
|
||||
else
|
||||
printf("ExternalIPAddress = %s\n", externalIPAddress);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
UPNP_GetExternalIPAddress(urls->controlURL,
|
||||
servicetype,
|
||||
externalIPAddress);
|
||||
if(externalIPAddress[0])
|
||||
printf("ExternalIPAddress = %s\n", externalIPAddress);
|
||||
else
|
||||
printf("GetExternalIPAddress failed.\n");
|
||||
#endif//>=-7
|
||||
#endif//>=-4
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= 11
|
||||
if (addAny) {
|
||||
r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype,
|
||||
eport, iport, iaddr, description,
|
||||
proto, 0, leaseDuration, reservedPort);
|
||||
if(r==UPNPCOMMAND_SUCCESS)
|
||||
eport = reservedPort;
|
||||
else
|
||||
printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n",
|
||||
eport, iport, iaddr, r, strupnperror(r));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#if MINIUPNPC_API_VERSION >= -1
|
||||
/* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */
|
||||
/* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */
|
||||
//UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
|
||||
// const char * extPort,
|
||||
// const char * inPort,
|
||||
// const char * inClient,
|
||||
// const char * desc,
|
||||
// const char * proto,
|
||||
// const char * remoteHost,
|
||||
// const char * leaseDuration);
|
||||
r = UPNP_AddPortMapping(urls->controlURL, servicetype,
|
||||
eport, iport, iaddr, description, proto, NULL, NULL);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -3 //1.0 2009/04/17
|
||||
/* $Id: upnpcommands.h,v 1.18 2010/06/09 10:59:09 nanard Exp $ */
|
||||
/* $Id: upnpcommands.h,v 1.17 2009/04/17 21:21:19 nanard Exp $ */
|
||||
//UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
|
||||
// const char * extPort,
|
||||
// const char * inPort,
|
||||
// const char * inClient,
|
||||
// const char * desc,
|
||||
// const char * proto,
|
||||
// const char * remoteHost);
|
||||
r = UPNP_AddPortMapping(urls->controlURL, servicetype,
|
||||
eport, iport, iaddr, description, proto, NULL);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//Before 1.0
|
||||
/* $Id: upnpcommands.h,v 1.14 2008/09/25 18:02:50 nanard Exp $ */
|
||||
/* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */
|
||||
//UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
|
||||
// const char * extPort,
|
||||
// const char * inPort,
|
||||
// const char * inClient,
|
||||
// const char * desc,
|
||||
// const char * proto);
|
||||
r = UPNP_AddPortMapping(urls->controlURL, servicetype,
|
||||
eport, iport, iaddr, description, proto);
|
||||
#else
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
#endif//>=-7
|
||||
#endif//>=-3
|
||||
#endif//>=-1
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= -5//2007/12/19
|
||||
if(r!=UPNPCOMMAND_SUCCESS){
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//Before 1.0
|
||||
if(r==0){
|
||||
#else
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
#endif//>=-7
|
||||
#endif//>=-5
|
||||
printf("AddPortMapping(%s, %s, %s) failed and returns %d\n", eport, iport, iaddr, r);
|
||||
//this seems to trigger for unknown reasons sometimes.
|
||||
//rely on Checking it afterwards...
|
||||
//should check IP address then!
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= 10//1.0 2006/09/04
|
||||
/* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */
|
||||
/* $Id: upnpcommands.h,v 1.26 2014/01/31 13:18:26 nanard Exp $ */
|
||||
//UPNP_GetSpecificPortMappingEntry(const char * controlURL,
|
||||
// const char * servicetype,
|
||||
// const char * extPort,
|
||||
// const char * proto,
|
||||
// const char * remoteHost,
|
||||
// char * intClient,
|
||||
// char * intPort,
|
||||
// char * desc,
|
||||
// char * enabled,
|
||||
// char * leaseDuration);
|
||||
r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
eport, proto, NULL/*remoteHost*/,
|
||||
intClient, intPort, NULL/*desc*/,
|
||||
NULL/*enabled*/, duration);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= 6//1.0 2006/09/04
|
||||
/* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */
|
||||
/* $Id: upnpcommands.h,v 1.22 2011/03/14 13:36:01 nanard Exp $ */
|
||||
//UPNP_GetSpecificPortMappingEntry(const char * controlURL,
|
||||
// const char * servicetype,
|
||||
// const char * extPort,
|
||||
// const char * proto,
|
||||
// char * intClient,
|
||||
// char * intPort,
|
||||
// char * desc,
|
||||
// char * enabled,
|
||||
// char * leaseDuration);
|
||||
r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
eport, proto,
|
||||
intClient, intPort, NULL/*desc*/,
|
||||
NULL/*enabled*/, duration);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
/* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */
|
||||
/* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */
|
||||
//UPNP_GetSpecificPortMappingEntry(const char * controlURL,
|
||||
// const char * servicetype,
|
||||
// const char * extPort,
|
||||
// const char * proto,
|
||||
// char * intClient,
|
||||
// char * intPort);
|
||||
UPNP_GetSpecificPortMappingEntry(urls->controlURL,
|
||||
servicetype,
|
||||
eport,
|
||||
proto,
|
||||
intClient,
|
||||
intPort);
|
||||
if(intClient[0]) r = UPNPCOMMAND_SUCCESS;
|
||||
#endif//>=-7
|
||||
#endif//>=6
|
||||
#endif//>=10
|
||||
|
||||
if(r!=UPNPCOMMAND_SUCCESS) {
|
||||
printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
ok = 0;
|
||||
} else if(intClient[0]) {
|
||||
printf("InternalIP:Port = %s:%s\n", intClient, intPort);
|
||||
printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
|
||||
externalIPAddress, eport, proto, intClient, intPort, duration);
|
||||
}
|
||||
|
||||
if ((strcmp(iaddr, intClient) != 0) || (strcmp(iport, intPort) != 0))
|
||||
{
|
||||
printf("PortMappingEntry to wrong location! FAILED\n");
|
||||
printf("IP1:\"%s\"\n", iaddr);
|
||||
printf("IP2:\"%s\"\n", intClient);
|
||||
printf("PORT1:\"%s\"\n", iport);
|
||||
printf("PORT2:\"%s\"\n", intPort);
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
printf("uPnP Forward/Mapping Succeeded\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("uPnP Forward/Mapping Failed\n");
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
int TestRedirect(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * iaddr,
|
||||
const char * iport,
|
||||
const char * eport,
|
||||
const char * proto)
|
||||
{
|
||||
char externalIPAddress[40];
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
char duration[16];
|
||||
int r = 0;
|
||||
int ok = 1;
|
||||
|
||||
if(!iaddr || !iport || !eport || !proto)
|
||||
{
|
||||
fprintf(stderr, "Wrong arguments\n");
|
||||
return 0;
|
||||
}
|
||||
proto = protofix(proto);
|
||||
if(!proto)
|
||||
{
|
||||
fprintf(stderr, "invalid protocol\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
|
||||
const char * servicetype = data->first.servicetype;
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
const char * servicetype = data->servicetype;
|
||||
#else
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MINIUPNPC_API_VERSION >= 10//1.0 2006/09/04
|
||||
/* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */
|
||||
/* $Id: upnpcommands.h,v 1.26 2014/01/31 13:18:26 nanard Exp $ */
|
||||
//UPNP_GetSpecificPortMappingEntry(const char * controlURL,
|
||||
// const char * servicetype,
|
||||
// const char * extPort,
|
||||
// const char * proto,
|
||||
// const char * remoteHost,
|
||||
// char * intClient,
|
||||
// char * intPort,
|
||||
// char * desc,
|
||||
// char * enabled,
|
||||
// char * leaseDuration);
|
||||
r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
|
||||
servicetype,
|
||||
eport, proto, NULL/*remoteHost*/,
|
||||
intClient, intPort, NULL/*desc*/,
|
||||
NULL/*enabled*/, duration);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= 6//1.0 2006/09/04
|
||||
/* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */
|
||||
/* $Id: upnpcommands.h,v 1.22 2011/03/14 13:36:01 nanard Exp $ */
|
||||
//UPNP_GetSpecificPortMappingEntry(const char * controlURL,
|
||||
// const char * servicetype,
|
||||
// const char * extPort,
|
||||
// const char * proto,
|
||||
// char * intClient,
|
||||
// char * intPort,
|
||||
// char * desc,
|
||||
// char * enabled,
|
||||
// char * leaseDuration);
|
||||
r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
|
||||
servicetype,
|
||||
eport, proto,
|
||||
intClient, intPort, NULL/*desc*/,
|
||||
NULL/*enabled*/, duration);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
/* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */
|
||||
/* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */
|
||||
//UPNP_GetSpecificPortMappingEntry(const char * controlURL,
|
||||
// const char * servicetype,
|
||||
// const char * extPort,
|
||||
// const char * proto,
|
||||
// char * intClient,
|
||||
// char * intPort);
|
||||
UPNP_GetSpecificPortMappingEntry(urls->controlURL,
|
||||
servicetype,
|
||||
eport,
|
||||
proto,
|
||||
intClient,
|
||||
intPort);
|
||||
if(intClient[0]) r = UPNPCOMMAND_SUCCESS;
|
||||
#endif//>=-7
|
||||
#endif//>=6
|
||||
#endif//>=10
|
||||
|
||||
if(r!=UPNPCOMMAND_SUCCESS) {
|
||||
printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
ok = 0;
|
||||
} else if(intClient[0]) {
|
||||
printf("uPnP Check: InternalIP:Port = %s:%s\n", intClient, intPort);
|
||||
printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
|
||||
externalIPAddress, eport, proto, intClient, intPort, duration);
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
printf("uPnP Check: uPnP Forward/Mapping still Active\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("uPnP Check: Forward/Mapping has been Dropped\n");
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
int
|
||||
RemoveRedirect(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * eport,
|
||||
const char * proto)
|
||||
{
|
||||
if(!proto || !eport)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return 0;
|
||||
}
|
||||
proto = protofix(proto);
|
||||
if(!proto)
|
||||
{
|
||||
fprintf(stderr, "protocol invalid\n");
|
||||
return 0;
|
||||
}
|
||||
#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
|
||||
UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, NULL);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -3//1.3 2009/04/17
|
||||
UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto, NULL);
|
||||
#else
|
||||
#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
|
||||
UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto);
|
||||
#else
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
#endif//>= -7
|
||||
#endif//>= -3
|
||||
#endif//>= -2
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
101
libretroshare/src/rs_upnp/upnputil.h
Normal file
101
libretroshare/src/rs_upnp/upnputil.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/upnp: upnputil.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* From MiniUPnPc, re-licensed with permission *
|
||||
* *
|
||||
* Copyright (c) 2005-2016, Thomas BERNARD *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
//this file uses miniupnp
|
||||
|
||||
#ifndef MINIUPNP_UTIL_H_
|
||||
#define MINIUPNP_UTIL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#include <miniupnpc/miniwget.h>
|
||||
#include <miniupnpc/miniupnpc.h>
|
||||
#include <miniupnpc/upnpcommands.h>
|
||||
#include <miniupnpc/upnperrors.h>
|
||||
|
||||
//Define this variable follow the date of used MiniUPnP Library
|
||||
//#define MINIUPNPC_API_VERSION -3
|
||||
#ifndef MINIUPNPC_API_VERSION
|
||||
#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
|
||||
//2006/09/04 to 2007/10/01 => -7//Start return struct UPNPDev * for upnpDiscover
|
||||
//2007/10/16 => -6 upnpDiscover
|
||||
//2007/12/19 => -5 upnpDiscover
|
||||
//2008/09/25 => -4 upnpDiscover
|
||||
//2009/04/17 => -3 UPNP_AddPortMapping
|
||||
//2010/12/09 => -2 //struct IGDdatas_service CIF;
|
||||
//2011/02/15 => -1 UPNP_AddPortMapping
|
||||
//2011/03/14 => 6 //Start of MINIUPNPC_API_VERSION
|
||||
#endif//>=-7
|
||||
|
||||
/* Ensure linking names are okay on OSX platform. (C interface) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* protofix() checks if protocol is "UDP" or "TCP"
|
||||
* returns NULL if not */
|
||||
const char * protofix(const char * proto);
|
||||
void DisplayInfos(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data);
|
||||
|
||||
void GetConnectionStatus(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data);
|
||||
|
||||
void ListRedirections(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data);
|
||||
|
||||
int SetRedirectAndTest(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * iaddr,
|
||||
const char * iport,
|
||||
const char * eport,
|
||||
const char * proto,
|
||||
const char *leaseDuration,
|
||||
const char *description,
|
||||
int addAny);
|
||||
|
||||
int TestRedirect(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * iaddr,
|
||||
const char * iport,
|
||||
const char * eport,
|
||||
const char * proto);
|
||||
|
||||
int RemoveRedirect(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * eport,
|
||||
const char * proto);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue