mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
NAT traversal: add support for TCP relays
This commit is contained in:
parent
5f3dc97eef
commit
2e9a731ff3
|
@ -8,6 +8,8 @@ libtoxcore_la_includedir = $(includedir)/tox
|
|||
|
||||
libtoxcore_la_SOURCES = ../toxcore/DHT.h \
|
||||
../toxcore/DHT.c \
|
||||
../toxcore/nat_traversal.h \
|
||||
../toxcore/nat_traversal.c \
|
||||
../toxcore/network.h \
|
||||
../toxcore/network.c \
|
||||
../toxcore/crypto_core.h \
|
||||
|
|
|
@ -1814,7 +1814,7 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
|
|||
}
|
||||
|
||||
if (options->tcp_server_port) {
|
||||
m->tcp_server = new_TCP_server(options->ipv6enabled, 1, &options->tcp_server_port, m->dht->self_secret_key, m->onion);
|
||||
m->tcp_server = new_TCP_server_nat(options->ipv6enabled, 1, &options->tcp_server_port, options->traversal_type, m->dht->self_secret_key, m->onion);
|
||||
|
||||
if (m->tcp_server == NULL) {
|
||||
kill_friend_connections(m->fr_c);
|
||||
|
|
|
@ -30,7 +30,9 @@
|
|||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include "util.h"
|
||||
#include "nat_traversal.h"
|
||||
|
||||
/* return 1 on success
|
||||
* return 0 on failure
|
||||
|
@ -939,8 +941,17 @@ static sock_t new_listening_TCP_socket(int family, uint16_t port)
|
|||
return sock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added for reverse compatibility with old new_TCP_server calls.
|
||||
*/
|
||||
TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *secret_key,
|
||||
Onion *onion)
|
||||
{
|
||||
return new_TCP_server_nat(ipv6_enabled,num_sockets,ports,TOX_TRAVERSAL_TYPE_NONE,secret_key,onion);
|
||||
}
|
||||
|
||||
TCP_Server *new_TCP_server_nat(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, TOX_TRAVERSAL_TYPE traversal_type,
|
||||
const uint8_t *secret_key, Onion *onion)
|
||||
{
|
||||
if (num_sockets == 0 || ports == NULL)
|
||||
return NULL;
|
||||
|
@ -999,6 +1010,16 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uin
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBMINIUPNPC
|
||||
if ((traversal_type == TOX_TRAVERSAL_TYPE_UPNP) || (traversal_type == TOX_TRAVERSAL_TYPE_ALL))
|
||||
upnp_map_port(NAT_TRAVERSAL_TCP,ntohs(ports[i]));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNATPMP
|
||||
if ((traversal_type == TOX_TRAVERSAL_TYPE_NATPMP) || (traversal_type == TOX_TRAVERSAL_TYPE_ALL))
|
||||
natpmp_map_port(NAT_TRAVERSAL_TCP,ntohs(ports[i]));
|
||||
#endif
|
||||
|
||||
temp->socks_listening[temp->num_listening_socks] = sock;
|
||||
++temp->num_listening_socks;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#ifndef TCP_SERVER_H
|
||||
#define TCP_SERVER_H
|
||||
|
||||
#include "tox.h"
|
||||
#include "crypto_core.h"
|
||||
#include "onion.h"
|
||||
#include "list.h"
|
||||
|
@ -142,10 +143,16 @@ typedef struct {
|
|||
} TCP_Server;
|
||||
|
||||
/* Create new TCP server instance.
|
||||
* Added for reverse compatibility with old new_TCP_server calls.
|
||||
*/
|
||||
TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *secret_key,
|
||||
Onion *onion);
|
||||
|
||||
/* Create new TCP server instance.
|
||||
*/
|
||||
TCP_Server *new_TCP_server_nat(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, TOX_TRAVERSAL_TYPE traversal_type,
|
||||
const uint8_t *secret_key, Onion *onion);
|
||||
|
||||
/* Run the TCP_server
|
||||
*/
|
||||
void do_TCP_server(TCP_Server *TCP_server);
|
||||
|
|
140
toxcore/nat_traversal.c
Normal file
140
toxcore/nat_traversal.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* nat_traversal.c -- Functions to traverse a NAT (UPnP, NAT-PMP).
|
||||
*
|
||||
* Copyright (C) 2014 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBMINIUPNPC
|
||||
#include <miniupnpc/miniupnpc.h>
|
||||
#include <miniupnpc/miniwget.h>
|
||||
#include <miniupnpc/upnpcommands.h>
|
||||
#include <miniupnpc/upnperrors.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNATPMP
|
||||
#include <natpmp.h>
|
||||
#endif
|
||||
|
||||
#include "nat_traversal.h"
|
||||
#include "logger.h"
|
||||
|
||||
#ifdef HAVE_LIBMINIUPNPC
|
||||
/* Setup port forwarding using UPnP */
|
||||
void upnp_map_port(NAT_TRAVERSAL_PROTO proto, uint16_t port)
|
||||
{
|
||||
LOGGER_DEBUG("Attempting to set up UPnP port forwarding");
|
||||
|
||||
int error = 0;
|
||||
struct UPNPDev *devlist = NULL;
|
||||
|
||||
#if MINIUPNPC_API_VERSION < 14
|
||||
devlist = upnpDiscover(1000, NULL, NULL, 0, 0, &error);
|
||||
#else
|
||||
devlist = upnpDiscover(1000, NULL, NULL, 0, 0, 2, &error);
|
||||
#endif
|
||||
|
||||
if (error) {
|
||||
LOGGER_WARNING("UPnP discovery failed (error = %d)", error);
|
||||
return;
|
||||
}
|
||||
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
char lanaddr[64];
|
||||
|
||||
error = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
|
||||
freeUPNPDevlist(devlist);
|
||||
if (error) {
|
||||
if (error == 1) {
|
||||
LOGGER_INFO("A valid IGD has been found.");
|
||||
|
||||
char portstr[10];
|
||||
snprintf(portstr, sizeof(portstr), "%d", port);
|
||||
|
||||
if (proto == NAT_TRAVERSAL_UDP)
|
||||
error = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, portstr, portstr, lanaddr, "Tox", "UDP", 0, "0");
|
||||
else if (proto == NAT_TRAVERSAL_TCP)
|
||||
error = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, portstr, portstr, lanaddr, "Tox", "TCP", 0, "0");
|
||||
else
|
||||
LOGGER_WARNING("UPnP port mapping failed (unknown NAT_TRAVERSAL_PROTO)");
|
||||
|
||||
if (error)
|
||||
LOGGER_WARNING("UPnP port mapping failed (error = %d)", error);
|
||||
else
|
||||
LOGGER_INFO("UPnP mapped port %d", port);
|
||||
} else if (error == 2)
|
||||
LOGGER_WARNING("IGD was found but reported as not connected.");
|
||||
else if (error == 3)
|
||||
LOGGER_WARNING("UPnP device was found but not recoginzed as IGD.");
|
||||
else
|
||||
LOGGER_WARNING("Unknown error finding IGD: %d", error);
|
||||
|
||||
FreeUPNPUrls(&urls);
|
||||
} else
|
||||
LOGGER_WARNING("No IGD was found.");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_LIBNATPMP
|
||||
/* Setup port forwarding using NAT-PMP */
|
||||
void natpmp_map_port(NAT_TRAVERSAL_PROTO proto, 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;
|
||||
}
|
||||
|
||||
if (proto == NAT_TRAVERSAL_UDP)
|
||||
error = sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, port, port, 3600);
|
||||
else if (proto == NAT_TRAVERSAL_TCP)
|
||||
error = sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, port, port, 3600);
|
||||
else {
|
||||
LOGGER_WARNING("NAT-PMP port mapping failed (unknown NAT_TRAVERSAL_PROTO)");
|
||||
closenatpmp(&natpmp);
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
53
toxcore/nat_traversal.h
Normal file
53
toxcore/nat_traversal.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* nat_traversal.h -- Functions to traverse a NAT (UPnP, NAT-PMP).
|
||||
*
|
||||
* Copyright (C) 2014 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NAT_TRAVERSAL_H
|
||||
#define NAT_TRAVERSAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/**
|
||||
* The protocol that will be used by the nat traversal.
|
||||
*/
|
||||
#if defined(HAVE_LIBMINIUPNPC) || defined(HAVE_LIBNATPMP)
|
||||
typedef enum NAT_TRAVERSAL_PROTO {
|
||||
|
||||
/* UDP */
|
||||
NAT_TRAVERSAL_UDP,
|
||||
|
||||
/* TCP */
|
||||
NAT_TRAVERSAL_TCP,
|
||||
|
||||
} NAT_TRAVERSAL_PROTO;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_LIBMINIUPNPC
|
||||
/* Setup port forwarding using UPnP */
|
||||
void upnp_map_port(NAT_TRAVERSAL_PROTO proto, uint16_t port);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNATPMP
|
||||
/* Setup port forwarding using NAT-PMP */
|
||||
void natpmp_map_port(NAT_TRAVERSAL_PROTO proto, uint16_t port);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -42,17 +42,7 @@
|
|||
|
||||
#include "network.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef HAVE_LIBMINIUPNPC
|
||||
#include <miniupnpc/miniupnpc.h>
|
||||
#include <miniupnpc/miniwget.h>
|
||||
#include <miniupnpc/upnpcommands.h>
|
||||
#include <miniupnpc/upnperrors.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNATPMP
|
||||
#include <natpmp.h>
|
||||
#endif
|
||||
#include "nat_traversal.h"
|
||||
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
|
||||
|
@ -122,96 +112,6 @@ static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf)
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBMINIUPNPC
|
||||
/* Setup port forwarding using UPnP */
|
||||
static void upnp_map_port(uint16_t port)
|
||||
{
|
||||
LOGGER_DEBUG("Attempting to set up UPnP port forwarding");
|
||||
|
||||
int error = 0;
|
||||
struct UPNPDev *devlist = NULL;
|
||||
|
||||
#if MINIUPNPC_API_VERSION < 14
|
||||
devlist = upnpDiscover(1000, NULL, NULL, 0, 0, &error);
|
||||
#else
|
||||
devlist = upnpDiscover(1000, NULL, NULL, 0, 0, 2, &error);
|
||||
#endif
|
||||
|
||||
if (error) {
|
||||
LOGGER_WARNING("UPnP discovery failed (error = %d)", error);
|
||||
return;
|
||||
}
|
||||
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
char lanaddr[64];
|
||||
|
||||
error = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
|
||||
freeUPNPDevlist(devlist);
|
||||
if (error) {
|
||||
if (error == 1) {
|
||||
LOGGER_INFO("A valid IGD has been found.");
|
||||
|
||||
char portstr[10];
|
||||
snprintf(portstr, sizeof(portstr), "%d", port);
|
||||
|
||||
error = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, portstr, portstr, lanaddr, "Tox", "UDP", 0, "0");
|
||||
if (error) {
|
||||
LOGGER_WARNING("UPnP port mapping failed (error = %d)", error);
|
||||
} else {
|
||||
LOGGER_INFO("UPnP mapped port %d", port);
|
||||
}
|
||||
} else if (error == 2) {
|
||||
LOGGER_WARNING("IGD was found but reported as not connected.");
|
||||
} else if (error == 3) {
|
||||
LOGGER_WARNING("UPnP device was found but not recoginzed as IGD.");
|
||||
} else {
|
||||
LOGGER_WARNING("Unknown error finding IGD: %d", error);
|
||||
}
|
||||
|
||||
FreeUPNPUrls(&urls);
|
||||
} else {
|
||||
LOGGER_WARNING("No IGD was found.");
|
||||
}
|
||||
}
|
||||
#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
|
||||
|
@ -785,12 +685,12 @@ Networking_Core *new_networking_nat(IP ip, uint16_t port_from, uint16_t port_to,
|
|||
|
||||
#ifdef HAVE_LIBMINIUPNPC
|
||||
if ((traversal_type == TOX_TRAVERSAL_TYPE_UPNP) || (traversal_type == TOX_TRAVERSAL_TYPE_ALL))
|
||||
upnp_map_port(ntohs(temp->port));
|
||||
upnp_map_port(NAT_TRAVERSAL_UDP,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));
|
||||
natpmp_map_port(NAT_TRAVERSAL_UDP,ntohs(temp->port));
|
||||
#endif
|
||||
|
||||
return temp;
|
||||
|
|
Loading…
Reference in New Issue
Block a user