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; } }
private bool HandleRTSPResponse200Setup(RtspProtocol rtspProtocol, Variant requestHeaders, ref string requestContent, Variant responseHeaders, ref string responseContent) { if (rtspProtocol.CustomParameters["connectionType"] == "pull") { if (responseHeaders[RTSP_FIRST_LINE, RTSP_STATUS_CODE] != 200) { FATAL("request {0} failed with response {1}", (requestHeaders.ToString()), (responseHeaders.ToString())); return false; } if (rtspProtocol.CustomParameters["pendingTracks"].ArrayLength != 0) return SendSetupTrackMessages(rtspProtocol); //2. Do the play command var uri = rtspProtocol.CustomParameters["uri", "fullUri"]; //3. prepare the play command rtspProtocol.PushRequestFirstLine(RTSP_METHOD_PLAY, uri, RTSP_VERSION_1_0); return rtspProtocol.SendRequestMessage(); } else { if (responseHeaders[RTSP_HEADERS, RTSP_HEADERS_TRANSPORT] == null) { FATAL("RTSP {0} request doesn't have {1} header line", RTSP_METHOD_SETUP, RTSP_HEADERS_TRANSPORT); return false; } //3. get the transport header line var raw = responseHeaders[RTSP_HEADERS, RTSP_HEADERS_TRANSPORT]; var transport = Variant.Get(); if (!SDP.ParseTransportLine(raw, transport)) { FATAL("Unable to parse transport line {0}", (raw)); return false; } bool forceTcp; if (transport["server_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; } if (forceTcp != (bool)rtspProtocol.CustomParameters["forceTcp"]) { FATAL("Invalid transport line: {0}", (transport.ToString())); return false; } var pConnectivity = GetOutboundConnectivity(rtspProtocol, forceTcp); if (pConnectivity == null) { FATAL("Unable to get outbound connectivity"); return false; } var param = rtspProtocol.CustomParameters; param[param["lastSetup"] == "audio" ? "audioTransport" : "videoTransport"] = transport; var variantUri = param["uri"]; 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 uri = variantUri["fullUri"] + "/trackID=" + trackId; rtspProtocol.PushRequestFirstLine(RTSP_METHOD_SETUP, uri, RTSP_VERSION_1_0); 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 { rtspProtocol.PushRequestFirstLine(RTSP_METHOD_RECORD,variantUri["fullUri"],RTSP_VERSION_1_0); return rtspProtocol.SendRequestMessage(); } } }
private bool SendSetupTrackMessages(RtspProtocol rtspProtocol) { //1. Get the pending tracks if (rtspProtocol.CustomParameters["pendingTracks"].ArrayLength == 0) { WARN("No more tracks"); return true; } //2. Get the inbound connectivity if (rtspProtocol.InboundConnectivity == null) { FATAL("Unable to get inbound connectivity"); return false; } //3. Get the first pending track var track = rtspProtocol.CustomParameters["pendingTracks"][0]; if (!track.IsMap) { FATAL("Invalid track"); return false; } //4. Add the track to the inbound connectivity if (!rtspProtocol.InboundConnectivity.AddTrack(track,track["isAudio"])) { FATAL("Unable to add the track to inbound connectivity"); return false; } //6. Prepare the SETUP request rtspProtocol.PushRequestFirstLine(RTSP_METHOD_SETUP, track["controlUri"], RTSP_VERSION_1_0); rtspProtocol.PushRequestHeader(RTSP_HEADERS_TRANSPORT, rtspProtocol.InboundConnectivity.GetTransportHeaderLine(track["isAudio"], true)); //7. Remove the track from pending rtspProtocol.CustomParameters["pendingTracks"].RemoveAt(0); //8. Send the request message return rtspProtocol.SendRequestMessage(); }
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; } }