Ejemplo n.º 1
0
        /// <summary>
        /// Handles the setup CMD.
        /// </summary>
        /// <param name="cseq">The cseq.</param>
        /// <param name="urlPreSuffix">The URL pre suffix.</param>
        /// <param name="urlSuffix">The URL suffix.</param>
        /// <param name="request">The request string.</param>
        private void HandleSetupCmd(string cseq, string urlPreSuffix, string urlSuffix, string request)
        {
            // Note: At present, I will use only one streaming mode of RTP_UDP
            // to transfer the data between server and client.

            // First, judges that the server media session exists or not.
            if (serverMediaSession == null)
            {
                serverMediaSession = rtspServer.LookupServerMediaSession(urlPreSuffix);
                if (serverMediaSession == null)
                {
                    HandleNotFoundCmd(cseq);
                    return;
                }
            }

            // Looks for a "Transport:" header in the request string,
            // to extract client parameters:
            int clientRtpPort;
            int clientRtcpPort;

            bool result = RtspCommon.ParseClientTransportHeader(request,
                                                                out clientRtpPort, out clientRtcpPort);

            if (!result)
            {
                HandleUnsupportedTransportCmd(cseq);
                return;
            }

            // Then, gets the server parameters from the server media session:
            streamState = null;
            string destinationAddr = base.ClientSessionIP;
            string sourceAddr      = Utils.GetLocalAddresses()[0];
            int    serverRtpPort   = rtspServer.GenerateRtpPortNumber();
            int    serverRtcpPort  = serverRtpPort + 1;

            result = serverMediaSession.GetStreamParameters(base.ClientSessionId,
                                                            base.ClientSessionIP, clientRtpPort, clientRtcpPort,
                                                            serverRtpPort, serverRtcpPort, ref streamState);
            if (!result)
            {
                HandleUnsupportedTransportCmd(cseq);
                return;
            }

            // Generates the response information now.
            StringBuilder sb = new StringBuilder();

            sb.Append("RTSP/1.0 200 OK\r\n");
            sb.AppendFormat("CSeq: {0}\r\n", cseq);
            sb.AppendFormat("Date: {0}\r\n", DateTime.Now.ToLocalTime());
            sb.Append("Transport: RTP/AVP;unicast;");
            sb.AppendFormat("destination={0};source={1};", destinationAddr, sourceAddr);
            sb.AppendFormat("client_port={0}-{1};", clientRtpPort, clientRtcpPort);
            sb.AppendFormat("server_port={0}-{1}\r\n", serverRtpPort, serverRtcpPort);
            sb.AppendFormat("Session: {0}\r\n\r\n", base.ClientSessionId);

            response = sb.ToString();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Sends the setup CMD.
        /// </summary>
        /// <returns>Succeeded or failed.</returns>
        private bool SendSetupCmd()
        {
            if (socket == null || !socket.Connected)
            {
                return(false);
            }

            bool result = false;

            clientRtpPort  = Utils.GenerateRandomNumber(8000, 9000);
            clientRtcpPort = clientRtpPort + 1;
            sessionId      = string.Empty;

            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("{0} ", Constants.RTSP_CMD_SETUP);                                                           // command name of 'SETUP'
            sb.AppendFormat("{0} RTSP/1.0\r\n", requestUrl);                                                             // request url
            sb.AppendFormat("CSeq: {0}\r\n", (++rtspSeqNum).ToString());                                                 // sequence number
            sb.AppendFormat("Transport: client_port={0}-{1};\r\n", clientRtpPort.ToString(), clientRtcpPort.ToString()); // transport string
            sb.AppendFormat("Session: {0}\r\n", sessionId);                                                              // session id
            sb.AppendFormat("User-Agent: {0}\r\n\r\n", Constants.USER_AGENT_HEADER);                                     // user agent header

            result = SendRtspRequest(sb.ToString());
            if (!result)
            {
                return(false);
            }

            result = GetRtspResponse();
            if (!result)
            {
                return(false);
            }

            result = RtspCommon.ParseServerTransportHeader(response,
                                                           out clientAddress, out serverAddress,
                                                           out serverRtpPort, out serverRtcpPort);
            if (!result)
            {
                return(false);
            }

            sessionId = RtspCommon.ParseSessionHeader(response);

            return(true);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Handles the play CMD.
        /// </summary>
        /// <param name="cseq">The cseq.</param>
        /// <param name="rtspUrl">The rtsp url.</param>
        /// <param name="request">The request string.</param>
        private void HandlePlayCmd(string cseq, string rtspUrl, string request)
        {
            if (serverMediaSession == null || streamState == null)
            {
                return;
            }

            // Parses the client's "Scale:" header:
            string scaleHeader = string.Empty;
            float  scale;
            bool   hasScaleHeader = RtspCommon.ParseScaleHeader(request, out scale);

            if (hasScaleHeader)
            {
                scaleHeader = string.Format("Scale: {0}\r\n", scale);
            }

            // Parses the client's "Range:" header:
            string rangeHeader    = string.Empty;
            double rangeStart     = 0.0;
            double rangeEnd       = 0.0;
            bool   hasRangeHeader = RtspCommon.ParseRangeHeader(request, out rangeStart, out rangeEnd);

            double duration = this.serverMediaSession.GetDuration();

            if (rangeEnd <= 0.0 || rangeEnd > duration)
            {
                rangeEnd = duration;
            }

            if (rangeStart < 0.0)
            {
                rangeStart = 0.0;
            }
            else if (rangeEnd > 0.0 && scale > 0.0 && rangeStart > rangeEnd)
            {
                rangeStart = rangeEnd;
            }

            if (hasRangeHeader)
            {
                if (rangeStart == 0.0 && scale >= 0.0)
                {
                    rangeHeader = string.Format("Range: npt={0}-\r\n", rangeStart);
                }
                else
                {
                    rangeHeader = string.Format("Range: npt={0}-{1}\r\n", rangeStart, rangeEnd);
                }
            }

            // Handles any require of scaling on session before starting streaming:
            if (hasScaleHeader)
            {
                // No implementation at present.
            }

            // Handles any require of seeking on session before starting streaming:
            if (hasRangeHeader)
            {
                serverMediaSession.SeekStream(streamState, rangeStart);
            }

            // Now, starts the stream:
            int rtpSeqNum    = 0;
            int rtpTimestamp = 0;

            serverMediaSession.StartStream(streamState, ref rtpSeqNum, ref rtpTimestamp);

            string rtpInfo = string.Format("RTP-Info: url={0}/{1};seq={2};rtptime={3}\r\n",
                                           rtspUrl, serverMediaSession.TrackId, rtpSeqNum, rtpTimestamp);

            // Generates the response information now.
            StringBuilder sb = new StringBuilder();

            sb.Append("RTSP/1.0 200 OK\r\n");
            sb.AppendFormat("CSeq: {0}\r\n", cseq);
            sb.AppendFormat("Date: {0}\r\n", DateTime.Now.ToLocalTime());
            sb.AppendFormat("{0}\r\n{1}\r\n", scaleHeader, rangeHeader);
            sb.AppendFormat("Session: {0}\r\n{1}\r\n", base.ClientSessionId, rtpInfo);

            response = sb.ToString();
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Handles the incoming request.
        /// </summary>
        /// <param name="recvBuffer">The receive buffer.</param>
        /// <param name="recvBufferSize">Size of the receive buffer.</param>
        private void HandleIncomingRequest(byte[] recvBuffer, int recvBufferSize)
        {
            string cmdName;
            string rtspUrl;
            string urlPreSuffix;
            string urlSuffix;
            string cseq;

            string request = Utils.BytesToString(recvBuffer, recvBufferSize);

            Utils.OutputMessage(false, MsgLevel.Debug, string.Empty, request);

            // Parses the request string into command name and 'CSeq', then handle the command.
            bool isSucceeded = RtspCommon.ParseRequestString(
                request, out cmdName, out rtspUrl, out urlPreSuffix, out urlSuffix, out cseq);

            if (isSucceeded)
            {
                switch (cmdName)
                {
                case Constants.RTSP_CMD_OPTIONS:
                    HandleOptionsCmd(cseq);
                    break;

                case Constants.RTSP_CMD_DESCRIBE:
                    HandleDescribeCmd(cseq, rtspUrl, urlSuffix, request);
                    break;

                case Constants.RTSP_CMD_SETUP:
                    HandleSetupCmd(cseq, urlPreSuffix, urlSuffix, request);
                    break;

                case Constants.RTSP_CMD_PLAY:
                    HandlePlayCmd(cseq, rtspUrl, request);
                    break;

                case Constants.RTSP_CMD_PAUSE:
                    HandlePauseCmd(cseq);
                    break;

                case Constants.RTSP_CMD_TEARDOWN:
                    HandleTearDownCmd(cseq);
                    break;

                default:
                    HandleNotSupportCmd(cseq);
                    break;
                }

                SessionState = cmdName;
                this.OnClientSessionUpdated(this);
            }
            else
            {
                // Parses request string failed!
                HandleBadCmd();
            }

            // After we handle the client request, we must send the response to the client.
            // *****
            //Converts string to bytes.
            byte[] sendBuffer = Utils.StringToBytes(response);

            // Sends the rtsp response to the client.
            clientSocket.SendDatagram(sendBuffer, sendBuffer.Length);
        }