123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- // Copyright 2020 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 "remoting/protocol/stun_tcp_packet_processor.h"
- #include "base/no_destructor.h"
- #include "base/notreached.h"
- #include "base/sys_byteorder.h"
- #include "net/base/io_buffer.h"
- #include "third_party/webrtc/media/base/rtp_utils.h"
- #include "third_party/webrtc/rtc_base/time_utils.h"
- namespace remoting {
- namespace protocol {
- namespace {
- using PacketLength = uint16_t;
- constexpr size_t kPacketHeaderSize = sizeof(PacketLength);
- constexpr size_t kStunHeaderSize = 20;
- constexpr size_t kTurnChannelDataHeaderSize = 4;
- constexpr size_t kPacketLengthOffset = 2;
- int GetExpectedStunPacketSize(const uint8_t* data,
- size_t len,
- size_t* pad_bytes) {
- DCHECK_LE(kTurnChannelDataHeaderSize, len);
- // Both stun and turn had length at offset 2.
- size_t packet_size = base::NetToHost16(
- *reinterpret_cast<const uint16_t*>(data + kPacketLengthOffset));
- // Get packet type (STUN or TURN).
- uint16_t msg_type =
- base::NetToHost16(*reinterpret_cast<const uint16_t*>(data));
- *pad_bytes = 0;
- // Add header length to packet length.
- if ((msg_type & 0xC000) == 0) {
- packet_size += kStunHeaderSize;
- } else {
- packet_size += kTurnChannelDataHeaderSize;
- // Calculate any padding if present.
- if (packet_size % 4)
- *pad_bytes = 4 - packet_size % 4;
- }
- return packet_size;
- }
- } // namespace
- StunTcpPacketProcessor::StunTcpPacketProcessor() = default;
- StunTcpPacketProcessor::~StunTcpPacketProcessor() = default;
- // static
- StunTcpPacketProcessor* StunTcpPacketProcessor::GetInstance() {
- static base::NoDestructor<StunTcpPacketProcessor> instance;
- return instance.get();
- }
- scoped_refptr<net::IOBufferWithSize> StunTcpPacketProcessor::Pack(
- const uint8_t* data,
- size_t data_size) const {
- // Each packet is expected to have header (STUN/TURN ChannelData), where
- // header contains message type and and length of message.
- if (data_size < kPacketHeaderSize + kPacketLengthOffset) {
- NOTREACHED();
- return nullptr;
- }
- size_t pad_bytes;
- size_t expected_len = GetExpectedStunPacketSize(data, data_size, &pad_bytes);
- // Accepts only complete STUN/TURN packets.
- if (data_size != expected_len) {
- NOTREACHED();
- return nullptr;
- }
- // Add any pad bytes to the total size.
- size_t size = data_size + pad_bytes;
- auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(size);
- memcpy(buffer->data(), data, data_size);
- if (pad_bytes) {
- char padding[4] = {0};
- DCHECK_LE(pad_bytes, 4u);
- memcpy(buffer->data() + data_size, padding, pad_bytes);
- }
- return buffer;
- }
- scoped_refptr<net::IOBufferWithSize> StunTcpPacketProcessor::Unpack(
- const uint8_t* data,
- size_t data_size,
- size_t* bytes_consumed) const {
- *bytes_consumed = 0;
- if (data_size < kPacketHeaderSize + kPacketLengthOffset)
- return nullptr;
- size_t pad_bytes;
- size_t packet_size = GetExpectedStunPacketSize(data, data_size, &pad_bytes);
- if (data_size < packet_size + pad_bytes)
- return nullptr;
- // We have a complete packet.
- const uint8_t* cur = data;
- *bytes_consumed = packet_size + pad_bytes;
- auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(packet_size);
- memcpy(buffer->data(), cur, packet_size);
- return buffer;
- }
- void StunTcpPacketProcessor::ApplyPacketOptions(
- uint8_t* data,
- size_t data_size,
- const rtc::PacketTimeUpdateParams& packet_time_params) const {
- cricket::ApplyPacketOptions(data, data_size, packet_time_params,
- rtc::TimeMicros());
- }
- } // namespace protocol
- } // namespace remoting
|