public override RtspResponse TearDown(RtspRequest request) { return RtspResponse.CreateBuilder() .Status(RtspResponse.Status.Ok) .AddHeader(CALLED_METHOD_HEADER, "TEARDOWN") .Build(); ; }
/// <summary> /// Handles the request play. /// Do not forward message if already playing /// </summary> /// <param name="destination">The destination.</param> /// <param name="requestPlay">The request play.</param> /// <returns>The message to transmit</returns> private RtspMessage HandleRequestPlay(ref RtspListener destination, RtspRequestPlay requestPlay) { Contract.Requires(requestPlay != null); Contract.Requires(destination != null); Contract.Ensures(Contract.Result <RtspMessage>() != null); Contract.Ensures(Contract.ValueAtReturn(out destination) != null); string sessionKey = RtspSession.GetSessionName(requestPlay.RtspUri, requestPlay.Session); if (_activesSession.ContainsKey(sessionKey)) { RtspSession session = _activesSession[sessionKey]; // si on est dèjà en play on n'envoie pas la commande a la source. if (session.State == RtspSession.SessionState.Playing) { session.Start(requestPlay.SourcePort.RemoteAdress); RtspResponse returnValue = requestPlay.CreateResponse(); destination = requestPlay.SourcePort; return(returnValue); } // ajoute un client session.Start(requestPlay.SourcePort.RemoteAdress); } return(requestPlay); }
/// <summary> /// <see cref="IRequestHandler.Describe(RtspRequest)"/> /// </summary> /// <param name="request"></param> /// <returns></returns> public override RtspResponse Describe(RtspRequest request) { return(RtspResponse.CreateBuilder() .Status(RtspResponse.Status.Ok) .Body(CreateSDP(request)) .Build()); }
public static ValidationStatus ValidateDigest(this RtspResponse response) { var messages = response.Conversation.GetMessages(ContentType.Rtsp); var details = messages.First(item => item.Response == response).Request.GetDetails(); var pairs = messages.Where(item => item.Request.GetDetails() == details); var responseAuth = Authentication.FromAuthHeader(response.AuthHeader); if (pairs.Any(item => { String authHeader = item.GetRequest <RtspMessage>().AuthHeader; if (String.IsNullOrEmpty(authHeader)) { return(false); } var requestAuth = Authentication.FromAuthHeader(authHeader); return(requestAuth.Nonce == responseAuth.Nonce && requestAuth.Realm == responseAuth.Realm && "200" == item.GetResponse <RtspResponse>().StatusCode); })) { return(ValidationStatus.RtspDigest); } return(ValidationStatus.Failed); }
public override RtspResponse SetUp(RtspRequest request) { var builder = RtspResponse.CreateBuilder().Status(RtspResponse.Status.Ok); var transport = request.Transport; if (transport == null) { return(builder.Status(RtspResponse.Status.BadRequest).Build()); } else if (transport.Type != TransportType.RtspInterleaved) { return(builder.Status(RtspResponse.Status.UnsupportedTransport).Build()); } lock (this) { PortPair channels = new PortPair(_currentChannel, _currentChannel + 1); _currentChannel += 2; var session = new InterleavedTestSession(request.Context, _spy, channels, PAYLOAD_TYPE); _sessionManager.RegisterSession(session); transport = TransportHeader.CreateBuilder() .Type(TransportType.RtspInterleaved) .InterleavedChannels(channels) .Build(); return(builder.AddHeader(RtspHeaders.Names.TRANSPORT, transport.ToString()) .AddHeader(RtspHeaders.Names.SESSION, session.Id) .Build()); } }
/// <summary> /// Handles one message. /// </summary> /// <param name="message">The message.</param> private void HandleOneMessage(RtspMessage message) { Contract.Requires(message != null); RtspListener destination = null; if (message is RtspRequest) { destination = HandleRequest(ref message); _logger.Debug("Dispatch message from {0} to {1}", message.SourcePort != null ? message.SourcePort.RemoteAdress : "UNKNOWN", destination != null ? destination.RemoteAdress : "UNKNOWN"); // HandleRequest can change message type. if (message is RtspRequest) { var context = new OriginContext(); context.OriginCSeq = message.CSeq; context.OriginSourcePort = message.SourcePort; (message as RtspRequest).ContextData = context; } } else if (message is RtspResponse) { RtspResponse response = message as RtspResponse; if (response.OriginalRequest != null) { var context = response.OriginalRequest.ContextData as OriginContext; if (context != null) { destination = context.OriginSourcePort; response.CSeq = context.OriginCSeq; _logger.Debug("Dispatch response back to {0}", destination.RemoteAdress); } } HandleResponse(response); } if (destination != null) { bool isGood = destination.SendMessage(message); if (!isGood) { destination.Stop(); _serverListener.Remove(destination.RemoteAdress); // send back a message because we can't forward. if (message is RtspRequest && message.SourcePort != null) { RtspRequest request = message as RtspRequest; RtspResponse theDirectResponse = request.CreateResponse(); _logger.Warn("Error during forward : {0}. So sending back a direct error response", message.Command); theDirectResponse.ReturnCode = 500; request.SourcePort.SendMessage(theDirectResponse); } } } }
private static RtspListener HandleRequestWithoutUrl(ref RtspMessage message) { Contract.Requires(message != null); Contract.Requires(message is RtspRequest); Contract.Ensures(Contract.Result <RtspListener>() != null); Contract.Ensures(Contract.ValueAtReturn(out message) != null); RtspListener destination; destination = message.SourcePort; RtspRequest request = message as RtspRequest; RtspResponse theDirectResponse = request.CreateResponse(); if (request.RequestTyped == RtspRequest.RequestType.OPTIONS) { // We know what to do... theDirectResponse.ReturnCode = 200; // But perhaps it is to prevent timeout !! // ARG ..... _logger.Info("I got an OPTION * message, I reply but I do not forward! The end session may timeout."); request.LogMessage(); } else { _logger.Warn("Do not know how to handle : {0}", message.Command); theDirectResponse.ReturnCode = 400; } message = theDirectResponse; return(destination); }
/// <summary> /// Handles the response to a setup message. /// </summary> /// <param name="message">A response message.</param> private void HandleResponseToSetup(RtspResponse message) { RtspRequest original = message.OriginalRequest; string setupKey = original.SourcePort.RemoteAdress + "SEQ" + message.CSeq.ToString(CultureInfo.InvariantCulture); if (message.IsOk) { Forwarder forwarder = ConfigureTransportAndForwarder(message, _setupForwarder[setupKey]); RtspSession newSession; string sessionKey = RtspSession.GetSessionName(original.RtspUri, message.Session); if (_activesSession.ContainsKey(sessionKey)) { newSession = _activesSession[sessionKey]; _logger.Info("There was an already a session with ths ID {0}", newSession.Name); } else { _logger.Info("Create a new session with the ID {0}", sessionKey); newSession = new RtspSession(); newSession.Name = message.Session; newSession.Destination = original.RtspUri.Authority; _activesSession.Add(sessionKey, newSession); } newSession.AddForwarder(original.RtspUri, forwarder); newSession.Timeout = message.Timeout; } // No needed here anymore. _setupForwarder.Remove(setupKey); }
public static RtspResponse CreateResponse(this RtspRequestOptions t, string options) { RtspResponse response = t.CreateResponse(); response.Headers[RtspHeaderNames.Public] = options; return(response); }
public override RtspResponse SetUp(RtspRequest request) { return RtspResponse.CreateBuilder() .Status(RtspResponse.Status.Ok) .AddHeader(CALLED_METHOD_HEADER, "SETUP") .Build(); }
private void ProcessSetupRequest(RtspResponse message) { // If we get a reply to SETUP (which was our third command), then process then send PLAY // Got Reply to SETUP Logger.Info("Got reply from Setup. Session is " + message.Session); session = message.Session; // Session value used with Play, Pause, Teardown // Check the Transport header if (message.Headers.ContainsKey(RtspHeaderNames.Transport)) { RtspTransport transport = RtspTransport.Parse(message.Headers[RtspHeaderNames.Transport]); // Check if Transport header includes Multicast if (transport.IsMulticast) { String multicastAddress = transport.Destination; videoDataChannel = transport.Port.First; videoRTCPChannel = transport.Port.Second; // Create the Pair of UDP Sockets in Multicast mode udpPair = new UDPSocketPair(multicastAddress, videoDataChannel, multicastAddress, videoRTCPChannel); udpPair.DataReceived += RtpDataReceived; udpPair.Start(); } } RtspRequest play_message = new RtspRequestPlay { RtspUri = new Uri(url), Session = session }; rtspListener.SendMessage(play_message); }
// RTSP Messages are OPTIONS, DESCRIBE, SETUP, PLAY etc private void RtspMessageReceived(object sender, Rtsp.RtspChunkEventArgs e) { RtspResponse message = e.Message as RtspResponse; if (message.OriginalRequest == null) { return; } Logger.Info("Received " + message.OriginalRequest.ToString()); if (message.OriginalRequest is RtspRequestOptions) { ProcessOptionsRequest(message); } else if (message.OriginalRequest is RtspRequestDescribe) { ProcessDescribeRequest(message); } else if (message.OriginalRequest is RtspRequestSetup) { ProcessSetupRequest(message); } else if (message.OriginalRequest is RtspRequestPlay) { ProcessPlayRequest(message); } }
public RtspResponse Options(RtspRequest request) { return(RtspResponse.CreateBuilder() .Status(RtspResponse.Status.Ok) .AddHeader(RtspHeaders.Names.PUBLIC, "OPTIONS, DESCRIBE, GET_PARAMETER, SETUP, PLAY, TEARDOWN") .Build()); }
public AsyncResponse(int cseq) { _cseq = cseq; _response = null; _callback = null; _event = new ManualResetEvent(false); }
public void SetSession() { RtspResponse testObject = new RtspResponse(); testObject.Session = "12345"; Assert.AreEqual("12345", testObject.Headers[RtspHeaderNames.Session]); }
public override RtspResponse GetParamater(RtspRequest request) { return RtspResponse.CreateBuilder() .Status(RtspResponse.Status.Ok) .AddHeader(RtspHeaders.Names.SESSION, request.Session) .AddHeader(CALLED_METHOD_HEADER, "GET_PARAMATER") .Build(); }
public override RtspResponse SetUp(RtspRequest request) { var builder = RtspResponse.CreateBuilder(); var queryParams = HttpUtility.ParseQueryString(request.URI.Query); var sourceId = queryParams["sourceId"]; if (sourceId == null || !_sourceMgr.ContainsSource(sourceId)) { return(builder.Status(RtspResponse.Status.NotFound).Build()); } var transport = request.Transport; if (transport == null) { return(builder.Status(RtspResponse.Status.BadRequest).Build()); } if (transport.Type != Pelco.Media.RTSP.TransportType.UdpUnicast) { return(builder.Status(RtspResponse.Status.UnsupportedTransport).Build()); } if (transport.ClientPorts == null || !transport.ClientPorts.IsSet) { return(builder.Status(RtspResponse.Status.BadRequest).Build()); } var rtpPort = transport.ClientPorts.RtpPort; var address = transport.Destination != null?Dns.GetHostAddresses(transport.Destination)[0] : request.RemoteEndpoint.Address; var rtspSession = new RtspSession(_sourceMgr.GetSource(sourceId).GetPipelineSource(), PAYLOAD_TYPE, new IPEndPoint(address, rtpPort)); if (!_sessionMgr.RegisterSession(rtspSession)) { return(builder.Status(RtspResponse.Status.InternalServerError) .AddHeader(RtspHeaders.Names.CONTENT_TYPE, "text/plain") .Body("Unable to register Rtsp session with system") .Build()); } var session = Session.FromParts(rtspSession.Id, RtspSession.RTSP_SESSION_TIMEOUT); transport = TransportHeader.CreateBuilder() .Type(Pelco.Media.RTSP.TransportType.UdpUnicast) .ClientPorts(transport.ClientPorts) .ServerPorts(rtpPort + 3, rtpPort + 4) // Just create dummy ports. .Build(); return(builder.Status(RtspResponse.Status.Ok) .AddHeader(RtspHeaders.Names.TRANSPORT, transport.ToString()) .AddHeader(RtspHeaders.Names.SESSION, session.ToString()) .Build()); }
/// <summary> /// Gets the assiociate OK response with the request. /// </summary> /// <returns> /// an Rtsp response corresponding to request. /// </returns> public override RtspResponse CreateResponse() { RtspResponse response = base.CreateResponse(); // Add genric suported operations. response.Headers.Add(RtspHeaderNames.Public, "OPTIONS,DESCRIBE,ANNOUNCE,SETUP,PLAY,PAUSE,TEARDOWN,GET_PARAMETER,SET_PARAMETER,REDIRECT"); return(response); }
public void ReadSessionAndTimeout() { RtspResponse testObject = new RtspResponse(); testObject.Headers[RtspHeaderNames.Session] = "12345;timeout=33"; Assert.AreEqual("12345", testObject.Session); Assert.AreEqual(33, testObject.Timeout); }
public void SetSessionAndTimeout() { RtspResponse testObject = new RtspResponse(); testObject.Session = "12345"; testObject.Timeout = 10; Assert.AreEqual("12345;timeout=10", testObject.Headers[RtspHeaderNames.Session]); }
private RtspResponse CheckResponse(RtspResponse response, RtspRequest.RtspMethod method) { var status = response.ResponseStatus; if (status.Code >= RtspResponse.Status.BadRequest.Code) { throw new RtspClientException($"{method} received response status {status.Code} {status.ReasonPhrase}"); } return(response); }
public void GetRtspMessageResponse(string requestLine, int returnCode, string returnMessage) { RtspMessage oneMessage = RtspMessage.GetRtspMessage(requestLine); Assert.IsInstanceOfType(typeof(RtspResponse), oneMessage); RtspResponse oneResponse = oneMessage as RtspResponse; Assert.AreEqual(returnCode, oneResponse.ReturnCode); Assert.AreEqual(returnMessage, oneResponse.ReturnMessage); }
public void ChangeSession() { RtspResponse testObject = new RtspResponse(); testObject.Headers[RtspHeaderNames.Session] = "12345;timeout=33"; testObject.Session = "456"; Assert.AreEqual("456", testObject.Session); Assert.AreEqual(33, testObject.Timeout); Assert.AreEqual("456;timeout=33", testObject.Headers[RtspHeaderNames.Session]); }
public void HandleResponse(RtspResponse response) { if (_callback != null) { _callback.Invoke(response); } else { _response = response; _event.Set(); } }
private void ProcessDescribeResponse(RtspResponse message) { // Got a reply for DESCRIBE // Examine the SDP Logger.Info(System.Text.Encoding.UTF8.GetString(message.Data)); Rtsp.Sdp.SdpFile sdpData; using (StreamReader sdpStream = new StreamReader(new MemoryStream(message.Data))) { sdpData = Rtsp.Sdp.SdpFile.Read(sdpStream); } // Process each 'Media' Attribute in the SDP (each sub-stream) // If the attribute is for Video, then carry out a SETUP and a PLAY // Only do this for the first Video attribute in case there is more than one in the SDP for (int x = 0; x < sdpData.Medias.Count; x++) { if (sdpData.Medias[x].MediaType == Media.MediaTypes.video) { // We only want the first video sub-stream if (videoPayloadType != -1) { return; } // search the attributes for control, fmtp and rtpmap ParseAttributes(sdpData, x, out string control, out Rtsp.Sdp.AttributFmtp fmtp, out Rtsp.Sdp.AttributRtpMap rtpmap); // Split the fmtp to get the sprop-parameter-sets which hold the SPS and PPS in base64 if (fmtp != null) { var param = Rtsp.Sdp.H264Parameters.Parse(fmtp.FormatParameter); OutputNal(param.SpropParameterSets); // output SPS and PPS } // Split the rtpmap to get the Payload Type videoPayloadType = 0; if (rtpmap != null) { videoPayloadType = rtpmap.PayloadNumber; } RtspRequestSetup setupMessage = new RtspRequestSetup(); setupMessage.RtspUri = new Uri(rtspUrl + "/" + control); var transport = GetRTSPTransport(); setupMessage.AddTransport(transport); PostRequest(setupMessage); } } }
/// <summary> /// <see cref="IRequestHandler.Play(RtspRequest)"/> /// </summary> /// <param name="request"></param> /// <returns></returns> public override RtspResponse Play(RtspRequest request) { var builder = RtspResponse.CreateBuilder().Status(RtspResponse.Status.Ok); var sessionId = request.Session; if (string.IsNullOrEmpty(sessionId) || !_sessionManager.PlaySession(sessionId)) { return(builder.Status(RtspResponse.Status.SessionNotFound).Build()); } return(builder.Build());; }
private static String GetValidationDetails(RtspRequest request, RtspResponse response) { //rtsp request validation does not exist var sb = new StringBuilder(); if (null != response && response.Validated) { sb.AppendLine(String.Format("Second-level validation:")); sb.AppendLine(String.Format("\tResponse code of unit:{0}", response.GetStatusString())); } return(sb.ToString()); }
private async void HandleRequest(RtspRequest request) { RtspListener listener = null; if (_listeners.TryGetValue(request.RemoteEndpoint.ToString(), out listener)) { await Task.Run(() => { try { int receivedCseq = request.CSeq; request.Context = new RequestContext(listener); var response = _dispatcher.Dispatch(request); if (response != null) { if (response.HasBody) { response.Headers[RtspHeaders.Names.CONTENT_LENGTH] = response.Body.Length.ToString(); } response.Headers[RtspHeaders.Names.CSEQ] = receivedCseq.ToString(); listener.SendResponse(response); // Remove listener on teardown. // VLC will terminate the connection and the listener will stop itself properly. // Some clients will send Teardown but keep the connection open, in this type scenario we'll close it. if (request.Method == RtspRequest.RtspMethod.TEARDOWN) { listener.Stop(); _listeners.Remove(listener.Endpoint.ToString()); } } } catch (Exception e) { LOG.Error(e, $"Caught exception while procesing RTSP request from {request.URI}"); listener.SendResponse(RtspResponse.CreateBuilder() .Status(RtspResponse.Status.InternalServerError) .Build()); } }); } else { LOG.Error($"Unable to process request because no active connection was found for {request.URI}"); } }
private void OnRtspChunk(RtspChunk chunk) { if (chunk is InterleavedData) { var interleaved = chunk as InterleavedData; var buffer = new ByteBuffer(interleaved.Payload, 0, interleaved.Payload.Length, true); buffer.Channel = interleaved.Channel; _rtpQueue.Add(buffer); } else if (chunk is RtspResponse) { var response = chunk as RtspResponse; LOG.Debug($"Received RTSP response from '{_connection.Endpoint}'"); LOG.Debug(response.ToString()); int cseq = response.CSeq; if (cseq <= 0) { LOG.Warn("Receive RTSP response that does not contain cseq header, disgarding."); return; } AsyncResponse cb = null; if (_callbacks.TryRemove(cseq, out cb)) { cb.HandleResponse(response); } } else { var msg = chunk as RtspMessage; LOG.Debug($"Received RTSP request from '{_connection.Endpoint}'"); LOG.Debug(msg.ToString()); // Server sent request. Since we do not support server side requests lets just // respond back with MethodNotAllowed. RtspResponse response = new RtspResponse(RtspResponse.Status.MethodNotAllowed); response.CSeq = msg.CSeq; if (!_connection.WriteMessage(response)) { LOG.Error("Received RTSP request from server but unable to send response."); } } }
public override RtspResponse Play(RtspRequest request) { var builder = RtspResponse.CreateBuilder().Status(RtspResponse.Status.SessionNotFound); if (request.Headers.ContainsKey(RtspHeaders.Names.SESSION)) { var session = request.Headers[RtspHeaders.Names.SESSION]; if (_sessionMgr.PlaySession(session)) { builder.Status(RtspResponse.Status.Ok); } } return(builder.Build()); }