2 * Copyright (C) 2020 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #include "STUNMessageParsing.h"
29 #if ENABLE(WEB_RTC) && USE(LIBWEBRTC)
31 #include <LibWebRTCMacros.h>
32 #include <webrtc/rtc_base/byte_order.h>
37 static inline bool isStunMessage(uint16_t messageType
)
39 // https://tools.ietf.org/html/rfc5389#section-6 for STUN messages.
40 // TURN messages start by the channel number which is constrained by https://tools.ietf.org/html/rfc5766#section-11.
41 return !(messageType
& 0xC000);
44 std::optional
<STUNMessageLengths
> getSTUNOrTURNMessageLengths(const uint8_t* data
, size_t size
)
49 auto messageType
= be16toh(*reinterpret_cast<const uint16_t*>(data
));
50 auto messageLength
= be16toh(*reinterpret_cast<const uint16_t*>(data
+ 2));
52 // STUN data message header is 20 bytes.
53 if (isStunMessage(messageType
)) {
54 size_t length
= 20 + messageLength
;
55 return STUNMessageLengths
{ length
, length
};
58 // TURN data message header is 4 bytes plus padding bytes to get 4 bytes alignment as needed.
59 size_t length
= 4 + messageLength
;
60 size_t roundedLength
= length
% 4 ? (length
+ 4 - (length
% 4)) : length
;
61 return STUNMessageLengths
{ length
, roundedLength
};
64 static inline Vector
<uint8_t> extractSTUNOrTURNMessages(Vector
<uint8_t>&& buffered
, const Function
<void(const uint8_t* data
, size_t size
)>& processMessage
)
66 auto* data
= buffered
.data();
67 size_t size
= buffered
.size();
70 auto lengths
= getSTUNOrTURNMessageLengths(data
, size
);
72 if (!lengths
|| lengths
->messageLengthWithPadding
> size
) {
76 std::memcpy(buffered
.data(), data
, size
);
77 buffered
.resize(size
);
78 return WTFMove(buffered
);
81 processMessage(data
, lengths
->messageLength
);
83 data
+= lengths
->messageLengthWithPadding
;
84 size
-= lengths
->messageLengthWithPadding
;
88 static inline Vector
<uint8_t> extractDataMessages(Vector
<uint8_t>&& buffered
, const Function
<void(const uint8_t* data
, size_t size
)>& processMessage
)
90 constexpr size_t lengthFieldSize
= 2; // number of bytes read by be16toh.
92 auto* data
= buffered
.data();
93 size_t size
= buffered
.size();
96 bool canReadLength
= size
>= lengthFieldSize
;
97 size_t length
= canReadLength
? be16toh(*reinterpret_cast<const uint16_t*>(data
)) : 0;
98 if (!canReadLength
|| length
> size
- lengthFieldSize
) {
102 std::memcpy(buffered
.data(), data
, size
);
103 buffered
.resize(size
);
104 return WTFMove(buffered
);
107 data
+= lengthFieldSize
;
108 size
-= lengthFieldSize
;
110 processMessage(data
, length
);
117 Vector
<uint8_t> extractMessages(Vector
<uint8_t>&& buffer
, MessageType type
, const Function
<void(const uint8_t* data
, size_t size
)>& processMessage
)
119 return type
== MessageType::STUN
? extractSTUNOrTURNMessages(WTFMove(buffer
), processMessage
) : extractDataMessages(WTFMove(buffer
), processMessage
);
122 } // namespace WebRTC
123 } // namespace WebCore
125 #endif // ENABLE(WEB_RTC) && USE(LIBWEBRTC)