blob: c413117fb6ed1b3992a44f11d83b61b65a7e3b65 [file] [log] [blame]
Sergey Ulanovdc305db2016-01-15 01:14:541/*
kjellander1afca732016-02-08 04:46:452 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
Sergey Ulanovdc305db2016-01-15 01:14:543 *
kjellander1afca732016-02-08 04:46:454 * 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.
Sergey Ulanovdc305db2016-01-15 01:14:549 */
10
Steve Anton10542f22019-01-11 17:11:0011#include "media/base/turn_utils.h"
Sergey Ulanovdc305db2016-01-15 01:14:5412
Patrik Höglund56d94522019-11-18 14:53:3213#include "api/transport/stun.h"
Steve Anton10542f22019-01-11 17:11:0014#include "rtc_base/byte_order.h"
Sergey Ulanovdc305db2016-01-15 01:14:5415
16namespace cricket {
17
18namespace {
19
20const size_t kTurnChannelHeaderLength = 4;
21
22bool IsTurnChannelData(const uint8_t* data, size_t length) {
23 return length >= kTurnChannelHeaderLength && ((*data & 0xC0) == 0x40);
24}
25
26bool 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
37bool 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