/// <summary> /// Parses a SIP response from a SIP message object. /// </summary> /// <param name="sipMessageBuffer">The SIP message to parse a response from.</param> /// <returns>A new SIP response object.</returns> public static SIPResponse ParseSIPResponse(SIPMessageBuffer sipMessageBuffer) { try { SIPResponse sipResponse = new SIPResponse(); sipResponse.LocalSIPEndPoint = sipMessageBuffer.LocalSIPEndPoint; sipResponse.RemoteSIPEndPoint = sipMessageBuffer.RemoteSIPEndPoint; string statusLine = sipMessageBuffer.FirstLine; int firstSpacePosn = statusLine.IndexOf(" "); sipResponse.SIPVersion = statusLine.Substring(0, firstSpacePosn).Trim(); statusLine = statusLine.Substring(firstSpacePosn).Trim(); sipResponse.StatusCode = Convert.ToInt32(statusLine.Substring(0, 3)); sipResponse.Status = SIPResponseStatusCodes.GetStatusTypeForCode(sipResponse.StatusCode); sipResponse.ReasonPhrase = statusLine.Substring(3).Trim(); sipResponse.Header = SIPHeader.ParseSIPHeaders(sipMessageBuffer.SIPHeaders); sipResponse.Body = sipMessageBuffer.Body; return(sipResponse); } catch (SIPValidationException) { throw; } catch (Exception excp) { logger.LogError("Exception ParseSIPResponse. " + excp.Message); logger.LogError(sipMessageBuffer.RawMessage); throw new SIPValidationException(SIPValidationFieldsEnum.Response, "Error parsing SIP Response"); } }
/// <summary> /// Attempts to extract SIP messages from the data that has been received on the SIP stream connection. /// </summary> /// <param name="recvChannel">The receiving SIP channel.</param> /// <param name="buffer">The buffer holding the current data from the stream. Note that the buffer can /// stretch over multiple receives.</param> /// <param name="bytesRead">The bytes that were read by the latest receive operation (the new bytes available).</param> public void ExtractSIPMessages(SIPChannel recvChannel, byte[] buffer, int bytesRead) { RecvEndPosn += bytesRead; int bytesSkipped = 0; byte[] sipMsgBuffer = SIPMessageBuffer.ParseSIPMessageFromStream(buffer, RecvStartPosn, RecvEndPosn, out bytesSkipped); while (sipMsgBuffer != null) { // A SIP message is available. if (SIPMessageReceived != null) { LastTransmission = DateTime.Now; SIPEndPoint localEndPoint = new SIPEndPoint(ConnectionProtocol, StreamSocket.LocalEndPoint as IPEndPoint, recvChannel.ID, ConnectionID); SIPEndPoint remoteEndPoint = new SIPEndPoint(ConnectionProtocol, RemoteEndPoint, recvChannel.ID, ConnectionID); SIPMessageReceived(recvChannel, localEndPoint, remoteEndPoint, sipMsgBuffer); } RecvStartPosn += (sipMsgBuffer.Length + bytesSkipped); if (RecvStartPosn == RecvEndPosn) { // All data has been successfully extracted from the receive buffer. RecvStartPosn = RecvEndPosn = 0; break; } else { // Try and extract another SIP message from the receive buffer. sipMsgBuffer = SIPMessageBuffer.ParseSIPMessageFromStream(buffer, RecvStartPosn, RecvEndPosn, out bytesSkipped); } } }
/// <summary> /// Attempts to parse a SIP message from a single buffer that can only contain a single message. /// </summary> /// <param name="buffer">The buffer that will be parsed for a SIP message.</param> /// <param name="localSIPEndPoint">The end point the message was received on.</param> /// <param name="remoteSIPEndPoint">The end point the message was received from.</param> /// <returns>If successful a SIP message or null if not.</returns> public static SIPMessageBuffer ParseSIPMessage(byte[] buffer, SIPEndPoint localSIPEndPoint, SIPEndPoint remoteSIPEndPoint) { string message = null; try { if (buffer == null || buffer.Length < m_minFirstLineLength) { // Ignore. return(null); } else if (buffer.Length > SIPConstants.SIP_MAXIMUM_RECEIVE_LENGTH) { throw new ApplicationException( "SIP message received that exceeded the maximum allowed message length, ignoring."); } else if (!BufferUtils.HasString(buffer, 0, buffer.Length, SIP_MESSAGE_IDENTIFIER, m_CRLF)) { // Message does not contain "SIP" anywhere on the first line, ignore. return(null); } else { message = ByteToStr(buffer, Encoding.UTF8); if (message.ToUpper().Contains("ENCODING=\"GBK\"") || message.ToUpper().Contains("ENCODING=\"GB2312\"")) { message = ByteToStr(buffer, Encoding.GetEncoding("GBK")); //兼容gbk,gb2312编码中文字符串 } SIPMessageBuffer sipMessageBuffer = ParseSIPMessage(message, localSIPEndPoint, remoteSIPEndPoint); if (sipMessageBuffer != null) { sipMessageBuffer.RawBuffer = buffer; return(sipMessageBuffer); } else { return(null); } } } catch (Exception excp) { message = message.Replace("\n", "LF"); message = message.Replace("\r", "CR"); logger.LogError("Exception ParseSIPMessage. " + excp.Message + "\nSIP Message=" + message + "."); return(null); } }
public static SIPRequest ParseSIPRequest(SIPMessageBuffer sipMessage) { try { SIPRequest sipRequest = new SIPRequest(); sipRequest.LocalSIPEndPoint = sipMessage.LocalSIPEndPoint; sipRequest.RemoteSIPEndPoint = sipMessage.RemoteSIPEndPoint; string statusLine = sipMessage.FirstLine; int firstSpacePosn = statusLine.IndexOf(" "); string method = statusLine.Substring(0, firstSpacePosn).Trim(); sipRequest.Method = SIPMethods.GetMethod(method); if (sipRequest.Method == SIPMethodsEnum.UNKNOWN) { sipRequest.UnknownMethod = method; logger.LogWarning("Unknown SIP method received " + sipRequest.UnknownMethod + "."); } statusLine = statusLine.Substring(firstSpacePosn).Trim(); int secondSpacePosn = statusLine.IndexOf(" "); if (secondSpacePosn != -1) { string uriStr = statusLine.Substring(0, secondSpacePosn); sipRequest.URI = SIPURI.ParseSIPURI(uriStr); sipRequest.SIPVersion = statusLine.Substring(secondSpacePosn, statusLine.Length - secondSpacePosn) .Trim(); sipRequest.Header = SIPHeader.ParseSIPHeaders(sipMessage.SIPHeaders); sipRequest.Body = sipMessage.Body; return(sipRequest); } else { throw new SIPValidationException(SIPValidationFieldsEnum.Request, "URI was missing on Request."); } } catch (SIPValidationException) { throw; } catch (Exception excp) { logger.LogError("Exception parsing SIP Request. " + excp.Message); logger.LogError(sipMessage.RawMessage); throw new SIPValidationException(SIPValidationFieldsEnum.Request, "Unknown error parsing SIP Request"); } }
public SIPEndPoint LocalSIPEndPoint; // The local SIP socket the message was received on or sent from. /// <summary> /// Attempts to parse a SIP message from a single buffer that can only contain a single message. /// </summary> /// <param name="buffer">The buffer that will be parsed for a SIP message.</param> /// <param name="localSIPEndPoint">The end point the message was received on.</param> /// <param name="remoteSIPEndPoint">The end point the message was received from.</param> /// <returns>If successful a SIP message or null if not.</returns> public static SIPMessageBuffer ParseSIPMessage(byte[] buffer, SIPEndPoint localSIPEndPoint, SIPEndPoint remoteSIPEndPoint) { string message = null; try { if (buffer == null || buffer.Length < m_minFirstLineLength) { // Ignore. return(null); } else if (buffer.Length > SIPConstants.SIP_MAXIMUM_RECEIVE_LENGTH) { throw new ApplicationException( "SIP message received that exceeded the maximum allowed message length, ignoring."); } else if (!ByteBufferInfo.HasString(buffer, 0, buffer.Length, SIP_MESSAGE_IDENTIFIER, m_CRLF)) { // Message does not contain "SIP" anywhere on the first line, ignore. return(null); } else { message = Encoding.UTF8.GetString(buffer, 0, buffer.Length); SIPMessageBuffer sipMessageBuffer = ParseSIPMessage(message, localSIPEndPoint, remoteSIPEndPoint); if (sipMessageBuffer != null) { sipMessageBuffer.RawBuffer = buffer; return(sipMessageBuffer); } else { return(null); } } } catch (Exception excp) { message = message.Replace("\n", "LF"); message = message.Replace("\r", "CR"); Logger.Logger.Error("Exception ParseSIPMessage. ->" + excp.Message + "->SIP Message=" + message + "."); return(null); } }
public static SIPRequest ParseSIPRequest(string sipMessageStr) { try { SIPMessageBuffer sipMessageBuffer = SIPMessageBuffer.ParseSIPMessage(sipMessageStr, null, null); return(ParseSIPRequest(sipMessageBuffer)); } catch (SIPValidationException) { throw; } catch (Exception excp) { Logger.Logger.Error("Exception ParseSIPRequest. ->" + sipMessageStr + "->" + excp.Message); throw new SIPValidationException(SIPValidationFieldsEnum.Request, "Unknown error parsing SIP Request"); } }
/// <summary> /// Parses a SIP response from a string. /// </summary> /// <param name="sipMessageStr">The string to parse the SIP response from.</param> /// <returns>A new SIP response object.</returns> public static SIPResponse ParseSIPResponse(string sipMessageStr) { try { SIPMessageBuffer sipMessage = SIPMessageBuffer.ParseSIPMessage(sipMessageStr, null, null); return(SIPResponse.ParseSIPResponse(sipMessage)); } catch (SIPValidationException) { throw; } catch (Exception excp) { logger.LogError("Exception ParseSIPResponse. " + excp.Message); logger.LogError(sipMessageStr); throw new SIPValidationException(SIPValidationFieldsEnum.Response, "Error parsing SIP Response"); } }
public static SIPRequest ParseSIPRequest(string sipMessageStr, Encoding sipEncoding, Encoding sipBodyEncoding) { try { SIPMessageBuffer sipMessageBuffer = SIPMessageBuffer.ParseSIPMessage(sipMessageStr, sipEncoding, sipBodyEncoding, null, null); return(ParseSIPRequest(sipMessageBuffer, sipEncoding, sipBodyEncoding)); } catch (SIPValidationException) { throw; } catch (Exception excp) { logger.LogError("Exception ParseSIPRequest. " + excp.Message); logger.LogError(sipMessageStr); throw new SIPValidationException(SIPValidationFieldsEnum.Request, "Unknown error parsing SIP Request"); } }
/// <summary> /// Attempts to extract SIP messages from the data that has been received on the client web socket SIP stream connection. /// </summary> /// <param name="recvChannel">The receiving SIP channel.</param> /// <param name="clientConn">The web socket client connection properties including pending receive buffer</param> /// <param name="buffer">The buffer holding the current data from the stream. Note that the buffer can /// stretch over multiple receives.</param> /// <param name="bytesRead">The bytes that were read by the latest receive operation (the new bytes available).</param> private void ExtractSIPMessages(SIPChannel recvChannel, ClientWebSocketConnection clientConn, ArraySegment <byte> buffer, int bytesRead) { if (bytesRead + clientConn.RecvEndPosn > clientConn.PendingReceiveBuffer.Length) { // Don't have enough space for the read. Throw away the pending buffer and hope the SIP transaction is re-attempted. clientConn.RecvStartPosn = clientConn.RecvEndPosn = 0; } Buffer.BlockCopy(buffer.ToArray(), 0, clientConn.PendingReceiveBuffer, clientConn.RecvEndPosn, bytesRead); clientConn.RecvEndPosn += bytesRead; int bytesSkipped = 0; byte[] sipMsgBuffer = SIPMessageBuffer.ParseSIPMessageFromStream(clientConn.PendingReceiveBuffer, clientConn.RecvStartPosn, clientConn.RecvEndPosn, out bytesSkipped); while (sipMsgBuffer != null) { // A SIP message is available. if (SIPMessageReceived != null) { clientConn.LastTransmission = DateTime.Now; SIPMessageReceived(recvChannel, clientConn.LocalEndPoint, clientConn.RemoteEndPoint, sipMsgBuffer) .Wait(); } clientConn.RecvStartPosn += (sipMsgBuffer.Length + bytesSkipped); if (clientConn.RecvStartPosn == clientConn.RecvEndPosn) { // All data has been successfully extracted from the receive buffer. clientConn.RecvStartPosn = clientConn.RecvEndPosn = 0; break; } else { // Try and extract another SIP message from the receive buffer. sipMsgBuffer = SIPMessageBuffer.ParseSIPMessageFromStream(clientConn.PendingReceiveBuffer, clientConn.RecvStartPosn, clientConn.RecvEndPosn, out bytesSkipped); } } }
/// <summary> /// Attempts to parse a SIP message from a string containing a single SIP request or response. /// </summary> /// <param name="message">The string to parse.</param> /// <param name="localSIPEndPoint">The end point the message was received on.</param> /// <param name="remoteSIPEndPoint">The end point the message was received from.</param> /// <returns>If successful a SIP message or null if not.</returns> public static SIPMessageBuffer ParseSIPMessage(string message, SIPEndPoint localSIPEndPoint, SIPEndPoint remoteSIPEndPoint) { try { SIPMessageBuffer sipMessage = new SIPMessageBuffer(); sipMessage.LocalSIPEndPoint = localSIPEndPoint; sipMessage.RemoteSIPEndPoint = remoteSIPEndPoint; // For connection oriented transports the same connection should be used for responses and subsequent requests. if (sipMessage.LocalSIPEndPoint != null && remoteSIPEndPoint.ConnectionID != null) { sipMessage.LocalSIPEndPoint.ConnectionID = remoteSIPEndPoint.ConnectionID; } sipMessage.RawMessage = message; int endFistLinePosn = message.IndexOf(m_CRLF); if (endFistLinePosn != -1) { sipMessage.FirstLine = message.Substring(0, endFistLinePosn); if (sipMessage.FirstLine.Substring(0, 3) == SIP_RESPONSE_PREFIX) { sipMessage.SIPMessageType = SIPMessageTypesEnum.Response; } else { sipMessage.SIPMessageType = SIPMessageTypesEnum.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); sipMessage.SIPHeaders = SIPHeader.SplitHeaders(headerString); } else { string headerString = message.Substring(endFistLinePosn + 2, endHeaderPosn - endFistLinePosn - 2); sipMessage.SIPHeaders = SIPHeader.SplitHeaders(headerString); if (message.Length > endHeaderPosn + 4) { sipMessage.Body = message.Substring(endHeaderPosn + 4); } } return(sipMessage); } else { Logger.Logger.Warn( "Error ParseSIPMessage, there were no end of line characters in the string being parsed."); return(null); } } catch (Exception excp) { Logger.Logger.Error("Exception ParseSIPMessage. ->" + excp.Message + "->SIP Message=" + message + "."); return(null); } }
public static SIPRequest ParseSIPRequest(SIPMessageBuffer sipMessage) => ParseSIPRequest(sipMessage, SIPConstants.DEFAULT_ENCODING, SIPConstants.DEFAULT_ENCODING);
/// <summary> /// Attempts to parse a SIP message from a single buffer that can only contain a single message. /// </summary> /// <param name="buffer">The buffer that will be parsed for a SIP message.</param> /// <param name="sipBodyEncoding">SIP payload encoding</param> /// <param name="localSIPEndPoint">The end point the message was received on.</param> /// <param name="remoteSIPEndPoint">The end point the message was received from.</param> /// <param name="sipEncoding">SIP protocol encoding, according to RFC should be UTF-8 </param> /// <returns>If successful a SIP message or null if not.</returns> public static SIPMessageBuffer ParseSIPMessage( byte[] buffer, Encoding sipEncoding, Encoding sipBodyEncoding, SIPEndPoint localSIPEndPoint, SIPEndPoint remoteSIPEndPoint) { if (buffer == null || buffer.Length < m_minFirstLineLength) { // Ignore. return(null); } else if (buffer.Length > SIPConstants.SIP_MAXIMUM_RECEIVE_LENGTH) { throw new ApplicationException("SIP message received that exceeded the maximum allowed message length, ignoring."); } else if (!BufferUtils.HasString(buffer, 0, buffer.Length, SIP_MESSAGE_IDENTIFIER, m_CRLF)) { // Message does not contain "SIP" anywhere on the first line, ignore. return(null); } else { var sipMessage = new SIPMessageBuffer(sipEncoding, sipBodyEncoding); sipMessage.RawBuffer = buffer; sipMessage.LocalSIPEndPoint = localSIPEndPoint; sipMessage.RemoteSIPEndPoint = remoteSIPEndPoint; // For connection oriented transports the same connection should be used for responses and subsequent requests. if (sipMessage.LocalSIPEndPoint != null && remoteSIPEndPoint.ConnectionID != null) { sipMessage.LocalSIPEndPoint.ConnectionID = remoteSIPEndPoint.ConnectionID; } string message = sipEncoding.GetString(buffer); int endFistLinePosn = message.IndexOf(m_CRLF); if (endFistLinePosn != -1) { sipMessage.FirstLine = message.Substring(0, endFistLinePosn); if (sipMessage.FirstLine.Substring(0, 3) == SIP_RESPONSE_PREFIX) { sipMessage.SIPMessageType = SIPMessageTypesEnum.Response; } else { sipMessage.SIPMessageType = SIPMessageTypesEnum.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); sipMessage.SIPHeaders = SIPHeader.SplitHeaders(headerString); } else { string headerString = message.Substring(endFistLinePosn + 2, endHeaderPosn - endFistLinePosn - 2); sipMessage.SIPHeaders = SIPHeader.SplitHeaders(headerString); if (message.Length > endHeaderPosn + 4) { sipMessage.Body = new byte[buffer.Length - (endHeaderPosn + 4)]; Buffer.BlockCopy(buffer, endHeaderPosn + 4, sipMessage.Body, 0, buffer.Length - (endHeaderPosn + 4)); } } return(sipMessage); } else { logger.LogWarning("Error ParseSIPMessage, there were no end of line characters in the string being parsed."); return(null); } } }
public static SIPResponse ParseSIPResponse(SIPMessageBuffer sipMessageBuffer) => ParseSIPResponse(sipMessageBuffer, sipMessageBuffer.SIPEncoding, sipMessageBuffer.SIPBodyEncoding);