using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace HPSocketCS
{
public class HttpAgent : TcpAgent
{
///
/// 【可选】开始解析
///
public event HttpAgentEvent.OnMessageBeginEventHandler OnMessageBegin;
///
/// 【可选】请求头通知
///
public event HttpAgentEvent.OnHeaderEventHandler OnHeader;
///
/// 【可选】Chunked 报文头通知
///
public event HttpAgentEvent.OnChunkHeaderEventHandler OnChunkHeader;
///
/// 【可选】Chunked 报文结束通知
///
public event HttpAgentEvent.OnChunkCompleteEventHandler OnChunkComplete;
///
/// 【可选】升级协议通知
///
public event HttpAgentEvent.OnUpgradeEventHandler OnUpgrade;
///
/// 【可选】状态行解析完成(仅用于 HTTP 客户端)
///
public event HttpAgentEvent.OnStatusLineEventHandler OnStatusLine;
///
/// 【必须】请求头完成通知
///
public event HttpAgentEvent.OnHeadersCompleteEventHandler OnHeadersComplete;
///
/// 【必须】请求体报文通知
///
public event HttpAgentEvent.OnBodyEventHandler OnBody;
///
/// 【必须】请求体报文通知
///
public event HttpAgentEvent.OnPointerDataBodyEventHandler OnPointerDataBody;
///
/// 【必须】完成解析通知
///
public event HttpAgentEvent.OnMessageCompleteEventHandler OnMessageComplete;
///
/// 【必须】解析错误通知
///
public event HttpAgentEvent.OnParseErrorEventHandler OnParseError;
///
/// 【必须】WebSocket数据包体通知(byte)
///
public event WebSocketEvent.OnWSMessageBodyEventHandler OnWSMessageBody;
///
/// 【必须】WebSocket数据包体通知(指针)
///
public event WebSocketEvent.OnPointerWSMessageBodyEventHandler OnPointerWSMessageBody;
///
/// 【必须】WebSocket数据完成解析通知
///
public event WebSocketEvent.OnWSMessageCompleteEventHandler OnWSMessageComplete;
///
/// 【必须】WebSocket数据头通知
///
public event WebSocketEvent.OnWSMessageHeaderEventHandler OnWSMessageHeader;
///
/// 创建socket监听&服务组件
///
///
protected override bool CreateListener()
{
if (IsCreate == true || pListener != IntPtr.Zero || pAgent != IntPtr.Zero)
{
return false;
}
pListener = HttpSdk.Create_HP_HttpAgentListener();
if (pListener == IntPtr.Zero)
{
return false;
}
pAgent = HttpSdk.Create_HP_HttpAgent(pListener);
if (pAgent == IntPtr.Zero)
{
return false;
}
IsCreate = true;
return true;
}
///
/// 终止服务并释放资源
///
public override void Destroy()
{
Stop();
if (pAgent != IntPtr.Zero)
{
HttpSdk.Destroy_HP_HttpAgent(pAgent);
pAgent = IntPtr.Zero;
}
if (pListener != IntPtr.Zero)
{
HttpSdk.Destroy_HP_HttpAgentListener(pListener);
pListener = IntPtr.Zero;
}
IsCreate = false;
}
HttpSdk.OnMessageBegin _OnMessageBegin;
HttpSdk.OnHeader _OnHeader;
HttpSdk.OnChunkHeader _OnChunkHeader;
HttpSdk.OnChunkComplete _OnChunkComplete;
HttpSdk.OnUpgrade _OnUpgrade;
HttpSdk.OnStatusLine _OnStatusLine;
HttpSdk.OnHeadersComplete _OnHeadersComplete;
HttpSdk.OnBody _OnBody;
HttpSdk.OnMessageComplete _OnMessageComplete;
HttpSdk.OnParseError _OnParseError;
//增加callback
HttpSdk.OnWSMessageBody _OnWSMessageBody;
HttpSdk.OnWSMessageComplete _OnWSMessageComplete;
HttpSdk.OnWSMessageHeader _OnWSMessageHeader;
///////////////////////////////////////////////////////////////////////////////////////
protected override void SetCallback()
{
// 设置tcpagent的callback
_OnPrepareConnect = new Sdk.OnPrepareConnect(SDK_OnPrepareConnect);
_OnConnect = new Sdk.OnConnect(SDK_OnConnect);
_OnSend = new Sdk.OnSend(SDK_OnSend);
_OnReceive = new Sdk.OnReceive(SDK_OnReceive);
_OnClose = new Sdk.OnClose(SDK_OnClose);
_OnShutdown = new Sdk.OnShutdown(SDK_OnShutdown);
_OnHandShake = new Sdk.OnHandShake(SDK_OnHandShake);
// 设置 Socket 监听器回调函数
HttpSdk.HP_Set_FN_HttpAgent_OnPrepareConnect(pListener, _OnPrepareConnect);
HttpSdk.HP_Set_FN_HttpAgent_OnConnect(pListener, _OnConnect);
HttpSdk.HP_Set_FN_HttpAgent_OnSend(pListener, _OnSend);
HttpSdk.HP_Set_FN_HttpAgent_OnReceive(pListener, _OnReceive);
HttpSdk.HP_Set_FN_HttpAgent_OnClose(pListener, _OnClose);
HttpSdk.HP_Set_FN_HttpAgent_OnShutdown(pListener, _OnShutdown);
HttpSdk.HP_Set_FN_HttpAgent_OnHandShake(pListener, _OnHandShake);
// 设置自身的callback
_OnMessageBegin = new HttpSdk.OnMessageBegin(SDK_OnMessageBegin);
_OnHeader = new HttpSdk.OnHeader(SDK_OnHeader);
_OnChunkHeader = new HttpSdk.OnChunkHeader(SDK_OnChunkHeader);
_OnChunkComplete = new HttpSdk.OnChunkComplete(SDK_OnChunkComplete);
_OnUpgrade = new HttpSdk.OnUpgrade(SDK_OnUpgrade);
_OnStatusLine = new HttpSdk.OnStatusLine(SDK_OnStatusLine);
_OnHeadersComplete = new HttpSdk.OnHeadersComplete(SDK_OnHeadersComplete);
_OnBody = new HttpSdk.OnBody(SDK_OnBody);
_OnMessageComplete = new HttpSdk.OnMessageComplete(SDK_OnMessageComplete);
_OnParseError = new HttpSdk.OnParseError(SDK_OnParseError);
//增加事件!
_OnWSMessageBody = new HttpSdk.OnWSMessageBody(SDK_OnWSMessageBody);
_OnWSMessageComplete = new HttpSdk.OnWSMessageComplete(SDK_OnWSMessageComplete);
_OnWSMessageHeader = new HttpSdk.OnWSMessageHeader(SDK_OnWSMessageHeader);
HttpSdk.HP_Set_FN_HttpAgent_OnMessageBegin(pListener, _OnMessageBegin);
HttpSdk.HP_Set_FN_HttpAgent_OnStatusLine(pListener, _OnStatusLine);
HttpSdk.HP_Set_FN_HttpAgent_OnHeader(pListener, _OnHeader);
HttpSdk.HP_Set_FN_HttpAgent_OnHeadersComplete(pListener, _OnHeadersComplete);
HttpSdk.HP_Set_FN_HttpAgent_OnBody(pListener, _OnBody);
HttpSdk.HP_Set_FN_HttpAgent_OnChunkHeader(pListener, _OnChunkHeader);
HttpSdk.HP_Set_FN_HttpAgent_OnChunkComplete(pListener, _OnChunkComplete);
HttpSdk.HP_Set_FN_HttpAgent_OnMessageComplete(pListener, _OnMessageComplete);
HttpSdk.HP_Set_FN_HttpAgent_OnUpgrade(pListener, _OnUpgrade);
HttpSdk.HP_Set_FN_HttpAgent_OnParseError(pListener, _OnParseError);
//增加
HttpSdk.HP_Set_FN_HttpAgent_OnWSMessageBody(pListener, _OnWSMessageBody);
HttpSdk.HP_Set_FN_HttpAgent_OnWSMessageComplete(pListener, _OnWSMessageComplete);
HttpSdk.HP_Set_FN_HttpAgent_OnWSMessageHeader(pListener, _OnWSMessageHeader);
}
//包解析完成事件
private HandleResult SDK_OnWSMessageHeader(IntPtr pSender, IntPtr connId, bool bFinal, byte iReserved, byte iOperationCode, byte[] lpszMask, ulong ullBodyLen)
{
if (OnWSMessageHeader != null) {
OnWSMessageHeader(connId, bFinal, iReserved, iOperationCode, lpszMask, ullBodyLen);
}
return HandleResult.Ok;
}
//头解析完成事件
private HandleResult SDK_OnWSMessageComplete(IntPtr pSender, IntPtr connId)
{
if (OnWSMessageComplete != null){
return OnWSMessageComplete(connId);
}
return HandleResult.Ok;
}
//包体事件!
private HandleResult SDK_OnWSMessageBody(IntPtr pSender, IntPtr connId, IntPtr pData, int iLength)
{
if (OnWSMessageBody != null)
{
byte[] bytes = new byte[iLength];
Marshal.Copy(pData, bytes, 0, iLength);
return OnWSMessageBody(connId, bytes);
}
else if(OnPointerWSMessageBody!=null)
{
return OnPointerWSMessageBody(connId, pData, iLength);
}
return HandleResult.Ok;
}
protected HttpParseResult SDK_OnParseError(IntPtr pSender, IntPtr connId, int iErrorCode, string lpszErrorDesc)
{
if (OnParseError != null)
{
return OnParseError(connId, iErrorCode, lpszErrorDesc);
}
return HttpParseResult.Ok;
}
protected HttpParseResult SDK_OnMessageComplete(IntPtr pSender, IntPtr connId)
{
if (OnMessageComplete != null)
{
return OnMessageComplete(connId);
}
return HttpParseResult.Ok;
}
protected HttpParseResult SDK_OnBody(IntPtr pSender, IntPtr connId, IntPtr pData, int iLength)
{
if (OnPointerDataBody != null)
{
return OnPointerDataBody(connId, pData, iLength);
}
else if (OnBody != null)
{
byte[] bytes = new byte[iLength];
Marshal.Copy(pData, bytes, 0, iLength);
return OnBody(connId, bytes);
}
return HttpParseResult.Ok;
}
private HttpParseResultEx SDK_OnHeadersComplete(IntPtr pSender, IntPtr connId)
{
if (OnHeadersComplete != null)
{
return OnHeadersComplete(connId);
}
return HttpParseResultEx.Ok;
}
protected HttpParseResult SDK_OnStatusLine(IntPtr pSender, IntPtr connId, ushort usStatusCode, string lpszDesc)
{
if (OnStatusLine != null)
{
return OnStatusLine(connId, usStatusCode, lpszDesc);
}
return HttpParseResult.Ok;
}
protected HttpParseResult SDK_OnUpgrade(IntPtr pSender, IntPtr connId, HttpUpgradeType enUpgradeType)
{
if (OnUpgrade != null)
{
return OnUpgrade(connId, enUpgradeType);
}
return HttpParseResult.Ok;
}
protected HttpParseResult SDK_OnChunkComplete(IntPtr pSender, IntPtr connId)
{
if (OnChunkComplete != null)
{
return OnChunkComplete(connId);
}
return HttpParseResult.Ok;
}
protected HttpParseResult SDK_OnChunkHeader(IntPtr pSender, IntPtr connId, int iLength)
{
if (OnChunkHeader != null)
{
return OnChunkHeader(connId, iLength);
}
return HttpParseResult.Ok;
}
protected HttpParseResult SDK_OnHeader(IntPtr pSender, IntPtr connId, string lpszName, string lpszValue)
{
if (OnHeader != null)
{
return OnHeader(connId, lpszName, lpszValue);
}
return HttpParseResult.Ok;
}
protected HttpParseResult SDK_OnMessageBegin(IntPtr pSender, IntPtr connId)
{
if (OnMessageBegin != null)
{
return OnMessageBegin(connId);
}
return HttpParseResult.Ok;
}
/**************************************************************************/
/***************************** Agent 操作方法 ******************************/
///
/// 发送请求
///
///
/// 请求方法
/// 请求路径
/// 请求头
/// 请求体
///
public bool SendRequest(IntPtr connId, HttpMethod method, string path, THeader[] headers, byte[] body, int bodyLength)
{
int headersLength = headers == null ? 0 : headers.Length;
return HttpSdk.HP_HttpAgent_SendRequest(pAgent, connId, method.ToString(), path, headers, headersLength, body, bodyLength);
}
///
/// 名称:发送本地文件
/// 描述:向指定连接发送 4096 KB 以下的小文件
///
///
///
///
///
///
///
public bool SendLocalFile(IntPtr connId, string fileName, HttpMethod method, string path, THeader[] headers)
{
int headersLength = headers == null ? 0 : headers.Length;
return HttpSdk.HP_HttpAgent_SendLocalFile(pAgent, connId, fileName, method.ToString(), path, headers, headersLength);
}
///
/// 发送 POST 请求
///
///
///
///
///
///
public bool SendPost(IntPtr connId, string path, THeader[] headers, string body)
{
int bodyLength = body == null ? 0 : body.Length;
int headersLength = headers == null ? 0 : headers.Length;
return HttpSdk.HP_HttpAgent_SendPost(pAgent, connId, path, headers, headersLength, body, bodyLength);
}
///
/// 发送 PUT 请求
///
///
///
///
///
///
public bool SendPut(IntPtr connId, string path, THeader[] headers, string body)
{
int bodyLength = body == null ? 0 : body.Length;
int headersLength = headers == null ? 0 : headers.Length;
return HttpSdk.HP_HttpAgent_SendPut(pAgent, connId, path, headers, headersLength, body, bodyLength);
}
///
/// 发送 PATCH 请求
///
///
///
///
///
///
public bool SendPatch(IntPtr connId, string path, THeader[] headers, string body)
{
int bodyLength = body == null ? 0 : body.Length;
int headersLength = headers == null ? 0 : headers.Length;
return HttpSdk.HP_HttpAgent_SendPatch(pAgent, connId, path, headers, headersLength, body, bodyLength);
}
///
/// 发送 GET 请求
///
///
///
///
///
public bool SendGet(IntPtr connId, string path, THeader[] headers)
{
int headersLength = headers == null ? 0 : headers.Length;
return HttpSdk.HP_HttpAgent_SendGet(pAgent, connId, path, headers, headersLength);
}
///
/// 发送 DELETE 请求
///
///
///
///
///
public bool SendDelete(IntPtr connId, string path, THeader[] headers)
{
return HttpSdk.HP_HttpAgent_SendDelete(pAgent, connId, path, headers, headers.Length);
}
///
/// 发送 HEAD 请求
///
///
///
///
///
public bool SendHead(IntPtr connId, string path, THeader[] headers)
{
int headersLength = headers == null ? 0 : headers.Length;
return HttpSdk.HP_HttpAgent_SendHead(pAgent, connId, path, headers, headersLength);
}
///
/// 发送 TRACE 请求
///
///
///
///
///
public bool SendTrace(IntPtr connId, string path, THeader[] headers)
{
int headersLength = headers == null ? 0 : headers.Length;
return HttpSdk.HP_HttpAgent_SendTrace(pAgent, connId, path, headers, headersLength);
}
///
/// 发送 OPTIONS 请求
///
///
///
///
///
public bool SendOptions(IntPtr connId, string path, THeader[] headers)
{
int headersLength = headers == null ? 0 : headers.Length;
return HttpSdk.HP_HttpAgent_SendOptions(pAgent, connId, path, headers, headersLength);
}
///
/// 发送 WSMessage 请求
///
///
///
///
///
///
///
///
///
public bool SendWSMessage(IntPtr dwConnID, bool bFinal, byte iReserved, byte iOperationCode, byte[] lpszMask, byte[] pData, ulong ullBodyLen) {
return HttpSdk.HP_HttpAgent_SendWSMessage(pAgent, dwConnID, bFinal, iReserved, iOperationCode, lpszMask, pData, pData.Length, ullBodyLen);
}
///
/// 发送 CONNECT 请求
///
///
///
///
///
public bool SendConnect(IntPtr connId, string path, THeader[] headers)
{
int headersLength = headers == null ? 0 : headers.Length;
return HttpSdk.HP_HttpAgent_SendConnect(pAgent, connId, path, headers, headersLength);
}
///
/// 启动 HTTP 通信, 当通信组件设置为非自动启动 HTTP 通信时,需要调用本方法启动 HTTP 通信
///
///
///
public bool StartHttp(IntPtr connId)
{
return HttpSdk.HP_HttpAgent_StartHttp(pAgent, connId);
}
/******************************************************************************/
/***************************** Agent 属性访问方法 ******************************/
///
/// 获取或设置是否使用 Cookie
///
public bool UseCookie
{
get
{
return HttpSdk.HP_HttpAgent_IsUseCookie(pAgent);
}
set
{
HttpSdk.HP_HttpAgent_SetUseCookie(pAgent, value);
}
}
///
/// 获取 HTTP 状态码
///
///
///
public HttpStatusCode GetStatusCode(IntPtr connId)
{
// 有没有可能获取到未定义的状态码???
return (HttpStatusCode)HttpSdk.HP_HttpAgent_GetStatusCode(pAgent, connId);
}
///
/// 获取或设置本地协议版本
///
public HttpVersion LocalVersion
{
get
{
return HttpSdk.HP_HttpAgent_GetLocalVersion(pAgent);
}
set
{
HttpSdk.HP_HttpAgent_SetLocalVersion(pAgent, value);
}
}
///
/// 检查是否升级协议
///
///
///
public bool IsUpgrade(IntPtr connId)
{
return HttpSdk.HP_HttpAgent_IsUpgrade(pAgent, connId);
}
///
/// 检查是否有 Keep-Alive 标识
///
///
///
public bool IsKeepAlive(IntPtr connId)
{
return HttpSdk.HP_HttpAgent_IsKeepAlive(pAgent, connId);
}
///
/// 获取协议版本
///
///
///
public HttpVersion GetVersion(IntPtr connId)
{
return (HttpVersion)HttpSdk.HP_HttpAgent_GetVersion(pAgent, connId);
}
///
/// 获取内容长度
///
///
///
public long GetContentLength(IntPtr connId)
{
return HttpSdk.HP_HttpAgent_GetContentLength(pAgent, connId);
}
///
/// 获取内容类型
///
///
///
public string GetContentType(IntPtr connId)
{
IntPtr ptr = HttpSdk.HP_HttpAgent_GetContentType(pAgent, connId);
return Common.PtrToAnsiString(ptr);
}
///
/// 获取内容类型
///
///
public string GetContentEncoding(IntPtr connId)
{
IntPtr ptr = HttpSdk.HP_HttpAgent_GetContentEncoding(pAgent, connId);
return Common.PtrToAnsiString(ptr);
}
///
/// 获取传输编码
///
///
public string GetTransferEncoding(IntPtr connId)
{
IntPtr ptr = HttpSdk.HP_HttpAgent_GetTransferEncoding(pAgent, connId);
return Common.PtrToAnsiString(ptr);
}
///
/// 获取协议升级类型
///
///
///
public HttpUpgradeType GetUpgradeType(IntPtr connId)
{
return HttpSdk.HP_HttpAgent_GetUpgradeType(pAgent, connId);
}
///
/// 获取解析错误代码
///
///
///
public ErrorInfo GetParseErrorInfo(IntPtr connId)
{
IntPtr ptr = IntPtr.Zero;
var error = new ErrorInfo();
error.ErrorCode = HttpSdk.HP_HttpAgent_GetParseErrorCode(pAgent, connId, ref ptr);
if (ptr != IntPtr.Zero)
{
try
{
error.ErrorMsg = Common.PtrToAnsiString(ptr); ;
}
catch (Exception)
{
}
}
return error;
}
///
/// 获取某个请求头(单值)
///
///
///
///
public string GetHeader(IntPtr connId, string key)
{
IntPtr ptr = IntPtr.Zero;
if (HttpSdk.HP_HttpAgent_GetHeader(pAgent, connId, key, ref ptr))
{
return Common.PtrToAnsiString(ptr);
}
return "";
}
///
/// 获取某个请求头(多值)
///
///
///
///
public List GetHeaders(IntPtr connId, string key)
{
var list = new List();
try
{
IntPtr[] arr = null;
uint count = 0;
HttpSdk.HP_HttpAgent_GetHeaders(pAgent, connId, key, arr, ref count);
if (count > 0)
{
arr = new IntPtr[count];
if (HttpSdk.HP_HttpAgent_GetHeaders(pAgent, connId, key, arr, ref count) && count > 0)
{
foreach (var item in arr)
{
list.Add(Common.PtrToAnsiString(item));
}
}
}
}
catch (Exception)
{
}
return list;
}
///
/// 获取所有请求头
///
///
///
public List GetAllHeaders(IntPtr connId)
{
var list = new List();
try
{
uint count = 0;
IntPtr arrPtr = IntPtr.Zero;
HttpSdk.HP_HttpAgent_GetAllHeaders(pAgent, connId, arrPtr, ref count);
if (count > 0)
{
var ptrArr = new THeaderForIntPtr[count];
arrPtr = Marshal.UnsafeAddrOfPinnedArrayElement(ptrArr, 0);
if (HttpSdk.HP_HttpAgent_GetAllHeaders(pAgent, connId, arrPtr, ref count))
{
foreach (var item in ptrArr)
{
list.Add(new THeader()
{
Name = Common.PtrToAnsiString(item.Name),
Value = Common.PtrToAnsiString(item.Value),
});
}
}
}
}
catch (Exception)
{
}
return list;
}
///
/// 获取所有请求头名称
///
///
///
public List GetAllHeaderNames(IntPtr connId)
{
var list = new List();
try
{
IntPtr[] arr = null;
uint count = 0;
HttpSdk.HP_HttpAgent_GetAllHeaderNames(pAgent, connId, arr, ref count);
if (count > 0)
{
arr = new IntPtr[count];
if (HttpSdk.HP_HttpAgent_GetAllHeaderNames(pAgent, connId, arr, ref count) && count > 0)
{
foreach (var item in arr)
{
list.Add(Common.PtrToAnsiString(item));
}
}
}
}
catch (Exception)
{
}
return list;
}
///
/// 获取Cookie
///
///
///
///
public string GetCookie(IntPtr connId, string key)
{
IntPtr ptr = IntPtr.Zero;
if (HttpSdk.HP_HttpAgent_GetCookie(pAgent, connId, key, ref ptr))
{
return Common.PtrToAnsiString(ptr);
}
return "";
}
///
/// 获取所有 Cookie
///
///
///
///
///
public List GetAllCookies(IntPtr connId)
{
var list = new List();
try
{
uint count = 0;
IntPtr arrPtr = IntPtr.Zero;
HttpSdk.HP_HttpAgent_GetAllCookies(pAgent, connId, arrPtr, ref count);
if (count > 0)
{
var ptrArr = new THeaderForIntPtr[count];
arrPtr = Marshal.UnsafeAddrOfPinnedArrayElement(ptrArr, 0);
if (HttpSdk.HP_HttpAgent_GetAllCookies(pAgent, connId, arrPtr, ref count))
{
foreach (var item in ptrArr)
{
list.Add(new TCookie()
{
Name = Common.PtrToAnsiString(item.Name),
Value = Common.PtrToAnsiString(item.Value)
});
}
}
}
}
catch (Exception)
{
}
return list;
}
///
/// 获取或设置 HTTP 启动方式,默认为true
///
public bool HttpAutoStart
{
get
{
return HttpSdk.HP_HttpAgent_IsHttpAutoStart(pAgent);
}
set
{
HttpSdk.HP_HttpAgent_SetHttpAutoStart(pAgent, value);
}
}
}
}