mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-06-29 06:12:22 +08:00
新增支持webrtc over tcp模式 (#2092)
* webrtc server/session/cadidate 改为tcp * 先屏蔽检查isCurrentThread * 接受和发送的数据处理tcp 2字节头 * 处理rtc tcp 分片 * 完善webrtc over tcp * 精简rtp服务器相关代码 * 适配webrtc AV1编码: #2091 * webrtc tcp模式支持Firefox * webrtc tcp模式支持线程安全 * c sdk支持webrtc tcp Co-authored-by: ziyue <1213642868@qq.com>
This commit is contained in:
@@ -10,14 +10,13 @@
|
||||
|
||||
#include "WebRtcSession.h"
|
||||
#include "Util/util.h"
|
||||
#include "Network/TcpServer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
static string getUserName(const Buffer::Ptr &buffer) {
|
||||
auto buf = buffer->data();
|
||||
auto len = buffer->size();
|
||||
static string getUserName(const char *buf, size_t len) {
|
||||
if (!RTC::StunPacket::IsStun((const uint8_t *) buf, len)) {
|
||||
return "";
|
||||
}
|
||||
@@ -35,7 +34,7 @@ static string getUserName(const Buffer::Ptr &buffer) {
|
||||
}
|
||||
|
||||
EventPoller::Ptr WebRtcSession::queryPoller(const Buffer::Ptr &buffer) {
|
||||
auto user_name = getUserName(buffer);
|
||||
auto user_name = getUserName(buffer->data(), buffer->size());
|
||||
if (user_name.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -45,33 +44,63 @@ EventPoller::Ptr WebRtcSession::queryPoller(const Buffer::Ptr &buffer) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WebRtcSession::WebRtcSession(const Socket::Ptr &sock) : UdpSession(sock) {
|
||||
WebRtcSession::WebRtcSession(const Socket::Ptr &sock) : Session(sock) {
|
||||
socklen_t addr_len = sizeof(_peer_addr);
|
||||
getpeername(sock->rawFD(), (struct sockaddr *)&_peer_addr, &addr_len);
|
||||
_over_tcp = sock->sockType() == SockNum::Sock_TCP;
|
||||
}
|
||||
|
||||
WebRtcSession::~WebRtcSession() {
|
||||
InfoP(this);
|
||||
}
|
||||
|
||||
void WebRtcSession::onRecv(const Buffer::Ptr &buffer) {
|
||||
void WebRtcSession::attachServer(const Server &server) {
|
||||
_server = std::dynamic_pointer_cast<toolkit::TcpServer>(const_cast<Server &>(server).shared_from_this());
|
||||
}
|
||||
|
||||
void WebRtcSession::onRecv_l(const char *data, size_t len) {
|
||||
if (_find_transport) {
|
||||
//只允许寻找一次transport
|
||||
// 只允许寻找一次transport
|
||||
_find_transport = false;
|
||||
auto user_name = getUserName(buffer);
|
||||
auto user_name = getUserName(data, len);
|
||||
auto transport = WebRtcTransportManager::Instance().getItem(user_name);
|
||||
CHECK(transport && transport->getPoller()->isCurrentThread());
|
||||
CHECK(transport);
|
||||
|
||||
//WebRtcTransport在其他poller线程上,需要切换poller线程并重新创建WebRtcSession对象
|
||||
if (!transport->getPoller()->isCurrentThread()) {
|
||||
auto sock = Socket::createSocket(transport->getPoller());
|
||||
sock->cloneFromPeerSocket(*(getSock()));
|
||||
auto server = _server;
|
||||
std::string str(data, len);
|
||||
sock->getPoller()->async([sock, server, str](){
|
||||
auto strong_server = server.lock();
|
||||
if (strong_server) {
|
||||
auto session = static_pointer_cast<WebRtcSession>(strong_server->createSession(sock));
|
||||
session->onRecv_l(str.data(), str.size());
|
||||
}
|
||||
});
|
||||
throw std::runtime_error("webrtc over tcp change poller: " + getPoller()->getThreadName() + " -> " + sock->getPoller()->getThreadName());
|
||||
}
|
||||
|
||||
transport->setSession(shared_from_this());
|
||||
_transport = std::move(transport);
|
||||
InfoP(this);
|
||||
}
|
||||
_ticker.resetTime();
|
||||
CHECK(_transport);
|
||||
_transport->inputSockData(buffer->data(), buffer->size(), (struct sockaddr *)&_peer_addr);
|
||||
_transport->inputSockData((char *)data, len, (struct sockaddr *)&_peer_addr);
|
||||
}
|
||||
|
||||
void WebRtcSession::onRecv(const Buffer::Ptr &buffer) {
|
||||
if (_over_tcp) {
|
||||
input(buffer->data(), buffer->size());
|
||||
} else {
|
||||
onRecv_l(buffer->data(), buffer->size());
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSession::onError(const SockException &err) {
|
||||
//udp链接超时,但是rtc链接不一定超时,因为可能存在udp链接迁移的情况
|
||||
//udp链接超时,但是rtc链接不一定超时,因为可能存在链接迁移的情况
|
||||
//在udp链接迁移时,新的WebRtcSession对象将接管WebRtcTransport对象的生命周期
|
||||
//本WebRtcSession对象将在超时后自动销毁
|
||||
WarnP(this) << err.what();
|
||||
@@ -97,6 +126,25 @@ void WebRtcSession::onManager() {
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t WebRtcSession::onRecvHeader(const char *data, size_t len) {
|
||||
onRecv_l(data + 2, len - 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *WebRtcSession::onSearchPacketTail(const char *data, size_t len) {
|
||||
if (len < 2) {
|
||||
// 数据不够
|
||||
return nullptr;
|
||||
}
|
||||
uint16_t length = (((uint8_t *)data)[0] << 8) | ((uint8_t *)data)[1];
|
||||
if (len < (size_t)(length + 2)) {
|
||||
// 数据不够
|
||||
return nullptr;
|
||||
}
|
||||
// 返回rtp包末尾
|
||||
return data + 2 + length;
|
||||
}
|
||||
|
||||
}// namespace mediakit
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user