posix_quic-master 客户端连接函数 QuicConnect()

首先会初始化结构体的地址

//初始化地址 addr是一个结构体
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9700);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");

建立连接

//根据socket套接字 网络地址来建立连接
    res = QuicConnect(socket, (struct sockaddr*)&addr, sizeof(addr));
    ```
跟进这个函数

```int QuicConnect(QuicSocket sock, const struct sockaddr* addr, socklen_t addrlen)
{
	//先判断传入的套接字
    auto socket = EntryBase::GetFdManager().Get(sock);//从map中找到sockd对应的指针  在前面的博客中有提到
    if (!socket || socket->Category() != EntryCategory::Socket) {
        DebugPrint(dbg_api, "sock = %d, return = -1, errno = EBADF", sock);
        errno = EBADF;
        return -1;
    }
//调用connect函数  返回一个整数
    int res = ((QuicSocketEntry*)socket.get())->Connect(addr, addrlen);
    DebugPrint(dbg_api, "sock = %d, return = %d, errno = %d", sock, res, errno);
    return res;
}

跟进这个connect函数

int QuicSocketEntry::Connect(const struct sockaddr* addr, socklen_t addrlen)
{//日志输出
    DebugPrint(dbg_connect, "begin. fd = %d", Fd());
//选择状态
    switch (socketState_) {
        case QuicSocketState_None:
            if (CreateNewUdpSocket() < 0) return -1;//如果没有创建成功,那么直接返回
            break;

        case QuicSocketState_Inited:
        case QuicSocketState_Binded:
            break;

        case QuicSocketState_Connecting:
            errno = EALREADY;
            return -1;

        default:
            errno = EINVAL;
            return -1;
    }
 //将状态设置为连接状态
    socketState_ = QuicSocketState_Connecting;
//存储地址
    struct sockaddr_storage addr_s = {};
   //拷贝传入的地址 
   memcpy(&addr_s, addr, addrlen);
    QuicSocketAddress address(addr_s);//把这个地址赋值给quic地址
//把这个地址赋值给set
/*
void PosixQuicPacketTransport::Set(std::shared_ptr<int> udpSocket, QuicSocketAddress const& address)
{
    udpSocket_ = udpSocket;
    address_ = address;
}
*/
    packetTransport_->Set(udpSocket_, address);

    DebugPrint(dbg_connect, "-> fd = %d, StartCryptoHandshake connectionId = %lu", Fd(), impl_->connection_id());//拿到连接id
/*
void QuartcSession::OnTransportCanWrite() {
  connection()->writer()->SetWritable();
  if (HasDataToWrite()) {//有数据可以写
    connection()->OnCanWrite();
  }
}*/ 
/*
bool QuicSession::HasDataToWrite() const {
  return write_blocked_streams_.HasWriteBlockedSpecialStream() ||
         write_blocked_streams_.HasWriteBlockedDataStreams() ||
         connection_->HasQueuedData() ||
         !streams_with_pending_retransmission_.empty() ||
         control_frame_manager_.WillingToWrite();//想要发送是数据
}

*/
  //可以发包
 impl_->OnTransportCanWrite();
/*
void QuartcSession::Initialize() {
  if (perspective_ == Perspective::IS_CLIENT) {
    QuicServerId server_id(unique_remote_server_id_, kQuicServerPort);
    QuicCryptoClientStream* crypto_stream =
        new QuicCryptoClientStream(server_id, this, new ProofVerifyContext(),
                                   quic_crypto_client_config_.get(), this);
    crypto_stream_.reset(crypto_stream);
    QuicSession::Initialize();
  } else {
    quic_compressed_certs_cache_.reset(new QuicCompressedCertsCache(
        QuicCompressedCertsCache::kQuicCompressedCertsCacheSize));
    bool use_stateless_rejects_if_peer_supported = false;
    QuicCryptoServerStream* crypto_stream = new QuicCryptoServerStream(
        quic_crypto_server_config_.get(), quic_compressed_certs_cache_.get(),
        use_stateless_rejects_if_peer_supported, this, &stream_helper_);
    crypto_stream_.reset(crypto_stream);
    QuicSession::Initialize();
  }
}

*/
    impl_->Initialize();
    if (GetOpt(sockopt_ack_timeout_secs) == 0 && kDefaultAckTimeout)
        this->SetOpt(sockopt_ack_timeout_secs, kDefaultAckTimeout);
//开始加密握手 
   impl_->StartCryptoHandshake();

    errno = EINPROGRESS;
    return -1;
}

这个是流的状态 表示可以写入

impl_->OnTransportCanWrite();  
void QuartcSession::OnTransportCanWrite() {
  connection()->writer()->SetWritable();
  if (HasDataToWrite()) {
    connection()->OnCanWrite();
  }
}

跟进一下这个函数
connection()->OnCanWrite();

void QuicConnection::OnCanWrite() {
  DCHECK(!writer_->IsWriteBlocked());

  // TODO(wub): Deprecate this histogram once crbug.com/818040 is fixed.
  if (!queued_packets_.empty() &&
      queued_packets_.front().packet_number <
          sent_packet_manager_.GetLargestSentPacket()) {
//    UMA_HISTOGRAM_BOOLEAN(
//        "Net.QuicSession.WriteOutOfOrderQueuedPacketAfterClose", !connected_);
  }

  WriteQueuedPackets();
  if (!session_decides_what_to_write()) {
    WritePendingRetransmissions();
  }

  // Sending queued packets may have caused the socket to become write blocked,
  // or the congestion manager to prohibit sending.  If we've sent everything
  // we had queued and we're still not blocked, let the visitor know it can
  // write more.
  if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
    return;
  }

  {
    ScopedPacketFlusher flusher(this, SEND_ACK_IF_QUEUED);
    visitor_->OnCanWrite();
    visitor_->PostProcessAfterData();
  }

  if (GetQuicReloadableFlag(quic_unified_send_alarm)) {
    // After the visitor writes, it may have caused the socket to become write
    // blocked or the congestion manager to prohibit sending, so check again.
    if (visitor_->WillingAndAbleToWrite() && !send_alarm_->IsSet() &&
        CanWrite(HAS_RETRANSMITTABLE_DATA)) {
      // We're not write blocked, but some stream didn't write out all of its
      // bytes. Register for 'immediate' resumption so we'll keep writing after
      // other connections and events have had a chance to use the thread.
      send_alarm_->Set(clock_->ApproximateNow());
    }
  } else {
    // After the visitor writes, it may have caused the socket to become write
    // blocked or the congestion manager to prohibit sending, so check again.
    if (visitor_->WillingAndAbleToWrite() && !resume_writes_alarm_->IsSet() &&
        CanWrite(HAS_RETRANSMITTABLE_DATA)) {
      // We're not write blocked, but some stream didn't write out all of its
      // bytes. Register for 'immediate' resumption so we'll keep writing after
      // other connections and events have had a chance to use the thread.
      resume_writes_alarm_->Set(clock_->ApproximateNow());
    }
  }
}

void QuicConnection::WriteIfNotBlocked() {
  if (!writer_->IsWriteBlocked()) {
    OnCanWrite();
  }
}

void QuicConnection::WriteAndBundleAcksIfNotBlocked() {
  if (!writer_->IsWriteBlocked()) {
    ScopedPacketFlusher flusher(this, SEND_ACK_IF_QUEUED);
    if (GetQuicReloadableFlag(quic_is_write_blocked)) {
      // TODO(ianswett): Merge OnCanWrite and WriteIfNotBlocked when deprecating
      // this flag.
      QUIC_FLAG_COUNT(quic_reloadable_flag_quic_is_write_blocked);
      WriteIfNotBlocked();
    } else {
      OnCanWrite();
    }
  }
}

bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
  if (perspective_ == Perspective::IS_SERVER && self_address_.IsInitialized() &&
      last_packet_destination_address_.IsInitialized() &&
      self_address_ != last_packet_destination_address_) {
    // Allow change between pure IPv4 and equivalent mapped IPv4 address.
    if (self_address_.port() != last_packet_destination_address_.port() ||
        self_address_.host().Normalized() !=
            last_packet_destination_address_.host().Normalized()) {
      if (!visitor_->AllowSelfAddressChange()) {
        CloseConnection(
            QUIC_ERROR_MIGRATING_ADDRESS,
            "Self address migration is not supported at the server.",
            ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
        return false;
      }
    }
    self_address_ = last_packet_destination_address_;
  }

  if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
    QUIC_FLAG_COUNT_N(quic_restart_flag_quic_enable_accept_random_ipn, 2, 2);
    // Configured to accept any packet number in range 1...0x7fffffff
    // as initial packet number.
    if (last_header_.packet_number != 0) {
      // The last packet's number is not 0. Ensure that this packet
      // is reasonably close to where it should be.
      if (!Near(header.packet_number, last_header_.packet_number)) {
        QUIC_DLOG(INFO) << ENDPOINT << "Packet " << header.packet_number
                        << " out of bounds.  Discarding";
        CloseConnection(QUIC_INVALID_PACKET_HEADER,
                        "Packet number out of bounds.",
                        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
        return false;
      }
    } else {
      // The "last packet's number" is 0, meaning that this packet is the first
      // one received. Ensure it is in range 1..kMaxRandomInitialPacketNumber,
      // inclusive.
      if ((header.packet_number == 0) ||
          (header.packet_number > kMaxRandomInitialPacketNumber)) {
        // packet number is bad.
        QUIC_DLOG(INFO) << ENDPOINT << "Initial packet " << header.packet_number
                        << " out of bounds.  Discarding";
        CloseConnection(QUIC_INVALID_PACKET_HEADER,
                        "Initial packet number out of bounds.",
                        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
        return false;
      }
    }
  } else {  //  if (FLAGS_quic_reloadable_flag_quic_accept_random_ipn) {
    // Count those that would have been accepted if FLAGS..random_ipn
    // were true -- to detect/diagnose potential issues prior to
    // enabling the flag.
    if ((header.packet_number > 1) &&
        (header.packet_number <= kMaxRandomInitialPacketNumber)) {
      QUIC_CODE_COUNT_N(had_possibly_random_ipn, 2, 2);
    }

    if (!Near(header.packet_number, last_header_.packet_number)) {
      QUIC_DLOG(INFO) << ENDPOINT << "Packet " << header.packet_number
                      << " out of bounds.  Discarding";
      CloseConnection(QUIC_INVALID_PACKET_HEADER,
                      "Packet number out of bounds.",
                      ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
      return false;
    }
  }

  if (version_negotiation_state_ != NEGOTIATED_VERSION) {
    if (perspective_ == Perspective::IS_CLIENT) {
      DCHECK(!header.version_flag);
      // If the client gets a packet without the version flag from the server
      // it should stop sending version since the version negotiation is done.
      packet_generator_.StopSendingVersion();
      version_negotiation_state_ = NEGOTIATED_VERSION;
      visitor_->OnSuccessfulVersionNegotiation(version());
      if (debug_visitor_ != nullptr) {
        debug_visitor_->OnSuccessfulVersionNegotiation(version());
      }
    } else if (!negotiate_version_early_) {
      if (!header.version_flag) {
        // Packets should have the version flag till version negotiation is
        // done.
        QuicString error_details =
            QuicStrCat(ENDPOINT, "Packet ", header.packet_number,
                       " without version flag before version negotiated.");
        QUIC_DLOG(WARNING) << error_details;
        CloseConnection(QUIC_INVALID_VERSION, error_details,
                        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
        return false;
      } else {
        DCHECK_EQ(header.version, version());
        version_negotiation_state_ = NEGOTIATED_VERSION;
        visitor_->OnSuccessfulVersionNegotiation(version());
        if (debug_visitor_ != nullptr) {
          debug_visitor_->OnSuccessfulVersionNegotiation(version());
        }
      }
    }
  }

跟进一下CreateNewUdpSocket()


int QuicSocketEntry::CreateNewUdpSocket()
{
    if (udpSocket_) {
        errno = EINVAL;
        return -1;
    }
//这就类似与udpsocket中的socket()函数  返回一个套接字
    int fd = ::socket(AF_INET, SOCK_DGRAM, 0);
    auto socket = EntryBase::GetFdManager().Get(sock);
    if (fd == -1) return -1;

    return SetUdpSocket(fd);
}

跟进一下这个函数 写出队列数据

  WriteQueuedPackets();
void QuicConnection::WriteQueuedPackets() {
  DCHECK(!writer_->IsWriteBlocked());//判断是否阻塞

  if (pending_version_negotiation_packet_) {
    SendVersionNegotiationPacket();//发送版本协商的包
    /*
    在quic_connection中将包发出去
WriteResult result = writer_->WritePacket(
      version_packet->data(), version_packet->length(), self_address().host(),
      peer_address(), per_packet_options_);//将报发送成出去

*/
  }

//  UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.NumQueuedPacketsBeforeWrite",
//                            queued_packets_.size());
  if (GetQuicReloadableFlag(quic_fix_write_out_of_order_queued_packet_crash)) {
    while (!queued_packets_.empty()) {
      QUIC_FLAG_COUNT(
          quic_reloadable_flag_quic_fix_write_out_of_order_queued_packet_crash);
      // WritePacket() can potentially clear all queued packets, so we need to
      // save the first queued packet to a local variable before calling it.
      SerializedPacket packet(std::move(queued_packets_.front()));
      queued_packets_.pop_front();

      const bool write_result = WritePacket(&packet);

      if (connected_ && !write_result) {
        // Write failed but connection is open, re-insert |packet| into the
        // front of the queue, it will be retried later.
        queued_packets_.emplace_front(std::move(packet));
        break;
      }

      delete[] packet.encrypted_buffer;
      ClearSerializedPacket(&packet);
      if (!connected_) {
        DCHECK(queued_packets_.empty()) << "Queued packets should have been "
                                           "cleared while closing connection";
        break;
      }

      // Continue to send the next packet in queue.
    }
  } else {
    QueuedPacketList::iterator packet_iterator = queued_packets_.begin();
    while (packet_iterator != queued_packets_.end() &&
           WritePacket(&(*packet_iterator))) {
      delete[] packet_iterator->encrypted_buffer;
      ClearSerializedPacket(&(*packet_iterator));
      packet_iterator = queued_packets_.erase(packet_iterator);
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值