Add NAT-PMP support

This commit is contained in:
Ansa89 2016-03-05 13:43:39 +01:00
parent eeaf35de80
commit 55f0400ad4
10 changed files with 182 additions and 24 deletions

View File

@ -9,7 +9,7 @@ before_script:
- sudo add-apt-repository ppa:avsm/ocaml42+opam12 -y
- sudo apt-get update -qq
- sudo apt-get install ocaml opam astyle -qq
- sudo apt-get install libconfig-dev libvpx-dev libopus-dev libminiupnpc-dev check -qq
- sudo apt-get install libconfig-dev libvpx-dev libopus-dev libminiupnpc-dev libnatpmp-dev check -qq
# build apidsl
- git clone https://github.com/iphydf/apidsl
- cd apidsl

View File

@ -42,6 +42,7 @@ LIBCHECK_FOUND="no"
WANT_NACL="no"
ADD_NACL_OBJECTS_TO_PKGCONFIG="yes"
MINIUPNP="yes"
NATPMP="yes"
TOXCORE_LT_LDFLAGS="-version-info $LIBTOXCORE_LT_VERSION"
TOXAV_LT_LDFLAGS="-version-info $LIBTOXAV_LT_VERSION"
@ -81,6 +82,17 @@ AC_ARG_ENABLE([miniupnp],
]
)
AC_ARG_ENABLE([natpmp],
[AC_HELP_STRING([--disable-natpmp], [nat-pmp port forwarding (default: enabled)]) ],
[
if test "x$enableval" = "xyes"; then
NATPMP="yes"
elif test "x$enableval" = "xno"; then
NATPMP="no"
fi
]
)
AC_ARG_ENABLE([randombytes-stir],
[AC_HELP_STRING([--enable-randombytes-stir], [use randombytes_stir() instead of sodium_init() for faster startup on android (default: disabled)]) ],
[
@ -241,6 +253,8 @@ NACL_SEARCH_HEADERS=
NACL_SEARCH_LIBS=
MINIUPNP_SEARCH_HEADERS=
MINIUPNP_SEARCH_LIBS=
NATPMP_SEARCH_HEADERS=
NATPMP_SEARCH_LIBS=
AC_ARG_WITH(dependency-search,
AC_HELP_STRING([--with-dependency-search=DIR],
@ -312,6 +326,24 @@ AC_ARG_WITH(miniupnp-libs,
]
)
AC_ARG_WITH(natpmp-headers,
AC_HELP_STRING([--with-natpmp-headers=DIR],
[search for natpmp header files in DIR]),
[
NATPMP_SEARCH_HEADERS="$withval"
AC_MSG_NOTICE([will search for natpmp header files in $withval])
]
)
AC_ARG_WITH(natpmp-libs,
AC_HELP_STRING([--with-natpmp-libs=DIR],
[search for natpmp libraries in DIR]),
[
NATPMP_SEARCH_LIBS="$withval"
AC_MSG_NOTICE([will search for natpmp libraries in $withval])
]
)
if test "x$WANT_NACL" = "xyes"; then
enable_shared=no
enable_static=yes
@ -459,6 +491,36 @@ if test "x$MINIUPNP" = "xyes"; then
AC_SUBST(MINIUPNP_LDFLAGS)
fi
if test "x$NATPMP" = "xyes"; then
NATPMP_LIBS=
NATPMP_LDFLAGS=
LDFLAGS_SAVE="$LDFLAGS"
if test -n "$NATPMP_SEARCH_LIBS"; then
LDFLAGS="-L$NATPMP_SEARCH_LIBS $LDFLAGS"
AC_CHECK_LIB(natpmp, initnatpmp
[
NATPMP_LDFLAGS="-L$NATPMP_SEARCH_LIBS"
NATPMP_LIBS="-lnatpmp"
],
[
AC_MSG_ERROR([required library libnatpmp was not found in requested location $NATPMP_SEARCH_LIBS])
]
)
else
AC_CHECK_LIB(natpmp, initnatpmp,
[],
[
AC_MSG_ERROR([required library libnatpmp was not found on your system, please check http://miniupnp.free.fr/])
]
)
fi
LDFLAGS="$LDFLAGS_SAVE"
AC_SUBST(NATPMP_LIBS)
AC_SUBST(NATPMP_LDFLAGS)
fi
# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/socket.h sys/time.h unistd.h])
@ -546,6 +608,34 @@ if test "x$MINIUPNP" = "xyes"; then
AC_SUBST(MINIUPNP_CFLAGS)
fi
if test "x$NATPMP" = "xyes"; then
NATPMP_CFLAGS=
CFLAGS_SAVE="$CFLAGS"
CPPFLAGS_SAVE="$CPPFLAGS"
if test -n "$NATPMP_SEARCH_HEADERS"; then
CFLAGS="-I$NATPMP_SEARCH_HEADERS $CFLAGS"
CPPFLAGS="-I$NATPMP_SEARCH_HEADERS $CPPFLAGS"
AC_CHECK_HEADERS(natpmp.h,
[
NATPMP_CFLAGS="-I$NATPMP_SEARCH_HEADERS"
],
[
AC_MSG_ERROR([header files for required library libnatpmp were not found in requested location $NATPMP_SEARCH_HEADERS])
]
)
else
AC_CHECK_HEADERS(natpmp.h,
[],
[
AC_MSG_ERROR([header files for required library libnatpmp was not found on your system, please check http://miniupnp.free.fr/])
]
)
fi
CFLAGS="$CFLAGS_SAVE"
CPPFLAGS="$CPPFLAGS_SAVE"
AC_SUBST(NATPMP_CFLAGS)
fi
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_TYPE_INT16_T

View File

@ -7,5 +7,5 @@ Name: libtoxcore
Description: Tox protocol library
Requires:
Version: @PACKAGE_VERSION@
Libs: @NACL_OBJECTS_PKGCONFIG@ -L${libdir} @NACL_LDFLAGS@ -ltoxdns -ltoxencryptsave -ltoxcore @NACL_LIBS@ @MINIUPNP_LIBS@ @LIBS@ @MATH_LDFLAGS@ @PTHREAD_LDFLAGS@
Libs: @NACL_OBJECTS_PKGCONFIG@ -L${libdir} @NACL_LDFLAGS@ -ltoxdns -ltoxencryptsave -ltoxcore @NACL_LIBS@ @MINIUPNP_LIBS@ @NATPMP_LIBS@ @LIBS@ @MATH_LDFLAGS@ @PTHREAD_LDFLAGS@
Cflags: -I${includedir}

View File

@ -57,14 +57,16 @@ libtoxcore_la_CFLAGS = -I$(top_srcdir) \
-I$(top_srcdir)/toxcore \
$(LIBSODIUM_CFLAGS) \
$(NACL_CFLAGS) \
$(MINIDUMP_CFLAGS) \
$(MINIUPNP_CFLAGS) \
$(NATPMP_CFLAGS) \
$(PTHREAD_CFLAGS)
libtoxcore_la_LDFLAGS = $(TOXCORE_LT_LDFLAGS) \
$(EXTRA_LT_LDFLAGS) \
$(LIBSODIUM_LDFLAGS) \
$(NACL_LDFLAGS) \
$(MINIDUMP_LDFLAGS) \
$(MINIUPNP_LDFLAGS) \
$(NATPMP_LDFLAGS) \
$(MATH_LDFLAGS) \
$(RT_LIBS) \
$(WINSOCK2_LIBS)
@ -72,5 +74,6 @@ libtoxcore_la_LDFLAGS = $(TOXCORE_LT_LDFLAGS) \
libtoxcore_la_LIBADD = $(LIBSODIUM_LIBS) \
$(NACL_OBJECTS) \
$(NAC_LIBS) \
$(MINIDUMP_LIBS) \
$(MINIUPNP_LIBS) \
$(NATPMP_LIBS) \
$(PTHREAD_LIBS)

View File

@ -1766,7 +1766,7 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
} else {
IP ip;
ip_init(&ip, options->ipv6enabled);
m->net = new_networking_upnp(ip, options->port_range[0], options->port_range[1], options->upnp_enabled, &net_err);
m->net = new_networking_nat(ip, options->port_range[0], options->port_range[1], options->traversal_type, &net_err);
}
if (m->net == NULL) {

View File

@ -68,7 +68,7 @@ enum {
typedef struct {
uint8_t ipv6enabled;
uint8_t udp_disabled;
uint8_t upnp_enabled;
TOX_TRAVERSAL_TYPE traversal_type;
TCP_Proxy_Info proxy_info;
uint16_t port_range[2];
uint16_t tcp_server_port;

View File

@ -50,6 +50,10 @@
#include <miniupnpc/upnperrors.h>
#endif
#ifdef HAVE_LIBNATPMP
#include <natpmp.h>
#endif
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
static const char *inet_ntop(sa_family_t family, void *addr, char *buf, size_t bufsize)
@ -133,7 +137,6 @@ static void upnp_map_port(uint16_t port)
devlist = upnpDiscover(1000, NULL, NULL, 0, 0, 2, &error);
#endif
if (error) {
LOGGER_WARNING("UPnP discovery failed (error = %d)", error);
return;
@ -173,6 +176,42 @@ static void upnp_map_port(uint16_t port)
}
#endif
#ifdef HAVE_LIBNATPMP
/* Setup port forwarding using NAT-PMP */
static void natpmp_map_port(uint16_t port)
{
LOGGER_DEBUG("Attempting to set up NAT-PMP port forwarding");
int error;
natpmp_t natpmp;
natpmpresp_t resp;
error = initnatpmp(&natpmp, 0, 0);
if (error) {
LOGGER_WARNING("NAT-PMP initialization failed (error = %d)", error);
return;
}
error = sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, port, port, 3600);
if (error != 12) {
LOGGER_WARNING("NAT-PMP send request failed (error = %d)", error);
closenatpmp(&natpmp);
return;
}
error = readnatpmpresponseorretry(&natpmp, &resp);
for ( ; error == NATPMP_TRYAGAIN ; error = readnatpmpresponseorretry(&natpmp, &resp) )
sleep(1);
if (error)
LOGGER_WARNING("NAT-PMP port mapping failed (error = %d)", error);
else
LOGGER_INFO("NAT-PMP mapped port %d", port);
closenatpmp(&natpmp);
}
#endif
/* Check if socket is valid.
*
* return 1 if valid
@ -544,7 +583,7 @@ static void at_shutdown(void)
*/
Networking_Core *new_networking(IP ip, uint16_t port)
{
return new_networking_upnp(ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), 1, 0);
return new_networking_nat(ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), TOX_TRAVERSAL_TYPE_NONE, 0);
}
/* Initialize networking.
@ -552,7 +591,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
*/
Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error)
{
return new_networking_upnp(ip, port_from, port_to, 1, 0);
return new_networking_nat(ip, port_from, port_to, TOX_TRAVERSAL_TYPE_NONE, 0);
}
/* Initialize networking.
@ -565,7 +604,7 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to,
*
* If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
*/
Networking_Core *new_networking_upnp(IP ip, uint16_t port_from, uint16_t port_to, bool upnp_enabled, unsigned int *error)
Networking_Core *new_networking_nat(IP ip, uint16_t port_from, uint16_t port_to, TOX_TRAVERSAL_TYPE traversal_type, unsigned int *error)
{
/* If both from and to are 0, use default port range
* If one is 0 and the other is non-0, use the non-0 value as only port
@ -745,10 +784,15 @@ Networking_Core *new_networking_upnp(IP ip, uint16_t port_from, uint16_t port_to
*error = 0;
#ifdef HAVE_LIBMINIUPNPC
if (upnp_enabled)
if ((traversal_type == TOX_TRAVERSAL_TYPE_UPNP) || (traversal_type == TOX_TRAVERSAL_TYPE_ALL))
upnp_map_port(ntohs(temp->port));
#endif
#ifdef HAVE_LIBNATPMP
if ((traversal_type == TOX_TRAVERSAL_TYPE_NATPMP) || (traversal_type == TOX_TRAVERSAL_TYPE_ALL))
natpmp_map_port(ntohs(temp->port));
#endif
return temp;
}

View File

@ -32,7 +32,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
@ -166,6 +165,33 @@ typedef struct {
}
IP_Port;
/**
* Type of technology used to try to traverse a NAT.
*/
typedef enum TOX_TRAVERSAL_TYPE {
/**
* Don't use any particular technology.
*/
TOX_TRAVERSAL_TYPE_NONE,
/**
* Use UPnP technology.
*/
TOX_TRAVERSAL_TYPE_UPNP,
/**
* Use NAT-PMP technology.
*/
TOX_TRAVERSAL_TYPE_NATPMP,
/**
* Use both UPnP and NAT-PMP technologies.
*/
TOX_TRAVERSAL_TYPE_ALL,
} TOX_TRAVERSAL_TYPE;
/* Does the IP6 struct a contain an IPv4 address in an IPv6 one? */
#define IPV6_IPV4_IN_V6(a) ((a.uint64[0] == 0) && (a.uint32[2] == htonl (0xffff)))
@ -379,7 +405,7 @@ void networking_poll(Networking_Core *net);
*/
Networking_Core *new_networking(IP ip, uint16_t port);
Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error);
Networking_Core *new_networking_upnp(IP ip, uint16_t port_from, uint16_t port_to, bool upnp_enabled, unsigned int *error);
Networking_Core *new_networking_nat(IP ip, uint16_t port_from, uint16_t port_to, TOX_TRAVERSAL_TYPE traversal_type, unsigned int *error);
/* Function to cleanup networking stuff (doesn't do much right now). */
void kill_networking(Networking_Core *net);

View File

@ -101,7 +101,7 @@ void tox_options_default(struct Tox_Options *options)
memset(options, 0, sizeof(struct Tox_Options));
options->ipv6_enabled = 1;
options->udp_enabled = 1;
options->upnp_enabled = 1;
options->traversal_type = TOX_TRAVERSAL_TYPE_NONE;
options->proxy_type = TOX_PROXY_TYPE_NONE;
}
}
@ -167,7 +167,7 @@ Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
m_options.ipv6enabled = options->ipv6_enabled;
m_options.udp_disabled = !options->udp_enabled;
m_options.upnp_enabled = options->upnp_enabled;
m_options.traversal_type = options->traversal_type;
m_options.port_range[0] = options->start_port;
m_options.port_range[1] = options->end_port;
m_options.tcp_server_port = options->tcp_port;

View File

@ -27,6 +27,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "network.h"
#ifdef __cplusplus
extern "C" {
@ -412,15 +413,9 @@ struct Tox_Options {
/**
* Enable the use of UPnP for port forwarding.
*
* When enabled it will automatically make a UPnP-compatible (and enabled)
* router forward port 33445 to you (or whichever port Tox decides to use).
* This should improve tox networking, especially in udp mode.
* Setting this to false will force Tox to not search/use UPnP-compatible
* devices.
* Try to traverse a NAT.
*/
bool upnp_enabled;
TOX_TRAVERSAL_TYPE traversal_type;
/**