📄 htsipconnection.cs
字号:
namespace Imps.Client.CommLayer.HTSipConnection
{
using Imps.Client.Base;
using Imps.Client.CommLayer;
using Imps.Client.CommLayer.Common;
using Imps.Client.CommLayer.TcpSipConnection;
using Imps.Client.Core;
using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
internal class HTSipConnection : Imps.Client.CommLayer.TcpSipConnection.TcpSipConnection
{
private ProxyAuthManager authManager;
private const int BufferSize = 0x2000;
private HttpsTunnelMode mode;
private string remoteHost;
private int remotePort;
private const string StatusCode = "StatusCode";
private const string StatusCodeGroup = @" +(?'StatusCode'\d{3}) +";
public HTSipConnection(object context, TcpSipConnectionOption option) : base(context, option)
{
this.mode = (HttpsTunnelMode) Enum.Parse(typeof(HttpsTunnelMode), Imps.Client.Core.FixedClientSetting.Instance.HTMode, true);
}
private string BuildConnectRequest()
{
StringBuilder builder = new StringBuilder();
switch (this.mode)
{
case HttpsTunnelMode.Nav:
builder.AppendFormat("CONNECT {0} HTTP/1.1\r\n", base.Option.UriSetting.SipcSslProxy);
break;
case HttpsTunnelMode.Buildin:
builder.AppendFormat("CONNECT {0}:443 HTTP/1.1\r\n", this.remoteHost);
break;
}
WebHeaderCollection headers = new WebHeaderCollection();
headers.Add(20, "*/*");
headers.Add(12, "text/html");
headers.Add("Proxy-Connection", "Keep-Alive");
headers.Add(11, "0");
builder.Append(headers.ToString()).Append("\r\n");
return builder.ToString();
}
public override void Connect(string host, int port)
{
this.authManager = new ProxyAuthManager(this);
this.remoteHost = host;
this.remotePort = port;
string proxyHost = CommHelper.GetProxyHost(ConnectionFactory.WebProxy);
if (string.IsNullOrEmpty(proxyHost) || !ConnectionManagerImp.VerfiyProxyHost(proxyHost))
{
this.ConnectWithoutProxy(host, port);
}
else
{
IPAddress address;
if (!IPAddress.TryParse(proxyHost, ref address))
{
IPAddress[] addressList = Dns.GetHostEntry(proxyHost).AddressList;
if ((addressList != null) && (addressList.Length > 0))
{
address = addressList[0];
}
}
int proxyPort = CommHelper.GetProxyPort(ConnectionFactory.WebProxy);
base.CreateClientSocket();
base._clientSocket.BeginConnect(address, proxyPort, new AsyncCallback(this.SocketEndConnect), null);
}
}
private void ConnectWithoutProxy(string host, int port)
{
switch (this.mode)
{
case HttpsTunnelMode.Nav:
{
string[] textArray = base.Option.UriSetting.SipcSslProxy.Split(new char[] { ':' });
if (textArray.Length == 2)
{
int num;
string text = textArray[0];
if (!int.TryParse(textArray[1], ref num))
{
num = 0x1bb;
}
base.Connect(text, num);
return;
}
base.Connect(host, port);
return;
}
case HttpsTunnelMode.Buildin:
base.Connect(host, 0x1bb);
return;
case HttpsTunnelMode.Off:
base.Connect(host, port);
return;
}
}
private void InitHttpsTunnel(string userName, string password)
{
byte[] buffer = new byte[0x2000];
this.SendConnectRequest(buffer);
int count = this.ReceiveConnectResponse(buffer);
if (count <= 0)
{
if (base._clientSocket != null)
{
base._clientSocket.Close();
base._clientSocket = null;
}
throw new SipConnectionException("CONNECT method timeout.");
}
string s = Encoding.UTF8.GetString(buffer, 0, count);
WebHeaderCollection headers = new WebHeaderCollection();
int num2 = -1;
using (StringReader reader = new StringReader(s))
{
string input = reader.ReadLine();
Match match = new Regex(@" +(?'StatusCode'\d{3}) +").Match(input);
if (match.Success && !int.TryParse(match.Groups["StatusCode"].Value, ref num2))
{
num2 = -1;
}
while (true)
{
string header = reader.ReadLine();
if ((header == null) || string.IsNullOrEmpty(header.Trim()))
{
goto Label_00E4;
}
headers.Add(header);
}
}
Label_00E4:
switch (num2)
{
case 200:
return;
case 0x197:
if (!this.authManager.DoAuth(userName, password, headers))
{
throw new SipConnectionException("Proxy authentication failed.");
}
return;
}
throw new SipConnectionException("Proxy dose not support \"CONNECT\" method.");
}
protected override void OnSendingMessageListEventTimeout()
{
try
{
if (base.State == ConnectionState.Connected)
{
this.SendMessage(ThreadSipConnectionBase.physicalHeartbeat);
}
}
catch
{
}
}
private int ReceiveConnectResponse(byte[] buffer)
{
int offset = 0;
int num2 = 0;
while (num2 < 50)
{
if (base._clientSocket.Poll(0x186a0, SelectMode.SelectRead))
{
offset += base._clientSocket.Receive(buffer, offset, buffer.Length - offset, SocketFlags.None);
}
else
{
num2++;
}
}
return offset;
}
private void SendConnectRequest(byte[] buffer)
{
string s = this.BuildConnectRequest();
int num = Encoding.UTF8.GetBytes(s, 0, s.Length, buffer, 0);
int offset = 0;
do
{
offset += base._clientSocket.Send(buffer, offset, num - offset, SocketFlags.None);
}
while (offset < num);
}
private void SocketEndConnect(IAsyncResult asyncResult)
{
try
{
base._clientSocket.EndConnect(asyncResult);
base.SetKeepAlive();
this.InitHttpsTunnel(Imps.Client.Core.NetworkSetting.Instance.HttpProxy.UserName, Imps.Client.Core.NetworkSetting.Instance.HttpProxy.Password);
base.State = ConnectionState.Connected;
}
catch (Exception exception)
{
base._clientSocket = null;
base.State = ConnectionState.Disconnected;
base.RaiseConnectFailed(new FailedEventArgs(exception, Imps.Client.CommLayer.TcpSipConnection.TcpSipConnection.GetErrorString(exception)));
}
}
public override string ToString()
{
return ("Https Tunnel方式 - " + Tools.GetConnectionStateString(base.State));
}
private enum HttpsTunnelMode
{
Nav,
Buildin,
Off
}
private class ProxyAuthManager
{
private Imps.Client.CommLayer.HTSipConnection.HTSipConnection _conn;
public ProxyAuthManager(Imps.Client.CommLayer.HTSipConnection.HTSipConnection conn)
{
this._conn = conn;
}
public bool DoAuth(string userName, string password, WebHeaderCollection http407Response)
{
string text;
string domain;
if (userName.IndexOf(@"\") > 0)
{
string[] textArray = userName.Split(new char[] { '\\' });
domain = textArray[0];
text = textArray[1];
}
else
{
text = userName;
domain = string.Empty;
}
NetworkCredential credential = new NetworkCredential(text, password, domain);
new NegotiateStream(null, false).AuthenticateAsClient(credential, string.Empty);
return false;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -