CapsuleEncoder.cpp (6351B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set sw=2 ts=8 et tw=80 : */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "nsString.h" 8 #include "nsTArray.h" 9 10 #include "Capsule.h" 11 #include "CapsuleEncoder.h" 12 13 namespace mozilla::net { 14 15 CapsuleEncoder::CapsuleEncoder() { 16 NeqoEncoder::Init(getter_AddRefs(mEncoder)); 17 MOZ_ASSERT(mEncoder); 18 } 19 20 CapsuleEncoder::~CapsuleEncoder() = default; 21 22 void CapsuleEncoder::EncodeCapsule(Capsule& aCapsule) { 23 if (aCapsule.mCapsule.is<UnknownCapsule>()) { 24 auto& value = aCapsule.mCapsule.as<UnknownCapsule>(); 25 EncodeVarint(value.mType).EncodeBufferWithVarintLen(value.mData); 26 return; 27 } 28 29 if (aCapsule.mCapsule.is<CloseWebTransportSessionCapsule>()) { 30 const auto& value = aCapsule.mCapsule.as<CloseWebTransportSessionCapsule>(); 31 EncodeVarint(value.Type()) 32 .EncodeVarint(4 + value.mReason.Length()) 33 .EncodeUint(4, value.mStatus) 34 .EncodeString(value.mReason); 35 return; 36 } 37 38 if (aCapsule.mCapsule.is<WebTransportMaxDataCapsule>()) { 39 auto& value = aCapsule.mCapsule.as<WebTransportMaxDataCapsule>(); 40 EncodeVarint(value.Type()) 41 .EncodeVarint(CapsuleEncoder::VarintLength(value.mMaxDataSize)) 42 .EncodeVarint(value.mMaxDataSize); 43 return; 44 } 45 46 if (aCapsule.mCapsule.is<WebTransportStreamDataCapsule>()) { 47 auto& value = aCapsule.mCapsule.as<WebTransportStreamDataCapsule>(); 48 uint64_t length = 49 CapsuleEncoder::VarintLength(value.mID) + value.mData.Length(); 50 EncodeVarint(value.Type()) 51 .EncodeVarint(length) 52 .EncodeVarint(value.mID) 53 .EncodeBuffer(value.mData); 54 mStreamMetadata = Some(StreamMetadata{ 55 value.mID, value.mData.Length(), 56 CapsuleEncoder::VarintLength(static_cast<uint64_t>(value.Type())) + 57 CapsuleEncoder::VarintLength(length) + 58 CapsuleEncoder::VarintLength(value.mID)}); 59 return; 60 } 61 62 if (aCapsule.mCapsule.is<WebTransportStreamsBlockedCapsule>()) { 63 auto& value = aCapsule.mCapsule.as<WebTransportStreamsBlockedCapsule>(); 64 EncodeVarint(value.Type()) 65 .EncodeVarint(CapsuleEncoder::VarintLength(value.mLimit)) 66 .EncodeVarint(value.mLimit); 67 return; 68 } 69 70 if (aCapsule.mCapsule.is<WebTransportMaxStreamsCapsule>()) { 71 auto& value = aCapsule.mCapsule.as<WebTransportMaxStreamsCapsule>(); 72 EncodeVarint(value.Type()) 73 .EncodeVarint(CapsuleEncoder::VarintLength(value.mLimit)) 74 .EncodeVarint(value.mLimit); 75 return; 76 } 77 78 if (aCapsule.mCapsule.is<WebTransportStreamDataBlockedCapsule>()) { 79 auto& value = aCapsule.mCapsule.as<WebTransportStreamDataBlockedCapsule>(); 80 EncodeVarint(value.Type()) 81 .EncodeVarint(CapsuleEncoder::VarintLength(value.mID) + 82 CapsuleEncoder::VarintLength(value.mLimit)) 83 .EncodeVarint(value.mID) 84 .EncodeVarint(value.mLimit); 85 return; 86 } 87 88 if (aCapsule.mCapsule.is<WebTransportMaxStreamDataCapsule>()) { 89 auto& value = aCapsule.mCapsule.as<WebTransportMaxStreamDataCapsule>(); 90 EncodeVarint(value.Type()) 91 .EncodeVarint(CapsuleEncoder::VarintLength(value.mID) + 92 CapsuleEncoder::VarintLength(value.mLimit)) 93 .EncodeVarint(value.mID) 94 .EncodeVarint(value.mLimit); 95 return; 96 } 97 98 if (aCapsule.mCapsule.is<WebTransportDataBlockedCapsule>()) { 99 auto& value = aCapsule.mCapsule.as<WebTransportDataBlockedCapsule>(); 100 EncodeVarint(value.Type()) 101 .EncodeVarint(CapsuleEncoder::VarintLength(value.mLimit)) 102 .EncodeVarint(value.mLimit); 103 return; 104 } 105 106 if (aCapsule.mCapsule.is<WebTransportStopSendingCapsule>()) { 107 auto& value = aCapsule.mCapsule.as<WebTransportStopSendingCapsule>(); 108 EncodeVarint(value.Type()) 109 .EncodeVarint(CapsuleEncoder::VarintLength(value.mID) + 110 CapsuleEncoder::VarintLength(value.mErrorCode)) 111 .EncodeVarint(value.mID) 112 .EncodeVarint(value.mErrorCode); 113 return; 114 } 115 116 if (aCapsule.mCapsule.is<WebTransportResetStreamCapsule>()) { 117 auto& value = aCapsule.mCapsule.as<WebTransportResetStreamCapsule>(); 118 EncodeVarint(value.Type()) 119 .EncodeVarint(CapsuleEncoder::VarintLength(value.mID) + 120 CapsuleEncoder::VarintLength(value.mErrorCode) + 121 CapsuleEncoder::VarintLength(value.mReliableSize)) 122 .EncodeVarint(value.mID) 123 .EncodeVarint(value.mErrorCode) 124 .EncodeVarint(value.mReliableSize); 125 return; 126 } 127 128 if (aCapsule.mCapsule.is<WebTransportDatagramCapsule>()) { 129 auto& value = aCapsule.mCapsule.as<WebTransportDatagramCapsule>(); 130 uint64_t length = value.mPayload.Length(); 131 EncodeVarint(value.Type()) 132 .EncodeVarint(length) 133 .EncodeBuffer(value.mPayload); 134 return; 135 } 136 } 137 138 CapsuleEncoder& CapsuleEncoder::EncodeByte(uint8_t aData) { 139 mEncoder->EncodeByte(aData); 140 return *this; 141 } 142 143 template <typename T> 144 CapsuleEncoder& CapsuleEncoder::EncodeUint(uint32_t aSize, T aValue) { 145 uint64_t value = static_cast<uint64_t>(aValue); 146 mEncoder->EncodeUint(aSize, value); 147 return *this; 148 } 149 150 template <typename T> 151 CapsuleEncoder& CapsuleEncoder::EncodeVarint(T aValue) { 152 uint64_t value = static_cast<uint64_t>(aValue); 153 mEncoder->EncodeVarint(value); 154 return *this; 155 } 156 157 CapsuleEncoder& CapsuleEncoder::EncodeString(const nsACString& aData) { 158 mEncoder->EncodeBuffer(reinterpret_cast<const uint8_t*>(aData.BeginReading()), 159 aData.Length()); 160 return *this; 161 } 162 163 CapsuleEncoder& CapsuleEncoder::EncodeBuffer(nsTArray<uint8_t>& aData) { 164 mEncoder->EncodeBuffer(aData.Elements(), aData.Length()); 165 return *this; 166 } 167 168 CapsuleEncoder& CapsuleEncoder::EncodeBufferWithVarintLen( 169 nsTArray<uint8_t>& aData) { 170 mEncoder->EncodeBufferWithVarintLen(aData.Elements(), aData.Length()); 171 return *this; 172 } 173 174 // static 175 size_t CapsuleEncoder::VarintLength(uint64_t aValue) { 176 return NeqoEncoder::VarintLength(aValue); 177 } 178 179 mozilla::Span<const uint8_t> CapsuleEncoder::GetBuffer() { 180 const uint8_t* buffer = nullptr; 181 uint32_t length = 0; 182 mEncoder->GetData(&buffer, &length); 183 return Span<const uint8_t>(buffer, length); 184 } 185 186 } // namespace mozilla::net