Commit 4a0cb166 authored by John Selbie's avatar John Selbie

TCP code update

parent 2b83b5e4
......@@ -4,6 +4,7 @@ nbproject/
*.gch
*.a
*.txtcode
callgrind.out.*
stunclient
stunserver
......
......@@ -20,6 +20,9 @@ copybin: everything
debug: T := debug
debug: all
profile: T := profile
profile: all
clean: T := clean
clean: everything
rm -f stunserver stunclient stuntestcode
......
StunServer version 1.0.0
September 7, 2011
StunServer version 1.1.0
January 22, 2012
---------------------------------------------------------
Features:
Compliant with the latest RFCs including 5389, 5769, and 5780. Also includes
backwards compatibility for RFC 3489.
IPv4 and IPv6 support
Supports both UDP and TCP on both IPv4 and IPv6.
Client test app provided
Client test app provided.
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
detection support for clients.
Open source Apache license. See LICENSE file fore more details.
---------------------------------------------------------
......@@ -23,8 +24,7 @@ Features:
Known issues:
UDP only. Command line options for working in TCP or TLS modes have yet to
be implemented.
TLS mode has yet to be implemented.
Server does not honor the stun padding attribute. If someone really wants
this support, let me know and I will consider adding it.
......@@ -38,7 +38,7 @@ Known issues:
hooks are provided for implementors to write their own code to validate a
username, fetch a password, and allow/deny a request. Details of writing
your own authentication provider code are described in the file
"server/sampleauthprovider.h"
"server/sampleauthprovider.h".
Dependency checking is not implemented in the Makefile. So if you need to
recompile, I recommend "make clean" from the root to preceed any subsequent
......@@ -67,16 +67,15 @@ Testing:
Prerequisites before compiling and running.
perl. Just have any old version installed. It is needed for one particular
build script.
Boost header files. (Actual boost runtime not required) www.boost.org (sudo
yum install boost-devel)
OpenSSL development files and runtime. www.boost.org (sudo yum install
openssl-devel)
/usr/bin/xxd (this is a tool for converting the help text into resources. It
is usually universally installed. If not, then "sudo yum install
vim-common")
pthreads header and libs (I haven't seen a distribution where this wasn't
already installed)
---------------------------------------------------------
......@@ -113,17 +112,18 @@ Firewall
Feature roadmap (the features I want to implement in a subsequent release)
TCP and TLS support
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
Scale across more than one CPU (for multi-core and multi-proc machines). The
threading code has already been written, just needs some finish work.
Host a full server across two separate machines (such that two ip addresses
on a single machine will not be required for full mode).
TLS support
Cleanup Makefile and add "configure" and autotools support
---------------------------------------------------------
......
......@@ -97,12 +97,14 @@ HRESULT CreateConfigFromCommandLine(ClientCmdLineArgs& args, StunClientLogicConf
uint16_t remoteport = 0;
int nPort = 0;
char szIP[100];
bool fTCP = false;
config.fBehaviorTest = false;
config.fFilteringTest = false;
config.timeoutSeconds = 5;
config.uMaxAttempts = 3;
config.fTimeoutIsInstant = false;
config.timeoutSeconds = 0; // use default
config.uMaxAttempts = 0;
socketconfig.family = AF_INET;
socketconfig.socktype = SOCK_DGRAM;
......@@ -132,11 +134,18 @@ HRESULT CreateConfigFromCommandLine(ClientCmdLineArgs& args, StunClientLogicConf
StringHelper::ToLower(args.strProtocol);
if (StringHelper::IsNullOrEmpty(args.strProtocol.c_str()) == false)
{
if (args.strProtocol != "udp")
if ((args.strProtocol != "udp") && (args.strProtocol != "tcp"))
{
Logging::LogMsg(LL_ALWAYS, "Only udp is supported as a protocol option in this version");
Logging::LogMsg(LL_ALWAYS, "Only udp and tcp are supported protocol versions");
Chk(E_INVALIDARG);
}
if (args.strProtocol == "tcp")
{
fTCP = true;
socketconfig.socktype = SOCK_STREAM;
config.uMaxAttempts = 1;
}
}
// remote port ---------------------------------------------
......@@ -224,7 +233,7 @@ HRESULT CreateConfigFromCommandLine(ClientCmdLineArgs& args, StunClientLogicConf
else if (args.strMode == "full")
{
config.fBehaviorTest = true;
config.fFilteringTest = true;
config.fFilteringTest = (fTCP == false); // impossible to to a filtering test in TCP
}
else
{
......@@ -241,7 +250,6 @@ Cleanup:
void NatBehaviorToString(NatBehavior behavior, std::string* pStr)
{
std::string& str = *pStr;
......@@ -308,13 +316,161 @@ void DumpResults(StunClientLogicConfig& config, StunClientResults& results)
Logging::LogMsg(LL_ALWAYS, "Nat filtering: %s", strResult.c_str());
}
}
}
void TcpClientLoop(StunClientLogicConfig& config, ClientSocketConfig& socketconfig)
{
HRESULT hr = S_OK;
CStunSocket stunsocket;
CStunClientLogic clientlogic;
int sock;
CRefCountedBuffer spMsg(new CBuffer(1500));
CRefCountedBuffer spMsgReader(new CBuffer(1500));
CSocketAddress addrDest, addrLocal;
HRESULT hrRet, hrResult;
int ret;
size_t bytes_sent, bytes_recv;
size_t bytes_to_send, max_bytes_recv, remaining;
uint8_t* pData=NULL;
size_t readsize;
CStunMessageReader reader;
StunClientResults results;
hr= clientlogic.Initialize(config);
if (FAILED(hr))
{
Logging::LogMsg(LL_ALWAYS, "clientlogic.Initialize failed (hr == %x)", hr);
Chk(hr);
}
while (true)
{
stunsocket.Close();
hr = stunsocket.TCPInit(socketconfig.addrLocal, RolePP, true);
if (FAILED(hr))
{
Logging::LogMsg(LL_ALWAYS, "Unable to create local socket for TCP connection (hr == %x)", hr);
Chk(hr);
}
hrRet = clientlogic.GetNextMessage(spMsg, &addrDest, ::GetMillisecondCounter());
if (hrRet == E_STUNCLIENT_RESULTS_READY)
{
// clean exit
break;
}
// we should never get a "still waiting" return with TCP, because config.timeout is 0
ASSERT(hrRet != E_STUNCLIENT_STILL_WAITING);
if (FAILED(hrRet))
{
Chk(hrRet);
}
// connect to server
sock = stunsocket.GetSocketHandle();
ret = ::connect(sock, addrDest.GetSockAddr(), addrDest.GetSockAddrLength());
if (ret == -1)
{
hrResult = ERRNOHR;
Logging::LogMsg(LL_ALWAYS, "Can't connect to server (hr == %x)", hrResult);
Chk(hrResult);
}
Logging::LogMsg(LL_DEBUG, "Connected to server");
bytes_to_send = (int)(spMsg->GetSize());
bytes_sent = 0;
pData = spMsg->GetData();
while (bytes_sent < bytes_to_send)
{
ret = ::send(sock, pData+bytes_sent, bytes_to_send-bytes_sent, 0);
if (ret < 0)
{
hrResult = ERRNOHR;
Logging::LogMsg(LL_ALWAYS, "Send failed (hr == %x)", hrResult);
Chk(hrResult);
}
bytes_sent += ret;
}
Logging::LogMsg(LL_DEBUG, "Request sent - waiting for response");
// consume the response
reader.Reset();
reader.GetStream().Attach(spMsgReader, true);
pData = spMsg->GetData();
bytes_recv = 0;
max_bytes_recv = spMsg->GetAllocatedSize();
remaining = max_bytes_recv;
while (remaining > 0)
{
readsize = reader.HowManyBytesNeeded();
if (readsize == 0)
{
break;
}
if (readsize > remaining)
{
// technically an error, but the client logic will figure it out
ASSERT(false);
break;
}
ret = ::recv(sock, pData+bytes_recv, readsize, 0);
if (ret == 0)
{
// server cut us off before we got all the bytes we thought we were supposed to get?
ASSERT(false);
break;
}
if (ret < 0)
{
hrResult = ERRNOHR;
Logging::LogMsg(LL_ALWAYS, "Recv failed (hr == %x)", hrResult);
Chk(hrResult);
}
reader.AddBytes(pData+bytes_recv, ret);
bytes_recv += ret;
remaining = max_bytes_recv - bytes_recv;
spMsg->SetSize(bytes_recv);
}
// now feed the response into the client logic
stunsocket.UpdateAddresses();
addrLocal = stunsocket.GetLocalAddress();
clientlogic.ProcessResponse(spMsg, addrDest, addrLocal);
}
stunsocket.Close();
HRESULT ClientLoop(StunClientLogicConfig& config, const ClientSocketConfig& socketconfig)
results.Init();
clientlogic.GetResults(&results);
::DumpResults(config, results);
Cleanup:
return;
}
HRESULT UdpClientLoop(StunClientLogicConfig& config, const ClientSocketConfig& socketconfig)
{
HRESULT hr = S_OK;
CRefCountedStunSocket spStunSocket;
......@@ -431,6 +587,11 @@ Cleanup:
}
int main(int argc, char** argv)
{
CCmdLineParser cmdline;
......@@ -495,7 +656,15 @@ int main(int argc, char** argv)
}
DumpConfig(config, socketconfig);
ClientLoop(config, socketconfig);
if (socketconfig.socktype == SOCK_STREAM)
{
TcpClientLoop(config, socketconfig);
}
else
{
UdpClientLoop(config, socketconfig);
}
return 0;
}
......@@ -4,30 +4,30 @@ Perform a binding test with a remote STUN server and optionally perform a full b
Parameters:
"server" is the IP address or FQDN of the remote server to befrom the binding tests with. It is the only required paramter
"port" is an optional paramter that can follow the server paramter. The default is 3478 for UDP and TCP. And 5349 for TLS.
"port" is an optional paramter that can follow the server paramter. The default is 3478 for UDP and TCP.
Available options:
--localaddr = INTERFACE OR IPADDRESS
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 on all addresses (INADDR_ANY).
--localaddr = INTERFACE OR IPADDRESS
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 on all addresses (INADDR_ANY).
--localport=PORTNUM
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. If not specified, a randomly avaialbe port chosed by the system is used.
--localport=PORTNUM
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. If not specified, a randomly avaialbe port chosed by the system is used.
--mode=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.
--mode=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.
--family=IPVERSION
IPVERSION is either "4" or "6" to specify the usage of IPV4 or IPV6. If not specified, the default value is "4".
--family=IPVERSION
IPVERSION is either "4" or "6" to specify the usage of IPV4 or IPV6. If not specified, the default value is "4".
--protocol=PROTO
PROTO is either "udp", "tcp", or "tls". Where "udp" is the default. "tcp" and "tls" modes are only available when the --mode option is "basic".
PROTO is either "udp" or "tcp". "udp" is the default if this parameter is not specified
--verbosity=LOGLEVEL
Sets the verbosity of the logging level. 0 is the default (minimal output and logging). 1 shows slightly more. 2 and higher shows even more.
Sets the verbosity of the logging level. 0 is the default (minimal output and logging). 1 shows slightly more. 2 and higher shows even more.
--help
Prints this help page
Prints this help page
Examples:
......@@ -37,4 +37,8 @@ stunclient stunserver.org 3478
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)
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
BOOST_INCLUDE := -I/home/jselbie/boost_1_48_0
# BOOST_INCLUDE := -I/home/jselbie/boost_1_48_0
# OPENSSL_INCLUDE := -I/home/jselbie/lib/openssl
DEFINES := -DNDEBUG
......@@ -7,6 +7,7 @@ STANDARD_FLAGS := -Wall -Wuninitialized
RELEASE_FLAGS := -O2
DEBUG_FLAGS := -g
PROFILE_FLAGS := -O2 -g
FLAVOR_FLAGS = $(RELEASE_FLAGS)
.PHONY: all clean debug
......@@ -26,5 +27,7 @@ debug: DEFINES = -DDEBUG
debug: all
profile: FLAVOR_FLAGS = $(PROFILE_FLAGS)
profile: all
......@@ -19,6 +19,11 @@
#define STUNSERVER_COMMON_COMMONINCLUDES_H
#if __linux || __linux__ || __gnu_linux__ || linux
#define IS_LINUX
#endif
// standard system includes
#include <sys/types.h>
#include <sys/socket.h>
......@@ -48,10 +53,14 @@
#include <list>
#include <string>
#ifndef _bsd
#ifdef IS_LINUX
#define HAS_EPOLL
#include <sys/epoll.h>
#endif
#include <poll.h>
#include <pthread.h>
......
......@@ -257,6 +257,16 @@ public:
return _size;
}
size_t GetMaxCapacity()
{
return _fsize;
}
size_t GetTableWidth()
{
return _tsize;
}
int Insert(const K& key, V& value)
{
size_t hashindex = FastHash_Hash(key) % _tsize;
......
include ../common.inc
PROJECT_TARGET := libnetworkutils.a
PROJECT_OBJS := adapters.o recvfromex.o resolvehostname.o stunsocket.o
PROJECT_OBJS := adapters.o polling.o recvfromex.o resolvehostname.o stunsocket.o
INCLUDES := $(BOOST_INCLUDE) -I../common -I../stuncore
......
This diff is collapsed.
/*
* File: polling.h
* Author: jselbie
*
* Created on January 12, 2012, 5:58 PM
*/
#ifndef POLLING_H
#define POLLING_H
struct PollEvent
{
int fd;
uint32_t eventflags;
};
// event flags
const uint32_t IPOLLING_READ = 0x01 << 0;
const uint32_t IPOLLING_WRITE = 0x01 << 1;
const uint32_t IPOLLING_EDGETRIGGER = 0x01 << 2;
const uint32_t IPOLLING_RDHUP = 0x01 << 3;
const uint32_t IPOLLING_HUP = 0x01 << 4;
const uint32_t IPOLLING_PRI = 0x01 << 5;
const uint32_t IPOLLING_ERROR = 0x01 << 6;
class IPolling : public IRefCounted
{
public:
virtual HRESULT Initialize() = 0;
virtual HRESULT Close() = 0;
virtual HRESULT Add(int fd, uint32_t eventflags) = 0;
virtual HRESULT Remove(int fd) = 0;
virtual HRESULT ChangeEventSet(int fd, uint32_t eventflags) = 0;
virtual HRESULT WaitForNextEvent(PollEvent* pPollEvent, int timeoutMilliseconds) = 0;
};
const uint32_t IPOLLING_TYPE_BEST = 0x01 << 0;
const uint32_t IPOLLING_TYPE_EPOLL = 0x01 << 1;
const uint32_t IPOLLING_TYPE_POLL = 0x01 << 2;
HRESULT CreatePollingInstance(uint32_t type, IPolling** ppPolling);
#endif /* POLLING_H */
......@@ -185,7 +185,7 @@ void CStunSocket::UpdateAddresses()
HRESULT CStunSocket::InitCommon(int socktype, const CSocketAddress& addrlocal, SocketRole role)
HRESULT CStunSocket::InitCommon(int socktype, const CSocketAddress& addrlocal, SocketRole role, bool fSetReuseFlag)
{
int sock = -1;
int ret;
......@@ -196,10 +196,15 @@ HRESULT CStunSocket::InitCommon(int socktype, const CSocketAddress& addrlocal, S
sock = socket(addrlocal.GetFamily(), socktype, 0);
ChkIf(sock < 0, ERRNOHR);
if (fSetReuseFlag)
{
int fAllow = 1;
ret = ::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &fAllow, sizeof(fAllow));
ChkIf(ret == -1, ERRNOHR);
}
ret = bind(sock, addrlocal.GetSockAddr(), addrlocal.GetSockAddrLength());
ChkIf(ret < 0, ERRNOHR);
ChkIf(ret == -1, ERRNOHR);
Attach(sock);
sock = -1;
......@@ -219,12 +224,12 @@ Cleanup:
HRESULT CStunSocket::UDPInit(const CSocketAddress& local, SocketRole role)
{
return InitCommon(SOCK_DGRAM, local, role);
return InitCommon(SOCK_DGRAM, local, role, false);
}
HRESULT CStunSocket::TCPInit(const CSocketAddress& local, SocketRole role)
HRESULT CStunSocket::TCPInit(const CSocketAddress& local, SocketRole role, bool fSetReuseFlag)
{
return InitCommon(SOCK_STREAM, local, role);
return InitCommon(SOCK_STREAM, local, role, fSetReuseFlag);
}
......@@ -30,7 +30,7 @@ private:
CStunSocket(const CStunSocket&) {;}
void operator=(const CStunSocket&) {;}
HRESULT InitCommon(int socktype, const CSocketAddress& addrlocal, SocketRole role);
HRESULT InitCommon(int socktype, const CSocketAddress& addrlocal, SocketRole role, bool fSetReuseFlag);
void Reset();
......@@ -59,7 +59,7 @@ public:
void UpdateAddresses();
HRESULT UDPInit(const CSocketAddress& local, SocketRole role);
HRESULT TCPInit(const CSocketAddress& local, SocketRole role);
HRESULT TCPInit(const CSocketAddress& local, SocketRole role, bool fSetReuseFlag);
};
typedef boost::shared_ptr<CStunSocket> CRefCountedStunSocket;
......
......@@ -97,6 +97,7 @@ struct StartupArgs
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>");
......@@ -113,6 +114,7 @@ void DumpStartupArgs(StartupArgs& args)
PRINTARG(strProtocol);
PRINTARG(strHelp);
PRINTARG(strVerbosity);
PRINTARG(strMaxConnections);
Logging::LogMsg(LL_DEBUG, "--------------------------\n");
}
......@@ -145,7 +147,10 @@ void DumpConfig(CStunServerConfig &config)
}
Logging::LogMsg(LL_DEBUG, "Protocol = %s", config.fTCP ? "TCP" : "UDP");
if (config.fTCP && (config.nMaxConnections>0))
{
Logging::LogMsg(LL_DEBUG, "Max TCP Connections per thread: %d", config.nMaxConnections);
}
}
......@@ -189,6 +194,7 @@ HRESULT BuildServerConfigurationFromArgs(StartupArgs& argsIn, CStunServerConfig*
int nAltPort = DEFAULT_STUN_PORT + 1;
bool fHasAtLeastTwoAdapters = false;
CStunServerConfig config;
int nMaxConnections = 0;
enum ServerMode
{
......@@ -272,6 +278,28 @@ HRESULT BuildServerConfigurationFromArgs(StartupArgs& argsIn, CStunServerConfig*
config.fTCP = (args.strProtocol == "tcp");
}
// ---- MAX Connections -----------------------------------------------------
nMaxConnections = 0;
if (args.strMaxConnections.length() > 0)
{
if (config.fTCP == false)
{
Logging::LogMsg(LL_ALWAYS, "Max connections parameter has no meaning in UDP mode. Did you mean to specify \"--protocol=tcp ?\"");
}
else
{
hr = StringHelper::ValidateNumberString(args.strMaxConnections.c_str(), 1, 100000, &nMaxConnections);
if (FAILED(hr))
{
Logging::LogMsg(LL_ALWAYS, "Max connections must be between 1-100000");
Chk(hr);
}
}
config.nMaxConnections = nMaxConnections;
}
// ---- PRIMARY PORT --------------------------------------------------------
nPrimaryPort = DEFAULT_STUN_PORT;
......@@ -376,6 +404,7 @@ HRESULT BuildServerConfigurationFromArgs(StartupArgs& argsIn, CStunServerConfig*
Logging::LogMsg(LL_ALWAYS, "Error - Primary interface and Alternate Interface appear to have the same IP address. Full mode requires two IP addresses that are unique");
Chk(E_INVALIDARG);
}
config.addrPP = addrPrimary;
config.addrPP.SetPort(portPrimary);
......@@ -392,7 +421,6 @@ HRESULT BuildServerConfigurationFromArgs(StartupArgs& argsIn, CStunServerConfig*
config.addrAA = addrAlternate;
config.addrAA.SetPort(portAlternate);
config.fHasAA = true;
}
......@@ -417,6 +445,7 @@ HRESULT ParseCommandLineArgs(int argc, char** argv, int startindex, StartupArgs*
cmdline.AddOption("altport", required_argument, &pStartupArgs->strAltPort);
cmdline.AddOption("family", required_argument, &pStartupArgs->strFamily);
cmdline.AddOption("protocol", required_argument, &pStartupArgs->strProtocol);
cmdline.AddOption("maxconn", required_argument, &pStartupArgs->strMaxConnections);
cmdline.AddOption("help", no_argument, &pStartupArgs->strHelp);
cmdline.AddOption("verbosity", required_argument, &pStartupArgs->strVerbosity);
......
......@@ -124,7 +124,7 @@ as appropriate:
To have the server host an instance of an IStunAuth implementation, modify
CStunServer::Initialize to create an instance of your class and initialize
CStunServer::Initialize and CTCPServer::Initialize to create an instance of your class and initialize
_spAuth as appropriate.
#endif
......@@ -138,6 +138,7 @@ class CShortTermAuth :
{
public:
virtual HRESULT DoAuthCheck(AuthAttributes* pAuthAttributes, AuthResponse* pResponse);
ADDREF_AND_RELEASE_IMPL();
};
......@@ -154,6 +155,7 @@ private:
public:
virtual HRESULT DoAuthCheck(AuthAttributes* pAuthAttributes, AuthResponse* pResponse);
ADDREF_AND_RELEASE_IMPL();
};
......
......@@ -30,7 +30,8 @@ fHasPA(false),
fHasAP(false),
fHasAA(false),
fMultiThreadedMode(false),
fTCP(false)
fTCP(false),
nMaxConnections(0) // zero means default
{
;
}
......
......@@ -28,6 +28,7 @@
class CStunServerConfig
{
public:
bool fHasPP; // PP: Primary ip, Primary port
bool fHasPA; // PA: Primary ip, Alternate port
bool fHasAP; // AP: Alternate ip, Primary port
......@@ -36,6 +37,7 @@ public:
bool fMultiThreadedMode; // if true, one thread for each socket
bool fTCP; // if true, then use TCP instead of UDP
uint32_t nMaxConnections; // only valid for TCP (on a per-thread basis)
CSocketAddress addrPP; // address for PP
CSocketAddress addrPA; // address for PA
......
This diff is collapsed.
......@@ -24,7 +24,7 @@
#include "fasthash.h"
#include "messagehandler.h"
#include "stunconnection.h"
#include "polling.h"
......@@ -37,17 +37,11 @@ class CTCPStunThread
HRESULT CreatePipes();
HRESULT NotifyThreadViaPipe();
void ClosePipes();
int _epoll;
CRefCountedPtr<IPolling> _spPolling;
bool _fListenSocketsOnEpoll;
HRESULT CreateEpoll();
void CloseEpoll();
// epoll helpers
HRESULT AddSocketToEpoll(int sock, uint32_t events);
HRESULT AddClientSocketToEpoll(int sock);
HRESULT DetachFromEpoll(int sock);
HRESULT EpollCtrl(int sock, uint32_t events);
HRESULT SetListenSocketsOnEpoll(bool fEnable);
TransportAddressSet _tsaListen; // this is not what gets passed to CStunRequestHandler, see _tsa below
......@@ -131,7 +125,8 @@ class CTCPServer :
private:
CTCPStunThread* _threads[4];
CRefCountedPtr<IStunAuth> _spAuth;
public:
......
......@@ -21,13 +21,16 @@ Available options:
--family=IPVERSION
IPVERSION is either "4" or "6" to specify the usage of IPV4 or IPV6. If not specified, the default value is "4".
--protocol=PROTO
PROTO is either "udp", "tcp", or "tls". Where "udp" is the default. "tcp" and "tls" modes are only available when the --mode option is "basic". (Note: tcp and tls are not yet available in this version)
--protocol=PROTO
PROTO is either "udp" or "tcp". "udp" is the default.
--verbosity=LOGLEVEL
--maxconn=MAXCONN
MAXCONN is a value between 1 and 100000. The default is 1000. This value specifies the maximum number of simultaneous TCP connections allowed (per thread). It's an ignored parameter when the PROTOCOL option is UDP.
--verbosity=LOGLEVEL
Sets the verbosity of the logging level. 0 is the default (minimal output and logging). 1 shows slightly more. 2 and higher shows even more.
--help
--help
Prints this help page
Examples:
......
......@@ -51,7 +51,7 @@ public:
HRESULT InitWithAllocAndCopy(uint8_t* pByteArray, size_t nByteArraySize);
HRESULT InitNoAlloc(uint8_t* pByteArray, size_t nByteArraySize);
size_t GetSize() {return _size;}
inline size_t GetSize() {return _size;}
inline size_t GetAllocatedSize() {return _allocatedSize;}
HRESULT SetSize(size_t size);
......
......@@ -83,15 +83,20 @@ HRESULT CStunClientLogic::Initialize(StunClientLogicConfig& config)
_fInitialized = true;
if (config.timeoutSeconds == 0)
if (_config.fTimeoutIsInstant)
{
_config.timeoutSeconds = 0;
}
else if (_config.timeoutSeconds == 0)
{
config.timeoutSeconds = 5;
_config.timeoutSeconds = 3; // default to waiting for 3 seconds
}
if (config.uMaxAttempts <= 0)
if (_config.uMaxAttempts <= 0)
{
config.uMaxAttempts = 2;
_config.uMaxAttempts = 2;
}
_nTestIndex = 0;
......@@ -183,7 +188,7 @@ HRESULT CStunClientLogic::GetNextMessage(CRefCountedBuffer& spMsg, CSocketAddres
break;
}
// have we exceed the retry count
// have we exceeded the retry count
if (_sendCount >= _config.uMaxAttempts)
{
// notify the test that it has timed out
......
......@@ -21,10 +21,14 @@
#include "stunclienttests.h"
struct StunClientLogicConfig
{
CSocketAddress addrServer;
uint32_t timeoutSeconds;
bool fTimeoutIsInstant; // if true, then timeoutSeconds is ignored and assumed to be zero
uint32_t timeoutSeconds; // if fTimeoutIsInstant is false, then "0" implies to use the default
uint32_t uMaxAttempts;
bool fBehaviorTest;
......
......@@ -75,8 +75,8 @@ uint16_t CStunMessageReader::HowManyBytesNeeded()
BOOST_ASSERT(STUN_HEADER_SIZE > currentSize);
return STUN_HEADER_SIZE - currentSize;
case HeaderValidated:
BOOST_ASSERT(_msgLength > currentSize);
return _msgLength - currentSize;
BOOST_ASSERT((_msgLength+STUN_HEADER_SIZE) > currentSize);
return (_msgLength+STUN_HEADER_SIZE) - currentSize;
default:
return 0;
}
......
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