public void EnqueueForDelete() { Cleanup(); _rtsp.EnqueueForDelete(); }
private bool HandleRTSPResponse200Options(RtspProtocol rtspProtocol, Variant requestHeaders, ref string requestContent, Variant responseHeaders, ref string responseContent) { if (rtspProtocol.HasConnectivity) return true; if (rtspProtocol.CustomParameters["connectionType"] == null) { FATAL("Bogus connection"); rtspProtocol.EnqueueForDelete(); return false; } //1. Sanitize if (responseHeaders[RTSP_HEADERS, RTSP_HEADERS_PUBLIC] == null) { FATAL("Invalid response:\n{0}", (responseHeaders.ToString())); return false; } //2. get the raw options string raw = responseHeaders[RTSP_HEADERS, RTSP_HEADERS_PUBLIC]; //3. split and normalize the options var parts = raw.Split(',').Select(x => x.Split(':')).ToDictionary(x => x[0], x => x[1]); string url = requestHeaders[RTSP_FIRST_LINE, RTSP_URL]; switch ((string)rtspProtocol.CustomParameters["connectionType"]) { case "pull": //4. Test the presence of the wanted methods if (!parts.ContainsKey(RTSP_METHOD_DESCRIBE) || !parts.ContainsKey(RTSP_METHOD_SETUP) || !parts.ContainsKey(RTSP_METHOD_PLAY)) { FATAL("Some of the supported methods are missing: {0}", (raw)); return false; } rtspProtocol.PushRequestFirstLine(RTSP_METHOD_DESCRIBE, url, RTSP_VERSION_1_0); rtspProtocol.PushRequestHeader(RTSP_HEADERS_ACCEPT, RTSP_HEADERS_ACCEPT_APPLICATIONSDP); return rtspProtocol.SendRequestMessage(); case "push": //4. Test the presence of the wanted methods if (!parts.ContainsKey(RTSP_METHOD_ANNOUNCE) || !parts.ContainsKey(RTSP_METHOD_SETUP) || !parts.ContainsKey(RTSP_METHOD_RECORD)) { FATAL("Some of the supported methods are missing: {0}", (raw)); return false; } var parameters = rtspProtocol.CustomParameters; rtspProtocol.PushRequestFirstLine(RTSP_METHOD_ANNOUNCE,url,RTSP_VERSION_1_0); var sdp = ComputeSDP(rtspProtocol, parameters["customParameters","localStreamConfig","localStreamName"], parameters["customParameters","localStreamConfig","targetStreamName"], parameters["customParameters","localStreamConfig","targetUri","host"]); if (sdp == "") { FATAL("Unable to compute sdp"); return false; } rtspProtocol.PushRequestHeader(RTSP_HEADERS_CONTENT_TYPE, RTSP_HEADERS_ACCEPT_APPLICATIONSDP); rtspProtocol.PushRequestContent(sdp,false); return rtspProtocol.SendRequestMessage(); default: FATAL("Bogus connection"); rtspProtocol.EnqueueForDelete(); return false; } }
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; } }
private bool HandleRTSPResponse200Announce(RtspProtocol rtspProtocol, Variant requestHeaders, ref string requestContent, Variant responseHeaders, ref string responseContent) { bool forceTcp = rtspProtocol.CustomParameters["forceTcp"]; //3. Get the outbound connectivity var pConnectivity = GetOutboundConnectivity(rtspProtocol,forceTcp); if (pConnectivity == null) { FATAL("Unable to get the outbound connectivity"); return false; } var param = rtspProtocol.CustomParameters; string trackId = ""; bool isAudio = false; if (param["audioTrackId"] != null) { trackId = param["audioTrackId"]; param["audioTrackId"] = null; param["lastSetup"] = "audio"; isAudio = true; pConnectivity.HasAudio = true; } else { if (param["videoTrackId"] != null) { trackId = param["videoTrackId"]; param["videoTrackId"] = null; param["lastSetup"] = "video"; pConnectivity.HasVideo = true; } } if (trackId != "") { var variantUri = param["uri"]; var uri = variantUri["fullUri"] + "/trackID=" + trackId; rtspProtocol.PushRequestFirstLine(RTSP_METHOD_SETUP, uri, RTSP_VERSION_1_0); var transport = forceTcp ? $"RTP/AVP/TCP;unicast;interleaved={(isAudio ? pConnectivity.AudioChannels : pConnectivity.VideoChannels)};mode=record" : $"RTP/AVP;unicast;client_port={(isAudio ? pConnectivity.AudioChannels : pConnectivity.VideoChannels)};mode=record"; rtspProtocol.PushRequestHeader(RTSP_HEADERS_TRANSPORT, transport); return rtspProtocol.SendRequestMessage(); } else { FATAL("Bogus RTSP connection"); rtspProtocol.EnqueueForDelete(); return false; } }