新增webrtc datachannel功能: #1216

This commit is contained in:
xiongziliang 2022-05-04 22:15:21 +08:00
parent 200a193c04
commit fb003714e9
6 changed files with 1251 additions and 8 deletions

View File

@ -176,13 +176,13 @@ endif ()
set(LINK_LIB_LIST zlmediakit zltoolkit) set(LINK_LIB_LIST zlmediakit zltoolkit)
#jemalloc ##jemalloc
find_package(JEMALLOC QUIET) #find_package(JEMALLOC QUIET)
if (JEMALLOC_FOUND) #if (JEMALLOC_FOUND)
message(STATUS "found library:\"${JEMALLOC_LIBRARIES}\"") # message(STATUS "found library:\"${JEMALLOC_LIBRARIES}\"")
include_directories(${JEMALLOC_INCLUDE_DIR}) # include_directories(${JEMALLOC_INCLUDE_DIR})
list(APPEND LINK_LIB_LIST ${JEMALLOC_LIBRARIES}) # list(APPEND LINK_LIB_LIST ${JEMALLOC_LIBRARIES})
endif () #endif ()
#openssl #openssl
find_package(OpenSSL QUIET) find_package(OpenSSL QUIET)
@ -351,6 +351,15 @@ if (ENABLE_WEBRTC)
add_library(webrtc ${SRC_WEBRTC_LIST}) add_library(webrtc ${SRC_WEBRTC_LIST})
list(APPEND LINK_LIB_LIST webrtc) list(APPEND LINK_LIB_LIST webrtc)
message(STATUS "webrtc功能已开启") message(STATUS "webrtc功能已开启")
find_package(SCTP QUIET)
if (SCTP_FOUND)
message(STATUS "found library:${SCTP_INCLUDE_DIRS} ${SCTP_LIBRARIES}")
include_directories(${SCTP_INCLUDE_DIRS})
list(APPEND LINK_LIB_LIST ${SCTP_LIBRARIES})
add_definitions(-DENABLE_SCTP)
message(STATUS "webrtc datachannel功能已打开")
endif ()
else () else ()
set(ENABLE_WEBRTC off) set(ENABLE_WEBRTC off)
message(WARNING "srtp未找到, webrtc相关功能打开失败") message(WARNING "srtp未找到, webrtc相关功能打开失败")

24
cmake/FindSCTP.cmake Normal file
View File

@ -0,0 +1,24 @@
# - Try to find sctp
#
# Once done this will define
# SCTP_FOUND - System has mbedtls
# SCTP_INCLUDE_DIRS - The mbedtls include directories
# SCTP_LIBRARIES - The mbedtls library
#find Mbedtls
FIND_PATH(
SCTP_INCLUDE_DIRS
NAMES usrsctp.h
)
FIND_LIBRARY(
SCTP_LIBRARIES
NAMES usrsctp
)
message(STATUS "SCTP LIBRARIES: " ${SCTP_LIBRARIES})
message(STATUS "SCTP INCLUDE DIRS: " ${SCTP_INCLUDE_DIRS})
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SCTP DEFAULT_MSG SCTP_LIBRARIES SCTP_INCLUDE_DIRS)

1006
webrtc/SctpAssociation.cpp Normal file

File diff suppressed because it is too large Load Diff

142
webrtc/SctpAssociation.hpp Normal file
View File

@ -0,0 +1,142 @@
#ifndef MS_RTC_SCTP_ASSOCIATION_HPP
#define MS_RTC_SCTP_ASSOCIATION_HPP
#ifdef ENABLE_SCTP
#include <usrsctp.h>
#include "Utils.hpp"
#include "Poller/EventPoller.h"
namespace RTC
{
class SctpEnv;
class SctpStreamParameters
{
public:
uint16_t streamId{ 0u };
bool ordered{ true };
uint16_t maxPacketLifeTime{ 0u };
uint16_t maxRetransmits{ 0u };
};
class SctpAssociation
{
public:
enum class SctpState
{
NEW = 1,
CONNECTING,
CONNECTED,
FAILED,
CLOSED
};
private:
enum class StreamDirection
{
INCOMING = 1,
OUTGOING
};
public:
class Listener
{
public:
virtual void OnSctpAssociationConnecting(RTC::SctpAssociation* sctpAssociation) = 0;
virtual void OnSctpAssociationConnected(RTC::SctpAssociation* sctpAssociation) = 0;
virtual void OnSctpAssociationFailed(RTC::SctpAssociation* sctpAssociation) = 0;
virtual void OnSctpAssociationClosed(RTC::SctpAssociation* sctpAssociation) = 0;
virtual void OnSctpAssociationSendData(
RTC::SctpAssociation* sctpAssociation, const uint8_t* data, size_t len) = 0;
virtual void OnSctpAssociationMessageReceived(
RTC::SctpAssociation* sctpAssociation,
uint16_t streamId,
uint32_t ppid,
const uint8_t* msg,
size_t len) = 0;
};
public:
static bool IsSctp(const uint8_t* data, size_t len)
{
// clang-format off
return (
(len >= 12) &&
// Must have Source Port Number and Destination Port Number set to 5000 (hack).
(Utils::Byte::Get2Bytes(data, 0) == 5000) &&
(Utils::Byte::Get2Bytes(data, 2) == 5000)
);
// clang-format on
}
public:
SctpAssociation(
Listener* listener, uint16_t os, uint16_t mis, size_t maxSctpMessageSize, bool isDataChannel);
virtual ~SctpAssociation();
public:
void TransportConnected();
size_t GetMaxSctpMessageSize() const
{
return this->maxSctpMessageSize;
}
SctpState GetState() const
{
return this->state;
}
void ProcessSctpData(const uint8_t* data, size_t len);
void SendSctpMessage(const RTC::SctpStreamParameters &params, uint32_t ppid, const uint8_t* msg, size_t len);
void HandleDataConsumer(const RTC::SctpStreamParameters &params);
void DataProducerClosed(const RTC::SctpStreamParameters &params);
void DataConsumerClosed(const RTC::SctpStreamParameters &params);
private:
void ResetSctpStream(uint16_t streamId, StreamDirection);
void AddOutgoingStreams(bool force = false);
public:
/* Callbacks fired by usrsctp events. */
virtual void OnUsrSctpSendSctpData(void* buffer, size_t len);
virtual void OnUsrSctpReceiveSctpData(uint16_t streamId, uint16_t ssn, uint32_t ppid, int flags, const uint8_t* data, size_t len);
virtual void OnUsrSctpReceiveSctpNotification(union sctp_notification* notification, size_t len);
private:
// Passed by argument.
Listener* listener{ nullptr };
uint16_t os{ 1024u };
uint16_t mis{ 1024u };
size_t maxSctpMessageSize{ 262144u };
bool isDataChannel{ false };
// Allocated by this.
uint8_t* messageBuffer{ nullptr };
// Others.
SctpState state{ SctpState::NEW };
struct socket* socket{ nullptr };
uint16_t desiredOs{ 0u };
size_t messageBufferLen{ 0u };
uint16_t lastSsnReceived{ 0u }; // Valid for us since no SCTP I-DATA support.
std::shared_ptr<SctpEnv> _env;
};
//保证线程安全
class SctpAssociationImp : public SctpAssociation, public std::enable_shared_from_this<SctpAssociationImp>{
public:
using Ptr = std::shared_ptr<SctpAssociationImp>;
template<typename ... ARGS>
SctpAssociationImp(toolkit::EventPoller::Ptr poller, ARGS &&...args) : SctpAssociation(std::forward<ARGS>(args)...) {
_poller = std::move(poller);
}
~SctpAssociationImp() override = default;
protected:
void OnUsrSctpSendSctpData(void* buffer, size_t len) override;
void OnUsrSctpReceiveSctpData(uint16_t streamId, uint16_t ssn, uint32_t ppid, int flags, const uint8_t* data, size_t len) override;
void OnUsrSctpReceiveSctpNotification(union sctp_notification* notification, size_t len) override;
private:
toolkit::EventPoller::Ptr _poller;
};
} // namespace RTC
#endif //ENABLE_SCTP
#endif //MS_RTC_SCTP_ASSOCIATION_HPP

View File

@ -60,6 +60,9 @@ void WebRtcTransport::onCreate(){
} }
void WebRtcTransport::onDestory(){ void WebRtcTransport::onDestory(){
#ifdef ENABLE_SCTP
_sctp = nullptr;
#endif
_dtls_transport = nullptr; _dtls_transport = nullptr;
_ice_server = nullptr; _ice_server = nullptr;
} }
@ -112,6 +115,10 @@ void WebRtcTransport::OnDtlsTransportConnected(
InfoL; InfoL;
_srtp_session_send = std::make_shared<RTC::SrtpSession>(RTC::SrtpSession::Type::OUTBOUND, srtpCryptoSuite, srtpLocalKey, srtpLocalKeyLen); _srtp_session_send = std::make_shared<RTC::SrtpSession>(RTC::SrtpSession::Type::OUTBOUND, srtpCryptoSuite, srtpLocalKey, srtpLocalKeyLen);
_srtp_session_recv = std::make_shared<RTC::SrtpSession>(RTC::SrtpSession::Type::INBOUND, srtpCryptoSuite, srtpRemoteKey, srtpRemoteKeyLen); _srtp_session_recv = std::make_shared<RTC::SrtpSession>(RTC::SrtpSession::Type::INBOUND, srtpCryptoSuite, srtpRemoteKey, srtpRemoteKeyLen);
#ifdef ENABLE_SCTP
_sctp = std::make_shared<RTC::SctpAssociationImp>(getPoller(), this, 128, 128, 262144, true);
_sctp->TransportConnected();
#endif
onStartWebRTC(); onStartWebRTC();
} }
@ -134,8 +141,44 @@ void WebRtcTransport::OnDtlsTransportClosed(const RTC::DtlsTransport *dtlsTransp
} }
void WebRtcTransport::OnDtlsTransportApplicationDataReceived(const RTC::DtlsTransport *dtlsTransport, const uint8_t *data, size_t len) { void WebRtcTransport::OnDtlsTransportApplicationDataReceived(const RTC::DtlsTransport *dtlsTransport, const uint8_t *data, size_t len) {
#ifdef ENABLE_SCTP
_sctp->ProcessSctpData(data, len);
#else
InfoL << hexdump(data, len); InfoL << hexdump(data, len);
#endif
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef ENABLE_SCTP
void WebRtcTransport::OnSctpAssociationConnecting(RTC::SctpAssociation* sctpAssociation) {
TraceL;
}
void WebRtcTransport::OnSctpAssociationConnected(RTC::SctpAssociation* sctpAssociation) {
InfoL << getIdentifier();
}
void WebRtcTransport::OnSctpAssociationFailed(RTC::SctpAssociation* sctpAssociation) {
WarnL << getIdentifier();
}
void WebRtcTransport::OnSctpAssociationClosed(RTC::SctpAssociation* sctpAssociation) {
InfoL << getIdentifier();
}
void WebRtcTransport::OnSctpAssociationSendData(RTC::SctpAssociation* sctpAssociation, const uint8_t* data, size_t len) {
_dtls_transport->SendApplicationData(data, len);
}
void WebRtcTransport::OnSctpAssociationMessageReceived(RTC::SctpAssociation *sctpAssociation, uint16_t streamId,
uint32_t ppid, const uint8_t *msg, size_t len) {
InfoL << getIdentifier() << " " << streamId << " " << ppid << " " << len << " " << string((char *)msg, len);
RTC::SctpStreamParameters params;
params.streamId = streamId;
//回显数据
_sctp->SendSctpMessage(params, ppid, msg, len);
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void WebRtcTransport::sendSockData(const char *buf, size_t len, RTC::TransportTuple *tuple){ void WebRtcTransport::sendSockData(const char *buf, size_t len, RTC::TransportTuple *tuple){

View File

@ -25,6 +25,7 @@
#include "Nack.h" #include "Nack.h"
#include "Network/Session.h" #include "Network/Session.h"
#include "TwccContext.h" #include "TwccContext.h"
#include "SctpAssociation.hpp"
//RTC配置项目 //RTC配置项目
namespace RTC { namespace RTC {
@ -56,7 +57,11 @@ private:
SockException _ex; SockException _ex;
}; };
class WebRtcTransport : public WebRtcInterface, public RTC::DtlsTransport::Listener, public RTC::IceServer::Listener, public std::enable_shared_from_this<WebRtcTransport> { class WebRtcTransport : public WebRtcInterface, public RTC::DtlsTransport::Listener, public RTC::IceServer::Listener, public std::enable_shared_from_this<WebRtcTransport>
#ifdef ENABLE_SCTP
, public RTC::SctpAssociation::Listener
#endif
{
public: public:
using Ptr = std::shared_ptr<WebRtcTransport>; using Ptr = std::shared_ptr<WebRtcTransport>;
WebRtcTransport(const EventPoller::Ptr &poller); WebRtcTransport(const EventPoller::Ptr &poller);
@ -128,6 +133,16 @@ protected:
void OnIceServerCompleted(const RTC::IceServer *iceServer) override; void OnIceServerCompleted(const RTC::IceServer *iceServer) override;
void OnIceServerDisconnected(const RTC::IceServer *iceServer) override; void OnIceServerDisconnected(const RTC::IceServer *iceServer) override;
#ifdef ENABLE_SCTP
void OnSctpAssociationConnecting(RTC::SctpAssociation* sctpAssociation) override;
void OnSctpAssociationConnected(RTC::SctpAssociation* sctpAssociation) override;
void OnSctpAssociationFailed(RTC::SctpAssociation* sctpAssociation) override;
void OnSctpAssociationClosed(RTC::SctpAssociation* sctpAssociation) override;
void OnSctpAssociationSendData(RTC::SctpAssociation* sctpAssociation, const uint8_t* data, size_t len) override;
void OnSctpAssociationMessageReceived(RTC::SctpAssociation *sctpAssociation, uint16_t streamId, uint32_t ppid,
const uint8_t *msg, size_t len) override;
#endif
protected: protected:
virtual void onStartWebRTC() = 0; virtual void onStartWebRTC() = 0;
virtual void onRtcConfigure(RtcConfigure &configure) const; virtual void onRtcConfigure(RtcConfigure &configure) const;
@ -163,6 +178,10 @@ private:
Ticker _ticker; Ticker _ticker;
//循环池 //循环池
ResourcePool<BufferRaw> _packet_pool; ResourcePool<BufferRaw> _packet_pool;
#ifdef ENABLE_SCTP
RTC::SctpAssociationImp::Ptr _sctp;
#endif
}; };
class RtpChannel; class RtpChannel;