private async Task SetupTrackAsync(RtspMediaTrackInfo track, CancellationToken token) { RtspRequestMessage setupRequest; RtspResponseMessage setupResponse; int rtpChannelNumber; int rtcpChannelNumber; Socket rtpClient = null; Socket rtcpClient = null; if (_connectionParameters.RtpTransport == RtpTransportProtocol.UDP) { rtpClient = NetworkClientFactory.CreateUdpClient(); rtcpClient = NetworkClientFactory.CreateUdpClient(); try { IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0); rtpClient.Bind(endPoint); int rtpPort = ((IPEndPoint)rtpClient.LocalEndPoint).Port; endPoint = new IPEndPoint(IPAddress.Any, rtpPort + 1); try { rtcpClient.Bind(endPoint); } catch (SocketException e) when(e.SocketErrorCode == SocketError.AddressAlreadyInUse) { endPoint = new IPEndPoint(IPAddress.Any, 0); rtcpClient.Bind(endPoint); } int rtcpPort = ((IPEndPoint)rtcpClient.LocalEndPoint).Port; setupRequest = _requestMessageFactory.CreateSetupUdpUnicastRequest(track.TrackName, rtpPort, rtcpPort); setupResponse = await _rtspTransportClient.EnsureExecuteRequest(setupRequest, token); } catch { rtpClient.Close(); rtcpClient.Close(); throw; } } else { int channelCounter = _streamsMap.Count; rtpChannelNumber = channelCounter; rtcpChannelNumber = ++channelCounter; setupRequest = _requestMessageFactory.CreateSetupTcpInterleavedRequest(track.TrackName, rtpChannelNumber, rtcpChannelNumber); setupResponse = await _rtspTransportClient.EnsureExecuteRequest(setupRequest, token); } string transportHeader = setupResponse.Headers[WellKnownHeaders.Transport]; if (string.IsNullOrEmpty(transportHeader)) { throw new RtspBadResponseException("Transport header is not found"); } string portsAttributeName = _connectionParameters.RtpTransport == RtpTransportProtocol.UDP ? "server_port" : "interleaved"; string[] transportAttributes = transportHeader.Split(TransportAttributesSeparator, StringSplitOptions.RemoveEmptyEntries); string portsAttribute = transportAttributes.FirstOrDefault(a => a.StartsWith(portsAttributeName, StringComparison.InvariantCultureIgnoreCase)); if (portsAttribute == null || !TryParseSeverPorts(portsAttribute, out rtpChannelNumber, out rtcpChannelNumber)) { throw new RtspBadResponseException("Server ports are not found"); } if (_connectionParameters.RtpTransport == RtpTransportProtocol.UDP) { string sourceAttribute = transportAttributes.FirstOrDefault(a => a.StartsWith("source", StringComparison.InvariantCultureIgnoreCase)); int equalSignIndex; IPAddress sourceAddress; if (sourceAttribute != null && (equalSignIndex = sourceAttribute.IndexOf("=", StringComparison.CurrentCultureIgnoreCase)) != -1) { sourceAddress = IPAddress.Parse(sourceAttribute.Substring(++equalSignIndex).Trim()); } else { sourceAddress = ((IPEndPoint)_rtspTransportClient.RemoteEndPoint).Address; } Debug.Assert(rtpClient != null, nameof(rtpClient) + " != null"); rtpClient.Connect(new IPEndPoint(sourceAddress, rtpChannelNumber)); Debug.Assert(rtcpClient != null, nameof(rtcpClient) + " != null"); rtcpClient.Connect(new IPEndPoint(sourceAddress, rtcpChannelNumber)); var udpHolePunchingPacketSegment = new ArraySegment <byte>(Array.Empty <byte>()); await rtpClient.SendAsync(udpHolePunchingPacketSegment, SocketFlags.None); await rtcpClient.SendAsync(udpHolePunchingPacketSegment, SocketFlags.None); _udpClientsMap[rtpChannelNumber] = rtpClient; _udpClientsMap[rtcpChannelNumber] = rtcpClient; } ParseSessionHeader(setupResponse.Headers[WellKnownHeaders.Session]); IMediaPayloadParser mediaPayloadParser = MediaPayloadParser.CreateFrom(track.Codec); IRtpSequenceAssembler rtpSequenceAssembler; if (_connectionParameters.RtpTransport == RtpTransportProtocol.TCP) { rtpSequenceAssembler = null; mediaPayloadParser.FrameGenerated = OnFrameGeneratedLockfree; } else { rtpSequenceAssembler = new RtpSequenceAssembler(Constants.UdpReceiveBufferSize, 256); mediaPayloadParser.FrameGenerated = OnFrameGeneratedThreadSafe; } var rtpStream = new RtpStream(mediaPayloadParser, track.SamplesFrequency, rtpSequenceAssembler); _streamsMap.Add(rtpChannelNumber, rtpStream); var rtcpStream = new RtcpStream(); rtcpStream.SessionShutdown += (sender, args) => _serverCancellationTokenSource.Cancel(); _streamsMap.Add(rtcpChannelNumber, rtcpStream); uint senderSyncSourceId = (uint)_random.Next(); var rtcpReportsProvider = new RtcpReceiverReportsProvider(rtpStream, rtcpStream, senderSyncSourceId); _reportProvidersMap.Add(rtpChannelNumber, rtcpReportsProvider); }
private async Task SetupTrackAsync(RtspMediaTrackInfo track, CancellationToken token) { RtspRequestMessage setupRequest; RtspResponseMessage setupResponse; int rtpChannelNumber; int rtcpChannelNumber; Socket rtpClient = null; Socket rtcpClient = null; if (_connectionParameters.RtpTransport == RtpTransportProtocol.UDP) { rtpClient = NetworkClientFactory.CreateUdpClient(); rtcpClient = NetworkClientFactory.CreateUdpClient(); try { IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0); rtpClient.Bind(endPoint); int rtpPort = ((IPEndPoint)rtpClient.LocalEndPoint).Port; endPoint = new IPEndPoint(IPAddress.Any, rtpPort + 1); try { rtcpClient.Bind(endPoint); } catch (SocketException e) when(e.SocketErrorCode == SocketError.AddressAlreadyInUse) { endPoint = new IPEndPoint(IPAddress.Any, 0); rtcpClient.Bind(endPoint); } int rtcpPort = ((IPEndPoint)rtcpClient.LocalEndPoint).Port; setupRequest = _requestMessageFactory.CreateSetupUdpUnicastRequest(track.TrackName, rtpPort, rtcpPort); setupResponse = await _rtspTransportClient.EnsureExecuteRequest(setupRequest, token); } catch { rtpClient.Close(); rtcpClient.Close(); throw; } } else { int channelCounter = _streamsMap.Count; rtpChannelNumber = channelCounter; rtcpChannelNumber = ++channelCounter; setupRequest = _requestMessageFactory.CreateSetupTcpInterleavedRequest(track.TrackName, rtpChannelNumber, rtcpChannelNumber); setupResponse = await _rtspTransportClient.EnsureExecuteRequest(setupRequest, token); } string transportHeader = setupResponse.Headers[WellKnownHeaders.Transport]; if (string.IsNullOrEmpty(transportHeader)) { throw new RtspBadResponseException("Transport header is not found"); } string attributeName = _connectionParameters.RtpTransport == RtpTransportProtocol.UDP ? "server_port" : "interleaved"; if (!ParseSeverPorts(transportHeader, attributeName, out rtpChannelNumber, out rtcpChannelNumber)) { throw new RtspBadResponseException("Server ports are not found"); } if (_connectionParameters.RtpTransport == RtpTransportProtocol.UDP) { IPEndPoint remoteEndPoint = (IPEndPoint)_rtspTransportClient.RemoteEndPoint; rtpClient?.Connect(new IPEndPoint(remoteEndPoint.Address, rtpChannelNumber)); rtcpClient?.Connect(new IPEndPoint(remoteEndPoint.Address, rtcpChannelNumber)); var udpHolePunchingPacketSegment = new ArraySegment <byte>(Array.Empty <byte>()); await rtpClient.SendAsync(udpHolePunchingPacketSegment, SocketFlags.None); await rtcpClient.SendAsync(udpHolePunchingPacketSegment, SocketFlags.None); _udpClientsMap[rtpChannelNumber] = rtpClient; _udpClientsMap[rtcpChannelNumber] = rtcpClient; } ParseSessionHeader(setupResponse.Headers[WellKnownHeaders.Session]); IMediaPayloadParser mediaPayloadParser = MediaPayloadParser.CreateFrom(track.Codec); IRtpSequenceAssembler rtpSequenceAssembler; if (_connectionParameters.RtpTransport == RtpTransportProtocol.TCP) { rtpSequenceAssembler = null; mediaPayloadParser.FrameGenerated = OnFrameGeneratedLockfree; } else { rtpSequenceAssembler = new RtpSequenceAssembler(Constants.UdpReceiveBufferSize, 8); mediaPayloadParser.FrameGenerated = OnFrameGeneratedThreadSafe; } var rtpStream = new RtpStream(mediaPayloadParser, track.SamplesFrequency, rtpSequenceAssembler); _streamsMap.Add(rtpChannelNumber, rtpStream); var rtcpStream = new RtcpStream(); rtcpStream.SessionShutdown += (sender, args) => _serverCancellationTokenSource.Cancel(); _streamsMap.Add(rtcpChannelNumber, rtcpStream); uint senderSyncSourceId = (uint)_random.Next(); var rtcpReportsProvider = new RtcpReceiverReportsProvider(rtpStream, rtcpStream, senderSyncSourceId); _reportProvidersMap.Add(rtpChannelNumber, rtcpReportsProvider); }