HRESULT CBasicBindingTest::ProcessResponse(CRefCountedBuffer& spMsg, CSocketAddress& addrRemote, CSocketAddress& addrLocal) { HRESULT hr = S_OK; CStunMessageReader reader; CSocketAddress addrMapped; CSocketAddress addrOther; bool fHasOtherAddress = false; // todo - figure out a way to make buffering TCP fragments work Chk(BasicReaderValidation(spMsg, reader)); hr = reader.GetXorMappedAddress(&addrMapped); if (FAILED(hr)) { hr = reader.GetMappedAddress(&addrMapped); } Chk(hr); // again drop the message if we can't parse the binding response fHasOtherAddress = SUCCEEDED(reader.GetOtherAddress(&addrOther)); // ok, we got a response. So we are done _fCompleted = true; _pResults->fBindingTestSuccess = true; _pResults->fIsDirect = addrLocal.IsSameIP_and_Port(addrMapped); _pResults->addrLocal = addrLocal; _pResults->addrMapped = addrMapped; _pResults->fHasOtherAddress = fHasOtherAddress; if (fHasOtherAddress) { _pResults->addrAA = addrOther; _pResults->addrPA = _pConfig->addrServer; _pResults->addrPA.SetPort(addrOther.GetPort()); _pResults->addrAP = addrOther; _pResults->addrAP.SetPort(_pConfig->addrServer.GetPort()); if (Logging::GetLogLevel() >= LL_DEBUG) { char sz[100]; addrOther.ToStringBuffer(sz, 100); Logging::LogMsg(LL_DEBUG, "Other address is %s\n",sz); } } Cleanup: return hr; }
StunConnection* CTCPStunThread::AcceptConnection(CStunSocket* pListenSocket) { int listensock = pListenSocket->GetSocketHandle(); SocketRole role = pListenSocket->GetRole(); int clientsock = -1; int socktmp = -1; sockaddr_storage addrClient; socklen_t socklen = sizeof(addrClient); StunConnection* pConn = NULL; HRESULT hr = S_OK; int insertresult; int err; ASSERT(listensock != -1); ASSERT(::IsValidSocketRole(role)); socktmp = ::accept(listensock, (sockaddr*)&addrClient, &socklen); err = errno; Logging::LogMsg(LL_VERBOSE, "accept returns %d (errno == %d)", socktmp, (socktmp<0)?err:0); ChkIfA(socktmp == -1, E_FAIL); // --- rate limit check------- if (_spLimiter.get()) { CSocketAddress addr = CSocketAddress(addrClient); bool allowed_to_pass = _spLimiter->RateCheck(addr); if (allowed_to_pass == false) { if (Logging::GetLogLevel() >= LL_VERBOSE) { char szIP[100]; addr.ToStringBuffer(szIP, 100); Logging::LogMsg(LL_VERBOSE, "Rate Limiter has blocked incoming connection from IP %s", szIP); } ChkIf(false, E_FAIL); // this will trigger the socket to be immediately closed } } // -------------------------- clientsock = socktmp; pConn = _connectionpool.GetConnection(clientsock, role); ChkIfA(pConn == NULL, E_FAIL); // Our connection pool has nothing left to give, only thing to do is abort this connection and close the socket socktmp = -1; ChkA(pConn->_stunsocket.SetNonBlocking(true)); ChkA(_spPolling->Add(clientsock, EPOLL_CLIENT_READ_EVENT_SET)); // add connection to our tracking tables pConn->_idHashTable = (_pNewConnList == &_hashConnections1) ? 1 : 2; insertresult = _pNewConnList->Insert(clientsock, pConn); // out of space in the lookup tables? ChkIfA(insertresult == -1, E_FAIL); if (Logging::GetLogLevel() >= LL_VERBOSE) { char szIPRemote[100]; char szIPLocal[100]; pConn->_stunsocket.GetLocalAddress().ToStringBuffer(szIPLocal, ARRAYSIZE(szIPLocal)); pConn->_stunsocket.GetRemoteAddress().ToStringBuffer(szIPRemote, ARRAYSIZE(szIPRemote)); Logging::LogMsg(LL_VERBOSE, "accepting new connection on socket %d from %s on interface %s", pConn->_stunsocket.GetSocketHandle(), szIPRemote, szIPLocal); } Cleanup: if (FAILED(hr)) { CloseConnection(pConn); pConn = NULL; if (socktmp != -1) { close(socktmp); } } return pConn; }