1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/common/masque/connect_udp_datagram_payload.h"
6 
7 #include <cstdint>
8 #include <memory>
9 #include <utility>
10 
11 #include "absl/strings/string_view.h"
12 #include "quiche/common/platform/api/quiche_bug_tracker.h"
13 #include "quiche/common/platform/api/quiche_logging.h"
14 #include "quiche/common/quiche_data_reader.h"
15 #include "quiche/common/quiche_data_writer.h"
16 
17 namespace quiche {
18 
19 // static
Parse(absl::string_view datagram_payload)20 std::unique_ptr<ConnectUdpDatagramPayload> ConnectUdpDatagramPayload::Parse(
21     absl::string_view datagram_payload) {
22   QuicheDataReader data_reader(datagram_payload);
23 
24   uint64_t context_id;
25   if (!data_reader.ReadVarInt62(&context_id)) {
26     QUICHE_DVLOG(1) << "Could not parse malformed UDP proxy payload";
27     return nullptr;
28   }
29 
30   if (ContextId{context_id} == ConnectUdpDatagramUdpPacketPayload::kContextId) {
31     return std::make_unique<ConnectUdpDatagramUdpPacketPayload>(
32         data_reader.ReadRemainingPayload());
33   } else {
34     return std::make_unique<ConnectUdpDatagramUnknownPayload>(
35         ContextId{context_id}, data_reader.ReadRemainingPayload());
36   }
37 }
38 
Serialize() const39 std::string ConnectUdpDatagramPayload::Serialize() const {
40   std::string buffer(SerializedLength(), '\0');
41   QuicheDataWriter writer(buffer.size(), buffer.data());
42 
43   bool result = SerializeTo(writer);
44   QUICHE_DCHECK(result);
45   QUICHE_DCHECK_EQ(writer.remaining(), 0u);
46 
47   return buffer;
48 }
49 
ConnectUdpDatagramUdpPacketPayload(absl::string_view udp_packet)50 ConnectUdpDatagramUdpPacketPayload::ConnectUdpDatagramUdpPacketPayload(
51     absl::string_view udp_packet)
52     : udp_packet_(udp_packet) {}
53 
54 ConnectUdpDatagramPayload::ContextId
GetContextId() const55 ConnectUdpDatagramUdpPacketPayload::GetContextId() const {
56   return kContextId;
57 }
58 
GetType() const59 ConnectUdpDatagramPayload::Type ConnectUdpDatagramUdpPacketPayload::GetType()
60     const {
61   return Type::kUdpPacket;
62 }
63 
GetUdpProxyingPayload() const64 absl::string_view ConnectUdpDatagramUdpPacketPayload::GetUdpProxyingPayload()
65     const {
66   return udp_packet_;
67 }
68 
SerializedLength() const69 size_t ConnectUdpDatagramUdpPacketPayload::SerializedLength() const {
70   return udp_packet_.size() +
71          QuicheDataWriter::GetVarInt62Len(uint64_t{kContextId});
72 }
73 
SerializeTo(QuicheDataWriter & writer) const74 bool ConnectUdpDatagramUdpPacketPayload::SerializeTo(
75     QuicheDataWriter& writer) const {
76   if (!writer.WriteVarInt62(uint64_t{kContextId})) {
77     return false;
78   }
79 
80   if (!writer.WriteStringPiece(udp_packet_)) {
81     return false;
82   }
83 
84   return true;
85 }
86 
ConnectUdpDatagramUnknownPayload(ContextId context_id,absl::string_view udp_proxying_payload)87 ConnectUdpDatagramUnknownPayload::ConnectUdpDatagramUnknownPayload(
88     ContextId context_id, absl::string_view udp_proxying_payload)
89     : context_id_(context_id), udp_proxying_payload_(udp_proxying_payload) {
90   if (context_id == ConnectUdpDatagramUdpPacketPayload::kContextId) {
91     QUICHE_BUG(udp_proxy_unknown_payload_udp_context)
92         << "ConnectUdpDatagramUnknownPayload created with UDP packet context "
93            "type (0). Should instead create a "
94            "ConnectUdpDatagramUdpPacketPayload.";
95   }
96 }
97 
98 ConnectUdpDatagramPayload::ContextId
GetContextId() const99 ConnectUdpDatagramUnknownPayload::GetContextId() const {
100   return context_id_;
101 }
102 
GetType() const103 ConnectUdpDatagramPayload::Type ConnectUdpDatagramUnknownPayload::GetType()
104     const {
105   return Type::kUnknown;
106 }
GetUdpProxyingPayload() const107 absl::string_view ConnectUdpDatagramUnknownPayload::GetUdpProxyingPayload()
108     const {
109   return udp_proxying_payload_;
110 }
111 
SerializedLength() const112 size_t ConnectUdpDatagramUnknownPayload::SerializedLength() const {
113   return udp_proxying_payload_.size() +
114          QuicheDataWriter::GetVarInt62Len(uint64_t{context_id_});
115 }
116 
SerializeTo(QuicheDataWriter & writer) const117 bool ConnectUdpDatagramUnknownPayload::SerializeTo(
118     QuicheDataWriter& writer) const {
119   if (!writer.WriteVarInt62(uint64_t{context_id_})) {
120     return false;
121   }
122 
123   if (!writer.WriteStringPiece(udp_proxying_payload_)) {
124     return false;
125   }
126 
127   return true;
128 }
129 
130 }  // namespace quiche
131