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

📄 port.cc

📁 本人收集整理的一份c/c++跨平台网络库
💻 CC
📖 第 1 页 / 共 3 页
字号:
/* * libjingle * Copyright 2004--2005, Google Inc. * * 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. *  3. The name of the author may not be used to endorse or promote products  *     derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 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. */#if defined(_MSC_VER) && _MSC_VER < 1300#pragma warning(disable:4786)#endif#include <errno.h>#include <algorithm>#include <iostream>#include <vector>#include "talk/base/asyncudpsocket.h"#include "talk/base/asynctcpsocket.h"#include "talk/base/helpers.h"#include "talk/base/logging.h"#include "talk/base/scoped_ptr.h"#include "talk/base/socketadapters.h"#include "talk/p2p/base/common.h"#include "talk/p2p/base/port.h"#if defined(_MSC_VER) && _MSC_VER < 1300namespace std {  using ::memcmp;}#endifnamespace {// The length of time we wait before timing out readability on a connection.const uint32 CONNECTION_READ_TIMEOUT = 30 * 1000; // 30 seconds// The length of time we wait before timing out writability on a connection.const uint32 CONNECTION_WRITE_TIMEOUT = 15 * 1000; // 15 seconds// The length of time we wait before we become unwritable.const uint32 CONNECTION_WRITE_CONNECT_TIMEOUT = 5 * 1000; // 5 seconds// The number of pings that must fail to respond before we become unwritable.const uint32 CONNECTION_WRITE_CONNECT_FAILURES = 5;// This is the length of time that we wait for a ping response to come back.const int CONNECTION_RESPONSE_TIMEOUT = 5 * 1000; // 5 seconds// Determines whether we have seen at least the given maximum number of// pings fail to have a response.inline bool TooManyFailures(    const std::vector<uint32>& pings_since_last_response,    uint32 maximum_failures,    uint32 rtt_estimate,    uint32 now) {  // If we haven't sent that many pings, then we can't have failed that many.  if (pings_since_last_response.size() < maximum_failures)    return false;  // Check if the window in which we would expect a response to the ping has  // already elapsed.  return pings_since_last_response[maximum_failures - 1] + rtt_estimate < now;}// Determines whether we have gone too long without seeing any response.inline bool TooLongWithoutResponse(    const std::vector<uint32>& pings_since_last_response,    uint32 maximum_time,    uint32 now) {  if (pings_since_last_response.size() == 0)    return false;  return pings_since_last_response[0] + maximum_time < now;}// We will restrict RTT estimates (when used for determining state) to be// within a reasonable range.const uint32 MINIMUM_RTT = 100;  // 0.1 secondsconst uint32 MAXIMUM_RTT = 3000; // 3 seconds// When we don't have any RTT data, we have to pick something reasonable.  We// use a large value just in case the connection is really slow.const uint32 DEFAULT_RTT = MAXIMUM_RTT;// Computes our estimate of the RTT given the current estimate and the number// of data points on which it is based.inline uint32 ConservativeRTTEstimate(uint32 rtt, uint32 rtt_data_points) {  if (rtt_data_points == 0)    return DEFAULT_RTT;  else    return talk_base::_max(MINIMUM_RTT, talk_base::_min(MAXIMUM_RTT, 2 * rtt));}// Weighting of the old rtt value to new data.const int RTT_RATIO = 3; // 3 : 1// The delay before we begin checking if this port is useless.const int kPortTimeoutDelay = 30 * 1000; // 30 secondsconst uint32 MSG_CHECKTIMEOUT = 1;const uint32 MSG_DELETE = 1;}namespace cricket {static const char * const PROTO_NAMES[PROTO_LAST+1] = { "udp", "tcp", "ssltcp" };const char * ProtoToString(ProtocolType proto) {  return PROTO_NAMES[proto];}bool StringToProto(const char * value, ProtocolType& proto) {  for (size_t i=0; i<=PROTO_LAST; ++i) {    if (strcmp(PROTO_NAMES[i], value) == 0) {      proto = static_cast<ProtocolType>(i);      return true;    }  }  return false;}std::string Port::agent_;talk_base::ProxyInfo Port::proxy_;Port::Port(talk_base::Thread* thread, const std::string& type,            talk_base::SocketFactory* factory, talk_base::Network* network)  : thread_(thread), factory_(factory), type_(type), network_(network),    preference_(-1), lifetime_(LT_PRESTART), enable_port_packets_(false) {  if (factory_ == NULL)    factory_ = thread_->socketserver();  set_username_fragment(CreateRandomString(16));  set_password(CreateRandomString(16));}Port::~Port() {  // Delete all of the remaining connections.  We copy the list up front  // because each deletion will cause it to be modified.  std::vector<Connection*> list;  AddressMap::iterator iter = connections_.begin();  while (iter != connections_.end()) {    list.push_back(iter->second);    ++iter;  }  for (uint32 i = 0; i < list.size(); i++)    delete list[i];}Connection* Port::GetConnection(const talk_base::SocketAddress& remote_addr) {  AddressMap::const_iterator iter = connections_.find(remote_addr);  if (iter != connections_.end())    return iter->second;  else    return NULL;}void Port::AddAddress(const talk_base::SocketAddress& address,                      const std::string& protocol,                      bool final) {  Candidate c;  c.set_name(name_);  c.set_type(type_);  c.set_protocol(protocol);  c.set_address(address);  c.set_preference(preference_);  c.set_username(username_frag_);  c.set_password(password_);  c.set_network_name(network_->name());  c.set_generation(generation_);  candidates_.push_back(c);  if (final)    SignalAddressReady(this);}void Port::AddConnection(Connection* conn) {  connections_[conn->remote_candidate().address()] = conn;  conn->SignalDestroyed.connect(this, &Port::OnConnectionDestroyed);  SignalConnectionCreated(this, conn);}void Port::OnReadPacket(    const char* data, size_t size, const talk_base::SocketAddress& addr) {  // If the user has enabled port packets, just hand this over.  if (enable_port_packets_) {    SignalReadPacket(this, data, size, addr);    return;  }  // If this is an authenticated STUN request, then signal unknown address and  // send back a proper binding response.  StunMessage* msg;  std::string remote_username;  if (!GetStunMessage(data, size, addr, msg, remote_username)) {    LOG_J(LS_ERROR, this) << "Received non-STUN packet from unknown address ("                          << addr.ToString() << ")";  } else if (!msg) {    // STUN message handled already  } else if (msg->type() == STUN_BINDING_REQUEST) {    SignalUnknownAddress(this, addr, msg, remote_username);  } else {    LOG_J(LS_ERROR, this) << "Received unexpected STUN message type ("                          << msg->type() << ") from unknown address ("                          << addr.ToString() << ")";    delete msg;  }}void Port::SendBindingRequest(Connection* conn) {  // Construct the request message.  StunMessage request;  request.SetType(STUN_BINDING_REQUEST);  request.SetTransactionID(CreateRandomString(16));  StunByteStringAttribute* username_attr =      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);  std::string username = conn->remote_candidate().username();  username.append(username_frag_);  username_attr->CopyBytes(username.c_str(), (uint16)username.size());  request.AddAttribute(username_attr);  // Send the request message.  // NOTE: If we wanted to, this is where we would add the HMAC.  talk_base::ByteBuffer buf;  request.Write(&buf);  SendTo(buf.Data(), buf.Length(), conn->remote_candidate().address(), false);}bool Port::GetStunMessage(const char* data, size_t size,                          const talk_base::SocketAddress& addr,                           StunMessage *& msg, std::string& remote_username) {  // NOTE: This could clearly be optimized to avoid allocating any memory.  //       However, at the data rates we'll be looking at on the client side,  //       this probably isn't worth worrying about.  msg = 0;  // Parse the request message.  If the packet is not a complete and correct  // STUN message, then ignore it.  talk_base::scoped_ptr<StunMessage> stun_msg(new StunMessage());  talk_base::ByteBuffer buf(data, size);  if (!stun_msg->Read(&buf) || (buf.Length() > 0)) {    return false;  }  // The packet must include a username that either begins or ends with our  // fragment.  It should begin with our fragment if it is a request and it  // should end with our fragment if it is a response.  const StunByteStringAttribute* username_attr =      stun_msg->GetByteString(STUN_ATTR_USERNAME);  int remote_frag_len = (username_attr ? username_attr->length() : 0);  remote_frag_len -= static_cast<int>(username_frag_.size());  if (stun_msg->type() == STUN_BINDING_REQUEST) {    if ((remote_frag_len < 0)        || (std::memcmp(username_attr->bytes(),                        username_frag_.c_str(), username_frag_.size()) != 0)) {      LOG_J(LS_ERROR, this) << "Received STUN request with bad username";      SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_BAD_REQUEST,        STUN_ERROR_REASON_BAD_REQUEST);      return true;    }    remote_username.assign(username_attr->bytes() + username_frag_.size(),      username_attr->bytes() + username_attr->length());  } else if ((stun_msg->type() == STUN_BINDING_RESPONSE)      || (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE)) {    if ((remote_frag_len < 0)        || (std::memcmp(username_attr->bytes() + remote_frag_len,                        username_frag_.c_str(), username_frag_.size()) != 0)) {       LOG_J(LS_ERROR, this) << "Received STUN response with bad username";      // Do not send error response to a response      return true;    }    remote_username.assign(username_attr->bytes(),      username_attr->bytes() + remote_frag_len);

⌨️ 快捷键说明

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