第一个问题,客户端什么时候发送CHLO消息?
void QuicClientBase::StartConnect(){
InitializeSession();//这个被子类覆盖
}
void QuicSpdyClientBase::InitializeSession() {
client_session()->Initialize();//create crypto_stream_
client_session()->CryptoConnect();
}
void QuicSpdyClientSession::CryptoConnect() {
DCHECK(flow_controller());
crypto_stream_->CryptoConnect();
}
bool QuicCryptoClientStream::CryptoConnect() {
return handshaker_->CryptoConnect();
}
bool QuicCryptoClientHandshaker::CryptoConnect() {
next_state_ = STATE_INITIALIZE;
DoHandshakeLoop(nullptr);
return session()->connection()->connected();
}
void QuicCryptoClientHandshaker::DoHandshakeLoop(
const CryptoHandshakeMessage* in) {
QuicCryptoClientConfig::CachedState* cached =
crypto_config_->LookupOrCreate(server_id_);
QuicAsyncStatus rv = QUIC_SUCCESS;
do {
CHECK_NE(STATE_NONE, next_state_);
const State state = next_state_;
next_state_ = STATE_IDLE;
rv = QUIC_SUCCESS;
switch (state) {
case STATE_INITIALIZE:
DoInitialize(cached);
break;
case STATE_SEND_CHLO:
DoSendCHLO(cached);
return; // return waiting to hear from server.
case STATE_RECV_REJ:
DoReceiveREJ(in, cached);
break;
case STATE_VERIFY_PROOF:
rv = DoVerifyProof(cached);
break;
case STATE_VERIFY_PROOF_COMPLETE:
DoVerifyProofComplete(cached);
break;
case STATE_GET_CHANNEL_ID:
rv = DoGetChannelID(cached);
break;
case STATE_GET_CHANNEL_ID_COMPLETE:
DoGetChannelIDComplete();
break;
case STATE_RECV_SHLO:
DoReceiveSHLO(in, cached);
break;
case STATE_IDLE:
// This means that the peer sent us a message that we weren't expecting.
stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
"Handshake in idle state");
return;
case STATE_INITIALIZE_SCUP:
DoInitializeServerConfigUpdate(cached);
break;
case STATE_NONE:
QUIC_NOTREACHED();
return; // We are done.
}
} while (rv != QUIC_PENDING && next_state_ != STATE_NONE);
}
void QuicCryptoClientHandshaker::DoSendCHLO(
QuicCryptoClientConfig::CachedState* cached) {
SendHandshakeMessage(out);
}
void QuicCryptoHandshaker::SendHandshakeMessage(
const CryptoHandshakeMessage& message) {
const QuicData& data = message.GetSerialized(session()->perspective());
stream_->WriteOrBufferData(QuicStringPiece(data.data(), data.length()), false,
nullptr);
}
2第二个问题,写入buffer中的数据何时被发送出去。
QuicConsumedData QuicSession::WritevData(QuicStream* stream,
QuicStreamId id,
size_t write_length,
QuicStreamOffset offset,
StreamSendingState state)
{
QuicConsumedData data =
connection_->SendStreamData(id, write_length, offset, state);
}
QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
size_t write_length,
QuicStreamOffset offset,
StreamSendingState state)
{
return packet_generator_.ConsumeData(id, write_length, offset, state);
}
QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
size_t write_length,
QuicStreamOffset offset,
StreamSendingState state)
{
packet_creator_.Flush();
}
void QuicPacketCreator::Flush()
{
SerializePacket(serialized_packet_buffer, kMaxPacketSize);
OnSerializedPacket();
}
void QuicPacketCreator::OnSerializedPacket()
{
SerializedPacket packet(std::move(packet_));//? why move
delegate_->OnSerializedPacket(&packet);
}
//serialized_packet包含了序列化之后的数据
void QuicConnection::OnSerializedPacket(SerializedPacket* serialized_packet)
{
SendOrQueuePacket(serialized_packet);
}
void QuicConnection::SendOrQueuePacket(SerializedPacket* packet)
{
if (!queued_packets_.empty() || !WritePacket(packet)){}
}
bool QuicConnection::WritePacket(SerializedPacket* packet)
{
WriteResult result = writer_->WritePacket(
packet->encrypted_buffer, encrypted_length, self_address().host(),
peer_address(), per_packet_options_);
}
//writer_->WritePacket 会调用最终的socket接口,将数据发送出去。例如下面这个子类
WriteResult QuicDefaultPacketWriter::WritePacket(
const char* buffer,
size_t buf_len,
const QuicIpAddress& self_address,
const QuicSocketAddress& peer_address,
PerPacketOptions* options) {
WriteResult result = QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
self_address, peer_address);
if (result.status == WRITE_STATUS_BLOCKED) {
write_blocked_ = true;
}
return result;
}
到这里依然有个疑问,buffer的数据被谁读取?再次看了下代码,stream_->WriteOrBufferData会将数据写入到QuicStream对象中的send_buffer_中。send_buffer_中数据是被哪个函数读取呢?是WriteStreamData。按图索骥,这次反过来分析代码,分析被调用关系。正常的调用关系则是1-2-3-4-5。
//5
//https://cs.chromium.org/chromium/src/net/third_party/quic/core/quic_stream.cc?q=WriteOrBufferData&dr=CSs&l=709
bool QuicStream::WriteStreamData(QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) {
return send_buffer_.WriteStreamData(offset, data_length, writer);
}
//4
//QuicStream::WriteStreamData is called in QuicSession
//
bool QuicSession::WriteStreamData(QuicStreamId id,
QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) {
QuicStream* stream = GetStream(id);
return stream->WriteStreamData(offset, data_length, writer);
}
//3
//QuicSession::WriteStreamData is called in QuicFramer
bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame,
bool no_stream_frame_length,
QuicDataWriter* writer)
{
if (!data_producer_->WriteStreamData(frame.stream_id, frame.offset,
frame.data_length, writer)){}
}
//2
size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
const QuicFrames& frames,
char* buffer,
size_t packet_length) {
QuicDataWriter writer(packet_length, buffer, endianness());
case STREAM_FRAME:
if (!AppendStreamFrame(*frame.stream_frame, no_stream_frame_length,
&writer)) {}
}
//1
void QuicPacketCreator::SerializePacket(char* encrypted_buffer,
size_t encrypted_buffer_len) {
size_t length = framer_->BuildDataPacket(header, queued_frames_,
encrypted_buffer, packet_size_);
}
但是,QuicFramer是QuicConnection中的一个对象,那么QuicSession是怎么传递给data_producer_的。
void QuicSession::Initialize() {
connection_->set_visitor(this);
connection_->SetSessionNotifier(this);
connection_->SetDataProducer(this);
connection_->SetFromConfig(config_);
DCHECK_EQ(kCryptoStreamId, GetMutableCryptoStream()->id());
static_stream_map_[kCryptoStreamId] = GetMutableCryptoStream();
}
void QuicConnection::SetDataProducer(
QuicStreamFrameDataProducer* data_producer) {
framer_.set_data_producer(data_producer);
}
//in quic_framer.h
void set_data_producer(QuicStreamFrameDataProducer* data_producer) {
data_producer_ = data_producer;
}