blob: 0a724eed599bbf5f8b8c9bd1b842a19349303a0b [file] [log] [blame]
// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/quic/core/frames/quic_frame.h"
#include "net/quic/core/quic_constants.h"
#include "net/quic/platform/api/quic_bug_tracker.h"
#include "net/quic/platform/api/quic_logging.h"
using std::string;
namespace net {
QuicFrame::QuicFrame() {}
QuicFrame::QuicFrame(QuicPaddingFrame padding_frame)
: type(PADDING_FRAME), padding_frame(padding_frame) {}
QuicFrame::QuicFrame(QuicStreamFrame* stream_frame)
: type(STREAM_FRAME), stream_frame(stream_frame) {}
QuicFrame::QuicFrame(QuicAckFrame* frame) : type(ACK_FRAME), ack_frame(frame) {}
QuicFrame::QuicFrame(QuicMtuDiscoveryFrame frame)
: type(MTU_DISCOVERY_FRAME), mtu_discovery_frame(frame) {}
QuicFrame::QuicFrame(QuicStopWaitingFrame* frame)
: type(STOP_WAITING_FRAME), stop_waiting_frame(frame) {}
QuicFrame::QuicFrame(QuicPingFrame frame)
: type(PING_FRAME), ping_frame(frame) {}
QuicFrame::QuicFrame(QuicRstStreamFrame* frame)
: type(RST_STREAM_FRAME), rst_stream_frame(frame) {}
QuicFrame::QuicFrame(QuicConnectionCloseFrame* frame)
: type(CONNECTION_CLOSE_FRAME), connection_close_frame(frame) {}
QuicFrame::QuicFrame(QuicGoAwayFrame* frame)
: type(GOAWAY_FRAME), goaway_frame(frame) {}
QuicFrame::QuicFrame(QuicWindowUpdateFrame* frame)
: type(WINDOW_UPDATE_FRAME), window_update_frame(frame) {}
QuicFrame::QuicFrame(QuicBlockedFrame* frame)
: type(BLOCKED_FRAME), blocked_frame(frame) {}
void DeleteFrames(QuicFrames* frames) {
for (QuicFrame& frame : *frames) {
DeleteFrame(&frame);
}
frames->clear();
}
void DeleteFrame(QuicFrame* frame) {
switch (frame->type) {
// Frames smaller than a pointer are inlined, so don't need to be deleted.
case PADDING_FRAME:
case MTU_DISCOVERY_FRAME:
case PING_FRAME:
break;
case STREAM_FRAME:
delete frame->stream_frame;
break;
case ACK_FRAME:
delete frame->ack_frame;
break;
case STOP_WAITING_FRAME:
delete frame->stop_waiting_frame;
break;
case RST_STREAM_FRAME:
delete frame->rst_stream_frame;
break;
case CONNECTION_CLOSE_FRAME:
delete frame->connection_close_frame;
break;
case GOAWAY_FRAME:
delete frame->goaway_frame;
break;
case BLOCKED_FRAME:
delete frame->blocked_frame;
break;
case WINDOW_UPDATE_FRAME:
delete frame->window_update_frame;
break;
case NUM_FRAME_TYPES:
DCHECK(false) << "Cannot delete type: " << frame->type;
}
}
void RemoveFramesForStream(QuicFrames* frames, QuicStreamId stream_id) {
QuicFrames::iterator it = frames->begin();
while (it != frames->end()) {
if (it->type != STREAM_FRAME || it->stream_frame->stream_id != stream_id) {
++it;
continue;
}
delete it->stream_frame;
it = frames->erase(it);
}
}
bool IsControlFrame(QuicFrameType type) {
switch (type) {
case RST_STREAM_FRAME:
case GOAWAY_FRAME:
case WINDOW_UPDATE_FRAME:
case BLOCKED_FRAME:
case PING_FRAME:
return true;
default:
return false;
}
}
QuicControlFrameId GetControlFrameId(const QuicFrame& frame) {
switch (frame.type) {
case RST_STREAM_FRAME:
return frame.rst_stream_frame->control_frame_id;
case GOAWAY_FRAME:
return frame.goaway_frame->control_frame_id;
case WINDOW_UPDATE_FRAME:
return frame.window_update_frame->control_frame_id;
case BLOCKED_FRAME:
return frame.blocked_frame->control_frame_id;
case PING_FRAME:
return frame.ping_frame.control_frame_id;
default:
return kInvalidControlFrameId;
}
}
void SetControlFrameId(QuicControlFrameId control_frame_id, QuicFrame* frame) {
switch (frame->type) {
case RST_STREAM_FRAME:
frame->rst_stream_frame->control_frame_id = control_frame_id;
return;
case GOAWAY_FRAME:
frame->goaway_frame->control_frame_id = control_frame_id;
return;
case WINDOW_UPDATE_FRAME:
frame->window_update_frame->control_frame_id = control_frame_id;
return;
case BLOCKED_FRAME:
frame->blocked_frame->control_frame_id = control_frame_id;
return;
case PING_FRAME:
frame->ping_frame.control_frame_id = control_frame_id;
return;
default:
QUIC_BUG
<< "Try to set control frame id of a frame without control frame id";
}
}
QuicFrame CopyRetransmittableControlFrame(const QuicFrame& frame) {
QuicFrame copy;
switch (frame.type) {
case RST_STREAM_FRAME:
copy = QuicFrame(new QuicRstStreamFrame(*frame.rst_stream_frame));
break;
case GOAWAY_FRAME:
copy = QuicFrame(new QuicGoAwayFrame(*frame.goaway_frame));
break;
case WINDOW_UPDATE_FRAME:
copy = QuicFrame(new QuicWindowUpdateFrame(*frame.window_update_frame));
break;
case BLOCKED_FRAME:
copy = QuicFrame(new QuicBlockedFrame(*frame.blocked_frame));
break;
case PING_FRAME:
copy = QuicFrame(QuicPingFrame(frame.ping_frame.control_frame_id));
break;
default:
QUIC_BUG << "Try to copy a non-retransmittable control frame: " << frame;
copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
break;
}
return copy;
}
std::ostream& operator<<(std::ostream& os, const QuicFrame& frame) {
switch (frame.type) {
case PADDING_FRAME: {
os << "type { PADDING_FRAME } " << frame.padding_frame;
break;
}
case RST_STREAM_FRAME: {
os << "type { RST_STREAM_FRAME } " << *(frame.rst_stream_frame);
break;
}
case CONNECTION_CLOSE_FRAME: {
os << "type { CONNECTION_CLOSE_FRAME } "
<< *(frame.connection_close_frame);
break;
}
case GOAWAY_FRAME: {
os << "type { GOAWAY_FRAME } " << *(frame.goaway_frame);
break;
}
case WINDOW_UPDATE_FRAME: {
os << "type { WINDOW_UPDATE_FRAME } " << *(frame.window_update_frame);
break;
}
case BLOCKED_FRAME: {
os << "type { BLOCKED_FRAME } " << *(frame.blocked_frame);
break;
}
case STREAM_FRAME: {
os << "type { STREAM_FRAME } " << *(frame.stream_frame);
break;
}
case ACK_FRAME: {
os << "type { ACK_FRAME } " << *(frame.ack_frame);
break;
}
case STOP_WAITING_FRAME: {
os << "type { STOP_WAITING_FRAME } " << *(frame.stop_waiting_frame);
break;
}
case PING_FRAME: {
os << "type { PING_FRAME } " << frame.ping_frame;
break;
}
case MTU_DISCOVERY_FRAME: {
os << "type { MTU_DISCOVERY_FRAME } ";
break;
}
default: {
QUIC_LOG(ERROR) << "Unknown frame type: " << frame.type;
break;
}
}
return os;
}
} // namespace net