blob: ae01817eeaf07dbd4c4a2cc4b58ee066821213c3 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "quiche/common/masque/connect_udp_datagram_payload.h"
#include <cstdint>
#include <memory>
#include <utility>
#include "absl/strings/string_view.h"
#include "quiche/common/platform/api/quiche_bug_tracker.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/quiche_data_reader.h"
#include "quiche/common/quiche_data_writer.h"
namespace quiche {
// static
std::unique_ptr<ConnectUdpDatagramPayload> ConnectUdpDatagramPayload::Parse(
absl::string_view datagram_payload) {
QuicheDataReader data_reader(datagram_payload);
uint64_t context_id;
if (!data_reader.ReadVarInt62(&context_id)) {
QUICHE_DVLOG(1) << "Could not parse malformed UDP proxy payload";
return nullptr;
}
if (ContextId{context_id} == ConnectUdpDatagramUdpPacketPayload::kContextId) {
return std::make_unique<ConnectUdpDatagramUdpPacketPayload>(
data_reader.ReadRemainingPayload());
} else {
return std::make_unique<ConnectUdpDatagramUnknownPayload>(
ContextId{context_id}, data_reader.ReadRemainingPayload());
}
}
std::string ConnectUdpDatagramPayload::Serialize() const {
std::string buffer(SerializedLength(), '\0');
QuicheDataWriter writer(buffer.size(), buffer.data());
bool result = SerializeTo(writer);
QUICHE_DCHECK(result);
QUICHE_DCHECK_EQ(writer.remaining(), 0u);
return buffer;
}
ConnectUdpDatagramUdpPacketPayload::ConnectUdpDatagramUdpPacketPayload(
absl::string_view udp_packet)
: udp_packet_(udp_packet) {}
ConnectUdpDatagramPayload::ContextId
ConnectUdpDatagramUdpPacketPayload::GetContextId() const {
return kContextId;
}
ConnectUdpDatagramPayload::Type ConnectUdpDatagramUdpPacketPayload::GetType()
const {
return Type::kUdpPacket;
}
absl::string_view ConnectUdpDatagramUdpPacketPayload::GetUdpProxyingPayload()
const {
return udp_packet_;
}
size_t ConnectUdpDatagramUdpPacketPayload::SerializedLength() const {
return udp_packet_.size() +
QuicheDataWriter::GetVarInt62Len(uint64_t{kContextId});
}
bool ConnectUdpDatagramUdpPacketPayload::SerializeTo(
QuicheDataWriter& writer) const {
if (!writer.WriteVarInt62(uint64_t{kContextId})) {
return false;
}
if (!writer.WriteStringPiece(udp_packet_)) {
return false;
}
return true;
}
ConnectUdpDatagramUnknownPayload::ConnectUdpDatagramUnknownPayload(
ContextId context_id, absl::string_view udp_proxying_payload)
: context_id_(context_id), udp_proxying_payload_(udp_proxying_payload) {
if (context_id == ConnectUdpDatagramUdpPacketPayload::kContextId) {
QUICHE_BUG(udp_proxy_unknown_payload_udp_context)
<< "ConnectUdpDatagramUnknownPayload created with UDP packet context "
"type (0). Should instead create a "
"ConnectUdpDatagramUdpPacketPayload.";
}
}
ConnectUdpDatagramPayload::ContextId
ConnectUdpDatagramUnknownPayload::GetContextId() const {
return context_id_;
}
ConnectUdpDatagramPayload::Type ConnectUdpDatagramUnknownPayload::GetType()
const {
return Type::kUnknown;
}
absl::string_view ConnectUdpDatagramUnknownPayload::GetUdpProxyingPayload()
const {
return udp_proxying_payload_;
}
size_t ConnectUdpDatagramUnknownPayload::SerializedLength() const {
return udp_proxying_payload_.size() +
QuicheDataWriter::GetVarInt62Len(uint64_t{context_id_});
}
bool ConnectUdpDatagramUnknownPayload::SerializeTo(
QuicheDataWriter& writer) const {
if (!writer.WriteVarInt62(uint64_t{context_id_})) {
return false;
}
if (!writer.WriteStringPiece(udp_proxying_payload_)) {
return false;
}
return true;
}
} // namespace quiche