⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 turnasyncsocket.cxx

📁 这是国外的resip协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
      }   }   else   {      // Check if success or not      if(stunMessage.mHasErrorCode)      {         if(mTurnAsyncSocketHandler) mTurnAsyncSocketHandler->onAllocationFailure(getSocketDescriptor(), asio::error_code(stunMessage.mErrorCode.errorClass * 100 + stunMessage.mErrorCode.number, asio::error::misc_category));      }      else      {         if(mTurnAsyncSocketHandler) mTurnAsyncSocketHandler->onAllocationFailure(getSocketDescriptor(), asio::error_code(MissingAttributes, asio::error::misc_category));         return asio::error_code(MissingAttributes, asio::error::misc_category);      }   }   return asio::error_code();}asio::error_code TurnAsyncSocket::handleRefreshResponse(StunMessage& stunMessage){   if(stunMessage.mClass == StunMessage::StunClassSuccessResponse)   {      if(stunMessage.mHasTurnLifetime)      {         mLifetime = stunMessage.mTurnLifetime;      }      else      {         mLifetime = 0;      }      if(mLifetime != 0)      {         mHaveAllocation = true;         startAllocationTimer();         if(mTurnAsyncSocketHandler) mTurnAsyncSocketHandler->onRefreshSuccess(getSocketDescriptor(), mLifetime);         if(mCloseAfterDestroyAllocationFinishes)         {            mHaveAllocation = false;            actualClose();         }      }      else      {         cancelAllocationTimer();         mHaveAllocation = false;         if(mTurnAsyncSocketHandler) mTurnAsyncSocketHandler->onRefreshSuccess(getSocketDescriptor(), 0);         if(mCloseAfterDestroyAllocationFinishes)         {            actualClose();         }      }   }   else   {      // Check if success or not      if(stunMessage.mHasErrorCode)      {         if(mTurnAsyncSocketHandler) mTurnAsyncSocketHandler->onRefreshFailure(getSocketDescriptor(), asio::error_code(stunMessage.mErrorCode.errorClass * 100 + stunMessage.mErrorCode.number, asio::error::misc_category));         if(mCloseAfterDestroyAllocationFinishes)         {            mHaveAllocation = false;            actualClose();         }      }      else      {         if(mTurnAsyncSocketHandler) mTurnAsyncSocketHandler->onRefreshFailure(getSocketDescriptor(), asio::error_code(MissingAttributes, asio::error::misc_category));         if(mCloseAfterDestroyAllocationFinishes)         {            mHaveAllocation = false;            actualClose();         }         return asio::error_code(MissingAttributes, asio::error::misc_category);      }   }   return asio::error_code();}voidTurnAsyncSocket::send(const char* buffer, unsigned int size){   boost::shared_ptr<DataBuffer> data(new DataBuffer(buffer, size));   mGuards.push(mAsyncSocketBase.shared_from_this());   mIOService.post(boost::bind(&TurnAsyncSocket::doSend, this, data));}voidTurnAsyncSocket::doSend(boost::shared_ptr<DataBuffer>& data){   GuardReleaser guardReleaser(mGuards);   // Allow raw data to be sent if there is no allocation   if(!mHaveAllocation)   {      send(data);      return;   }   return sendTo(*mActiveDestination, data);}void TurnAsyncSocket::sendTo(const asio::ip::address& address, unsigned short port, const char* buffer, unsigned int size){   boost::shared_ptr<DataBuffer> data(new DataBuffer(buffer, size));   mGuards.push(mAsyncSocketBase.shared_from_this());   mIOService.post(boost::bind(&TurnAsyncSocket::doSendTo, this, address, port, data));}void TurnAsyncSocket::doSendTo(const asio::ip::address& address, unsigned short port, boost::shared_ptr<DataBuffer>& data){   GuardReleaser guardReleaser(mGuards);   // Allow raw data to be sent if there is no allocation   if(!mHaveAllocation)   {      StunTuple destination(mLocalBinding.getTransportType(), address, port);      mAsyncSocketBase.send(destination, data);      return;   }   // Setup Remote Peer    StunTuple remoteTuple(mRelayTransportType, address, port);   RemotePeer* remotePeer = mChannelManager.findRemotePeerByPeerAddress(remoteTuple);   if(!remotePeer)   {      // No remote peer yet (ie. not data sent or received from remote peer) - so create one      remotePeer = mChannelManager.createRemotePeer(remoteTuple, mChannelManager.getNextChannelNumber(), 0);      assert(remotePeer);   }   return sendTo(*remotePeer, data);}voidTurnAsyncSocket::sendTo(RemotePeer& remotePeer, boost::shared_ptr<DataBuffer>& data){   if(remotePeer.isClientToServerChannelConfirmed())   {      // send framed data to active destination      send(remotePeer.getClientToServerChannel(), data);   }   else   {      // Data must be wrapped in a Send Indication      // Wrap data in a SendInd      StunMessage* ind = createNewStunMessage(StunMessage::StunClassIndication, StunMessage::TurnSendMethod, false);      ind->mHasTurnPeerAddress = true;      StunMessage::setStunAtrAddressFromTuple(ind->mTurnPeerAddress, remotePeer.getPeerTuple());      ind->mHasTurnChannelNumber = true;      ind->mTurnChannelNumber = remotePeer.getClientToServerChannel();      if(data->size() > 0)      {         ind->setTurnData(data->data(), data->size());      }      // If not using UDP - then mark channel as confirmed      if(mLocalBinding.getTransportType() != StunTuple::UDP)      {         remotePeer.setClientToServerChannelConfirmed();      }      // Send indication to Turn Server      sendStunMessage(ind);   }}voidTurnAsyncSocket::connect(const std::string& address, unsigned short port, bool turnFraming){   mTurnFraming = turnFraming;   mAsyncSocketBase.connect(address,port);}voidTurnAsyncSocket::close(){   mGuards.push(mAsyncSocketBase.shared_from_this());   mIOService.post(boost::bind(&TurnAsyncSocket::doClose, this));}voidTurnAsyncSocket::doClose(){   GuardReleaser guardReleaser(mGuards);   // If we have an allocation over UDP then we should send a refresh with lifetime 0 to destroy the allocation   // Note:  For TCP and TLS, the socket disconnection will destroy the allocation automatically   if(mHaveAllocation && mLocalBinding.getTransportType() == StunTuple::UDP)   {      mCloseAfterDestroyAllocationFinishes = true;      destroyAllocation();   }   else   {      actualClose();   }}voidTurnAsyncSocket::actualClose(){   clearActiveRequestMap();   cancelAllocationTimer();   mAsyncSocketBase.close();}void TurnAsyncSocket::turnReceive(){   if(mTurnFraming)   {      //mAsyncSocketBase.framedReceive();      mAsyncSocketBase.doFramedReceive();   }   else   {      //mAsyncSocketBase.receive();      mAsyncSocketBase.doReceive();   }}void TurnAsyncSocket::send(boost::shared_ptr<DataBuffer>& data){   StunTuple destination(mLocalBinding.getTransportType(), mAsyncSocketBase.getConnectedAddress(), mAsyncSocketBase.getConnectedPort());   mAsyncSocketBase.send(destination, data);}void TurnAsyncSocket::send(unsigned short channel, boost::shared_ptr<DataBuffer>& data){   StunTuple destination(mLocalBinding.getTransportType(), mAsyncSocketBase.getConnectedAddress(), mAsyncSocketBase.getConnectedPort());   mAsyncSocketBase.send(destination, channel, data);}TurnAsyncSocket::RequestEntry::RequestEntry(asio::io_service& ioService,                                             TurnAsyncSocket* turnAsyncSocket,                                             StunMessage* requestMessage) :    mIOService(ioService),    mTurnAsyncSocket(turnAsyncSocket),    mRequestMessage(requestMessage),    mRequestTimer(ioService),   mRequestsSent(1){   mTimeout = mTurnAsyncSocket->mLocalBinding.getTransportType() == StunTuple::UDP ? UDP_RT0 : TCP_RESPONSE_TIME;}voidTurnAsyncSocket::RequestEntry::startTimer(){   // start the request timer   mRequestTimer.expires_from_now(boost::posix_time::milliseconds(mTimeout));     mRequestTimer.async_wait(boost::bind(&TurnAsyncSocket::RequestEntry::requestTimerExpired, shared_from_this(), asio::placeholders::error));}voidTurnAsyncSocket::RequestEntry::stopTimer(){   // stop the request timer   mRequestTimer.cancel();}TurnAsyncSocket::RequestEntry::~RequestEntry() {    delete mRequestMessage; }void TurnAsyncSocket::RequestEntry::requestTimerExpired(const asio::error_code& e){   if(!e && mRequestMessage)  // Note:  There is a race condition with clearing out of mRequestMessage when 401 is received - check that mRequestMessage is not 0 avoids any resulting badness   {      if(mTurnAsyncSocket->mLocalBinding.getTransportType() != StunTuple::UDP || mRequestsSent == UDP_MAX_RETRANSMITS)      {         mTurnAsyncSocket->requestTimeout(mRequestMessage->mHeader.magicCookieAndTid);         return;      }      // timed out and should retransmit - calculate next timeout      if(mRequestsSent == UDP_MAX_RETRANSMITS - 1)      {          mTimeout = UDP_FINAL_REQUEST_TIME;      }       else      {          mTimeout = (mTimeout*2);      }      // retransmit      DebugLog(<< "RequestEntry::requestTimerExpired: retransmitting...");      mRequestsSent++;      mTurnAsyncSocket->sendStunMessage(mRequestMessage, true);      startTimer();   }}void TurnAsyncSocket::requestTimeout(UInt128 tid){   RequestMap::iterator it = mActiveRequestMap.find(tid);   if(it != mActiveRequestMap.end())   {      switch(it->second->mRequestMessage->mMethod)      {      case StunMessage::BindMethod:         if(mTurnAsyncSocketHandler) mTurnAsyncSocketHandler->onBindFailure(getSocketDescriptor(), asio::error_code(reTurn::ResponseTimeout, asio::error::misc_category));         break;      case StunMessage::SharedSecretMethod:         if(mTurnAsyncSocketHandler) mTurnAsyncSocketHandler->onSharedSecretFailure(getSocketDescriptor(), asio::error_code(reTurn::ResponseTimeout, asio::error::misc_category));         break;      case StunMessage::TurnAllocateMethod:         if(mTurnAsyncSocketHandler) mTurnAsyncSocketHandler->onAllocationFailure(getSocketDescriptor(), asio::error_code(reTurn::ResponseTimeout, asio::error::misc_category));         break;      case StunMessage::TurnRefreshMethod:         if(mTurnAsyncSocketHandler) mTurnAsyncSocketHandler->onRefreshFailure(getSocketDescriptor(), asio::error_code(reTurn::ResponseTimeout, asio::error::misc_category));         if(mCloseAfterDestroyAllocationFinishes)         {            mHaveAllocation = false;            actualClose();         }         break;      default:         assert(false);      }      mActiveRequestMap.erase(it);   }}voidTurnAsyncSocket::clearActiveRequestMap(){   // Clear out active request map - !slg! TODO this really should happen from the io service thread   RequestMap::iterator it = mActiveRequestMap.begin();   for(;it != mActiveRequestMap.end(); it++)   {      it->second->stopTimer();   }   mActiveRequestMap.clear();}voidTurnAsyncSocket::startAllocationTimer(){   mAllocationTimer.expires_from_now(boost::posix_time::seconds((mLifetime*5)/8));  // Allocation refresh should sent before 3/4 lifetime - use 5/8 lifetime    mGuards.push(mAsyncSocketBase.shared_from_this());   mAllocationTimer.async_wait(boost::bind(&TurnAsyncSocket::allocationTimerExpired, this, asio::placeholders::error));}voidTurnAsyncSocket::cancelAllocationTimer(){   mAllocationTimer.cancel();}void TurnAsyncSocket::allocationTimerExpired(const asio::error_code& e){   if(!e)   {      doRefreshAllocation(mLifetime);   }   else   {      // Note:  only release guard if not calling doRefreshAllocation - since      // doRefreshAllocation will release the guard      GuardReleaser guardReleaser(mGuards);   }}} // namespace/* ==================================================================== Original contribution Copyright (C) 2007 Plantronics, Inc. Provided under the terms of the Vovida Software License, Version 2.0. The Vovida Software License, Version 2.0   Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:  1. Redistributions of source code must retain the above copyright    notice, this list of conditions and the following disclaimer.  2. Redistributions in binary form must reproduce the above copyright    notice, this list of conditions and the following disclaimer in    the documentation and/or other materials provided with the    distribution.   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================== */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -