xref: /aosp_15_r20/external/webrtc/media/base/turn_utils.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "media/base/turn_utils.h"
12 
13 #include "api/transport/stun.h"
14 #include "rtc_base/byte_order.h"
15 
16 namespace cricket {
17 
18 namespace {
19 
20 const size_t kTurnChannelHeaderLength = 4;
21 
IsTurnChannelData(const uint8_t * data,size_t length)22 bool IsTurnChannelData(const uint8_t* data, size_t length) {
23   return length >= kTurnChannelHeaderLength && ((*data & 0xC0) == 0x40);
24 }
25 
IsTurnSendIndicationPacket(const uint8_t * data,size_t length)26 bool IsTurnSendIndicationPacket(const uint8_t* data, size_t length) {
27   if (length < kStunHeaderSize) {
28     return false;
29   }
30 
31   uint16_t type = rtc::GetBE16(data);
32   return (type == TURN_SEND_INDICATION);
33 }
34 
35 }  // namespace
36 
UnwrapTurnPacket(const uint8_t * packet,size_t packet_size,size_t * content_position,size_t * content_size)37 bool UnwrapTurnPacket(const uint8_t* packet,
38                       size_t packet_size,
39                       size_t* content_position,
40                       size_t* content_size) {
41   if (IsTurnChannelData(packet, packet_size)) {
42     // Turn Channel Message header format.
43     //   0                   1                   2                   3
44     //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
45     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46     // |         Channel Number        |            Length             |
47     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48     // |                                                               |
49     // /                       Application Data                        /
50     // /                                                               /
51     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52     size_t length = rtc::GetBE16(&packet[2]);
53     if (length + kTurnChannelHeaderLength > packet_size) {
54       return false;
55     }
56 
57     *content_position = kTurnChannelHeaderLength;
58     *content_size = length;
59     return true;
60   }
61 
62   if (IsTurnSendIndicationPacket(packet, packet_size)) {
63     // Validate STUN message length.
64     const size_t stun_message_length = rtc::GetBE16(&packet[2]);
65     if (stun_message_length + kStunHeaderSize != packet_size) {
66       return false;
67     }
68 
69     // First skip mandatory stun header which is of 20 bytes.
70     size_t pos = kStunHeaderSize;
71     // Loop through STUN attributes until we find STUN DATA attribute.
72     while (pos < packet_size) {
73       // Keep reading STUN attributes until we hit DATA attribute.
74       // Attribute will be a TLV structure.
75       // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
76       // |         Type                  |            Length             |
77       // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78       // |                         Value (variable)                ....
79       // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80       // The value in the length field MUST contain the length of the Value
81       // part of the attribute, prior to padding, measured in bytes.  Since
82       // STUN aligns attributes on 32-bit boundaries, attributes whose content
83       // is not a multiple of 4 bytes are padded with 1, 2, or 3 bytes of
84       // padding so that its value contains a multiple of 4 bytes.  The
85       // padding bits are ignored, and may be any value.
86       uint16_t attr_type, attr_length;
87       const int kAttrHeaderLength = sizeof(attr_type) + sizeof(attr_length);
88 
89       if (packet_size < pos + kAttrHeaderLength) {
90         return false;
91       }
92 
93       // Getting attribute type and length.
94       attr_type = rtc::GetBE16(&packet[pos]);
95       attr_length = rtc::GetBE16(&packet[pos + sizeof(attr_type)]);
96 
97       pos += kAttrHeaderLength;  // Skip STUN_DATA_ATTR header.
98 
99       // Checking for bogus attribute length.
100       if (pos + attr_length > packet_size) {
101         return false;
102       }
103 
104       if (attr_type == STUN_ATTR_DATA) {
105         *content_position = pos;
106         *content_size = attr_length;
107         return true;
108       }
109 
110       pos += attr_length;
111       if ((attr_length % 4) != 0) {
112         pos += (4 - (attr_length % 4));
113       }
114     }
115 
116     // There is no data attribute present in the message.
117     return false;
118   }
119 
120   // This is not a TURN packet.
121   *content_position = 0;
122   *content_size = packet_size;
123   return true;
124 }
125 
126 }  // namespace cricket
127