Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
bdf2783a
Commit
bdf2783a
authored
Mar 27, 2021
by
ziyue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
还原原始文件名
parent
704421b7
隐藏空白字符变更
内嵌
并排
正在显示
14 个修改的文件
包含
1058 行增加
和
888 行删除
+1058
-888
server/WebApi.cpp
+1
-1
webrtc/DtlsTransport.cpp
+1
-1
webrtc/DtlsTransport.hpp
+1
-1
webrtc/IceServer.cpp
+1
-1
webrtc/IceServer.hpp
+1
-1
webrtc/SrtpSession.cpp
+1
-1
webrtc/SrtpSession.hpp
+1
-1
webrtc/StunPacket.cpp
+851
-694
webrtc/StunPacket.hpp
+195
-0
webrtc/Utils.hpp
+0
-0
webrtc/WebRtcTransport.cpp
+1
-1
webrtc/WebRtcTransport.h
+4
-4
webrtc/logger.h
+0
-3
webrtc/stun_packet.h
+0
-179
没有找到文件。
server/WebApi.cpp
查看文件 @
bdf2783a
...
@@ -36,7 +36,7 @@
...
@@ -36,7 +36,7 @@
#include "Rtp/RtpServer.h"
#include "Rtp/RtpServer.h"
#endif
#endif
#ifdef ENABLE_WEBRTC
#ifdef ENABLE_WEBRTC
#include "../webrtc/
webrtc_t
ransport.h"
#include "../webrtc/
WebRtcT
ransport.h"
#endif
#endif
using
namespace
toolkit
;
using
namespace
toolkit
;
...
...
webrtc/
rtc_dtls_transport.cc
→
webrtc/
DtlsTransport.cpp
查看文件 @
bdf2783a
#define MS_CLASS "RTC::DtlsTransport"
#define MS_CLASS "RTC::DtlsTransport"
// #define MS_LOG_DEV_LEVEL 3
// #define MS_LOG_DEV_LEVEL 3
#include "
rtc_dtls_transport.h
"
#include "
DtlsTransport.hpp
"
#include "logger.h"
#include "logger.h"
#include <openssl/asn1.h>
#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/bn.h>
...
...
webrtc/
rtc_dtls_transport.h
→
webrtc/
DtlsTransport.hpp
查看文件 @
bdf2783a
#ifndef MS_RTC_DTLS_TRANSPORT_HPP
#ifndef MS_RTC_DTLS_TRANSPORT_HPP
#define MS_RTC_DTLS_TRANSPORT_HPP
#define MS_RTC_DTLS_TRANSPORT_HPP
#include "
srtp_session.h
"
#include "
SrtpSession.hpp
"
#include <openssl/bio.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/x509.h>
...
...
webrtc/
ice_server.cc
→
webrtc/
IceServer.cpp
查看文件 @
bdf2783a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
// #define MS_LOG_DEV_LEVEL 3
// #define MS_LOG_DEV_LEVEL 3
#include <utility>
#include <utility>
#include "
ice_server.h
"
#include "
IceServer.hpp
"
namespace
RTC
namespace
RTC
{
{
...
...
webrtc/
ice_server.h
→
webrtc/
IceServer.hpp
查看文件 @
bdf2783a
#ifndef MS_RTC_ICE_SERVER_HPP
#ifndef MS_RTC_ICE_SERVER_HPP
#define MS_RTC_ICE_SERVER_HPP
#define MS_RTC_ICE_SERVER_HPP
#include "
stun_packet.h
"
#include "
StunPacket.hpp
"
#include "logger.h"
#include "logger.h"
#include <list>
#include <list>
#include <string>
#include <string>
...
...
webrtc/
srtp_session.cc
→
webrtc/
SrtpSession.cpp
查看文件 @
bdf2783a
#define MS_CLASS "RTC::SrtpSession"
#define MS_CLASS "RTC::SrtpSession"
// #define MS_LOG_DEV_LEVEL 3
// #define MS_LOG_DEV_LEVEL 3
#include "
srtp_session.h
"
#include "
SrtpSession.hpp
"
#include <cstring> // std::memset(), std::memcpy()
#include <cstring> // std::memset(), std::memcpy()
#include "logger.h"
#include "logger.h"
...
...
webrtc/
srtp_session.h
→
webrtc/
SrtpSession.hpp
查看文件 @
bdf2783a
#ifndef MS_RTC_SRTP_SESSION_HPP
#ifndef MS_RTC_SRTP_SESSION_HPP
#define MS_RTC_SRTP_SESSION_HPP
#define MS_RTC_SRTP_SESSION_HPP
#include "
utils.h
"
#include "
Utils.hpp
"
#include <srtp2/srtp.h>
#include <srtp2/srtp.h>
#include <vector>
#include <vector>
...
...
webrtc/
stun_packet.cc
→
webrtc/
StunPacket.cpp
查看文件 @
bdf2783a
#define MS_CLASS "RTC::StunPacket"
#define MS_CLASS "RTC::StunPacket"
// #define MS_LOG_DEV
// #define MS_LOG_DEV
_LEVEL 3
#include "stun_packet.h"
#include "StunPacket.hpp"
#include <cstdio> // std::snprintf()
#include <cstring> // std::memcmp(), std::memcpy()
#include <cstdio> // std::snprintf()
namespace
RTC
#include <cstring> // std::memcmp(), std::memcpy()
namespace
RTC
{
static
const
uint32_t
crc32Table
[]
=
{
{
0x00000000
,
0x77073096
,
0xee0e612c
,
0x990951ba
,
0x076dc419
,
0x706af48f
,
0xe963a535
,
0x9e6495a3
,
static
const
uint32_t
crc32Table
[]
=
0x0edb8832
,
0x79dcb8a4
,
0xe0d5e91e
,
0x97d2d988
,
0x09b64c2b
,
0x7eb17cbd
,
0xe7b82d07
,
0x90bf1d91
,
{
0x1db71064
,
0x6ab020f2
,
0xf3b97148
,
0x84be41de
,
0x1adad47d
,
0x6ddde4eb
,
0xf4d4b551
,
0x83d385c7
,
0x00000000
,
0x77073096
,
0xee0e612c
,
0x990951ba
,
0x076dc419
,
0x706af48f
,
0xe963a535
,
0x9e6495a3
,
0x136c9856
,
0x646ba8c0
,
0xfd62f97a
,
0x8a65c9ec
,
0x14015c4f
,
0x63066cd9
,
0xfa0f3d63
,
0x8d080df5
,
0x0edb8832
,
0x79dcb8a4
,
0xe0d5e91e
,
0x97d2d988
,
0x09b64c2b
,
0x7eb17cbd
,
0xe7b82d07
,
0x90bf1d91
,
0x3b6e20c8
,
0x4c69105e
,
0xd56041e4
,
0xa2677172
,
0x3c03e4d1
,
0x4b04d447
,
0xd20d85fd
,
0xa50ab56b
,
0x1db71064
,
0x6ab020f2
,
0xf3b97148
,
0x84be41de
,
0x1adad47d
,
0x6ddde4eb
,
0xf4d4b551
,
0x83d385c7
,
0x35b5a8fa
,
0x42b2986c
,
0xdbbbc9d6
,
0xacbcf940
,
0x32d86ce3
,
0x45df5c75
,
0xdcd60dcf
,
0xabd13d59
,
0x136c9856
,
0x646ba8c0
,
0xfd62f97a
,
0x8a65c9ec
,
0x14015c4f
,
0x63066cd9
,
0xfa0f3d63
,
0x8d080df5
,
0x26d930ac
,
0x51de003a
,
0xc8d75180
,
0xbfd06116
,
0x21b4f4b5
,
0x56b3c423
,
0xcfba9599
,
0xb8bda50f
,
0x3b6e20c8
,
0x4c69105e
,
0xd56041e4
,
0xa2677172
,
0x3c03e4d1
,
0x4b04d447
,
0xd20d85fd
,
0xa50ab56b
,
0x2802b89e
,
0x5f058808
,
0xc60cd9b2
,
0xb10be924
,
0x2f6f7c87
,
0x58684c11
,
0xc1611dab
,
0xb6662d3d
,
0x35b5a8fa
,
0x42b2986c
,
0xdbbbc9d6
,
0xacbcf940
,
0x32d86ce3
,
0x45df5c75
,
0xdcd60dcf
,
0xabd13d59
,
0x76dc4190
,
0x01db7106
,
0x98d220bc
,
0xefd5102a
,
0x71b18589
,
0x06b6b51f
,
0x9fbfe4a5
,
0xe8b8d433
,
0x26d930ac
,
0x51de003a
,
0xc8d75180
,
0xbfd06116
,
0x21b4f4b5
,
0x56b3c423
,
0xcfba9599
,
0xb8bda50f
,
0x7807c9a2
,
0x0f00f934
,
0x9609a88e
,
0xe10e9818
,
0x7f6a0dbb
,
0x086d3d2d
,
0x91646c97
,
0xe6635c01
,
0x2802b89e
,
0x5f058808
,
0xc60cd9b2
,
0xb10be924
,
0x2f6f7c87
,
0x58684c11
,
0xc1611dab
,
0xb6662d3d
,
0x6b6b51f4
,
0x1c6c6162
,
0x856530d8
,
0xf262004e
,
0x6c0695ed
,
0x1b01a57b
,
0x8208f4c1
,
0xf50fc457
,
0x76dc4190
,
0x01db7106
,
0x98d220bc
,
0xefd5102a
,
0x71b18589
,
0x06b6b51f
,
0x9fbfe4a5
,
0xe8b8d433
,
0x65b0d9c6
,
0x12b7e950
,
0x8bbeb8ea
,
0xfcb9887c
,
0x62dd1ddf
,
0x15da2d49
,
0x8cd37cf3
,
0xfbd44c65
,
0x7807c9a2
,
0x0f00f934
,
0x9609a88e
,
0xe10e9818
,
0x7f6a0dbb
,
0x086d3d2d
,
0x91646c97
,
0xe6635c01
,
0x4db26158
,
0x3ab551ce
,
0xa3bc0074
,
0xd4bb30e2
,
0x4adfa541
,
0x3dd895d7
,
0xa4d1c46d
,
0xd3d6f4fb
,
0x6b6b51f4
,
0x1c6c6162
,
0x856530d8
,
0xf262004e
,
0x6c0695ed
,
0x1b01a57b
,
0x8208f4c1
,
0xf50fc457
,
0x4369e96a
,
0x346ed9fc
,
0xad678846
,
0xda60b8d0
,
0x44042d73
,
0x33031de5
,
0xaa0a4c5f
,
0xdd0d7cc9
,
0x65b0d9c6
,
0x12b7e950
,
0x8bbeb8ea
,
0xfcb9887c
,
0x62dd1ddf
,
0x15da2d49
,
0x8cd37cf3
,
0xfbd44c65
,
0x5005713c
,
0x270241aa
,
0xbe0b1010
,
0xc90c2086
,
0x5768b525
,
0x206f85b3
,
0xb966d409
,
0xce61e49f
,
0x4db26158
,
0x3ab551ce
,
0xa3bc0074
,
0xd4bb30e2
,
0x4adfa541
,
0x3dd895d7
,
0xa4d1c46d
,
0xd3d6f4fb
,
0x5edef90e
,
0x29d9c998
,
0xb0d09822
,
0xc7d7a8b4
,
0x59b33d17
,
0x2eb40d81
,
0xb7bd5c3b
,
0xc0ba6cad
,
0x4369e96a
,
0x346ed9fc
,
0xad678846
,
0xda60b8d0
,
0x44042d73
,
0x33031de5
,
0xaa0a4c5f
,
0xdd0d7cc9
,
0xedb88320
,
0x9abfb3b6
,
0x03b6e20c
,
0x74b1d29a
,
0xead54739
,
0x9dd277af
,
0x04db2615
,
0x73dc1683
,
0x5005713c
,
0x270241aa
,
0xbe0b1010
,
0xc90c2086
,
0x5768b525
,
0x206f85b3
,
0xb966d409
,
0xce61e49f
,
0xe3630b12
,
0x94643b84
,
0x0d6d6a3e
,
0x7a6a5aa8
,
0xe40ecf0b
,
0x9309ff9d
,
0x0a00ae27
,
0x7d079eb1
,
0x5edef90e
,
0x29d9c998
,
0xb0d09822
,
0xc7d7a8b4
,
0x59b33d17
,
0x2eb40d81
,
0xb7bd5c3b
,
0xc0ba6cad
,
0xf00f9344
,
0x8708a3d2
,
0x1e01f268
,
0x6906c2fe
,
0xf762575d
,
0x806567cb
,
0x196c3671
,
0x6e6b06e7
,
0xedb88320
,
0x9abfb3b6
,
0x03b6e20c
,
0x74b1d29a
,
0xead54739
,
0x9dd277af
,
0x04db2615
,
0x73dc1683
,
0xfed41b76
,
0x89d32be0
,
0x10da7a5a
,
0x67dd4acc
,
0xf9b9df6f
,
0x8ebeeff9
,
0x17b7be43
,
0x60b08ed5
,
0xe3630b12
,
0x94643b84
,
0x0d6d6a3e
,
0x7a6a5aa8
,
0xe40ecf0b
,
0x9309ff9d
,
0x0a00ae27
,
0x7d079eb1
,
0xd6d6a3e8
,
0xa1d1937e
,
0x38d8c2c4
,
0x4fdff252
,
0xd1bb67f1
,
0xa6bc5767
,
0x3fb506dd
,
0x48b2364b
,
0xf00f9344
,
0x8708a3d2
,
0x1e01f268
,
0x6906c2fe
,
0xf762575d
,
0x806567cb
,
0x196c3671
,
0x6e6b06e7
,
0xd80d2bda
,
0xaf0a1b4c
,
0x36034af6
,
0x41047a60
,
0xdf60efc3
,
0xa867df55
,
0x316e8eef
,
0x4669be79
,
0xfed41b76
,
0x89d32be0
,
0x10da7a5a
,
0x67dd4acc
,
0xf9b9df6f
,
0x8ebeeff9
,
0x17b7be43
,
0x60b08ed5
,
0xcb61b38c
,
0xbc66831a
,
0x256fd2a0
,
0x5268e236
,
0xcc0c7795
,
0xbb0b4703
,
0x220216b9
,
0x5505262f
,
0xd6d6a3e8
,
0xa1d1937e
,
0x38d8c2c4
,
0x4fdff252
,
0xd1bb67f1
,
0xa6bc5767
,
0x3fb506dd
,
0x48b2364b
,
0xc5ba3bbe
,
0xb2bd0b28
,
0x2bb45a92
,
0x5cb36a04
,
0xc2d7ffa7
,
0xb5d0cf31
,
0x2cd99e8b
,
0x5bdeae1d
,
0xd80d2bda
,
0xaf0a1b4c
,
0x36034af6
,
0x41047a60
,
0xdf60efc3
,
0xa867df55
,
0x316e8eef
,
0x4669be79
,
0x9b64c2b0
,
0xec63f226
,
0x756aa39c
,
0x026d930a
,
0x9c0906a9
,
0xeb0e363f
,
0x72076785
,
0x05005713
,
0xcb61b38c
,
0xbc66831a
,
0x256fd2a0
,
0x5268e236
,
0xcc0c7795
,
0xbb0b4703
,
0x220216b9
,
0x5505262f
,
0x95bf4a82
,
0xe2b87a14
,
0x7bb12bae
,
0x0cb61b38
,
0x92d28e9b
,
0xe5d5be0d
,
0x7cdcefb7
,
0x0bdbdf21
,
0xc5ba3bbe
,
0xb2bd0b28
,
0x2bb45a92
,
0x5cb36a04
,
0xc2d7ffa7
,
0xb5d0cf31
,
0x2cd99e8b
,
0x5bdeae1d
,
0x86d3d2d4
,
0xf1d4e242
,
0x68ddb3f8
,
0x1fda836e
,
0x81be16cd
,
0xf6b9265b
,
0x6fb077e1
,
0x18b74777
,
0x9b64c2b0
,
0xec63f226
,
0x756aa39c
,
0x026d930a
,
0x9c0906a9
,
0xeb0e363f
,
0x72076785
,
0x05005713
,
0x88085ae6
,
0xff0f6a70
,
0x66063bca
,
0x11010b5c
,
0x8f659eff
,
0xf862ae69
,
0x616bffd3
,
0x166ccf45
,
0x95bf4a82
,
0xe2b87a14
,
0x7bb12bae
,
0x0cb61b38
,
0x92d28e9b
,
0xe5d5be0d
,
0x7cdcefb7
,
0x0bdbdf21
,
0xa00ae278
,
0xd70dd2ee
,
0x4e048354
,
0x3903b3c2
,
0xa7672661
,
0xd06016f7
,
0x4969474d
,
0x3e6e77db
,
0x86d3d2d4
,
0xf1d4e242
,
0x68ddb3f8
,
0x1fda836e
,
0x81be16cd
,
0xf6b9265b
,
0x6fb077e1
,
0x18b74777
,
0xaed16a4a
,
0xd9d65adc
,
0x40df0b66
,
0x37d83bf0
,
0xa9bcae53
,
0xdebb9ec5
,
0x47b2cf7f
,
0x30b5ffe9
,
0x88085ae6
,
0xff0f6a70
,
0x66063bca
,
0x11010b5c
,
0x8f659eff
,
0xf862ae69
,
0x616bffd3
,
0x166ccf45
,
0xbdbdf21c
,
0xcabac28a
,
0x53b39330
,
0x24b4a3a6
,
0xbad03605
,
0xcdd70693
,
0x54de5729
,
0x23d967bf
,
0xa00ae278
,
0xd70dd2ee
,
0x4e048354
,
0x3903b3c2
,
0xa7672661
,
0xd06016f7
,
0x4969474d
,
0x3e6e77db
,
0xb3667a2e
,
0xc4614ab8
,
0x5d681b02
,
0x2a6f2b94
,
0xb40bbe37
,
0xc30c8ea1
,
0x5a05df1b
,
0x2d02ef8d
0xaed16a4a
,
0xd9d65adc
,
0x40df0b66
,
0x37d83bf0
,
0xa9bcae53
,
0xdebb9ec5
,
0x47b2cf7f
,
0x30b5ffe9
,
};
0xbdbdf21c
,
0xcabac28a
,
0x53b39330
,
0x24b4a3a6
,
0xbad03605
,
0xcdd70693
,
0x54de5729
,
0x23d967bf
,
0xb3667a2e
,
0xc4614ab8
,
0x5d681b02
,
0x2a6f2b94
,
0xb40bbe37
,
0xc30c8ea1
,
0x5a05df1b
,
0x2d02ef8d
inline
uint32_t
GetCRC32
(
const
uint8_t
*
data
,
size_t
size
)
{
};
uint32_t
crc
{
0xFFFFFFFF
};
const
uint8_t
*
p
=
data
;
inline
uint32_t
GetCRC32
(
const
uint8_t
*
data
,
size_t
size
)
{
uint32_t
crc
{
0xFFFFFFFF
};
while
(
size
--
)
{
const
uint8_t
*
p
=
data
;
crc
=
crc32Table
[(
crc
^
*
p
++
)
&
0xFF
]
^
(
crc
>>
8
);
}
while
(
size
--
)
{
crc
=
crc32Table
[(
crc
^
*
p
++
)
&
0xFF
]
^
(
crc
>>
8
);
}
return
crc
^
~
0U
;
return
crc
^
~
0U
;
}
}
static
std
::
string
openssl_HMACsha1
(
const
void
*
key
,
size_t
key_len
,
const
void
*
data
,
size_t
data_len
){
static
std
::
string
openssl_HMACsha1
(
const
void
*
key
,
size_t
key_len
,
const
void
*
data
,
size_t
data_len
){
std
::
string
str
;
std
::
string
str
;
str
.
resize
(
20
);
str
.
resize
(
20
);
unsigned
int
out_len
;
unsigned
int
out_len
;
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10100000L)
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10100000L)
//openssl 1.1.0新增api,老版本api作废
//openssl 1.1.0新增api,老版本api作废
HMAC_CTX
*
ctx
=
HMAC_CTX_new
();
HMAC_CTX
*
ctx
=
HMAC_CTX_new
();
HMAC_CTX_reset
(
ctx
);
HMAC_CTX_reset
(
ctx
);
HMAC_Init_ex
(
ctx
,
key
,
(
int
)
key_len
,
EVP_sha1
(),
NULL
);
HMAC_Init_ex
(
ctx
,
key
,
(
int
)
key_len
,
EVP_sha1
(),
NULL
);
HMAC_Update
(
ctx
,
(
unsigned
char
*
)
data
,
data_len
);
HMAC_Update
(
ctx
,
(
unsigned
char
*
)
data
,
data_len
);
HMAC_Final
(
ctx
,
(
unsigned
char
*
)
str
.
data
(),
&
out_len
);
HMAC_Final
(
ctx
,
(
unsigned
char
*
)
str
.
data
(),
&
out_len
);
HMAC_CTX_reset
(
ctx
);
HMAC_CTX_reset
(
ctx
);
HMAC_CTX_free
(
ctx
);
HMAC_CTX_free
(
ctx
);
#else
#else
HMAC_CTX
ctx
;
HMAC_CTX
ctx
;
HMAC_CTX_init
(
&
ctx
);
HMAC_CTX_init
(
&
ctx
);
HMAC_Init_ex
(
&
ctx
,
key
,
key_len
,
EVP_sha1
(),
NULL
);
HMAC_Init_ex
(
&
ctx
,
key
,
key_len
,
EVP_sha1
(),
NULL
);
HMAC_Update
(
&
ctx
,
(
unsigned
char
*
)
data
,
data_len
);
HMAC_Update
(
&
ctx
,
(
unsigned
char
*
)
data
,
data_len
);
HMAC_Final
(
&
ctx
,
(
unsigned
char
*
)
str
.
data
(),
&
out_len
);
HMAC_Final
(
&
ctx
,
(
unsigned
char
*
)
str
.
data
(),
&
out_len
);
HMAC_CTX_cleanup
(
&
ctx
);
HMAC_CTX_cleanup
(
&
ctx
);
#endif //defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10100000L)
#endif //defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10100000L)
return
str
;
return
str
;
}
/* Class variables. */
const
uint8_t
StunPacket
::
kMagicCookie
[]
=
{
0x21
,
0x12
,
0xA4
,
0x42
};
/* Class methods. */
StunPacket
*
StunPacket
::
Parse
(
const
uint8_t
*
data
,
size_t
len
)
{
if
(
!
StunPacket
::
IsStun
(
data
,
len
))
return
nullptr
;
/*
The message type field is decomposed further into the following
structure:
0 1
2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
|11|10|9|8|7|1|6|5|4|0|3|2|1|0|
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 3: Format of STUN Message Type Field
Here the bits in the message type field are shown as most significant
(M11) through least significant (M0). M11 through M0 represent a 12-
bit encoding of the method. C1 and C0 represent a 2-bit encoding of
the class.
*/
// Get type field.
uint16_t
msgType
=
Utils
::
Byte
::
Get2Bytes
(
data
,
0
);
// Get length field.
uint16_t
msgLength
=
Utils
::
Byte
::
Get2Bytes
(
data
,
2
);
// length field must be total size minus header's 20 bytes, and must be multiple of 4 Bytes.
if
((
static_cast
<
size_t
>
(
msgLength
)
!=
len
-
20
)
||
((
msgLength
&
0x03
)
!=
0
))
{
ELOG_DEBUG
(
"length field + 20 does not match total size (or it is not multiple of 4 bytes), "
"packet discarded"
);
return
nullptr
;
}
// Get STUN method.
uint16_t
msgMethod
=
(
msgType
&
0x000f
)
|
((
msgType
&
0x00e0
)
>>
1
)
|
((
msgType
&
0x3E00
)
>>
2
);
// Get STUN class.
uint16_t
msgClass
=
((
data
[
0
]
&
0x01
)
<<
1
)
|
((
data
[
1
]
&
0x10
)
>>
4
);
// Create a new StunPacket (data + 8 points to the received TransactionID field).
auto
packet
=
new
StunPacket
(
static_cast
<
Class
>
(
msgClass
),
static_cast
<
Method
>
(
msgMethod
),
data
+
8
,
data
,
len
);
/*
STUN Attributes
After the STUN header are zero or more attributes. Each attribute
MUST be TLV encoded, with a 16-bit type, 16-bit length, and value.
Each STUN attribute MUST end on a 32-bit boundary. As mentioned
above, all fields in an attribute are transmitted most significant
bit first.
0 1 2 3
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Value (variable) ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
// Start looking for attributes after STUN header (Byte #20).
size_t
pos
{
20
};
// Flags (positions) for special MESSAGE-INTEGRITY and FINGERPRINT attributes.
bool
hasMessageIntegrity
{
false
};
bool
hasFingerprint
{
false
};
size_t
fingerprintAttrPos
;
// Will point to the beginning of the attribute.
uint32_t
fingerprint
;
// Holds the value of the FINGERPRINT attribute.
// Ensure there are at least 4 remaining bytes (attribute with 0 length).
while
(
pos
+
4
<=
len
)
{
// Get the attribute type.
auto
attrType
=
static_cast
<
Attribute
>
(
Utils
::
Byte
::
Get2Bytes
(
data
,
pos
));
// Get the attribute length.
uint16_t
attrLength
=
Utils
::
Byte
::
Get2Bytes
(
data
,
pos
+
2
);
// Ensure the attribute length is not greater than the remaining size.
if
((
pos
+
4
+
attrLength
)
>
len
)
{
ELOG_DEBUG
(
"the attribute length exceeds the remaining size, packet discarded"
);
delete
packet
;
return
nullptr
;
}
// FINGERPRINT must be the last attribute.
if
(
hasFingerprint
)
{
ELOG_DEBUG
(
"attribute after FINGERPRINT is not allowed, packet discarded"
);
delete
packet
;
return
nullptr
;
}
// After a MESSAGE-INTEGRITY attribute just FINGERPRINT is allowed.
if
(
hasMessageIntegrity
&&
attrType
!=
Attribute
::
FINGERPRINT
)
{
ELOG_DEBUG
(
"attribute after MESSAGE-INTEGRITY other than FINGERPRINT is not allowed, "
"packet discarded"
);
delete
packet
;
return
nullptr
;
}
}
const
uint8_t
*
attrValuePos
=
data
+
pos
+
4
;
/* Class variables. */
switch
(
attrType
)
{
const
uint8_t
StunPacket
::
magicCookie
[]
=
{
0x21
,
0x12
,
0xA4
,
0x42
};
case
Attribute
:
:
USERNAME
:
{
packet
->
SetUsername
(
reinterpret_cast
<
const
char
*>
(
attrValuePos
),
/* Class methods. */
static_cast
<
size_t
>
(
attrLength
));
StunPacket
*
StunPacket
::
Parse
(
const
uint8_t
*
data
,
size_t
len
)
break
;
{
}
MS_TRACE
();
case
Attribute
:
:
PRIORITY
:
{
if
(
!
StunPacket
::
IsStun
(
data
,
len
))
// Ensure attribute length is 4 bytes.
return
nullptr
;
if
(
attrLength
!=
4
)
{
ELOG_DEBUG
(
"attribute PRIORITY must be 4 bytes length, packet discarded"
);
/*
The message type field is decomposed further into the following
delete
packet
;
structure:
return
nullptr
;
}
0 1
2 3 4 5 6 7 8 9 0 1 2 3 4 5
packet
->
SetPriority
(
Utils
::
Byte
::
Get4Bytes
(
attrValuePos
,
0
));
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
break
;
|11|10|9|8|7|1|6|5|4|0|3|2|1|0|
}
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
case
Attribute
:
:
ICE_CONTROLLING
:
{
Figure 3: Format of STUN Message Type Field
// Ensure attribute length is 8 bytes.
if
(
attrLength
!=
8
)
{
Here the bits in the message type field are shown as most significant
ELOG_DEBUG
(
"attribute ICE-CONTROLLING must be 8 bytes length, packet discarded"
);
(M11) through least significant (M0). M11 through M0 represent a 12-
bit encoding of the method. C1 and C0 represent a 2-bit encoding of
delete
packet
;
the class.
return
nullptr
;
*/
}
// Get type field.
packet
->
SetIceControlling
(
Utils
::
Byte
::
Get8Bytes
(
attrValuePos
,
0
));
uint16_t
msgType
=
Utils
::
Byte
::
Get2Bytes
(
data
,
0
);
break
;
// Get length field.
}
uint16_t
msgLength
=
Utils
::
Byte
::
Get2Bytes
(
data
,
2
);
case
Attribute
:
:
ICE_CONTROLLED
:
{
// length field must be total size minus header's 20 bytes, and must be multiple of 4 Bytes.
// Ensure attribute length is 8 bytes.
if
((
static_cast
<
size_t
>
(
msgLength
)
!=
len
-
20
)
||
((
msgLength
&
0x03
)
!=
0
))
if
(
attrLength
!=
8
)
{
{
ELOG_DEBUG
(
"attribute ICE-CONTROLLED must be 8 bytes length, packet discarded"
);
MS_WARN_TAG
(
ice
,
delete
packet
;
"length field + 20 does not match total size (or it is not multiple of 4 bytes), "
return
nullptr
;
"packet discarded"
);
}
return
nullptr
;
packet
->
SetIceControlled
(
Utils
::
Byte
::
Get8Bytes
(
attrValuePos
,
0
));
}
break
;
// Get STUN method.
}
uint16_t
msgMethod
=
(
msgType
&
0x000f
)
|
((
msgType
&
0x00e0
)
>>
1
)
|
((
msgType
&
0x3E00
)
>>
2
);
case
Attribute
:
:
USE_CANDIDATE
:
{
// Get STUN class.
// Ensure attribute length is 0 bytes.
uint16_t
msgClass
=
((
data
[
0
]
&
0x01
)
<<
1
)
|
((
data
[
1
]
&
0x10
)
>>
4
);
if
(
attrLength
!=
0
)
{
ELOG_DEBUG
(
"attribute USE-CANDIDATE must be 0 bytes length, packet discarded"
);
// Create a new StunPacket (data + 8 points to the received TransactionID field).
auto
*
packet
=
new
StunPacket
(
delete
packet
;
static_cast
<
Class
>
(
msgClass
),
static_cast
<
Method
>
(
msgMethod
),
data
+
8
,
data
,
len
);
return
nullptr
;
}
/*
STUN Attributes
packet
->
SetUseCandidate
();
After the STUN header are zero or more attributes. Each attribute
break
;
MUST be TLV encoded, with a 16-bit type, 16-bit length, and value.
}
Each STUN attribute MUST end on a 32-bit boundary. As mentioned
above, all fields in an attribute are transmitted most significant
case
Attribute
:
:
MESSAGE_INTEGRITY
:
{
bit first.
// Ensure attribute length is 20 bytes.
if
(
attrLength
!=
20
)
{
0 1 2 3
ELOG_DEBUG
(
"attribute MESSAGE-INTEGRITY must be 20 bytes length, packet discarded"
);
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
delete
packet
;
| Type | Length |
return
nullptr
;
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
}
| Value (variable) ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
hasMessageIntegrity
=
true
;
*/
packet
->
SetMessageIntegrity
(
attrValuePos
);
// Start looking for attributes after STUN header (Byte #20).
break
;
size_t
pos
{
20
};
}
// Flags (positions) for special MESSAGE-INTEGRITY and FINGERPRINT attributes.
bool
hasMessageIntegrity
{
false
};
case
Attribute
:
:
FINGERPRINT
:
{
bool
hasFingerprint
{
false
};
// Ensure attribute length is 4 bytes.
size_t
fingerprintAttrPos
;
// Will point to the beginning of the attribute.
if
(
attrLength
!=
4
)
{
uint32_t
fingerprint
;
// Holds the value of the FINGERPRINT attribute.
ELOG_DEBUG
(
"attribute FINGERPRINT must be 4 bytes length, packet discarded"
);
// Ensure there are at least 4 remaining bytes (attribute with 0 length).
delete
packet
;
while
(
pos
+
4
<=
len
)
return
nullptr
;
{
}
// Get the attribute type.
auto
attrType
=
static_cast
<
Attribute
>
(
Utils
::
Byte
::
Get2Bytes
(
data
,
pos
));
hasFingerprint
=
true
;
fingerprintAttrPos
=
pos
;
// Get the attribute length.
fingerprint
=
Utils
::
Byte
::
Get4Bytes
(
attrValuePos
,
0
);
uint16_t
attrLength
=
Utils
::
Byte
::
Get2Bytes
(
data
,
pos
+
2
);
packet
->
SetFingerprint
();
// Ensure the attribute length is not greater than the remaining size.
break
;
if
((
pos
+
4
+
attrLength
)
>
len
)
}
{
MS_WARN_TAG
(
ice
,
"the attribute length exceeds the remaining size, packet discarded"
);
case
Attribute
:
:
ERROR_CODE
:
{
// Ensure attribute length >= 4bytes.
delete
packet
;
if
(
attrLength
<
4
)
{
return
nullptr
;
ELOG_DEBUG
(
"attribute ERROR-CODE must be >= 4bytes length, packet discarded"
);
}
delete
packet
;
// FINGERPRINT must be the last attribute.
return
nullptr
;
if
(
hasFingerprint
)
}
{
MS_WARN_TAG
(
ice
,
"attribute after FINGERPRINT is not allowed, packet discarded"
);
uint8_t
errorClass
=
Utils
::
Byte
::
Get1Byte
(
attrValuePos
,
2
);
uint8_t
errorNumber
=
Utils
::
Byte
::
Get1Byte
(
attrValuePos
,
3
);
delete
packet
;
auto
errorCode
=
static_cast
<
uint16_t
>
(
errorClass
*
100
+
errorNumber
);
return
nullptr
;
}
packet
->
SetErrorCode
(
errorCode
);
// After a MESSAGE-INTEGRITY attribute just FINGERPRINT is allowed.
break
;
if
(
hasMessageIntegrity
&&
attrType
!=
Attribute
::
FINGERPRINT
)
}
{
MS_WARN_TAG
(
default
:
;
ice
,
}
"attribute after MESSAGE-INTEGRITY other than FINGERPRINT is not allowed, "
"packet discarded"
);
// Set next attribute position.
pos
=
static_cast
<
size_t
>
(
Utils
::
Byte
::
PadTo4Bytes
(
static_cast
<
uint16_t
>
(
pos
+
4
+
attrLength
)));
delete
packet
;
}
return
nullptr
;
}
// Ensure current position matches the total length.
if
(
pos
!=
len
)
{
const
uint8_t
*
attrValuePos
=
data
+
pos
+
4
;
ELOG_DEBUG
(
"computed packet size does not match total size, packet discarded"
);
switch
(
attrType
)
delete
packet
;
{
return
nullptr
;
case
Attribute
:
:
USERNAME
:
}
{
packet
->
SetUsername
(
// If it has FINGERPRINT attribute then verify it.
reinterpret_cast
<
const
char
*>
(
attrValuePos
),
static_cast
<
size_t
>
(
attrLength
));
if
(
hasFingerprint
)
{
// Compute the CRC32 of the received packet up to (but excluding) the
break
;
// FINGERPRINT attribute and XOR it with 0x5354554e.
}
uint32_t
computedFingerprint
=
GetCRC32
(
data
,
fingerprintAttrPos
)
^
0x5354554e
;
case
Attribute
:
:
PRIORITY
:
// Compare with the FINGERPRINT value in the packet.
{
if
(
fingerprint
!=
computedFingerprint
)
{
// Ensure attribute length is 4 bytes.
ELOG_DEBUG
(
if
(
attrLength
!=
4
)
"computed FINGERPRINT value does not match the value in the packet, "
{
"packet discarded"
);
MS_WARN_TAG
(
ice
,
"attribute PRIORITY must be 4 bytes length, packet discarded"
);
delete
packet
;
delete
packet
;
return
nullptr
;
return
nullptr
;
}
}
}
packet
->
SetPriority
(
Utils
::
Byte
::
Get4Bytes
(
attrValuePos
,
0
));
return
packet
;
}
break
;
}
/* Instance methods. */
case
Attribute
:
:
ICE_CONTROLLING
:
StunPacket
::
StunPacket
(
Class
klass
,
Method
method
,
const
uint8_t
*
transactionId
,
{
const
uint8_t
*
data
,
size_t
size
)
// Ensure attribute length is 8 bytes.
:
klass
(
klass
),
if
(
attrLength
!=
8
)
method
(
method
),
{
transactionId
(
transactionId
),
MS_WARN_TAG
(
ice
,
"attribute ICE-CONTROLLING must be 8 bytes length, packet discarded"
);
data
(
const_cast
<
uint8_t
*>
(
data
)),
size
(
size
)
{
delete
packet
;
// MS_TRACE();
return
nullptr
;
}
}
StunPacket
::~
StunPacket
()
{
packet
->
SetIceControlling
(
Utils
::
Byte
::
Get8Bytes
(
attrValuePos
,
0
));
// MS_TRACE();
}
break
;
}
StunPacket
::
Authentication
StunPacket
::
CheckAuthentication
(
const
std
::
string
&
localUsername
,
const
std
::
string
&
localPassword
)
{
case
Attribute
:
:
ICE_CONTROLLED
:
// MS_TRACE();
{
// Ensure attribute length is 8 bytes.
switch
(
this
->
klass
)
{
if
(
attrLength
!=
8
)
case
Class
:
:
REQUEST
:
{
case
Class
:
:
INDICATION
:
{
MS_WARN_TAG
(
ice
,
"attribute ICE-CONTROLLED must be 8 bytes length, packet discarded"
);
// Both USERNAME and MESSAGE-INTEGRITY must be present.
if
(
this
->
messageIntegrity
==
nullptr
||
this
->
username
.
empty
())
delete
packet
;
return
Authentication
::
BAD_REQUEST
;
return
nullptr
;
}
// Check that USERNAME attribute begins with our local username plus ":".
size_t
localUsernameLen
=
localUsername
.
length
();
packet
->
SetIceControlled
(
Utils
::
Byte
::
Get8Bytes
(
attrValuePos
,
0
));
if
(
this
->
username
.
length
()
<=
localUsernameLen
||
break
;
this
->
username
.
at
(
localUsernameLen
)
!=
':'
||
}
(
this
->
username
.
compare
(
0
,
localUsernameLen
,
localUsername
)
!=
0
))
{
return
Authentication
::
UNAUTHORIZED
;
case
Attribute
:
:
USE_CANDIDATE
:
}
{
// Ensure attribute length is 0 bytes.
break
;
if
(
attrLength
!=
0
)
}
{
// This method cannot check authentication in received responses (as we
MS_WARN_TAG
(
ice
,
"attribute USE-CANDIDATE must be 0 bytes length, packet discarded"
);
// are ICE-Lite and don't generate requests).
case
Class
:
:
SUCCESS_RESPONSE
:
delete
packet
;
case
Class
:
:
ERROR_RESPONSE
:
{
return
nullptr
;
// MS_ERROR("cannot check authentication for a STUN response");
}
return
Authentication
::
BAD_REQUEST
;
packet
->
SetUseCandidate
();
}
}
break
;
}
// If there is FINGERPRINT it must be discarded for MESSAGE-INTEGRITY calculation,
// so the header length field must be modified (and later restored).
case
Attribute
:
:
MESSAGE_INTEGRITY
:
if
(
this
->
hasFingerprint
)
{
// Set the header length field: full size - header length (20) - FINGERPRINT length (8).
// Ensure attribute length is 20 bytes.
Utils
::
Byte
::
Set2Bytes
(
this
->
data
,
2
,
static_cast
<
uint16_t
>
(
this
->
size
-
20
-
8
));
if
(
attrLength
!=
20
)
{
// Calculate the HMAC-SHA1 of the message according to MESSAGE-INTEGRITY rules.
MS_WARN_TAG
(
ice
,
"attribute MESSAGE-INTEGRITY must be 20 bytes length, packet discarded"
);
auto
computedMessageIntegrity
=
openssl_HMACsha1
(
localPassword
.
data
(),
localPassword
.
size
(),
this
->
data
,
(
this
->
messageIntegrity
-
4
)
-
this
->
data
);
delete
packet
;
return
nullptr
;
Authentication
result
;
}
// Compare the computed HMAC-SHA1 with the MESSAGE-INTEGRITY in the packet.
hasMessageIntegrity
=
true
;
if
(
std
::
memcmp
(
this
->
messageIntegrity
,
computedMessageIntegrity
.
data
(),
computedMessageIntegrity
.
size
())
==
0
)
packet
->
SetMessageIntegrity
(
attrValuePos
);
result
=
Authentication
::
OK
;
else
break
;
result
=
Authentication
::
UNAUTHORIZED
;
}
// Restore the header length field.
case
Attribute
:
:
FINGERPRINT
:
if
(
this
->
hasFingerprint
)
{
Utils
::
Byte
::
Set2Bytes
(
this
->
data
,
2
,
static_cast
<
uint16_t
>
(
this
->
size
-
20
));
// Ensure attribute length is 4 bytes.
if
(
attrLength
!=
4
)
return
result
;
{
}
MS_WARN_TAG
(
ice
,
"attribute FINGERPRINT must be 4 bytes length, packet discarded"
);
StunPacket
*
StunPacket
::
CreateSuccessResponse
()
{
delete
packet
;
// MS_TRACE();
return
nullptr
;
}
// MS_ASSERT(
// this->klass == Class::REQUEST,
hasFingerprint
=
true
;
// "attempt to create a success response for a non Request STUN packet");
fingerprintAttrPos
=
pos
;
fingerprint
=
Utils
::
Byte
::
Get4Bytes
(
attrValuePos
,
0
);
return
new
StunPacket
(
Class
::
SUCCESS_RESPONSE
,
this
->
method
,
this
->
transactionId
,
nullptr
,
0
);
packet
->
SetFingerprint
();
}
break
;
StunPacket
*
StunPacket
::
CreateErrorResponse
(
uint16_t
errorCode
)
{
}
// MS_TRACE();
case
Attribute
:
:
ERROR_CODE
:
// MS_ASSERT(
{
// this->klass == Class::REQUEST,
// Ensure attribute length >= 4bytes.
// "attempt to create an error response for a non Request STUN packet");
if
(
attrLength
<
4
)
{
auto
response
=
MS_WARN_TAG
(
ice
,
"attribute ERROR-CODE must be >= 4bytes length, packet discarded"
);
new
StunPacket
(
Class
::
ERROR_RESPONSE
,
this
->
method
,
this
->
transactionId
,
nullptr
,
0
);
delete
packet
;
response
->
SetErrorCode
(
errorCode
);
return
nullptr
;
}
return
response
;
}
uint8_t
errorClass
=
Utils
::
Byte
::
Get1Byte
(
attrValuePos
,
2
);
uint8_t
errorNumber
=
Utils
::
Byte
::
Get1Byte
(
attrValuePos
,
3
);
void
StunPacket
::
Authenticate
(
const
std
::
string
&
password
)
{
auto
errorCode
=
static_cast
<
uint16_t
>
(
errorClass
*
100
+
errorNumber
);
// Just for Request, Indication and SuccessResponse messages.
if
(
this
->
klass
==
Class
::
ERROR_RESPONSE
)
{
packet
->
SetErrorCode
(
errorCode
);
// MS_ERROR("cannot set password for ErrorResponse messages");
break
;
return
;
}
}
default
:
;
this
->
password
=
password
;
}
}
// Set next attribute position.
void
StunPacket
::
Serialize
(
uint8_t
*
buffer
)
{
pos
=
// MS_TRACE();
static_cast
<
size_t
>
(
Utils
::
Byte
::
PadTo4Bytes
(
static_cast
<
uint16_t
>
(
pos
+
4
+
attrLength
)));
}
// Some useful variables.
uint16_t
usernamePaddedLen
{
0
};
// Ensure current position matches the total length.
uint16_t
xorMappedAddressPaddedLen
{
0
};
if
(
pos
!=
len
)
bool
addXorMappedAddress
=
{
((
this
->
xorMappedAddress
!=
nullptr
)
&&
this
->
method
==
StunPacket
::
Method
::
BINDING
&&
MS_WARN_TAG
(
ice
,
"computed packet size does not match total size, packet discarded"
);
this
->
klass
==
Class
::
SUCCESS_RESPONSE
);
bool
addErrorCode
=
((
this
->
errorCode
!=
0u
)
&&
this
->
klass
==
Class
::
ERROR_RESPONSE
);
delete
packet
;
bool
addMessageIntegrity
=
(
this
->
klass
!=
Class
::
ERROR_RESPONSE
&&
!
this
->
password
.
empty
());
return
nullptr
;
bool
addFingerprint
{
true
};
// Do always.
}
// Update data pointer.
// If it has FINGERPRINT attribute then verify it.
this
->
data
=
buffer
;
if
(
hasFingerprint
)
{
// First calculate the total required size for the entire packet.
// Compute the CRC32 of the received packet up to (but excluding) the
this
->
size
=
20
;
// Header.
// FINGERPRINT attribute and XOR it with 0x5354554e.
uint32_t
computedFingerprint
=
GetCRC32
(
data
,
fingerprintAttrPos
)
^
0x5354554e
;
if
(
!
this
->
username
.
empty
())
{
usernamePaddedLen
=
Utils
::
Byte
::
PadTo4Bytes
(
static_cast
<
uint16_t
>
(
this
->
username
.
length
()));
// Compare with the FINGERPRINT value in the packet.
this
->
size
+=
4
+
usernamePaddedLen
;
if
(
fingerprint
!=
computedFingerprint
)
}
{
MS_WARN_TAG
(
if
(
this
->
priority
!=
0u
)
this
->
size
+=
4
+
4
;
ice
,
"computed FINGERPRINT value does not match the value in the packet, "
if
(
this
->
iceControlling
!=
0u
)
this
->
size
+=
4
+
8
;
"packet discarded"
);
if
(
this
->
iceControlled
!=
0u
)
this
->
size
+=
4
+
8
;
delete
packet
;
return
nullptr
;
if
(
this
->
hasUseCandidate
)
this
->
size
+=
4
;
}
}
if
(
addXorMappedAddress
)
{
switch
(
this
->
xorMappedAddress
->
sa_family
)
{
return
packet
;
case
AF_INET
:
{
}
xorMappedAddressPaddedLen
=
8
;
this
->
size
+=
4
+
8
;
/* Instance methods. */
break
;
StunPacket
::
StunPacket
(
}
Class
klass
,
Method
method
,
const
uint8_t
*
transactionId
,
const
uint8_t
*
data
,
size_t
size
)
:
klass
(
klass
),
method
(
method
),
transactionId
(
transactionId
),
data
(
const_cast
<
uint8_t
*>
(
data
)),
case
AF_INET6
:
{
size
(
size
)
xorMappedAddressPaddedLen
=
20
;
{
this
->
size
+=
4
+
20
;
MS_TRACE
();
}
break
;
}
StunPacket
::~
StunPacket
()
{
default
:
{
MS_TRACE
();
// MS_ERROR("invalid inet family in XOR-MAPPED-ADDRESS attribute");
}
addXorMappedAddress
=
false
;
#if 0
}
void StunPacket::Dump() const
}
{
}
MS_TRACE();
if
(
addErrorCode
)
this
->
size
+=
4
+
4
;
MS_DUMP("<StunPacket>");
if
(
addMessageIntegrity
)
this
->
size
+=
4
+
20
;
std::string klass;
switch (this->klass)
if
(
addFingerprint
)
this
->
size
+=
4
+
4
;
{
case Class::REQUEST:
// Merge class and method fields into type.
klass = "Request";
uint16_t
typeField
=
(
static_cast
<
uint16_t
>
(
this
->
method
)
&
0x0f80
)
<<
2
;
break;
case Class::INDICATION:
typeField
|=
(
static_cast
<
uint16_t
>
(
this
->
method
)
&
0x0070
)
<<
1
;
klass = "Indication";
typeField
|=
(
static_cast
<
uint16_t
>
(
this
->
method
)
&
0x000f
);
break;
typeField
|=
(
static_cast
<
uint16_t
>
(
this
->
klass
)
&
0x02
)
<<
7
;
case Class::SUCCESS_RESPONSE:
typeField
|=
(
static_cast
<
uint16_t
>
(
this
->
klass
)
&
0x01
)
<<
4
;
klass = "SuccessResponse";
break;
// Set type field.
case Class::ERROR_RESPONSE:
Utils
::
Byte
::
Set2Bytes
(
buffer
,
0
,
typeField
);
klass = "ErrorResponse";
// Set length field.
break;
Utils
::
Byte
::
Set2Bytes
(
buffer
,
2
,
static_cast
<
uint16_t
>
(
this
->
size
)
-
20
);
}
// Set magic cookie.
if (this->method == Method::BINDING)
std
::
memcpy
(
buffer
+
4
,
StunPacket
::
kMagicCookie
,
4
);
{
// Set TransactionId field.
MS_DUMP(" Binding %s", klass.c_str());
std
::
memcpy
(
buffer
+
8
,
this
->
transactionId
,
12
);
}
// Update the transaction ID pointer.
else
this
->
transactionId
=
buffer
+
8
;
{
// Add atributes.
// This prints the unknown method number. Example: TURN Allocate => 0x003.
size_t
pos
{
20
};
MS_DUMP(" %s with unknown method %#.3x", klass.c_str(), static_cast<uint16_t>(this->method));
}
// Add USERNAME.
MS_DUMP(" size: %zu bytes", this->size);
if
(
usernamePaddedLen
!=
0u
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
USERNAME
));
static char transactionId[25];
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
static_cast
<
uint16_t
>
(
this
->
username
.
length
()));
std
::
memcpy
(
buffer
+
pos
+
4
,
this
->
username
.
c_str
(),
this
->
username
.
length
());
for (int i{ 0 }; i < 12; ++i)
pos
+=
4
+
usernamePaddedLen
;
{
}
// NOTE: n must be 3 because snprintf adds a \0 after printed chars.
std::snprintf(transactionId + (i * 2), 3, "%.2x", this->transactionId[i]);
// Add PRIORITY.
}
if
(
this
->
priority
!=
0u
)
{
MS_DUMP(" transactionId: %s", transactionId);
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
PRIORITY
));
if (this->errorCode != 0u)
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
4
);
MS_DUMP(" errorCode: %" PRIu16, this->errorCode);
Utils
::
Byte
::
Set4Bytes
(
buffer
,
pos
+
4
,
this
->
priority
);
if (!this->username.empty())
pos
+=
4
+
4
;
MS_DUMP(" username: %s", this->username.c_str());
}
if (this->priority != 0u)
MS_DUMP(" priority: %" PRIu32, this->priority);
// Add ICE-CONTROLLING.
if (this->iceControlling != 0u)
if
(
this
->
iceControlling
!=
0u
)
{
MS_DUMP(" iceControlling: %" PRIu64, this->iceControlling);
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
ICE_CONTROLLING
));
if (this->iceControlled != 0u)
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
8
);
MS_DUMP(" iceControlled: %" PRIu64, this->iceControlled);
Utils
::
Byte
::
Set8Bytes
(
buffer
,
pos
+
4
,
this
->
iceControlling
);
if (this->hasUseCandidate)
pos
+=
4
+
8
;
MS_DUMP(" useCandidate");
}
if (this->xorMappedAddress != nullptr)
{
// Add ICE-CONTROLLED.
int family;
if
(
this
->
iceControlled
!=
0u
)
{
uint16_t port;
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
ICE_CONTROLLED
));
std::string ip;
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
8
);
Utils
::
Byte
::
Set8Bytes
(
buffer
,
pos
+
4
,
this
->
iceControlled
);
Utils::IP::GetAddressInfo(this->xorMappedAddress, family, ip, port);
pos
+=
4
+
8
;
}
MS_DUMP(" xorMappedAddress: %s : %" PRIu16, ip.c_str(), port);
}
// Add USE-CANDIDATE.
if (this->messageIntegrity != nullptr)
if
(
this
->
hasUseCandidate
)
{
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
USE_CANDIDATE
));
static char messageIntegrity[41];
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
0
);
pos
+=
4
;
for (int i{ 0 }; i < 20; ++i)
}
{
std::snprintf(messageIntegrity + (i * 2), 3, "%.2x", this->messageIntegrity[i]);
// Add XOR-MAPPED-ADDRESS
}
if
(
addXorMappedAddress
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
XOR_MAPPED_ADDRESS
));
MS_DUMP(" messageIntegrity: %s", messageIntegrity);
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
xorMappedAddressPaddedLen
);
}
if (this->hasFingerprint)
uint8_t
*
attrValue
=
buffer
+
pos
+
4
;
MS_DUMP(" has fingerprint");
switch
(
this
->
xorMappedAddress
->
sa_family
)
{
MS_DUMP("</StunPacket>");
case
AF_INET
:
{
}
// Set first byte to 0.
#endif
attrValue
[
0
]
=
0
;
// Set inet family.
StunPacket
::
Authentication
StunPacket
::
CheckAuthentication
(
attrValue
[
1
]
=
0x01
;
const
std
::
string
&
localUsername
,
const
std
::
string
&
localPassword
)
// Set port and XOR it.
{
std
::
memcpy
(
attrValue
+
2
,
MS_TRACE
();
&
(
reinterpret_cast
<
const
sockaddr_in
*>
(
this
->
xorMappedAddress
))
->
sin_port
,
2
);
attrValue
[
2
]
^=
StunPacket
::
kMagicCookie
[
0
];
switch
(
this
->
klass
)
attrValue
[
3
]
^=
StunPacket
::
kMagicCookie
[
1
];
{
// Set address and XOR it.
case
Class
:
:
REQUEST
:
std
::
memcpy
(
case
Class
:
:
INDICATION
:
attrValue
+
4
,
{
&
(
reinterpret_cast
<
const
sockaddr_in
*>
(
this
->
xorMappedAddress
))
->
sin_addr
.
s_addr
,
4
);
// Both USERNAME and MESSAGE-INTEGRITY must be present.
attrValue
[
4
]
^=
StunPacket
::
kMagicCookie
[
0
];
if
(
!
this
->
messageIntegrity
||
this
->
username
.
empty
())
attrValue
[
5
]
^=
StunPacket
::
kMagicCookie
[
1
];
return
Authentication
::
BAD_REQUEST
;
attrValue
[
6
]
^=
StunPacket
::
kMagicCookie
[
2
];
attrValue
[
7
]
^=
StunPacket
::
kMagicCookie
[
3
];
// Check that USERNAME attribute begins with our local username plus ":".
size_t
localUsernameLen
=
localUsername
.
length
();
pos
+=
4
+
8
;
if
(
break
;
this
->
username
.
length
()
<=
localUsernameLen
||
this
->
username
.
at
(
localUsernameLen
)
!=
':'
||
}
(
this
->
username
.
compare
(
0
,
localUsernameLen
,
localUsername
)
!=
0
))
{
case
AF_INET6
:
{
return
Authentication
::
UNAUTHORIZED
;
// Set first byte to 0.
}
attrValue
[
0
]
=
0
;
// Set inet family.
break
;
attrValue
[
1
]
=
0x02
;
}
// Set port and XOR it.
// This method cannot check authentication in received responses (as we
std
::
memcpy
(
attrValue
+
2
,
// are ICE-Lite and don't generate requests).
&
(
reinterpret_cast
<
const
sockaddr_in6
*>
(
this
->
xorMappedAddress
))
->
sin6_port
,
2
);
case
Class
:
:
SUCCESS_RESPONSE
:
attrValue
[
2
]
^=
StunPacket
::
kMagicCookie
[
0
];
case
Class
:
:
ERROR_RESPONSE
:
attrValue
[
3
]
^=
StunPacket
::
kMagicCookie
[
1
];
{
// Set address and XOR it.
MS_ERROR
(
"cannot check authentication for a STUN response"
);
std
::
memcpy
(
attrValue
+
4
,
return
Authentication
::
BAD_REQUEST
;
&
(
reinterpret_cast
<
const
sockaddr_in6
*>
(
this
->
xorMappedAddress
))
->
sin6_addr
.
s6_addr
,
}
16
);
}
attrValue
[
4
]
^=
StunPacket
::
kMagicCookie
[
0
];
attrValue
[
5
]
^=
StunPacket
::
kMagicCookie
[
1
];
// If there is FINGERPRINT it must be discarded for MESSAGE-INTEGRITY calculation,
attrValue
[
6
]
^=
StunPacket
::
kMagicCookie
[
2
];
// so the header length field must be modified (and later restored).
attrValue
[
7
]
^=
StunPacket
::
kMagicCookie
[
3
];
if
(
this
->
hasFingerprint
)
attrValue
[
8
]
^=
this
->
transactionId
[
0
];
// Set the header length field: full size - header length (20) - FINGERPRINT length (8).
attrValue
[
9
]
^=
this
->
transactionId
[
1
];
Utils
::
Byte
::
Set2Bytes
(
this
->
data
,
2
,
static_cast
<
uint16_t
>
(
this
->
size
-
20
-
8
));
attrValue
[
10
]
^=
this
->
transactionId
[
2
];
attrValue
[
11
]
^=
this
->
transactionId
[
3
];
// Calculate the HMAC-SHA1 of the message according to MESSAGE-INTEGRITY rules.
attrValue
[
12
]
^=
this
->
transactionId
[
4
];
auto
computedMessageIntegrity
=
openssl_HMACsha1
(
attrValue
[
13
]
^=
this
->
transactionId
[
5
];
localPassword
.
data
(),
localPassword
.
size
(),
this
->
data
,
(
this
->
messageIntegrity
-
4
)
-
this
->
data
);
attrValue
[
14
]
^=
this
->
transactionId
[
6
];
attrValue
[
15
]
^=
this
->
transactionId
[
7
];
Authentication
result
;
attrValue
[
16
]
^=
this
->
transactionId
[
8
];
attrValue
[
17
]
^=
this
->
transactionId
[
9
];
// Compare the computed HMAC-SHA1 with the MESSAGE-INTEGRITY in the packet.
attrValue
[
18
]
^=
this
->
transactionId
[
10
];
if
(
std
::
memcmp
(
this
->
messageIntegrity
,
computedMessageIntegrity
.
data
(),
computedMessageIntegrity
.
size
())
==
0
)
attrValue
[
19
]
^=
this
->
transactionId
[
11
];
result
=
Authentication
::
OK
;
else
pos
+=
4
+
20
;
result
=
Authentication
::
UNAUTHORIZED
;
break
;
// Restore the header length field.
}
if
(
this
->
hasFingerprint
)
}
Utils
::
Byte
::
Set2Bytes
(
this
->
data
,
2
,
static_cast
<
uint16_t
>
(
this
->
size
-
20
));
}
return
result
;
// Add ERROR-CODE.
}
if
(
addErrorCode
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
ERROR_CODE
));
StunPacket
*
StunPacket
::
CreateSuccessResponse
()
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
4
);
{
MS_TRACE
();
auto
codeClass
=
static_cast
<
uint8_t
>
(
this
->
errorCode
/
100
);
uint8_t
codeNumber
=
static_cast
<
uint8_t
>
(
this
->
errorCode
)
-
(
codeClass
*
100
);
MS_ASSERT
(
this
->
klass
==
Class
::
REQUEST
,
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
4
,
0
);
"attempt to create a success response for a non Request STUN packet"
);
Utils
::
Byte
::
Set1Byte
(
buffer
,
pos
+
6
,
codeClass
);
Utils
::
Byte
::
Set1Byte
(
buffer
,
pos
+
7
,
codeNumber
);
return
new
StunPacket
(
Class
::
SUCCESS_RESPONSE
,
this
->
method
,
this
->
transactionId
,
nullptr
,
0
);
pos
+=
4
+
4
;
}
}
StunPacket
*
StunPacket
::
CreateErrorResponse
(
uint16_t
errorCode
)
// Add MESSAGE-INTEGRITY.
{
if
(
addMessageIntegrity
)
{
MS_TRACE
();
// Ignore FINGERPRINT.
if
(
addFingerprint
)
MS_ASSERT
(
Utils
::
Byte
::
Set2Bytes
(
buffer
,
2
,
static_cast
<
uint16_t
>
(
this
->
size
-
20
-
8
));
this
->
klass
==
Class
::
REQUEST
,
"attempt to create an error response for a non Request STUN packet"
);
// Calculate the HMAC-SHA1 of the packet according to MESSAGE-INTEGRITY rules.
auto
computedMessageIntegrity
=
openssl_HMACsha1
(
this
->
password
.
data
(),
this
->
password
.
size
(),
buffer
,
pos
);
auto
*
response
=
new
StunPacket
(
Class
::
ERROR_RESPONSE
,
this
->
method
,
this
->
transactionId
,
nullptr
,
0
);
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
MESSAGE_INTEGRITY
));
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
20
);
response
->
SetErrorCode
(
errorCode
);
std
::
memcpy
(
buffer
+
pos
+
4
,
computedMessageIntegrity
.
data
(),
computedMessageIntegrity
.
size
());
return
response
;
// Update the pointer.
}
this
->
messageIntegrity
=
buffer
+
pos
+
4
;
pos
+=
4
+
20
;
void
StunPacket
::
Authenticate
(
const
std
::
string
&
password
)
{
// Restore length field.
// Just for Request, Indication and SuccessResponse messages.
if
(
addFingerprint
)
Utils
::
Byte
::
Set2Bytes
(
buffer
,
2
,
static_cast
<
uint16_t
>
(
this
->
size
-
20
));
if
(
this
->
klass
==
Class
::
ERROR_RESPONSE
)
}
else
{
{
// Unset the pointer (if it was set).
MS_ERROR
(
"cannot set password for ErrorResponse messages"
);
this
->
messageIntegrity
=
nullptr
;
}
return
;
}
// Add FINGERPRINT.
if
(
addFingerprint
)
{
this
->
password
=
password
;
// Compute the CRC32 of the packet up to (but excluding) the FINGERPRINT
}
// attribute and XOR it with 0x5354554e.
uint32_t
computedFingerprint
=
GetCRC32
(
buffer
,
pos
)
^
0x5354554e
;
void
StunPacket
::
Serialize
(
uint8_t
*
buffer
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
FINGERPRINT
));
MS_TRACE
();
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
4
);
Utils
::
Byte
::
Set4Bytes
(
buffer
,
pos
+
4
,
computedFingerprint
);
// Some useful variables.
pos
+=
4
+
4
;
uint16_t
usernamePaddedLen
{
0
};
uint16_t
xorMappedAddressPaddedLen
{
0
};
// Set flag.
bool
addXorMappedAddress
=
this
->
hasFingerprint
=
true
;
((
this
->
xorMappedAddress
!=
nullptr
)
&&
this
->
method
==
StunPacket
::
Method
::
BINDING
&&
}
else
{
this
->
klass
==
Class
::
SUCCESS_RESPONSE
);
this
->
hasFingerprint
=
false
;
bool
addErrorCode
=
((
this
->
errorCode
!=
0u
)
&&
this
->
klass
==
Class
::
ERROR_RESPONSE
);
}
bool
addMessageIntegrity
=
(
this
->
klass
!=
Class
::
ERROR_RESPONSE
&&
!
this
->
password
.
empty
());
bool
addFingerprint
{
true
};
// Do always.
// MS_ASSERT(pos == this->size, "pos != this->size");
}
// Update data pointer.
}
// namespace RTC
this
->
data
=
buffer
;
// First calculate the total required size for the entire packet.
this
->
size
=
20
;
// Header.
if
(
!
this
->
username
.
empty
())
{
usernamePaddedLen
=
Utils
::
Byte
::
PadTo4Bytes
(
static_cast
<
uint16_t
>
(
this
->
username
.
length
()));
this
->
size
+=
4
+
usernamePaddedLen
;
}
if
(
this
->
priority
!=
0u
)
this
->
size
+=
4
+
4
;
if
(
this
->
iceControlling
!=
0u
)
this
->
size
+=
4
+
8
;
if
(
this
->
iceControlled
!=
0u
)
this
->
size
+=
4
+
8
;
if
(
this
->
hasUseCandidate
)
this
->
size
+=
4
;
if
(
addXorMappedAddress
)
{
switch
(
this
->
xorMappedAddress
->
sa_family
)
{
case
AF_INET
:
{
xorMappedAddressPaddedLen
=
8
;
this
->
size
+=
4
+
8
;
break
;
}
case
AF_INET6
:
{
xorMappedAddressPaddedLen
=
20
;
this
->
size
+=
4
+
20
;
break
;
}
default
:
{
MS_ERROR
(
"invalid inet family in XOR-MAPPED-ADDRESS attribute"
);
addXorMappedAddress
=
false
;
}
}
}
if
(
addErrorCode
)
this
->
size
+=
4
+
4
;
if
(
addMessageIntegrity
)
this
->
size
+=
4
+
20
;
if
(
addFingerprint
)
this
->
size
+=
4
+
4
;
// Merge class and method fields into type.
uint16_t
typeField
=
(
static_cast
<
uint16_t
>
(
this
->
method
)
&
0x0f80
)
<<
2
;
typeField
|=
(
static_cast
<
uint16_t
>
(
this
->
method
)
&
0x0070
)
<<
1
;
typeField
|=
(
static_cast
<
uint16_t
>
(
this
->
method
)
&
0x000f
);
typeField
|=
(
static_cast
<
uint16_t
>
(
this
->
klass
)
&
0x02
)
<<
7
;
typeField
|=
(
static_cast
<
uint16_t
>
(
this
->
klass
)
&
0x01
)
<<
4
;
// Set type field.
Utils
::
Byte
::
Set2Bytes
(
buffer
,
0
,
typeField
);
// Set length field.
Utils
::
Byte
::
Set2Bytes
(
buffer
,
2
,
static_cast
<
uint16_t
>
(
this
->
size
)
-
20
);
// Set magic cookie.
std
::
memcpy
(
buffer
+
4
,
StunPacket
::
magicCookie
,
4
);
// Set TransactionId field.
std
::
memcpy
(
buffer
+
8
,
this
->
transactionId
,
12
);
// Update the transaction ID pointer.
this
->
transactionId
=
buffer
+
8
;
// Add atributes.
size_t
pos
{
20
};
// Add USERNAME.
if
(
usernamePaddedLen
!=
0u
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
USERNAME
));
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
static_cast
<
uint16_t
>
(
this
->
username
.
length
()));
std
::
memcpy
(
buffer
+
pos
+
4
,
this
->
username
.
c_str
(),
this
->
username
.
length
());
pos
+=
4
+
usernamePaddedLen
;
}
// Add PRIORITY.
if
(
this
->
priority
!=
0u
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
PRIORITY
));
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
4
);
Utils
::
Byte
::
Set4Bytes
(
buffer
,
pos
+
4
,
this
->
priority
);
pos
+=
4
+
4
;
}
// Add ICE-CONTROLLING.
if
(
this
->
iceControlling
!=
0u
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
ICE_CONTROLLING
));
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
8
);
Utils
::
Byte
::
Set8Bytes
(
buffer
,
pos
+
4
,
this
->
iceControlling
);
pos
+=
4
+
8
;
}
// Add ICE-CONTROLLED.
if
(
this
->
iceControlled
!=
0u
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
ICE_CONTROLLED
));
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
8
);
Utils
::
Byte
::
Set8Bytes
(
buffer
,
pos
+
4
,
this
->
iceControlled
);
pos
+=
4
+
8
;
}
// Add USE-CANDIDATE.
if
(
this
->
hasUseCandidate
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
USE_CANDIDATE
));
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
0
);
pos
+=
4
;
}
// Add XOR-MAPPED-ADDRESS
if
(
addXorMappedAddress
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
XOR_MAPPED_ADDRESS
));
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
xorMappedAddressPaddedLen
);
uint8_t
*
attrValue
=
buffer
+
pos
+
4
;
switch
(
this
->
xorMappedAddress
->
sa_family
)
{
case
AF_INET
:
{
// Set first byte to 0.
attrValue
[
0
]
=
0
;
// Set inet family.
attrValue
[
1
]
=
0x01
;
// Set port and XOR it.
std
::
memcpy
(
attrValue
+
2
,
&
(
reinterpret_cast
<
const
sockaddr_in
*>
(
this
->
xorMappedAddress
))
->
sin_port
,
2
);
attrValue
[
2
]
^=
StunPacket
::
magicCookie
[
0
];
attrValue
[
3
]
^=
StunPacket
::
magicCookie
[
1
];
// Set address and XOR it.
std
::
memcpy
(
attrValue
+
4
,
&
(
reinterpret_cast
<
const
sockaddr_in
*>
(
this
->
xorMappedAddress
))
->
sin_addr
.
s_addr
,
4
);
attrValue
[
4
]
^=
StunPacket
::
magicCookie
[
0
];
attrValue
[
5
]
^=
StunPacket
::
magicCookie
[
1
];
attrValue
[
6
]
^=
StunPacket
::
magicCookie
[
2
];
attrValue
[
7
]
^=
StunPacket
::
magicCookie
[
3
];
pos
+=
4
+
8
;
break
;
}
case
AF_INET6
:
{
// Set first byte to 0.
attrValue
[
0
]
=
0
;
// Set inet family.
attrValue
[
1
]
=
0x02
;
// Set port and XOR it.
std
::
memcpy
(
attrValue
+
2
,
&
(
reinterpret_cast
<
const
sockaddr_in6
*>
(
this
->
xorMappedAddress
))
->
sin6_port
,
2
);
attrValue
[
2
]
^=
StunPacket
::
magicCookie
[
0
];
attrValue
[
3
]
^=
StunPacket
::
magicCookie
[
1
];
// Set address and XOR it.
std
::
memcpy
(
attrValue
+
4
,
&
(
reinterpret_cast
<
const
sockaddr_in6
*>
(
this
->
xorMappedAddress
))
->
sin6_addr
.
s6_addr
,
16
);
attrValue
[
4
]
^=
StunPacket
::
magicCookie
[
0
];
attrValue
[
5
]
^=
StunPacket
::
magicCookie
[
1
];
attrValue
[
6
]
^=
StunPacket
::
magicCookie
[
2
];
attrValue
[
7
]
^=
StunPacket
::
magicCookie
[
3
];
attrValue
[
8
]
^=
this
->
transactionId
[
0
];
attrValue
[
9
]
^=
this
->
transactionId
[
1
];
attrValue
[
10
]
^=
this
->
transactionId
[
2
];
attrValue
[
11
]
^=
this
->
transactionId
[
3
];
attrValue
[
12
]
^=
this
->
transactionId
[
4
];
attrValue
[
13
]
^=
this
->
transactionId
[
5
];
attrValue
[
14
]
^=
this
->
transactionId
[
6
];
attrValue
[
15
]
^=
this
->
transactionId
[
7
];
attrValue
[
16
]
^=
this
->
transactionId
[
8
];
attrValue
[
17
]
^=
this
->
transactionId
[
9
];
attrValue
[
18
]
^=
this
->
transactionId
[
10
];
attrValue
[
19
]
^=
this
->
transactionId
[
11
];
pos
+=
4
+
20
;
break
;
}
}
}
// Add ERROR-CODE.
if
(
addErrorCode
)
{
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
ERROR_CODE
));
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
4
);
auto
codeClass
=
static_cast
<
uint8_t
>
(
this
->
errorCode
/
100
);
uint8_t
codeNumber
=
static_cast
<
uint8_t
>
(
this
->
errorCode
)
-
(
codeClass
*
100
);
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
4
,
0
);
Utils
::
Byte
::
Set1Byte
(
buffer
,
pos
+
6
,
codeClass
);
Utils
::
Byte
::
Set1Byte
(
buffer
,
pos
+
7
,
codeNumber
);
pos
+=
4
+
4
;
}
// Add MESSAGE-INTEGRITY.
if
(
addMessageIntegrity
)
{
// Ignore FINGERPRINT.
if
(
addFingerprint
)
Utils
::
Byte
::
Set2Bytes
(
buffer
,
2
,
static_cast
<
uint16_t
>
(
this
->
size
-
20
-
8
));
// Calculate the HMAC-SHA1 of the packet according to MESSAGE-INTEGRITY rules.
auto
computedMessageIntegrity
=
openssl_HMACsha1
(
this
->
password
.
data
(),
this
->
password
.
size
(),
buffer
,
pos
);
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
MESSAGE_INTEGRITY
));
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
20
);
std
::
memcpy
(
buffer
+
pos
+
4
,
computedMessageIntegrity
.
data
(),
computedMessageIntegrity
.
size
());
// Update the pointer.
this
->
messageIntegrity
=
buffer
+
pos
+
4
;
pos
+=
4
+
20
;
// Restore length field.
if
(
addFingerprint
)
Utils
::
Byte
::
Set2Bytes
(
buffer
,
2
,
static_cast
<
uint16_t
>
(
this
->
size
-
20
));
}
else
{
// Unset the pointer (if it was set).
this
->
messageIntegrity
=
nullptr
;
}
// Add FINGERPRINT.
if
(
addFingerprint
)
{
// Compute the CRC32 of the packet up to (but excluding) the FINGERPRINT
// attribute and XOR it with 0x5354554e.
uint32_t
computedFingerprint
=
GetCRC32
(
buffer
,
pos
)
^
0x5354554e
;
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
,
static_cast
<
uint16_t
>
(
Attribute
::
FINGERPRINT
));
Utils
::
Byte
::
Set2Bytes
(
buffer
,
pos
+
2
,
4
);
Utils
::
Byte
::
Set4Bytes
(
buffer
,
pos
+
4
,
computedFingerprint
);
pos
+=
4
+
4
;
// Set flag.
this
->
hasFingerprint
=
true
;
}
else
{
this
->
hasFingerprint
=
false
;
}
MS_ASSERT
(
pos
==
this
->
size
,
"pos != this->size"
);
}
}
// namespace RTC
webrtc/StunPacket.hpp
0 → 100644
查看文件 @
bdf2783a
#ifndef MS_RTC_STUN_PACKET_HPP
#define MS_RTC_STUN_PACKET_HPP
#include "logger.h"
#include "Utils.hpp"
#include <string>
namespace
RTC
{
class
StunPacket
{
public
:
// STUN message class.
enum
class
Class
:
uint16_t
{
REQUEST
=
0
,
INDICATION
=
1
,
SUCCESS_RESPONSE
=
2
,
ERROR_RESPONSE
=
3
};
// STUN message method.
enum
class
Method
:
uint16_t
{
BINDING
=
1
};
// Attribute type.
enum
class
Attribute
:
uint16_t
{
MAPPED_ADDRESS
=
0x0001
,
USERNAME
=
0x0006
,
MESSAGE_INTEGRITY
=
0x0008
,
ERROR_CODE
=
0x0009
,
UNKNOWN_ATTRIBUTES
=
0x000A
,
REALM
=
0x0014
,
NONCE
=
0x0015
,
XOR_MAPPED_ADDRESS
=
0x0020
,
PRIORITY
=
0x0024
,
USE_CANDIDATE
=
0x0025
,
SOFTWARE
=
0x8022
,
ALTERNATE_SERVER
=
0x8023
,
FINGERPRINT
=
0x8028
,
ICE_CONTROLLED
=
0x8029
,
ICE_CONTROLLING
=
0x802A
};
// Authentication result.
enum
class
Authentication
{
OK
=
0
,
UNAUTHORIZED
=
1
,
BAD_REQUEST
=
2
};
public
:
static
bool
IsStun
(
const
uint8_t
*
data
,
size_t
len
)
{
// clang-format off
return
(
// STUN headers are 20 bytes.
(
len
>=
20
)
&&
// DOC: https://tools.ietf.org/html/draft-ietf-avtcore-rfc5764-mux-fixes
(
data
[
0
]
<
3
)
&&
// Magic cookie must match.
(
data
[
4
]
==
StunPacket
::
magicCookie
[
0
])
&&
(
data
[
5
]
==
StunPacket
::
magicCookie
[
1
])
&&
(
data
[
6
]
==
StunPacket
::
magicCookie
[
2
])
&&
(
data
[
7
]
==
StunPacket
::
magicCookie
[
3
])
);
// clang-format on
}
static
StunPacket
*
Parse
(
const
uint8_t
*
data
,
size_t
len
);
private
:
static
const
uint8_t
magicCookie
[];
public
:
StunPacket
(
Class
klass
,
Method
method
,
const
uint8_t
*
transactionId
,
const
uint8_t
*
data
,
size_t
size
);
~
StunPacket
();
void
Dump
()
const
;
Class
GetClass
()
const
{
return
this
->
klass
;
}
Method
GetMethod
()
const
{
return
this
->
method
;
}
const
uint8_t
*
GetData
()
const
{
return
this
->
data
;
}
size_t
GetSize
()
const
{
return
this
->
size
;
}
void
SetUsername
(
const
char
*
username
,
size_t
len
)
{
this
->
username
.
assign
(
username
,
len
);
}
void
SetPriority
(
uint32_t
priority
)
{
this
->
priority
=
priority
;
}
void
SetIceControlling
(
uint64_t
iceControlling
)
{
this
->
iceControlling
=
iceControlling
;
}
void
SetIceControlled
(
uint64_t
iceControlled
)
{
this
->
iceControlled
=
iceControlled
;
}
void
SetUseCandidate
()
{
this
->
hasUseCandidate
=
true
;
}
void
SetXorMappedAddress
(
const
struct
sockaddr
*
xorMappedAddress
)
{
this
->
xorMappedAddress
=
xorMappedAddress
;
}
void
SetErrorCode
(
uint16_t
errorCode
)
{
this
->
errorCode
=
errorCode
;
}
void
SetMessageIntegrity
(
const
uint8_t
*
messageIntegrity
)
{
this
->
messageIntegrity
=
messageIntegrity
;
}
void
SetFingerprint
()
{
this
->
hasFingerprint
=
true
;
}
const
std
::
string
&
GetUsername
()
const
{
return
this
->
username
;
}
uint32_t
GetPriority
()
const
{
return
this
->
priority
;
}
uint64_t
GetIceControlling
()
const
{
return
this
->
iceControlling
;
}
uint64_t
GetIceControlled
()
const
{
return
this
->
iceControlled
;
}
bool
HasUseCandidate
()
const
{
return
this
->
hasUseCandidate
;
}
uint16_t
GetErrorCode
()
const
{
return
this
->
errorCode
;
}
bool
HasMessageIntegrity
()
const
{
return
(
this
->
messageIntegrity
?
true
:
false
);
}
bool
HasFingerprint
()
const
{
return
this
->
hasFingerprint
;
}
Authentication
CheckAuthentication
(
const
std
::
string
&
localUsername
,
const
std
::
string
&
localPassword
);
StunPacket
*
CreateSuccessResponse
();
StunPacket
*
CreateErrorResponse
(
uint16_t
errorCode
);
void
Authenticate
(
const
std
::
string
&
password
);
void
Serialize
(
uint8_t
*
buffer
);
private
:
// Passed by argument.
Class
klass
;
// 2 bytes.
Method
method
;
// 2 bytes.
const
uint8_t
*
transactionId
{
nullptr
};
// 12 bytes.
uint8_t
*
data
{
nullptr
};
// Pointer to binary data.
size_t
size
{
0u
};
// The full message size (including header).
// STUN attributes.
std
::
string
username
;
// Less than 513 bytes.
uint32_t
priority
{
0u
};
// 4 bytes unsigned integer.
uint64_t
iceControlling
{
0u
};
// 8 bytes unsigned integer.
uint64_t
iceControlled
{
0u
};
// 8 bytes unsigned integer.
bool
hasUseCandidate
{
false
};
// 0 bytes.
const
uint8_t
*
messageIntegrity
{
nullptr
};
// 20 bytes.
bool
hasFingerprint
{
false
};
// 4 bytes.
const
struct
sockaddr
*
xorMappedAddress
{
nullptr
};
// 8 or 20 bytes.
uint16_t
errorCode
{
0u
};
// 4 bytes (no reason phrase).
std
::
string
password
;
};
}
// namespace RTC
#endif
webrtc/
utils.h
→
webrtc/
Utils.hpp
查看文件 @
bdf2783a
File moved
webrtc/
webrtc_transport.cc
→
webrtc/
WebRtcTransport.cpp
查看文件 @
bdf2783a
#include "
webrtc_t
ransport.h"
#include "
WebRtcT
ransport.h"
#include <iostream>
#include <iostream>
#include "Rtcp/Rtcp.h"
#include "Rtcp/Rtcp.h"
...
...
webrtc/
webrtc_t
ransport.h
→
webrtc/
WebRtcT
ransport.h
查看文件 @
bdf2783a
...
@@ -3,10 +3,10 @@
...
@@ -3,10 +3,10 @@
#include <memory>
#include <memory>
#include <string>
#include <string>
#include "
rtc_dtls_transport.h
"
#include "
DtlsTransport.hpp
"
#include "
ice_server.h
"
#include "
IceServer.hpp
"
#include "
srtp_session.h
"
#include "
SrtpSession.hpp
"
#include "
stun_packet.h
"
#include "
StunPacket.hpp
"
class
WebRtcTransport
:
public
RTC
::
DtlsTransport
::
Listener
,
public
RTC
::
IceServer
::
Listener
{
class
WebRtcTransport
:
public
RTC
::
DtlsTransport
::
Listener
,
public
RTC
::
IceServer
::
Listener
{
public
:
public
:
...
...
webrtc/logger.h
查看文件 @
bdf2783a
...
@@ -2,9 +2,6 @@
...
@@ -2,9 +2,6 @@
#include <stdio.h>
#include <stdio.h>
#include <assert.h>
#include <assert.h>
#define ELOG_DEBUG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
#define ELOG_WARN(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
#define MS_TRACE()
#define MS_TRACE()
#define MS_ERROR(fmt, ...) printf("error:" fmt "\n", ##__VA_ARGS__)
#define MS_ERROR(fmt, ...) printf("error:" fmt "\n", ##__VA_ARGS__)
#define MS_THROW_ERROR(fmt, ...) do{ printf("throw:" fmt "\n", ##__VA_ARGS__); throw std::runtime_error("error"); } while(false);
#define MS_THROW_ERROR(fmt, ...) do{ printf("throw:" fmt "\n", ##__VA_ARGS__); throw std::runtime_error("error"); } while(false);
...
...
webrtc/stun_packet.h
deleted
100644 → 0
查看文件 @
704421b7
#ifndef MS_RTC_STUN_PACKET_HPP
#define MS_RTC_STUN_PACKET_HPP
#include "logger.h"
#include "utils.h"
#include <string>
namespace
RTC
{
class
StunPacket
{
public
:
// STUN message class.
enum
class
Class
:
uint16_t
{
REQUEST
=
0
,
INDICATION
=
1
,
SUCCESS_RESPONSE
=
2
,
ERROR_RESPONSE
=
3
};
// STUN message method.
enum
class
Method
:
uint16_t
{
BINDING
=
1
};
// Attribute type.
enum
class
Attribute
:
uint16_t
{
MAPPED_ADDRESS
=
0x0001
,
USERNAME
=
0x0006
,
MESSAGE_INTEGRITY
=
0x0008
,
ERROR_CODE
=
0x0009
,
UNKNOWN_ATTRIBUTES
=
0x000A
,
REALM
=
0x0014
,
NONCE
=
0x0015
,
XOR_MAPPED_ADDRESS
=
0x0020
,
PRIORITY
=
0x0024
,
USE_CANDIDATE
=
0x0025
,
SOFTWARE
=
0x8022
,
ALTERNATE_SERVER
=
0x8023
,
FINGERPRINT
=
0x8028
,
ICE_CONTROLLED
=
0x8029
,
ICE_CONTROLLING
=
0x802A
};
// Authentication result.
enum
class
Authentication
{
OK
=
0
,
UNAUTHORIZED
=
1
,
BAD_REQUEST
=
2
};
public
:
static
bool
IsStun
(
const
uint8_t
*
data
,
size_t
len
);
static
StunPacket
*
Parse
(
const
uint8_t
*
data
,
size_t
len
);
private
:
static
const
uint8_t
kMagicCookie
[];
public
:
StunPacket
(
Class
klass
,
Method
method
,
const
uint8_t
*
transactionId
,
const
uint8_t
*
data
,
size_t
size
);
~
StunPacket
();
void
Dump
()
const
;
Class
GetClass
()
const
;
Method
GetMethod
()
const
;
const
uint8_t
*
GetData
()
const
;
size_t
GetSize
()
const
;
void
SetUsername
(
const
char
*
username
,
size_t
len
);
void
SetPriority
(
uint32_t
priority
);
void
SetIceControlling
(
uint64_t
iceControlling
);
void
SetIceControlled
(
uint64_t
iceControlled
);
void
SetUseCandidate
();
void
SetXorMappedAddress
(
const
struct
sockaddr
*
xorMappedAddress
);
void
SetErrorCode
(
uint16_t
errorCode
);
void
SetMessageIntegrity
(
const
uint8_t
*
messageIntegrity
);
void
SetFingerprint
();
const
std
::
string
&
GetUsername
()
const
;
uint32_t
GetPriority
()
const
;
uint64_t
GetIceControlling
()
const
;
uint64_t
GetIceControlled
()
const
;
bool
HasUseCandidate
()
const
;
uint16_t
GetErrorCode
()
const
;
bool
HasMessageIntegrity
()
const
;
bool
HasFingerprint
()
const
;
Authentication
CheckAuthentication
(
const
std
::
string
&
localUsername
,
const
std
::
string
&
localPassword
);
StunPacket
*
CreateSuccessResponse
();
StunPacket
*
CreateErrorResponse
(
uint16_t
errorCode
);
void
Authenticate
(
const
std
::
string
&
password
);
void
Serialize
(
uint8_t
*
buffer
);
private
:
// Passed by argument.
Class
klass
;
// 2 bytes.
Method
method
;
// 2 bytes.
const
uint8_t
*
transactionId
{
nullptr
};
// 12 bytes.
uint8_t
*
data
{
nullptr
};
// Pointer to binary data.
size_t
size
{
0
};
// The full message size (including header).
// STUN attributes.
std
::
string
username
;
// Less than 513 bytes.
uint32_t
priority
{
0
};
// 4 bytes unsigned integer.
uint64_t
iceControlling
{
0
};
// 8 bytes unsigned integer.
uint64_t
iceControlled
{
0
};
// 8 bytes unsigned integer.
bool
hasUseCandidate
{
false
};
// 0 bytes.
const
uint8_t
*
messageIntegrity
{
nullptr
};
// 20 bytes.
bool
hasFingerprint
{
false
};
// 4 bytes.
const
struct
sockaddr
*
xorMappedAddress
{
nullptr
};
// 8 or 20 bytes.
uint16_t
errorCode
{
0
};
// 4 bytes (no reason phrase).
std
::
string
password
;
};
/* Inline class methods. */
inline
bool
StunPacket
::
IsStun
(
const
uint8_t
*
data
,
size_t
len
)
{
// clang-format off
return
(
// STUN headers are 20 bytes.
(
len
>=
20
)
&&
// DOC: https://tools.ietf.org/html/draft-ietf-avtcore-rfc5764-mux-fixes
(
data
[
0
]
<
3
)
&&
// Magic cookie must match.
(
data
[
4
]
==
StunPacket
::
kMagicCookie
[
0
])
&&
(
data
[
5
]
==
StunPacket
::
kMagicCookie
[
1
])
&&
(
data
[
6
]
==
StunPacket
::
kMagicCookie
[
2
])
&&
(
data
[
7
]
==
StunPacket
::
kMagicCookie
[
3
])
);
// clang-format on
}
/* Inline instance methods. */
inline
StunPacket
::
Class
StunPacket
::
GetClass
()
const
{
return
this
->
klass
;
}
inline
StunPacket
::
Method
StunPacket
::
GetMethod
()
const
{
return
this
->
method
;
}
inline
const
uint8_t
*
StunPacket
::
GetData
()
const
{
return
this
->
data
;
}
inline
size_t
StunPacket
::
GetSize
()
const
{
return
this
->
size
;
}
inline
void
StunPacket
::
SetUsername
(
const
char
*
username
,
size_t
len
)
{
this
->
username
.
assign
(
username
,
len
);
}
inline
void
StunPacket
::
SetPriority
(
const
uint32_t
priority
)
{
this
->
priority
=
priority
;
}
inline
void
StunPacket
::
SetIceControlling
(
const
uint64_t
iceControlling
)
{
this
->
iceControlling
=
iceControlling
;
}
inline
void
StunPacket
::
SetIceControlled
(
const
uint64_t
iceControlled
)
{
this
->
iceControlled
=
iceControlled
;
}
inline
void
StunPacket
::
SetUseCandidate
()
{
this
->
hasUseCandidate
=
true
;
}
inline
void
StunPacket
::
SetXorMappedAddress
(
const
struct
sockaddr
*
xorMappedAddress
)
{
this
->
xorMappedAddress
=
xorMappedAddress
;
}
inline
void
StunPacket
::
SetErrorCode
(
uint16_t
errorCode
)
{
this
->
errorCode
=
errorCode
;
}
inline
void
StunPacket
::
SetMessageIntegrity
(
const
uint8_t
*
messageIntegrity
)
{
this
->
messageIntegrity
=
messageIntegrity
;
}
inline
void
StunPacket
::
SetFingerprint
()
{
this
->
hasFingerprint
=
true
;
}
inline
const
std
::
string
&
StunPacket
::
GetUsername
()
const
{
return
this
->
username
;
}
inline
uint32_t
StunPacket
::
GetPriority
()
const
{
return
this
->
priority
;
}
inline
uint64_t
StunPacket
::
GetIceControlling
()
const
{
return
this
->
iceControlling
;
}
inline
uint64_t
StunPacket
::
GetIceControlled
()
const
{
return
this
->
iceControlled
;
}
inline
bool
StunPacket
::
HasUseCandidate
()
const
{
return
this
->
hasUseCandidate
;
}
inline
uint16_t
StunPacket
::
GetErrorCode
()
const
{
return
this
->
errorCode
;
}
inline
bool
StunPacket
::
HasMessageIntegrity
()
const
{
return
(
this
->
messageIntegrity
?
true
:
false
);
}
inline
bool
StunPacket
::
HasFingerprint
()
const
{
return
this
->
hasFingerprint
;
}
}
// namespace RTC
#endif
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论