传输媒体流的通道的建立在Media soup源码分析(三)中已经说明,实际上流的转发是依赖于Socket
文章目录
创建socket
WebRtcTransport
下述socket的创建函数在C++的WebRtcTransport类的构造函数中
auto* udpSocket = new RTC::UdpSocket(this, listenIp.ip);
这行代码创建了UdpSocket,且有多少个listenIp就创建多少个socket
UdpSocket
进入UdpSocket的构造函数,它调用了父类**::UdpSocket的构造函数,实际上在参数中,还调用了PortManager::BindUdp(ip)**,它通过udp获得了端口,并且生成了一个与libuv绑定的handle
UdpSocket::UdpSocket(Listener* listener, std::string& ip)
: // This may throw.
::UdpSocket::UdpSocket(PortManager::BindUdp(ip)), listener(listener)
{
MS_TRACE();
}
::UdpSocket
在父类的构造函数中,启动了一个uvHandle,并且申请了onRecv这个API
UdpSocket::UdpSocket(uv_udp_t* uvHandle) : uvHandle(uvHandle)
{
MS_TRACE();
int err;
this->uvHandle->data = static_cast<void*>(this);
err = uv_udp_recv_start(
this->uvHandle, static_cast<uv_alloc_cb>(onAlloc), static_cast<uv_udp_recv_cb>(onRecv));
if (err != 0)
{
uv_close(reinterpret_cast<uv_handle_t*>(this->uvHandle), static_cast<uv_close_cb>(onClose));
MS_THROW_ERROR("uv_udp_recv_start() failed: %s", uv_strerror(err));
}
// Set local address.
if (!SetLocalAddress())
{
uv_close(reinterpret_cast<uv_handle_t*>(this->uvHandle), static_cast<uv_close_cb>(onClose));
MS_THROW_ERROR("error setting local IP and port");
}
}
传递数据包
onRecv
onRecv是一个全局静态函数,为了贯彻面向对象的思想,这里继续把参数传给socket->OnUvRecv,
inline static void onRecv(
uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned int flags)
{
auto* socket = static_cast<UdpSocket*>(handle->data);
if (socket)
socket->OnUvRecv(nread, buf, addr, flags);
}
OnUvRecv
在这个函数体内,重要的是下面这行代码