2021-09-08 18:00:55 +08:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by MIT license that can be found in the
|
|
|
|
|
* LICENSE file in the root of the source tree. All contributing project authors
|
|
|
|
|
* may be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "WebRtcSession.h"
|
|
|
|
|
#include "Util/util.h"
|
2022-11-18 22:52:57 +08:00
|
|
|
|
#include "Network/TcpServer.h"
|
2022-11-29 11:07:13 +08:00
|
|
|
|
#include "Common/config.h"
|
|
|
|
|
#include "IceServer.hpp"
|
|
|
|
|
#include "WebRtcTransport.h"
|
2021-09-08 18:00:55 +08:00
|
|
|
|
|
2022-02-02 20:34:50 +08:00
|
|
|
|
using namespace std;
|
2022-09-18 21:03:05 +08:00
|
|
|
|
|
|
|
|
|
namespace mediakit {
|
2022-02-02 20:34:50 +08:00
|
|
|
|
|
2022-11-18 22:52:57 +08:00
|
|
|
|
static string getUserName(const char *buf, size_t len) {
|
2021-09-10 18:37:32 +08:00
|
|
|
|
if (!RTC::StunPacket::IsStun((const uint8_t *) buf, len)) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
std::unique_ptr<RTC::StunPacket> packet(RTC::StunPacket::Parse((const uint8_t *) buf, len));
|
|
|
|
|
if (!packet) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
if (packet->GetClass() != RTC::StunPacket::Class::REQUEST ||
|
|
|
|
|
packet->GetMethod() != RTC::StunPacket::Method::BINDING) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
//收到binding request请求
|
|
|
|
|
auto vec = split(packet->GetUsername(), ":");
|
|
|
|
|
return vec[0];
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-16 10:29:00 +08:00
|
|
|
|
EventPoller::Ptr WebRtcSession::queryPoller(const Buffer::Ptr &buffer) {
|
2022-11-18 22:52:57 +08:00
|
|
|
|
auto user_name = getUserName(buffer->data(), buffer->size());
|
2021-09-10 18:37:32 +08:00
|
|
|
|
if (user_name.empty()) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2021-10-16 10:25:23 +08:00
|
|
|
|
auto ret = WebRtcTransportManager::Instance().getItem(user_name);
|
2021-09-10 18:37:32 +08:00
|
|
|
|
return ret ? ret->getPoller() : nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-16 10:29:00 +08:00
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2022-11-18 22:52:57 +08:00
|
|
|
|
WebRtcSession::WebRtcSession(const Socket::Ptr &sock) : Session(sock) {
|
|
|
|
|
_over_tcp = sock->sockType() == SockNum::Sock_TCP;
|
2021-10-16 10:29:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-04-22 23:30:22 +08:00
|
|
|
|
WebRtcSession::~WebRtcSession() = default;
|
2021-10-16 10:29:00 +08:00
|
|
|
|
|
2022-11-18 22:52:57 +08:00
|
|
|
|
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) {
|
2021-09-15 11:50:15 +08:00
|
|
|
|
if (_find_transport) {
|
2022-11-18 22:52:57 +08:00
|
|
|
|
// 只允许寻找一次transport
|
2021-09-15 11:50:15 +08:00
|
|
|
|
_find_transport = false;
|
2022-11-18 22:52:57 +08:00
|
|
|
|
auto user_name = getUserName(data, len);
|
2021-10-16 10:25:23 +08:00
|
|
|
|
auto transport = WebRtcTransportManager::Instance().getItem(user_name);
|
2022-11-18 22:52:57 +08:00
|
|
|
|
CHECK(transport);
|
|
|
|
|
|
|
|
|
|
//WebRtcTransport在其他poller线程上,需要切换poller线程并重新创建WebRtcSession对象
|
|
|
|
|
if (!transport->getPoller()->isCurrentThread()) {
|
2022-11-28 17:52:28 +08:00
|
|
|
|
auto sock = Socket::createSocket(transport->getPoller(), false);
|
2022-11-27 12:43:16 +08:00
|
|
|
|
//1、克隆socket(fd不变),切换poller线程到WebRtcTransport所在线程
|
2023-04-19 13:12:39 +08:00
|
|
|
|
sock->cloneSocket(*(getSock()));
|
2022-11-18 22:52:57 +08:00
|
|
|
|
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));
|
2022-11-27 12:43:16 +08:00
|
|
|
|
//2、创建新的WebRtcSession对象(绑定到WebRtcTransport所在线程),重新处理一遍ice binding request命令
|
2022-11-18 22:52:57 +08:00
|
|
|
|
session->onRecv_l(str.data(), str.size());
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-11-27 12:43:16 +08:00
|
|
|
|
//3、销毁原先的socket和WebRtcSession(原先的对象跟WebRtcTransport不在同一条线程)
|
2022-11-18 22:52:57 +08:00
|
|
|
|
throw std::runtime_error("webrtc over tcp change poller: " + getPoller()->getThreadName() + " -> " + sock->getPoller()->getThreadName());
|
|
|
|
|
}
|
2021-10-15 18:56:49 +08:00
|
|
|
|
_transport = std::move(transport);
|
2021-10-15 17:12:39 +08:00
|
|
|
|
InfoP(this);
|
2021-09-08 18:00:55 +08:00
|
|
|
|
}
|
2021-09-10 22:31:44 +08:00
|
|
|
|
_ticker.resetTime();
|
2021-09-15 11:50:15 +08:00
|
|
|
|
CHECK(_transport);
|
2023-03-03 11:18:21 +08:00
|
|
|
|
_transport->inputSockData((char *)data, len, this);
|
2022-11-18 22:52:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebRtcSession::onRecv(const Buffer::Ptr &buffer) {
|
|
|
|
|
if (_over_tcp) {
|
|
|
|
|
input(buffer->data(), buffer->size());
|
|
|
|
|
} else {
|
|
|
|
|
onRecv_l(buffer->data(), buffer->size());
|
|
|
|
|
}
|
2021-09-08 18:00:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebRtcSession::onError(const SockException &err) {
|
2022-11-18 22:52:57 +08:00
|
|
|
|
//udp链接超时,但是rtc链接不一定超时,因为可能存在链接迁移的情况
|
2021-09-10 22:31:44 +08:00
|
|
|
|
//在udp链接迁移时,新的WebRtcSession对象将接管WebRtcTransport对象的生命周期
|
|
|
|
|
//本WebRtcSession对象将在超时后自动销毁
|
2023-04-23 00:10:18 +08:00
|
|
|
|
WarnP(this) << err;
|
2021-09-16 10:03:28 +08:00
|
|
|
|
|
2021-09-16 10:05:04 +08:00
|
|
|
|
if (!_transport) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-03-03 11:18:21 +08:00
|
|
|
|
auto self = shared_from_this();
|
2021-09-16 10:03:28 +08:00
|
|
|
|
auto transport = std::move(_transport);
|
2023-03-03 11:18:21 +08:00
|
|
|
|
getPoller()->async([transport, self]() mutable {
|
2021-09-16 10:03:28 +08:00
|
|
|
|
//延时减引用,防止使用transport对象时,销毁对象
|
2023-03-03 11:18:21 +08:00
|
|
|
|
transport->removeTuple(self.get());
|
|
|
|
|
//确保transport在Session对象前销毁,防止WebRtcTransport::onDestory()时获取不到Session对象
|
|
|
|
|
transport = nullptr;
|
2021-09-16 10:03:28 +08:00
|
|
|
|
}, false);
|
2021-09-08 18:00:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebRtcSession::onManager() {
|
2022-09-18 21:03:05 +08:00
|
|
|
|
GET_CONFIG(float, timeoutSec, Rtc::kTimeOutSec);
|
2021-09-10 22:31:44 +08:00
|
|
|
|
if (!_transport && _ticker.createdTime() > timeoutSec * 1000) {
|
|
|
|
|
shutdown(SockException(Err_timeout, "illegal webrtc connection"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (_ticker.elapsedTime() > timeoutSec * 1000) {
|
|
|
|
|
shutdown(SockException(Err_timeout, "webrtc connection timeout"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-09-08 18:00:55 +08:00
|
|
|
|
}
|
2021-10-15 17:12:39 +08:00
|
|
|
|
|
2022-11-18 22:52:57 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 21:03:05 +08:00
|
|
|
|
}// namespace mediakit
|
2022-09-07 13:58:26 +08:00
|
|
|
|
|
2021-10-15 17:12:39 +08:00
|
|
|
|
|