├── .travis.yml ├── CMakeLists.txt ├── README.md ├── include ├── libupnp │ ├── bsdqueue.h │ ├── codelength.h │ ├── connecthostport.h │ ├── declspec.h │ ├── igd_desc_parse.h │ ├── minisoap.h │ ├── minissdpc.h │ ├── miniupnpc.h │ ├── miniupnpctypes.h │ ├── miniwget.h │ ├── minixml.h │ ├── portlistingparse.h │ ├── receivedata.h │ ├── upnpcommands.h │ ├── upnperrors.h │ └── upnpreplyparse.h └── nat │ ├── maidsafe-dht_config.h │ ├── maidsafe_calllatertimer.h │ ├── maidsafe_gateway.h │ ├── maidsafe_network_interface.h │ ├── maidsafe_utils.h │ ├── miniupnpclientimpl.h │ ├── nat_tracker.h │ ├── natpmpclient.h │ ├── natpmpclientimpl.h │ ├── natpmpprotocol.h │ ├── upnpcfg.h │ ├── upnpclient.h │ └── upnpclientimpl.h ├── lib ├── CMakeLists.txt ├── libupnp │ ├── CMakeLists.txt │ ├── Changelog.txt │ ├── LICENSE │ ├── README │ ├── connecthostport.c │ ├── external-ip.sh │ ├── igd_desc_parse.c │ ├── minihttptestserver.c │ ├── minisoap.c │ ├── minissdpc.c │ ├── miniupnpc.c │ ├── miniupnpc.def │ ├── miniwget.c │ ├── minixml.c │ ├── portlistingparse.c │ ├── receivedata.c │ ├── upnpcommands.c │ ├── upnperrors.c │ └── upnpreplyparse.c ├── maidsafe_calllatertimer.cc ├── maidsafe_gateway.cc ├── maidsafe_network_interface.cc ├── maidsafe_utils.cc ├── miniupnpclientimpl.cc ├── natpmpclient.cc ├── natpmpclientimpl.cc ├── natpmpprotocol.cc ├── upnpclient.cc └── upnpclientimpl.cc └── tests ├── CMakeLists.txt ├── libupnp ├── CMakeLists.txt ├── minixmlvalid.c ├── testigddescparse.c ├── testminiwget.c ├── testminiwget.sh ├── testminixml.c ├── testupnpreplyparse.c └── upnpc.c ├── test_natpmp.cpp └── test_upnp.cpp /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: clang 3 | cache: apt 4 | before_install: 5 | - ./travis-ci/travis_install_packages.sh 6 | - ./travis-ci/travis_build_ninja.sh 7 | - ./travis-ci/travis_build_libcxx.sh 8 | - ./travis-ci/travis_build_boost.sh 9 | script: CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -G "Ninja" -DTRAVIS_CI=YES -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=YES . && ninja && ctest -V 10 | notifications: 11 | email: false 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | if (NOT BUILD_IN_UVVY) 4 | include(cmake/setup.cmake) 5 | include_directories(3rdparty/endian 3rdparty/arsenal/include) 6 | add_subdirectory(3rdparty/arsenal/lib) 7 | endif() 8 | 9 | include_directories(include) 10 | add_subdirectory(lib) 11 | 12 | if (BUILD_TESTING) 13 | add_subdirectory(tests) 14 | endif (BUILD_TESTING) 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Libraries for NAT traversal and hole punching 2 | ============================================= 3 | 4 | Notes 5 | ===== 6 | 7 | - NAT relaying (using accessible server S to forward packets between A and B) - TURN protocol 8 | - Connection reversal (via server S, but while only one of A, B is behind NAT) 9 | - UDP Hole punching (via server S) 10 | - hairpin (loopback) translation? 11 | 12 | Relevant documents 13 | ================== 14 | 15 | * [NAT-PMP RFC](http://tools.ietf.org/html/rfc6886) 16 | * [Port Control Protocol](http://tools.ietf.org/html/rfc6887) 17 | * [UPnP](http://www.upnp.org/) 18 | 19 | Relevant libraries 20 | ================== 21 | 22 | * [miniupnpc](https://github.com/miniupnp/miniupnp/tree/master/miniupnpc) 23 | * [libnatpmp](http://thebends.googlecode.com/svn/trunk/nat/pmp) 24 | * upnp based on upnp implementation in [ktorrent](http://ktorrent.sourceforce.net) 25 | * [pupnp](http://pupnp.sourceforge.net) (BSD License) latest update Apr 2012, first code 2005 26 | * http://www.keymolen.com/ssdp.html C++ SSDP library, non-OSS 27 | * https://code.google.com/p/upnpx/ objc/C++ upnp and ssdp lib, BSD License, based on pupnp, abandoned Nov 2012 28 | * [reTurn C++ asio BSD STUN and TURN library](http://www.resiprocate.org/ReTurn_Overview) 29 | * [nat-pmp and upnp implementation in maidsafe](https://code.google.com/p/maidsafe-dht/source/browse/trunk/src/maidsafe/nat-pmp/natpmpclient.h) 2009 30 | -------------------------------------------------------------------------------- /include/libupnp/codelength.h: -------------------------------------------------------------------------------- 1 | /* $Id: codelength.h,v 1.3 2011/07/30 13:10:05 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * Author : Thomas BERNARD 4 | * copyright (c) 2005-2011 Thomas Bernard 5 | * This software is subjet to the conditions detailed in the 6 | * provided LICENCE file. */ 7 | #ifndef CODELENGTH_H_INCLUDED 8 | #define CODELENGTH_H_INCLUDED 9 | 10 | /* Encode length by using 7bit per Byte : 11 | * Most significant bit of each byte specifies that the 12 | * following byte is part of the code */ 13 | #define DECODELENGTH(n, p) n = 0; \ 14 | do { n = (n << 7) | (*p & 0x7f); } \ 15 | while((*(p++)&0x80) && (n<(1<<25))); 16 | 17 | #define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ 18 | n = 0; \ 19 | do { \ 20 | if((p) >= (p_limit)) break; \ 21 | n = (n << 7) | (*(p) & 0x7f); \ 22 | } while((*((p)++)&0x80) && (n<(1<<25))); 23 | 24 | #define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ 25 | if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ 26 | if(n>=16384) *(p++) = (n >> 14) | 0x80; \ 27 | if(n>=128) *(p++) = (n >> 7) | 0x80; \ 28 | *(p++) = n & 0x7f; 29 | 30 | #endif 31 | 32 | -------------------------------------------------------------------------------- /include/libupnp/connecthostport.h: -------------------------------------------------------------------------------- 1 | /* $Id: connecthostport.h,v 1.2 2012/06/23 22:32:33 nanard Exp $ */ 2 | /* Project: miniupnp 3 | * http://miniupnp.free.fr/ 4 | * Author: Thomas Bernard 5 | * Copyright (c) 2010-2012 Thomas Bernard 6 | * This software is subjects to the conditions detailed 7 | * in the LICENCE file provided within this distribution */ 8 | #ifndef CONNECTHOSTPORT_H_INCLUDED 9 | #define CONNECTHOSTPORT_H_INCLUDED 10 | 11 | /* connecthostport() 12 | * return a socket connected (TCP) to the host and port 13 | * or -1 in case of error */ 14 | int connecthostport(const char * host, unsigned short port, 15 | unsigned int scope_id); 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /include/libupnp/declspec.h: -------------------------------------------------------------------------------- 1 | #ifndef DECLSPEC_H_INCLUDED 2 | #define DECLSPEC_H_INCLUDED 3 | 4 | #if defined(_WIN32) && !defined(STATICLIB) 5 | #ifdef MINIUPNP_EXPORTS 6 | #define LIBSPEC __declspec(dllexport) 7 | #else 8 | #define LIBSPEC __declspec(dllimport) 9 | #endif 10 | #else 11 | #define LIBSPEC 12 | #endif 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /include/libupnp/igd_desc_parse.h: -------------------------------------------------------------------------------- 1 | /* $Id: igd_desc_parse.h,v 1.10 2011/04/11 09:19:24 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * http://miniupnp.free.fr/ 4 | * Author : Thomas Bernard 5 | * Copyright (c) 2005-2010 Thomas Bernard 6 | * This software is subject to the conditions detailed in the 7 | * LICENCE file provided in this distribution. 8 | * */ 9 | #ifndef IGD_DESC_PARSE_H_INCLUDED 10 | #define IGD_DESC_PARSE_H_INCLUDED 11 | 12 | /* Structure to store the result of the parsing of UPnP 13 | * descriptions of Internet Gateway Devices */ 14 | #define MINIUPNPC_URL_MAXSIZE (128) 15 | struct IGDdatas_service { 16 | char controlurl[MINIUPNPC_URL_MAXSIZE]; 17 | char eventsuburl[MINIUPNPC_URL_MAXSIZE]; 18 | char scpdurl[MINIUPNPC_URL_MAXSIZE]; 19 | char servicetype[MINIUPNPC_URL_MAXSIZE]; 20 | /*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ 21 | }; 22 | 23 | struct IGDdatas { 24 | char cureltname[MINIUPNPC_URL_MAXSIZE]; 25 | char urlbase[MINIUPNPC_URL_MAXSIZE]; 26 | char presentationurl[MINIUPNPC_URL_MAXSIZE]; 27 | int level; 28 | /*int state;*/ 29 | /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ 30 | struct IGDdatas_service CIF; 31 | /* "urn:schemas-upnp-org:service:WANIPConnection:1" 32 | * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ 33 | struct IGDdatas_service first; 34 | /* if both WANIPConnection and WANPPPConnection are present */ 35 | struct IGDdatas_service second; 36 | /* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ 37 | struct IGDdatas_service IPv6FC; 38 | /* tmp */ 39 | struct IGDdatas_service tmp; 40 | }; 41 | 42 | void IGDstartelt(void *, const char *, int); 43 | void IGDendelt(void *, const char *, int); 44 | void IGDdata(void *, const char *, int); 45 | void printIGD(struct IGDdatas *); 46 | 47 | #endif 48 | 49 | -------------------------------------------------------------------------------- /include/libupnp/minisoap.h: -------------------------------------------------------------------------------- 1 | /* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * Author : Thomas Bernard 4 | * Copyright (c) 2005 Thomas Bernard 5 | * This software is subject to the conditions detailed in the 6 | * LICENCE file provided in this distribution. */ 7 | #ifndef MINISOAP_H_INCLUDED 8 | #define MINISOAP_H_INCLUDED 9 | 10 | /*int httpWrite(int, const char *, int, const char *);*/ 11 | int soapPostSubmit(int, const char *, const char *, unsigned short, 12 | const char *, const char *, const char *); 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /include/libupnp/minissdpc.h: -------------------------------------------------------------------------------- 1 | /* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 nanard Exp $ */ 2 | /* Project: miniupnp 3 | * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 4 | * Author: Thomas Bernard 5 | * Copyright (c) 2005-2007 Thomas Bernard 6 | * This software is subjects to the conditions detailed 7 | * in the LICENCE file provided within this distribution */ 8 | #ifndef MINISSDPC_H_INCLUDED 9 | #define MINISSDPC_H_INCLUDED 10 | 11 | struct UPNPDev * 12 | getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath); 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /include/libupnp/miniupnpc.h: -------------------------------------------------------------------------------- 1 | /* $Id: miniupnpc.h,v 1.30 2012/06/28 18:52:12 nanard Exp $ */ 2 | /* Project: miniupnp 3 | * http://miniupnp.free.fr/ 4 | * Author: Thomas Bernard 5 | * Copyright (c) 2005-2012 Thomas Bernard 6 | * This software is subjects to the conditions detailed 7 | * in the LICENCE file provided within this distribution */ 8 | #ifndef MINIUPNPC_H_INCLUDED 9 | #define MINIUPNPC_H_INCLUDED 10 | 11 | #include "declspec.h" 12 | #include "igd_desc_parse.h" 13 | 14 | /* error codes : */ 15 | #define UPNPDISCOVER_SUCCESS (0) 16 | #define UPNPDISCOVER_UNKNOWN_ERROR (-1) 17 | #define UPNPDISCOVER_SOCKET_ERROR (-101) 18 | #define UPNPDISCOVER_MEMORY_ERROR (-102) 19 | 20 | /* versions : */ 21 | #define MINIUPNPC_VERSION "1.7" 22 | #define MINIUPNPC_API_VERSION 9 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Structures definitions : */ 29 | struct UPNParg { const char * elt; const char * val; }; 30 | 31 | char * 32 | simpleUPnPcommand(int, const char *, const char *, 33 | const char *, struct UPNParg *, 34 | int *); 35 | 36 | struct UPNPDev { 37 | struct UPNPDev * pNext; 38 | char * descURL; 39 | char * st; 40 | unsigned int scope_id; 41 | char buffer[2]; 42 | }; 43 | 44 | /* upnpDiscover() 45 | * discover UPnP devices on the network. 46 | * The discovered devices are returned as a chained list. 47 | * It is up to the caller to free the list with freeUPNPDevlist(). 48 | * delay (in millisecond) is the maximum time for waiting any device 49 | * response. 50 | * If available, device list will be obtained from MiniSSDPd. 51 | * Default path for minissdpd socket will be used if minissdpdsock argument 52 | * is NULL. 53 | * If multicastif is not NULL, it will be used instead of the default 54 | * multicast interface for sending SSDP discover packets. 55 | * If sameport is not null, SSDP packets will be sent from the source port 56 | * 1900 (same as destination port) otherwise system assign a source port. */ 57 | LIBSPEC struct UPNPDev * 58 | upnpDiscover(int delay, const char * multicastif, 59 | const char * minissdpdsock, int sameport, 60 | int ipv6, 61 | int * error); 62 | /* freeUPNPDevlist() 63 | * free list returned by upnpDiscover() */ 64 | LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist); 65 | 66 | /* parserootdesc() : 67 | * parse root XML description of a UPnP device and fill the IGDdatas 68 | * structure. */ 69 | LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *); 70 | 71 | /* structure used to get fast access to urls 72 | * controlURL: controlURL of the WANIPConnection 73 | * ipcondescURL: url of the description of the WANIPConnection 74 | * controlURL_CIF: controlURL of the WANCommonInterfaceConfig 75 | * controlURL_6FC: controlURL of the WANIPv6FirewallControl 76 | */ 77 | struct UPNPUrls { 78 | char * controlURL; 79 | char * ipcondescURL; 80 | char * controlURL_CIF; 81 | char * controlURL_6FC; 82 | char * rootdescURL; 83 | }; 84 | 85 | /* UPNP_GetValidIGD() : 86 | * return values : 87 | * 0 = NO IGD found 88 | * 1 = A valid connected IGD has been found 89 | * 2 = A valid IGD has been found but it reported as 90 | * not connected 91 | * 3 = an UPnP device has been found but was not recognized as an IGD 92 | * 93 | * In any non zero return case, the urls and data structures 94 | * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to 95 | * free allocated memory. 96 | */ 97 | LIBSPEC int 98 | UPNP_GetValidIGD(struct UPNPDev * devlist, 99 | struct UPNPUrls * urls, 100 | struct IGDdatas * data, 101 | char * lanaddr, int lanaddrlen); 102 | 103 | /* UPNP_GetIGDFromUrl() 104 | * Used when skipping the discovery process. 105 | * return value : 106 | * 0 - Not ok 107 | * 1 - OK */ 108 | LIBSPEC int 109 | UPNP_GetIGDFromUrl(const char * rootdescurl, 110 | struct UPNPUrls * urls, 111 | struct IGDdatas * data, 112 | char * lanaddr, int lanaddrlen); 113 | 114 | LIBSPEC void 115 | GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, 116 | const char *, unsigned int); 117 | 118 | LIBSPEC void 119 | FreeUPNPUrls(struct UPNPUrls *); 120 | 121 | /* return 0 or 1 */ 122 | LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); 123 | 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | #endif 130 | 131 | -------------------------------------------------------------------------------- /include/libupnp/miniupnpctypes.h: -------------------------------------------------------------------------------- 1 | /* $Id: miniupnpctypes.h,v 1.1 2011/02/15 11:10:40 nanard Exp $ */ 2 | /* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org 3 | * Author : Thomas Bernard 4 | * Copyright (c) 2011 Thomas Bernard 5 | * This software is subject to the conditions detailed in the 6 | * LICENCE file provided within this distribution */ 7 | #ifndef MINIUPNPCTYPES_H_INCLUDED 8 | #define MINIUPNPCTYPES_H_INCLUDED 9 | 10 | #if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) 11 | #define UNSIGNED_INTEGER unsigned long long 12 | #define STRTOUI strtoull 13 | #else 14 | #define UNSIGNED_INTEGER unsigned int 15 | #define STRTOUI strtoul 16 | #endif 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /include/libupnp/miniwget.h: -------------------------------------------------------------------------------- 1 | /* $Id: miniwget.h,v 1.7 2012/06/23 22:35:59 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * Author : Thomas Bernard 4 | * Copyright (c) 2005-2012 Thomas Bernard 5 | * This software is subject to the conditions detailed in the 6 | * LICENCE file provided in this distribution. 7 | * */ 8 | #ifndef MINIWGET_H_INCLUDED 9 | #define MINIWGET_H_INCLUDED 10 | 11 | #include "declspec.h" 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | LIBSPEC void * getHTTPResponse(int s, int * size); 18 | 19 | LIBSPEC void * miniwget(const char *, int *, unsigned int); 20 | 21 | LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int); 22 | 23 | int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /include/libupnp/minixml.h: -------------------------------------------------------------------------------- 1 | /* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */ 2 | /* minimal xml parser 3 | * 4 | * Project : miniupnp 5 | * Website : http://miniupnp.free.fr/ 6 | * Author : Thomas Bernard 7 | * Copyright (c) 2005 Thomas Bernard 8 | * This software is subject to the conditions detailed in the 9 | * LICENCE file provided in this distribution. 10 | * */ 11 | #ifndef MINIXML_H_INCLUDED 12 | #define MINIXML_H_INCLUDED 13 | #define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) 14 | 15 | /* if a callback function pointer is set to NULL, 16 | * the function is not called */ 17 | struct xmlparser { 18 | const char *xmlstart; 19 | const char *xmlend; 20 | const char *xml; /* pointer to current character */ 21 | int xmlsize; 22 | void * data; 23 | void (*starteltfunc) (void *, const char *, int); 24 | void (*endeltfunc) (void *, const char *, int); 25 | void (*datafunc) (void *, const char *, int); 26 | void (*attfunc) (void *, const char *, int, const char *, int); 27 | }; 28 | 29 | /* parsexml() 30 | * the xmlparser structure must be initialized before the call 31 | * the following structure members have to be initialized : 32 | * xmlstart, xmlsize, data, *func 33 | * xml is for internal usage, xmlend is computed automatically */ 34 | void parsexml(struct xmlparser *); 35 | 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /include/libupnp/portlistingparse.h: -------------------------------------------------------------------------------- 1 | /* $Id: portlistingparse.h,v 1.5 2012/01/21 13:30:33 nanard Exp $ */ 2 | /* MiniUPnP project 3 | * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 4 | * (c) 2011-2012 Thomas Bernard 5 | * This software is subject to the conditions detailed 6 | * in the LICENCE file provided within the distribution */ 7 | #ifndef PORTLISTINGPARSE_H_INCLUDED 8 | #define PORTLISTINGPARSE_H_INCLUDED 9 | 10 | #include "declspec.h" 11 | /* for the definition of UNSIGNED_INTEGER */ 12 | #include "miniupnpctypes.h" 13 | 14 | #if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__) 15 | #include "bsdqueue.h" 16 | #else 17 | #include 18 | #endif 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /* sample of PortMappingEntry : 25 | 26 | 202.233.2.1 27 | 2345 28 | TCP 29 | 2345 30 | 192.168.1.137 31 | 1 32 | dooom 33 | 345 34 | 35 | */ 36 | typedef enum { PortMappingEltNone, 37 | PortMappingEntry, NewRemoteHost, 38 | NewExternalPort, NewProtocol, 39 | NewInternalPort, NewInternalClient, 40 | NewEnabled, NewDescription, 41 | NewLeaseTime } portMappingElt; 42 | 43 | struct PortMapping { 44 | LIST_ENTRY(PortMapping) entries; 45 | UNSIGNED_INTEGER leaseTime; 46 | unsigned short externalPort; 47 | unsigned short internalPort; 48 | char remoteHost[64]; 49 | char internalClient[64]; 50 | char description[64]; 51 | char protocol[4]; 52 | unsigned char enabled; 53 | }; 54 | 55 | struct PortMappingParserData { 56 | LIST_HEAD(portmappinglisthead, PortMapping) head; 57 | portMappingElt curelt; 58 | }; 59 | 60 | LIBSPEC void 61 | ParsePortListing(const char * buffer, int bufsize, 62 | struct PortMappingParserData * pdata); 63 | 64 | LIBSPEC void 65 | FreePortListing(struct PortMappingParserData * pdata); 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /include/libupnp/receivedata.h: -------------------------------------------------------------------------------- 1 | /* $Id: receivedata.h,v 1.3 2012/06/23 22:34:47 nanard Exp $ */ 2 | /* Project: miniupnp 3 | * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 4 | * Author: Thomas Bernard 5 | * Copyright (c) 2011-2012 Thomas Bernard 6 | * This software is subjects to the conditions detailed 7 | * in the LICENCE file provided within this distribution */ 8 | #ifndef RECEIVEDATA_H_INCLUDED 9 | #define RECEIVEDATA_H_INCLUDED 10 | 11 | /* Reads data from the specified socket. 12 | * Returns the number of bytes read if successful, zero if no bytes were 13 | * read or if we timed out. Returns negative if there was an error. */ 14 | int receivedata(int socket, 15 | char * data, int length, 16 | int timeout, unsigned int * scope_id); 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /include/libupnp/upnpcommands.h: -------------------------------------------------------------------------------- 1 | /* $Id: upnpcommands.h,v 1.23 2011/04/11 09:14:00 nanard Exp $ */ 2 | /* Miniupnp project : http://miniupnp.free.fr/ 3 | * Author : Thomas Bernard 4 | * Copyright (c) 2005-2011 Thomas Bernard 5 | * This software is subject to the conditions detailed in the 6 | * LICENCE file provided within this distribution */ 7 | #ifndef UPNPCOMMANDS_H_INCLUDED 8 | #define UPNPCOMMANDS_H_INCLUDED 9 | 10 | #include "upnpreplyparse.h" 11 | #include "portlistingparse.h" 12 | #include "declspec.h" 13 | #include "miniupnpctypes.h" 14 | 15 | /* MiniUPnPc return codes : */ 16 | #define UPNPCOMMAND_SUCCESS (0) 17 | #define UPNPCOMMAND_UNKNOWN_ERROR (-1) 18 | #define UPNPCOMMAND_INVALID_ARGS (-2) 19 | #define UPNPCOMMAND_HTTP_ERROR (-3) 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | LIBSPEC UNSIGNED_INTEGER 26 | UPNP_GetTotalBytesSent(const char * controlURL, 27 | const char * servicetype); 28 | 29 | LIBSPEC UNSIGNED_INTEGER 30 | UPNP_GetTotalBytesReceived(const char * controlURL, 31 | const char * servicetype); 32 | 33 | LIBSPEC UNSIGNED_INTEGER 34 | UPNP_GetTotalPacketsSent(const char * controlURL, 35 | const char * servicetype); 36 | 37 | LIBSPEC UNSIGNED_INTEGER 38 | UPNP_GetTotalPacketsReceived(const char * controlURL, 39 | const char * servicetype); 40 | 41 | /* UPNP_GetStatusInfo() 42 | * status and lastconnerror are 64 byte buffers 43 | * Return values : 44 | * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR 45 | * or a UPnP Error code */ 46 | LIBSPEC int 47 | UPNP_GetStatusInfo(const char * controlURL, 48 | const char * servicetype, 49 | char * status, 50 | unsigned int * uptime, 51 | char * lastconnerror); 52 | 53 | /* UPNP_GetConnectionTypeInfo() 54 | * argument connectionType is a 64 character buffer 55 | * Return Values : 56 | * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR 57 | * or a UPnP Error code */ 58 | LIBSPEC int 59 | UPNP_GetConnectionTypeInfo(const char * controlURL, 60 | const char * servicetype, 61 | char * connectionType); 62 | 63 | /* UPNP_GetExternalIPAddress() call the corresponding UPNP method. 64 | * if the third arg is not null the value is copied to it. 65 | * at least 16 bytes must be available 66 | * 67 | * Return values : 68 | * 0 : SUCCESS 69 | * NON ZERO : ERROR Either an UPnP error code or an unknown error. 70 | * 71 | * possible UPnP Errors : 72 | * 402 Invalid Args - See UPnP Device Architecture section on Control. 73 | * 501 Action Failed - See UPnP Device Architecture section on Control. */ 74 | LIBSPEC int 75 | UPNP_GetExternalIPAddress(const char * controlURL, 76 | const char * servicetype, 77 | char * extIpAdd); 78 | 79 | /* UPNP_GetLinkLayerMaxBitRates() 80 | * call WANCommonInterfaceConfig:1#GetCommonLinkProperties 81 | * 82 | * return values : 83 | * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR 84 | * or a UPnP Error Code. */ 85 | LIBSPEC int 86 | UPNP_GetLinkLayerMaxBitRates(const char* controlURL, 87 | const char* servicetype, 88 | unsigned int * bitrateDown, 89 | unsigned int * bitrateUp); 90 | 91 | /* UPNP_AddPortMapping() 92 | * if desc is NULL, it will be defaulted to "libminiupnpc" 93 | * remoteHost is usually NULL because IGD don't support it. 94 | * 95 | * Return values : 96 | * 0 : SUCCESS 97 | * NON ZERO : ERROR. Either an UPnP error code or an unknown error. 98 | * 99 | * List of possible UPnP errors for AddPortMapping : 100 | * errorCode errorDescription (short) - Description (long) 101 | * 402 Invalid Args - See UPnP Device Architecture section on Control. 102 | * 501 Action Failed - See UPnP Device Architecture section on Control. 103 | * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be 104 | * wild-carded 105 | * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded 106 | * 718 ConflictInMappingEntry - The port mapping entry specified conflicts 107 | * with a mapping assigned previously to another client 108 | * 724 SamePortValuesRequired - Internal and External port values 109 | * must be the same 110 | * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports 111 | * permanent lease times on port mappings 112 | * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard 113 | * and cannot be a specific IP address or DNS name 114 | * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and 115 | * cannot be a specific port value */ 116 | LIBSPEC int 117 | UPNP_AddPortMapping(const char * controlURL, const char * servicetype, 118 | const char * extPort, 119 | const char * inPort, 120 | const char * inClient, 121 | const char * desc, 122 | const char * proto, 123 | const char * remoteHost, 124 | const char * leaseDuration); 125 | 126 | /* UPNP_DeletePortMapping() 127 | * Use same argument values as what was used for AddPortMapping(). 128 | * remoteHost is usually NULL because IGD don't support it. 129 | * Return Values : 130 | * 0 : SUCCESS 131 | * NON ZERO : error. Either an UPnP error code or an undefined error. 132 | * 133 | * List of possible UPnP errors for DeletePortMapping : 134 | * 402 Invalid Args - See UPnP Device Architecture section on Control. 135 | * 714 NoSuchEntryInArray - The specified value does not exist in the array */ 136 | LIBSPEC int 137 | UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, 138 | const char * extPort, const char * proto, 139 | const char * remoteHost); 140 | 141 | /* UPNP_GetPortMappingNumberOfEntries() 142 | * not supported by all routers */ 143 | LIBSPEC int 144 | UPNP_GetPortMappingNumberOfEntries(const char* controlURL, 145 | const char* servicetype, 146 | unsigned int * num); 147 | 148 | /* UPNP_GetSpecificPortMappingEntry() 149 | * retrieves an existing port mapping 150 | * params : 151 | * in extPort 152 | * in proto 153 | * out intClient (16 bytes) 154 | * out intPort (6 bytes) 155 | * out desc (80 bytes) 156 | * out enabled (4 bytes) 157 | * out leaseDuration (16 bytes) 158 | * 159 | * return value : 160 | * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR 161 | * or a UPnP Error Code. */ 162 | LIBSPEC int 163 | UPNP_GetSpecificPortMappingEntry(const char * controlURL, 164 | const char * servicetype, 165 | const char * extPort, 166 | const char * proto, 167 | char * intClient, 168 | char * intPort, 169 | char * desc, 170 | char * enabled, 171 | char * leaseDuration); 172 | 173 | /* UPNP_GetGenericPortMappingEntry() 174 | * params : 175 | * in index 176 | * out extPort (6 bytes) 177 | * out intClient (16 bytes) 178 | * out intPort (6 bytes) 179 | * out protocol (4 bytes) 180 | * out desc (80 bytes) 181 | * out enabled (4 bytes) 182 | * out rHost (64 bytes) 183 | * out duration (16 bytes) 184 | * 185 | * return value : 186 | * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR 187 | * or a UPnP Error Code. 188 | * 189 | * Possible UPNP Error codes : 190 | * 402 Invalid Args - See UPnP Device Architecture section on Control. 191 | * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds 192 | */ 193 | LIBSPEC int 194 | UPNP_GetGenericPortMappingEntry(const char * controlURL, 195 | const char * servicetype, 196 | const char * index, 197 | char * extPort, 198 | char * intClient, 199 | char * intPort, 200 | char * protocol, 201 | char * desc, 202 | char * enabled, 203 | char * rHost, 204 | char * duration); 205 | 206 | /* UPNP_GetListOfPortMappings() Available in IGD v2 207 | * 208 | * 209 | * Possible UPNP Error codes : 210 | * 606 Action not Authorized 211 | * 730 PortMappingNotFound - no port mapping is found in the specified range. 212 | * 733 InconsistantParameters - NewStartPort and NewEndPort values are not 213 | * consistent. 214 | */ 215 | LIBSPEC int 216 | UPNP_GetListOfPortMappings(const char * controlURL, 217 | const char * servicetype, 218 | const char * startPort, 219 | const char * endPort, 220 | const char * protocol, 221 | const char * numberOfPorts, 222 | struct PortMappingParserData * data); 223 | 224 | /* IGD:2, functions for service WANIPv6FirewallControl:1 */ 225 | LIBSPEC int 226 | UPNP_GetFirewallStatus(const char * controlURL, 227 | const char * servicetype, 228 | int * firewallEnabled, 229 | int * inboundPinholeAllowed); 230 | 231 | LIBSPEC int 232 | UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, 233 | const char * remoteHost, 234 | const char * remotePort, 235 | const char * intClient, 236 | const char * intPort, 237 | const char * proto, 238 | int * opTimeout); 239 | 240 | LIBSPEC int 241 | UPNP_AddPinhole(const char * controlURL, const char * servicetype, 242 | const char * remoteHost, 243 | const char * remotePort, 244 | const char * intClient, 245 | const char * intPort, 246 | const char * proto, 247 | const char * leaseTime, 248 | char * uniqueID); 249 | 250 | LIBSPEC int 251 | UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, 252 | const char * uniqueID, 253 | const char * leaseTime); 254 | 255 | LIBSPEC int 256 | UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID); 257 | 258 | LIBSPEC int 259 | UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, 260 | const char * uniqueID, int * isWorking); 261 | 262 | LIBSPEC int 263 | UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, 264 | const char * uniqueID, int * packets); 265 | 266 | #ifdef __cplusplus 267 | } 268 | #endif 269 | 270 | #endif 271 | 272 | -------------------------------------------------------------------------------- /include/libupnp/upnperrors.h: -------------------------------------------------------------------------------- 1 | /* $Id: upnperrors.h,v 1.2 2008/07/02 23:31:15 nanard Exp $ */ 2 | /* (c) 2007 Thomas Bernard 3 | * All rights reserved. 4 | * MiniUPnP Project. 5 | * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 6 | * This software is subjet to the conditions detailed in the 7 | * provided LICENCE file. */ 8 | #ifndef UPNPERRORS_H_INCLUDED 9 | #define UPNPERRORS_H_INCLUDED 10 | 11 | #include "declspec.h" 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /* strupnperror() 18 | * Return a string description of the UPnP error code 19 | * or NULL for undefinded errors */ 20 | LIBSPEC const char * strupnperror(int err); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /include/libupnp/upnpreplyparse.h: -------------------------------------------------------------------------------- 1 | /* $Id: upnpreplyparse.h,v 1.12 2012/01/21 13:30:33 nanard Exp $ */ 2 | /* MiniUPnP project 3 | * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 4 | * (c) 2006-2012 Thomas Bernard 5 | * This software is subject to the conditions detailed 6 | * in the LICENCE file provided within the distribution */ 7 | 8 | #ifndef UPNPREPLYPARSE_H_INCLUDED 9 | #define UPNPREPLYPARSE_H_INCLUDED 10 | 11 | #if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__) 12 | #include "bsdqueue.h" 13 | #else 14 | #include 15 | #endif 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | struct NameValue { 22 | LIST_ENTRY(NameValue) entries; 23 | char name[64]; 24 | char value[64]; 25 | }; 26 | 27 | struct NameValueParserData { 28 | LIST_HEAD(listhead, NameValue) head; 29 | char curelt[64]; 30 | char * portListing; 31 | int portListingLength; 32 | }; 33 | 34 | /* ParseNameValue() */ 35 | void 36 | ParseNameValue(const char * buffer, int bufsize, 37 | struct NameValueParserData * data); 38 | 39 | /* ClearNameValueList() */ 40 | void 41 | ClearNameValueList(struct NameValueParserData * pdata); 42 | 43 | /* GetValueFromNameValueList() */ 44 | char * 45 | GetValueFromNameValueList(struct NameValueParserData * pdata, 46 | const char * Name); 47 | 48 | /* GetValueFromNameValueListIgnoreNS() */ 49 | char * 50 | GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, 51 | const char * Name); 52 | 53 | /* DisplayNameValueList() */ 54 | #ifdef DEBUG 55 | void 56 | DisplayNameValueList(char * buffer, int bufsize); 57 | #endif 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif 64 | 65 | -------------------------------------------------------------------------------- /include/nat/maidsafe-dht_config.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | 29 | /******************************************************************************* 30 | * This file defines all main constants and enums used by the library. * 31 | * * 32 | * NOTE: This file is unlikely to have any breaking changes applied. However, * 33 | * it should not be regarded as final until this notice is removed. * 34 | ******************************************************************************/ 35 | #pragma once 36 | 37 | 38 | /******************************************************************************* 39 | * maidsafe-dht Version * 40 | ******************************************************************************/ 41 | #define MAIDSAFE_DHT_VERSION 24 42 | 43 | 44 | /******************************************************************************* 45 | * Platform detection and platform-specific includes * 46 | ******************************************************************************/ 47 | #if defined(linux) || defined(__linux) || defined(__linux__) || \ 48 | defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ 49 | defined(__DragonFly__) || defined(sun) || defined(__sun) || \ 50 | defined(__sgi) || defined(__hpux) || defined(__BEOS__) || \ 51 | defined(__IBMCPP__) || defined(_AIX) || defined(__QNXNTO__) || \ 52 | defined(unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) 53 | #ifndef MAIDSAFE_POSIX 54 | #define MAIDSAFE_POSIX 55 | #endif 56 | 57 | #elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || \ 58 | defined(_WIN32_WINNT) || defined(NTDDI_VERSION) || \ 59 | defined(_WIN32_WINDOWS) || defined(__MINGW__) 60 | #ifndef MAIDSAFE_WIN32 61 | #define MAIDSAFE_WIN32 62 | #endif 63 | #include 64 | #include 65 | #include 66 | 67 | #elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) 68 | #ifndef MAIDSAFE_APPLE 69 | #define MAIDSAFE_APPLE 70 | #endif 71 | #endif 72 | 73 | 74 | #ifndef MAIDSAFE_WIN32 75 | #include 76 | #include 77 | #include // must be before ifaddrs.h 78 | #include 79 | #include // included in apple's net/route.h 80 | #include // included in apple's net/route.h 81 | #include // used for implementation of LocalIPPort() 82 | #endif 83 | 84 | #include 85 | #include 86 | #include 87 | 88 | 89 | 90 | /******************************************************************************* 91 | * Kademlia Layer * 92 | ******************************************************************************/ 93 | namespace kad { 94 | 95 | // Functor for general callback functions. 96 | typedef boost::function VoidFunctorOneString; 97 | 98 | enum KBucketExitCode { SUCCEED, FULL, FAIL }; 99 | 100 | // DIRECT_CONNECTED - node is directly connected to the internet, IP is an 101 | // external IP or port has been manually mapped or port 102 | // mapped with UPnP 103 | // RESTRICTED - node is behind a port or address restricted NAT, has to be 104 | // contacted with its rendezvous server 105 | // NONE - node is behind a symmetric NAT and can not be contacted without it 106 | // making the first contact and keeping the connection open 107 | enum NatType { DIRECT_CONNECTED, RESTRICTED, NONE }; 108 | 109 | // CLIENT - does not map external ip and port, is not stored in other nodes 110 | // routing table 111 | // CLIENT_PORT_MAPPED - maps external ip and port, is not stored in other nodes 112 | // routing table 113 | // VAULT - maps external ip and port, complete functionality of a kademlia node 114 | enum NodeType { CLIENT, CLIENT_PORT_MAPPED, VAULT }; 115 | 116 | enum ConnectionType { LOCAL, REMOTE, UNKNOWN }; 117 | 118 | // The size of DHT keys and node IDs in bytes. 119 | const boost::uint16_t kKeySizeBytes = 64; 120 | 121 | // The parallel level of search iterations. 122 | const boost::uint16_t kAlpha = 3; 123 | 124 | // The number of replies required in a search iteration to allow the next 125 | // iteration to begin. 126 | const boost::uint16_t kBeta = 1; 127 | 128 | // The frequency (in seconds) of the refresh routine. 129 | const boost::uint32_t kRefreshTime = 3600; // 1 hour 130 | 131 | // The frequency (in seconds) of the republish routine. 132 | const boost::uint32_t kRepublishTime = 43200; // 12 hours 133 | 134 | // The duration (in seconds) after which a given is deleted locally. 135 | const boost::uint32_t kExpireTime = kRepublishTime + kRefreshTime + 300; 136 | 137 | // RPC result constants. 138 | const std::string kRpcResultSuccess("T"); 139 | const std::string kRpcResultFailure("F"); 140 | // TODO(Fraser#5#): 2009-05-15 - Make these bools 141 | 142 | // The ratio of k successful individual kad store RPCs to yield overall success. 143 | const double kMinSuccessfulPecentageStore = 0.75; 144 | 145 | // The number of failed RPCs tolerated before a contact is removed from the 146 | // k-bucket. 147 | const boost::uint16_t kFailedRpc = 0; 148 | 149 | // The maximum number of bootstrap contacts allowed in the .kadconfig file. 150 | const boost::uint32_t kMaxBootstrapContacts = 10000; 151 | 152 | // Signature used to sign anonymous RPC requests. 153 | const std::string kAnonymousSignedRequest(2 * kKeySizeBytes, 'f'); 154 | 155 | } // namespace kad 156 | 157 | 158 | /******************************************************************************* 159 | * RPC Layer * 160 | ******************************************************************************/ 161 | namespace rpcprotocol { 162 | 163 | // Maximum port number. 164 | const boost::uint16_t kMaxPort = 65535; 165 | 166 | // Minimum port number. 167 | const boost::uint16_t kMinPort = 5000; 168 | 169 | // RPC timeout duration (in milliseconds). 170 | const boost::uint32_t kRpcTimeout = 10000; 171 | 172 | // RPC result constants. 173 | const std::string kStartTransportSuccess("T"); 174 | const std::string kStartTransportFailure("F"); 175 | // TODO(Fraser#5#): 2009-05-16 - Make these bools 176 | 177 | // RPC Error Messages 178 | const std::string kTimeOut("T"); 179 | const std::string kCancelled("C"); 180 | 181 | } // namespace rpcprotocol 182 | 183 | 184 | /******************************************************************************* 185 | * Transport Layer * 186 | ******************************************************************************/ 187 | namespace transport { 188 | 189 | enum TransportType { kUdt, kTcp, kOther }; 190 | 191 | } // namespace transport 192 | -------------------------------------------------------------------------------- /include/nat/maidsafe_calllatertimer.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #pragma once 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | namespace base { 41 | 42 | typedef std::function VoidFunctorEmpty; 43 | 44 | struct CallLaterMap { 45 | CallLaterMap() : time_to_execute(0), callback(), call_later_id(0) {} 46 | uint64_t time_to_execute; 47 | VoidFunctorEmpty callback; 48 | uint32_t call_later_id; 49 | }; 50 | 51 | class CallLaterTimer { 52 | public: 53 | typedef std::map > TimersMap; 55 | CallLaterTimer(); 56 | ~CallLaterTimer(); 57 | inline bool IsStarted() { return is_started_; } 58 | int CancelAll(); 59 | bool CancelOne(const uint32_t &call_later_id); 60 | size_t TimersMapSize(); 61 | // Delay msecs milliseconds to call the function specified by callback 62 | uint32_t AddCallLater(const uint64_t &msecs, 63 | VoidFunctorEmpty callback); 64 | private: 65 | void Run(); 66 | void ExecuteFunctor(const VoidFunctorEmpty &callback, 67 | const uint32_t &call_later_id, 68 | const boost::system::error_code &ec); 69 | CallLaterTimer(const CallLaterTimer&); 70 | CallLaterTimer& operator=(const CallLaterTimer&); 71 | std::mutex timers_mutex_; 72 | bool is_started_; 73 | TimersMap timers_; 74 | boost::asio::io_service io_service_; 75 | boost::asio::strand strand_; 76 | std::shared_ptr work_; 77 | std::shared_ptr worker_thread_; 78 | uint32_t call_later_id_; 79 | }; 80 | 81 | } // namespace base 82 | -------------------------------------------------------------------------------- /include/nat/maidsafe_gateway.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | Created by Julian Cain on 11/3/09. 28 | 29 | */ 30 | #pragma once 31 | 32 | #include 33 | #include 34 | #include "maidsafe-dht_config.h" 35 | #include "maidsafe_network_interface.h" 36 | 37 | #if (defined(MAIDSAFE_APPLE) || defined(MAIDSAFE_POSIX) || defined(__MACH__)) \ 38 | && !defined(MAIDSAFE_LINUX) 39 | struct rt_msghdr; 40 | #elif defined(MAIDSAFE_LINUX) 41 | struct nlmsghdr; 42 | #endif 43 | 44 | namespace base { 45 | 46 | class Gateway { 47 | public: 48 | 49 | /** 50 | * Returns the default gateway address. 51 | * @param ios 52 | * @param ec 53 | */ 54 | static boost::asio::ip::address DefaultRoute(boost::asio::io_service & ios, 55 | boost::system::error_code & ec); 56 | 57 | private: 58 | 59 | /** 60 | * Enumerates and returns ip routes. 61 | */ 62 | static std::vector Routes(boost::asio::io_service & ios, 63 | boost::system::error_code & ec); 64 | 65 | protected: 66 | 67 | #if (defined(MAIDSAFE_APPLE) || defined(MAIDSAFE_POSIX) || defined(__MACH__)) \ 68 | && !defined(MAIDSAFE_LINUX) 69 | /** 70 | * Parse a rt_msghdr and assign it to rt_if. 71 | * @param rtm 72 | * @param rt_info 73 | */ 74 | static bool ParseRtMsghdr(rt_msghdr * rtm, NetworkInterface & rt_if); 75 | #elif defined(MAIDSAFE_LINUX) 76 | 77 | /** 78 | * Reads the netlink socket. 79 | * @param sock The socket to read. 80 | * @param buf The buffer. 81 | * @param len The len of buffer in bytes. 82 | * @param seq The sequence. 83 | * @param pid The process id. 84 | */ 85 | static int ReadNetlinkSock(int sock, char * buf, int len, int seq, int pid); 86 | 87 | /** 88 | * Parse a nlmsghdr and assign it to rt_if. 89 | * @param nl_hdr 90 | * @param rt_info 91 | */ 92 | static bool ParseNlmsghdr(nlmsghdr * nl_hdr, NetworkInterface & rt_if); 93 | #endif 94 | }; 95 | 96 | } // namespace base 97 | -------------------------------------------------------------------------------- /include/nat/maidsafe_network_interface.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | Created by Julian Cain on 11/3/09. 28 | 29 | */ 30 | #pragma once 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | namespace base { 37 | 38 | /** 39 | * Network interface utilities. 40 | */ 41 | struct NetworkInterface { 42 | NetworkInterface() : destination(), gateway(), netmask() {} 43 | /** 44 | * Determines if the given ip address is local. 45 | * @param addr The ip address to check. 46 | */ 47 | static bool IsLocal(const boost::asio::ip::address & addr); 48 | 49 | /** 50 | * Determines if the given ip address is loopback. 51 | * @param addr The ip address to check. 52 | */ 53 | static bool IsLoopback(const boost::asio::ip::address & addr); 54 | 55 | /** 56 | * Determines if the given ip address is multicast. 57 | * @param addr The ip address to check. 58 | */ 59 | static bool IsMulticast(const boost::asio::ip::address & addr); 60 | 61 | /** 62 | * Determines if the given ip address is any. 63 | * @param addr The ip address to check. 64 | */ 65 | static bool IsAny(const boost::asio::ip::address & addr); 66 | 67 | /** 68 | * Takes an in_addr structure and returns a boost::asio::ip::address 69 | * object. 70 | * @param addr The in_addr struct to convert. 71 | */ 72 | static boost::asio::ip::address InaddrToAddress(const in_addr * addr); 73 | 74 | /** 75 | * Takes an in6_addr structure and returns a boost::asio::ip::address 76 | * object. 77 | * @param addr The in6_addr struct to convert. 78 | */ 79 | static boost::asio::ip::address Inaddr6ToAddress(const in6_addr * addr); 80 | 81 | /** 82 | * Takes an sockaddr structure and returns a boost::asio::ip::address 83 | * object. 84 | * @param addr The sockaddr struct to convert. 85 | */ 86 | static boost::asio::ip::address SockaddrToAddress(const sockaddr * addr); 87 | 88 | /** 89 | * Returns all the network interfaces on the local system. 90 | * @return An std::vector of NetworkInterface objects, one per 91 | * physical or virtual network interface. 92 | */ 93 | static std::vector LocalList( 94 | boost::system::error_code & ec); 95 | 96 | /** 97 | * Returns the local ip address of the machine. 98 | * @note If the system is dualstack or multihomed this will return the 99 | * first valid network interface. Also this could be split into two 100 | * functions local_ipv4_address and local_ipv6_address respectively. 101 | */ 102 | static boost::asio::ip::address LocalAddress(); 103 | 104 | /** 105 | * The destination ip address. 106 | */ 107 | boost::asio::ip::address destination; 108 | 109 | /** 110 | * The gateway ip address. 111 | */ 112 | boost::asio::ip::address gateway; 113 | 114 | /** 115 | * The netmask of the network interface. 116 | */ 117 | boost::asio::ip::address netmask; 118 | 119 | /** 120 | * The string representation of the network interface. 121 | */ 122 | char name[64]; 123 | }; 124 | 125 | } // namespace base 126 | -------------------------------------------------------------------------------- /include/nat/maidsafe_utils.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /******************************************************************************* 29 | * NOTE: This header is unlikely to have any breaking changes applied. * 30 | * However, it should not be regarded as finalised until this notice is * 31 | * removed. * 32 | ******************************************************************************/ 33 | 34 | #pragma once 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "maidsafe-dht_config.h" 41 | 42 | 43 | namespace kad { 44 | class Contact; 45 | } // namespace kad 46 | 47 | 48 | namespace base { 49 | 50 | struct DeviceStruct { 51 | DeviceStruct() : ip_address(), device_interface() {} 52 | boost::asio::ip::address ip_address; 53 | std::string device_interface; 54 | }; 55 | 56 | /** 57 | * @class Stats 58 | * A simple class to determine statistical properties of a data set, computed 59 | * without storing the values. Data type must be numerical. 60 | */ 61 | template 62 | class Stats { 63 | public: 64 | Stats() : size_(0), min_(0), max_(0), sum_(0) {} 65 | /** 66 | * Add a datum to the data set. 67 | * @param value The data value. 68 | */ 69 | void Add(const T &value) { 70 | sum_ += value; 71 | ++size_; 72 | if (size_ == 1) { 73 | min_ = value; 74 | max_ = value; 75 | } else { 76 | if (value < min_) 77 | min_ = value; 78 | if (value > max_) 79 | max_ = value; 80 | } 81 | } 82 | /** 83 | * Get the size of the data set. 84 | * @return number of elements 85 | */ 86 | boost::uint64_t Size() const { return size_; } 87 | /** 88 | * Get the smallest value in the set. 89 | * @return minimum 90 | */ 91 | T Min() const { return min_; } 92 | /** 93 | * Get the biggest value in the set. 94 | * @return maximum 95 | */ 96 | T Max() const { return max_; } 97 | /** 98 | * Get the sum of values in the set. 99 | * @return sum 100 | */ 101 | T Sum() const { return sum_; } 102 | /** 103 | * Get the average of values in the set. 104 | * @return arithmetic mean 105 | */ 106 | T Mean() const { return size_ > 0 ? sum_ / size_ : 0; } 107 | private: 108 | boost::uint64_t size_; 109 | T min_; 110 | T max_; 111 | T sum_; 112 | }; 113 | 114 | // Generate a 32bit signed integer 115 | // Use this function if receiving it in a variable that is int or int32_t 116 | // or if before assinging to a signed int variable you are doing a modulo op 117 | boost::int32_t RandomInt32(); 118 | 119 | // Generate a 32bit unsigned integer 120 | // Use this one if receiving it in a variable that is unsigned int or uint32_t 121 | boost::uint32_t RandomUint32(); 122 | 123 | // Convert from int to string. 124 | std::string IntToString(const int &value); 125 | 126 | // Generate a random string. 127 | std::string RandomString(const size_t &length); 128 | 129 | // Generate a random string containing only alphanumeric characters. 130 | std::string RandomAlphaNumericString(const size_t &length); 131 | 132 | // Encode a string to hex. 133 | std::string EncodeToHex(const std::string &non_hex_input); 134 | 135 | // Encode a string to Base64. 136 | std::string EncodeToBase64(const std::string &non_base64_input); 137 | 138 | // Encode a string to Base32. 139 | std::string EncodeToBase32(const std::string &non_base32_input); 140 | 141 | // Decode a string from hex. 142 | std::string DecodeFromHex(const std::string &hex_input); 143 | 144 | // Decode a string from Base64. 145 | std::string DecodeFromBase64(const std::string &base64_input); 146 | 147 | // Decode a string from Base32. 148 | std::string DecodeFromBase32(const std::string &base32_input); 149 | 150 | // Return the number of seconds since 1st January 2000. 151 | boost::uint32_t GetEpochTime(); 152 | 153 | // Return the number of milliseconds since 1st January 2000. 154 | boost::uint64_t GetEpochMilliseconds(); 155 | 156 | // Return the number of nanoseconds since 1st January 2000. 157 | boost::uint64_t GetEpochNanoseconds(); 158 | 159 | // Convert an IP in ASCII format to IPv4 or IPv6 bytes 160 | std::string IpAsciiToBytes(const std::string &decimal_ip); 161 | 162 | // Convert an IPv4 or IPv6 in bytes format to ASCII format 163 | std::string IpBytesToAscii(const std::string &bytes_ip); 164 | 165 | // Convert an internet network address into dotted string format. 166 | void IpNetToAscii(boost::uint32_t address, char *ip_buffer); 167 | 168 | // Convert a dotted string format internet address into Ipv4 format. 169 | boost::uint32_t IpAsciiToNet(const char *buffer); 170 | 171 | // Return a list of network interfaces in the format of "address, adapter name". 172 | void GetNetInterfaces(std::vector *alldevices); 173 | 174 | // Return the first local network interface found. 175 | bool GetLocalAddress(boost::asio::ip::address *local_address); 176 | 177 | // Return all local addresses 178 | std::vector GetLocalAddresses(); 179 | 180 | // Generate a (transaction) id between 1 & 2147483646 inclusive. 181 | boost::uint32_t GenerateNextTransactionId(const boost::uint32_t &id); 182 | 183 | } // namespace base 184 | -------------------------------------------------------------------------------- /include/nat/miniupnpclientimpl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #pragma once 29 | 30 | // #define VERBOSE_DEBUG 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "upnpcfg.h" 37 | #include "libupnp/miniupnpc.h" 38 | #include "maidsafe_calllatertimer.h" 39 | 40 | namespace upnp { 41 | 42 | // control point for a UPnP Internet Gateway Device (miniupnp implementation) 43 | class UpnpIgdClientImpl { 44 | public: 45 | UpnpIgdClientImpl(); 46 | ~UpnpIgdClientImpl(); 47 | 48 | // returns true if the mapping functions use callbacks 49 | bool IsAsync(); 50 | // returns true if suitable services have been found 51 | bool HasServices(); 52 | 53 | // starts up the UPnP control point, including device discovery 54 | bool InitControlPoint(); 55 | 56 | // get a list of existing port mappings from the IGD 57 | bool GetPortMappings(std::list& out_mappings); 58 | 59 | // schedules a port mapping for registration with known and future services 60 | bool AddPortMapping(const PortMapping &mapping); 61 | // checks, if the given mapping exists in the internal list 62 | bool PortMappingExists(const int &port, const ProtocolType &protocol, 63 | std::list::iterator &it); 64 | // removes the mapping from the internal list and all known services 65 | bool DeletePortMapping(const int &port, const ProtocolType &protocol); 66 | // removes all mappings 67 | bool DeleteAllPortMappings(); 68 | 69 | // retrieves the external IP address from the device 70 | std::string GetExternalIpAddress(); 71 | 72 | // register a function to be called when a mapping has been successful 73 | void SetNewMappingCallback(const upnp_callback &) {} 74 | // register a function to be called when all instances of a mapping are gone 75 | void SetLostMappingCallback(const upnp_callback &) {} 76 | // register a function to be called when a mapping couldn't be set up 77 | void SetFailedMappingCallback(const upnp_callback &) {} 78 | 79 | private: 80 | UpnpIgdClientImpl(const UpnpIgdClientImpl&); 81 | UpnpIgdClientImpl& operator=(const UpnpIgdClientImpl&); 82 | 83 | void DiscoverDevices(); 84 | void RefreshCallback(); 85 | 86 | bool is_initialised_; 87 | bool has_services_; 88 | 89 | UPNPUrls upnp_urls_; 90 | IGDdatas igd_data_; 91 | std::list port_mappings_; 92 | base::CallLaterTimer timer_; 93 | }; 94 | 95 | } // namespace upnp 96 | -------------------------------------------------------------------------------- /include/nat/nat_tracker.h: -------------------------------------------------------------------------------- 1 | namespace uia 2 | namespace nat 3 | 4 | /** 5 | * This class keeps track of all gateways with NATs and opens, renews and closes port mappings 6 | * using a multitude of available and supported methods. 7 | */ 8 | class tracker 9 | { 10 | std::vector> nats_; 11 | //mappings_; // Track mappings with timeouts. 12 | }; 13 | -------------------------------------------------------------------------------- /include/nat/natpmpclient.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | Created by Julian Cain on 11/3/09. 28 | 29 | */ 30 | #pragma once 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include "natpmpclientimpl.h" 37 | 38 | namespace natpmp { 39 | 40 | /** 41 | * Implements a NAT-PMP client. 42 | */ 43 | class NatPmpClient { 44 | public: 45 | 46 | /** 47 | * Constructor 48 | * @param ios The boost::asio::io_service object to use. 49 | */ 50 | explicit NatPmpClient(boost::asio::io_service *ios) : io_service_(ios), 51 | impl_() {} 52 | 53 | /** 54 | * Destructor 55 | */ 56 | ~NatPmpClient() {} 57 | 58 | /** 59 | * Start the underlying subsystem. 60 | */ 61 | void Start(); 62 | 63 | /** 64 | * Stop the underlying subsystem. 65 | */ 66 | void Stop(); 67 | 68 | /** 69 | * Set the port map success callback. 70 | */ 71 | void SetMapPortSuccessCallback( 72 | const NatPmpMapPortSuccessCbType &map_port_success_cb); 73 | 74 | /** 75 | * Maps a private port to a public port of the given protocol and 76 | * lifetime. 77 | * @param protocol 78 | * @param private_port 79 | * @param public_port 80 | * @param lifetime 81 | */ 82 | void MapPort(boost::uint32_t protocol, 83 | boost::uint16_t private_port, 84 | boost::uint16_t public_port, 85 | boost::uint64_t lifetime); 86 | 87 | private: 88 | 89 | // ... 90 | /** 91 | * Copy constructor and equal operator. 92 | */ 93 | NatPmpClient(const NatPmpClient &natpnp_client); 94 | NatPmpClient &operator=(const NatPmpClient &natpnp_client); 95 | 96 | protected: 97 | 98 | /** 99 | * Pointer to the boost::asio::io_service object. 100 | */ 101 | boost::asio::io_service *io_service_; 102 | 103 | /** 104 | * The underlying nat-pmp implementation. 105 | */ 106 | boost::shared_ptr impl_; 107 | }; 108 | 109 | } // namespace natpmp 110 | -------------------------------------------------------------------------------- /include/nat/natpmpclientimpl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | Created by Julian Cain on 11/3/09. 28 | 29 | */ 30 | #pragma once 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | #include "natpmpprotocol.h" 41 | 42 | namespace natpmp { 43 | 44 | typedef boost::function NatPmpMapPortSuccessCbType; 48 | 49 | /** 50 | * Implements the underlying NAT-PMP client implementation. 51 | */ 52 | class NatPmpClientImpl { 53 | public: 54 | 55 | /** 56 | * Constructor 57 | * @param ios The boost::asio::io_service object to use. 58 | */ 59 | explicit NatPmpClientImpl(boost::asio::io_service *ios); 60 | 61 | /** 62 | * Destructor 63 | */ 64 | ~NatPmpClientImpl(); 65 | 66 | /** 67 | * Start the nat-pmp client. 68 | */ 69 | void Start(); 70 | 71 | /** 72 | * Stops the nat-pmp client removing all mappings. 73 | */ 74 | void Stop(); 75 | 76 | /** 77 | * Set the port map success callback. 78 | */ 79 | void SetMapPortSuccessCallback( 80 | const NatPmpMapPortSuccessCbType &map_port_success_cb); 81 | 82 | /** 83 | * Sends a mapping request by posting it to the 84 | * boost::asio::io_service object with the given protocol, 85 | * private port, public port and lifetime. 86 | * @param protocol 87 | * @param private_port 88 | * @param public_port 89 | * @param lifetime 90 | * @note thread-safe 91 | */ 92 | void SendMappingRequest(boost::uint16_t protocol, 93 | boost::uint16_t private_port, 94 | boost::uint16_t public_port, 95 | boost::uint32_t lifetime); 96 | 97 | private: 98 | /** 99 | * Copy constructor and equal operator. 100 | */ 101 | NatPmpClientImpl(const NatPmpClientImpl &natpnp_client); 102 | NatPmpClientImpl &operator=(const NatPmpClientImpl &natpnp_client); 103 | 104 | /** 105 | * Sends a mapping. 106 | */ 107 | void DoSendMappingRequest(boost::uint16_t protocol, 108 | boost::uint16_t private_port, 109 | boost::uint16_t public_port, 110 | boost::uint32_t lifetime); 111 | 112 | /** 113 | * Sends a public address request to the gateway. 114 | */ 115 | void SendPublicAddressRequest(); 116 | 117 | /** 118 | * Performs a public address request re-transmission. 119 | */ 120 | void RetransmitPublicAdddressRequest(const boost::system::error_code & ec); 121 | 122 | /** 123 | * Sends a request to the gateway. 124 | */ 125 | void SendRequest(Protocol::MappingRequest & req); 126 | 127 | /** 128 | * Sends any queued requests. 129 | */ 130 | void SendQueuedRequests(); 131 | 132 | /** 133 | * Sends buf of size len to the gateway. 134 | */ 135 | void Send(const char * buf, std::size_t len); 136 | 137 | /** 138 | * Asynchronous send handler. 139 | */ 140 | void HandleSend(const boost::system::error_code & ec, std::size_t); 141 | 142 | /** 143 | * Asynchronous cannot handler. 144 | */ 145 | void HandleConnect(const boost::system::error_code & ec); 146 | 147 | /** 148 | * Asynchronous receive from handler. 149 | */ 150 | void HandleReceiveFrom(const boost::system::error_code & ec, 151 | std::size_t bytes); 152 | 153 | /** 154 | * Asynchronous response handler. 155 | */ 156 | void HandleResponse(const char * buf, std::size_t); 157 | 158 | /** 159 | * The ip address of the gateway. 160 | */ 161 | boost::asio::ip::address m_gateway_address_; 162 | 163 | /** 164 | * The ip address on the WAN side of the gateway. 165 | */ 166 | boost::asio::ip::address m_public_ip_address_; 167 | 168 | protected: 169 | 170 | /** 171 | * A reference to the boost::asio::io_service. 172 | */ 173 | boost::asio::io_service *io_service_; 174 | 175 | /** 176 | * The request retry timer. 177 | */ 178 | boost::asio::deadline_timer retry_timer_; 179 | 180 | /** 181 | * The udp socket. 182 | */ 183 | boost::shared_ptr socket_; 184 | 185 | /** 186 | * The gateway endpoint. 187 | */ 188 | boost::asio::ip::udp::endpoint endpoint_; 189 | 190 | /** 191 | * The non-parallel public ip address request. 192 | */ 193 | Protocol::MappingRequest public_ip_request_; 194 | 195 | /** 196 | * The parallel reuqest queue. 197 | */ 198 | std::deque request_queue_; 199 | 200 | /** 201 | * The receive buffer length. 202 | */ 203 | enum { kReceiveBufferLength = 512 }; 204 | 205 | /** 206 | * The receive buffer. 207 | */ 208 | char data_[kReceiveBufferLength]; 209 | 210 | /** 211 | * Mappings that we are responsible for. 212 | */ 213 | std::vector< std::pair > 214 | mappings_; 215 | 216 | /** 217 | * Map port success callback. 218 | */ 219 | NatPmpMapPortSuccessCbType nat_pmp_map_port_success_cb_; 220 | }; 221 | 222 | } // namespace natpmp 223 | -------------------------------------------------------------------------------- /include/nat/natpmpprotocol.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | Created by Julian Cain on 11/3/09. 28 | 29 | */ 30 | #pragma once 31 | 32 | #include 33 | #include 34 | 35 | namespace natpmp { 36 | 37 | /** 38 | * Implements the NAT-PMP base protocol. 39 | */ 40 | class Protocol { 41 | public: 42 | 43 | /** 44 | * NAT-PMP port. 45 | */ 46 | enum { kPort = 5351 }; 47 | 48 | /** 49 | * Supported protocols. 50 | */ 51 | enum { kTcp = 1, kUdp = 2 }; 52 | 53 | /** 54 | * Result opcodes. 55 | * 0 - Success 56 | * 1 - Unsupported Version 57 | * 2 - Not Authorized/Refused (e.g. box supports mapping, but user 58 | * has turned feature off) 59 | * 3 - Network Failure (e.g. NAT box itself has not obtained a 60 | * DHCP lease) 61 | * 4 - Out of resources 62 | (NAT box cannot create any more mappings at this time) 63 | * 5 - Unsupported opcode 64 | */ 65 | enum ResultOpcodes { 66 | kResultSuccess = 0, 67 | kResultUnsupportedVersion = 1, 68 | kResultNotAuthorisedRefused = 2, 69 | kResultNetworkFailure = 3, 70 | kResultOutOfResources = 4, 71 | kResultUnsupportedOpcode = 5, 72 | kResultUndefined = 64 73 | }; 74 | 75 | /** 76 | * Error codes. 77 | */ 78 | enum ErrorCodes { 79 | kErrorInvalidArgs = 1, 80 | kErrorSocketError = 2, 81 | kErrorConnect = 3, 82 | kErrorSend = 4, 83 | kErrorReceiveFrom = 5, 84 | kErrorSourceConflict = 6, 85 | kErrorCannotGetGateway = 7 86 | }; 87 | 88 | /** 89 | * Mapping request structure. 90 | */ 91 | struct MappingRequest { 92 | bool operator == (const MappingRequest & other) const { 93 | return std::memcmp(buffer, other.buffer, sizeof(buffer)) == 0; 94 | } 95 | 96 | std::size_t length; 97 | char buffer[12]; 98 | boost::uint8_t retry_count; 99 | }; 100 | 101 | /** 102 | * External ip address request structure. 103 | */ 104 | struct ExternalAddressRequest { 105 | boost::uint16_t opcode; 106 | }; 107 | 108 | /** 109 | * Mapping response structure. 110 | */ 111 | struct MappingResponse { 112 | MappingResponse() : type(0), result_code(0), epoch(0), public_address(), 113 | private_port(0), public_port(0), lifetime(0) {} 114 | bool operator == (const MappingResponse & other) const { 115 | return (private_port == other.private_port && 116 | public_port == other.public_port); 117 | } 118 | 119 | boost::uint16_t type; 120 | boost::uint16_t result_code; 121 | boost::uint32_t epoch; 122 | boost::asio::ip::address public_address; 123 | boost::uint16_t private_port; 124 | boost::uint16_t public_port; 125 | boost::uint32_t lifetime; 126 | }; 127 | 128 | /** 129 | * Generates a string representation from an opcode 130 | * @param opcode 131 | */ 132 | static const char * StringFromOpcode(unsigned int opcode); 133 | 134 | private: 135 | 136 | // ... 137 | 138 | protected: 139 | 140 | // ... 141 | }; 142 | 143 | } // namespace natpnp 144 | -------------------------------------------------------------------------------- /include/nat/upnpcfg.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #pragma once 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | namespace upnp { 34 | 35 | const int kSearchTime = 2; 36 | const int kLeaseDuration = 900; 37 | const int kRefreshThreshold = 10; 38 | const char kClientName[] = "libsss-nat-upnp"; 39 | 40 | enum ProtocolType { 41 | kUdp = 0, 42 | kTcp = 1 43 | }; 44 | 45 | // params: port, protocol 46 | typedef boost::function upnp_callback; 47 | 48 | struct PortMapping { 49 | PortMapping(const int &port, const ProtocolType &protocol_) 50 | : internal_port(port) 51 | , external_port(port) 52 | , protocol(protocol_) 53 | , enabled(false) 54 | , last_refresh() 55 | {} 56 | 57 | PortMapping(int in_port, int out_port, const ProtocolType &protocol_) 58 | : internal_port(in_port) 59 | , external_port(out_port) 60 | , protocol(protocol_) 61 | , enabled(false) 62 | , last_refresh() 63 | {} 64 | 65 | int internal_port; 66 | int external_port; 67 | ProtocolType protocol; 68 | bool enabled; 69 | std::map last_refresh; 70 | }; 71 | 72 | struct PortMappingExt : public PortMapping 73 | { 74 | std::string internal_host; 75 | std::string external_host; 76 | std::string description; 77 | int duration{kLeaseDuration}; 78 | 79 | PortMappingExt(const int &port, const ProtocolType &protocol_) 80 | : PortMapping(port, protocol_) 81 | {} 82 | PortMappingExt(int in_port, int out_port, const ProtocolType &protocol_) 83 | : PortMapping(in_port, out_port, protocol_) 84 | {} 85 | }; 86 | 87 | } // namespace upnp 88 | -------------------------------------------------------------------------------- /include/nat/upnpclient.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #pragma once 29 | 30 | #include 31 | #include 32 | #include "miniupnpclientimpl.h" 33 | 34 | namespace upnp { 35 | 36 | // control point for a UPnP Internet Gateway Device 37 | class UpnpIgdClient { 38 | public: 39 | UpnpIgdClient(); 40 | ~UpnpIgdClient(); 41 | 42 | bool IsAsync(); 43 | bool HasServices(); 44 | 45 | bool InitControlPoint(); 46 | bool GetPortMappings(std::list& out_mapping); 47 | bool AddPortMapping(const int &port, const ProtocolType &protocol); 48 | bool AddPortMapping(int in_port, int out_port, ProtocolType protocol); 49 | bool DeletePortMapping(const int &port, const ProtocolType &protocol); 50 | bool DeleteAllPortMappings(); 51 | 52 | std::string GetExternalIpAddress(); 53 | 54 | void SetNewMappingCallback(const upnp_callback &new_mapping_callback); 55 | void SetLostMappingCallback(const upnp_callback &lost_mapping_callback); 56 | void SetFailedMappingCallback(const upnp_callback &failed_mapping_callback); 57 | private: 58 | boost::shared_ptr pimpl_; 59 | }; 60 | 61 | } // namespace upnp 62 | -------------------------------------------------------------------------------- /include/nat/upnpclientimpl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #pragma once 28 | 29 | // #define VERBOSE_DEBUG 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "upnpcfg.h" 38 | #include "maidsafe_calllatertimer.h" 39 | 40 | namespace upnp { 41 | 42 | const char kIgdDeviceType[] = 43 | "urn:schemas-upnp-org:device:InternetGatewayDevice:1"; 44 | const char kWanIpServiceType[] = 45 | "urn:schemas-upnp-org:service:WANIPConnection:1"; 46 | const char kWanPppServiceType[] = 47 | "urn:schemas-upnp-org:service:WANPPPConnection:1"; 48 | 49 | struct RootDevice; 50 | 51 | struct Service { 52 | Service(): service_type(), 53 | service_id(), 54 | scpd_url(), 55 | control_url(), 56 | event_sub_url(), 57 | enabled(false), 58 | status_requested(false), 59 | subscription_requested(false), 60 | subscription_id(), 61 | subscription_expires(0), 62 | parent_root_device(NULL) {} 63 | std::string service_type; 64 | std::string service_id; 65 | std::string scpd_url; 66 | std::string control_url; 67 | std::string event_sub_url; 68 | 69 | bool enabled; 70 | bool status_requested; 71 | bool subscription_requested; 72 | std::string subscription_id; 73 | uint32_t subscription_expires; 74 | RootDevice* parent_root_device; 75 | }; 76 | 77 | struct Device { 78 | Device(): device_type(), 79 | friendly_name(), 80 | manufacturer(), 81 | model_name(), 82 | unique_device_name(), 83 | services(), 84 | devices() {} 85 | std::string device_type; 86 | std::string friendly_name; 87 | std::string manufacturer; 88 | std::string model_name; 89 | std::string unique_device_name; 90 | 91 | std::list< boost::shared_ptr > services; 92 | std::list< boost::shared_ptr > devices; 93 | }; 94 | 95 | struct RootDevice { 96 | RootDevice(const boost::shared_ptr &details_, 97 | const int &expires_, 98 | const std::string &location_): details(details_), 99 | expires(expires_), 100 | location(location_) {} 101 | boost::shared_ptr details; 102 | uint32_t expires; // absolute timestamp! 103 | std::string location; 104 | }; 105 | 106 | // control point for a UPnP Internet Gateway Device (libupnp implementation) 107 | class UpnpIgdClientImpl { 108 | public: 109 | UpnpIgdClientImpl(); 110 | ~UpnpIgdClientImpl(); 111 | 112 | // returns true if the mapping functions use callbacks 113 | bool IsAsync(); 114 | // returns true if suitable services have been found 115 | bool HasServices(); 116 | 117 | // starts up the UPnP control point, including device discovery 118 | bool InitControlPoint(); 119 | // returns the ip address of the internal server listening for requests 120 | std::string GetServerIpAddress(); 121 | // returns the port of the internal server listening for requests 122 | int GetServerPort(); 123 | 124 | // schedules a port mapping for registration with known and future services 125 | bool AddPortMapping(const PortMapping &mapping); 126 | // checks, if the given mapping exists in the internal list 127 | bool PortMappingExists(const int &port, const ProtocolType &protocol, 128 | std::list::iterator &it); 129 | // removes the mapping from the internal list and all known services 130 | bool DeletePortMapping(const int &port, const ProtocolType &protocol); 131 | // removes all mappings 132 | bool DeleteAllPortMappings(); 133 | 134 | // retrieves the external IP address from the first device (blocking) 135 | std::string GetExternalIpAddress(); 136 | 137 | // callbacks for processing UPnP event notifications 138 | void ProcessDiscoveryEvent(Upnp_EventType event_type, Upnp_Discovery* event); 139 | void ProcessActionEvent(Upnp_Action_Complete* event); 140 | void ProcessChangeEvent(Upnp_Event* event); 141 | void ProcessSubscriptionEvent(Upnp_EventType event_type, 142 | Upnp_Event_Subscribe* event); 143 | // main callback, called by upnplib 144 | static int EventCallback(Upnp_EventType event_type, void* event, 145 | void* cookie); 146 | 147 | // register a function to be called when a mapping has been successful 148 | void SetNewMappingCallback(const upnp_callback &new_mapping_callback); 149 | // register a function to be called when all instances of a mapping are gone 150 | void SetLostMappingCallback(const upnp_callback &lost_mapping_callback); 151 | // register a function to be called when a mapping couldn't be set up 152 | void SetFailedMappingCallback(const upnp_callback &failed_mapping_callback); 153 | 154 | private: 155 | UpnpIgdClientImpl(const UpnpIgdClientImpl&); 156 | UpnpIgdClientImpl& operator=(const UpnpIgdClientImpl&); 157 | 158 | // initialises the UPnP SDK 159 | bool Init(); 160 | // terminates the SDK 161 | void Finish(); 162 | 163 | // registers the client with the SDK 164 | bool Register(); 165 | // unregisters the client, unsubscribing all active subscriptions 166 | void UnRegister(); 167 | 168 | // starts the search for suitable devices 169 | void DiscoverDevices(); 170 | 171 | // extracts a device structure from an xml hierarchy 172 | bool ParseDeviceDescription(IXML_Node* node, 173 | const boost::shared_ptr &device, 174 | const std::string &location); 175 | // extracts a service structure from an xml hierarchy 176 | bool ParseServiceDescription(IXML_Node* node, 177 | const boost::shared_ptr &service, 178 | const std::string &location); 179 | 180 | // adds a unique root device to the internal list 181 | bool AddRootDevice(const boost::shared_ptr &device, 182 | const uint32_t &expires, const std::string location); 183 | // checks, if a root device with the given ID exists in the internal list 184 | bool RootDeviceExists(const std::string &udn, const std::string location, 185 | std::list::iterator &it); 186 | // keeps the root device from expiring 187 | void UpdateRootDevice(RootDevice* rd, const uint32_t &expires); 188 | // removes the root device with the given ID 189 | bool DeleteRootDevice(const std::string &udn, const std::string location); 190 | 191 | // rebuilds list of relevant services 192 | void UpdateServicesCache(); 193 | // renews mappings on active services, if needed 194 | void UpdatePortMappings(); 195 | // sends request to find out whether service exists and is active 196 | void RequestServiceStatusInfo(const boost::shared_ptr &service); 197 | 198 | // retrieves service from cache list by its control URL 199 | bool GetCachedServiceByControlUrl(const std::string &url, 200 | boost::shared_ptr &service); 201 | // retrieves service from cache list by its subscription URL 202 | bool GetCachedServiceByEventSubUrl(const std::string &url, 203 | boost::shared_ptr &service); 204 | // retrieves service from cache list by its subscription ID 205 | bool GetCachedServiceBySubscriptionId(const std::string &sid, 206 | boost::shared_ptr &service); 207 | 208 | // creates/refreshes mapping-service relation 209 | bool AddPortMappingToService(const boost::shared_ptr &service, 210 | PortMapping *mapping); 211 | // removes mapping-service relation 212 | bool DeletePortMappingFromService(const boost::shared_ptr &service, 213 | const PortMapping &mapping); 214 | // gets called periodically to refresh a mapping 215 | void RefreshPortMappingCallback(const int &port, 216 | const ProtocolType &protocol, 217 | const std::string &service_control_url); 218 | 219 | // void RefreshSubscriptionCallback(const std::string &subscription_id); 220 | 221 | // calls the callback for a new mapping 222 | void OnNewMapping(const int &port, const ProtocolType &protocol); 223 | // calls the callback for a lost mapping 224 | void OnLostMapping(const int &port, const ProtocolType &protocol); 225 | // calls the callback for a failed mapping 226 | void OnFailedMapping(const int &port, const ProtocolType &protocol); 227 | 228 | 229 | bool is_initialised_; 230 | bool is_registered_; 231 | UpnpClient_Handle handle_; 232 | boost::recursive_mutex mutex_; 233 | base::CallLaterTimer timer_; 234 | 235 | std::list root_devices_; 236 | std::list port_mappings_; 237 | std::list< boost::shared_ptr > services_cache_; 238 | 239 | upnp_callback new_mapping_callback_; 240 | upnp_callback lost_mapping_callback_; 241 | upnp_callback failed_mapping_callback_; 242 | }; 243 | 244 | } // namespace upnp 245 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(libupnp) 2 | add_library(nat STATIC 3 | natpmpprotocol.cc 4 | natpmpclient.cc 5 | natpmpclientimpl.cc 6 | upnpclient.cc 7 | miniupnpclientimpl.cc 8 | maidsafe_calllatertimer.cc 9 | maidsafe_network_interface.cc 10 | maidsafe_gateway.cc 11 | maidsafe_utils.cc) 12 | add_definitions(-Wno-unused-function) # in maidsafe_network_interface.cc 13 | 14 | if (UNIX AND NOT APPLE) 15 | add_definitions(-DMAIDSAFE_LINUX) 16 | endif() 17 | -------------------------------------------------------------------------------- /lib/libupnp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | option (UPNPC_BUILD_STATIC "Build static library" TRUE) 2 | option (UPNPC_BUILD_SHARED "Build shared library" FALSE) 3 | option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE) 4 | mark_as_advanced (NO_GETADDRINFO) 5 | 6 | if (CMAKE_BUILD_TYPE MATCHES "Debug") 7 | add_definitions(-DDEBUG) 8 | endif() 9 | 10 | add_definitions(-DMINIUPNPC_VERSION_STRING=\"1.7\") 11 | add_definitions(-DOS_STRING=\"${CMAKE_SYSTEM_NAME}\") 12 | 13 | if (NO_GETADDRINFO) 14 | add_definitions(-DNO_GETADDRINFO) 15 | endif (NO_GETADDRINFO) 16 | 17 | if (NOT WIN32) 18 | add_definitions(-DMINIUPNPC_SET_SOCKET_TIMEOUT) 19 | add_definitions(-D_BSD_SOURCE -D_POSIX_C_SOURCE=1) 20 | else (NOT WIN32) 21 | add_definitions(-D_WIN32_WINNT=0x0501) # XP or higher for getnameinfo and friends 22 | endif (NOT WIN32) 23 | 24 | if (APPLE) 25 | add_definitions(-DMACOSX -D_DARWIN_C_SOURCE) 26 | endif () 27 | 28 | set (MINIUPNPC_SOURCES 29 | igd_desc_parse.c 30 | miniupnpc.c 31 | minixml.c 32 | minisoap.c 33 | miniwget.c 34 | upnpcommands.c 35 | upnpreplyparse.c 36 | upnperrors.c 37 | connecthostport.c 38 | portlistingparse.c 39 | receivedata.c) 40 | 41 | if (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") 42 | list (APPEND MINIUPNPC_SOURCES minissdpc.c) 43 | endif (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") 44 | 45 | if (WIN32) 46 | set_source_files_properties (${MINIUPNPC_SOURCES} PROPERTIES 47 | COMPILE_DEFINITIONS STATICLIB 48 | COMPILE_DEFINITIONS MINIUPNP_EXPORTS) 49 | endif (WIN32) 50 | 51 | if (WIN32) 52 | find_library (WINSOCK2_LIBRARY NAMES ws2_32 WS2_32 Ws2_32) 53 | find_library (IPHLPAPI_LIBRARY NAMES iphlpapi) 54 | set (LDLIBS ${WINSOCK2_LIBRARY} ${IPHLPAPI_LIBRARY} ${LDLIBS}) 55 | endif (WIN32) 56 | 57 | if (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED) 58 | message (FATAL "Both shared and static libraries are disabled!") 59 | endif (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED) 60 | 61 | if (UPNPC_BUILD_STATIC) 62 | add_library (upnpc STATIC ${MINIUPNPC_SOURCES}) 63 | endif (UPNPC_BUILD_STATIC) 64 | 65 | if (UPNPC_BUILD_SHARED) 66 | add_library (upnpc-shared SHARED ${MINIUPNPC_SOURCES}) 67 | set_target_properties (upnpc-shared PROPERTIES OUTPUT_NAME "miniupnpc") 68 | set_target_properties (upnpc-shared PROPERTIES VERSION ${MINIUPNPC_VERSION}) 69 | set_target_properties (upnpc-shared PROPERTIES SOVERSION ${MINIUPNPC_API_VERSION}) 70 | target_link_libraries (upnpc-shared ${LDLIBS}) 71 | endif (UPNPC_BUILD_SHARED) 72 | -------------------------------------------------------------------------------- /lib/libupnp/LICENSE: -------------------------------------------------------------------------------- 1 | MiniUPnPc 2 | Copyright (c) 2005-2011, Thomas BERNARD 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | * The name of the author may not be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | 28 | -------------------------------------------------------------------------------- /lib/libupnp/README: -------------------------------------------------------------------------------- 1 | Project: miniupnp 2 | Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 3 | github: https://github.com/miniupnp/miniupnp 4 | freecode: http://freecode.com/projects/miniupnp 5 | Author: Thomas Bernard 6 | Copyright (c) 2005-2012 Thomas Bernard 7 | This software is subject to the conditions detailed in the 8 | LICENSE file provided within this distribution. 9 | 10 | 11 | For the comfort of Win32 users, bsdqueue.h is included in the distribution. 12 | Its licence is included in the header of the file. 13 | bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system. 14 | 15 | 16 | * miniUPnP Client - miniUPnPc * 17 | 18 | To compile, simply run 'gmake' (could be 'make' on your system). 19 | Under win32, to compile with MinGW, type "mingw32make.bat". 20 | MS Visual C solution and project files are supplied in the msvc/ subdirectory. 21 | 22 | The compilation is known to work under linux, FreeBSD, 23 | OpenBSD, MacOS X, AmigaOS and cygwin. 24 | The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3. 25 | upx (http://upx.sourceforge.net) is used to compress the win32 .exe files. 26 | 27 | upnpc.c is a sample client using the libminiupnpc. 28 | To use the libminiupnpc in your application, link it with 29 | libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h, 30 | upnpcommands.h and miniwget.h : 31 | - upnpDiscover() 32 | - miniwget() 33 | - parserootdesc() 34 | - GetUPNPUrls() 35 | - UPNP_* (calling UPNP methods) 36 | 37 | Note : use #include etc... for the includes 38 | and -lminiupnpc for the link 39 | 40 | Discovery process is speeded up when MiniSSDPd is running on the machine. 41 | 42 | 43 | Feel free to contact me if you have any problem : 44 | e-mail : miniupnp@free.fr 45 | 46 | If you are using libminiupnpc in your application, please 47 | send me an email ! 48 | 49 | For any question, you can use the web forum : 50 | http://miniupnp.tuxfamily.org/forum/ 51 | 52 | -------------------------------------------------------------------------------- /lib/libupnp/connecthostport.c: -------------------------------------------------------------------------------- 1 | /* $Id: connecthostport.c,v 1.9 2012/06/26 00:00:27 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * Author : Thomas Bernard 4 | * Copyright (c) 2010-2012 Thomas Bernard 5 | * This software is subject to the conditions detailed in the 6 | * LICENCE file provided in this distribution. */ 7 | 8 | /* use getaddrinfo() or gethostbyname() 9 | * uncomment the following line in order to use gethostbyname() */ 10 | #ifdef NO_GETADDRINFO 11 | #define USE_GETHOSTBYNAME 12 | #endif 13 | 14 | #include 15 | #include 16 | #ifdef _WIN32 17 | #include 18 | #include 19 | #include 20 | #define MAXHOSTNAMELEN 64 21 | #define snprintf _snprintf 22 | #define herror 23 | #define socklen_t int 24 | #else /* #ifdef _WIN32 */ 25 | #include 26 | #include 27 | #include 28 | #define closesocket close 29 | #include 30 | #include 31 | /* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions 32 | * during the connect() call */ 33 | #define MINIUPNPC_IGNORE_EINTR 34 | #ifndef USE_GETHOSTBYNAME 35 | #include 36 | #include 37 | #endif /* #ifndef USE_GETHOSTBYNAME */ 38 | #endif /* #else _WIN32 */ 39 | 40 | /* definition of PRINT_SOCKET_ERROR */ 41 | #ifdef _WIN32 42 | #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); 43 | #else 44 | #define PRINT_SOCKET_ERROR(x) perror(x) 45 | #endif 46 | 47 | #if defined(__amigaos__) || defined(__amigaos4__) 48 | #define herror(A) printf("%s\n", A) 49 | #endif 50 | 51 | #include "libupnp/connecthostport.h" 52 | 53 | /* connecthostport() 54 | * return a socket connected (TCP) to the host and port 55 | * or -1 in case of error */ 56 | int connecthostport(const char * host, unsigned short port, 57 | unsigned int scope_id) 58 | { 59 | int s, n; 60 | #ifdef USE_GETHOSTBYNAME 61 | struct sockaddr_in dest; 62 | struct hostent *hp; 63 | #else /* #ifdef USE_GETHOSTBYNAME */ 64 | char tmp_host[MAXHOSTNAMELEN+1]; 65 | char port_str[8]; 66 | struct addrinfo *ai, *p; 67 | struct addrinfo hints; 68 | #endif /* #ifdef USE_GETHOSTBYNAME */ 69 | #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT 70 | struct timeval timeout; 71 | #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ 72 | 73 | #ifdef USE_GETHOSTBYNAME 74 | hp = gethostbyname(host); 75 | if(hp == NULL) 76 | { 77 | herror(host); 78 | return -1; 79 | } 80 | memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr)); 81 | memset(dest.sin_zero, 0, sizeof(dest.sin_zero)); 82 | s = socket(PF_INET, SOCK_STREAM, 0); 83 | if(s < 0) 84 | { 85 | PRINT_SOCKET_ERROR("socket"); 86 | return -1; 87 | } 88 | #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT 89 | /* setting a 3 seconds timeout for the connect() call */ 90 | timeout.tv_sec = 3; 91 | timeout.tv_usec = 0; 92 | if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) 93 | { 94 | PRINT_SOCKET_ERROR("setsockopt"); 95 | } 96 | timeout.tv_sec = 3; 97 | timeout.tv_usec = 0; 98 | if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) 99 | { 100 | PRINT_SOCKET_ERROR("setsockopt"); 101 | } 102 | #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ 103 | dest.sin_family = AF_INET; 104 | dest.sin_port = htons(port); 105 | n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); 106 | #ifdef MINIUPNPC_IGNORE_EINTR 107 | while(n < 0 && errno == EINTR) 108 | { 109 | socklen_t len; 110 | fd_set wset; 111 | int err; 112 | FD_ZERO(&wset); 113 | FD_SET(s, &wset); 114 | if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) 115 | continue; 116 | /*len = 0;*/ 117 | /*n = getpeername(s, NULL, &len);*/ 118 | len = sizeof(err); 119 | if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { 120 | PRINT_SOCKET_ERROR("getsockopt"); 121 | closesocket(s); 122 | return -1; 123 | } 124 | if(err != 0) { 125 | errno = err; 126 | n = -1; 127 | } 128 | } 129 | #endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ 130 | if(n<0) 131 | { 132 | PRINT_SOCKET_ERROR("connect"); 133 | closesocket(s); 134 | return -1; 135 | } 136 | #else /* #ifdef USE_GETHOSTBYNAME */ 137 | /* use getaddrinfo() instead of gethostbyname() */ 138 | memset(&hints, 0, sizeof(hints)); 139 | /* hints.ai_flags = AI_ADDRCONFIG; */ 140 | #ifdef AI_NUMERICSERV 141 | hints.ai_flags = AI_NUMERICSERV; 142 | #endif 143 | hints.ai_socktype = SOCK_STREAM; 144 | hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */ 145 | /* hints.ai_protocol = IPPROTO_TCP; */ 146 | snprintf(port_str, sizeof(port_str), "%hu", port); 147 | if(host[0] == '[') 148 | { 149 | /* literal ip v6 address */ 150 | int i, j; 151 | for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++) 152 | { 153 | tmp_host[i] = host[j]; 154 | if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */ 155 | j+=2; /* skip "25" */ 156 | } 157 | tmp_host[i] = '\0'; 158 | } 159 | else 160 | { 161 | strncpy(tmp_host, host, MAXHOSTNAMELEN); 162 | } 163 | tmp_host[MAXHOSTNAMELEN] = '\0'; 164 | n = getaddrinfo(tmp_host, port_str, &hints, &ai); 165 | if(n != 0) 166 | { 167 | #ifdef _WIN32 168 | fprintf(stderr, "getaddrinfo() error : %d\n", n); 169 | #else 170 | fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n)); 171 | #endif 172 | return -1; 173 | } 174 | s = -1; 175 | for(p = ai; p; p = p->ai_next) 176 | { 177 | s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); 178 | if(s < 0) 179 | continue; 180 | if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) { 181 | struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr; 182 | addr6->sin6_scope_id = scope_id; 183 | } 184 | #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT 185 | /* setting a 3 seconds timeout for the connect() call */ 186 | timeout.tv_sec = 3; 187 | timeout.tv_usec = 0; 188 | if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) 189 | { 190 | PRINT_SOCKET_ERROR("setsockopt"); 191 | } 192 | timeout.tv_sec = 3; 193 | timeout.tv_usec = 0; 194 | if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) 195 | { 196 | PRINT_SOCKET_ERROR("setsockopt"); 197 | } 198 | #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ 199 | n = connect(s, p->ai_addr, p->ai_addrlen); 200 | #ifdef MINIUPNPC_IGNORE_EINTR 201 | while(n < 0 && errno == EINTR) 202 | { 203 | socklen_t len; 204 | fd_set wset; 205 | int err; 206 | FD_ZERO(&wset); 207 | FD_SET(s, &wset); 208 | if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) 209 | continue; 210 | /*len = 0;*/ 211 | /*n = getpeername(s, NULL, &len);*/ 212 | len = sizeof(err); 213 | if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { 214 | PRINT_SOCKET_ERROR("getsockopt"); 215 | closesocket(s); 216 | freeaddrinfo(ai); 217 | return -1; 218 | } 219 | if(err != 0) { 220 | errno = err; 221 | n = -1; 222 | } 223 | } 224 | #endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ 225 | if(n < 0) 226 | { 227 | closesocket(s); 228 | continue; 229 | } 230 | else 231 | { 232 | break; 233 | } 234 | } 235 | freeaddrinfo(ai); 236 | if(s < 0) 237 | { 238 | PRINT_SOCKET_ERROR("socket"); 239 | return -1; 240 | } 241 | if(n < 0) 242 | { 243 | PRINT_SOCKET_ERROR("connect"); 244 | return -1; 245 | } 246 | #endif /* #ifdef USE_GETHOSTBYNAME */ 247 | return s; 248 | } 249 | 250 | -------------------------------------------------------------------------------- /lib/libupnp/external-ip.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # $Id: external-ip.sh,v 1.1 2010/08/05 12:57:41 nanard Exp $ 3 | # (c) 2010 Reuben Hawkins 4 | upnpc -s | grep ExternalIPAddress | sed 's/[^0-9\.]//g' 5 | -------------------------------------------------------------------------------- /lib/libupnp/igd_desc_parse.c: -------------------------------------------------------------------------------- 1 | /* $Id: igd_desc_parse.c,v 1.14 2011/04/11 09:19:24 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * http://miniupnp.free.fr/ 4 | * Author : Thomas Bernard 5 | * Copyright (c) 2005-2010 Thomas Bernard 6 | * This software is subject to the conditions detailed in the 7 | * LICENCE file provided in this distribution. */ 8 | 9 | #include "libupnp/igd_desc_parse.h" 10 | #include 11 | #include 12 | 13 | /* Start element handler : 14 | * update nesting level counter and copy element name */ 15 | void IGDstartelt(void * d, const char * name, int l) 16 | { 17 | struct IGDdatas * datas = (struct IGDdatas *)d; 18 | memcpy( datas->cureltname, name, l); 19 | datas->cureltname[l] = '\0'; 20 | datas->level++; 21 | if( (l==7) && !memcmp(name, "service", l) ) { 22 | datas->tmp.controlurl[0] = '\0'; 23 | datas->tmp.eventsuburl[0] = '\0'; 24 | datas->tmp.scpdurl[0] = '\0'; 25 | datas->tmp.servicetype[0] = '\0'; 26 | } 27 | } 28 | 29 | /* End element handler : 30 | * update nesting level counter and update parser state if 31 | * service element is parsed */ 32 | void IGDendelt(void * d, const char * name, int l) 33 | { 34 | struct IGDdatas * datas = (struct IGDdatas *)d; 35 | datas->level--; 36 | /*printf("endelt %2d %.*s\n", datas->level, l, name);*/ 37 | if( (l==7) && !memcmp(name, "service", l) ) 38 | { 39 | /* 40 | if( datas->state < 1 41 | && !strcmp(datas->servicetype, 42 | // "urn:schemas-upnp-org:service:WANIPConnection:1") ) 43 | "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) 44 | datas->state ++; 45 | */ 46 | if(0==strcmp(datas->tmp.servicetype, 47 | "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) { 48 | memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service)); 49 | } else if(0==strcmp(datas->tmp.servicetype, 50 | "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1")) { 51 | memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service)); 52 | } else if(0==strcmp(datas->tmp.servicetype, 53 | "urn:schemas-upnp-org:service:WANIPConnection:1") 54 | || 0==strcmp(datas->tmp.servicetype, 55 | "urn:schemas-upnp-org:service:WANPPPConnection:1") ) { 56 | if(datas->first.servicetype[0] == '\0') { 57 | memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service)); 58 | } else { 59 | memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service)); 60 | } 61 | } 62 | } 63 | } 64 | 65 | /* Data handler : 66 | * copy data depending on the current element name and state */ 67 | void IGDdata(void * d, const char * data, int l) 68 | { 69 | struct IGDdatas * datas = (struct IGDdatas *)d; 70 | char * dstmember = 0; 71 | /*printf("%2d %s : %.*s\n", 72 | datas->level, datas->cureltname, l, data); */ 73 | if( !strcmp(datas->cureltname, "URLBase") ) 74 | dstmember = datas->urlbase; 75 | else if( !strcmp(datas->cureltname, "presentationURL") ) 76 | dstmember = datas->presentationurl; 77 | else if( !strcmp(datas->cureltname, "serviceType") ) 78 | dstmember = datas->tmp.servicetype; 79 | else if( !strcmp(datas->cureltname, "controlURL") ) 80 | dstmember = datas->tmp.controlurl; 81 | else if( !strcmp(datas->cureltname, "eventSubURL") ) 82 | dstmember = datas->tmp.eventsuburl; 83 | else if( !strcmp(datas->cureltname, "SCPDURL") ) 84 | dstmember = datas->tmp.scpdurl; 85 | /* else if( !strcmp(datas->cureltname, "deviceType") ) 86 | dstmember = datas->devicetype_tmp;*/ 87 | if(dstmember) 88 | { 89 | if(l>=MINIUPNPC_URL_MAXSIZE) 90 | l = MINIUPNPC_URL_MAXSIZE-1; 91 | memcpy(dstmember, data, l); 92 | dstmember[l] = '\0'; 93 | } 94 | } 95 | 96 | void printIGD(struct IGDdatas * d) 97 | { 98 | printf("urlbase = '%s'\n", d->urlbase); 99 | printf("WAN Device (Common interface config) :\n"); 100 | /*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/ 101 | printf(" serviceType = '%s'\n", d->CIF.servicetype); 102 | printf(" controlURL = '%s'\n", d->CIF.controlurl); 103 | printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl); 104 | printf(" SCPDURL = '%s'\n", d->CIF.scpdurl); 105 | printf("primary WAN Connection Device (IP or PPP Connection):\n"); 106 | /*printf(" deviceType = '%s'\n", d->first.devicetype);*/ 107 | printf(" servicetype = '%s'\n", d->first.servicetype); 108 | printf(" controlURL = '%s'\n", d->first.controlurl); 109 | printf(" eventSubURL = '%s'\n", d->first.eventsuburl); 110 | printf(" SCPDURL = '%s'\n", d->first.scpdurl); 111 | printf("secondary WAN Connection Device (IP or PPP Connection):\n"); 112 | /*printf(" deviceType = '%s'\n", d->second.devicetype);*/ 113 | printf(" servicetype = '%s'\n", d->second.servicetype); 114 | printf(" controlURL = '%s'\n", d->second.controlurl); 115 | printf(" eventSubURL = '%s'\n", d->second.eventsuburl); 116 | printf(" SCPDURL = '%s'\n", d->second.scpdurl); 117 | printf("WAN IPv6 Firewall Control :\n"); 118 | /*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/ 119 | printf(" servicetype = '%s'\n", d->IPv6FC.servicetype); 120 | printf(" controlURL = '%s'\n", d->IPv6FC.controlurl); 121 | printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl); 122 | printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl); 123 | } 124 | 125 | 126 | -------------------------------------------------------------------------------- /lib/libupnp/minisoap.c: -------------------------------------------------------------------------------- 1 | /* $Id: minisoap.c,v 1.22 2012/01/21 13:30:31 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * Author : Thomas Bernard 4 | * Copyright (c) 2005-2012 Thomas Bernard 5 | * This software is subject to the conditions detailed in the 6 | * LICENCE file provided in this distribution. 7 | * 8 | * Minimal SOAP implementation for UPnP protocol. 9 | */ 10 | #include 11 | #include 12 | #ifdef _WIN32 13 | #include 14 | #include 15 | #define snprintf _snprintf 16 | #else 17 | #include 18 | #include 19 | #include 20 | #endif 21 | #include "libupnp/minisoap.h" 22 | 23 | /* only for malloc */ 24 | #include 25 | 26 | #ifdef _WIN32 27 | #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); 28 | #else 29 | #define PRINT_SOCKET_ERROR(x) perror(x) 30 | #endif 31 | 32 | /* httpWrite sends the headers and the body to the socket 33 | * and returns the number of bytes sent */ 34 | static int 35 | httpWrite(int fd, const char * body, int bodysize, 36 | const char * headers, int headerssize) 37 | { 38 | int n = 0; 39 | /*n = write(fd, headers, headerssize);*/ 40 | /*if(bodysize>0) 41 | n += write(fd, body, bodysize);*/ 42 | /* Note : my old linksys router only took into account 43 | * soap request that are sent into only one packet */ 44 | char * p; 45 | /* TODO: AVOID MALLOC */ 46 | p = malloc(headerssize+bodysize); 47 | if(!p) 48 | return 0; 49 | memcpy(p, headers, headerssize); 50 | memcpy(p+headerssize, body, bodysize); 51 | /*n = write(fd, p, headerssize+bodysize);*/ 52 | n = send(fd, p, headerssize+bodysize, 0); 53 | if(n<0) { 54 | PRINT_SOCKET_ERROR("send"); 55 | } 56 | /* disable send on the socket */ 57 | /* draytek routers dont seems to like that... */ 58 | #if 0 59 | #ifdef _WIN32 60 | if(shutdown(fd, SD_SEND)<0) { 61 | #else 62 | if(shutdown(fd, SHUT_WR)<0) { /*SD_SEND*/ 63 | #endif 64 | PRINT_SOCKET_ERROR("shutdown"); 65 | } 66 | #endif 67 | free(p); 68 | return n; 69 | } 70 | 71 | /* self explanatory */ 72 | int soapPostSubmit(int fd, 73 | const char * url, 74 | const char * host, 75 | unsigned short port, 76 | const char * action, 77 | const char * body, 78 | const char * httpversion) 79 | { 80 | int bodysize; 81 | char headerbuf[512]; 82 | int headerssize; 83 | char portstr[8]; 84 | bodysize = (int)strlen(body); 85 | /* We are not using keep-alive HTTP connections. 86 | * HTTP/1.1 needs the header Connection: close to do that. 87 | * This is the default with HTTP/1.0 88 | * Using HTTP/1.1 means we need to support chunked transfer-encoding : 89 | * When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked 90 | * transfer encoding. */ 91 | /* Connection: Close is normally there only in HTTP/1.1 but who knows */ 92 | portstr[0] = '\0'; 93 | if(port != 80) 94 | snprintf(portstr, sizeof(portstr), ":%hu", port); 95 | headerssize = snprintf(headerbuf, sizeof(headerbuf), 96 | "POST %s HTTP/%s\r\n" 97 | "Host: %s%s\r\n" 98 | "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" 99 | "Content-Length: %d\r\n" 100 | "Content-Type: text/xml\r\n" 101 | "SOAPAction: \"%s\"\r\n" 102 | "Connection: Close\r\n" 103 | "Cache-Control: no-cache\r\n" /* ??? */ 104 | "Pragma: no-cache\r\n" 105 | "\r\n", 106 | url, httpversion, host, portstr, bodysize, action); 107 | #ifdef DEBUG 108 | /*printf("SOAP request : headersize=%d bodysize=%d\n", 109 | headerssize, bodysize); 110 | */ 111 | printf("SOAP request : POST %s HTTP/%s - Host: %s%s\n", 112 | url, httpversion, host, portstr); 113 | printf("SOAPAction: \"%s\" - Content-Length: %d\n", action, bodysize); 114 | printf("Headers :\n%s", headerbuf); 115 | printf("Body :\n%s\n", body); 116 | #endif 117 | return httpWrite(fd, body, bodysize, headerbuf, headerssize); 118 | } 119 | 120 | 121 | -------------------------------------------------------------------------------- /lib/libupnp/minissdpc.c: -------------------------------------------------------------------------------- 1 | /* $Id: minissdpc.c,v 1.15 2012/01/21 13:30:31 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * Web : http://miniupnp.free.fr/ 4 | * Author : Thomas BERNARD 5 | * copyright (c) 2005-2012 Thomas Bernard 6 | * This software is subjet to the conditions detailed in the 7 | * provided LICENCE file. */ 8 | /*#include */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) 15 | #ifdef _WIN32 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #endif 22 | #if defined(__amigaos__) || defined(__amigaos4__) 23 | #include 24 | #endif 25 | #if defined(__amigaos__) 26 | #define uint16_t unsigned short 27 | #endif 28 | /* Hack */ 29 | #define UNIX_PATH_LEN 108 30 | struct sockaddr_un { 31 | uint16_t sun_family; 32 | char sun_path[UNIX_PATH_LEN]; 33 | }; 34 | #else 35 | #include 36 | #include 37 | #endif 38 | 39 | #include "libupnp/minissdpc.h" 40 | #include "libupnp/miniupnpc.h" 41 | #include "libupnp/codelength.h" 42 | 43 | struct UPNPDev * 44 | getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath) 45 | { 46 | struct UPNPDev * tmp; 47 | struct UPNPDev * devlist = NULL; 48 | unsigned char buffer[2048]; 49 | ssize_t n; 50 | unsigned char * p; 51 | unsigned char * url; 52 | unsigned int i; 53 | unsigned int urlsize, stsize, usnsize, l; 54 | int s; 55 | struct sockaddr_un addr; 56 | 57 | s = socket(AF_UNIX, SOCK_STREAM, 0); 58 | if(s < 0) 59 | { 60 | /*syslog(LOG_ERR, "socket(unix): %m");*/ 61 | perror("socket(unix)"); 62 | return NULL; 63 | } 64 | addr.sun_family = AF_UNIX; 65 | strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path)); 66 | /* TODO : check if we need to handle the EINTR */ 67 | if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) 68 | { 69 | /*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/ 70 | close(s); 71 | return NULL; 72 | } 73 | stsize = strlen(devtype); 74 | buffer[0] = 1; /* request type 1 : request devices/services by type */ 75 | p = buffer + 1; 76 | l = stsize; CODELENGTH(l, p); 77 | if(p + stsize > buffer + sizeof(buffer)) 78 | { 79 | /* devtype is too long ! */ 80 | close(s); 81 | return NULL; 82 | } 83 | memcpy(p, devtype, stsize); 84 | p += stsize; 85 | if(write(s, buffer, p - buffer) < 0) 86 | { 87 | /*syslog(LOG_ERR, "write(): %m");*/ 88 | perror("minissdpc.c: write()"); 89 | close(s); 90 | return NULL; 91 | } 92 | n = read(s, buffer, sizeof(buffer)); 93 | if(n<=0) 94 | { 95 | perror("minissdpc.c: read()"); 96 | close(s); 97 | return NULL; 98 | } 99 | p = buffer + 1; 100 | for(i = 0; i < buffer[0]; i++) 101 | { 102 | if(p+2>=buffer+sizeof(buffer)) 103 | break; 104 | DECODELENGTH(urlsize, p); 105 | if(p+urlsize+2>=buffer+sizeof(buffer)) 106 | break; 107 | url = p; 108 | p += urlsize; 109 | DECODELENGTH(stsize, p); 110 | if(p+stsize+2>=buffer+sizeof(buffer)) 111 | break; 112 | tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize); 113 | tmp->pNext = devlist; 114 | tmp->descURL = tmp->buffer; 115 | tmp->st = tmp->buffer + 1 + urlsize; 116 | memcpy(tmp->buffer, url, urlsize); 117 | tmp->buffer[urlsize] = '\0'; 118 | memcpy(tmp->buffer + urlsize + 1, p, stsize); 119 | p += stsize; 120 | tmp->buffer[urlsize+1+stsize] = '\0'; 121 | devlist = tmp; 122 | /* added for compatibility with recent versions of MiniSSDPd 123 | * >= 2007/12/19 */ 124 | DECODELENGTH(usnsize, p); 125 | p += usnsize; 126 | if(p>buffer + sizeof(buffer)) 127 | break; 128 | } 129 | close(s); 130 | return devlist; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /lib/libupnp/miniupnpc.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | ; miniupnpc library 3 | 4 | EXPORTS 5 | ; miniupnpc 6 | upnpDiscover 7 | freeUPNPDevlist 8 | parserootdesc 9 | UPNP_GetValidIGD 10 | UPNP_GetIGDFromUrl 11 | GetUPNPUrls 12 | FreeUPNPUrls 13 | ; miniwget 14 | miniwget 15 | miniwget_getaddr 16 | ; upnpcommands 17 | UPNP_GetTotalBytesSent 18 | UPNP_GetTotalBytesReceived 19 | UPNP_GetTotalPacketsSent 20 | UPNP_GetTotalPacketsReceived 21 | UPNP_GetStatusInfo 22 | UPNP_GetConnectionTypeInfo 23 | UPNP_GetExternalIPAddress 24 | UPNP_GetLinkLayerMaxBitRates 25 | UPNP_AddPortMapping 26 | UPNP_DeletePortMapping 27 | UPNP_GetPortMappingNumberOfEntries 28 | UPNP_GetSpecificPortMappingEntry 29 | UPNP_GetGenericPortMappingEntry 30 | UPNP_GetListOfPortMappings 31 | UPNP_AddPinhole 32 | UPNP_CheckPinholeWorking 33 | UPNP_UpdatePinhole 34 | UPNP_GetPinholePackets 35 | UPNP_DeletePinhole 36 | UPNP_GetFirewallStatus 37 | UPNP_GetOutboundPinholeTimeout 38 | ; upnperrors 39 | strupnperror 40 | ; portlistingparse 41 | ParsePortListing 42 | FreePortListing 43 | -------------------------------------------------------------------------------- /lib/libupnp/minixml.c: -------------------------------------------------------------------------------- 1 | /* $Id: minixml.c,v 1.9 2011/02/07 13:44:57 nanard Exp $ */ 2 | /* minixml.c : the minimum size a xml parser can be ! */ 3 | /* Project : miniupnp 4 | * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 5 | * Author : Thomas Bernard 6 | 7 | Copyright (c) 2005-2011, Thomas BERNARD 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | * Redistributions of source code must retain the above copyright notice, 14 | this list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * The name of the author may not be used to endorse or promote products 19 | derived from this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | #include 34 | #include "libupnp/minixml.h" 35 | 36 | /* parseatt : used to parse the argument list 37 | * return 0 (false) in case of success and -1 (true) if the end 38 | * of the xmlbuffer is reached. */ 39 | static int parseatt(struct xmlparser * p) 40 | { 41 | const char * attname; 42 | int attnamelen; 43 | const char * attvalue; 44 | int attvaluelen; 45 | while(p->xml < p->xmlend) 46 | { 47 | if(*p->xml=='/' || *p->xml=='>') 48 | return 0; 49 | if( !IS_WHITE_SPACE(*p->xml) ) 50 | { 51 | char sep; 52 | attname = p->xml; 53 | attnamelen = 0; 54 | while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) ) 55 | { 56 | attnamelen++; p->xml++; 57 | if(p->xml >= p->xmlend) 58 | return -1; 59 | } 60 | while(*(p->xml++) != '=') 61 | { 62 | if(p->xml >= p->xmlend) 63 | return -1; 64 | } 65 | while(IS_WHITE_SPACE(*p->xml)) 66 | { 67 | p->xml++; 68 | if(p->xml >= p->xmlend) 69 | return -1; 70 | } 71 | sep = *p->xml; 72 | if(sep=='\'' || sep=='\"') 73 | { 74 | p->xml++; 75 | if(p->xml >= p->xmlend) 76 | return -1; 77 | attvalue = p->xml; 78 | attvaluelen = 0; 79 | while(*p->xml != sep) 80 | { 81 | attvaluelen++; p->xml++; 82 | if(p->xml >= p->xmlend) 83 | return -1; 84 | } 85 | } 86 | else 87 | { 88 | attvalue = p->xml; 89 | attvaluelen = 0; 90 | while( !IS_WHITE_SPACE(*p->xml) 91 | && *p->xml != '>' && *p->xml != '/') 92 | { 93 | attvaluelen++; p->xml++; 94 | if(p->xml >= p->xmlend) 95 | return -1; 96 | } 97 | } 98 | /*printf("%.*s='%.*s'\n", 99 | attnamelen, attname, attvaluelen, attvalue);*/ 100 | if(p->attfunc) 101 | p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen); 102 | } 103 | p->xml++; 104 | } 105 | return -1; 106 | } 107 | 108 | /* parseelt parse the xml stream and 109 | * call the callback functions when needed... */ 110 | static void parseelt(struct xmlparser * p) 111 | { 112 | int i; 113 | const char * elementname; 114 | while(p->xml < (p->xmlend - 1)) 115 | { 116 | if((p->xml)[0]=='<' && (p->xml)[1]!='?') 117 | { 118 | i = 0; elementname = ++p->xml; 119 | while( !IS_WHITE_SPACE(*p->xml) 120 | && (*p->xml!='>') && (*p->xml!='/') 121 | ) 122 | { 123 | i++; p->xml++; 124 | if (p->xml >= p->xmlend) 125 | return; 126 | /* to ignore namespace : */ 127 | if(*p->xml==':') 128 | { 129 | i = 0; 130 | elementname = ++p->xml; 131 | } 132 | } 133 | if(i>0) 134 | { 135 | if(p->starteltfunc) 136 | p->starteltfunc(p->data, elementname, i); 137 | if(parseatt(p)) 138 | return; 139 | if(*p->xml!='/') 140 | { 141 | const char * data; 142 | i = 0; data = ++p->xml; 143 | if (p->xml >= p->xmlend) 144 | return; 145 | while( IS_WHITE_SPACE(*p->xml) ) 146 | { 147 | i++; p->xml++; 148 | if (p->xml >= p->xmlend) 149 | return; 150 | } 151 | if(memcmp(p->xml, "xml += 9; 155 | data = p->xml; 156 | i = 0; 157 | while(memcmp(p->xml, "]]>", 3) != 0) 158 | { 159 | i++; p->xml++; 160 | if ((p->xml + 3) >= p->xmlend) 161 | return; 162 | } 163 | if(i>0 && p->datafunc) 164 | p->datafunc(p->data, data, i); 165 | while(*p->xml!='<') 166 | { 167 | p->xml++; 168 | if (p->xml >= p->xmlend) 169 | return; 170 | } 171 | } 172 | else 173 | { 174 | while(*p->xml!='<') 175 | { 176 | i++; p->xml++; 177 | if ((p->xml + 1) >= p->xmlend) 178 | return; 179 | } 180 | if(i>0 && p->datafunc && *(p->xml + 1) == '/') 181 | p->datafunc(p->data, data, i); 182 | } 183 | } 184 | } 185 | else if(*p->xml == '/') 186 | { 187 | i = 0; elementname = ++p->xml; 188 | if (p->xml >= p->xmlend) 189 | return; 190 | while((*p->xml != '>')) 191 | { 192 | i++; p->xml++; 193 | if (p->xml >= p->xmlend) 194 | return; 195 | } 196 | if(p->endeltfunc) 197 | p->endeltfunc(p->data, elementname, i); 198 | p->xml++; 199 | } 200 | } 201 | else 202 | { 203 | p->xml++; 204 | } 205 | } 206 | } 207 | 208 | /* the parser must be initialized before calling this function */ 209 | void parsexml(struct xmlparser * parser) 210 | { 211 | parser->xml = parser->xmlstart; 212 | parser->xmlend = parser->xmlstart + parser->xmlsize; 213 | parseelt(parser); 214 | } 215 | 216 | 217 | -------------------------------------------------------------------------------- /lib/libupnp/portlistingparse.c: -------------------------------------------------------------------------------- 1 | /* $Id: portlistingparse.c,v 1.6 2012/05/29 10:26:51 nanard Exp $ */ 2 | /* MiniUPnP project 3 | * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 4 | * (c) 2011 Thomas Bernard 5 | * This software is subject to the conditions detailed 6 | * in the LICENCE file provided within the distribution */ 7 | #include 8 | #include 9 | #include "libupnp/portlistingparse.h" 10 | #include "libupnp/minixml.h" 11 | 12 | /* list of the elements */ 13 | static const struct { 14 | const portMappingElt code; 15 | const char * const str; 16 | } elements[] = { 17 | { PortMappingEntry, "PortMappingEntry"}, 18 | { NewRemoteHost, "NewRemoteHost"}, 19 | { NewExternalPort, "NewExternalPort"}, 20 | { NewProtocol, "NewProtocol"}, 21 | { NewInternalPort, "NewInternalPort"}, 22 | { NewInternalClient, "NewInternalClient"}, 23 | { NewEnabled, "NewEnabled"}, 24 | { NewDescription, "NewDescription"}, 25 | { NewLeaseTime, "NewLeaseTime"}, 26 | { PortMappingEltNone, NULL} 27 | }; 28 | 29 | /* Helper function */ 30 | static UNSIGNED_INTEGER 31 | atoui(const char * p, int l) 32 | { 33 | UNSIGNED_INTEGER r = 0; 34 | while(l > 0 && *p) 35 | { 36 | if(*p >= '0' && *p <= '9') 37 | r = r*10 + (*p - '0'); 38 | else 39 | break; 40 | p++; 41 | l--; 42 | } 43 | return r; 44 | } 45 | 46 | /* Start element handler */ 47 | static void 48 | startelt(void * d, const char * name, int l) 49 | { 50 | int i; 51 | struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; 52 | pdata->curelt = PortMappingEltNone; 53 | for(i = 0; elements[i].str; i++) 54 | { 55 | if(memcmp(name, elements[i].str, l) == 0) 56 | { 57 | pdata->curelt = elements[i].code; 58 | break; 59 | } 60 | } 61 | if(pdata->curelt == PortMappingEntry) 62 | { 63 | struct PortMapping * pm; 64 | pm = calloc(1, sizeof(struct PortMapping)); 65 | LIST_INSERT_HEAD( &(pdata->head), pm, entries); 66 | } 67 | } 68 | 69 | /* End element handler */ 70 | static void 71 | endelt(void * d, const char * name, int l) 72 | { 73 | struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; 74 | (void)name; 75 | (void)l; 76 | pdata->curelt = PortMappingEltNone; 77 | } 78 | 79 | /* Data handler */ 80 | static void 81 | data(void * d, const char * data, int l) 82 | { 83 | struct PortMapping * pm; 84 | struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; 85 | pm = pdata->head.lh_first; 86 | if(!pm) 87 | return; 88 | if(l > 63) 89 | l = 63; 90 | switch(pdata->curelt) 91 | { 92 | case NewRemoteHost: 93 | memcpy(pm->remoteHost, data, l); 94 | pm->remoteHost[l] = '\0'; 95 | break; 96 | case NewExternalPort: 97 | pm->externalPort = (unsigned short)atoui(data, l); 98 | break; 99 | case NewProtocol: 100 | if(l > 3) 101 | l = 3; 102 | memcpy(pm->protocol, data, l); 103 | pm->protocol[l] = '\0'; 104 | break; 105 | case NewInternalPort: 106 | pm->internalPort = (unsigned short)atoui(data, l); 107 | break; 108 | case NewInternalClient: 109 | memcpy(pm->internalClient, data, l); 110 | pm->internalClient[l] = '\0'; 111 | break; 112 | case NewEnabled: 113 | pm->enabled = (unsigned char)atoui(data, l); 114 | break; 115 | case NewDescription: 116 | memcpy(pm->description, data, l); 117 | pm->description[l] = '\0'; 118 | break; 119 | case NewLeaseTime: 120 | pm->leaseTime = atoui(data, l); 121 | break; 122 | default: 123 | break; 124 | } 125 | } 126 | 127 | 128 | /* Parse the PortMappingList XML document for IGD version 2 129 | */ 130 | void 131 | ParsePortListing(const char * buffer, int bufsize, 132 | struct PortMappingParserData * pdata) 133 | { 134 | struct xmlparser parser; 135 | 136 | memset(pdata, 0, sizeof(struct PortMappingParserData)); 137 | LIST_INIT(&(pdata->head)); 138 | /* init xmlparser */ 139 | parser.xmlstart = buffer; 140 | parser.xmlsize = bufsize; 141 | parser.data = pdata; 142 | parser.starteltfunc = startelt; 143 | parser.endeltfunc = endelt; 144 | parser.datafunc = data; 145 | parser.attfunc = 0; 146 | parsexml(&parser); 147 | } 148 | 149 | void 150 | FreePortListing(struct PortMappingParserData * pdata) 151 | { 152 | struct PortMapping * pm; 153 | while((pm = pdata->head.lh_first) != NULL) 154 | { 155 | LIST_REMOVE(pm, entries); 156 | free(pm); 157 | } 158 | } 159 | 160 | -------------------------------------------------------------------------------- /lib/libupnp/receivedata.c: -------------------------------------------------------------------------------- 1 | /* $Id: receivedata.c,v 1.4 2012/06/23 22:34:47 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * Website : http://miniupnp.free.fr/ 4 | * Author : Thomas Bernard 5 | * Copyright (c) 2011-2012 Thomas Bernard 6 | * This software is subject to the conditions detailed in the 7 | * LICENCE file provided in this distribution. */ 8 | 9 | #include 10 | #ifdef _WIN32 11 | #include 12 | #include 13 | #else 14 | #include 15 | #if defined(__amigaos__) && !defined(__amigaos4__) 16 | #define socklen_t int 17 | #else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ 18 | #include 19 | #endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ 20 | #include 21 | #include 22 | #if !defined(__amigaos__) && !defined(__amigaos4__) 23 | #include 24 | #endif 25 | #include 26 | #define MINIUPNPC_IGNORE_EINTR 27 | #endif 28 | 29 | #ifdef _WIN32 30 | #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); 31 | #else 32 | #define PRINT_SOCKET_ERROR(x) perror(x) 33 | #endif 34 | 35 | #include "libupnp/receivedata.h" 36 | 37 | int 38 | receivedata(int socket, 39 | char * data, int length, 40 | int timeout, unsigned int * scope_id) 41 | { 42 | #if MINIUPNPC_GET_SRC_ADDR 43 | struct sockaddr_storage src_addr; 44 | socklen_t src_addr_len = sizeof(src_addr); 45 | #endif 46 | int n; 47 | #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) 48 | /* using poll */ 49 | struct pollfd fds[1]; /* for the poll */ 50 | #ifdef MINIUPNPC_IGNORE_EINTR 51 | do { 52 | #endif 53 | fds[0].fd = socket; 54 | fds[0].events = POLLIN; 55 | n = poll(fds, 1, timeout); 56 | #ifdef MINIUPNPC_IGNORE_EINTR 57 | } while(n < 0 && errno == EINTR); 58 | #endif 59 | if(n < 0) { 60 | PRINT_SOCKET_ERROR("poll"); 61 | return -1; 62 | } else if(n == 0) { 63 | /* timeout */ 64 | return 0; 65 | } 66 | #else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ 67 | /* using select under _WIN32 and amigaos */ 68 | fd_set socketSet; 69 | TIMEVAL timeval; 70 | FD_ZERO(&socketSet); 71 | FD_SET(socket, &socketSet); 72 | timeval.tv_sec = timeout / 1000; 73 | timeval.tv_usec = (timeout % 1000) * 1000; 74 | n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval); 75 | if(n < 0) { 76 | PRINT_SOCKET_ERROR("select"); 77 | return -1; 78 | } else if(n == 0) { 79 | return 0; 80 | } 81 | #endif 82 | #if MINIUPNPC_GET_SRC_ADDR 83 | n = recvfrom(socket, data, length, 0, 84 | (struct sockaddr *)&src_addr, &src_addr_len); 85 | #else 86 | n = recv(socket, data, length, 0); 87 | #endif 88 | if(n<0) { 89 | PRINT_SOCKET_ERROR("recv"); 90 | } 91 | #if MINIUPNPC_GET_SRC_ADDR 92 | if (src_addr.ss_family == AF_INET6) { 93 | const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; 94 | #ifdef DEBUG 95 | printf("scope_id=%u\n", src_addr6->sin6_scope_id); 96 | #endif 97 | if(scope_id) 98 | *scope_id = src_addr6->sin6_scope_id; 99 | } 100 | #endif 101 | return n; 102 | } 103 | 104 | 105 | -------------------------------------------------------------------------------- /lib/libupnp/upnperrors.c: -------------------------------------------------------------------------------- 1 | /* $Id: upnperrors.c,v 1.5 2011/04/10 11:19:36 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * Author : Thomas BERNARD 4 | * copyright (c) 2007 Thomas Bernard 5 | * All Right reserved. 6 | * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 7 | * This software is subjet to the conditions detailed in the 8 | * provided LICENCE file. */ 9 | #include 10 | #include "libupnp/upnperrors.h" 11 | #include "libupnp/upnpcommands.h" 12 | #include "libupnp/miniupnpc.h" 13 | 14 | const char * strupnperror(int err) 15 | { 16 | const char * s = NULL; 17 | switch(err) { 18 | case UPNPCOMMAND_SUCCESS: 19 | s = "Success"; 20 | break; 21 | case UPNPCOMMAND_UNKNOWN_ERROR: 22 | s = "Miniupnpc Unknown Error"; 23 | break; 24 | case UPNPCOMMAND_INVALID_ARGS: 25 | s = "Miniupnpc Invalid Arguments"; 26 | break; 27 | case UPNPDISCOVER_SOCKET_ERROR: 28 | s = "Miniupnpc Socket error"; 29 | break; 30 | case UPNPDISCOVER_MEMORY_ERROR: 31 | s = "Miniupnpc Memory allocation error"; 32 | break; 33 | case 401: 34 | s = "Invalid Action"; 35 | break; 36 | case 402: 37 | s = "Invalid Args"; 38 | break; 39 | case 501: 40 | s = "Action Failed"; 41 | break; 42 | case 606: 43 | s = "Action not authorized"; 44 | break; 45 | case 701: 46 | s = "PinholeSpaceExhausted"; 47 | break; 48 | case 702: 49 | s = "FirewallDisabled"; 50 | break; 51 | case 703: 52 | s = "InboundPinholeNotAllowed"; 53 | break; 54 | case 704: 55 | s = "NoSuchEntry"; 56 | break; 57 | case 705: 58 | s = "ProtocolNotSupported"; 59 | break; 60 | case 706: 61 | s = "InternalPortWildcardingNotAllowed"; 62 | break; 63 | case 707: 64 | s = "ProtocolWildcardingNotAllowed"; 65 | break; 66 | case 708: 67 | s = "WildcardNotPermittedInSrcIP"; 68 | break; 69 | case 709: 70 | s = "NoPacketSent"; 71 | break; 72 | case 713: 73 | s = "SpecifiedArrayIndexInvalid"; 74 | break; 75 | case 714: 76 | s = "NoSuchEntryInArray"; 77 | break; 78 | case 715: 79 | s = "WildCardNotPermittedInSrcIP"; 80 | break; 81 | case 716: 82 | s = "WildCardNotPermittedInExtPort"; 83 | break; 84 | case 718: 85 | s = "ConflictInMappingEntry"; 86 | break; 87 | case 724: 88 | s = "SamePortValuesRequired"; 89 | break; 90 | case 725: 91 | s = "OnlyPermanentLeasesSupported"; 92 | break; 93 | case 726: 94 | s = "RemoteHostOnlySupportsWildcard"; 95 | break; 96 | case 727: 97 | s = "ExternalPortOnlySupportsWildcard"; 98 | break; 99 | default: 100 | s = "UnknownError"; 101 | break; 102 | } 103 | return s; 104 | } 105 | -------------------------------------------------------------------------------- /lib/libupnp/upnpreplyparse.c: -------------------------------------------------------------------------------- 1 | /* $Id: upnpreplyparse.c,v 1.11 2011/02/07 16:17:06 nanard Exp $ */ 2 | /* MiniUPnP project 3 | * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 4 | * (c) 2006-2011 Thomas Bernard 5 | * This software is subject to the conditions detailed 6 | * in the LICENCE file provided within the distribution */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include "libupnp/upnpreplyparse.h" 12 | #include "libupnp/minixml.h" 13 | 14 | static void 15 | NameValueParserStartElt(void * d, const char * name, int l) 16 | { 17 | struct NameValueParserData * data = (struct NameValueParserData *)d; 18 | if(l>63) 19 | l = 63; 20 | memcpy(data->curelt, name, l); 21 | data->curelt[l] = '\0'; 22 | } 23 | 24 | static void 25 | NameValueParserGetData(void * d, const char * datas, int l) 26 | { 27 | struct NameValueParserData * data = (struct NameValueParserData *)d; 28 | struct NameValue * nv; 29 | if(strcmp(data->curelt, "NewPortListing") == 0) 30 | { 31 | /* specific case for NewPortListing which is a XML Document */ 32 | data->portListing = malloc(l + 1); 33 | if(!data->portListing) 34 | { 35 | /* malloc error */ 36 | return; 37 | } 38 | memcpy(data->portListing, datas, l); 39 | data->portListing[l] = '\0'; 40 | data->portListingLength = l; 41 | } 42 | else 43 | { 44 | /* standard case. Limited to 63 chars strings */ 45 | nv = malloc(sizeof(struct NameValue)); 46 | if(l>63) 47 | l = 63; 48 | strncpy(nv->name, data->curelt, 64); 49 | nv->name[63] = '\0'; 50 | memcpy(nv->value, datas, l); 51 | nv->value[l] = '\0'; 52 | LIST_INSERT_HEAD( &(data->head), nv, entries); 53 | } 54 | } 55 | 56 | void 57 | ParseNameValue(const char * buffer, int bufsize, 58 | struct NameValueParserData * data) 59 | { 60 | struct xmlparser parser; 61 | LIST_INIT(&(data->head)); 62 | data->portListing = NULL; 63 | data->portListingLength = 0; 64 | /* init xmlparser object */ 65 | parser.xmlstart = buffer; 66 | parser.xmlsize = bufsize; 67 | parser.data = data; 68 | parser.starteltfunc = NameValueParserStartElt; 69 | parser.endeltfunc = 0; 70 | parser.datafunc = NameValueParserGetData; 71 | parser.attfunc = 0; 72 | parsexml(&parser); 73 | } 74 | 75 | void 76 | ClearNameValueList(struct NameValueParserData * pdata) 77 | { 78 | struct NameValue * nv; 79 | if(pdata->portListing) 80 | { 81 | free(pdata->portListing); 82 | pdata->portListing = NULL; 83 | pdata->portListingLength = 0; 84 | } 85 | while((nv = pdata->head.lh_first) != NULL) 86 | { 87 | LIST_REMOVE(nv, entries); 88 | free(nv); 89 | } 90 | } 91 | 92 | char * 93 | GetValueFromNameValueList(struct NameValueParserData * pdata, 94 | const char * Name) 95 | { 96 | struct NameValue * nv; 97 | char * p = NULL; 98 | for(nv = pdata->head.lh_first; 99 | (nv != NULL) && (p == NULL); 100 | nv = nv->entries.le_next) 101 | { 102 | if(strcmp(nv->name, Name) == 0) 103 | p = nv->value; 104 | } 105 | return p; 106 | } 107 | 108 | #if 0 109 | /* useless now that minixml ignores namespaces by itself */ 110 | char * 111 | GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, 112 | const char * Name) 113 | { 114 | struct NameValue * nv; 115 | char * p = NULL; 116 | char * pname; 117 | for(nv = pdata->head.lh_first; 118 | (nv != NULL) && (p == NULL); 119 | nv = nv->entries.le_next) 120 | { 121 | pname = strrchr(nv->name, ':'); 122 | if(pname) 123 | pname++; 124 | else 125 | pname = nv->name; 126 | if(strcmp(pname, Name)==0) 127 | p = nv->value; 128 | } 129 | return p; 130 | } 131 | #endif 132 | 133 | /* debug all-in-one function 134 | * do parsing then display to stdout */ 135 | #ifdef DEBUG 136 | void 137 | DisplayNameValueList(char * buffer, int bufsize) 138 | { 139 | struct NameValueParserData pdata; 140 | struct NameValue * nv; 141 | ParseNameValue(buffer, bufsize, &pdata); 142 | for(nv = pdata.head.lh_first; 143 | nv != NULL; 144 | nv = nv->entries.le_next) 145 | { 146 | printf("%s = %s\n", nv->name, nv->value); 147 | } 148 | ClearNameValueList(&pdata); 149 | } 150 | #endif 151 | 152 | -------------------------------------------------------------------------------- /lib/maidsafe_calllatertimer.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include "nat/maidsafe_calllatertimer.h" 30 | #include "arsenal/logging.h" 31 | 32 | using scoped_lock = std::unique_lock; 33 | 34 | namespace base { 35 | 36 | void dummy_timeout_func() {} 37 | 38 | CallLaterTimer::CallLaterTimer() 39 | : timers_mutex_(), 40 | is_started_(true), 41 | timers_(), 42 | io_service_(), 43 | strand_(io_service_), 44 | work_(new boost::asio::io_service::work(io_service_)), 45 | worker_thread_(), 46 | call_later_id_(0) 47 | { 48 | worker_thread_.reset(new std::thread(&CallLaterTimer::Run, this)); 49 | } 50 | 51 | CallLaterTimer::~CallLaterTimer() 52 | { 53 | CancelAll(); 54 | { 55 | scoped_lock guard(timers_mutex_); 56 | is_started_ = false; 57 | } 58 | // Allow io_service_.run() to exit. 59 | work_.reset(); 60 | worker_thread_->join(); 61 | } 62 | 63 | void CallLaterTimer::Run() { 64 | while (true) { 65 | try { 66 | io_service_.run(); 67 | break; 68 | } catch(const std::exception &e) { 69 | logger::warning() << e.what() << std::endl; 70 | } 71 | } 72 | } 73 | 74 | void CallLaterTimer::ExecuteFunctor( 75 | const VoidFunctorEmpty &callback, 76 | const uint32_t &call_later_id, 77 | const boost::system::error_code &error_code) 78 | { 79 | if (error_code) { 80 | if (error_code != boost::asio::error::operation_aborted) { 81 | logger::warning() << error_code.message() << std::endl; 82 | scoped_lock guard(timers_mutex_); 83 | timers_.erase(call_later_id); 84 | } 85 | } else { 86 | strand_.dispatch(callback); 87 | scoped_lock guard(timers_mutex_); 88 | timers_.erase(call_later_id); 89 | } 90 | } 91 | 92 | uint32_t CallLaterTimer::AddCallLater(const uint64_t &msecs, VoidFunctorEmpty callback) 93 | { 94 | scoped_lock guard(timers_mutex_); 95 | if ((msecs == 0) || (!is_started_)) 96 | return std::numeric_limits::max(); 97 | call_later_id_ = (call_later_id_ + 1) % 32768; 98 | std::shared_ptr timer( 99 | new boost::asio::deadline_timer(io_service_, 100 | boost::posix_time::milliseconds(msecs))); 101 | std::pair p = 102 | timers_.insert(TimersMap::value_type(call_later_id_, timer)); 103 | if (p.second) { 104 | timer->async_wait(boost::bind(&CallLaterTimer::ExecuteFunctor, this, 105 | callback, call_later_id_, _1)); 106 | return call_later_id_; 107 | } 108 | return std::numeric_limits::max(); 109 | } 110 | 111 | bool CallLaterTimer::CancelOne(const boost::uint32_t &call_later_id) 112 | { 113 | scoped_lock guard(timers_mutex_); 114 | TimersMap::iterator it = timers_.find(call_later_id); 115 | if (it == timers_.end()) 116 | return false; 117 | it->second->cancel(); 118 | timers_.erase(call_later_id); 119 | return true; 120 | } 121 | 122 | int CallLaterTimer::CancelAll() 123 | { 124 | scoped_lock guard(timers_mutex_); 125 | int n = timers_.size(); 126 | for (TimersMap::iterator it = timers_.begin(); it != timers_.end(); ++it) { 127 | it->second->cancel(); 128 | } 129 | timers_.clear(); 130 | return n; 131 | } 132 | 133 | size_t CallLaterTimer::TimersMapSize() { 134 | scoped_lock guard(timers_mutex_); 135 | return timers_.size(); 136 | } 137 | } // namespace base 138 | -------------------------------------------------------------------------------- /lib/maidsafe_gateway.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | Created by Julian Cain on 11/3/09. 28 | 29 | */ 30 | 31 | #include "nat/maidsafe_gateway.h" 32 | 33 | #if (defined(MAIDSAFE_APPLE) || defined(MAIDSAFE_POSIX) || defined(__MACH__)) \ 34 | && !defined(MAIDSAFE_LINUX) 35 | #include 36 | #include 37 | #include 38 | #elif defined(MAIDSAFE_WIN32) 39 | #ifndef WIN32_LEAN_AND_MEAN 40 | #define WIN32_LEAN_AND_MEAN 41 | #endif // WIN32_LEAN_AND_MEAN 42 | #include 43 | #include 44 | #elif defined(MAIDSAFE_LINUX) 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #endif 54 | 55 | #include 56 | 57 | namespace base { 58 | 59 | boost::asio::ip::address Gateway::DefaultRoute( 60 | boost::asio::io_service & ios, 61 | boost::system::error_code & ec) { 62 | std::vector ret = Routes(ios, ec); 63 | #if defined(MAIDSAFE_WIN32) 64 | std::vector::iterator it = std::find_if( 65 | ret.begin(), 66 | ret.end(), 67 | boost::bind( 68 | &NetworkInterface::IsLoopback, 69 | boost::bind(&NetworkInterface::destination, _1))); 70 | #else 71 | std::vector::iterator it = std::find_if( 72 | ret.begin(), 73 | ret.end(), 74 | boost::bind( 75 | &NetworkInterface::destination, _1) == boost::asio::ip::address()); 76 | #endif 77 | if (it == ret.end()) { 78 | return boost::asio::ip::address(); 79 | } 80 | return it->gateway; 81 | } 82 | 83 | #if (defined(MAIDSAFE_APPLE) || defined(MAIDSAFE_POSIX) || defined(__MACH__)) \ 84 | && !defined(MAIDSAFE_LINUX) 85 | 86 | inline int32_t RoundUp(int32_t val) { 87 | return ((val) > 0 ? (1 + (((val) - 1) | (sizeof(int32_t) - 1))) : 88 | sizeof(int32_t)); 89 | } 90 | 91 | bool Gateway::ParseRtMsghdr(rt_msghdr * rtm, NetworkInterface & rt_if) { 92 | sockaddr * rti_info[RTAX_MAX]; 93 | sockaddr * sa = reinterpret_cast(rtm + 1); 94 | 95 | for (unsigned int i = 0; i < RTAX_MAX; ++i) { 96 | if ((rtm->rtm_addrs & (1 << i)) == 0) { 97 | rti_info[i] = 0; 98 | continue; 99 | } 100 | 101 | rti_info[i] = sa; 102 | 103 | sa = reinterpret_cast(reinterpret_cast(sa) + 104 | RoundUp(sa->sa_len)); 105 | } 106 | 107 | sa = rti_info[RTAX_GATEWAY]; 108 | 109 | if (sa == 0 || rti_info[RTAX_DST] == 0 || rti_info[RTAX_NETMASK] == 0 || 110 | (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)) { 111 | return false; 112 | } 113 | 114 | rt_if.gateway = NetworkInterface::SockaddrToAddress(rti_info[RTAX_GATEWAY]); 115 | 116 | rt_if.netmask = NetworkInterface::SockaddrToAddress(rti_info[RTAX_NETMASK]); 117 | 118 | rt_if.destination = NetworkInterface::SockaddrToAddress(rti_info[RTAX_DST]); 119 | 120 | if_indextoname(rtm->rtm_index, rt_if.name); 121 | 122 | return true; 123 | } 124 | 125 | #elif defined(MAIDSAFE_LINUX) 126 | 127 | int Gateway::ReadNetlinkSock(int sock, char * buf, int len, int seq, int pid) { 128 | nlmsghdr * nl_hdr; 129 | 130 | int msg_len = 0; 131 | 132 | do { 133 | int read_len = recv(sock, buf, len - msg_len, 0); 134 | 135 | if (read_len < 0) { 136 | return -1; 137 | } 138 | 139 | nl_hdr = reinterpret_cast(buf); 140 | 141 | if ((NLMSG_OK(nl_hdr, static_cast(read_len)) == 0) || 142 | (nl_hdr->nlmsg_type == NLMSG_ERROR)) { 143 | return -1; 144 | } 145 | 146 | if (nl_hdr->nlmsg_type == NLMSG_DONE) { 147 | break; 148 | } 149 | 150 | buf += read_len; 151 | 152 | msg_len += read_len; 153 | 154 | if ((nl_hdr->nlmsg_flags & NLM_F_MULTI) == 0) { 155 | break; 156 | } 157 | } while ((nl_hdr->nlmsg_seq != boost::uint32_t(seq)) || 158 | (nl_hdr->nlmsg_pid != boost::uint32_t(pid))); 159 | 160 | return msg_len; 161 | } 162 | 163 | bool Gateway::ParseNlmsghdr(nlmsghdr * nl_hdr, NetworkInterface & rt_if) { 164 | rtmsg * rt_msg = reinterpret_cast(NLMSG_DATA(nl_hdr)); 165 | 166 | if ((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN)) { 167 | return false; 168 | } 169 | 170 | int rt_len = RTM_PAYLOAD(nl_hdr); 171 | 172 | rtattr * rt_attr = reinterpret_cast(RTM_RTA(rt_msg)); 173 | 174 | for (; RTA_OK(rt_attr, rt_len); rt_attr = RTA_NEXT(rt_attr, rt_len)) { 175 | switch (rt_attr->rta_type) { 176 | case RTA_OIF: 177 | if_indextoname(*reinterpret_cast(RTA_DATA(rt_attr)), rt_if.name); 178 | break; 179 | case RTA_GATEWAY: 180 | rt_if.gateway = boost::asio::ip::address_v4( 181 | ntohl(*reinterpret_cast(RTA_DATA(rt_attr)))); 182 | break; 183 | case RTA_DST: 184 | rt_if.destination = boost::asio::ip::address_v4( 185 | ntohl(*reinterpret_cast(RTA_DATA(rt_attr)))); 186 | break; 187 | } 188 | } 189 | return true; 190 | } 191 | 192 | #endif 193 | 194 | std::vector Gateway::Routes(boost::asio::io_service&, 195 | boost::system::error_code &ec) { 196 | std::vector ret; 197 | 198 | #if (defined(MAIDSAFE_APPLE) || defined(MAIDSAFE_POSIX) || defined(__MACH__)) \ 199 | && !defined(MAIDSAFE_LINUX) 200 | 201 | int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0 }; 202 | 203 | std::size_t needed = 0; 204 | 205 | if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) { 206 | ec = boost::system::error_code(errno, boost::asio::error::system_category); 207 | return std::vector(); 208 | } 209 | 210 | if (needed <= 0) { 211 | return std::vector(); 212 | } 213 | 214 | boost::scoped_ptr buf(new char[needed]); 215 | 216 | if (sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0) { 217 | ec = boost::system::error_code(errno, boost::asio::error::system_category); 218 | return std::vector(); 219 | } 220 | 221 | char * end = buf.get() + needed; 222 | 223 | rt_msghdr * rtm; 224 | 225 | for (char * next = buf.get(); next < end; next += rtm->rtm_msglen) { 226 | rtm = reinterpret_cast(next); 227 | 228 | if (rtm->rtm_version != RTM_VERSION) { 229 | continue; 230 | } 231 | 232 | NetworkInterface r; 233 | 234 | if (ParseRtMsghdr(rtm, r)) { 235 | ret.push_back(r); 236 | } 237 | } 238 | 239 | #elif defined(MAIDSAFE_WIN32) 240 | 241 | HMODULE iphlp = LoadLibraryA("Iphlpapi.dll"); 242 | 243 | if (!iphlp) { 244 | ec = boost::asio::error::operation_not_supported; 245 | return std::vector(); 246 | } 247 | 248 | typedef DWORD(WINAPI *GetAdaptersInfo_t)(PIP_ADAPTER_INFO, PULONG); 249 | 250 | GetAdaptersInfo_t GetAdaptersInfo = 251 | (GetAdaptersInfo_t)GetProcAddress(iphlp, "GetAdaptersInfo"); 252 | 253 | if (!GetAdaptersInfo) { 254 | FreeLibrary(iphlp); 255 | ec = boost::asio::error::operation_not_supported; 256 | return std::vector(); 257 | } 258 | 259 | PIP_ADAPTER_INFO adapter_info = 0; 260 | 261 | ULONG out_buf_size = 0; 262 | 263 | if (GetAdaptersInfo(adapter_info, &out_buf_size) != ERROR_BUFFER_OVERFLOW) { 264 | FreeLibrary(iphlp); 265 | ec = boost::asio::error::operation_not_supported; 266 | return std::vector(); 267 | } 268 | 269 | adapter_info = new IP_ADAPTER_INFO[out_buf_size]; 270 | 271 | if (GetAdaptersInfo(adapter_info, &out_buf_size) == NO_ERROR) { 272 | for (PIP_ADAPTER_INFO adapter = adapter_info; adapter != 0; 273 | adapter = adapter->Next) { 274 | NetworkInterface r; 275 | 276 | r.destination = boost::asio::ip::address::from_string( 277 | adapter->IpAddressList.IpAddress.String, 278 | ec); 279 | 280 | r.gateway = boost::asio::ip::address::from_string( 281 | adapter->GatewayList.IpAddress.String, 282 | ec); 283 | 284 | r.netmask = boost::asio::ip::address::from_string( 285 | adapter->IpAddressList.IpMask.String, 286 | ec); 287 | 288 | strncpy(r.name, adapter->AdapterName, sizeof(r.name)); 289 | 290 | if (ec) { 291 | ec = boost::system::error_code(); 292 | continue; 293 | } 294 | ret.push_back(r); 295 | } 296 | } 297 | 298 | delete adapter_info, adapter_info = 0; 299 | FreeLibrary(iphlp); 300 | 301 | #elif defined(MAIDSAFE_LINUX) 302 | 303 | enum { kBufSize = 8192 }; 304 | 305 | int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE); 306 | 307 | if (sock < 0) { 308 | ec = boost::system::error_code(errno, boost::asio::error::system_category); 309 | return std::vector(); 310 | } 311 | 312 | int seq = 0; 313 | 314 | char msg[kBufSize]; 315 | 316 | std::memset(msg, 0, kBufSize); 317 | 318 | nlmsghdr * nl_msg = reinterpret_cast(msg); 319 | 320 | nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg)); 321 | nl_msg->nlmsg_type = RTM_GETROUTE; 322 | nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; 323 | nl_msg->nlmsg_seq = seq++; 324 | nl_msg->nlmsg_pid = getpid(); 325 | 326 | if (send(sock, nl_msg, nl_msg->nlmsg_len, 0) < 0) { 327 | ec = boost::system::error_code(errno, boost::asio::error::system_category); 328 | 329 | close(sock); 330 | 331 | return std::vector(); 332 | } 333 | 334 | int len = ReadNetlinkSock(sock, msg, kBufSize, seq, getpid()); 335 | 336 | if (len < 0) { 337 | ec = boost::system::error_code(errno, boost::asio::error::system_category); 338 | 339 | close(sock); 340 | 341 | return std::vector(); 342 | } 343 | 344 | for (; NLMSG_OK(nl_msg, static_cast(len)); 345 | nl_msg = NLMSG_NEXT(nl_msg, len)) { 346 | NetworkInterface intf; 347 | 348 | if (ParseNlmsghdr(nl_msg, intf)) { 349 | ret.push_back(intf); 350 | } 351 | } 352 | close(sock); 353 | 354 | #endif 355 | return ret; 356 | } 357 | 358 | } // namespace base 359 | -------------------------------------------------------------------------------- /lib/maidsafe_network_interface.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | Created by Julian Cain on 11/3/09. 28 | 29 | */ 30 | 31 | #include "nat/maidsafe_network_interface.h" 32 | #include "nat/maidsafe-dht_config.h" // NOLINT (Fraser) - This is needed for preprocessor definitions 33 | 34 | #if !defined (MAIDSAFE_WIN32) 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #endif 44 | 45 | namespace base { 46 | 47 | bool NetworkInterface::IsLocal(const boost::asio::ip::address & addr) { 48 | if (addr.is_v6()) { 49 | return addr.to_v6().is_link_local(); 50 | } else { 51 | boost::asio::ip::address_v4 a4 = addr.to_v4(); 52 | 53 | boost::uint32_t ip = a4.to_ulong(); 54 | 55 | return ( 56 | (ip & 0xff000000) == 0x0a000000 || 57 | (ip & 0xfff00000) == 0xac100000 || 58 | (ip & 0xffff0000) == 0xc0a80000); 59 | } 60 | 61 | return false; 62 | } 63 | 64 | bool NetworkInterface::IsLoopback(const boost::asio::ip::address & addr) { 65 | if (addr.is_v4()) { 66 | return addr.to_v4() == boost::asio::ip::address_v4::loopback(); 67 | } else { 68 | return addr.to_v6() == boost::asio::ip::address_v6::loopback(); 69 | } 70 | } 71 | 72 | bool NetworkInterface::IsMulticast(const boost::asio::ip::address & addr) { 73 | if (addr.is_v4()) { 74 | return addr.to_v4().is_multicast(); 75 | } else { 76 | return addr.to_v6().is_multicast(); 77 | } 78 | } 79 | 80 | bool NetworkInterface::IsAny(const boost::asio::ip::address & addr) { 81 | if (addr.is_v4()) { 82 | return addr.to_v4() == boost::asio::ip::address_v4::any(); 83 | } else { 84 | /* Currently only supporting IPv4 as IPv6 has yet to be tested */ 85 | // TODO(Alec): Test system using IPv6 addresses 86 | return /*addr.to_v6() == boost::asio::ip::address_v6::any()*/true; 87 | } 88 | } 89 | 90 | boost::asio::ip::address NetworkInterface::InaddrToAddress( 91 | const in_addr * addr) { 92 | typedef boost::asio::ip::address_v4::bytes_type bytes_t; 93 | bytes_t b; 94 | std::memcpy(&b[0], addr, b.size()); 95 | return boost::asio::ip::address_v4(b); 96 | } 97 | 98 | boost::asio::ip::address NetworkInterface::Inaddr6ToAddress( 99 | const in6_addr * addr) { 100 | typedef boost::asio::ip::address_v6::bytes_type bytes_t; 101 | bytes_t b; 102 | std::memcpy(&b[0], addr, b.size()); 103 | return boost::asio::ip::address_v6(b); 104 | } 105 | 106 | boost::asio::ip::address NetworkInterface::SockaddrToAddress( 107 | const sockaddr * addr) { 108 | if (addr->sa_family == AF_INET) { 109 | in_addr address = (reinterpret_cast(addr))->sin_addr; 110 | return InaddrToAddress(&address); 111 | } else if (addr->sa_family == AF_INET6) { 112 | in6_addr address = (reinterpret_cast(addr))->sin6_addr; 113 | return Inaddr6ToAddress(&address); 114 | } 115 | return boost::asio::ip::address(); 116 | } 117 | 118 | #if (defined(MAIDSAFE_APPLE) || defined(MAIDSAFE_POSIX) || defined(__MACH__)) \ 119 | && !defined(MAIDSAFE_LINUX) 120 | static bool VerifySockaddr(sockaddr_in * sin) { 121 | return (sin->sin_len == sizeof(sockaddr_in) && sin->sin_family == AF_INET) || 122 | (sin->sin_len == sizeof(sockaddr_in6) && sin->sin_family == AF_INET6); 123 | } 124 | #endif 125 | 126 | boost::asio::ip::address NetworkInterface::LocalAddress() { 127 | boost::system::error_code ec; 128 | boost::asio::ip::address ret = boost::asio::ip::address_v4::any(); 129 | 130 | const std::vector & interfaces = LocalList(ec); 131 | 132 | std::vector::const_iterator it = interfaces.begin(); 133 | 134 | for (; it != interfaces.end(); ++it) { 135 | const boost::asio::ip::address & a = (*it).destination; 136 | 137 | // Skip loopback, multicast and any. 138 | if (IsLoopback(a)|| IsMulticast(a) || IsAny(a)) { 139 | continue; 140 | } 141 | 142 | // :NOTE: Other properties could be checked here such as the IFF_UP flag. 143 | 144 | // Prefer an ipv4 address over v6. 145 | if (a.is_v4()) { 146 | ret = a; 147 | break; 148 | } 149 | 150 | // If this one is not any then return it. 151 | if (ret != boost::asio::ip::address_v4::any()) { 152 | ret = a; 153 | } 154 | } 155 | 156 | return ret; 157 | } 158 | 159 | std::vector NetworkInterface::LocalList( 160 | boost::system::error_code & ec) { 161 | std::vector ret; 162 | 163 | #if defined(MAIDSAFE_LINUX) || defined(MAIDSAFE_APPLE) || \ 164 | defined(MAIDSAFE_POSIX) || defined(__MACH__) 165 | 166 | int s = socket(AF_INET, SOCK_DGRAM, 0); 167 | 168 | if (s < 0) { 169 | ec = boost::asio::error::fault; 170 | return ret; 171 | } 172 | 173 | ifconf ifc; 174 | char buf[1024]; 175 | 176 | ifc.ifc_len = sizeof(buf); 177 | ifc.ifc_buf = buf; 178 | 179 | if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { 180 | ec = boost::system::error_code(errno, boost::asio::error::system_category); 181 | 182 | close(s); 183 | 184 | return ret; 185 | } 186 | 187 | char *ifr = reinterpret_cast(ifc.ifc_req); 188 | 189 | int remaining = ifc.ifc_len; 190 | 191 | while (remaining) { 192 | const ifreq & item = *reinterpret_cast(ifr); 193 | 194 | if (item.ifr_addr.sa_family == AF_INET || 195 | item.ifr_addr.sa_family == AF_INET6) { 196 | NetworkInterface iface; 197 | 198 | iface.destination = SockaddrToAddress(&item.ifr_addr); 199 | 200 | // strcpy(iface.name, item.ifr_name); 201 | snprintf(iface.name, sizeof(iface.name), "%s", item.ifr_name); 202 | 203 | ifreq netmask = item; 204 | 205 | if (ioctl(s, SIOCGIFNETMASK, &netmask) < 0) { 206 | if (iface.destination.is_v6()) { 207 | iface.netmask = boost::asio::ip::address_v6::any(); 208 | } else { 209 | ec = boost::system::error_code(errno, 210 | boost::asio::error::system_category); 211 | 212 | close(s); 213 | 214 | return ret; 215 | } 216 | } else { 217 | iface.netmask = SockaddrToAddress(&netmask.ifr_addr); 218 | } 219 | ret.push_back(iface); 220 | } 221 | 222 | #if !defined(MAIDSAFE_LINUX) 223 | std::size_t if_size = item.ifr_addr.sa_len + IFNAMSIZ; 224 | #else 225 | std::size_t if_size = sizeof(ifreq); 226 | #endif 227 | ifr += if_size; 228 | remaining -= if_size; 229 | } 230 | 231 | close(s); 232 | 233 | #elif defined(MAIDSAFE_WIN32) 234 | 235 | SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); 236 | 237 | if (static_cast(s) == SOCKET_ERROR) { 238 | ec = boost::system::error_code(WSAGetLastError(), 239 | boost::asio::error::system_category); 240 | 241 | return ret; 242 | } 243 | 244 | INTERFACE_INFO buf[30]; 245 | 246 | DWORD size; 247 | 248 | int err = WSAIoctl(s, SIO_GET_INTERFACE_LIST, 0, 0, buf, sizeof(buf), &size, 249 | 0, 0); 250 | 251 | if (err != 0) { 252 | ec = boost::system::error_code(WSAGetLastError(), 253 | boost::asio::error::system_category); 254 | 255 | closesocket(s); 256 | 257 | return ret; 258 | } 259 | 260 | closesocket(s); 261 | 262 | std::size_t n = size / sizeof(INTERFACE_INFO); 263 | 264 | NetworkInterface iface; 265 | 266 | for (std::size_t i = 0; i < n; ++i) { 267 | iface.destination = SockaddrToAddress(&buf[i].iiAddress.Address); 268 | 269 | iface.netmask = SockaddrToAddress(&buf[i].iiNetmask.Address); 270 | 271 | iface.name[0] = 0; 272 | 273 | if (iface.destination == boost::asio::ip::address_v4::any()) { 274 | continue; 275 | } 276 | ret.push_back(iface); 277 | } 278 | #else 279 | #error "Unsupported Device or Platform." 280 | #endif 281 | return ret; 282 | } 283 | 284 | } // namespace base 285 | -------------------------------------------------------------------------------- /lib/maidsafe_utils.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include "nat/maidsafe_utils.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "nat/maidsafe_network_interface.h" 38 | 39 | namespace base { 40 | 41 | // POSIX and APPLE Socket implementation 42 | #if defined(MAIDSAFE_POSIX) || defined (MAIDSAFE_APPLE) 43 | // || defined (__MINGW__) 44 | static boost::uint32_t SockAddrToUint32(struct sockaddr * a) { 45 | return ((a)&&(a->sa_family == AF_INET)) ? 46 | ntohl(((struct sockaddr_in *)a)->sin_addr.s_addr) : 0; 47 | } 48 | #endif 49 | 50 | void GetNetInterfaces(std::vector *alldevices) { 51 | alldevices->clear(); 52 | boost::system::error_code ec; 53 | std::vector net_interfaces; 54 | net_interfaces = NetworkInterface::LocalList(ec); 55 | if (ec) 56 | return; 57 | for (std::vector::iterator it = net_interfaces.begin(); 58 | it != net_interfaces.end(); ++it) { 59 | DeviceStruct device; 60 | device.device_interface = std::string(it->name); 61 | device.ip_address = it->destination; 62 | alldevices->push_back(device); 63 | } 64 | } 65 | 66 | bool GetLocalAddress(boost::asio::ip::address *local_address) { 67 | *local_address = NetworkInterface::LocalAddress(); 68 | if (NetworkInterface::IsAny(*local_address)) 69 | return false; 70 | return true; 71 | } 72 | 73 | std::vector GetLocalAddresses() { 74 | // get all network interfaces 75 | std::vector addresses; 76 | std::vector alldevices; 77 | GetNetInterfaces(&alldevices); 78 | for (std::vector::iterator it = alldevices.begin(); 79 | it != alldevices.end(); ++it) { 80 | if (!NetworkInterface::IsLoopback(it->ip_address) && 81 | !NetworkInterface::IsMulticast(it->ip_address) && 82 | !NetworkInterface::IsAny(it->ip_address)) { 83 | addresses.push_back(it->ip_address.to_string()); 84 | } 85 | } 86 | return addresses; 87 | } 88 | 89 | } // namespace base 90 | -------------------------------------------------------------------------------- /lib/miniupnpclientimpl.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include "nat/miniupnpclientimpl.h" 29 | #include 30 | #include 31 | #include 32 | #include "nat/maidsafe_utils.h" 33 | #include "libupnp/miniwget.h" 34 | #include "libupnp/miniupnpc.h" 35 | #include "libupnp/upnpcommands.h" 36 | 37 | #define DEBUG 38 | 39 | namespace upnp { 40 | 41 | UpnpIgdClientImpl::UpnpIgdClientImpl() 42 | : is_initialised_(false), has_services_(false), 43 | upnp_urls_(), igd_data_(), 44 | port_mappings_(), timer_() {} 45 | 46 | UpnpIgdClientImpl::~UpnpIgdClientImpl() { 47 | timer_.CancelAll(); 48 | DeleteAllPortMappings(); 49 | } 50 | 51 | bool UpnpIgdClientImpl::IsAsync() { 52 | return false; 53 | } 54 | 55 | bool UpnpIgdClientImpl::HasServices() { 56 | return has_services_; 57 | } 58 | 59 | bool UpnpIgdClientImpl::InitControlPoint() { 60 | if (is_initialised_) 61 | return false; 62 | 63 | DiscoverDevices(); 64 | 65 | is_initialised_ = true; 66 | 67 | timer_.AddCallLater(kLeaseDuration * 1000, 68 | boost::bind(&UpnpIgdClientImpl::RefreshCallback, this)); 69 | 70 | return is_initialised_; // && has_services_; 71 | } 72 | 73 | bool UpnpIgdClientImpl::GetPortMappings(std::list& out_mapping) 74 | { 75 | int ret; 76 | 77 | out_mapping.clear(); 78 | 79 | // get the state var instead 80 | // PortMappingNumberOfEntries 81 | // @todo Parse SCPD and get actual supported command and var names from there... 82 | 83 | int i = 0; 84 | while (true) 85 | { 86 | char extPort[6] = {0}; 87 | char intClient[16] = {0}; 88 | char intPort[6] = {0}; 89 | char protocol[4] = {0}; 90 | char desc[80] = {0}; 91 | char enabled[4] = {0}; 92 | char rHost[64] = {0}; 93 | char duration[16] = {0}; 94 | 95 | char index[16] = {0}; 96 | snprintf(index, 16, "%u", i); 97 | ret = UPNP_GetGenericPortMappingEntry(upnp_urls_.controlURL, 98 | igd_data_.first.servicetype, 99 | index, 100 | extPort, 101 | intClient, 102 | intPort, 103 | protocol, 104 | desc, 105 | enabled, 106 | rHost, 107 | duration); 108 | 109 | if (ret == 501) { 110 | break; 111 | } 112 | // Compal Broadband Networks, Inc/Linux/2.6.39.3 UPnP/1.1 MiniUPnPd/1.7 spits this: 113 | // 713 - SpecifiedArrayIndexInvalid 114 | if (ret == 713) { 115 | break; 116 | } 117 | assert(ret == UPNPCOMMAND_SUCCESS); 118 | 119 | PortMappingExt pm(boost::lexical_cast(intPort), 120 | boost::lexical_cast(extPort), 121 | (std::string(protocol) == "TCP" ? kTcp : kUdp)); 122 | pm.enabled = (std::string(enabled) == "1" ? true : false); 123 | pm.internal_host = intClient; 124 | pm.external_host = rHost; 125 | pm.duration = boost::lexical_cast(duration); 126 | pm.description = desc; 127 | 128 | out_mapping.emplace_back(pm); 129 | 130 | ++i; 131 | } 132 | 133 | return true; 134 | } 135 | 136 | bool UpnpIgdClientImpl::AddPortMapping(const PortMapping &mapping) { 137 | PortMapping *pm; 138 | std::list::iterator it; 139 | if (PortMappingExists(mapping.external_port, mapping.protocol, it)) { 140 | pm = &(*it); 141 | } else { 142 | port_mappings_.push_back(mapping); 143 | pm = &port_mappings_.back(); 144 | } 145 | 146 | std::string extPort = boost::lexical_cast(mapping.external_port); 147 | std::string intPort = boost::lexical_cast(mapping.internal_port); 148 | std::string proto = (mapping.protocol == kTcp ? "TCP" : "UDP"); 149 | 150 | #ifdef DEBUG 151 | /* if (pm->enabled) { 152 | printf("UPnP port mapping already exists: %s %s\n", 153 | proto.c_str(), ext_port.c_str()); 154 | } */ 155 | #endif 156 | 157 | if (has_services_) { 158 | boost::asio::ip::address ip_addr; 159 | base::GetLocalAddress(&ip_addr); 160 | 161 | int res = UPNP_AddPortMapping(upnp_urls_.controlURL, 162 | igd_data_.first.servicetype, 163 | extPort.c_str(), intPort.c_str(), 164 | ip_addr.to_string().c_str(), 165 | kClientName, 166 | proto.c_str(), 167 | NULL, 168 | boost::lexical_cast(kad::kRefreshTime).c_str()); 169 | 170 | if (res == UPNPCOMMAND_SUCCESS) { 171 | pm->enabled = true; 172 | } else { 173 | pm->enabled = false; 174 | #ifdef DEBUG 175 | printf("Error adding UPnP port mapping (%s %s): %d\n", 176 | proto.c_str(), 177 | extPort.c_str(), 178 | res); 179 | #endif 180 | } 181 | 182 | return res == UPNPCOMMAND_SUCCESS; 183 | } else { 184 | return false; 185 | } 186 | } 187 | 188 | bool UpnpIgdClientImpl::PortMappingExists( 189 | const int &port, const ProtocolType &protocol, 190 | std::list::iterator &it) { 191 | for (it = port_mappings_.begin(); it != port_mappings_.end(); ++it) { 192 | if ((*it).external_port == port && 193 | (*it).protocol == protocol) 194 | return true; 195 | } 196 | return false; 197 | } 198 | 199 | bool UpnpIgdClientImpl::DeletePortMapping(const int &port, 200 | const ProtocolType &protocol) { 201 | std::list::iterator it_pm; 202 | if (PortMappingExists(port, protocol, it_pm)) { 203 | bool ok = true; 204 | if ((*it_pm).enabled) { 205 | std::string ext_port = boost::lexical_cast(port); 206 | std::string proto = (protocol == kTcp ? "TCP" : "UDP"); 207 | 208 | int res = UPNP_DeletePortMapping(upnp_urls_.controlURL, 209 | igd_data_.first.servicetype, 210 | ext_port.c_str(), 211 | proto.c_str(), 212 | NULL); 213 | 214 | #ifdef DEBUG 215 | if (res != UPNPCOMMAND_SUCCESS) { 216 | printf("Error deleting UPnP port mapping (%s %d): %d\n", proto.c_str(), 217 | port, res); 218 | } 219 | #endif 220 | 221 | ok = (res == UPNPCOMMAND_SUCCESS); 222 | } 223 | port_mappings_.erase(it_pm); 224 | return ok; 225 | } 226 | return false; 227 | } 228 | 229 | bool UpnpIgdClientImpl::DeleteAllPortMappings() { 230 | bool result = true; 231 | while (!port_mappings_.empty()) { 232 | result &= DeletePortMapping(port_mappings_.front().external_port, 233 | port_mappings_.front().protocol); 234 | } 235 | return result; 236 | } 237 | 238 | std::string UpnpIgdClientImpl::GetExternalIpAddress() { 239 | char ip[16]; 240 | ip[0] = '\0'; 241 | if (has_services_) { 242 | int res = UPNP_GetExternalIPAddress(upnp_urls_.controlURL, 243 | igd_data_.first.servicetype, ip); 244 | if (res == UPNPCOMMAND_SUCCESS) { 245 | return std::string(ip); 246 | } 247 | } 248 | return ""; 249 | } 250 | 251 | void UpnpIgdClientImpl::DiscoverDevices() { 252 | struct UPNPDev* devlist = upnpDiscover(kSearchTime * 1000, NULL, NULL, 0, /*IPv6:*/0, NULL); 253 | int res = UPNP_GetValidIGD(devlist, &upnp_urls_, &igd_data_, NULL, 0); 254 | freeUPNPDevlist(devlist); 255 | 256 | has_services_ = (res == 1); 257 | } 258 | 259 | bool IsUpnpIgdConnected(const UPNPUrls &urls, const IGDdatas &data) { 260 | char status[64]; 261 | unsigned int uptime; 262 | status[0] = '\0'; 263 | UPNP_GetStatusInfo(urls.controlURL, data.first.servicetype, 264 | status, &uptime, NULL); 265 | return (0 == strcmp("Connected", status)); 266 | } 267 | 268 | void UpnpIgdClientImpl::RefreshCallback() { 269 | #ifdef DEBUG 270 | if (port_mappings_.size() > 0) 271 | printf("Refreshing UPnP port mappings...\n"); 272 | #endif 273 | 274 | if (!has_services_ || !IsUpnpIgdConnected(upnp_urls_, igd_data_)) { 275 | DiscoverDevices(); 276 | } 277 | 278 | for (std::list::iterator it = port_mappings_.begin(); 279 | it != port_mappings_.end(); ++it) { 280 | if (has_services_) { 281 | AddPortMapping(*it); 282 | } else { 283 | (*it).enabled = false; 284 | } 285 | } 286 | 287 | timer_.AddCallLater(kLeaseDuration * 1000, 288 | boost::bind(&UpnpIgdClientImpl::RefreshCallback, this)); 289 | } 290 | 291 | } // namespace upnp 292 | -------------------------------------------------------------------------------- /lib/natpmpclient.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | Created by Julian Cain on 11/3/09. 28 | 29 | */ 30 | 31 | #include 32 | #include "nat/natpmpclient.h" 33 | #include "nat/natpmpprotocol.h" 34 | #include "arsenal/logging.h" 35 | 36 | namespace natpmp { 37 | 38 | void NatPmpClient::Start() { 39 | if (impl_) { 40 | // ... 41 | } else { 42 | // Allocate the implementation. 43 | impl_.reset(new NatPmpClientImpl(io_service_)); 44 | 45 | // Start the implementation. 46 | impl_->Start(); 47 | } 48 | } 49 | 50 | void NatPmpClient::Stop() { 51 | if (impl_) { 52 | // Stop the implementation. 53 | impl_->Stop(); 54 | 55 | // Cleanup 56 | impl_.reset(); 57 | } else { 58 | // ... 59 | } 60 | } 61 | 62 | void NatPmpClient::SetMapPortSuccessCallback( 63 | const NatPmpMapPortSuccessCbType & map_port_success_cb) { 64 | if (impl_) { 65 | impl_->SetMapPortSuccessCallback(map_port_success_cb); 66 | } else { 67 | logger::warning() << "Cannot set NAT-PMP success callback with null impl."; 68 | } 69 | } 70 | 71 | void NatPmpClient::MapPort(boost::uint32_t protocol, 72 | boost::uint16_t private_port, 73 | boost::uint16_t public_port, 74 | boost::uint64_t lifetime) { 75 | if (protocol != Protocol::kTcp && protocol != Protocol::kUdp) { 76 | throw std::runtime_error( 77 | Protocol::StringFromOpcode(Protocol::kErrorInvalidArgs)); 78 | } 79 | 80 | if (impl_) { 81 | impl_->SendMappingRequest(protocol, private_port, public_port, lifetime); 82 | } else { 83 | throw std::runtime_error("Attempted to map nat-pmp port while subsystem is not started."); 84 | } 85 | } 86 | 87 | } // namespace natpmp 88 | -------------------------------------------------------------------------------- /lib/natpmpprotocol.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | Created by Julian Cain on 11/3/09. 28 | 29 | */ 30 | 31 | #include "nat/natpmpprotocol.h" 32 | 33 | namespace natpmp { 34 | 35 | const char * Protocol::StringFromOpcode(unsigned int opcode) { 36 | const char * str; 37 | 38 | switch (opcode) { 39 | case kErrorInvalidArgs: 40 | str = "invalid arguments"; 41 | break; 42 | case kErrorSocketError: 43 | str = "socket() failed"; 44 | break; 45 | case kErrorCannotGetGateway: 46 | str = "cannot get default gateway ip address"; 47 | break; 48 | case kResultOutOfResources: 49 | str = "Out of resources (NAT box cannot create any more mappings at " 50 | "this time)."; 51 | break; 52 | case kResultNetworkFailure: 53 | str = "Network Failure, nat box may have not obtained a DHCP lease."; 54 | break; 55 | default: 56 | str = "Unknown NAT-PMP error"; 57 | } 58 | 59 | return str; 60 | } 61 | 62 | } // namespace natpmp 63 | -------------------------------------------------------------------------------- /lib/upnpclient.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include "nat/upnpclient.h" 29 | #include 30 | 31 | namespace upnp { 32 | 33 | UpnpIgdClient::UpnpIgdClient() : pimpl_(new UpnpIgdClientImpl()) {} 34 | 35 | UpnpIgdClient::~UpnpIgdClient() {} 36 | 37 | bool UpnpIgdClient::IsAsync() { 38 | return pimpl_->IsAsync(); 39 | } 40 | 41 | bool UpnpIgdClient::HasServices() { 42 | return pimpl_->HasServices(); 43 | } 44 | 45 | bool UpnpIgdClient::InitControlPoint() { 46 | return pimpl_->InitControlPoint(); 47 | } 48 | 49 | bool UpnpIgdClient::GetPortMappings(std::list& out_mapping) { 50 | return pimpl_->GetPortMappings(out_mapping); 51 | } 52 | 53 | bool UpnpIgdClient::AddPortMapping(const int &port, 54 | const ProtocolType &protocol) { 55 | return pimpl_->AddPortMapping(PortMapping(port, protocol)); 56 | } 57 | 58 | bool UpnpIgdClient::AddPortMapping(int in_port, int out_port, ProtocolType protocol) 59 | { 60 | return pimpl_->AddPortMapping(PortMapping(in_port, out_port, protocol)); 61 | } 62 | 63 | bool UpnpIgdClient::DeletePortMapping(const int &port, 64 | const ProtocolType &protocol) { 65 | return pimpl_->DeletePortMapping(port, protocol); 66 | } 67 | 68 | bool UpnpIgdClient::DeleteAllPortMappings() 69 | { 70 | return pimpl_->DeleteAllPortMappings(); 71 | } 72 | 73 | std::string UpnpIgdClient::GetExternalIpAddress() { 74 | return pimpl_->GetExternalIpAddress(); 75 | } 76 | 77 | void UpnpIgdClient::SetNewMappingCallback( 78 | const upnp_callback &new_mapping_callback) { 79 | pimpl_->SetNewMappingCallback(new_mapping_callback); 80 | } 81 | 82 | void UpnpIgdClient::SetLostMappingCallback( 83 | const upnp_callback &lost_mapping_callback) { 84 | pimpl_->SetLostMappingCallback(lost_mapping_callback); 85 | } 86 | 87 | void UpnpIgdClient::SetFailedMappingCallback( 88 | const upnp_callback &failed_mapping_callback) { 89 | pimpl_->SetFailedMappingCallback(failed_mapping_callback); 90 | } 91 | 92 | } // namespace upnp 93 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(libupnp) 2 | 3 | create_test(natpmp LIBS nat arsenal ${Boost_LIBRARIES}) 4 | create_test(upnp LIBS nat upnpc arsenal ${Boost_LIBRARIES}) 5 | -------------------------------------------------------------------------------- /tests/libupnp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (WIN32) 2 | find_library (WINSOCK2_LIBRARY NAMES ws2_32 WS2_32 Ws2_32) 3 | find_library (IPHLPAPI_LIBRARY NAMES iphlpapi) 4 | set (LDLIBS ${WINSOCK2_LIBRARY} ${IPHLPAPI_LIBRARY} ${LDLIBS}) 5 | endif (WIN32) 6 | 7 | add_executable(upnpc-static upnpc.c) 8 | target_link_libraries(upnpc-static nat upnpc ${LDLIBS}) 9 | install(TARGETS upnpc-static 10 | RUNTIME DESTINATION tools) 11 | 12 | add_executable(testminixml testminixml.c) 13 | target_link_libraries(testminixml nat upnpc ${LDLIBS}) 14 | install(TARGETS testminixml 15 | RUNTIME DESTINATION tests/nat) 16 | 17 | add_executable(minixmlvalid minixmlvalid.c) 18 | target_link_libraries(minixmlvalid nat upnpc ${LDLIBS}) 19 | install(TARGETS minixmlvalid 20 | RUNTIME DESTINATION tests/nat) 21 | 22 | add_executable(testupnpreplyparse testupnpreplyparse.c) 23 | target_link_libraries(testupnpreplyparse nat upnpc ${LDLIBS}) 24 | install(TARGETS testupnpreplyparse 25 | RUNTIME DESTINATION tests/nat) 26 | 27 | add_executable(testigddescparse testigddescparse.c) 28 | target_link_libraries(testigddescparse nat upnpc ${LDLIBS}) 29 | install(TARGETS testigddescparse 30 | RUNTIME DESTINATION tests/nat) 31 | 32 | add_executable(testminiwget testminiwget.c) 33 | target_link_libraries(testminiwget nat upnpc ${LDLIBS}) 34 | install(TARGETS testminiwget 35 | RUNTIME DESTINATION tests/nat) 36 | -------------------------------------------------------------------------------- /tests/libupnp/minixmlvalid.c: -------------------------------------------------------------------------------- 1 | /* $Id: minixmlvalid.c,v 1.6 2012/05/01 16:24:07 nanard Exp $ */ 2 | /* MiniUPnP Project 3 | * http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ 4 | * minixmlvalid.c : 5 | * validation program for the minixml parser 6 | * 7 | * (c) 2006-2011 Thomas Bernard */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "libupnp/minixml.h" 13 | 14 | /* xml event structure */ 15 | struct event { 16 | enum { ELTSTART, ELTEND, ATT, CHARDATA } type; 17 | const char * data; 18 | int len; 19 | }; 20 | 21 | struct eventlist { 22 | int n; 23 | struct event * events; 24 | }; 25 | 26 | /* compare 2 xml event lists 27 | * return 0 if the two lists are equals */ 28 | int evtlistcmp(struct eventlist * a, struct eventlist * b) 29 | { 30 | int i; 31 | struct event * ae, * be; 32 | if(a->n != b->n) 33 | { 34 | printf("event number not matching : %d != %d\n", a->n, b->n); 35 | /*return 1;*/ 36 | } 37 | for(i=0; in; i++) 38 | { 39 | ae = a->events + i; 40 | be = b->events + i; 41 | if( (ae->type != be->type) 42 | ||(ae->len != be->len) 43 | ||memcmp(ae->data, be->data, ae->len)) 44 | { 45 | printf("Found a difference : %d '%.*s' != %d '%.*s'\n", 46 | ae->type, ae->len, ae->data, 47 | be->type, be->len, be->data); 48 | return 1; 49 | } 50 | } 51 | return 0; 52 | } 53 | 54 | /* Test data */ 55 | static const char xmldata[] = 56 | "\n" 57 | " " 58 | "character data" 59 | " \n \t" 60 | "" 61 | "\nstuff !\n ]]> \n\n" 62 | " \tchardata1 chardata2 " 63 | ""; 64 | 65 | static const struct event evtref[] = 66 | { 67 | {ELTSTART, "xmlroot", 7}, 68 | {ELTSTART, "elt1", 4}, 69 | /* attributes */ 70 | {CHARDATA, "character data", 14}, 71 | {ELTEND, "elt1", 4}, 72 | {ELTSTART, "elt1b", 5}, 73 | {ELTSTART, "elt1", 4}, 74 | {CHARDATA, " stuff !\n ", 16}, 75 | {ELTEND, "elt1", 4}, 76 | {ELTSTART, "elt2a", 5}, 77 | {ELTSTART, "elt2b", 5}, 78 | {CHARDATA, "chardata1", 9}, 79 | {ELTEND, "elt2b", 5}, 80 | {ELTSTART, "elt2b", 5}, 81 | {CHARDATA, " chardata2 ", 11}, 82 | {ELTEND, "elt2b", 5}, 83 | {ELTEND, "elt2a", 5}, 84 | {ELTEND, "xmlroot", 7} 85 | }; 86 | 87 | void startelt(void * data, const char * p, int l) 88 | { 89 | struct eventlist * evtlist = data; 90 | struct event * evt; 91 | evt = evtlist->events + evtlist->n; 92 | /*printf("startelt : %.*s\n", l, p);*/ 93 | evt->type = ELTSTART; 94 | evt->data = p; 95 | evt->len = l; 96 | evtlist->n++; 97 | } 98 | 99 | void endelt(void * data, const char * p, int l) 100 | { 101 | struct eventlist * evtlist = data; 102 | struct event * evt; 103 | evt = evtlist->events + evtlist->n; 104 | /*printf("endelt : %.*s\n", l, p);*/ 105 | evt->type = ELTEND; 106 | evt->data = p; 107 | evt->len = l; 108 | evtlist->n++; 109 | } 110 | 111 | void chardata(void * data, const char * p, int l) 112 | { 113 | struct eventlist * evtlist = data; 114 | struct event * evt; 115 | evt = evtlist->events + evtlist->n; 116 | /*printf("chardata : '%.*s'\n", l, p);*/ 117 | evt->type = CHARDATA; 118 | evt->data = p; 119 | evt->len = l; 120 | evtlist->n++; 121 | } 122 | 123 | int testxmlparser(const char * xml, int size) 124 | { 125 | int r; 126 | struct eventlist evtlist; 127 | struct eventlist evtlistref; 128 | struct xmlparser parser; 129 | evtlist.n = 0; 130 | evtlist.events = malloc(sizeof(struct event)*100); 131 | memset(&parser, 0, sizeof(parser)); 132 | parser.xmlstart = xml; 133 | parser.xmlsize = size; 134 | parser.data = &evtlist; 135 | parser.starteltfunc = startelt; 136 | parser.endeltfunc = endelt; 137 | parser.datafunc = chardata; 138 | parsexml(&parser); 139 | printf("%d events\n", evtlist.n); 140 | /* compare */ 141 | evtlistref.n = sizeof(evtref)/sizeof(struct event); 142 | evtlistref.events = (struct event *)evtref; 143 | r = evtlistcmp(&evtlistref, &evtlist); 144 | free(evtlist.events); 145 | return r; 146 | } 147 | 148 | int main(int argc, char * * argv) 149 | { 150 | int r; 151 | (void)argc; (void)argv; 152 | 153 | r = testxmlparser(xmldata, sizeof(xmldata)-1); 154 | if(r) 155 | printf("minixml validation test failed\n"); 156 | return r; 157 | } 158 | 159 | -------------------------------------------------------------------------------- /tests/libupnp/testigddescparse.c: -------------------------------------------------------------------------------- 1 | /* $Id: testigddescparse.c,v 1.4 2012/06/28 18:52:12 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * http://miniupnp.free.fr/ 4 | * Author : Thomas Bernard 5 | * Copyright (c) 2008-2012 Thomas Bernard 6 | * This software is subject to the conditions detailed in the 7 | * LICENCE file provided in this distribution. 8 | * */ 9 | #include 10 | #include 11 | #include 12 | #include "libupnp/igd_desc_parse.h" 13 | #include "libupnp/minixml.h" 14 | #include "libupnp/miniupnpc.h" 15 | 16 | int test_igd_desc_parse(char * buffer, int len) 17 | { 18 | struct IGDdatas igd; 19 | struct xmlparser parser; 20 | struct UPNPUrls urls; 21 | memset(&igd, 0, sizeof(struct IGDdatas)); 22 | memset(&parser, 0, sizeof(struct xmlparser)); 23 | parser.xmlstart = buffer; 24 | parser.xmlsize = len; 25 | parser.data = &igd; 26 | parser.starteltfunc = IGDstartelt; 27 | parser.endeltfunc = IGDendelt; 28 | parser.datafunc = IGDdata; 29 | parsexml(&parser); 30 | printIGD(&igd); 31 | GetUPNPUrls(&urls, &igd, "http://fake/desc/url/file.xml", 0); 32 | printf("ipcondescURL='%s'\n", urls.ipcondescURL); 33 | printf("controlURL='%s'\n", urls.controlURL); 34 | printf("controlURL_CIF='%s'\n", urls.controlURL_CIF); 35 | FreeUPNPUrls(&urls); 36 | return 0; 37 | } 38 | 39 | int main(int argc, char * * argv) 40 | { 41 | FILE * f; 42 | char * buffer; 43 | int len; 44 | int r = 0; 45 | if(argc<2) { 46 | fprintf(stderr, "Usage: %s file.xml\n", argv[0]); 47 | return 1; 48 | } 49 | f = fopen(argv[1], "r"); 50 | if(!f) { 51 | fprintf(stderr, "Cannot open %s for reading.\n", argv[1]); 52 | return 1; 53 | } 54 | fseek(f, 0, SEEK_END); 55 | len = ftell(f); 56 | fseek(f, 0, SEEK_SET); 57 | buffer = malloc(len); 58 | fread(buffer, 1, len, f); 59 | fclose(f); 60 | r = test_igd_desc_parse(buffer, len); 61 | free(buffer); 62 | return r; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /tests/libupnp/testminiwget.c: -------------------------------------------------------------------------------- 1 | /* $Id: testminiwget.c,v 1.4 2012/06/23 22:35:59 nanard Exp $ */ 2 | /* Project : miniupnp 3 | * Author : Thomas Bernard 4 | * Copyright (c) 2005-2012 Thomas Bernard 5 | * This software is subject to the conditions detailed in the 6 | * LICENCE file provided in this distribution. 7 | * */ 8 | #include 9 | #include 10 | #include "libupnp/miniwget.h" 11 | 12 | /** 13 | * This program uses the miniwget / miniwget_getaddr function 14 | * from miniwget.c in order to retreive a web ressource using 15 | * a GET HTTP method, and store it in a file. 16 | */ 17 | int main(int argc, char * * argv) 18 | { 19 | void * data; 20 | int size, writtensize; 21 | FILE *f; 22 | char addr[64]; 23 | 24 | if(argc < 3) { 25 | fprintf(stderr, "Usage:\t%s url file\n", argv[0]); 26 | fprintf(stderr, "Example:\t%s http://www.google.com/ out.html\n", argv[0]); 27 | return 1; 28 | } 29 | data = miniwget_getaddr(argv[1], &size, addr, sizeof(addr), 0); 30 | if(!data) { 31 | fprintf(stderr, "Error fetching %s\n", argv[1]); 32 | return 1; 33 | } 34 | printf("local address : %s\n", addr); 35 | printf("got %d bytes\n", size); 36 | f = fopen(argv[2], "wb"); 37 | if(!f) { 38 | fprintf(stderr, "Cannot open file %s for writing\n", argv[2]); 39 | free(data); 40 | return 1; 41 | } 42 | writtensize = fwrite(data, 1, size, f); 43 | if(writtensize != size) { 44 | fprintf(stderr, "Could only write %d bytes out of %d to %s\n", 45 | writtensize, size, argv[2]); 46 | } else { 47 | printf("%d bytes written to %s\n", writtensize, argv[2]); 48 | } 49 | fclose(f); 50 | free(data); 51 | return 0; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /tests/libupnp/testminiwget.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # $Id: testminiwget.sh,v 1.6 2012/05/29 13:03:40 nanard Exp $ 3 | # project miniupnp : http://miniupnp.free.fr/ 4 | # (c) 2011-2012 Thomas Bernard 5 | # 6 | # test program for miniwget.c 7 | # is usually invoked by "make check" 8 | # 9 | # This test program : 10 | # 1 - launches a local HTTP server (minihttptestserver) 11 | # 2 - uses testminiwget to retreive data from this server 12 | # 3 - compares served and received data 13 | # 4 - kills the local HTTP server and exits 14 | # 15 | # The script was tested and works with ksh, bash 16 | # It fails to run with dash 0.5.5.1 because of "kill %1" 17 | 18 | TMPDIR=`mktemp -d` 19 | HTTPSERVEROUT="${TMPDIR}/httpserverout" 20 | EXPECTEDFILE="${TMPDIR}/expectedfile" 21 | DOWNLOADEDFILE="${TMPDIR}/downloadedfile" 22 | #ADDR=localhost 23 | ADDR="[::1]" 24 | PORT= 25 | RET=0 26 | 27 | #make minihttptestserver 28 | #make testminiwget 29 | 30 | # launching the test HTTP server 31 | ./minihttptestserver -6 -e $EXPECTEDFILE > $HTTPSERVEROUT & 32 | while [ -z "$PORT" ]; do 33 | sleep 1 34 | PORT=`cat $HTTPSERVEROUT | sed 's/Listening on port \([0-9]*\)/\1/' ` 35 | done 36 | echo "Test HTTP server is listening on $PORT" 37 | 38 | URL1="http://$ADDR:$PORT/index.html" 39 | URL2="http://$ADDR:$PORT/chunked" 40 | URL3="http://$ADDR:$PORT/addcrap" 41 | 42 | echo "standard test ..." 43 | ./testminiwget $URL1 "${DOWNLOADEDFILE}.1" 44 | if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.1" ; then 45 | echo "ok" 46 | else 47 | echo "standard test FAILED" 48 | RET=1 49 | fi 50 | 51 | echo "chunked transfert encoding test ..." 52 | ./testminiwget $URL2 "${DOWNLOADEDFILE}.2" 53 | if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.2" ; then 54 | echo "ok" 55 | else 56 | echo "chunked transfert encoding test FAILED" 57 | RET=1 58 | fi 59 | 60 | echo "response too long test ..." 61 | ./testminiwget $URL3 "${DOWNLOADEDFILE}.3" 62 | if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.3" ; then 63 | echo "ok" 64 | else 65 | echo "response too long test FAILED" 66 | RET=1 67 | fi 68 | 69 | # kill the test HTTP server 70 | kill %1 71 | wait %1 72 | 73 | # remove temporary files (for success cases) 74 | if [ $RET -eq 0 ]; then 75 | rm -f "${DOWNLOADEDFILE}.1" 76 | rm -f "${DOWNLOADEDFILE}.2" 77 | rm -f "${DOWNLOADEDFILE}.3" 78 | rm -f $EXPECTEDFILE $HTTPSERVEROUT 79 | rmdir ${TMPDIR} 80 | else 81 | echo "at least one of the test FAILED" 82 | echo "directory ${TMPDIR} is left intact" 83 | fi 84 | exit $RET 85 | 86 | -------------------------------------------------------------------------------- /tests/libupnp/testminixml.c: -------------------------------------------------------------------------------- 1 | /* $Id: testminixml.c,v 1.7 2012/01/21 13:30:33 nanard Exp $ 2 | * MiniUPnP project 3 | * Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 4 | * Author : Thomas Bernard. 5 | * Copyright (c) 2005-2012 Thomas Bernard 6 | * 7 | * testminixml.c 8 | * test program for the "minixml" functions. 9 | */ 10 | #include 11 | #include 12 | #include 13 | #include "libupnp/minixml.h" 14 | #include "libupnp/igd_desc_parse.h" 15 | 16 | /* ---------------------------------------------------------------------- */ 17 | void printeltname1(void * d, const char * name, int l) 18 | { 19 | int i; 20 | printf("element "); 21 | for(i=0;i 8 | #include 9 | #include "libupnp/upnpreplyparse.h" 10 | 11 | void 12 | test_parsing(const char * buf, int len) 13 | { 14 | struct NameValueParserData pdata; 15 | ParseNameValue(buf, len, &pdata); 16 | ClearNameValueList(&pdata); 17 | } 18 | 19 | int main(int argc, char * * argv) 20 | { 21 | FILE * f; 22 | char buffer[4096]; 23 | int l; 24 | if(argc<2) 25 | { 26 | fprintf(stderr, "Usage: %s file.xml\n", argv[0]); 27 | return 1; 28 | } 29 | f = fopen(argv[1], "r"); 30 | if(!f) 31 | { 32 | fprintf(stderr, "Error : can not open file %s\n", argv[1]); 33 | return 2; 34 | } 35 | l = fread(buffer, 1, sizeof(buffer)-1, f); 36 | fclose(f); 37 | buffer[l] = '\0'; 38 | #ifdef DEBUG 39 | DisplayNameValueList(buffer, l); 40 | #endif 41 | test_parsing(buffer, l); 42 | return 0; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /tests/test_natpmp.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #define BOOST_TEST_MODULE Test_natpmp 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "nat/natpmpclient.h" 36 | 37 | BOOST_AUTO_TEST_CASE(NATPMP) 38 | { 39 | boost::asio::io_service ios; 40 | 41 | natpmp::NatPmpClient client(&ios); 42 | 43 | boost::uint16_t tcp_port = 33333; 44 | boost::uint16_t udp_port = 33333; 45 | 46 | printf("Starting NAT-PMP...\n"); 47 | 48 | printf("Requesting external ip address from gateway.\n"); 49 | 50 | client.Start(); 51 | 52 | printf("Queueing mapping request for tcp port %d to %d.\n", tcp_port, tcp_port); 53 | 54 | client.MapPort(natpmp::Protocol::kTcp, 33333, 33333, 3600); 55 | 56 | printf("Queueing mapping request for udp port %d to %d.\n", udp_port, udp_port); 57 | 58 | client.MapPort(natpmp::Protocol::kUdp, 33333, 33333, 3600); 59 | 60 | std::thread thread([&] { ios.run(); }); 61 | 62 | printf("Sleeping for 30 seconds...\n"); 63 | 64 | std::this_thread::sleep_for(std::chrono::seconds(30)); 65 | 66 | printf("Stopping NAT-PMP...\n"); 67 | 68 | client.Stop(); 69 | 70 | ios.stop(); 71 | thread.join(); 72 | } 73 | -------------------------------------------------------------------------------- /tests/test_upnp.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 maidsafe.net limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the maidsafe.net limited nor the names of its 13 | contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #define BOOST_TEST_MODULE Test_upnp 28 | #include 29 | 30 | #include 31 | #include 32 | #include "nat/maidsafe-dht_config.h" 33 | #include "nat/upnpclient.h" 34 | 35 | // #include "protocol.h" 36 | const int default_port = 9660; // Define port in-place instead of sss dependency 37 | 38 | using namespace std; 39 | 40 | // Test depends on external UPnP device, but doesn't fail if none found 41 | 42 | class UpnpTest { 43 | public: 44 | UpnpTest() : num_total_mappings(3), num_curr_mappings(0) {} 45 | void OnNewMapping(const int &port, const upnp::ProtocolType &protocol); 46 | void OnLostMapping(const int &port, const upnp::ProtocolType &protocol); 47 | void OnFailedMapping(const int &port, const upnp::ProtocolType &protocol); 48 | 49 | int num_total_mappings; 50 | int num_curr_mappings; 51 | }; 52 | 53 | void UpnpTest::OnNewMapping(const int &port, 54 | const upnp::ProtocolType &protocol) { 55 | num_curr_mappings++; 56 | printf("New port mapping: %s %d\n", 57 | protocol == upnp::kUdp ? "UDP" : "TCP", port); 58 | } 59 | 60 | void UpnpTest::OnLostMapping(const int &port, 61 | const upnp::ProtocolType &protocol) { 62 | num_curr_mappings--; 63 | printf("Lost port mapping: %s %d\n", 64 | protocol == upnp::kUdp ? "UDP" : "TCP", port); 65 | } 66 | 67 | void UpnpTest::OnFailedMapping(const int &port, 68 | const upnp::ProtocolType &protocol) { 69 | printf("Failed port mapping: %s %d\n", 70 | protocol == upnp::kUdp ? "UDP" : "TCP", port); 71 | } 72 | 73 | BOOST_AUTO_TEST_CASE(UPNP_TcpPortMappingTest) 74 | { 75 | upnp::UpnpIgdClient upnp; 76 | UpnpTest test; 77 | 78 | printf("Initialising UPnP...\n"); 79 | 80 | BOOST_CHECK(upnp.InitControlPoint()); 81 | 82 | if (upnp.IsAsync()) { 83 | upnp.SetNewMappingCallback( 84 | boost::bind(&UpnpTest::OnNewMapping, &test, _1, _2)); 85 | upnp.SetLostMappingCallback( 86 | boost::bind(&UpnpTest::OnLostMapping, &test, _1, _2)); 87 | upnp.SetFailedMappingCallback( 88 | boost::bind(&UpnpTest::OnFailedMapping, &test, _1, _2)); 89 | } 90 | 91 | // this_thread::sleep_for(chrono::seconds(2)); 92 | 93 | std::list out_mapping; 94 | upnp.GetPortMappings(out_mapping); 95 | 96 | for (auto m : out_mapping) 97 | { 98 | cout << "UPNP mapping found: int host " << m.internal_host << ", int port " << m.internal_port 99 | << " to ext host " << m.external_host << ", ext port " << m.external_port << endl 100 | << " protocol " << m.protocol << ", enabled " << m.enabled << ", duration " << m.duration 101 | << ", desc " << m.description << endl; 102 | } 103 | 104 | boost::int32_t start_port(default_port); 105 | 106 | bool all_added = true; 107 | for (int i = 0; i < test.num_total_mappings; ++i) { 108 | all_added &= upnp.AddPortMapping(start_port + i, upnp::kTcp); 109 | } 110 | 111 | if (upnp.IsAsync()) { 112 | printf("Waiting...\n"); 113 | this_thread::sleep_for(chrono::seconds(3)); 114 | } 115 | 116 | if (upnp.HasServices()) { 117 | printf("External IP: %s\n", upnp.GetExternalIpAddress().c_str()); 118 | BOOST_CHECK(all_added); 119 | if (upnp.IsAsync()) { 120 | BOOST_CHECK(test.num_curr_mappings == test.num_total_mappings); 121 | } 122 | printf("All UPnP mappings successful.\n"); 123 | } else { 124 | printf("Sorry, no port mappings via UPnP possible.\n"); 125 | } 126 | BOOST_CHECK(upnp.DeletePortMapping(start_port + test.num_total_mappings - 1, upnp::kTcp)); 127 | BOOST_CHECK(upnp.DeleteAllPortMappings()); 128 | } 129 | 130 | BOOST_AUTO_TEST_CASE(UPNP_UdpPortMappingTest) 131 | { 132 | upnp::UpnpIgdClient upnp; 133 | UpnpTest test; 134 | 135 | printf("Initialising UPnP...\n"); 136 | 137 | BOOST_CHECK(upnp.InitControlPoint()); 138 | 139 | if (upnp.IsAsync()) { 140 | upnp.SetNewMappingCallback( 141 | boost::bind(&UpnpTest::OnNewMapping, &test, _1, _2)); 142 | upnp.SetLostMappingCallback( 143 | boost::bind(&UpnpTest::OnLostMapping, &test, _1, _2)); 144 | upnp.SetFailedMappingCallback( 145 | boost::bind(&UpnpTest::OnFailedMapping, &test, _1, _2)); 146 | } 147 | 148 | boost::int32_t start_port(default_port); 149 | 150 | bool all_added = true; 151 | for (int i = 0; i < test.num_total_mappings; ++i) { 152 | all_added &= upnp.AddPortMapping(start_port + i, upnp::kUdp); 153 | } 154 | 155 | if (upnp.IsAsync()) { 156 | printf("Waiting...\n"); 157 | this_thread::sleep_for(chrono::seconds(3)); 158 | } 159 | 160 | if (upnp.HasServices()) { 161 | printf("External IP: %s\n", upnp.GetExternalIpAddress().c_str()); 162 | BOOST_CHECK(all_added); 163 | if (upnp.IsAsync()) { 164 | BOOST_CHECK(test.num_curr_mappings == test.num_total_mappings); 165 | } 166 | printf("All UPnP mappings successful.\n"); 167 | } else { 168 | printf("Sorry, no port mappings via UPnP possible.\n"); 169 | } 170 | BOOST_CHECK(upnp.DeletePortMapping(start_port + test.num_total_mappings - 1, upnp::kUdp)); 171 | BOOST_CHECK(upnp.DeleteAllPortMappings()); 172 | } 173 | --------------------------------------------------------------------------------