概述

RTC::Transport是mediasoup中的一个重要概念,它用于在mediasoup与客户端之间传输实时音视频数据。

Transport继承着众多的类,主要用于Transport的整体感知

	class Transport : public RTC::Producer::Listener,
	                  public RTC::Consumer::Listener,
	                  public RTC::DataProducer::Listener,
	                  public RTC::DataConsumer::Listener,
	                  public RTC::SctpAssociation::Listener,
	                  public RTC::TransportCongestionControlClient::Listener,
	                  public RTC::TransportCongestionControlServer::Listener,
	                  public Channel::ChannelSocket::RequestHandler,
	                  public PayloadChannel::PayloadChannelSocket::RequestHandler,
	                  public PayloadChannel::PayloadChannelSocket::NotificationHandler,
分析Transport的创建流程

在Router层会根据类型来进入分支创建transport,以PlainTransport为例

			case Channel::ChannelRequest::MethodId::ROUTER_CREATE_PLAIN_TRANSPORT:
			{
				std::string transportId;//从上层获取到transport的ID

				// This may throw
				SetNewTransportIdFromData(request->data, transportId);

				auto* plainTransport =
				  new RTC::PlainTransport(this->shared, transportId, this, request->data);

				// Insert into the map.绑定ID与transport的映射
				this->mapTransports[transportId] = plainTransport;

				MS_DEBUG_DEV("PlainTransport created [transportId:%s]", transportId.c_str());

				json data = json::object();

				plainTransport->FillJson(data);

				request->Accept(data);

				break;
			}

在构造函数中,创建了socket,并且绑定了通道消息回调

	PlainTransport::PlainTransport(RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data)
	  : RTC::Transport::Transport(shared, id, listener, data)
	{
		MS_TRACE();

		auto jsonListenIpIt = data.find("listenIp");

		if (jsonListenIpIt == data.end())
			MS_THROW_TYPE_ERROR("missing listenIp");
		else if (!jsonListenIpIt->is_object())
			MS_THROW_TYPE_ERROR("wrong listenIp (not an object)");

		auto jsonIpIt = jsonListenIpIt->find("ip");

		if (jsonIpIt == jsonListenIpIt->end())
			MS_THROW_TYPE_ERROR("missing listenIp.ip");
		else if (!jsonIpIt->is_string())
			MS_THROW_TYPE_ERROR("wrong listenIp.ip (not an string)");
        //获得内网IP
		this->listenIp.ip.assign(jsonIpIt->get<std::string>());

		// This may throw.
		Utils::IP::NormalizeIp(this->listenIp.ip);

		auto jsonAnnouncedIpIt = jsonListenIpIt->find("announcedIp");

		if (jsonAnnouncedIpIt != jsonListenIpIt->end())
		{
			if (!jsonAnnouncedIpIt->is_string())
				MS_THROW_TYPE_ERROR("wrong listenIp.announcedIp (not an string");
            //获得外网IP
			this->listenIp.announcedIp.assign(jsonAnnouncedIpIt->get<std::string>());
		}
        //获取端口
		uint16_t port{ 0 };
		auto jsonPortIt = data.find("port");
        //判断端口是否合法
		if (jsonPortIt != data.end())
		{
			if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt)))
				MS_THROW_TYPE_ERROR("wrong port (not a positive number)");

			port = jsonPortIt->get<uint16_t>();
		}

		auto jsonRtcpMuxIt = data.find("rtcpMux");

		if (jsonRtcpMuxIt != data.end())
		{
			if (!jsonRtcpMuxIt->is_boolean())
				MS_THROW_TYPE_ERROR("wrong rtcpMux (not a boolean)");

			this->rtcpMux = jsonRtcpMuxIt->get<bool>();
		}

		auto jsonComediaIt = data.find("comedia");

		if (jsonComediaIt != data.end())
		{
			if (!jsonComediaIt->is_boolean())
				MS_THROW_TYPE_ERROR("wrong comedia (not a boolean)");

			this->comedia = jsonComediaIt->get<bool>();
		}

		auto jsonEnableSrtpIt = data.find("enableSrtp");

		// clang-format off
		if (
			jsonEnableSrtpIt != data.end() &&
			jsonEnableSrtpIt->is_boolean() &&
			jsonEnableSrtpIt->get<bool>()
		)
		// clang-format on
		{
			auto jsonSrtpCryptoSuiteIt = data.find("srtpCryptoSuite");

			if (jsonSrtpCryptoSuiteIt == data.end() || !jsonSrtpCryptoSuiteIt->is_string())
				MS_THROW_TYPE_ERROR("missing srtpCryptoSuite)");

			// Ensure it's a crypto suite supported by us.
			auto it =
			  PlainTransport::string2SrtpCryptoSuite.find(jsonSrtpCryptoSuiteIt->get<std::string>());

			if (it == PlainTransport::string2SrtpCryptoSuite.end())
				MS_THROW_TYPE_ERROR("invalid/unsupported srtpCryptoSuite");

			// NOTE: The SRTP crypto suite may change later on connect().
			this->srtpCryptoSuite = it->second;

			switch (this->srtpCryptoSuite)
			{
				case RTC::SrtpSession::CryptoSuite::AEAD_AES_256_GCM:
				{
					this->srtpMasterLength = SrtpAesGcm256MasterLength;

					break;
				}

				case RTC::SrtpSession::CryptoSuite::AEAD_AES_128_GCM:
				{
					this->srtpMasterLength = SrtpAesGcm128MasterLength;

					break;
				}

				case RTC::SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_80:
				case RTC::SrtpSession::CryptoSuite::AES_CM_128_HMAC_SHA1_32:
				{
					this->srtpMasterLength = SrtpMasterLength;

					break;
				}

				default:
				{
					MS_ABORT("unknown SRTP crypto suite");
				}
			}

			this->srtpKey       = Utils::Crypto::GetRandomString(this->srtpMasterLength);
			this->srtpKeyBase64 = Utils::String::Base64Encode(this->srtpKey);//进行base64编码
		}

		try
		{
			// This may throw. 通过 listenIp, port 创建 UdpSocket
			if (port != 0)
				this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip, port);
			else
				this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip);

			if (!this->rtcpMux)
			{
				// This may throw.
				this->rtcpUdpSocket = new RTC::UdpSocket(this, this->listenIp.ip);
			}

			// NOTE: This may throw.
			this->shared->channelMessageRegistrator->RegisterHandler(
			  this->id,
			  /*channelRequestHandler*/ this,
			  /*payloadChannelRequestHandler*/ this,
			  /*payloadChannelNotificationHandler*/ this);
		}
		catch (const MediaSoupError& error)
		{
			delete this->udpSocket;
			this->udpSocket = nullptr;

			delete this->rtcpUdpSocket;
			this->rtcpUdpSocket = nullptr;

			throw;
		}
	}
09-23 08:05