// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved #include namespace { void addQuicSimpleFrameToEvent( quic::QLogPacketEvent* event, const quic::QuicSimpleFrame& simpleFrame) { switch (simpleFrame.type()) { case quic::QuicSimpleFrame::Type::StopSendingFrame: { const quic::StopSendingFrame& frame = *simpleFrame.asStopSendingFrame(); event->frames.push_back(std::make_unique( frame.streamId, frame.errorCode)); break; } case quic::QuicSimpleFrame::Type::PathChallengeFrame: { const quic::PathChallengeFrame& frame = *simpleFrame.asPathChallengeFrame(); event->frames.push_back( std::make_unique(frame.pathData)); break; } case quic::QuicSimpleFrame::Type::PathResponseFrame: { const quic::PathResponseFrame& frame = *simpleFrame.asPathResponseFrame(); event->frames.push_back( std::make_unique(frame.pathData)); break; } case quic::QuicSimpleFrame::Type::NewConnectionIdFrame: { const quic::NewConnectionIdFrame& frame = *simpleFrame.asNewConnectionIdFrame(); event->frames.push_back(std::make_unique( frame.sequenceNumber, frame.token)); break; } case quic::QuicSimpleFrame::Type::MaxStreamsFrame: { const quic::MaxStreamsFrame& frame = *simpleFrame.asMaxStreamsFrame(); event->frames.push_back(std::make_unique( frame.maxStreams, frame.isForBidirectional)); break; } case quic::QuicSimpleFrame::Type::RetireConnectionIdFrame: { const quic::RetireConnectionIdFrame& frame = *simpleFrame.asRetireConnectionIdFrame(); event->frames.push_back( std::make_unique( frame.sequenceNumber)); break; } case quic::QuicSimpleFrame::Type::HandshakeDoneFrame: { event->frames.push_back(std::make_unique()); break; } case quic::QuicSimpleFrame::Type::KnobFrame: { const quic::KnobFrame& frame = *simpleFrame.asKnobFrame(); event->frames.push_back(std::make_unique( frame.knobSpace, frame.id, frame.blob->length())); break; } case quic::QuicSimpleFrame::Type::AckFrequencyFrame: { const quic::AckFrequencyFrame& frame = *simpleFrame.asAckFrequencyFrame(); event->frames.push_back(std::make_unique( frame.sequenceNumber, frame.packetTolerance, frame.updateMaxAckDelay, frame.ignoreOrder)); break; } } } } // namespace namespace quic { std::unique_ptr BaseQLogger::createPacketEvent( const RegularQuicPacket& regularPacket, uint64_t packetSize) { auto event = std::make_unique(); event->refTime = std::chrono::duration_cast( std::chrono::steady_clock::now().time_since_epoch()); event->packetSize = packetSize; event->eventType = QLogEventType::PacketReceived; const ShortHeader* shortHeader = regularPacket.header.asShort(); if (shortHeader) { event->packetType = kShortHeaderPacketType.toString(); } else { event->packetType = toQlogString(regularPacket.header.asLong()->getHeaderType()).str(); } if (event->packetType != toString(LongHeader::Types::Retry)) { // A Retry packet does not include a packet number. event->packetNum = regularPacket.header.getPacketSequenceNum(); } uint64_t numPaddingFrames = 0; // looping through the packet to store logs created from frames in the packet for (const auto& quicFrame : regularPacket.frames) { switch (quicFrame.type()) { case QuicFrame::Type::PaddingFrame: { ++numPaddingFrames; break; } case QuicFrame::Type::RstStreamFrame: { const auto& frame = *quicFrame.asRstStreamFrame(); event->frames.push_back(std::make_unique( frame.streamId, frame.errorCode, frame.offset)); break; } case QuicFrame::Type::ConnectionCloseFrame: { const auto& frame = *quicFrame.asConnectionCloseFrame(); event->frames.push_back(std::make_unique( frame.errorCode, frame.reasonPhrase, frame.closingFrameType)); break; } case QuicFrame::Type::MaxDataFrame: { const auto& frame = *quicFrame.asMaxDataFrame(); event->frames.push_back( std::make_unique(frame.maximumData)); break; } case QuicFrame::Type::MaxStreamDataFrame: { const auto& frame = *quicFrame.asMaxStreamDataFrame(); event->frames.push_back(std::make_unique( frame.streamId, frame.maximumData)); break; } case QuicFrame::Type::DataBlockedFrame: { const auto& frame = *quicFrame.asDataBlockedFrame(); event->frames.push_back( std::make_unique(frame.dataLimit)); break; } case QuicFrame::Type::StreamDataBlockedFrame: { const auto& frame = *quicFrame.asStreamDataBlockedFrame(); event->frames.push_back(std::make_unique( frame.streamId, frame.dataLimit)); break; } case QuicFrame::Type::StreamsBlockedFrame: { const auto& frame = *quicFrame.asStreamsBlockedFrame(); event->frames.push_back(std::make_unique( frame.streamLimit, frame.isForBidirectional)); break; } case QuicFrame::Type::ReadAckFrame: { const auto& frame = *quicFrame.asReadAckFrame(); event->frames.push_back( std::make_unique(frame.ackBlocks, frame.ackDelay)); break; } case QuicFrame::Type::ReadStreamFrame: { const auto& frame = *quicFrame.asReadStreamFrame(); event->frames.push_back(std::make_unique( frame.streamId, frame.offset, frame.data->length(), frame.fin)); break; } case QuicFrame::Type::ReadCryptoFrame: { const auto& frame = *quicFrame.asReadCryptoFrame(); event->frames.push_back(std::make_unique( frame.offset, frame.data->length())); break; } case QuicFrame::Type::ReadNewTokenFrame: { event->frames.push_back(std::make_unique()); break; } case QuicFrame::Type::PingFrame: { event->frames.push_back(std::make_unique()); break; } case QuicFrame::Type::QuicSimpleFrame: { const auto& simpleFrame = *quicFrame.asQuicSimpleFrame(); addQuicSimpleFrameToEvent(event.get(), simpleFrame); break; } case QuicFrame::Type::NoopFrame: { break; } case QuicFrame::Type::DatagramFrame: { // TODO break; } } } if (numPaddingFrames > 0) { event->frames.push_back( std::make_unique(numPaddingFrames)); } return event; } std::unique_ptr BaseQLogger::createPacketEvent( const RegularQuicWritePacket& writePacket, uint64_t packetSize) { auto event = std::make_unique(); event->refTime = std::chrono::duration_cast( std::chrono::steady_clock::now().time_since_epoch()); event->packetNum = writePacket.header.getPacketSequenceNum(); event->packetSize = packetSize; event->eventType = QLogEventType::PacketSent; const ShortHeader* shortHeader = writePacket.header.asShort(); if (shortHeader) { event->packetType = kShortHeaderPacketType.toString(); } else { event->packetType = toQlogString(writePacket.header.asLong()->getHeaderType()).str(); } uint64_t numPaddingFrames = 0; // looping through the packet to store logs created from frames in the packet for (const auto& quicFrame : writePacket.frames) { switch (quicFrame.type()) { case QuicWriteFrame::Type::PaddingFrame: ++numPaddingFrames; break; case QuicWriteFrame::Type::RstStreamFrame: { const RstStreamFrame& frame = *quicFrame.asRstStreamFrame(); event->frames.push_back(std::make_unique( frame.streamId, frame.errorCode, frame.offset)); break; } case QuicWriteFrame::Type::ConnectionCloseFrame: { const ConnectionCloseFrame& frame = *quicFrame.asConnectionCloseFrame(); event->frames.push_back(std::make_unique( frame.errorCode, frame.reasonPhrase, frame.closingFrameType)); break; } case QuicWriteFrame::Type::MaxDataFrame: { const MaxDataFrame& frame = *quicFrame.asMaxDataFrame(); event->frames.push_back( std::make_unique(frame.maximumData)); break; } case QuicWriteFrame::Type::MaxStreamDataFrame: { const MaxStreamDataFrame& frame = *quicFrame.asMaxStreamDataFrame(); event->frames.push_back(std::make_unique( frame.streamId, frame.maximumData)); break; } case QuicWriteFrame::Type::StreamsBlockedFrame: { const StreamsBlockedFrame& frame = *quicFrame.asStreamsBlockedFrame(); event->frames.push_back(std::make_unique( frame.streamLimit, frame.isForBidirectional)); break; } case QuicWriteFrame::Type::DataBlockedFrame: { const DataBlockedFrame& frame = *quicFrame.asDataBlockedFrame(); event->frames.push_back( std::make_unique(frame.dataLimit)); break; } case QuicWriteFrame::Type::StreamDataBlockedFrame: { const StreamDataBlockedFrame& frame = *quicFrame.asStreamDataBlockedFrame(); event->frames.push_back(std::make_unique( frame.streamId, frame.dataLimit)); break; } case QuicWriteFrame::Type::WriteAckFrame: { const WriteAckFrame& frame = *quicFrame.asWriteAckFrame(); event->frames.push_back(std::make_unique( frame.ackBlocks, frame.ackDelay)); break; } case QuicWriteFrame::Type::WriteStreamFrame: { const WriteStreamFrame& frame = *quicFrame.asWriteStreamFrame(); event->frames.push_back(std::make_unique( frame.streamId, frame.offset, frame.len, frame.fin)); break; } case QuicWriteFrame::Type::WriteCryptoFrame: { const WriteCryptoFrame& frame = *quicFrame.asWriteCryptoFrame(); event->frames.push_back( std::make_unique(frame.offset, frame.len)); break; } case QuicWriteFrame::Type::QuicSimpleFrame: { const QuicSimpleFrame& simpleFrame = *quicFrame.asQuicSimpleFrame(); addQuicSimpleFrameToEvent(event.get(), simpleFrame); break; } case QuicWriteFrame::Type::NoopFrame: { break; } case QuicWriteFrame::Type::DatagramFrame: { // TODO break; } default: { break; } } } if (numPaddingFrames > 0) { event->frames.push_back( std::make_unique(numPaddingFrames)); } return event; } std::unique_ptr BaseQLogger::createPacketEvent( const VersionNegotiationPacket& versionPacket, uint64_t packetSize, bool isPacketRecvd) { auto event = std::make_unique(); event->refTime = std::chrono::duration_cast( std::chrono::steady_clock::now().time_since_epoch()); event->packetSize = packetSize; event->eventType = isPacketRecvd ? QLogEventType::PacketReceived : QLogEventType::PacketSent; event->packetType = kVersionNegotiationPacketType; event->versionLog = std::make_unique( VersionNegotiationLog(versionPacket.versions)); return event; } std::unique_ptr BaseQLogger::createPacketEvent( const RetryPacket& retryPacket, uint64_t packetSize, bool isPacketRecvd) { auto event = std::make_unique(); event->refTime = std::chrono::duration_cast( std::chrono::steady_clock::now().time_since_epoch()); event->packetSize = packetSize; event->tokenSize = retryPacket.header.getToken().size(); event->eventType = isPacketRecvd ? QLogEventType::PacketReceived : QLogEventType::PacketSent; event->packetType = toQlogString(retryPacket.header.getHeaderType()).str(); return event; } } // namespace quic