public bool Options(RTSPRequestParser parser) { // TODO : Take care of the Uri format string media = parser.Media; ServerMediaSession session = Server.lookupServerMediaSession(media); if (session == null) { HandleNotFound(parser); return(false); } StringBuilder sb = new StringBuilder(); sb.Append("RTSP/1.0 200 OK\r\n"); sb.AppendFormat("Server: {0}\r\n", RTSPServer.ServerVersion); sb.AppendFormat("Cseq: {0}\r\n", parser.Headers["CSEQ"]); sb.AppendFormat("Public: {0}\r\n", _supportedCommands); sb.Append("\r\n"); SendResponse(sb.ToString()); return(true); }
void HandleCommandNotSupported(RTSPRequestParser parser) { string reply = String.Format("RTSP/1.0 405 Method Not Allowed\r\nCSeq: {0}\r\n{1}\r\nAllow: {2}\r\n\r\n", parser.Headers["CSEQ"], "Tue, 30 Aug 2016 01:33:17 GMT", _supportedCommands); SendResponse(reply); }
public void HandleUnsupportedTransport(RTSPRequestParser parser) { string reply = String.Format("RTSP/1.0 461 Unsupported Transport\r\nCSeq: {0}\r\n{1}\r\n\r\n", parser.Headers["CSEQ"], "Tue, 30 Aug 2016 01:33:17 GMT"); SendResponse(reply); }
public void HandleInvalidState(RTSPRequestParser parser) { string reply = String.Format("RTSP/1.0 455 Method Not Valid in This State\r\nCSeq: {0}\r\n{1}\r\n\r\n", parser.Headers["CSEQ"], "Tue, 30 Aug 2016 01:33:17 GMT"); SendResponse(reply); }
void HandleSessionNotFound(RTSPRequestParser parser) { string reply = String.Format("RTSP/1.0 454 Session Not Found\r\nCSeq: {0}\r\n{1}\r\n\r\n", parser.Headers["CSEQ"], "Tue, 30 Aug 2016 01:33:17 GMT"); SendResponse(reply); }
private void ParseGetParameter(RTSPRequestParser parser) { if (String.IsNullOrEmpty(parser.Body)) { _connection.HandleInvalidParameter(parser); } }
public bool GetParameter(RTSPRequestParser parser) { string media = parser.Media; ServerMediaSession session = _connection.Server.lookupServerMediaSession(media); if (session == null) { _connection.HandleNotFound(parser); return(false); } // Look up information for the specified subsession (track): ServerMediaSubsession subsession = session.LookupSubSession(media); // Not yet implemented //ParseGetParameter(parser); StringBuilder sb = new StringBuilder(); sb.Append("RTSP/1.0 200 OK\r\n"); sb.AppendFormat("Server: {0}\r\n", RTSPServer.ServerVersion); sb.AppendFormat("Cseq: {0}\r\n", parser.Headers["CSEQ"]); sb.AppendFormat("Session: {0}\r\n", SessionId); sb.Append("Last-Modified: Tue, 30 Aug 2016 01:33:17 GMT\r\n"); sb.Append("Date: Sat, 22 Dec 2018 16:18:03 GMT\r\n"); sb.Append("Expires: Sun, 23 Dec 2018 12:01:28 GMT\r\n\r\n"); string reply = sb.ToString(); _connection.SendResponse(reply); return(true); }
public void Teardown(RTSPRequestParser parser) { try { Close(); } catch (Exception ex) { _logger.Error(ex); } }
public async Task <bool> Play(RTSPRequestParser parser) { string stream = parser.Media; ServerMediaSession session = _connection.Server.lookupServerMediaSession(stream); if (session == null) { _connection.HandleNotFound(parser); return(false); } // Look up information for the specified subsession (track): ServerMediaSubsession subsession; subsession = session.LookupSubSession(stream); ushort rtpSeqNum = 0; uint rtpTimestamp = 0; _rtpStream = subsession.GetStreamInstance(); rtpSeqNum = _rtpStream.CurrentSeqNo(); rtpTimestamp = _rtpStream.CurrentTimeStamp(); // presetNextTimestamp(); Playing = true; await _rtpStream.AddDestination(this, _destinations); if (_destinations.isTCP) { _connection.RegisterFilter(_rtpStream); } StringBuilder sb = new StringBuilder(); sb.Append("RTSP/1.0 200 OK\r\n"); sb.AppendFormat("Server: {0}\r\n", RTSPServer.ServerVersion); sb.AppendFormat("Cseq: {0}\r\n", parser.Headers["CSEQ"]); sb.AppendFormat("Session: {0}\r\n", parser.Headers["SESSION"]); sb.Append("Last-Modified: Tue, 30 Aug 2016 01:33:17 GMT\r\n"); sb.Append("Cache-Control: must-revalidate\r\n"); sb.Append("Date: Sat, 22 Dec 2018 16:18:03 GMT\r\n"); sb.Append("Expires: Sun, 23 Dec 2018 12:01:28 GMT\r\n"); sb.Append("Range: npt=0.000-\r\n"). AppendFormat("RTP-Info: url=rtsp://{0}:{1}/{2}/track1;seq={3};rtptime={4}\r\n\r\n", SocketExtensions.GetLocalIPV4Address(), _connection.Server.Port, subsession.Name, rtpSeqNum, rtpTimestamp); string reply = sb.ToString(); _connection.SendResponse(reply); return(true); }
private bool SetParameter(RTSPRequestParser parser) { // Begin by looking up the "ServerMediaSession" object for the specified "urlTotalSuffix": string media = parser.Media; ServerMediaSession session = Server.lookupServerMediaSession(media); if (session == null) { HandleNotFound(parser); return(false); } // Look up information for the specified subsession (track): ServerMediaSubsession subsession; media = media.TrimEnd('/'); // parser.Uri.Segments[2].TrimStart('/'); subsession = session.LookupSubSession(media); string body = parser.Body; if (String.IsNullOrEmpty(body)) { HandleInvalidParameter(parser); } Dictionary <string, string> parameters = new Dictionary <string, string>(); try { StringParser bodyParser = new StringParser(body.ToUpper()); ParseParameters(parser, bodyParser, parameters); Server.NewParameters(parameters); } catch { return(true); } StringBuilder sb = new StringBuilder(); sb.Append("RTSP/1.0 200 OK\r\n"); sb.AppendFormat("Server: {0}\r\n", RTSPServer.ServerVersion); sb.AppendFormat("Cseq: {0}\r\n", parser.Headers["CSEQ"]); sb.Append("\r\n"); SendResponse(sb.ToString()); return(true); }
private bool Describes(RTSPRequestParser parser) { // Begin by looking up the "ServerMediaSession" object for the specified "urlTotalSuffix": string media = parser.Media; ServerMediaSession session = Server.lookupServerMediaSession(media); if (session == null) { HandleNotFound(parser); return(false); } // Look up information for the specified subsession (track): ServerMediaSubsession subsession; media = media.TrimEnd('/'); // parser.Uri.Segments[2].TrimStart('/'); subsession = session.LookupSubSession(media); var sdp = subsession.GenerateSDPDescription(); StringBuilder sb = new StringBuilder(); sb.Append("RTSP/1.0 200 OK\r\n"); sb.AppendFormat("Server: {0}\r\n", RTSPServer.ServerVersion); sb.AppendFormat("Cseq: {0}\r\n", parser.Headers["CSEQ"]); sb.Append("Last-Modified: Tue, 30 Aug 2016 01:33:17 GMT\r\n"); sb.Append("Cache-Control: must-revalidate\r\n"); sb.AppendFormat("Content-length: {0}\r\n", sdp.Length); sb.Append("Date: Sat, 22 Dec 2018 16:18:03 GMT\r\n"); sb.Append("Expires: Sat, 22 Dec 2018 16:18:03 GMT\r\n"); sb.Append("Content-Type: application/sdp\r\n"). Append("x-Accept-Retransmit: our-retransmit\r\n"). Append("x-Accept-Dynamic-Rate: 1\r\n"). AppendFormat("Content-Base: rtsp://{0}:{1}/{2}\r\n\r\n", SocketExtensions.GetLocalIPV4Address(), Server.Port, subsession.Name). Append(sdp); var str = sb.ToString(); SendResponse(str); return(true); }
public void HandleInvalidParameter(RTSPRequestParser parser, params string[] parameters) { StringBuilder sb = new StringBuilder(); sb.Append("RTSP/1.0 451 Invalid Parameter\r\n"); sb.AppendFormat("CSeq: {0}\r\n", parser.Headers["CSEQ"]); StringBuilder body = new StringBuilder(); foreach (var str in parameters) { body.AppendFormat("{0}\r\n", str); } string tmp = body.ToString(); sb.AppendFormat("Content-length: {0}\r\n", tmp.Length); sb.Append("Content-type: text/parameters\r\n\r\n"); sb.AppendFormat("{0}", tmp); SendResponse(sb.ToString()); }
public bool Pause(RTSPRequestParser parser) { if (!Playing) { _connection.HandleInvalidState(parser); return(true); } if (_rtpStream != null) { _rtpStream.RemoveSession(SessionId); Playing = false; } StringBuilder sb = new StringBuilder(); sb.Append("RTSP/1.0 200 OK\r\n"); sb.AppendFormat("Cseq: {0}\r\n", parser.Headers["CSEQ"]); sb.AppendFormat("Session: {0}\r\n", parser.Headers["SESSION"]); sb.Append("Date: Sat, 22 Dec 2018 16:18:03 GMT\r\n\r\n"); _connection.SendResponse(sb.ToString()); return(true); }
public async Task <bool> ProcessIncomingRequest(string message) { bool retVal = false; if (_logger.IsDebugEnabled) { _logger.Debug("C->S:\n{0}", message); } if (_session != null) { _session.LastKeepAlive = DateTime.Now; } RTSPRequestParser parser = new RTSPRequestParser(); try { parser.Parse(message.ToUpper()); // TODO : Error handling } catch (Exception ex) { _logger.Error(ex); HandleBadRequest(); return(false); } if (!_commands.Contains(parser.Method)) { HandleCommandNotSupported(parser); return(false); } if (!String.IsNullOrEmpty(parser.TransportType)) { if (parser.TransportType != "RTP/AVP" && parser.TransportType != "RTP/AVP/TCP") { HandleUnsupportedTransport(parser); return(false); } } // Handle session less verbs first if (parser.Method == "OPTIONS") { retVal = Options(parser); return(retVal); } if (parser.Method == "DESCRIBE") { retVal = Describes(parser); return(retVal); } if (parser.Method == "SET_PARAMETER") { retVal = SetParameter(parser); return(retVal); } if (parser.Headers.ContainsKey("SESSION")) { _session = Server.GetSession(Convert.ToInt32(parser.Headers["SESSION"])); if (_session == null) { HandleSessionNotFound(parser); return(false); } } else { _session = Server.GenerateSession(this); if (_logger.IsDebugEnabled) { _logger.Debug("Generating new session {0}", _session.SessionId); } } _session.LastKeepAlive = DateTime.Now; if (parser.Method == "SETUP") { retVal = _session.Setup(_tcpClient, parser); } else if (parser.Method == "PAUSE") { retVal = _session.Pause(parser); } else if (parser.Method == "GET_PARAMETER") { retVal = _session.GetParameter(parser); } else if (parser.Method == "PLAY") { retVal = await _session.Play(parser); } else if (parser.Method == "TEARDOWN") { _session.Teardown(parser); return(false); } else { HandleBadRequest(); } return(retVal); }
public void HandleNotFound(RTSPRequestParser parser) { string reply = String.Format("RTSP/1.0 404 Stream Not Found\r\nCSeq: {0}\r\n\r\n", parser.Headers["CSEQ"]); SendResponse(reply); }
public bool Setup(TcpClient tcpSocket, RTSPRequestParser parser) { string media = parser.Media; ServerMediaSession session = _connection.Server.lookupServerMediaSession(media); if (session == null) { _connection.HandleNotFound(parser); return(false); } // Look up information for the specified subsession (track): ServerMediaSubsession subsession = session.LookupSubSession(media); Socket socket = null; if (String.Compare(parser.TransportType, "RTP/AVP/TCP") == 0) { socket = tcpSocket.Client; IsRTPOverTCP = true; } if ((subsession.IsMulticast && parser.TransportMode == "UNICAST") || (!subsession.IsMulticast && parser.TransportMode == "MULTICAST")) { _connection.HandleUnsupportedTransport(parser); return(false); } int clientRTPPort = parser.ClientPort1; int clientRTCPPort = parser.ClientPort2; int serverRTPPort; int serverRTCPPort; string multiCastAddress; var clientAddress = tcpSocket.Client.RemoteEndPoint as IPEndPoint; subsession.GetStreamParameters(out serverRTPPort, out serverRTCPPort, out multiCastAddress); SetupDestinations(socket, clientAddress, null, clientRTPPort, clientRTCPPort, (byte)parser.Channel1, (byte)parser.Channel2); StringBuilder sb = new StringBuilder(); sb.Append("RTSP/1.0 200 OK\r\n"); sb.AppendFormat("Server: {0}\r\n", RTSPServer.ServerVersion); sb.AppendFormat("Cseq: {0}\r\n", parser.Headers["CSEQ"]); var localIP = SocketExtensions.GetLocalIPV4Address(); if (parser.TransportMode == "UNICAST") { sb.AppendFormat("Session: {0}\r\n", SessionId); sb.Append("Last-Modified: Tue, 30 Aug 2016 01:33:17 GMT\r\n"); sb.Append("Cache-Control: must-revalidate\r\n"); sb.Append("Date: Sat, 22 Dec 2018 16:18:03 GMT\r\n"); sb.Append("Expires: Sun, 23 Dec 2018 12:01:28 GMT\r\n"); if (socket == null) { // UDP sb.AppendFormat("Transport: RTP/AVP;unicast;destination={0};source={1};client_port={2}-{3};server_port={4}-{5};\r\n\r\n", clientAddress.Address, localIP, parser.ClientPort1, parser.ClientPort2, serverRTPPort, serverRTCPPort); } else { // TCP sb.AppendFormat("Transport: RTP/AVP/TCP;unicast;destination={0};source={1};interleaved={2}-{3}\r\n\r\n", clientAddress.Address, localIP, parser.Channel1, parser.Channel2); } } // Multicast else { sb.Append("Date: Sat, 22 Dec 2018 16:18:03 GMT\r\n"); sb.AppendFormat("Transport: RTP/AVP;multicast;destination={0};source={1};port={2}-{3};ttl=255\r\n", multiCastAddress, localIP, serverRTPPort, serverRTCPPort). AppendFormat("Session: {0};timeout=65\r\n\r\n", SessionId); } var reply = sb.ToString(); _connection.SendResponse(reply); return(true); }
private void ParseParameters(RTSPRequestParser requestParser, StringParser parser, Dictionary <string, string> parameters) { while ((parser.Peek() != '\r') && (parser.Peek() != '\n')) { //First get the parameter identifier bool isOk; string keyword = parser.GetThru(':', out isOk); if (!isOk) { if (!parser.ParserEndOfString()) { throw new Exception(String.Format("Missing semicolumn in body {0}", parser.ToString())); } else { return; } } keyword = keyword.Trim(); //Look up the proper header enumeration based on the header string. //Use the enumeration to look up the dictionary ID of this header, //and set that dictionary attribute to be whatever is in the body of the header var headerVal = parser.ConsumeUntil(StringParser.sEOLMask); headerVal = headerVal.Trim(); if (!RTSPServer._validParameters.Contains(keyword)) { HandleInvalidParameter(requestParser, keyword); } else { parameters.Add(keyword, headerVal); } if ((parser.Peek() == '\r') || (parser.Peek() == '\n')) { isOk = true; parser.ConsumeEOL(); } else { isOk = false; } while ((parser.Peek() == ' ') || (parser.Peek() == '\t')) { parser.ConsumeUntil(StringParser.sEOLMask); if ((parser.Peek() == '\r') || (parser.Peek() == '\n')) { isOk = true; parser.ConsumeEOL(); } else { isOk = false; } } try { switch (keyword) { case "WIDTH": Convert.ToInt32(headerVal); break; case "HEIGHT": Convert.ToInt32(headerVal); break; } } catch { HandleInvalidParameter(requestParser, keyword, headerVal); throw; } if (!isOk) { throw new Exception(String.Format("Error in header {0}", parser.ToString())); } ; } if (!parser.ExpectEOL()) { throw new Exception(String.Format("Invalid request {0}", parser.ToString())); } }