feat: 增加webrtc代理拉流 (#4389)

- 增加客户端模式,支持主动拉流、推流:
   - addStreamProxy接口新增支持whep主动拉流,拉流地址目前只兼容zlm的whep url。
   - addStreamPusherProxy接口新增支持whip主动推流,推流地址目前只兼容zlm的whip url。
   - 以上推流url格式为webrtc[s]://server_host:server_port/app/stream_id?key=value, 内部会自动转换为http[s]://server_host:server_port/index/api/[whip/whep]?app=app&stream=stream_id&key=value。

- 增加WebRtc p2p 模式:
  - 增加 ICE FULL模式。
  - 增加STUN/TURN 服务器。
  - 增加websocket 信令。
  - 增加P2P代理拉流。

---------

Co-authored-by: xia-chu <771730766@qq.com>
Co-authored-by: mtdxc <mtdxc@126.com>
Co-authored-by: cqm <cqm@97kid.com>
This commit is contained in:
baigao-X
2025-09-20 16:23:30 +08:00
committed by GitHub
parent 97d2a1fb08
commit 3fb43c5fef
72 changed files with 16912 additions and 10319 deletions

View File

@@ -49,11 +49,11 @@ inline const EVP_CIPHER* aes_key_len_mapping_ctr_cipher(int key_len) {
static bool aes_wrap(const uint8_t* in, int in_len, uint8_t* out, int* outLen, uint8_t* key, int key_len) {
#if defined(ENABLE_OPENSSL)
EVP_CIPHER_CTX* ctx = NULL;
EVP_CIPHER_CTX* ctx = NULL;
*outLen = 0;
do {
do {
if (!(ctx = EVP_CIPHER_CTX_new())) {
WarnL << "EVP_CIPHER_CTX_new fail";
break;
@@ -62,29 +62,29 @@ static bool aes_wrap(const uint8_t* in, int in_len, uint8_t* out, int* outLen, u
if (1 != EVP_EncryptInit_ex(ctx, aes_key_len_mapping_wrap_cipher(key_len), NULL, key, NULL)) {
WarnL << "EVP_EncryptInit_ex fail";
break;
}
break;
}
int len1 = 0;
if (1 != EVP_EncryptUpdate(ctx, (uint8_t*)out, &len1, (uint8_t*)in, in_len)) {
int len1 = 0;
if (1 != EVP_EncryptUpdate(ctx, (uint8_t*)out, &len1, (uint8_t*)in, in_len)) {
WarnL << "EVP_EncryptUpdate fail";
break;
}
break;
}
int len2 = 0;
if (1 != EVP_EncryptFinal_ex(ctx, (uint8_t*)out + len1, &len2)) {
int len2 = 0;
if (1 != EVP_EncryptFinal_ex(ctx, (uint8_t*)out + len1, &len2)) {
WarnL << "EVP_EncryptFinal_ex fail";
break;
}
break;
}
*outLen = len1 + len2;
} while (0);
*outLen = len1 + len2;
} while (0);
if (ctx != NULL) {
EVP_CIPHER_CTX_free(ctx);
}
if (ctx != NULL) {
EVP_CIPHER_CTX_free(ctx);
}
return *outLen != 0;
return *outLen != 0;
#else
return false;
#endif
@@ -103,11 +103,11 @@ static bool aes_wrap(const uint8_t* in, int in_len, uint8_t* out, int* outLen, u
static bool aes_unwrap(const uint8_t* in, int in_len, uint8_t* out, int* outLen, uint8_t* key, int key_len) {
#if defined(ENABLE_OPENSSL)
EVP_CIPHER_CTX* ctx = NULL;
EVP_CIPHER_CTX* ctx = NULL;
*outLen = 0;
do {
do {
if (!(ctx = EVP_CIPHER_CTX_new())) {
WarnL << "EVP_CIPHER_CTX_new fail";
@@ -117,8 +117,8 @@ static bool aes_unwrap(const uint8_t* in, int in_len, uint8_t* out, int* outLen,
if (1 != EVP_DecryptInit_ex(ctx, aes_key_len_mapping_wrap_cipher(key_len), NULL, key, NULL)) {
WarnL << "EVP_DecryptInit_ex fail";
break;
}
break;
}
//设置pkcs7padding
if (1 != EVP_CIPHER_CTX_set_padding(ctx, 1)) {
@@ -126,26 +126,26 @@ static bool aes_unwrap(const uint8_t* in, int in_len, uint8_t* out, int* outLen,
break;
}
int len1 = 0;
if (1 != EVP_DecryptUpdate(ctx, (uint8_t*)out, &len1, (uint8_t*)in, in_len)) {
int len1 = 0;
if (1 != EVP_DecryptUpdate(ctx, (uint8_t*)out, &len1, (uint8_t*)in, in_len)) {
WarnL << "EVP_DecryptUpdate fail";
break;
}
break;
}
int len2 = 0;
if (1 != EVP_DecryptFinal_ex(ctx, (uint8_t*)out + len1, &len2)) {
int len2 = 0;
if (1 != EVP_DecryptFinal_ex(ctx, (uint8_t*)out + len1, &len2)) {
WarnL << "EVP_DecryptFinal_ex fail";
break;
}
break;
}
*outLen = len1 + len2;
} while (0);
*outLen = len1 + len2;
} while (0);
if (ctx != NULL) {
EVP_CIPHER_CTX_free(ctx);
}
if (ctx != NULL) {
EVP_CIPHER_CTX_free(ctx);
}
return *outLen != 0;
return *outLen != 0;
#else
return false;
@@ -166,11 +166,11 @@ static bool aes_unwrap(const uint8_t* in, int in_len, uint8_t* out, int* outLen,
static bool aes_ctr_encrypt(const uint8_t* in, int in_len, uint8_t* out, int* outLen, uint8_t* key, int key_len, uint8_t* iv) {
#if defined(ENABLE_OPENSSL)
EVP_CIPHER_CTX* ctx = NULL;
EVP_CIPHER_CTX* ctx = NULL;
*outLen = 0;
do {
do {
if (!(ctx = EVP_CIPHER_CTX_new())) {
WarnL << "EVP_CIPHER_CTX_new fail";
break;
@@ -178,29 +178,29 @@ static bool aes_ctr_encrypt(const uint8_t* in, int in_len, uint8_t* out, int* ou
if (1 != EVP_EncryptInit_ex(ctx, aes_key_len_mapping_ctr_cipher(key_len), NULL, key, iv)) {
WarnL << "EVP_EncryptInit_ex fail";
break;
}
break;
}
int len1 = 0;
if (1 != EVP_EncryptUpdate(ctx, (uint8_t*)out, &len1, (uint8_t*)in, in_len)) {
int len1 = 0;
if (1 != EVP_EncryptUpdate(ctx, (uint8_t*)out, &len1, (uint8_t*)in, in_len)) {
WarnL << "EVP_EncryptUpdate fail";
break;
}
break;
}
int len2 = 0;
if (1 != EVP_EncryptFinal_ex(ctx, (uint8_t*)out + len1, &len2)) {
int len2 = 0;
if (1 != EVP_EncryptFinal_ex(ctx, (uint8_t*)out + len1, &len2)) {
WarnL << "EVP_EncryptFinal_ex fail";
break;
}
break;
}
*outLen = len1 + len2;
} while (0);
*outLen = len1 + len2;
} while (0);
if (ctx != NULL) {
EVP_CIPHER_CTX_free(ctx);
}
if (ctx != NULL) {
EVP_CIPHER_CTX_free(ctx);
}
return *outLen != 0;
return *outLen != 0;
#else
return false;
#endif
@@ -221,42 +221,42 @@ static bool aes_ctr_encrypt(const uint8_t* in, int in_len, uint8_t* out, int* ou
static bool aes_ctr_decrypt(const uint8_t* in, int in_len, uint8_t* out, int* outLen, uint8_t* key, int key_len, uint8_t* iv) {
#if defined(ENABLE_OPENSSL)
EVP_CIPHER_CTX* ctx = NULL;
EVP_CIPHER_CTX* ctx = NULL;
*outLen = 0;
do {
do {
if (!(ctx = EVP_CIPHER_CTX_new())) {
WarnL << "EVP_CIPHER_CTX_new fail";
break;
}
if (1 != EVP_DecryptInit_ex(ctx, aes_key_len_mapping_ctr_cipher(key_len), NULL, key, iv)) {
if (1 != EVP_DecryptInit_ex(ctx, aes_key_len_mapping_ctr_cipher(key_len), NULL, key, iv)) {
WarnL << "EVP_DecryptInit_ex fail";
break;
}
break;
}
int len1 = 0;
if (1 != EVP_DecryptUpdate(ctx, (uint8_t*)out, &len1, (uint8_t*)in, in_len)) {
int len1 = 0;
if (1 != EVP_DecryptUpdate(ctx, (uint8_t*)out, &len1, (uint8_t*)in, in_len)) {
WarnL << "EVP_DecryptUpdate fail";
break;
}
break;
}
int len2 = 0;
if (1 != EVP_DecryptFinal_ex(ctx, (uint8_t*)out + len1, &len2)) {
int len2 = 0;
if (1 != EVP_DecryptFinal_ex(ctx, (uint8_t*)out + len1, &len2)) {
WarnL << "EVP_DecryptFinal_ex fail";
break;
}
break;
}
*outLen = len1 + len2;
} while (0);
*outLen = len1 + len2;
} while (0);
if (ctx != NULL) {
EVP_CIPHER_CTX_free(ctx);
}
if (ctx != NULL) {
EVP_CIPHER_CTX_free(ctx);
}
return *outLen != 0;
return *outLen != 0;
#else
return false;

View File

@@ -353,7 +353,7 @@ bool HandshakePacket::loadExtMessage(uint8_t *buf, size_t len) {
case HSExt::SRT_CMD_SID: ext = std::make_shared<HSExtStreamID>(); break;
case HSExt::SRT_CMD_KMREQ:
case HSExt::SRT_CMD_KMRSP:
ext = std::make_shared<HSExtKeyMaterial>(); break;
ext = std::make_shared<HSExtKeyMaterial>(); break;
default: WarnL << "not support ext " << type; break;
}
if (ext) {

View File

@@ -1,29 +1,29 @@
#ifndef ZLMEDIAKIT_SRT_SESSION_H
#define ZLMEDIAKIT_SRT_SESSION_H
#include "Network/Session.h"
#include "SrtTransport.hpp"
namespace SRT {
using namespace toolkit;
class SrtSession : public Session {
public:
SrtSession(const Socket::Ptr &sock);
void onRecv(const Buffer::Ptr &) override;
void onError(const SockException &err) override;
void onManager() override;
void attachServer(const toolkit::Server &server) override;
static EventPoller::Ptr queryPoller(const Buffer::Ptr &buffer);
private:
bool _find_transport = true;
Ticker _ticker;
struct sockaddr_storage _peer_addr;
SrtTransport::Ptr _transport;
};
} // namespace SRT
#endif // ZLMEDIAKIT_SRT_SESSION_H
#ifndef ZLMEDIAKIT_SRT_SESSION_H
#define ZLMEDIAKIT_SRT_SESSION_H
#include "Network/Session.h"
#include "SrtTransport.hpp"
namespace SRT {
using namespace toolkit;
class SrtSession : public Session {
public:
SrtSession(const Socket::Ptr &sock);
void onRecv(const Buffer::Ptr &) override;
void onError(const SockException &err) override;
void onManager() override;
void attachServer(const toolkit::Server &server) override;
static EventPoller::Ptr queryPoller(const Buffer::Ptr &buffer);
private:
bool _find_transport = true;
Ticker _ticker;
struct sockaddr_storage _peer_addr;
SrtTransport::Ptr _transport;
};
} // namespace SRT
#endif // ZLMEDIAKIT_SRT_SESSION_H

View File

@@ -400,7 +400,7 @@ void SrtTransport::sendMsgDropReq(uint32_t first, uint32_t last) {
}
void SrtTransport::tryAnnounceKeyMaterial() {
//TraceL;
//TraceL;
if (!_crypto) {
return;

View File

@@ -169,8 +169,8 @@ private:
// for encryption
Crypto::Ptr _crypto;
Timer::Ptr _announce_timer;
KeyMaterialPacket::Ptr _announce_req;
Timer::Ptr _announce_timer;
KeyMaterialPacket::Ptr _announce_req;
};
class SrtTransportManager {