Stun Server  Compliant with the latest RFCs including 5389, 5769, and 5780
discover the local host's own external IP address
testrecvfromex.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 #include "commonincludes.hpp"
19 
20 #include "stuncore.h"
21 #include "recvfromex.h"
22 #include "testrecvfromex.h"
23 #include "stunsocket.h"
24 
25 
27 {
28  return CTestRecvFromEx::DoTest(false); // ipv4
29 
30 }
31 
33 {
34  return CTestRecvFromEx::DoTest(true); // ipv6
35 }
36 
37 
38 
39 // This test validates that the EnablePktInfoOption set on a socket allows us to get at the destination IP address for incoming packets
40 // This is needed so that we can correctly insert an origin address into responses from the server
41 // Otherwise, the server doesn't have a way of knowing which interface a packet arrived on when it's listening on INADDR_ANY (all available addresses)
43 {
44  // create a couple of sockets for send/recv
45  HRESULT hr = S_OK;
46  CSocketAddress addrAny(0,0); // INADDR_ANY, random port
47  sockaddr_in6 addrAnyIPV6 = {};
48  uint16_t portRecv = 0;
49  CStunSocket socketSend, socketRecv;
50  fd_set set = {};
51  CSocketAddress addrDestForSend;
52  CSocketAddress addrDestOnRecv;
53  CSocketAddress addrSrcOnRecv;
54 
55  CSocketAddress addrSrc;
56  CSocketAddress addrDst;
57 
58  char ch = 'x';
59  sockaddr_storage addrDummy;
60  socklen_t addrlength;
61  int ret;
62  timeval tv = {};
63 
64 
65  if (fIPV6)
66  {
67  addrAnyIPV6.sin6_family = AF_INET6;
68  addrAny = CSocketAddress(addrAnyIPV6);
69  }
70 
71 
72  // create two sockets listening on INADDR_ANY. One for sending and one for receiving
73  ChkA(socketSend.UDPInit(addrAny, RolePP));
74 
75  ChkA(socketRecv.UDPInit(addrAny, RolePP));
76 
77  socketRecv.EnablePktInfoOption(true);
78 
79  portRecv = socketRecv.GetLocalAddress().GetPort();
80 
81  // now send to localhost
82  if (fIPV6)
83  {
84  sockaddr_in6 addr6 = {};
85  addr6.sin6_family = AF_INET6;
86  ::inet_pton(AF_INET6, "::1", &(addr6.sin6_addr));
87  addrDestForSend = CSocketAddress(addr6);
88  }
89  else
90  {
91  sockaddr_in addr4 = {};
92  addr4.sin_family = AF_INET;
93  ::inet_pton(AF_INET, "127.0.0.1", &(addr4.sin_addr));
94  addrDestForSend = CSocketAddress(addr4);
95  }
96  addrDestForSend.SetPort(portRecv);
97 
98  // flush out any residual packets that might be buffered up on recv socket
99  ret = -1;
100  do
101  {
102  addrlength = sizeof(addrDummy);
103  ret = ::recvfrom(socketRecv.GetSocketHandle(), &ch, sizeof(ch), MSG_DONTWAIT, (sockaddr*)&addrDummy, &addrlength);
104  } while (ret >= 0);
105 
106  // now send some data to ourselves
107  ret = sendto(socketSend.GetSocketHandle(), &ch, sizeof(ch), 0, addrDestForSend.GetSockAddr(), addrDestForSend.GetSockAddrLength());
108  ChkIfA(ret <= 0, E_UNEXPECTED);
109 
110  // now wait for the data to arrive
111  FD_ZERO(&set);
112  FD_SET(socketRecv.GetSocketHandle(), &set);
113  tv.tv_sec = 3;
114 
115  ret = select(socketRecv.GetSocketHandle()+1, &set, NULL, NULL, &tv);
116 
117  ChkIfA(ret <= 0, E_UNEXPECTED);
118 
119  ret = ::recvfromex(socketRecv.GetSocketHandle(), &ch, 1, MSG_DONTWAIT, &addrSrcOnRecv, &addrDestOnRecv);
120 
121  ChkIfA(ret <= 0, E_UNEXPECTED);
122 
123  ChkIfA(addrSrcOnRecv.IsIPAddressZero(), E_UNEXPECTED);
124  ChkIfA(addrDestOnRecv.IsIPAddressZero(), E_UNEXPECTED);
125 
126 
127 Cleanup:
128 
129  return hr;
130 }
131 
#define S_OK
Definition: hresult.h:46
socklen_t GetSockAddrLength() const
ssize_t recvfromex(int sockfd, void *buf, size_t len, int flags, CSocketAddress *pSrcAddr, CSocketAddress *pDstAddr)
Definition: recvfromex.cpp:44
uint16_t GetPort() const
#define E_UNEXPECTED
Definition: hresult.h:48
void SetPort(uint16_t)
int GetSocketHandle() const
Definition: stunsocket.cpp:82
int32_t HRESULT
Definition: hresult.h:22
const sockaddr * GetSockAddr() const
HRESULT EnablePktInfoOption(bool fEnable)
Definition: stunsocket.cpp:179
#define ChkA(expr)
Definition: chkmacros.h:73
HRESULT UDPInit(const CSocketAddress &local, SocketRole role)
Definition: stunsocket.cpp:322
static HRESULT DoTest(bool fUseIPV6)
bool IsIPAddressZero() const
#define ChkIfA(expr, hrerror)
Definition: chkmacros.h:84
const CSocketAddress & GetLocalAddress() const
Definition: stunsocket.cpp:87