Commit 42b1b132 authored by jselbie's avatar jselbie Committed by John Selbie

Version 1.2.0 candidate

parent 09e63bc0
......@@ -9,5 +9,4 @@ Version 1.1.2 - Fix compile issues for older linux and macos distributions
Version 1.1.3 - Fix compile issue for clang on MacOSX
Version 1.2.0 - Amazon EC2 support added
STUNTMAN - An open source STUN server
Version 1.1.0
February 1, 2012
Version 1.2.0
December 5, 2012
---------------------------------------------------------
......@@ -19,6 +19,10 @@ Features:
address interfaces (if available) and provide NAT behavior and filtering
detection support for clients.
Support for running a full mode STUN service on an Amazon EC2 instance. Run
"stunserver --help" for visit www.stunprotocol.org on how to configure this
mode.
Open source Apache license. See LICENSE file fore more details.
---------------------------------------------------------
......@@ -58,9 +62,12 @@ Testing:
Fedora 15 with gcc/g++ 4.6.0
Ubuntu 11 with gcc/g++ 4.5.2
Ubuntu 12 with gcc/g++ 4.6.3
Ubuntu 12 with clang/clang++ 3.0
Amazon AWS with gcc/g++ 4.4
MacOS Snow Leopard (will not compile on earlier versions without updating to
a newer version of gcc/g++)
MacOS Lion (with Clang compiler)
FreeBSD 9.0 with gcc/g++ 4.2.1
Solaris 11 with gcc/g++ 4.5.2
......@@ -124,9 +131,6 @@ Firewall
Feature roadmap (the features I want to implement in a subsequent release)
Host a full server across two separate machines (such that two ip addresses
on a single machine will not be required for full mode).
Cleanup Makefile and add "configure" and autotools support
Finish Windows port and able to run as a Windows service
......
# BOOST_INCLUDE := -I/home/jselbie/boost_1_48_0
# BOOST_INCLUDE := -I/home/jselbie/boost_1_51_0
# OPENSSL_INCLUDE := -I/home/jselbie/lib/openssl
DEFINES := -DNDEBUG
# CLANG compiler works fine
# CXX := /usr/bin/clang++
STANDARD_FLAGS := -Wall -Wuninitialized
RELEASE_FLAGS := -O2
......@@ -19,6 +22,7 @@ endif
.PHONY: all clean debug
%.h.gch: %.h
......
......@@ -61,6 +61,33 @@ Cleanup:
}
HRESULT NumericIPToAddress(int family, const char* pszIP, CSocketAddress* pAddr)
{
HRESULT hr = S_OK;
ChkIf((family != AF_INET) && (family != AF_INET6), E_INVALIDARG);
if (family == AF_INET)
{
sockaddr_in addr4 = {};
ChkIf(0 == ::inet_pton(family, pszIP, &addr4.sin_addr), E_FAIL);
addr4.sin_family = family;
*pAddr = CSocketAddress(addr4);
}
else
{
sockaddr_in6 addr6 = {};
ChkIf(0 == ::inet_pton(family, pszIP, &addr6.sin6_addr), E_FAIL);
addr6.sin6_family = family;
*pAddr = CSocketAddress(addr6);
}
Cleanup:
return hr;
}
......@@ -29,6 +29,8 @@
*/
HRESULT ResolveHostName(const char* pszHostName, int family, bool fNumericOnly, CSocketAddress* pAddr);
HRESULT NumericIPToAddress(int family, const char* pszIP, CSocketAddress* pAddr);
#endif /* RESOLVEHOSTNAME_H */
......
STUNK - An open source STUN server
Version 1.1.0
February 1, 2012
STUNTMAN - An open source STUN server
Version 1.2.0
December 5, 2012
---------------------------------------------------------
......@@ -19,6 +19,10 @@ Features:
address interfaces (if available) and provide NAT behavior and filtering
detection support for clients.
Support for running a full mode STUN service on an Amazon EC2 instance. Run
"stunserver --help" for visit www.stunprotocol.org on how to configure this
mode.
Open source Apache license. See LICENSE file fore more details.
---------------------------------------------------------
......@@ -58,9 +62,12 @@ Testing:
Fedora 15 with gcc/g++ 4.6.0
Ubuntu 11 with gcc/g++ 4.5.2
Ubuntu 12 with gcc/g++ 4.6.3
Ubuntu 12 with clang/clang++ 3.0
Amazon AWS with gcc/g++ 4.4
MacOS Snow Leopard (will not compile on earlier versions without updating to
a newer version of gcc/g++)
MacOS Lion (with Clang compiler)
FreeBSD 9.0 with gcc/g++ 4.2.1
Solaris 11 with gcc/g++ 4.5.2
......@@ -124,9 +131,6 @@ Firewall
Feature roadmap (the features I want to implement in a subsequent release)
Host a full server across two separate machines (such that two ip addresses
on a single machine will not be required for full mode).
Cleanup Makefile and add "configure" and autotools support
Finish Windows port and able to run as a Windows service
......
STUNK - An open source STUN server
Version 1.1.0
February 1, 2012
STUNTMAN - An open source STUN server
Version 1.2.0
December 5, 2012
---------------------------------------------------------
......@@ -14,6 +14,8 @@ Features:
Stun server can operate in "full" mode as well as "basic" mode. Basic mode configures the server to listen on one port and respond to STUN binding requests. Full mode configures the service to listen on two different IP address interfaces (if available) and provide NAT behavior and filtering detection support for clients.
Support for running a full mode STUN service on an Amazon EC2 instance. Run "stunserver --help" for visit www.stunprotocol.org on how to configure this mode.
Open source Apache license. See LICENSE file fore more details.
---------------------------------------------------------
......@@ -36,8 +38,11 @@ Testing:
Fedora 15 with gcc/g++ 4.6.0
Ubuntu 11 with gcc/g++ 4.5.2
Ubuntu 12 with gcc/g++ 4.6.3
Ubuntu 12 with clang/clang++ 3.0
Amazon AWS with gcc/g++ 4.4
MacOS Snow Leopard (will not compile on earlier versions without updating to a newer version of gcc/g++)
MacOS Lion (with Clang compiler)
FreeBSD 9.0 with gcc/g++ 4.2.1
Solaris 11 with gcc/g++ 4.5.2
......@@ -79,8 +84,6 @@ Firewall
Feature roadmap (the features I want to implement in a subsequent release)
Host a full server across two separate machines (such that two ip addresses on a single machine will not be required for full mode).
Cleanup Makefile and add "configure" and autotools support
Finish Windows port and able to run as a Windows service
......
......@@ -7,94 +7,93 @@ stunclient - command line app for the STUN protocol
\f[B]stunclient\f[] [OPTIONS] server [port]
.SH DESCRIPTION
.PP
stunclient attempts to discover the local host's own external IP
address, obtain a port mapping, and optionally discover properties
of the Network Address Translator (NAT) between the host and the
the server.
stunclient attempts to discover the local host\[aq]s own external IP
address, obtain a port mapping, and optionally discover properties of
the Network Address Translator (NAT) between the host and the the
server.
.SH OPTIONS
.PP
The following options are supported.
.PP
\f[CR]
--mode\ MODE
--localaddr\ INTERFACE
--localport\ PORTNUMBER
--family\ IPVERSION
--protocol\ PROTO
--verbosity\ LOGLEVEL
--help
.IP
.nf
\f[C]
--mode\ MODE
--localaddr\ INTERFACE
--localport\ PORTNUMBER
--family\ IPVERSION
--protocol\ PROTO
--verbosity\ LOGLEVEL
--help
\f[]
.fi
.PP
Details of each option and paramters are as follows.
.PP
\f[B]server\f[]
.PP
The \f[B]server\f[] parameter is the IP address or FQDN of the
remote server to befrom the binding tests with.
The \f[B]server\f[] parameter is the IP address or FQDN of the remote
server to befrom the binding tests with.
It is the only required parameter.
.PP
* * * * *
.PP
\f[B]port\f[]
.PP
The \f[B]port\f[] parameter is an optional parameter that can
follow the server parameter.
The \f[B]port\f[] parameter is an optional parameter that can follow the
server parameter.
The default is 3478 for UDP and TCP.
.PP
* * * * *
.PP
\f[B]\[em]mode\f[] MODE
\f[B]--mode\f[] MODE
.PP
Where MODE is either \[lq]basic\[rq] or \[lq]full\[rq].
\[lq]basic\[rq] mode is the default and indicates that the client
should perform a STUN binding test only.
\[lq]full\[rq] mode indicates that the client should attempt to
diagnose NAT behavior and filtering methodologies if the server
supports this mode.
Where MODE is either "basic" or "full".
"basic" mode is the default and indicates that the client should perform
a STUN binding test only.
"full" mode indicates that the client should attempt to diagnose NAT
behavior and filtering methodologies if the server supports this mode.
The NAT filtering test is only supported for UDP.
.PP
* * * * *
.PP
\f[B]\[em]localaddr\f[] INTERFACE or IPADDRESS
\f[B]--localaddr\f[] INTERFACE or IPADDRESS
.PP
The value for this option may the name of an interface (such as
\[lq]eth0\[rq] or \[lq]lo\[rq]).
Or it may be one of the available IP addresses assigned to a
network interface present on the host (such as
\[lq]128.23.45.67\[rq]).
The value for this option may the name of an interface (such as "eth0"
or "lo").
Or it may be one of the available IP addresses assigned to a network
interface present on the host (such as "128.23.45.67").
The interface chosen will be the preferred address for sending and
receiving responses with the remote server.
The default is to let the system decide which address to send on
and to listen for responses on all addresses (INADDR_ANY).
The default is to let the system decide which address to send on and to
listen for responses on all addresses (INADDR_ANY).
.PP
* * * * *
.PP
\f[B]\[em]localport\f[] PORTNUM
\f[B]--localport\f[] PORTNUM
.PP
PORTNUM is a value between 1 to 65535.
This is the UDP or TCP port that the primary and alternate
interfaces listen on as the primary port for binding requests.
This is the UDP or TCP port that the primary and alternate interfaces
listen on as the primary port for binding requests.
If not specified, a randomly available port chosen by the system is
used.
.PP
* * * * *
.PP
\f[B]\[em]family\f[] IPVERSION
\f[B]--family\f[] IPVERSION
.PP
IPVERSION is either \[lq]4\[rq] or \[lq]6\[rq] to specify the usage
of IPV4 or IPV6.
If not specified, the default value is \[lq]4\[rq].
IPVERSION is either "4" or "6" to specify the usage of IPV4 or IPV6.
If not specified, the default value is "4".
.PP
* * * * *
.PP
\f[B]\[em]protocol\f[] PROTO
\f[B]--protocol\f[] PROTO
.PP
PROTO is either \[lq]udp\[rq] or \[lq]tcp\[rq].
\[lq]udp\[rq] is the default if this parameter is not specified
PROTO is either "udp" or "tcp".
"udp" is the default if this parameter is not specified
.PP
* * * * *
.PP
\f[B]\[em]verbosity\f[] LOGLEVEL
\f[B]--verbosity\f[] LOGLEVEL
.PP
Sets the verbosity of the logging level.
0 is the default (minimal output and logging).
......@@ -103,22 +102,22 @@ Sets the verbosity of the logging level.
.PP
* * * * *
.PP
\f[B]\[em]help\f[] Prints this help page
\f[B]--help\f[] Prints this help page
.SH EXAMPLES
.TP
.B stunclient stunserver.org 3478
Performs a simple binding test request with the server listening at
\[lq]stunserver.org\[rq]
"stunserver.org"
.RS
.RE
.TP
.B stunclient \[em]mode full \[em]localport 9999 12.34.56.78
Performs a full set of UDP NAT behavior tests from local port 9999
to the server listening at IP Address 12.34.56.78 (port 3478)
.B stunclient --mode full --localport 9999 12.34.56.78
Performs a full set of UDP NAT behavior tests from local port 9999 to
the server listening at IP Address 12.34.56.78 (port 3478)
.RS
.RE
.TP
.B stunclient \[em]protocol tcp stun.selbie.com
.B stunclient --protocol tcp stun.selbie.com
Performs a simple binding test using TCP to server listening on the
default port of 3478 at stun.selbie.com
.RS
......@@ -126,4 +125,3 @@ default port of 3478 at stun.selbie.com
.SH AUTHOR
.PP
john selbie (jselbie\@gmail.com)
This diff is collapsed.
This diff is collapsed.
......@@ -26,6 +26,8 @@ The following options are supported.
--protocol PROTO
--maxconn MAXCONN
--verbosity LOGLEVEL
--primaryadvertised
--altadvertised
--help
Details of each option are as follows.
......@@ -67,7 +69,7 @@ a configured IP address.
____
**--altinterface** INTERFACE OR IPADDRESS
**--altinterface** INTERFACE
Where INTERFACE specified is either a local IP address (e.g. "192.168.1.3")
of the host or the name of a network interface (e.g. "eth1").
......@@ -148,6 +150,31 @@ The default is 0.
____
**--primaryadvertised** PRIMARY-IP
**--altadvertised** ALT-IP
Where PRIMARY-IP and ALT-IP are valid numeric IP address strings (e.g. "101.23.45.67") that
are the public IP addresses of the --primaryinterface and --altinterface addresses discussed
above.
These two parameters are for advanced usage only. It is intended for support of
running a STUN server in full mode on Amazon EC2 or other hosted environment
where the server is running behind a NAT. Do not set this parameter unless you
know specifically the effect it creates.
Normally, without these parameters being set, the ORIGIN attribute, OTHER-ADDRESS attribute, and
CHANGED-ADDRESS attributes are are determined by querying the local adapters or sockets
for the IP address they are listening on. When running the server in a NAT environment,
binding responses will still contain a correct set of mapping address attributes, such that P2P
connectivity may succeed. However, the the ORIGIN, OTHER-ADDRESS,
and CHANGED-ADDRESS attributes sent by the server will be incorrect. The impact of sending an incorrect OTHER-ADDRESS or CHANGED-ADDRESS
will result in a client attempting to do NAT Behavior tests or NAT filtering tests to report an incorrect result.
For more details, visit www.stunprotocol.org for details on how to correctly set these parameters for use within Amazon EC2.
____
**--help**
Prints this help page
......
This diff is collapsed.
......@@ -31,6 +31,7 @@
// these are auto-generated files made from markdown sources. See ../resources
#include "stunserver.txtcode"
#include "stunserver_lite.txtcode"
#include "resolvehostname.h"
void PrintUsage(bool fSummaryUsage)
......@@ -104,11 +105,14 @@ struct StartupArgs
std::string strAltInterface;
std::string strPrimaryPort;
std::string strAltPort;
std::string strPrimaryAdvertised;
std::string strAlternateAdvertised;
std::string strFamily;
std::string strProtocol;
std::string strHelp;
std::string strVerbosity;
std::string strMaxConnections;
};
#define PRINTARG(member) Logging::LogMsg(LL_DEBUG, "%s = %s", #member, args.member.length() ? args.member.c_str() : "<empty>");
......@@ -119,6 +123,8 @@ void DumpStartupArgs(StartupArgs& args)
PRINTARG(strMode);
PRINTARG(strPrimaryInterface);
PRINTARG(strAltInterface);
PRINTARG(strPrimaryAdvertised);
PRINTARG(strAlternateAdvertised);
PRINTARG(strPrimaryPort);
PRINTARG(strAltPort);
PRINTARG(strFamily);
......@@ -157,6 +163,18 @@ void DumpConfig(CStunServerConfig &config)
Logging::LogMsg(LL_DEBUG, "AA = %s", strSocket.c_str());
}
if (config.addrPrimaryAdvertised.IsIPAddressZero() == false)
{
config.addrPrimaryAdvertised.ToString(&strSocket);
Logging::LogMsg(LL_DEBUG, "Primary IP will be advertised as %s", strSocket.c_str());
}
if (config.addrAlternateAdvertised.IsIPAddressZero() == false)
{
config.addrAlternateAdvertised.ToString(&strSocket);
Logging::LogMsg(LL_DEBUG, "Alternate IP will be advertised as %s", strSocket.c_str());
}
Logging::LogMsg(LL_DEBUG, "Protocol = %s", config.fTCP ? "TCP" : "UDP");
if (config.fTCP && (config.nMaxConnections>0))
{
......@@ -206,6 +224,8 @@ HRESULT BuildServerConfigurationFromArgs(StartupArgs& argsIn, CStunServerConfig*
bool fHasAtLeastTwoAdapters = false;
CStunServerConfig config;
int nMaxConnections = 0;
const char* pszPrimaryAdvertised = argsIn.strPrimaryAdvertised.c_str();
const char* pszAltAdvertised = argsIn.strAlternateAdvertised.c_str();
enum ServerMode
{
......@@ -221,7 +241,7 @@ HRESULT BuildServerConfigurationFromArgs(StartupArgs& argsIn, CStunServerConfig*
ChkIfA(pConfigOut == NULL, E_INVALIDARG);
// normalize the args. The "trim" is not needed for command line args, but will be useful when we have an "init file" for intializing the server
// normalize the args. The "trim" is not needed for command line args, but will be useful when we have an "init file" for initializing the server
StringHelper::ToLower(args.strMode);
StringHelper::Trim(args.strMode);
......@@ -237,6 +257,9 @@ HRESULT BuildServerConfigurationFromArgs(StartupArgs& argsIn, CStunServerConfig*
StringHelper::ToLower(args.strProtocol);
StringHelper::Trim(args.strProtocol);
StringHelper::Trim(args.strPrimaryAdvertised);
StringHelper::Trim(args.strAlternateAdvertised);
......@@ -338,7 +361,7 @@ HRESULT BuildServerConfigurationFromArgs(StartupArgs& argsIn, CStunServerConfig*
if (nPrimaryPort == nAltPort)
{
Logging::LogMsg(LL_ALWAYS, "Primary port and altnernate port must be different values");
Logging::LogMsg(LL_ALWAYS, "Primary port and alternate port must be different values");
Chk(E_INVALIDARG);
}
......@@ -435,6 +458,37 @@ HRESULT BuildServerConfigurationFromArgs(StartupArgs& argsIn, CStunServerConfig*
}
// ---- Address advertisement --------------------------------------------------------
// handle the advertised address parameters and make sure they are valid IP address strings
if (!StringHelper::IsNullOrEmpty(pszPrimaryAdvertised))
{
hr = ::NumericIPToAddress(family, pszPrimaryAdvertised, &config.addrPrimaryAdvertised);
if (FAILED(hr))
{
Logging::LogMsg(LL_ALWAYS, "Error with --primaryadvertised. %s is not a valid IP address string", pszPrimaryAdvertised);
Chk(hr);
}
}
if (!StringHelper::IsNullOrEmpty(pszAltAdvertised))
{
if (mode != Full)
{
Logging::LogMsg(LL_ALWAYS, "Error. --altadvertised was specified, but --mode param was not set to FULL.");
ChkIf(config.fHasAA, E_INVALIDARG);
}
hr = ::NumericIPToAddress(family, pszAltAdvertised, &config.addrAlternateAdvertised);
if (FAILED(hr))
{
Logging::LogMsg(LL_ALWAYS, "Error with --altadvertised. %s is not a valid IP address string", pszAltAdvertised);
Chk(hr);
}
}
*pConfigOut = config;
hr = S_OK;
......@@ -452,6 +506,8 @@ HRESULT ParseCommandLineArgs(int argc, char** argv, int startindex, StartupArgs*
cmdline.AddOption("mode", required_argument, &pStartupArgs->strMode);
cmdline.AddOption("primaryinterface", required_argument, &pStartupArgs->strPrimaryInterface);
cmdline.AddOption("altinterface", required_argument, &pStartupArgs->strAltInterface);
cmdline.AddOption("primaryadvertised", required_argument, &pStartupArgs->strPrimaryAdvertised);
cmdline.AddOption("altadvertised", required_argument, &pStartupArgs->strAlternateAdvertised);
cmdline.AddOption("primaryport", required_argument, &pStartupArgs->strPrimaryPort);
cmdline.AddOption("altport", required_argument, &pStartupArgs->strAltPort);
cmdline.AddOption("family", required_argument, &pStartupArgs->strFamily);
......
......@@ -49,11 +49,54 @@ CStunServer::~CStunServer()
Shutdown();
}
HRESULT CStunServer::AddSocket(TransportAddressSet* pTSA, SocketRole role, const CSocketAddress& addrListen, const CSocketAddress& addrAdvertise)
{
HRESULT hr = S_OK;
ASSERT(IsValidSocketRole(role));
Chk(_arrSockets[role].UDPInit(addrListen, role));
ChkA(_arrSockets[role].EnablePktInfoOption(true));
#ifdef DEBUG
{
CSocketAddress addrLocal = _arrSockets[role].GetLocalAddress();
// addrListen is the address we asked the socket to listen on via a call to bind()
// addrLocal is the socket address returned by getsockname after the socket is binded
// I can't think of any case where addrListen != addrLocal
// the ports will be different if addrListen.GetPort() is 0, but that
// should never happen.
// but if the assert below fails, I want to know about it
ASSERT(addrLocal.IsSameIP_and_Port(addrListen));
}
#endif
pTSA->set[role].fValid = true;
if (addrAdvertise.IsIPAddressZero() == false)
{
// set the TSA for this socket to what the configuration wants us to advertise this address for in ORIGIN and OTHER address attributes
pTSA->set[role].addr = addrAdvertise;
pTSA->set[role].addr.SetPort(addrListen.GetPort()); // use the original port
}
else
{
pTSA->set[role].addr = addrListen; // use the socket's IP and port (OK if this is INADDR_ANY)
}
Cleanup:
return hr;
}
HRESULT CStunServer::Initialize(const CStunServerConfig& config)
{
HRESULT hr = S_OK;
int socketcount = 0;
CRefCountedPtr<IStunAuth> _spAuth;
TransportAddressSet tsa = {};
// cleanup any thing that's going on now
Shutdown();
......@@ -61,39 +104,34 @@ HRESULT CStunServer::Initialize(const CStunServerConfig& config)
// optional code: create an authentication provider and initialize it here (if you want authentication)
// set the _spAuth member to reference it
// Chk(CYourAuthProvider::CreateInstanceNoInit(&_spAuth));
// Create the sockets
// Create the sockets and initialize the TSA thing
if (config.fHasPP)
{
Chk(_arrSockets[RolePP].UDPInit(config.addrPP, RolePP));
ChkA(_arrSockets[RolePP].EnablePktInfoOption(true));
Chk(AddSocket(&tsa, RolePP, config.addrPP, config.addrPrimaryAdvertised));
socketcount++;
}
if (config.fHasPA)
{
Chk(_arrSockets[RolePA].UDPInit(config.addrPA, RolePA));
ChkA(_arrSockets[RolePA].EnablePktInfoOption(true));
Chk(AddSocket(&tsa, RolePA, config.addrPA, config.addrPrimaryAdvertised));
socketcount++;
}
if (config.fHasAP)
{
Chk(_arrSockets[RoleAP].UDPInit(config.addrAP, RoleAP));
ChkA(_arrSockets[RoleAP].EnablePktInfoOption(true));
Chk(AddSocket(&tsa, RoleAP, config.addrAP, config.addrAlternateAdvertised));
socketcount++;
}
if (config.fHasAA)
{
Chk(_arrSockets[RoleAA].UDPInit(config.addrAA, RoleAA));
ChkA(_arrSockets[RoleAA].EnablePktInfoOption(true));
Chk(AddSocket(&tsa, RoleAA, config.addrAA, config.addrAlternateAdvertised));
socketcount++;
}
ChkIf(socketcount == 0, E_INVALIDARG);
if (config.fMultiThreadedMode == false)
{
Logging::LogMsg(LL_DEBUG, "Configuring single threaded mode\n");
......@@ -104,7 +142,7 @@ HRESULT CStunServer::Initialize(const CStunServerConfig& config)
_threads.push_back(pThread);
Chk(pThread->Init(_arrSockets, _spAuth, (SocketRole)-1));
Chk(pThread->Init(_arrSockets, &tsa, _spAuth, (SocketRole)-1));
}
else
{
......@@ -121,7 +159,7 @@ HRESULT CStunServer::Initialize(const CStunServerConfig& config)
pThread = new CStunSocketThread();
ChkIf(pThread==NULL, E_OUTOFMEMORY);
_threads.push_back(pThread);
Chk(pThread->Init(_arrSockets, _spAuth, rolePrimaryRecv));
Chk(pThread->Init(_arrSockets, &tsa, _spAuth, rolePrimaryRecv));
}
}
}
......@@ -161,8 +199,7 @@ HRESULT CStunServer::Shutdown()
_threads.clear();
_spAuth.ReleaseAndClear();
return S_OK;
}
......
......@@ -21,6 +21,7 @@
#include "stunsocket.h"
#include "stunsocketthread.h"
#include "stunauth.h"
#include "messagehandler.h"
......@@ -43,6 +44,9 @@ public:
CSocketAddress addrPA; // address for PA
CSocketAddress addrAP; // address for AP
CSocketAddress addrAA; // address for AA
CSocketAddress addrPrimaryAdvertised; // public-IP for PP and PA (port is ignored)
CSocketAddress addrAlternateAdvertised; // public-IP for AP and AA (port is ignored)
CStunServerConfig();
};
......@@ -68,6 +72,8 @@ private:
friend class CObjectFactory<CStunServer>;
CRefCountedPtr<IStunAuth> _spAuth;
HRESULT AddSocket(TransportAddressSet* pTSA, SocketRole role, const CSocketAddress& addrListen, const CSocketAddress& addrAdvertise);
public:
......
......@@ -46,7 +46,7 @@ void CStunSocketThread::ClearSocketArray()
_socks.clear();
}
HRESULT CStunSocketThread::Init(CStunSocket* arrayOfFourSockets, IStunAuth* pAuth, SocketRole rolePrimaryRecv)
HRESULT CStunSocketThread::Init(CStunSocket* arrayOfFourSockets, TransportAddressSet* pTSA, IStunAuth* pAuth, SocketRole rolePrimaryRecv)
{
HRESULT hr = S_OK;
......@@ -55,6 +55,7 @@ HRESULT CStunSocketThread::Init(CStunSocket* arrayOfFourSockets, IStunAuth* pAut
ChkIfA(_fThreadIsValid, E_UNEXPECTED);
ChkIfA(arrayOfFourSockets == NULL, E_INVALIDARG);
ChkIfA(pTSA == NULL, E_INVALIDARG);
// if this thread was configured to listen on a single socket (aka "multi-threaded mode"), then
// validate that it exists
......@@ -66,18 +67,7 @@ HRESULT CStunSocketThread::Init(CStunSocket* arrayOfFourSockets, IStunAuth* pAut
_arrSendSockets = arrayOfFourSockets;
// initialize the TSA thing
memset(&_tsa, '\0', sizeof(_tsa));
for (size_t i = 0; i < 4; i++)
{
if (_arrSendSockets[i].IsValid())
{
SocketRole role = _arrSendSockets[i].GetRole();
ASSERT(role == (SocketRole)i);
_tsa.set[role].fValid = true;
_tsa.set[role].addr = _arrSendSockets[i].GetLocalAddress();
}
}
_tsa = *pTSA;
if (fSingleSocketRecv)
{
......@@ -275,10 +265,12 @@ void CStunSocketThread::Run()
int ret;
int sendsocketcount = 0;
sendsocketcount += (int)(_tsa.set[RolePP].fValid);
sendsocketcount += (int)(_tsa.set[RolePA].fValid);
sendsocketcount += (int)(_tsa.set[RoleAP].fValid);
sendsocketcount += (int)(_tsa.set[RoleAA].fValid);
Logging::LogMsg(LL_DEBUG, "Starting listener thread (%d recv sockets, %d send sockets)", _socks.size(), sendsocketcount);
while (_fNeedToExit == false)
......
......@@ -32,7 +32,7 @@ public:
CStunSocketThread();
~CStunSocketThread();
HRESULT Init(CStunSocket* arrayOfFourSockets, IStunAuth* pAuth, SocketRole rolePrimaryRecv);
HRESULT Init(CStunSocket* arrayOfFourSockets, TransportAddressSet* pTSA, IStunAuth* pAuth, SocketRole rolePrimaryRecv);
HRESULT Start();
HRESULT SignalForStop(bool fPostMessages);
......@@ -52,20 +52,16 @@ private:
CStunSocket* _arrSendSockets; // matches CStunServer::_arrSockets
std::vector<CStunSocket*> _socks; // sockets for receiving on
bool _fNeedToExit;
pthread_t _pthread;
bool _fThreadIsValid;
int _rotation;
TransportAddressSet _tsa;
CRefCountedPtr<IStunAuth> _spAuth;
// pre-allocated objects for the thread
CStunMessageReader _reader;
CRefCountedBuffer _spBufferReader; // buffer internal to the reader
......
......@@ -243,7 +243,7 @@ HRESULT CTCPStunThread::Init(const TransportAddressSet& tsaListen, const Transpo
// Max sure we didn't accidently pass in anything crazy
ChkIfA(_maxConnections >= 100000, E_INVALIDARG);
for (size_t i = 0; i <= ARRAYSIZE(_tsa.set); i++)
for (size_t i = 0; i < ARRAYSIZE(_tsa.set); i++)
{
countListen += tsaListen.set[i].fValid ? 1 : 0;
countHandler += tsaHandler.set[i].fValid ? 1 : 0;
......@@ -825,10 +825,34 @@ CTCPServer::~CTCPServer()
}
void CTCPServer::InitTSA(TransportAddressSet* pTSA, SocketRole role, bool fValid, const CSocketAddress& addrListen, const CSocketAddress& addrAdvertise)
{
if (fValid == false)
{
pTSA->set[role].fValid = false;
pTSA->set[role].addr = CSocketAddress();
}
else
{
pTSA->set[role].fValid = true;
if (addrAdvertise.IsIPAddressZero())
{
pTSA->set[role].addr = addrListen;
}
else
{
pTSA->set[role].addr = addrAdvertise;
pTSA->set[role].addr.SetPort(addrListen.GetPort());
}
}
}
HRESULT CTCPServer::Initialize(const CStunServerConfig& config)
{
HRESULT hr = S_OK;
TransportAddressSet tsaListen;
TransportAddressSet tsaListenAll;
TransportAddressSet tsaHandler;
ChkIfA(_threads[0] != NULL, E_UNEXPECTED); // we can't already be initialized, right?
......@@ -838,39 +862,45 @@ HRESULT CTCPServer::Initialize(const CStunServerConfig& config)
// Chk(CYourAuthProvider::CreateInstanceNoInit(&_spAuth));
// tsaHandler is sort of a hack for TCP. It's really just a glorified indication to the the
// CStunRequestHandler code to figure out if can offer a CHANGED-ADDRESS attribute.
// CStunRequestHandler code to figure out if it can offer a CHANGED-ADDRESS attribute.
tsaHandler.set[RolePP].fValid = config.fHasPP;
tsaHandler.set[RolePP].addr = config.addrPP;
tsaHandler.set[RolePA].fValid = config.fHasPA;
tsaHandler.set[RolePA].addr = config.addrPA;
tsaHandler.set[RoleAP].fValid = config.fHasAP;
tsaHandler.set[RoleAP].addr = config.addrAP;
tsaHandler.set[RoleAA].fValid = config.fHasAA;
tsaHandler.set[RoleAA].addr = config.addrAA;
InitTSA(&tsaHandler, RolePP, config.fHasPP, config.addrPP, config.addrPrimaryAdvertised);
InitTSA(&tsaHandler, RolePA, config.fHasPA, config.addrPA, config.addrPrimaryAdvertised);
InitTSA(&tsaHandler, RoleAP, config.fHasAP, config.addrAP, config.addrAlternateAdvertised);
InitTSA(&tsaHandler, RoleAA, config.fHasAA, config.addrAA, config.addrAlternateAdvertised);
InitTSA(&tsaListenAll, RolePP, config.fHasPP, config.addrPP, CSocketAddress());
InitTSA(&tsaListenAll, RolePA, config.fHasPA, config.addrPA, CSocketAddress());
InitTSA(&tsaListenAll, RoleAP, config.fHasAP, config.addrAP, CSocketAddress());
InitTSA(&tsaListenAll, RoleAA, config.fHasAA, config.addrAA, CSocketAddress());
if (config.fMultiThreadedMode == false)
{
tsaListen = tsaHandler;
_threads[0] = new CTCPStunThread();
ChkA(_threads[0]->Init(tsaListen, tsaHandler, _spAuth, config.nMaxConnections));
ChkA(_threads[0]->Init(tsaListenAll, tsaHandler, _spAuth, config.nMaxConnections));
}
else
{
for (int threadindex = 0; threadindex < 4; threadindex++)
{
memset(&tsaListen, '\0', sizeof(tsaListen));
if (tsaHandler.set[threadindex].fValid)
{
tsaListen.set[threadindex] = tsaHandler.set[threadindex];
TransportAddressSet tsaListen = tsaListenAll;
// Since we already initialized tsaListenAll above,
// make a copy and uninit each one that isn't going to be managed
// by the thread we are about to create
for (int temp = 0; temp < 4; temp++)
{
if (temp != threadindex)
{
tsaListen.set[temp].fValid = false;
tsaListen.set[temp].addr = CSocketAddress();
}
}
_threads[threadindex] = new CTCPStunThread();
Chk(_threads[threadindex]->Init(tsaListen, tsaHandler, _spAuth, config.nMaxConnections));
}
......
......@@ -126,7 +126,9 @@ private:
CTCPStunThread* _threads[4];
CRefCountedPtr<IStunAuth> _spAuth;
CRefCountedPtr<IStunAuth> _spAuth;
void InitTSA(TransportAddressSet* pTSA, SocketRole role, bool fValid, const CSocketAddress& addrListen, const CSocketAddress& addrAdvertise);
public:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment