📄 sipcparser.cs
字号:
namespace Imps.Base.Sipc
{
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
public class SipcParser
{
private LineReader _reader = new LineReader();
private SipcRequestReceivedEventArgs _requestEventArgs = new SipcRequestReceivedEventArgs();
private SipcResponseReceivedEventArgs _responseEventArgs = new SipcResponseReceivedEventArgs();
private MemoryStream _stream = new MemoryStream(0x800);
private static Hashtable _validMethods = new Hashtable();
public const int MaxMessageLength = 0x20000;
public const string SipcProtocol = "SIP-C/2.0";
public event EventHandler MessageParsingFailed;
public event SipcRequestReceivedEventHandler RequestReceived;
public event SipcResponseReceivedEventHandler ResponseReceived;
static SipcParser()
{
_validMethods.Add("A", null);
_validMethods.Add("BN", null);
_validMethods.Add("B", null);
_validMethods.Add("C", null);
_validMethods.Add("I", null);
_validMethods.Add("M", null);
_validMethods.Add("NEG", null);
_validMethods.Add("N", null);
_validMethods.Add("REF", null);
_validMethods.Add("R", null);
_validMethods.Add("S", null);
_validMethods.Add("SUB", null);
_validMethods.Add("IN", null);
_validMethods.Add("O", null);
}
public SipcParser()
{
this._reader.Bind(this._stream);
}
private bool CheckLine(string line)
{
if (line == null)
{
return false;
}
byte[] buffer = this._stream.GetBuffer();
return ((buffer[(int) ((IntPtr) (this._stream.Position - 1))] == 10) && (buffer[(int) ((IntPtr) (this._stream.Position - 2))] == 13));
}
private bool CheckRequest(SipcRequest req)
{
SipcCallIdHeader callId = req.CallId;
SipcCSeqHeader cSeq = req.CSeq;
if (((callId != null) && (cSeq != null)) && (cSeq.Method == req.Method))
{
SipcContentLengthHeader contentLength = req.ContentLength;
if ((contentLength == null) || ((contentLength.Length >= 0) && (contentLength.Length < 0x20000)))
{
return true;
}
}
if (this.MessageParsingFailed != null)
{
this.MessageParsingFailed(this, EventArgs.Empty);
}
return false;
}
private bool CheckResponse(SipcResponse rsp)
{
if (((rsp.CallId != null) && (rsp.CSeq != null)) && ((rsp.ContentLength == null) || ((rsp.ContentLength.Length >= 0) && (rsp.ContentLength.Length < 0x20000))))
{
return true;
}
if (this.MessageParsingFailed != null)
{
this.MessageParsingFailed(this, EventArgs.Empty);
}
return false;
}
public void Clear()
{
this._stream = new MemoryStream(0x800);
this._reader.Bind(this._stream);
}
public string GetUnderlyContent()
{
if ((this._stream != null) && (this._stream.Length > 0))
{
return Encoding.UTF8.GetString(this._stream.GetBuffer(), 0, (int) this._stream.Length);
}
return string.Empty;
}
private void MoveData(long pos)
{
if (pos == 0)
{
this._stream.Position = this._stream.Length;
}
else if ((pos < 0) || (pos >= this._stream.Length))
{
this._stream.Position = 0;
this._stream.SetLength((long) 0);
}
else
{
MemoryStream stream = new MemoryStream(0x800);
stream.Write(this._stream.GetBuffer(), (int) pos, (int) (this._stream.Length - pos));
this._stream = stream;
this._reader.Bind(this._stream);
}
}
public void Parse(byte[] buffer, int pos, int len)
{
this._stream.Write(buffer, pos, len);
if (this._stream.Length > 8)
{
this._stream.Seek((long) 0, SeekOrigin.Begin);
this.TryToParse();
}
if ((this._stream.Length >= 0x20000) && (this.MessageParsingFailed != null))
{
this.MessageParsingFailed(this, EventArgs.Empty);
}
}
private bool ParseBody(SipcMessage msg)
{
SipcContentLengthHeader contentLength = msg.ContentLength;
if ((contentLength != null) && (contentLength.Length >= 1))
{
if ((this._stream.Length - this._stream.Position) < contentLength.Length)
{
return false;
}
msg.BodyBuffer = new byte[contentLength.Length];
this._stream.Read(msg.BodyBuffer, 0, contentLength.Length);
}
return true;
}
private SipcHeader ParseHeader(string name, string value)
{
switch (name.ToUpper())
{
case "A":
return new SipcAuthorizationHeader(value);
case "C":
return new SipcContentTypeHeader(value);
case "E":
return null;
case "Q":
return new SipcCSeqHeader(value);
case "F":
return new SipcFromHeader(value);
case "I":
return new SipcCallIdHeader(value);
case "L":
return new SipcContentLengthHeader(value);
case "M":
return null;
case "N":
return new SipcEventHeader(value);
case "X":
return new SipcExpiresHeader(value);
case "K":
return new SipcSupportedHeader(value);
case "T":
return new SipcToHeader(value);
case "W":
return new SipcWWWAuthenticateHeader(value);
case "RM":
return new SipcRosterManagerHeader(value);
case "EP":
return new SipcEndPointsHeader(value);
case "RT":
return new SipcReferToHeader(value);
case "RB":
return new SipcReferredByHeader(value);
case "RQ":
return new SipcRequireHeader(value);
case "UK":
return new SipcUnsupportedHeader(value);
case "D":
return new SipcDateHeader(value);
case "SO":
return new SipcSourceHeader(value);
case "XI":
return new SipcMessageIDHeader(value);
}
return null;
}
private bool ParseHeaders(SipcMessage msg)
{
for (string line = this._reader.ReadLine(); this.CheckLine(line); line = this._reader.ReadLine())
{
if (line.Length < 1)
{
return this.ParseBody(msg);
}
int length = line.IndexOf(": ");
if (length < 1)
{
return false;
}
string name = line.Substring(0, length);
SipcHeader header = this.ParseHeader(name, line.Substring(length + 2));
if (header != null)
{
msg.Headers.Add(header);
}
}
return false;
}
private bool ParseRequest(string line)
{
if (line.Length >= 1)
{
string[] textArray = line.Split(new char[] { ' ' });
if (((textArray.Length != 3) || (textArray[2] != "SIP-C/2.0")) || !_validMethods.ContainsKey(textArray[0]))
{
if (this.MessageParsingFailed != null)
{
this.MessageParsingFailed(this, EventArgs.Empty);
}
return false;
}
SipcRequest msg = new SipcRequest(textArray[0], textArray[1]);
if (!this.ParseHeaders(msg))
{
return false;
}
if (!this.CheckRequest(msg))
{
return false;
}
this._requestEventArgs.Request = msg;
if (this.RequestReceived != null)
{
this.RequestReceived(this, this._requestEventArgs);
}
}
return true;
}
private bool ParseResponse(string line)
{
int startIndex = line.IndexOf(" ");
int index = line.IndexOf(" ", startIndex + 1);
if ((startIndex < 1) || (index < 1))
{
if (this.MessageParsingFailed != null)
{
this.MessageParsingFailed(this, EventArgs.Empty);
}
return false;
}
try
{
SipcResponse msg = new SipcResponse(int.Parse(line.Substring(startIndex, index - startIndex)), line.Substring(index + 1));
if (this.ParseHeaders(msg))
{
if (!this.CheckResponse(msg))
{
return false;
}
this._responseEventArgs.Response = msg;
if (this.ResponseReceived != null)
{
this.ResponseReceived(this, this._responseEventArgs);
}
return true;
}
return false;
}
catch (Exception exception)
{
Trace.WriteLine(exception.ToString());
return false;
}
}
private void TryToParse()
{
string line = this._reader.ReadLine();
if (this.CheckLine(line))
{
bool flag;
if (line.IndexOf("SIP-C/2.0") == 0)
{
flag = this.ParseResponse(line);
}
else
{
flag = this.ParseRequest(line);
}
long pos = 0;
while (flag)
{
pos = this._stream.Position;
line = this._reader.ReadLine();
if (!this.CheckLine(line))
{
break;
}
if (line.IndexOf("SIP-C/2.0") == 0)
{
flag = this.ParseResponse(line);
}
else
{
flag = this.ParseRequest(line);
}
}
this.MoveData(pos);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -