PushResponseHeader() 공개 메소드

public PushResponseHeader ( string name, string value ) : void
name string
value string
리턴 void
        private bool SendAuthenticationChallenge(RtspProtocol from, Variant realm)
        {
            //10. Ok, the user doesn't know that this needs authentication. We
            //will respond back with a nice 401. Generate the line first
            string wwwAuthenticate = HTTPAuthHelper.GetWWWAuthenticateHeader(
                    realm["method"],
                    realm["name"]);

            //12. Save the nonce for later validation when new requests are coming in again
            from.CustomParameters["wwwAuthenticate"] = wwwAuthenticate;

            //13. send the response
            from.PushResponseFirstLine(RTSP_VERSION_1_0, 401, "Unauthorized");
            from.PushResponseHeader(HTTP_HEADERS_WWWAUTHENTICATE, wwwAuthenticate);
            return from.SendResponseMessage();
        }
        private bool HandleRTSPRequestSetupOutbound(RtspProtocol @from, Variant requestHeaders, string requestContent)
        {
            //1. Minimal sanitize
            if (requestHeaders[RTSP_HEADERS, RTSP_HEADERS_TRANSPORT] == null)
            {
                FATAL("RTSP %s request doesn't have %s header line",
                        RTSP_METHOD_SETUP,
                        RTSP_HEADERS_TRANSPORT);
                return false;
            }

            //2. get the transport header line
            string raw = requestHeaders[RTSP_HEADERS, RTSP_HEADERS_TRANSPORT];
            Variant transport = Variant.Get();
            if (!Rtsp.SDP.ParseTransportLine(raw, transport))
            {
                FATAL("Unable to parse transport line {0}", (raw));
                return false;
            }
            bool forceTcp = false;
            if (transport["client_port"]!=null && (transport["rtp/avp/udp"]!=null || transport["rtp/avp"]!=null))
            {
                forceTcp = false;
            }
            else if (transport["interleaved"]!=null && transport["rtp/avp/tcp"]!=null)
            {
                forceTcp = true;
            }
            else
            {
                FATAL("Invalid transport line: {0}", (transport.ToString()));
                return false;
            }
            from.CustomParameters["forceTcp"] = forceTcp;
            
            //3. Get the outbound connectivity
            OutboundConnectivity pOutboundConnectivity = GetOutboundConnectivity(from, forceTcp);
            if (pOutboundConnectivity == null)
            {
                FATAL("Unable to get the outbound connectivity");
                return false;
            }

            //5. Find out if this is audio or video
            bool isAudioTrack;
            string rawUrl = requestHeaders[RTSP_FIRST_LINE,RTSP_URL];
            string audioTrackId = "trackID=" + from.CustomParameters["audioTrackId"];
            string videoTrackId = "trackID=" + from.CustomParameters["videoTrackId"];
            /*FINEST("rawUrl: %s; audioTrackId: %s; videoTrackId: %s; fa: %d; fv: %d",
                (rawUrl),
                (audioTrackId),
                (videoTrackId),
                rawUrl.find(audioTrackId) != string::npos,
                rawUrl.find(videoTrackId) != string::npos
            );*/
            if (rawUrl.Contains(audioTrackId))
            {
                isAudioTrack = true;
            }
            else if (rawUrl.Contains(videoTrackId))
            {
                isAudioTrack = false;
            }
            else
            {
                FATAL("Invalid track. Wanted: {0} or {1}; Got: {2}",
                        (from.CustomParameters["audioTrackId"]),
                        (from.CustomParameters["videoTrackId"]),
                        (requestHeaders[RTSP_FIRST_LINE,RTSP_URL]));
                return false;
            }
            from.CustomParameters["isAudioTrack"] = isAudioTrack;
            
            if (isAudioTrack)
            {
                if (forceTcp)
                {
                    from.CustomParameters["audioDataChannelNumber"] = transport["interleaved","data"];
                    from.CustomParameters["audioRtcpChannelNumber"] = transport["interleaved","rtcp"];
                    from.CustomParameters["audioTrackUri"] = requestHeaders[RTSP_FIRST_LINE,RTSP_URL];
                    pOutboundConnectivity.HasAudio = true;
                }
                else
                {
                    from.CustomParameters["audioDataPortNumber"] = transport["client_port","data"];
                    from.CustomParameters["audioRtcpPortNumber"] = transport["client_port","rtcp"];
                    from.CustomParameters["audioTrackUri"] = requestHeaders[RTSP_FIRST_LINE,RTSP_URL];
                    pOutboundConnectivity.HasAudio = true;
                }
            }
            else
            {
                if (forceTcp)
                {
                    from.CustomParameters["videoDataChannelNumber"] = transport["interleaved","data"];
                    from.CustomParameters["videoRtcpChannelNumber"] = transport["interleaved","rtcp"];
                    from.CustomParameters["videoTrackUri"] = requestHeaders[RTSP_FIRST_LINE,RTSP_URL];
                    pOutboundConnectivity.HasVideo = true;
                }
                else
                {
                    from.CustomParameters["videoDataPortNumber"] = transport["client_port","data"];
                    from.CustomParameters["videoRtcpPortNumber"] = transport["client_port","rtcp"];
                    from.CustomParameters["videoTrackUri"] = requestHeaders[RTSP_FIRST_LINE,RTSP_URL];
                    pOutboundConnectivity.HasVideo = true;
                }
            }
            
            //10. Create a session
            from.GenerateSessionId();

            //11 Compose the response
            from.PushResponseFirstLine(RTSP_VERSION_1_0, 200, "OK");
            @from.PushResponseHeader(RTSP_HEADERS_TRANSPORT,
                forceTcp
                    ? "RTP/AVP/TCP;unicast;interleaved="+ transport["interleaved","all"]
                    : $"RTP/AVP/UDP;unicast;source={((TCPCarrier) @from.IOHandler).NearIP};client_port={(string)(transport["client_port","all"])};server_port={(isAudioTrack ? (pOutboundConnectivity.AudioPorts) : (pOutboundConnectivity.VideoPorts))};ssrc={(isAudioTrack ? pOutboundConnectivity.AudioSSRC : pOutboundConnectivity.VideoSSRC)}");
            //12. Done
            return from.SendResponseMessage();
        }
        public bool HandleRTSPRequest(RtspProtocol from,Variant requestHeaders,string requestContent)
        {
            string method = requestHeaders[RTSP_FIRST_LINE, RTSP_METHOD];
            //1. we need a CSeq
            if (requestHeaders[RTSP_HEADERS, RTSP_HEADERS_CSEQ] == null)
            {
                FATAL("Request doesn't have {0}:\n{1}", RTSP_HEADERS_CSEQ, requestHeaders);
                return false;
            }
            //2. Validate session id
            string wantedSessionId = from.SessionId;
            if (!string.IsNullOrEmpty(wantedSessionId))
            {
                var requestSessionId = "";
                if (requestHeaders[RTSP_HEADERS, RTSP_HEADERS_SESSION] == null)
                {
                    FATAL("No session id");
                    return false;
                }
                requestSessionId = requestHeaders[RTSP_HEADERS, RTSP_HEADERS_SESSION];
                var parts = requestSessionId.Split(';');
                if (parts.Length >= 1)
                {
                    requestSessionId = parts[0];
                }
                if (requestSessionId != wantedSessionId)
                {
                    FATAL("Invalid session ID. Wanted: `{0}`; Got: `{1}`",
                            (wantedSessionId),
                            (requestSessionId));
                    return false;
                }
            }
            //4. Prepare a fresh new response. Add the sequence number
            from.ClearResponseMessage();
            from.PushResponseHeader(RTSP_HEADERS_CSEQ, requestHeaders[RTSP_HEADERS, RTSP_HEADERS_CSEQ]);
            //5. Do we have authentication? We will authenticate everything except "OPTIONS"
            if ( !string.IsNullOrEmpty(_usersFile) && NeedAuthentication(from,requestHeaders,requestContent))
            {
                //6. Re-parse authentication file if necessary
                if (!ParseUsersFile())
                {
                    FATAL("Unable to parse authentication file");
                    return false;
                }
                //7. Get the real name to use it further in authentication process
                string realmName = GetAuthenticationRealm(from, requestHeaders,
                        requestContent);
                //8. Do we have that realm?
                if (_realms[realmName]==null)
                {
                    FATAL("Realm `{0}` not found", (realmName));
                    return false;
                }
                Variant realm = _realms[realmName];
                //9. Is the user even trying to authenticate?
                if (requestHeaders[RTSP_HEADERS, RTSP_HEADERS_AUTHORIZATION] == null)
                {
                    return SendAuthenticationChallenge(from, realm);
                }
                else
                {
                    //14. The client sent us some response. Validate it now
                    //Did we ever sent him an authorization challange?
                    if (from.CustomParameters["wwwAuthenticate"] ==null)
                    {
                        FATAL("Client tried to authenticate and the server didn't required that");
                        return false;
                    }

                    //15. Get the server challenge
                    string wwwAuthenticate = from.CustomParameters["wwwAuthenticate"];

                    //16. Get the client response
                    string authorization = requestHeaders[RTSP_HEADERS, RTSP_HEADERS_AUTHORIZATION];

                    //17. Try to authenticate
                    if (!HTTPAuthHelper.ValidateAuthRequest(wwwAuthenticate,
                            authorization,
                            method,
                            (string)requestHeaders[RTSP_FIRST_LINE,RTSP_URL],
                            realm))
                    {
                        WARN("Authorization failed: challenge: {0}; response: {1}",
                                wwwAuthenticate, authorization);
                        return SendAuthenticationChallenge(from, realm);
                    }

                    //18. Success. User authenticated
                    //INFO("User authenticated: %s", (authorization));
                }
            }
            switch (method)
            {
                case RTSP_METHOD_OPTIONS:
                    from.PushResponseFirstLine(RTSP_VERSION_1_0, 200, "OK");
                    from.PushResponseHeader(RTSP_HEADERS_PUBLIC, "DESCRIBE, OPTIONS, PAUSE, PLAY, SETUP, TEARDOWN, ANNOUNCE, RECORD");
                    return from.SendResponseMessage();
                case RTSP_METHOD_DESCRIBE:
                    //1. get the stream name
                    Uri uri = new Uri(requestHeaders[RTSP_FIRST_LINE,RTSP_URL]);
                    
                    string streamName = (uri.Segments.LastOrDefault(x=>!x.EndsWith("/"))??"")+uri.Query;
                    if (streamName == "")
                    {
                        FATAL("Invalid stream name");
                        return false;
                    }

                    //2. Get the inbound stream capabilities
                    IInNetStream pInStream = GetInboundStream(streamName);

                    //3. Prepare the body of the response
                    string outboundContent = ComputeSDP(from, streamName, "", "0.0.0.0");
                    if (outboundContent == "")
                    {
                        FATAL("Unable to compute SDP");
                        return false;
                    }

                    //4. Save the stream id for later usage
                    from.CustomParameters["streamId"] = pInStream.UniqueId;

                    //5. Mark this connection as outbound connection
                    from.CustomParameters["isInbound"] = false;

                    //6. prepare the response
                    from.PushResponseFirstLine(RTSP_VERSION_1_0, 200, "OK");
                    from.PushResponseHeader(RTSP_HEADERS_CONTENT_TYPE, RTSP_HEADERS_ACCEPT_APPLICATIONSDP);
                    from.PushResponseContent(outboundContent, false);

                    //7. Done
                    return from.SendResponseMessage();
                case RTSP_METHOD_SETUP:
                    if (from.CustomParameters["isInbound"] != VariantType.Boolean)
                    {
                        FATAL("Invalid state");
                        return false;
                    }

                    return @from.CustomParameters["isInbound"] ? HandleRTSPRequestSetupInbound(@from, requestHeaders, requestContent) : HandleRTSPRequestSetupOutbound(@from, requestHeaders, requestContent);
                case RTSP_METHOD_PLAY:
                    return HandleRTSPRequestPlay(from, requestHeaders, requestContent);
                case RTSP_METHOD_TEARDOWN:
                    from.EnqueueForDelete();
                    return true;
                case RTSP_METHOD_ANNOUNCE:
                    return HandleRTSPRequestAnnounce(from, requestHeaders, requestContent);
                case RTSP_METHOD_RECORD:
                    //1. Make sure we have everything and we are in the proper state
                    if ((from.CustomParameters["isInbound"] != VariantType.Boolean)
                            || ((bool)from.CustomParameters["isInbound"] != true))
                    {
                        FATAL("Invalid state");
                        return false;
                    }

                    if (from.CustomParameters["pendingTracks"] != VariantType.Map)
                    {
                        FATAL("Invalid state");
                        return false;
                    }

                    //3. Get the inbound connectivity
                    InboundConnectivity pConnectivity = from.InboundConnectivity;
                    if (pConnectivity == null)
                    {
                        FATAL("Unable to get inbound connectivity");
                        return false;
                    }
                    if (!pConnectivity.Initialize())
                    {
                        FATAL("Unable to initialize inbound connectivity");
                        return false;
                    }

                    //4. Send back the response
                    from.PushResponseFirstLine(RTSP_VERSION_1_0, 200, "OK");
                    return from.SendResponseMessage();
                case RTSP_METHOD_PAUSE:
                    from.PushResponseFirstLine(RTSP_VERSION_1_0, 200, "OK");
                    return from.SendResponseMessage();
                default:
                    return false;
            }
        }