private void RTSP_ProcessAuthorization(RtspRequest message, RtspListener listener) { bool authorized = false; if (message.Headers.ContainsKey("Authorization") == true) { // The Header contained Authorization // Check the message has the correct Authorization // If it does not have the correct Authorization then close the RTSP connection authorized = _auth.IsValid(message); if (authorized == false) { // Send a 401 Authentication Failed reply, then close the RTSP Socket Rtsp.Messages.RtspResponse authorization_response = message.CreateResponse(_logger); authorization_response.AddHeader("WWW-Authenticate: " + _auth.GetHeader()); authorization_response.ReturnCode = 401; listener.SendMessage(authorization_response); CloseConnection("unauthorized"); listener.Dispose(); return; } } if ((message.Headers.ContainsKey("Authorization") == false)) { // Send a 401 Authentication Failed with extra info in WWW-Authenticate // to tell the Client if we are using Basic or Digest Authentication Rtsp.Messages.RtspResponse authorization_response = message.CreateResponse(_logger); authorization_response.AddHeader("WWW-Authenticate: " + _auth.GetHeader()); // 'Basic' or 'Digest' authorization_response.ReturnCode = 401; listener.SendMessage(authorization_response); return; } }
public void Connect() { _client.Start(); // Send first setup messge: OPTIONS RtspRequest optionsMessage = new RtspRequestOptions(); optionsMessage.RtspUri = new Uri(_url); _client.SendMessage(optionsMessage); }
private void RTSP_ProcessPlayRequest(RtspRequestPlay message, RtspListener listener) { OnPlay?.Invoke(Id); Play = true; // ACTUALLY YOU COULD PAUSE JUST THE VIDEO (or JUST THE AUDIO) _logger.Info($"Connection {Id} play started"); string range = "npt=0-"; // Playing the 'video' from 0 seconds until the end string rtp_info = "url=" + message.RtspUri + ";seq=" + _videoSequenceNumber; // TODO Add rtptime +";rtptime="+session.rtp_initial_timestamp; // Send the reply Rtsp.Messages.RtspResponse play_response = message.CreateResponse(_logger); play_response.AddHeader("Range: " + range); play_response.AddHeader("RTP-Info: " + rtp_info); listener.SendMessage(play_response); //TODO: find a p[lace for this check] // Session ID was not found in the list of Sessions. Send a 454 error /* Rtsp.Messages.RtspResponse play_failed_response = (e.Message as Rtsp.Messages.RtspRequestPlay).CreateResponse(); * play_failed_response.ReturnCode = 454; // Session Not Found * listener.SendMessage(play_failed_response);*/ }
/// <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); } } } }
public void SendMessage() { MemoryStream stream = new MemoryStream(); _mockTransport.GetStream().Returns(stream); // Setup test object. RtspListener testedListener = new RtspListener(_mockTransport); testedListener.MessageReceived += new EventHandler <RtspChunkEventArgs>(MessageReceived); testedListener.DataReceived += new EventHandler <RtspChunkEventArgs>(DataReceived); RtspMessage message = new RtspRequestOptions(); // Run var isSuccess = testedListener.SendMessage(message); Assert.That(isSuccess, Is.True); string result = Encoding.UTF8.GetString(stream.GetBuffer()); result = result.TrimEnd('\0'); Assert.That(result, Does.StartWith("OPTIONS * RTSP/1.0\r\n")); // packet without payload must end with double return Assert.That(result, Does.EndWith("\r\n\r\n")); }
private void RTSP_ProcessTeardownRequest(RtspRequestTeardown message, RtspListener listener) { if (message.Session == _videoSessionId) // SHOULD HAVE AN AUDIO TEARDOWN AS WELL { // If this is UDP, close the transport // For TCP there is no transport to close (as RTP packets were interleaved into the RTSP connection) Rtsp.Messages.RtspResponse teardown_response = message.CreateResponse(_logger); listener.SendMessage(teardown_response); CloseConnection("teardown"); } }
private void RTSP_ProcessDescribeRequest(RtspRequestDescribe message, RtspListener listener) { String requested_url = message.RtspUri.ToString(); Task <byte[]> sdpDataTask = _videoSource != null? OnProvideSdpData?.Invoke(Id, _videoSource) : Task.FromResult <byte[]>(null); byte[] sdpData = sdpDataTask.Result; if (sdpData != null) { Rtsp.Messages.RtspResponse describe_response = message.CreateResponse(_logger); describe_response.AddHeader("Content-Base: " + requested_url); describe_response.AddHeader("Content-Type: application/sdp"); describe_response.Data = sdpData; describe_response.AdjustContentLength(); // Create the reponse to DESCRIBE // This must include the Session Description Protocol (SDP) describe_response.Headers.TryGetValue(RtspHeaderNames.ContentBase, out contentBase); using (StreamReader sdp_stream = new StreamReader(new MemoryStream(describe_response.Data))) { _sdpFile = Rtsp.Sdp.SdpFile.Read(sdp_stream); } listener.SendMessage(describe_response); } else { Rtsp.Messages.RtspResponse describe_response = (message as Rtsp.Messages.RtspRequestDescribe).CreateResponse(_logger); //Method Not Valid In This State" describe_response.ReturnCode = 455; listener.SendMessage(describe_response); } }
private void RTSP_ProcessOptionsRequest(RtspRequestOptions message, RtspListener listener) { String requested_url = message.RtspUri.ToString(); _logger.Info($"Connection {listener.ConnectionId} requested for url: {requested_url}"); _videoSource = _requestUrlVideoSourceResolverStrategy.ResolveVideoSource(requested_url); OnConnectionAdded?.Invoke(Id, _videoSource); //treat connection useful when VideoSource determined // Create the reponse to OPTIONS Rtsp.Messages.RtspResponse options_response = message.CreateResponse(_logger); // Rtsp.Messages.RtspResponse options_response = OnRtspMessageReceived?.Invoke(message as Rtsp.Messages.RtspRequest,targetConnection); listener.SendMessage(options_response); }
private void RTSP_ProcessPauseRequest(RtspRequestPause message, RtspListener listener) { if (message.Session == _videoSessionId /* OR AUDIO SESSION ID */) { OnStop?.Invoke(Id); // found the session Play = false; // COULD HAVE PLAY/PAUSE FOR VIDEO AND AUDIO } // ToDo - only send back the OK response if the Session in the RTSP message was found Rtsp.Messages.RtspResponse pause_response = message.CreateResponse(_logger); listener.SendMessage(pause_response); }
private void RTSP_ProcessGetParameterRequest(RtspRequestGetParameter message, RtspListener listener) { // Create the reponse to GET_PARAMETER Rtsp.Messages.RtspResponse getparameter_response = message.CreateResponse(_logger); listener.SendMessage(getparameter_response); }
private void RTSP_ProcessSetupRequest(RtspRequestSetup message, RtspListener listener) { // var setupMessage = message; // Check the RTSP transport // If it is UDP or Multicast, create the sockets // If it is RTP over RTSP we send data via the RTSP Listener // FIXME client may send more than one possible transport. // very rare RtspTransport transport = setupMessage.GetTransports()[0]; // Construct the Transport: reply from the Server to the client Rtsp.UDPSocket udp_pair; RtspTransport transport_reply = RTSP_ConstructReplyTransport(transport, out udp_pair); bool mediaTransportSet = false; if (transport_reply != null) { // Update the session with transport information String copy_of_session_id = ""; // ToDo - Check the Track ID to determine if this is a SETUP for the Video Stream // or a SETUP for an Audio Stream. // In the SDP the H264 video track is TrackID 0 // Add the transports to the connection if (contentBase != null) { string controlTrack = setupMessage.RtspUri.AbsoluteUri.Replace(contentBase, string.Empty); var requestMedia = _sdpFile.Medias.FirstOrDefault(media => media.Attributs.FirstOrDefault(a => a.Key == "control" && (a.Value == controlTrack || "/" + a.Value == controlTrack)) != null); if (requestMedia != null) { if (requestMedia.MediaType == Media.MediaTypes.video) { _videoClientTransport = transport; _videoTransportReply = transport_reply; // If we are sending in UDP mode, add the UDP Socket pair and the Client Hostname if (_videoUdpPair != null) { ReleaseUDPSocket(_videoUdpPair); } _videoUdpPair = udp_pair; mediaTransportSet = true; if (setupMessage.Session == null) { _videoSessionId = _sessionHandle.ToString(); _sessionHandle++; } else { _videoSessionId = setupMessage.Session; } // Copy the Session ID copy_of_session_id = _videoSessionId; } if (requestMedia.MediaType == Media.MediaTypes.audio) { _audioClientTransport = transport; _audioTransportReply = transport_reply; // If we are sending in UDP mode, add the UDP Socket pair and the Client Hostname if (_audioUdpPair != null) { ReleaseUDPSocket(_audioUdpPair); } _audioUdpPair = udp_pair; mediaTransportSet = true; if (setupMessage.Session == null) { _audioSessionId = _sessionHandle.ToString(); _sessionHandle++; } else { _audioSessionId = setupMessage.Session; } // Copy the Session ID copy_of_session_id = _audioSessionId; } } } if (false == mediaTransportSet) { Rtsp.Messages.RtspResponse setup_response = setupMessage.CreateResponse(_logger); // unsuported mediatime setup_response.ReturnCode = 415; listener.SendMessage(setup_response); } else { Rtsp.Messages.RtspResponse setup_response = setupMessage.CreateResponse(_logger); setup_response.Headers[Rtsp.Messages.RtspHeaderNames.Transport] = transport_reply.ToString(); setup_response.Session = copy_of_session_id; setup_response.Timeout = timeout_in_seconds; listener.SendMessage(setup_response); } } else { Rtsp.Messages.RtspResponse setup_response = setupMessage.CreateResponse(_logger); // unsuported transport setup_response.ReturnCode = 461; listener.SendMessage(setup_response); } if (false == mediaTransportSet) { if (udp_pair != null) { ReleaseUDPSocket(udp_pair); udp_pair = null; } } }
public void SendMessage() { MemoryStream stream = new MemoryStream(); _mockTransport.GetStream().Returns(stream); // Setup test object. RtspListener testedListener = new RtspListener(_mockTransport); testedListener.MessageReceived += new EventHandler<RtspChunkEventArgs>(MessageReceived); testedListener.DataReceived += new EventHandler<RtspChunkEventArgs>(DataReceived); RtspMessage message = new RtspRequestOptions(); // Run var isSuccess = testedListener.SendMessage(message); Assert.That(isSuccess, Is.True); string result = Encoding.UTF8.GetString(stream.GetBuffer()); result = result.TrimEnd('\0'); Assert.That(result, Does.StartWith("OPTIONS * RTSP/1.0\r\n")); // packet without payload must end with double return Assert.That(result, Does.EndWith("\r\n\r\n")); }