예제 #1
0
        public void SendRtcpSenderReport(Socket srcRtpSocket, IPEndPoint dstRtpSocket, uint timestamp)
        {
            try
            {
                var ntp          = RTSPSession.DateTimeToNptTimestamp(DateTime.Now);
                var rtcpSRPacket = new RTCPPacket(Ssrc, ntp, timestamp, PacketsSent, OctetsSent);

                if (SrtcpProtect == null)
                {
                    srcRtpSocket.SendTo(rtcpSRPacket.GetBytes(), dstRtpSocket);
                }
                else
                {
                    var    rtcpSRBytes = rtcpSRPacket.GetBytes();
                    byte[] sendBuffer  = new byte[rtcpSRBytes.Length + SRTP_AUTH_KEY_LENGTH];
                    Buffer.BlockCopy(rtcpSRBytes, 0, sendBuffer, 0, rtcpSRBytes.Length);

                    int rtperr = SrtcpProtect(sendBuffer, sendBuffer.Length - SRTP_AUTH_KEY_LENGTH);
                    if (rtperr != 0)
                    {
                        logger.LogWarning("SRTP RTCP packet protection failed, result " + rtperr + ".");
                    }
                    else
                    {
                        srcRtpSocket.SendTo(sendBuffer, dstRtpSocket);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogWarning("Exception SendRtcpSenderReport. " + excp.Message);
            }
        }
예제 #2
0
        /// <summary>
        /// Creates a new RTSP session and intialises the RTP and control sockets for the session.
        /// </summary>
        /// <param name="remoteEndPoint">The remote end point of the RTSP client that requested the RTSP session be set up.</param>
        /// <returns>An RTSP session object.</returns>
        public RTSPSession CreateRTSPSession(IPEndPoint remoteEndPoint, IPEndPoint rtcpRemoteEndPoint)
        {
            var rtspSession = new RTSPSession(Guid.NewGuid().ToString(), remoteEndPoint, rtcpRemoteEndPoint);

            rtspSession.ReservePorts();
            rtspSession.OnRTPSocketDisconnected += RTPSocketDisconnected;

            lock (m_rtspSessions)
            {
                m_rtspSessions.Add(rtspSession.SessionID, rtspSession);
            }

            return(rtspSession);
        }
예제 #3
0
        public void Send(byte[] buffer)
        {
            try
            {
                Peer.LastTimestamp = (Peer.LastTimestamp == 0) ? RTSPSession.DateTimeToNptTimestamp32(DateTime.Now) : Peer.LastTimestamp + TIMESTAMP_SPACING;

                for (int index = 0; index *RTP_MAX_PAYLOAD < buffer.Length; index++)
                {
                    int offset        = (index == 0) ? 0 : (index * RTP_MAX_PAYLOAD);
                    int payloadLength = (offset + RTP_MAX_PAYLOAD < buffer.Length) ? RTP_MAX_PAYLOAD : buffer.Length - offset;

                    byte[] vp8HeaderBytes = (index == 0) ? new byte[] { 0x10 } : new byte[] { 0x00 };

                    RTPPacket rtpPacket = new RTPPacket(payloadLength + SRTP_AUTH_KEY_LENGTH + vp8HeaderBytes.Length);
                    rtpPacket.Header.SyncSource     = Peer.SSRC;
                    rtpPacket.Header.SequenceNumber = Peer.SequenceNumber++;
                    rtpPacket.Header.Timestamp      = Peer.LastTimestamp;
                    rtpPacket.Header.MarkerBit      = ((offset + payloadLength) >= buffer.Length) ? 1 : 0; // Set marker bit for the last packet in the frame.
                    rtpPacket.Header.PayloadType    = PAYLOAD_TYPE_ID;

                    Buffer.BlockCopy(vp8HeaderBytes, 0, rtpPacket.Payload, 0, vp8HeaderBytes.Length);
                    Buffer.BlockCopy(buffer, offset, rtpPacket.Payload, vp8HeaderBytes.Length, payloadLength);

                    var rtpBuffer = rtpPacket.GetBytes();

                    int rtperr = SrtpContext.ProtectRTP(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH);
                    if (rtperr != 0)
                    {
                        logger.Warn("SRTP packet protection failed, result " + rtperr + ".");
                    }
                    else
                    {
                        var connectedIceCandidate = Peer.LocalIceCandidates.Where(y => y.RemoteRtpEndPoint != null).First();
                        connectedIceCandidate.LocalRtpSocket.SendTo(rtpBuffer, connectedIceCandidate.RemoteRtpEndPoint);
                    }
                }
            }
            catch (Exception sendExcp)
            {
                // logger.Error("SendRTP exception sending to " + client.SocketAddress + ". " + sendExcp.Message);
            }
        }
예제 #4
0
        /// <summary>
        /// Periodically checks the established connections and closes any that have not had a transmission for a specified
        /// period or where the number of connections allowed per IP address has been exceeded.
        /// </summary>
        private void PruneConnections(string threadName)
        {
            try
            {
                Thread.CurrentThread.Name = threadName;

                Thread.Sleep(INITIALPRUNE_CONNECTIONS_DELAY);

                while (!Closed)
                {
                    // Check the TCP connections established by RTSP clients for any inactive ones.
                    try
                    {
                        RTSPConnection inactiveConnection = null;

                        lock (m_connectedSockets)
                        {
                            var inactiveConnectionQuery = from connection in m_connectedSockets
                                                          where connection.Value.LastTransmission < DateTime.Now.AddMinutes(PRUNE_NOTRANSMISSION_MINUTES * -1)
                                                          select connection.Key;

                            var inactiveConnectionKey = inactiveConnectionQuery.FirstOrDefault();

                            while (inactiveConnectionKey != null)
                            {
                                if (inactiveConnectionKey != null)
                                {
                                    inactiveConnection = m_connectedSockets[inactiveConnectionKey];
                                    m_connectedSockets.Remove(inactiveConnectionKey);

                                    logger.Debug("Pruning inactive RTSP connection on to remote end point " + inactiveConnection.RemoteEndPoint + ".");
                                    inactiveConnection.Close();
                                }

                                inactiveConnectionKey = inactiveConnectionQuery.FirstOrDefault();
                            }
                        }
                    }
                    catch (SocketException)
                    {
                        // Will be thrown if the socket is already closed.
                    }
                    catch (Exception pruneExcp)
                    {
                        logger.Error("Exception RTSPServer PruneConnections (pruning). " + pruneExcp.Message);
                    }

                    // Check the list of active RTSP sessions for any that have stopped communicating or that have closed.
                    try
                    {
                        RTSPSession inactiveSession = null;

                        lock (m_rtspSessions)
                        {
                            var inactiveSessionQuery = from session in m_rtspSessions
                                                       where (session.Value.DontTimeout == false &&
                                                              session.Value.RTPLastActivityAt < DateTime.Now.AddSeconds(CLOSE_RTSP_SESSION_NO_DATA_SECONDS * -1) &&
                                                              session.Value.ControlLastActivityAt < DateTime.Now.AddSeconds(CLOSE_RTSP_SESSION_NO_DATA_SECONDS * -1) &&
                                                              session.Value.StartedAt < DateTime.Now.AddSeconds(CLOSE_RTSP_SESSION_NO_DATA_SECONDS * -1) &&
                                                              session.Value.CreatedAt < DateTime.Now.AddSeconds(CLOSE_RTSP_SESSION_NO_DATA_SECONDS * -1)) ||
                                                       session.Value.IsClosed
                                                       select session.Key;

                            var inactiveSessionKey = inactiveSessionQuery.FirstOrDefault();

                            while (inactiveSessionKey != null)
                            {
                                inactiveSession = m_rtspSessions[inactiveSessionKey];
                                m_rtspSessions.Remove(inactiveSessionKey);

                                if (!inactiveSession.IsClosed)
                                {
                                    logger.Debug("Closing inactive RTSP session for session ID " + inactiveSession.SessionID + " established from RTSP client on " + inactiveSession.RemoteEndPoint + " (started at " + inactiveSession.StartedAt + ", RTP last activity at " + inactiveSession.RTPLastActivityAt + ", control last activity at " + inactiveSession.ControlLastActivityAt + ", is closed " + inactiveSession.IsClosed + ").");
                                    inactiveSession.Close();
                                }

                                inactiveSessionKey = inactiveSessionQuery.FirstOrDefault();
                            }
                        }
                    }
                    catch (Exception rtspSessExcp)
                    {
                        logger.Error("Exception RTSPServer checking for inactive RTSP sessions. " + rtspSessExcp);
                    }

                    Thread.Sleep(PRUNE_CONNECTIONS_INTERVAL * 1000);
                }

                logger.Debug("RTSPServer socket on " + m_localIPEndPoint.ToString() + " pruning connections halted.");
            }
            catch (Exception excp)
            {
                logger.Error("Exception RTSPServer PruneConnections. " + excp.Message);
            }
        }
예제 #5
0
        public void Start(string url)
        {
            _url = url;

            Match urlMatch = Regex.Match(url, @"rtsp://(?<hostname>\S+?)/", RegexOptions.IgnoreCase);

            if (!urlMatch.Success)
            {
                throw new ApplicationException("The URL provided to the RTSP client was not recognised, " + url + ".");
            }
            else
            {
                string hostname = urlMatch.Result("${hostname}");
                int    port     = RTSP_PORT;

                if (hostname.Contains(':'))
                {
                    port     = SIPSorcery.Sys.IPSocket.ParsePortFromSocket(hostname);
                    hostname = SIPSorcery.Sys.IPSocket.ParseHostFromSocket(hostname);
                }

                logger.LogDebug("RTSP client connecting to " + hostname + ", port " + port + ".");

                _rtspConnection = new TcpClient(hostname, port);
                _rtspStream     = _rtspConnection.GetStream();

                _rtspSession = new RTSPSession();
                _rtspSession.RTPPayloadHeaderLength = _rtpPayloadHeaderLength;
                _rtspSession.ReservePorts();
                _rtspSession.OnRTPQueueFull += RTPQueueFull;

                RTSPRequest rtspRequest = new RTSPRequest(RTSPMethodsEnum.SETUP, url);
                RTSPHeader  rtspHeader  = new RTSPHeader(_cseq++, null);
                rtspHeader.Transport = new RTSPTransportHeader()
                {
                    ClientRTPPortRange = _rtspSession.RTPPort + "-" + _rtspSession.ControlPort
                };
                rtspRequest.Header = rtspHeader;
                string rtspReqStr = rtspRequest.ToString();

                RTSPMessage rtspMessage = null;

                System.Diagnostics.Debug.WriteLine(rtspReqStr);

                byte[] rtspRequestBuffer = Encoding.UTF8.GetBytes(rtspReqStr);
                _rtspStream.Write(rtspRequestBuffer, 0, rtspRequestBuffer.Length);

                byte[] buffer    = new byte[2048];
                int    bytesRead = _rtspStream.Read(buffer, 0, 2048);

                if (bytesRead > 0)
                {
                    System.Diagnostics.Debug.WriteLine(Encoding.UTF8.GetString(buffer, 0, bytesRead));

                    rtspMessage = RTSPMessage.ParseRTSPMessage(buffer, null, null);

                    if (rtspMessage.RTSPMessageType == RTSPMessageTypesEnum.Response)
                    {
                        var setupResponse = RTSPResponse.ParseRTSPResponse(rtspMessage);

                        if (setupResponse.Status == RTSPResponseStatusCodesEnum.OK)
                        {
                            _rtspSession.SessionID      = setupResponse.Header.Session;
                            _rtspSession.RemoteEndPoint = new IPEndPoint((_rtspConnection.Client.RemoteEndPoint as IPEndPoint).Address, setupResponse.Header.Transport.GetServerRTPPort());
                            _rtspSession.Start();

                            logger.LogDebug("RTSP Response received to SETUP: " + setupResponse.Status + ", session ID " + _rtspSession.SessionID + ", server RTP endpoint " + _rtspSession.RemoteEndPoint + ".");

                            if (OnSetupSuccess != null)
                            {
                                OnSetupSuccess(this);
                            }
                        }
                        else
                        {
                            logger.LogWarning("RTSP Response received to SETUP: " + setupResponse.Status + ".");
                            throw new ApplicationException("An error response of " + setupResponse.Status + " was received for an RTSP setup request.");
                        }
                    }
                }
                else
                {
                    throw new ApplicationException("Zero bytes were read from the RTSP client socket in response to a SETUP request.");
                }
            }
        }