public static RTSPResponse ParseRTSPResponse(RTSPMessage rtspMessage, out RTSPResponseParserError responseParserError) { responseParserError = RTSPResponseParserError.None; try { RTSPResponse rtspResponse = new RTSPResponse(); string statusLine = rtspMessage.FirstLine; int firstSpacePosn = statusLine.IndexOf(" "); rtspResponse.RTSPVersion = statusLine.Substring(0, firstSpacePosn).Trim(); statusLine = statusLine.Substring(firstSpacePosn).Trim(); rtspResponse.StatusCode = Convert.ToInt32(statusLine.Substring(0, 3)); rtspResponse.Status = RTSPResponseStatusCodes.GetStatusTypeForCode(rtspResponse.StatusCode); rtspResponse.ReasonPhrase = statusLine.Substring(3).Trim(); rtspResponse.Header = RTSPHeader.ParseRTSPHeaders(rtspMessage.RTSPHeaders); rtspResponse.Body = rtspMessage.Body; //rtspResponse.Valid = rtspResponse.Validate(out sipResponse.ValidationError); return(rtspResponse); } catch (Exception excp) { logger.Error("Exception parsing RTSP reqsponse. " + excp.Message); throw new ApplicationException("There was an exception parsing an RTSP response. " + excp.Message); } }
public static RTSPMessage ParseRTSPMessage(string message, IPEndPoint receivedFrom, IPEndPoint receivedOn) { try { RTSPMessage rtspMessage = new RTSPMessage(); rtspMessage.ReceivedAt = DateTime.Now; rtspMessage.ReceivedFrom = receivedFrom; rtspMessage.ReceivedOn = receivedOn; rtspMessage.RawMessage = message; int endFistLinePosn = message.IndexOf(m_CRLF); if (endFistLinePosn != -1) { rtspMessage.FirstLine = message.Substring(0, endFistLinePosn); if (rtspMessage.FirstLine.Substring(0, RTSP_RESPONSE_PREFIX.Length) == RTSP_RESPONSE_PREFIX) { rtspMessage.RTSPMessageType = RTSPMessageTypesEnum.Response; } else { rtspMessage.RTSPMessageType = RTSPMessageTypesEnum.Request; } int endHeaderPosn = message.IndexOf(m_CRLF + m_CRLF); if (endHeaderPosn == -1) { // Assume flakey implementation if message does not contain the required CRLFCRLF sequence and treat the message as having no body. string headerString = message.Substring(endFistLinePosn + 2, message.Length - endFistLinePosn - 2); rtspMessage.RTSPHeaders = RTSPHeader.SplitHeaders(headerString); } else if (endHeaderPosn > endFistLinePosn + 2) { string headerString = message.Substring(endFistLinePosn + 2, endHeaderPosn - endFistLinePosn - 2); rtspMessage.RTSPHeaders = RTSPHeader.SplitHeaders(headerString); if (message.Length > endHeaderPosn + 4) { rtspMessage.Body = message.Substring(endHeaderPosn + 4); } } return(rtspMessage); } else { logger.Error( "Error ParseRTSPMessage, there were no end of line characters in the string being parsed."); return(null); } } catch (Exception excp) { logger.Error("Exception ParseRTSPMessage. " + excp.Message + "\nRTSP Message=" + message + "."); return(null); } }
/// <summary> /// Send a PLAY request to the RTSP server to commence the media stream. /// </summary> public void Play() { ThreadPool.QueueUserWorkItem(delegate { ProcessRTPPackets(); }); ThreadPool.QueueUserWorkItem(delegate { SendKeepAlives(); }); RTSPRequest playRequest = new RTSPRequest(RTSPMethodsEnum.PLAY, _url); RTSPHeader playHeader = new RTSPHeader(_cseq++, _rtspSession.SessionID); playRequest.Header = playHeader; System.Diagnostics.Debug.WriteLine(playRequest.ToString()); var rtspRequestBuffer = Encoding.UTF8.GetBytes(playRequest.ToString()); _rtspStream.Write(rtspRequestBuffer, 0, rtspRequestBuffer.Length); var buffer = new byte[2048]; var bytesRead = _rtspStream.Read(buffer, 0, 2048); if (bytesRead > 0) { System.Diagnostics.Debug.WriteLine(Encoding.UTF8.GetString(buffer, 0, bytesRead)); var rtspMessage = RTSPMessage.ParseRTSPMessage(buffer, null, null); if (rtspMessage.RTSPMessageType == RTSPMessageTypesEnum.Response) { var playResponse = RTSPResponse.ParseRTSPResponse(rtspMessage); logger.Debug("RTSP Response received to PLAY: " + playResponse.StatusCode + " " + playResponse.Status + " " + playResponse.ReasonPhrase + "."); } } else { throw new ApplicationException("Zero bytes were read from the RTSP client socket in response to a PLAY request."); } }
public string GetStreamDescription(string url) { try { string hostname = Regex.Match(url, @"rtsp://(?<hostname>\S+?)/").Result("${hostname}"); //IPEndPoint rtspEndPoint = DNSResolver.R(hostname, DNS_RESOLUTION_TIMEOUT); Logger.Logger.Debug("RTSP Client Connecting to " + hostname + "."); TcpClient rtspSocket = new TcpClient(hostname, RTSP_PORT); NetworkStream rtspStream = rtspSocket.GetStream(); string rtspSDP = null; RTSPRequest rtspRequest = new RTSPRequest(RTSPMethodsEnum.DESCRIBE, url); RTSPHeader rtspHeader = new RTSPHeader(1, null); rtspRequest.Header = rtspHeader; string rtspReqStr = rtspRequest.ToString(); RTSPMessage rtspMessage = null; RTSPResponse rtspResponse = null; byte[] rtspRequestBuffer = Encoding.UTF8.GetBytes(rtspReqStr); rtspStream.Write(rtspRequestBuffer, 0, rtspRequestBuffer.Length); byte[] buffer = new byte[2048]; int bytesRead = rtspStream.Read(buffer, 0, 2048); if (bytesRead > 0) { Logger.Logger.Debug(Encoding.UTF8.GetString(buffer, 0, bytesRead)); byte[] msgBuffer = new byte[bytesRead]; Buffer.BlockCopy(buffer, 0, msgBuffer, 0, bytesRead); rtspMessage = RTSPMessage.ParseRTSPMessage(msgBuffer, null, null); if (rtspMessage.RTSPMessageType == RTSPMessageTypesEnum.Response) { rtspResponse = RTSPResponse.ParseRTSPResponse(rtspMessage); Logger.Logger.Debug("RTSP Response received: " + rtspResponse.StatusCode + " " + rtspResponse.Status + " " + rtspResponse.ReasonPhrase + "."); } rtspSDP = rtspResponse.Body; } else { Logger.Logger.Warn("Socket closed prematurely in GetStreamDescription for " + url + "."); } rtspSocket.Close(); return(rtspSDP); } catch (Exception excp) { Logger.Logger.Error("Exception GetStreamDescription. ->" + excp.Message); throw excp; } }
/// <summary> /// Sends a keep-alive packet to keep the RTSP RTP connection from being shut. /// </summary> private void SendKeepAlives() { try { Thread.CurrentThread.Name = "rtspclient-keepalive"; // Set the initial pause as half the keep-alive interval. Thread.Sleep(RTP_KEEP_ALIVE_INTERVAL * 500); while (!_isClosed) { _rtspSession.SendRTPRaw(new byte[] { 0x00, 0x00, 0x00, 0x00 }); // Also send an OPTIONS request on the RTSP connection to prevent the remote server from timing it out. RTSPRequest optionsRequest = new RTSPRequest(RTSPMethodsEnum.OPTIONS, _url); RTSPHeader optionsHeader = new RTSPHeader(_cseq++, _rtspSession.SessionID); optionsRequest.Header = optionsHeader; Debug.WriteLine(optionsRequest.ToString()); var rtspRequestBuffer = Encoding.UTF8.GetBytes(optionsRequest.ToString()); _rtspStream.Write(rtspRequestBuffer, 0, rtspRequestBuffer.Length); var buffer = new byte[2048]; var bytesRead = _rtspStream.Read(buffer, 0, 2048); if (bytesRead > 0) { Debug.WriteLine(Encoding.UTF8.GetString(buffer, 0, bytesRead)); var rtspMessage = RTSPMessage.ParseRTSPMessage(buffer, null, null); if (rtspMessage.RTSPMessageType == RTSPMessageTypesEnum.Response) { var optionsResponse = RTSPResponse.ParseRTSPResponse(rtspMessage); //logger.Debug("RTSP Response received for OPTIONS keep-alive request: " + optionsResponse.StatusCode + " " + optionsResponse.Status + " " + optionsResponse.ReasonPhrase + "."); } } else { logger.Warn( "Zero bytes were read from the RTSP client socket in response to an OPTIONS keep-alive request."); } _sendKeepAlivesMRE.Reset(); _sendKeepAlivesMRE.WaitOne(RTP_KEEP_ALIVE_INTERVAL * 1000); } } catch (Exception excp) { logger.Error("Exception RTSPClient.SendKeepAlives. " + excp); } }
public static RTSPRequest ParseRTSPRequest(RTSPMessage rtspMessage, out RTSPRequestParserError requestParserError) { requestParserError = RTSPRequestParserError.None; string urlStr = null; try { var rtspRequest = new RTSPRequest(); string statusLine = rtspMessage.FirstLine; int firstSpacePosn = statusLine.IndexOf(" ", StringComparison.OrdinalIgnoreCase); string method = statusLine.Substring(0, firstSpacePosn).Trim(); rtspRequest.Method = RTSPMethods.GetMethod(method); if (rtspRequest.Method == RTSPMethodsEnum.UNKNOWN) { rtspRequest.UnknownMethod = method; Logger.Logger.Warn("Unknown RTSP method received " + rtspRequest.Method + "."); } statusLine = statusLine.Substring(firstSpacePosn).Trim(); int secondSpacePosn = statusLine.IndexOf(" "); if (secondSpacePosn != -1) { urlStr = statusLine.Substring(0, secondSpacePosn); rtspRequest.URL = RTSPURL.ParseRTSPURL(urlStr); rtspRequest.RTSPVersion = statusLine.Substring(secondSpacePosn, statusLine.Length - secondSpacePosn) .Trim(); rtspRequest.Header = (rtspMessage.RTSPHeaders != null) ? RTSPHeader.ParseRTSPHeaders(rtspMessage.RTSPHeaders) : new RTSPHeader(0, null); rtspRequest.Body = rtspMessage.Body; return(rtspRequest); } else { throw new ApplicationException("URI was missing on RTSP request."); } } catch (Exception excp) { Logger.Logger.Error("Exception parsing RTSP request. URI, " + urlStr + "."); throw new ApplicationException("There was an exception parsing an RTSP request. " + excp.Message); } }
public static RTSPMessage ParseRTSPMessage(byte[] buffer, IPEndPoint receivedFrom, IPEndPoint receivedOn) { string message = null; try { if (buffer == null || buffer.Length < m_minFirstLineLength) { // Ignore. return(null); } else if (buffer.Length > RTSPConstants.RTSP_MAXIMUM_LENGTH) { Logger.Logger.Error( "RTSP message received that exceeded the maximum allowed message length, ignoring."); return(null); } else if (!ByteBufferInfo.HasString(buffer, 0, buffer.Length, RTSP_MESSAGE_IDENTIFIER, m_CRLF)) { // Message does not contain "RTSP" anywhrere on the first line, ignore. return(null); } else { message = Encoding.UTF8.GetString(buffer); RTSPMessage rtspMessage = ParseRTSPMessage(message, receivedFrom, receivedOn); rtspMessage.RawBuffer = buffer; return(rtspMessage); } } catch (Exception excp) { message = message.Replace("\n", "LF"); message = message.Replace("\r", "CR"); Logger.Logger.Error("Exception ParseRTSPMessage. ->" + excp.Message + "->RTSP Message=" + message + "."); return(null); } }
public static RTSPRequest ParseRTSPRequest(RTSPMessage rtspMessage) { RTSPRequestParserError dontCare = RTSPRequestParserError.None; return(ParseRTSPRequest(rtspMessage, out dontCare)); }
public void Start(string url) { _url = url; Match urlMatch = Regex.Match(url, @"rtsp://(?<hostname>\S+?)/", RegexOptions.IgnoreCase); if (!urlMatch.Success) { throw new ApplicationException("The URL provided to the RTSP client was not recognised, " + url + "."); } else { string hostname = urlMatch.Result("${hostname}"); int port = RTSP_PORT; if (hostname.Contains(':')) { port = IPSocket.ParsePortFromSocket(hostname); hostname = IPSocket.ParseHostFromSocket(hostname); } logger.Debug("RTSP client connecting to " + hostname + ", port " + port + "."); _rtspConnection = new TcpClient(hostname, port); _rtspStream = _rtspConnection.GetStream(); _rtspSession = new RTSPSession(); _rtspSession.RTPPayloadHeaderLength = _rtpPayloadHeaderLength; _rtspSession.ReservePorts(); _rtspSession.OnRTPQueueFull += RTPQueueFull; RTSPRequest rtspRequest = new RTSPRequest(RTSPMethodsEnum.SETUP, url); RTSPHeader rtspHeader = new RTSPHeader(_cseq++, null); rtspHeader.Transport = new RTSPTransportHeader() { ClientRTPPortRange = _rtspSession.RTPPort + "-" + _rtspSession.ControlPort }; rtspRequest.Header = rtspHeader; string rtspReqStr = rtspRequest.ToString(); RTSPMessage rtspMessage = null; Debug.WriteLine(rtspReqStr); byte[] rtspRequestBuffer = Encoding.UTF8.GetBytes(rtspReqStr); _rtspStream.Write(rtspRequestBuffer, 0, rtspRequestBuffer.Length); byte[] buffer = new byte[2048]; int bytesRead = _rtspStream.Read(buffer, 0, 2048); if (bytesRead > 0) { Debug.WriteLine(Encoding.UTF8.GetString(buffer, 0, bytesRead)); rtspMessage = RTSPMessage.ParseRTSPMessage(buffer, null, null); if (rtspMessage.RTSPMessageType == RTSPMessageTypesEnum.Response) { var setupResponse = RTSPResponse.ParseRTSPResponse(rtspMessage); if (setupResponse.Status == RTSPResponseStatusCodesEnum.OK) { _rtspSession.SessionID = setupResponse.Header.Session; _rtspSession.RemoteEndPoint = new IPEndPoint( (_rtspConnection.Client.RemoteEndPoint as IPEndPoint).Address, setupResponse.Header.Transport.GetServerRTPPort()); _rtspSession.Start(); logger.Debug("RTSP Response received to SETUP: " + setupResponse.Status + ", session ID " + _rtspSession.SessionID + ", server RTP endpoint " + _rtspSession.RemoteEndPoint + "."); if (OnSetupSuccess != null) { OnSetupSuccess(this); } } else { logger.Warn("RTSP Response received to SETUP: " + setupResponse.Status + "."); throw new ApplicationException("An error response of " + setupResponse.Status + " was received for an RTSP setup request."); } } } else { throw new ApplicationException( "Zero bytes were read from the RTSP client socket in response to a SETUP request."); } } }
public static RTSPResponse ParseRTSPResponse(RTSPMessage rtspMessage) { RTSPResponseParserError dontCare = RTSPResponseParserError.None; return(ParseRTSPResponse(rtspMessage, out dontCare)); }