首先会初始化结构体的地址
//初始化地址 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);
}
}
}