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