Example #1
0
        protected override async Task WriteAsync(byte[] buffer, int offset, int count)
        {
            using (_commandsClient = NetworkClientFactory.CreateTcpClient())
            {
                Uri connectionUri = ConnectionParameters.ConnectionUri;

                int httpPort = connectionUri.Port != -1 ? connectionUri.Port : Constants.DefaultHttpPort;

                await _commandsClient.ConnectAsync(connectionUri.Host, httpPort);

                string base64CodedCommandString = Convert.ToBase64String(buffer, offset, count);
                byte[] base64CommandBytes       = Encoding.ASCII.GetBytes(base64CodedCommandString);

                string request      = ComposePostRequest(base64CommandBytes);
                byte[] requestBytes = Encoding.ASCII.GetBytes(request);

                ArraySegment <byte>[] sendList =
                {
                    new ArraySegment <byte>(requestBytes),
                    new ArraySegment <byte>(base64CommandBytes)
                };

                await _commandsClient.SendAsync(sendList, SocketFlags.None);
            }
        }
        public override async Task ConnectAsync(CancellationToken token)
        {
            _tcpClient = NetworkClientFactory.CreateTcpClient();

            Uri connectionUri = ConnectionParameters.ConnectionUri;

            int rtspPort = connectionUri.Port != -1 ? connectionUri.Port : Constants.DefaultRtspPort;

            await _tcpClient.ConnectAsync(connectionUri.Host, rtspPort);

            _remoteEndPoint = _tcpClient.RemoteEndPoint;
            _networkStream  = new NetworkStream(_tcpClient, false);
        }
Example #3
0
        public override async Task ConnectAsync(CancellationToken token)
        {
            _commandCounter = 0;
            _sessionCookie  = Guid.NewGuid().ToString("N").Substring(0, 10);

            _streamDataClient = NetworkClientFactory.CreateTcpClient();

            Uri connectionUri = ConnectionParameters.ConnectionUri;

            int httpPort = connectionUri.Port != -1 ? connectionUri.Port : Constants.DefaultHttpPort;

            await _streamDataClient.ConnectAsync(connectionUri.Host, httpPort);

            _remoteEndPoint    = _streamDataClient.RemoteEndPoint;
            _dataNetworkStream = new NetworkStream(_streamDataClient, false);

            string request = ComposeGetRequest();

            byte[] requestBytes = Encoding.ASCII.GetBytes(request);

            await _dataNetworkStream.WriteAsync(requestBytes, 0, requestBytes.Length, token);

            var buffer = new byte[Constants.MaxResponseHeadersSize];
            int read   = await ReadUntilEndOfHeadersAsync(_dataNetworkStream, buffer);

            var ms           = new MemoryStream(buffer, 0, read);
            var streamReader = new StreamReader(ms, Encoding.ASCII);

            string responseLine = streamReader.ReadLine();

            if (responseLine == null)
            {
                throw new HttpBadResponseException("Empty response");
            }

            string[] tokens = responseLine.Split(' ');

            if (tokens.Length != 3)
            {
                throw new HttpRequestException("Invalid first response line");
            }

            HttpStatusCode statusCode = (HttpStatusCode)int.Parse(tokens[1]);

            if (statusCode == HttpStatusCode.OK)
            {
                return;
            }

            if (statusCode == HttpStatusCode.Unauthorized &&
                !ConnectionParameters.Credentials.IsEmpty() &&
                _authenticator == null)
            {
                NameValueCollection headers = HeadersParser.ParseHeaders(streamReader);

                string authenticateHeader = headers.Get(WellKnownHeaders.WwwAuthenticate);

                if (string.IsNullOrEmpty(authenticateHeader))
                {
                    throw new HttpBadResponseCodeException(statusCode);
                }

                _authenticator = Authenticator.Create(ConnectionParameters.Credentials, authenticateHeader);

                _streamDataClient.Dispose();

                await ConnectAsync(token);

                return;
            }

            throw new HttpBadResponseCodeException(statusCode);
        }
        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);
        }