int CGSocket::Connect( LPCTSTR pszHostName, WORD wPort ) { CSocketAddress SockAddr; SockAddr.SetHostStr( pszHostName ); SockAddr.SetPort( wPort ); return( Connect( SockAddr )); }
// This test validates that the EnablePktInfoOption set on a socket allows us to get at the destination IP address for incoming packets // This is needed so that we can correctly insert an origin address into responses from the server // 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) HRESULT CTestRecvFromEx::DoTest(bool fIPV6) { // create a couple of sockets for send/recv HRESULT hr = S_OK; CSocketAddress addrAny(0,0); // INADDR_ANY, random port sockaddr_in6 addrAnyIPV6 = {}; uint16_t portRecv = 0; CRefCountedStunSocket spSocketSend, spSocketRecv; fd_set set = {}; CSocketAddress addrDestForSend; CSocketAddress addrDestOnRecv; CSocketAddress addrSrcOnRecv; CSocketAddress addrSrc; CSocketAddress addrDst; char ch = 'x'; sockaddr_storage addrDummy; socklen_t addrlength; int ret; timeval tv = {}; if (fIPV6) { addrAnyIPV6.sin6_family = AF_INET6; addrAny = CSocketAddress(addrAnyIPV6); } // create two sockets listening on INADDR_ANY. One for sending and one for receiving ChkA(CStunSocket::Create(addrAny, RolePP, &spSocketSend)); ChkA(CStunSocket::Create(addrAny, RolePP, &spSocketRecv)); spSocketRecv->EnablePktInfoOption(true); portRecv = spSocketRecv->GetLocalAddress().GetPort(); // now send to localhost if (fIPV6) { sockaddr_in6 addr6 = {}; addr6.sin6_family = AF_INET6; ::inet_pton(AF_INET6, "::1", &(addr6.sin6_addr)); addrDestForSend = CSocketAddress(addr6); } else { sockaddr_in addr4 = {}; addr4.sin_family = AF_INET; ::inet_pton(AF_INET, "127.0.0.1", &(addr4.sin_addr)); addrDestForSend = CSocketAddress(addr4); } addrDestForSend.SetPort(portRecv); // flush out any residual packets that might be buffered up on recv socket ret = -1; do { addrlength = sizeof(addrDummy); ret = ::recvfrom(spSocketRecv->GetSocketHandle(), &ch, sizeof(ch), MSG_DONTWAIT, (sockaddr*)&addrDummy, &addrlength); } while (ret >= 0); // now send some data to ourselves ret = sendto(spSocketSend->GetSocketHandle(), &ch, sizeof(ch), 0, addrDestForSend.GetSockAddr(), addrDestForSend.GetSockAddrLength()); ChkIfA(ret <= 0, E_UNEXPECTED); // now wait for the data to arrive FD_ZERO(&set); FD_SET(spSocketRecv->GetSocketHandle(), &set); tv.tv_sec = 3; ret = select(spSocketRecv->GetSocketHandle()+1, &set, NULL, NULL, &tv); ChkIfA(ret <= 0, E_UNEXPECTED); ret = ::recvfromex(spSocketRecv->GetSocketHandle(), &ch, 1, MSG_DONTWAIT, &addrSrcOnRecv, &addrDestOnRecv); ChkIfA(ret <= 0, E_UNEXPECTED); ChkIfA(addrSrcOnRecv.IsIPAddressZero(), E_UNEXPECTED); ChkIfA(addrDestOnRecv.IsIPAddressZero(), E_UNEXPECTED); Cleanup: return hr; }
// send a binding request to a duplex server instructing it to send back on it's alternate port and alternate IP to an alternate client port HRESULT CTestMessageHandler::Test2() { HRESULT hr=S_OK; CStunMessageBuilder builder; CSocketAddress clientaddr(0x12345678, 9876); CSocketAddress recvaddr; uint16_t responsePort = 2222; CRefCountedBuffer spBuffer; CStunThreadMessageHandler handler; CStunMessageReader reader; CStunMessageReader::ReaderParseState state; ::StunChangeRequestAttribute changereq; StunMessageEnvelope message; _spTransport->Reset(); _spTransport->AddPP(CSocketAddress(0xaaaaaaaa, 1234)); _spTransport->AddPA(CSocketAddress(0xaaaaaaaa, 1235)); _spTransport->AddAP(CSocketAddress(0xbbbbbbbb, 1234)); _spTransport->AddAA(CSocketAddress(0xbbbbbbbb, 1235)); InitBindingRequest(builder); builder.AddResponsePort(responsePort); changereq.fChangeIP = true; changereq.fChangePort = true; builder.AddChangeRequest(changereq); builder.AddResponsePort(responsePort); builder.GetResult(&spBuffer); message.localSocket = RolePP; message.remoteAddr = clientaddr; message.spBuffer = spBuffer; _spTransport->GetSocketAddressForRole(RolePP, &(message.localAddr)); handler.SetResponder(_spTransport); handler.ProcessRequest(message); spBuffer->Reset(); _spTransport->GetOutputStream().GetBuffer(&spBuffer); // parse the response state = reader.AddBytes(spBuffer->GetData(), spBuffer->GetSize()); ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL); // validate that the binding response matches our expectations ChkA(ValidateMappedAddress(reader, clientaddr)); ChkA(ValidateOriginAddress(reader, RoleAA)); // did it get sent back to where we thought it was recvaddr = clientaddr; recvaddr.SetPort(responsePort); ChkA(ValidateResponseAddress(recvaddr)); Cleanup: return hr; }
// Test2 - send a binding request to a duplex server instructing it to send back on it's alternate port and alternate IP to an alternate client port HRESULT CTestMessageHandler::Test2() { HRESULT hr = S_OK; CStunMessageBuilder builder; CRefCountedBuffer spBuffer, spBufferOut(new CBuffer(MAX_STUN_MESSAGE_SIZE)); CStunMessageReader reader; StunMessageIn msgIn; StunMessageOut msgOut; TransportAddressSet tas = {}; uint16_t responsePort = 2222; StunChangeRequestAttribute changereq; CStunMessageReader::ReaderParseState state; CSocketAddress addrDestExpected; InitTransportAddressSet(tas, true, true, true, true); InitBindingRequest(builder); builder.AddResponsePort(responsePort); changereq.fChangeIP = true; changereq.fChangePort = true; builder.AddChangeRequest(changereq); builder.AddResponsePort(responsePort); builder.GetResult(&spBuffer); ChkIfA(CStunMessageReader::BodyValidated != reader.AddBytes(spBuffer->GetData(), spBuffer->GetSize()), E_FAIL); msgIn.fConnectionOriented = false; msgIn.addrLocal = _addrServerPP; msgIn.pReader = &reader; msgIn.socketrole = RolePP; msgIn.addrRemote = _addrMapped; msgOut.socketrole = RolePP; // deliberate initialized wrong msgOut.spBufferOut = spBufferOut; ChkA(CStunRequestHandler::ProcessRequest(msgIn, msgOut, &tas, NULL)); // parse the response reader.Reset(); state = reader.AddBytes(spBufferOut->GetData(), spBufferOut->GetSize()); ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL); // validate that the message was sent back from the AA ChkIfA(msgOut.socketrole != RoleAA, E_FAIL); // validate that the server though it was sending back from the AA ChkA(ValidateResponseOriginAddress(reader, _addrServerAA)); // validate that the message was sent to the response port requested addrDestExpected = _addrMapped; addrDestExpected.SetPort(responsePort); ChkIfA(addrDestExpected.IsSameIP_and_Port(msgOut.addrDest)==false, E_FAIL); // validate that the binding response came back ChkA(ValidateMappedAddress(reader, _addrMapped, false)); // the "other" address is still AA (See RFC 3489 - section 8.1) ChkA(ValidateOtherAddress(reader, _addrServerAA)); Cleanup: return hr; }