Stun Server  Compliant with the latest RFCs including 5389, 5769, and 5780
discover the local host's own external IP address
clientmain.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2011 John Selbie
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 
18 
19 #include "commonincludes.hpp"
20 #include "stuncore.h"
21 #include "socketrole.h" // so we can re-use the "SocketRole" definitions again
22 #include "stunsocket.h"
23 #include "cmdlineparser.h"
24 #include "recvfromex.h"
25 #include "resolvehostname.h"
26 #include "stringhelper.h"
27 #include "adapters.h"
28 #include "oshelper.h"
29 #include "prettyprint.h"
30 
31 // These files are in ../resources
32 #include "stunclient.txtcode"
33 #include "stunclient_lite.txtcode"
34 
35 
37 {
38  std::string strRemoteServer;
39  std::string strRemotePort;
40  std::string strLocalAddr;
41  std::string strLocalPort;
42  std::string strMode;
43  std::string strFamily;
44  std::string strProtocol;
45  std::string strVerbosity;
46  std::string strHelp;
47 };
48 
50 {
51  int family;
52  int socktype;
54 };
55 
57 {
58  std::string strAddr;
59 
60 
61  Logging::LogMsg(LL_DEBUG, "config.fBehaviorTest = %s", config.fBehaviorTest?"true":"false");
62  Logging::LogMsg(LL_DEBUG, "config.fFilteringTest = %s", config.fFilteringTest?"true":"false");
63  Logging::LogMsg(LL_DEBUG, "config.timeoutSeconds = %d", config.timeoutSeconds);
64  Logging::LogMsg(LL_DEBUG, "config.uMaxAttempts = %d", config.uMaxAttempts);
65 
66  config.addrServer.ToString(&strAddr);
67  Logging::LogMsg(LL_DEBUG, "config.addrServer = %s", strAddr.c_str());
68 
69  socketConfig.addrLocal.ToString(&strAddr);
70  Logging::LogMsg(LL_DEBUG, "socketconfig.addrLocal = %s", strAddr.c_str());
71 
72 }
73 
74 void PrintUsage(bool fSummaryUsage)
75 {
76  size_t width = GetConsoleWidth();
77  const char* psz = fSummaryUsage ? stunclient_lite_text : stunclient_text;
78 
79  // save some margin space
80  if (width > 2)
81  {
82  width -= 2;
83  }
84 
85  PrettyPrint(psz, width);
86 }
87 
88 
89 
91 {
92  HRESULT hr = S_OK;
93  StunClientLogicConfig& config = *pConfig;
94  ClientSocketConfig& socketconfig = *pSocketConfig;
95  int ret;
96  uint16_t localport = 0;
97  uint16_t remoteport = 0;
98  int nPort = 0;
99  char szIP[100];
100  bool fTCP = false;
101 
102 
103  config.fBehaviorTest = false;
104  config.fFilteringTest = false;
105  config.fTimeoutIsInstant = false;
106  config.timeoutSeconds = 0; // use default
107  config.uMaxAttempts = 0;
108 
109  socketconfig.family = AF_INET;
110  socketconfig.socktype = SOCK_DGRAM;
111  socketconfig.addrLocal = CSocketAddress(0, 0);
112 
113  ChkIfA(pConfig == NULL, E_INVALIDARG);
114  ChkIfA(pSocketConfig==NULL, E_INVALIDARG);
115 
116 
117  // family (protocol type) ------------------------------------
118  if (StringHelper::IsNullOrEmpty(args.strFamily.c_str())==false)
119  {
120  int optvalue = atoi(args.strFamily.c_str());
121  switch (optvalue)
122  {
123  case 4: socketconfig.family = AF_INET; break;
124  case 6: socketconfig.family = AF_INET6; break;
125  default:
126  {
127  Logging::LogMsg(LL_ALWAYS, "Family option must be either 4 or 6");
128  Chk(E_INVALIDARG);
129  }
130  }
131  }
132 
133  // protocol --------------------------------------------
135  if (StringHelper::IsNullOrEmpty(args.strProtocol.c_str()) == false)
136  {
137  if ((args.strProtocol != "udp") && (args.strProtocol != "tcp"))
138  {
139  Logging::LogMsg(LL_ALWAYS, "Only udp and tcp are supported protocol versions");
140  Chk(E_INVALIDARG);
141  }
142 
143  if (args.strProtocol == "tcp")
144  {
145  fTCP = true;
146  socketconfig.socktype = SOCK_STREAM;
147  config.uMaxAttempts = 1;
148  }
149  }
150 
151  // remote port ---------------------------------------------
152  if (StringHelper::IsNullOrEmpty(args.strRemotePort.c_str()) == false)
153  {
154  ret = StringHelper::ValidateNumberString(args.strRemotePort.c_str(), 1, 0xffff, &nPort);
155  if (ret < 0)
156  {
157  Logging::LogMsg(LL_ALWAYS, "Remote port must be between 1 - 65535");
158  Chk(E_INVALIDARG);
159  }
160  remoteport = (uint16_t)(unsigned int)nPort;
161  }
162  else
163  {
164  remoteport = DEFAULT_STUN_PORT;
165  }
166 
167 
168  // remote server -----------------------------------------
170  {
171  Logging::LogMsg(LL_ALWAYS, "No server address specified");
172  Chk(E_INVALIDARG);
173  }
174 
175  hr = ::ResolveHostName(args.strRemoteServer.c_str(), socketconfig.family, false, &config.addrServer);
176 
177  if (FAILED(hr))
178  {
179  Logging::LogMsg(LL_ALWAYS, "Unable to resolve hostname for %s", args.strRemoteServer.c_str());
180  Chk(hr);
181  }
182 
183  config.addrServer.ToStringBuffer(szIP, ARRAYSIZE(szIP));
184  Logging::LogMsg(LL_DEBUG, "Resolved %s to %s", args.strRemoteServer.c_str(), szIP);
185  config.addrServer.SetPort(remoteport);
186 
187 
188  // local port --------------------------------------------
189  if (StringHelper::IsNullOrEmpty(args.strLocalPort.c_str()) == false)
190  {
191  ret = StringHelper::ValidateNumberString(args.strLocalPort.c_str(), 1, 0xffff, &nPort);
192  if (ret < 0)
193  {
194  Logging::LogMsg(LL_ALWAYS, "Local port must be between 1 - 65535");
195  Chk(E_INVALIDARG);
196  }
197  localport = (uint16_t)(unsigned int)nPort;
198  }
199 
200  // local address ------------------------------------------
201  if (StringHelper::IsNullOrEmpty(args.strLocalAddr.c_str()) == false)
202  {
203  hr = GetSocketAddressForAdapter(socketconfig.family, args.strLocalAddr.c_str(), localport, &socketconfig.addrLocal);
204  if (FAILED(hr))
205  {
206  Logging::LogMsg(LL_ALWAYS, "Unable to find matching adapter or interface for local address option");
207  Chk(hr);
208  }
209  }
210  else
211  {
212  if (socketconfig.family == AF_INET6)
213  {
214  sockaddr_in6 addr6 = {};
215  addr6.sin6_family = AF_INET6;
216  socketconfig.addrLocal = CSocketAddress(addr6);
217  socketconfig.addrLocal.SetPort(localport);
218  }
219  else
220  {
221  socketconfig.addrLocal = CSocketAddress(0,localport);
222  }
223  }
224 
225  // mode ---------------------------------------------
227  if (StringHelper::IsNullOrEmpty(args.strMode.c_str()) == false)
228  {
229  if (args.strMode == "basic")
230  {
231  ;
232  }
233  else if (args.strMode == "full")
234  {
235  config.fBehaviorTest = true;
236  config.fFilteringTest = (fTCP == false); // impossible to to a filtering test in TCP
237  }
238  else if (args.strMode == "behavior")
239  {
240  config.fBehaviorTest = true;
241  }
242  else if (args.strMode == "filtering")
243  {
244  config.fFilteringTest = true;
245  }
246  else
247  {
248  Logging::LogMsg(LL_ALWAYS, "Mode option must be 'full', 'basic', 'behavior', or 'filtering'");
249  }
250  }
251 
252 
253 
254 Cleanup:
255  return hr;
256 }
257 
258 
259 
260 
261 void NatBehaviorToString(NatBehavior behavior, std::string* pStr)
262 {
263  std::string& str = *pStr;
264 
265  switch (behavior)
266  {
267  case UnknownBehavior: str="Unknown Behavior"; break;
268  case DirectMapping: str="Direct Mapping"; break;
269  case EndpointIndependentMapping: str = "Endpoint Independent Mapping"; break;
270  case AddressDependentMapping: str = "Address Dependent Mapping"; break;
271  case AddressAndPortDependentMapping: str = "Address and Port Dependent Mapping"; break;
272  default: ASSERT(false); str = ""; break;
273  }
274 }
275 
276 void NatFilteringToString(NatFiltering filtering, std::string* pStr)
277 {
278  std::string& str = *pStr;
279 
280  switch (filtering)
281  {
282  case UnknownFiltering: str="Unknown Behavior"; break;
283  case DirectConnectionFiltering: str="Direct Mapping"; break;
284  case EndpointIndependentFiltering: str = "Endpoint Independent Filtering"; break;
285  case AddressDependentFiltering: str = "Address Dependent Filtering"; break;
286  case AddressAndPortDependentFiltering: str = "Address and Port Dependent Filtering"; break;
287  default: ASSERT(false); str = ""; break;
288  }
289 }
290 
292 {
293  char szBuffer[100];
294  const int buffersize = 100;
295  std::string strResult;
296 
297  Logging::LogMsg(LL_ALWAYS, "Binding test: %s", results.fBindingTestSuccess?"success":"fail");
298  if (results.fBindingTestSuccess)
299  {
300  results.addrLocal.ToStringBuffer(szBuffer, buffersize);
301  Logging::LogMsg(LL_ALWAYS, "Local address: %s", szBuffer);
302 
303  results.addrMapped.ToStringBuffer(szBuffer, buffersize);
304  Logging::LogMsg(LL_ALWAYS, "Mapped address: %s", szBuffer);
305  }
306 
307  if (config.fBehaviorTest)
308  {
309 
310  Logging::LogMsg(LL_ALWAYS, "Behavior test: %s", results.fBehaviorTestSuccess?"success":"fail");
311  if (results.fBehaviorTestSuccess)
312  {
313  NatBehaviorToString(results.behavior, &strResult);
314  Logging::LogMsg(LL_ALWAYS, "Nat behavior: %s", strResult.c_str());
315  }
316  }
317 
318  if (config.fFilteringTest)
319  {
320  Logging::LogMsg(LL_ALWAYS, "Filtering test: %s", results.fFilteringTestSuccess?"success":"fail");
321  if (results.fFilteringTestSuccess)
322  {
323  NatFilteringToString(results.filtering, &strResult);
324  Logging::LogMsg(LL_ALWAYS, "Nat filtering: %s", strResult.c_str());
325  }
326  }
327 }
328 
329 
331 {
332 
333  HRESULT hr = S_OK;
334  CStunSocket stunsocket;
335  CStunClientLogic clientlogic;
336  int sock;
337  CRefCountedBuffer spMsg(new CBuffer(1500));
338  CRefCountedBuffer spMsgReader(new CBuffer(1500));
339  CSocketAddress addrDest, addrLocal;
340  HRESULT hrRet, hrResult;
341  int ret;
342  size_t bytes_sent, bytes_recv;
343  size_t bytes_to_send, max_bytes_recv, remaining;
344  uint8_t* pData=NULL;
345  size_t readsize;
346  CStunMessageReader reader;
347  StunClientResults results;
348 
349 
350  hr= clientlogic.Initialize(config);
351  if (FAILED(hr))
352  {
353  Logging::LogMsg(LL_ALWAYS, "clientlogic.Initialize failed (hr == %x)", hr);
354  Chk(hr);
355  }
356 
357 
358  while (true)
359  {
360 
361  stunsocket.Close();
362  hr = stunsocket.TCPInit(socketconfig.addrLocal, RolePP, true);
363  if (FAILED(hr))
364  {
365  Logging::LogMsg(LL_ALWAYS, "Unable to create local socket for TCP connection (hr == %x)", hr);
366  Chk(hr);
367  }
368 
369  hrRet = clientlogic.GetNextMessage(spMsg, &addrDest, ::GetMillisecondCounter());
370 
371  if (hrRet == E_STUNCLIENT_RESULTS_READY)
372  {
373  // clean exit
374  break;
375  }
376 
377  // we should never get a "still waiting" return with TCP, because config.timeout is 0
379 
380  if (FAILED(hrRet))
381  {
382  Chk(hrRet);
383  }
384 
385  // connect to server
386  sock = stunsocket.GetSocketHandle();
387 
388  ret = ::connect(sock, addrDest.GetSockAddr(), addrDest.GetSockAddrLength());
389 
390  if (ret == -1)
391  {
392  hrResult = ERRNOHR;
393  Logging::LogMsg(LL_ALWAYS, "Can't connect to server (hr == %x)", hrResult);
394  Chk(hrResult);
395  }
396 
397  Logging::LogMsg(LL_DEBUG, "Connected to server");
398 
399  bytes_to_send = (int)(spMsg->GetSize());
400 
401  bytes_sent = 0;
402  pData = spMsg->GetData();
403  while (bytes_sent < bytes_to_send)
404  {
405  ret = ::send(sock, pData+bytes_sent, bytes_to_send-bytes_sent, 0);
406  if (ret < 0)
407  {
408  hrResult = ERRNOHR;
409  Logging::LogMsg(LL_ALWAYS, "Send failed (hr == %x)", hrResult);
410  Chk(hrResult);
411  }
412  bytes_sent += ret;
413  }
414 
415  Logging::LogMsg(LL_DEBUG, "Request sent - waiting for response");
416 
417 
418  // consume the response
419  reader.Reset();
420  reader.GetStream().Attach(spMsgReader, true);
421  pData = spMsg->GetData();
422  bytes_recv = 0;
423  max_bytes_recv = spMsg->GetAllocatedSize();
424  remaining = max_bytes_recv;
425 
426  while (remaining > 0)
427  {
428  readsize = reader.HowManyBytesNeeded();
429 
430  if (readsize == 0)
431  {
432  break;
433  }
434 
435  if (readsize > remaining)
436  {
437  // technically an error, but the client logic will figure it out
438  ASSERT(false);
439  break;
440  }
441 
442  ret = ::recv(sock, pData+bytes_recv, readsize, 0);
443  if (ret == 0)
444  {
445  // server cut us off before we got all the bytes we thought we were supposed to get?
446  ASSERT(false);
447  Logging::LogMsg(LL_ALWAYS, "Lost connection");
448  break;
449  }
450  if (ret < 0)
451  {
452  hrResult = ERRNOHR;
453  Logging::LogMsg(LL_ALWAYS, "Recv failed (hr == %x)", hrResult);
454  Chk(hrResult);
455  }
456 
457  reader.AddBytes(pData+bytes_recv, ret);
458  bytes_recv += ret;
459  remaining = max_bytes_recv - bytes_recv;
460  spMsg->SetSize(bytes_recv);
461  }
462 
463 
464  // now feed the response into the client logic
465  stunsocket.UpdateAddresses();
466  addrLocal = stunsocket.GetLocalAddress();
467  clientlogic.ProcessResponse(spMsg, addrDest, addrLocal);
468  }
469 
470  stunsocket.Close();
471 
472  results.Init();
473  clientlogic.GetResults(&results);
474  ::DumpResults(config, results);
475 
476 Cleanup:
477  return;
478 
479 }
480 
481 
483 {
484  HRESULT hr = S_OK;
485  CStunSocket stunSocket;
487  int sock = -1;
488  CSocketAddress addrDest; // who we send to
489  CSocketAddress addrRemote; // who we
490  CSocketAddress addrLocal;
491  int ret;
492  fd_set set;
493  timeval tv = {};
494  std::string strAddr;
495  std::string strAddrLocal;
496  StunClientResults results;
497 
498  CStunClientLogic clientlogic;
499 
500 
501  hr = clientlogic.Initialize(config);
502 
503  if (FAILED(hr))
504  {
505  Logging::LogMsg(LL_ALWAYS, "Unable to initialize client: (error = x%x)", hr);
506  Chk(hr);
507  }
508 
509  hr = stunSocket.UDPInit(socketconfig.addrLocal, RolePP);
510  if (FAILED(hr))
511  {
512  Logging::LogMsg(LL_ALWAYS, "Unable to create local socket: (error = x%x)", hr);
513  Chk(hr);
514  }
515 
516 
517  stunSocket.EnablePktInfoOption(true);
518 
519  sock = stunSocket.GetSocketHandle();
520 
521  // let's get a loop going!
522 
523  while (true)
524  {
525  HRESULT hrRet;
526  spMsg->SetSize(0);
527  hrRet = clientlogic.GetNextMessage(spMsg, &addrDest, GetMillisecondCounter());
528 
529  if (SUCCEEDED(hrRet))
530  {
531  addrDest.ToString(&strAddr);
532  ASSERT(spMsg->GetSize() > 0);
533 
535  {
536  std::string strAddr;
537  addrDest.ToString(&strAddr);
538  Logging::LogMsg(LL_DEBUG, "Sending message to %s", strAddr.c_str());
539  }
540 
541  ret = ::sendto(sock, spMsg->GetData(), spMsg->GetSize(), 0, addrDest.GetSockAddr(), addrDest.GetSockAddrLength());
542 
543  if (ret <= 0)
544  {
545  Logging::LogMsg(LL_DEBUG, "ERROR. sendto failed (errno = %d)", errno);
546  }
547  // there's not much we can do if "sendto" fails except time out and try again
548  }
549  else if (hrRet == E_STUNCLIENT_STILL_WAITING)
550  {
551  Logging::LogMsg(LL_DEBUG, "Continuing to wait for response...");
552  }
553  else if (hrRet == E_STUNCLIENT_RESULTS_READY)
554  {
555  break;
556  }
557  else
558  {
559  Logging::LogMsg(LL_DEBUG, "Fatal error (hr == %x)", hrRet);
560  Chk(hrRet);
561  }
562 
563 
564  // now wait for a response
565  spMsg->SetSize(0);
566  FD_ZERO(&set);
567  FD_SET(sock, &set);
568  tv.tv_usec = 500000; // half-second
569  tv.tv_sec = config.timeoutSeconds;
570 
571  ret = select(sock+1, &set, NULL, NULL, &tv);
572  if (ret > 0)
573  {
574  ret = ::recvfromex(sock, spMsg->GetData(), spMsg->GetAllocatedSize(), MSG_DONTWAIT, &addrRemote, &addrLocal);
575  if (ret > 0)
576  {
577  addrLocal.SetPort(stunSocket.GetLocalAddress().GetPort()); // recvfromex doesn't fill in the dest port value, only dest IP
578  addrRemote.ToString(&strAddr);
579  addrLocal.ToString(&strAddrLocal);
580  Logging::LogMsg(LL_DEBUG, "Got response (%d bytes) from %s on interface %s", ret, strAddr.c_str(), strAddrLocal.c_str());
581  spMsg->SetSize(ret);
582  clientlogic.ProcessResponse(spMsg, addrRemote, addrLocal);
583  }
584  }
585  }
586 
587 
588  results.Init();
589  clientlogic.GetResults(&results);
590 
591  DumpResults(config, results);
592 
593 
594 Cleanup:
595  return hr;
596 }
597 
598 
599 
600 
601 
602 
603 
604 int main(int argc, char** argv)
605 {
606  CCmdLineParser cmdline;
607  ClientCmdLineArgs args;
608  StunClientLogicConfig config;
609  ClientSocketConfig socketconfig;
610  bool fError = false;
611  uint32_t loglevel = LL_ALWAYS;
612 
613 
614 #ifdef DEBUG
615  loglevel = LL_DEBUG;
616 #endif
617  Logging::SetLogLevel(loglevel);
618 
619 
620  cmdline.AddNonOption(&args.strRemoteServer);
621  cmdline.AddNonOption(&args.strRemotePort);
622  cmdline.AddOption("localaddr", required_argument, &args.strLocalAddr);
623  cmdline.AddOption("localport", required_argument, &args.strLocalPort);
624  cmdline.AddOption("mode", required_argument, &args.strMode);
625  cmdline.AddOption("family", required_argument, &args.strFamily);
626  cmdline.AddOption("protocol", required_argument, &args.strProtocol);
627  cmdline.AddOption("verbosity", required_argument, &args.strVerbosity);
628  cmdline.AddOption("help", no_argument, &args.strHelp);
629 
630  if (argc <= 1)
631  {
632  PrintUsage(true);
633  return -1;
634  }
635 
636  cmdline.ParseCommandLine(argc, argv, 1, &fError);
637 
638  if (args.strHelp.length() > 0)
639  {
640  PrintUsage(false);
641  return -2;
642  }
643 
644  if (fError)
645  {
646  PrintUsage(true);
647  return -3;
648  }
649 
650 
651  if (args.strVerbosity.length() > 0)
652  {
653  int level = atoi(args.strVerbosity.c_str());
654  if (level >= 0)
655  {
656  Logging::SetLogLevel(level);
657  }
658  }
659 
660  if (FAILED(CreateConfigFromCommandLine(args, &config, &socketconfig)))
661  {
662  Logging::LogMsg(LL_ALWAYS, "Can't start client");
663  PrintUsage(true);
664  return -4;
665  }
666 
667  DumpConfig(config, socketconfig);
668 
669  if (socketconfig.socktype == SOCK_STREAM)
670  {
671  TcpClientLoop(config, socketconfig);
672  }
673  else
674  {
675  UdpClientLoop(config, socketconfig);
676  }
677 
678  return 0;
679 }
const uint32_t MAX_STUN_MESSAGE_SIZE
Definition: stuntypes.h:178
#define S_OK
Definition: hresult.h:46
void DumpResults(StunClientLogicConfig &config, StunClientResults &results)
Definition: clientmain.cpp:291
#define ASSERT(expr)
const uint32_t LL_DEBUG
Definition: logger.h:24
void TcpClientLoop(StunClientLogicConfig &config, ClientSocketConfig &socketconfig)
Definition: clientmain.cpp:330
CDataStream & GetStream()
Definition: stunreader.cpp:855
HRESULT Initialize(StunClientLogicConfig &config)
void UpdateAddresses()
Definition: stunsocket.cpp:245
#define E_STUNCLIENT_STILL_WAITING
std::string strRemoteServer
Definition: clientmain.cpp:38
socklen_t GetSockAddrLength() const
void Close()
Definition: stunsocket.cpp:41
int ValidateNumberString(const char *psz, int nMinValue, int nMaxValue, int *pnResult)
#define E_STUNCLIENT_RESULTS_READY
#define Chk(expr)
Definition: chkmacros.h:53
void DumpConfig(StunClientLogicConfig &config, ClientSocketConfig &socketConfig)
Definition: clientmain.cpp:56
HRESULT ResolveHostName(const char *pszHostName, int family, bool fNumericOnly, CSocketAddress *pAddr)
ssize_t recvfromex(int sockfd, void *buf, size_t len, int flags, CSocketAddress *pSrcAddr, CSocketAddress *pDstAddr)
Definition: recvfromex.cpp:44
void LogMsg(uint32_t level, const char *pszFormat,...)
Definition: logger.cpp:44
HRESULT CreateConfigFromCommandLine(ClientCmdLineArgs &args, StunClientLogicConfig *pConfig, ClientSocketConfig *pSocketConfig)
Definition: clientmain.cpp:90
HRESULT GetNextMessage(CRefCountedBuffer &spMsg, CSocketAddress *pAddrDest, uint32_t timeCurrentMilliseconds)
uint32_t GetMillisecondCounter()
CSocketAddress addrLocal
Definition: clientmain.cpp:53
uint16_t GetPort() const
std::string strProtocol
Definition: clientmain.cpp:44
#define ARRAYSIZE(arr)
bool IsNullOrEmpty(const char *psz)
NatBehavior behavior
ReaderParseState AddBytes(const uint8_t *pData, uint32_t size)
Definition: stunreader.cpp:750
HRESULT GetSocketAddressForAdapter(int family, const char *pszAdapterName, uint16_t port, CSocketAddress *pSocketAddr)
Definition: adapters.cpp:111
void NatBehaviorToString(NatBehavior behavior, std::string *pStr)
Definition: clientmain.cpp:261
Definition: buffer.h:27
#define SUCCEEDED(hr)
Definition: hresult.h:28
void SetPort(uint16_t)
int GetSocketHandle() const
Definition: stunsocket.cpp:82
void SetLogLevel(uint32_t level)
Definition: logger.cpp:38
void ToLower(std::string &str)
CSocketAddress addrMapped
size_t GetConsoleWidth()
int32_t HRESULT
Definition: hresult.h:22
const uint16_t DEFAULT_STUN_PORT
Definition: stuntypes.h:29
HRESULT UdpClientLoop(StunClientLogicConfig &config, const ClientSocketConfig &socketconfig)
Definition: clientmain.cpp:482
HRESULT ParseCommandLine(int argc, char **argv, int startindex, bool *fParseError)
std::string strMode
Definition: clientmain.cpp:42
std::string strLocalAddr
Definition: clientmain.cpp:40
const sockaddr * GetSockAddr() const
void ToString(std::string *pStr) const
HRESULT EnablePktInfoOption(bool fEnable)
Definition: stunsocket.cpp:179
void PrintUsage(bool fSummaryUsage)
Definition: clientmain.cpp:74
int main(int argc, char **argv)
Definition: clientmain.cpp:604
HRESULT ToStringBuffer(char *pszAddrBytes, size_t length) const
CSocketAddress addrLocal
#define E_INVALIDARG
Definition: hresult.h:51
std::string strVerbosity
Definition: clientmain.cpp:45
HRESULT ProcessResponse(CRefCountedBuffer &spMsg, CSocketAddress &addrRemote, CSocketAddress &addrLocal)
#define FAILED(hr)
Definition: hresult.h:29
HRESULT GetResults(StunClientResults *pResults)
std::string strLocalPort
Definition: clientmain.cpp:41
uint32_t GetLogLevel()
Definition: logger.cpp:33
HRESULT AddNonOption(std::string *pStrResult)
std::string strRemotePort
Definition: clientmain.cpp:39
const uint32_t LL_ALWAYS
Definition: logger.h:23
HRESULT UDPInit(const CSocketAddress &local, SocketRole role)
Definition: stunsocket.cpp:322
HRESULT AddOption(const char *pszName, int has_arg, std::string *pStrResult)
NatFiltering filtering
HRESULT TCPInit(const CSocketAddress &local, SocketRole role, bool fSetReuseFlag)
Definition: stunsocket.cpp:327
NatBehavior
boost::shared_ptr< CBuffer > CRefCountedBuffer
Definition: buffer.h:65
NatFiltering
std::string strHelp
Definition: clientmain.cpp:46
std::string strFamily
Definition: clientmain.cpp:43
void Attach(CRefCountedBuffer &buffer, bool fForWriting)
Definition: datastream.cpp:55
uint16_t HowManyBytesNeeded()
Definition: stunreader.cpp:76
#define ChkIfA(expr, hrerror)
Definition: chkmacros.h:84
void PrettyPrint(const char *pszInput, size_t width)
void NatFilteringToString(NatFiltering filtering, std::string *pStr)
Definition: clientmain.cpp:276
#define ERRNOHR
Definition: hresult.h:42
CSocketAddress addrServer
const CSocketAddress & GetLocalAddress() const
Definition: stunsocket.cpp:87