HP Socket HttpServer使用

使用HP搭建Socket HttpServer,并且实现post,get,以及websocket,主要是webssockt折腾了不少时间。

首先要自己实现底层接口,都是纯虚函数,需要自己去实现,继承自IHttpServerListener

#pragma once

#include "SocketInterface.h"
#include "stdio.h"
#include<sys/stat.h>  
#include "BASE64.h"
#include "USER_SHA1.h"


#define html_base_path  "f:\\Desktop\\桌面文件整理\\临时工程\\helsinki-blue\\"

/************************************************************************
名称:IComplexHttp 组件监听器基接口
描述:定义 IComplexHttp 组件监听器的所有事件
************************************************************************/
class  HttpServerListernet : public IHttpServerListener
{


	/**********************************************************************/
	/* Give a client a 404 not found status message. */
	/**********************************************************************/
	void not_found(IHttpServer* pSender, CONNID dwConnID)
	{
		const char *pErrorNotFound =
			"<HTML><TITLE>Not Found</TITLE>\r\n"\
			"<BODY><P>The server could not fulfill\r\n"\
			"your request because the resource specified\r\n"\
			"is unavailable or nonexistent.\r\n"\
			"</BODY></HTML>\r\n";

		pSender->SendResponse(dwConnID, HSC_OK, nullptr, nullptr, 0, (BYTE *)pErrorNotFound, sizeof(pErrorNotFound));
	}


public:

	/*
	* 名称:开始解析通知
	* 描述:开始解析 HTTP 报文时,向监听器发送该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	* 返回值:	HPR_OK		-- 继续执行
	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
	*/
	EnHttpParseResult OnMessageBegin(IHttpServer* pSender, CONNID dwConnID)
	{
		return HPR_OK;
	}

	/*
	* 名称:请求行解析完成通知(仅用于 HTTP 服务端)
	* 描述:请求行解析完成后,向监听器发送该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	*			lpszMethod	-- 请求方法名
	*			lpszUrl		-- 请求行中的 URL 域
	* 返回值:	HPR_OK		-- 继续执行
	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
	*/
	//过滤器在此完成
	EnHttpParseResult OnRequestLine(IHttpServer* pSender, CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl)
	{
		char buff[512 + 4];
		char UrlData[1024 + 4];
		char *pParameter = nullptr;	//参数
		char ExtenName[4];
		char path[512];
		int len;
		
		struct stat st;

		if (lpszMethod != nullptr)
		{
			if (strcmp(lpszMethod, "POST") == 0)				//POST 
			{
				//pSender->SendResponse(dwConnID, HSC_OK, nullptr, nullptr, 0, nullptr);
				return HPR_OK;
			}
			else if (strcmp(lpszMethod, "GET") == 0)			//GET
			{
				len = strlen(lpszUrl);
				if (len > 1024)	//限制长度为1KB
				{
					len = 1024;
					
				}
				if (len > 0)
				{
					//拷贝数据到缓冲区中
					memcpy(UrlData, lpszUrl, len);
					UrlData[len] = 0;
					if (lpszUrl[len - 1] == '/')				//当前请求的是目录,打开默认文件
					{
						if (strcmp(UrlData, "/websocket/data/") == 0) //websocket api接口
						{
							//pSender->Send(dwConnID, (BYTE *)"123456\r\n", 8, 0);
							//pSender->SendWSMessage(dwConnID, true, 0, 0, nullptr, (BYTE *)"123456\r\n", 8, 0);

							return HPR_OK;
						}
						else
						{
							sprintf_s(path, 512, "%s%s", html_base_path, "index.html");
						}						
					}
					else //非目录,先处理参数,去掉参数后判断是文件还是虚拟路径URL
					{
						pParameter = strstr(UrlData, "?");		//搜索到第一个问号,问号后面的都是参数
						if (pParameter != nullptr)				//有参数
						{
							*pParameter = '\0';					//截断数据-前面的是URL,后面的是参数,并且去掉了第一个问号
							pParameter += 1;					//跳过问号

						}
						sprintf_s(path, 512, "%s%s", html_base_path, UrlData);	//生成文件绝对路径
					}

					if (stat(path, &st) == -1)	//文件不存在
					{						
						not_found(pSender, dwConnID); //返回404
					}
					else //文件存在
					{
						pSender->SendLocalFile(dwConnID, path, HSC_OK, nullptr, nullptr, 0);//返回文件
					}


				}
				
				return HPR_OK;
			}
		}

		return HPR_ERROR;
	}


	/*
	* 名称:BODY 报文通知
	* 描述:每当接收到 HTTP BODY 报文,向监听器发送该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	*			pData		-- 数据缓冲区
	*			iLength		-- 数据长度
	* 返回值:	HPR_OK		-- 继续执行
	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
	*/
	//收到POST请求负载
	EnHttpParseResult OnBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
	{
		//pSender->Send(dwConnID, (BYTE *)"123456\r\n", 8, 0);
		pSender->SendResponse(dwConnID, HSC_OK, nullptr, nullptr, 0, pData, iLength);
		//pSender->SendLocalFile(dwConnID, "f:\\Desktop\\桌面文件夹整理\\青岛站点4.png", HSC_OK, nullptr, nullptr, 0);
		return HPR_OK;
	}



	/*
	* 名称:状态行解析完成通知(仅用于 HTTP 客户端)
	* 描述:状态行解析完成后,向监听器发送该通知
	*
	* 参数:		pSender			-- 事件源对象
	*			dwConnID		-- 连接 ID
	*			usStatusCode	-- HTTP 状态码
	*			lpszDesc		-- 状态描述
	* 返回值:	HPR_OK			-- 继续执行
	*			HPR_ERROR		-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
	*/
	EnHttpParseResult OnStatusLine(IHttpServer* pSender, CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc)
	{
		return HPR_OK;
	}

	/*
	* 名称:请求头通知
	* 描述:每当解析完成一个请求头后,向监听器发送该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	*			lpszName	-- 请求头名称
	*			lpszValue	-- 请求头值
	* 返回值:	HPR_OK		-- 继续执行
	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
	*/
	EnHttpParseResult OnHeader(IHttpServer* pSender, CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)
	{
		if (strcmp("Sec-WebSocket-Key", lpszName) == 0)	//收到websocket握手
		{
			THeader lpHeaders[4];
			BYTE OutSHA1Buf[512];
			static char key[256];
			lpHeaders[0].name = "Upgrade";
			lpHeaders[0].value = "websocket";
			lpHeaders[1].name = "Connection";
			lpHeaders[1].value = "Upgrade";
			lpHeaders[2].name = "Sec-WebSocket-Accept";
			
			sprintf_s(key, 255, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", lpszValue);
			
			int len = SHA1_String((unsigned char*)key, strlen(key), OutSHA1Buf);
			base64_encode(OutSHA1Buf, 20, key);
			lpHeaders[2].value = key;			//生成握手加密key
			lpHeaders[3].name = "Sec-WebSocket-Protocol";
			lpHeaders[3].value = "chat";


			pSender->SendResponse(dwConnID, HSC_SWITCHING_PROTOCOLS, nullptr, lpHeaders, 3, nullptr, 0);

	
			return HPR_OK;
		}
		return HPR_OK;
	}

	/*
	* 名称:请求头完成通知
	* 描述:解析完成所有请求头后,向监听器发送该通知
	*
	* 参数:		pSender			-- 事件源对象
	*			dwConnID		-- 连接 ID
	* 返回值:	HPR_OK			-- 继续执行
	*			HPR_SKIP_BODY	-- 跳过当前请求的 HTTP BODY
	*			HPR_UPGRADE		-- 升级协议
	*			HPR_ERROR		-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
	*/
	EnHttpParseResult OnHeadersComplete(IHttpServer* pSender, CONNID dwConnID)
	{
		return HPR_OK;
	}

	

	/*
	* 名称:Chunked 报文头通知
	* 描述:每当解析出一个 Chunked 报文头,向监听器发送该通知THeader lpHeaders[4];
							lpHeaders[0].name = "Upgrade";
							lpHeaders[0].value = "websocket";
							lpHeaders[1].name = "Connection";
							lpHeaders[1].value = "Upgrade";
							lpHeaders[2].name = "Sec-WebSocket-Accept";
							lpHeaders[2].value = "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=";			//生成握手加密key
							lpHeaders[3].name = "Sec-WebSocket-Protocol";
							lpHeaders[3].value = "chat";

							pSender->SendResponse(dwConnID, HSC_SWITCHING_PROTOCOLS, nullptr, lpHeaders, 4, nullptr, 0);
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	*			iLength		-- Chunked 报文体数据长度
	* 返回值:	HPR_OK		-- 继续执行
	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
	*/
	EnHttpParseResult OnChunkHeader(IHttpServer* pSender, CONNID dwConnID, int iLength)
	{
		return HPR_OK;
	}

	/*
	* 名称:Chunked 报文结束通知
	* 描述:每当解析完一个 Chunked 报文,向监听器发送该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	* 返回值:	HPR_OK		-- 继续执行
	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
	*/
	EnHttpParseResult OnChunkComplete(IHttpServer* pSender, CONNID dwConnID)
	{
		return HPR_OK;
	}

	/*
	* 名称:完成解析通知
	* 描述:每当解析完成一个完整 HTTP 报文,向监听器发送该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	* 返回值:	HPR_OK		-- 继续执行
	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
	*/
	EnHttpParseResult OnMessageComplete(IHttpServer* pSender, CONNID dwConnID)
	{
		//pSender->Send(dwConnID, (BYTE *)"123456\r\n", 8, 0);
		//pSender->SendSmallFile(dwConnID, L"f:\\Desktop\\桌面文件夹整理\\新建文本文档 (3).html", nullptr, nullptr);
		return HPR_OK;
	}

	/*
	* 名称:升级协议通知
	* 描述:当需要升级协议时,向监听器发送该通知
	*
	* 参数:		pSender			-- 事件源对象
	*			dwConnID		-- 连接 ID
	*			enUpgradeType	-- 协议类型
	* 返回值:	HPR_OK			-- 继续执行
	*			HPR_ERROR		-- 引发 OnClose() 事件并关闭连接
	*/
	EnHttpParseResult OnUpgrade(IHttpServer* pSender, CONNID dwConnID, EnHttpUpgradeType enUpgradeType)
	{
		return HPR_OK;
	}

	/*
	* 名称:解析错误通知
	* 描述:当解析 HTTP 报文错误时,向监听器发送该通知
	*
	* 参数:		pSender			-- 事件源对象
	*			dwConnID		-- 连接 ID
	*			iErrorCode		-- 错误代码
	*			lpszErrorDesc	-- 错误描述
	* 返回值:	HPR_OK			-- 继续执行
	*			HPR_ERROR		-- 引发 OnClose() 事件并关闭连接
	*/
	EnHttpParseResult OnParseError(IHttpServer* pSender, CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc)
	{
		return HPR_OK;
	}

	/*
	* 名称:WebSocket 数据包头通知
	* 描述:当解析 WebSocket 数据包头时,向监听器发送该通知
	*
	* 参数:		pSender			-- 事件源对象
	*			dwConnID		-- 连接 ID
	*			bFinal			-- 是否结束帧
	*			iReserved		-- RSV1/RSV2/RSV3 各 1 位
	*			iOperationCode	-- 操作码:0x0 - 0xF
	*			lpszMask		-- 掩码(nullptr 或 4 字节掩码,如果为 nullptr 则没有掩码)
	*			ullBodyLen		-- 消息体长度
	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
	*/
	EnHandleResult OnWSMessageHeader(IHttpServer* pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen)
	{
		static char buff[32];
		static int cnt = 0;
		//iOperationCode 0:连接帧;1:文本帧;2:二进制数据;8:关闭;9:ping;10:pong
		if (iOperationCode == 8) //断开连接
		{
			return HR_ERROR;
		}


		int len = sprintf_s(buff, 31, "%d", cnt++);
		BYTE MaskingKey[] = { 11, 121, 24, 191 };
		//注意:服务器发送到从机是不需要掩码
		int status = pSender->SendWSMessage(dwConnID, 1, 0, 1, nullptr, (BYTE*)buff, len, len);

		return HR_OK;
	}

	/*
	* 名称:WebSocket 数据包体通知
	* 描述:当接收到 WebSocket 数据包体时,向监听器发送该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	*			pData		-- 消息体数据缓冲区
	*			iLength		-- 消息体数据长度
	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
	*/
	EnHandleResult OnWSMessageBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
	{
		/*char buff[32];
		static int cnt = 0;

		int len = sprintf_s(buff, 31, "%d", cnt++);
		BYTE MaskingKey[] = {11,121,24,191};
		int status = pSender->SendWSMessage(dwConnID, false, 0, 2, MaskingKey, (BYTE*)buff, len, len);*/
		return HR_OK;
	}

	/*
	* 名称:WebSocket 数据包完成通知
	* 描述:当完整接收一个 WebSocket 数据包时,向监听器发送该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
	*/
	EnHandleResult OnWSMessageComplete(IHttpServer* pSender, CONNID dwConnID)
	{
		return HR_OK;
	}



	/*
	* 名称:准备监听通知
	* 描述:通信服务端组件启动时,在监听 Socket 创建完成并开始执行监听前,Socket 监听
	*		器将收到该通知,监听器可以在通知处理方法中执行 Socket 选项设置等额外工作
	*
	* 参数:		pSender		-- 事件源对象
	*			soListen	-- 监听 Socket
	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
	*			HR_ERROR			-- 终止启动通信服务组件
	*/
	EnHandleResult OnPrepareListen(ITcpServer* pSender, SOCKET soListen)
	{
		return HR_OK;
	}

	/*
	* 名称:接收连接通知
	* 描述:接收到客户端连接请求时,Socket 监听器将收到该通知,监听器可以在通知处理方
	*		法中执行 Socket 选项设置或拒绝客户端连接等额外工作
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	*			soClient	-- TCP: 客户端 Socket 句柄,UDP: 客户端 Socket SOCKADDR 指针
	* 返回值:	HR_OK / HR_IGNORE	-- 接受连接
	*			HR_ERROR			-- 拒绝连接
	*/
	EnHandleResult OnAccept(ITcpServer* pSender, CONNID dwConnID, UINT_PTR soClient)
	{
		return HR_OK;
	}


	/*
	* 名称:握手完成通知
	* 描述:连接完成握手时,Socket 监听器将收到该通知,监听器接收到该通知后才能开始
	*		数据收发操作
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
	*/
	EnHandleResult OnHandShake(ITcpServer* pSender, CONNID dwConnID)
	{
		return HR_OK;
	}

	/*
	* 名称:已发送数据通知
	* 描述:成功发送数据后,Socket 监听器将收到该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	*			pData		-- 已发送数据缓冲区
	*			iLength		-- 已发送数据长度
	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
	*			HR_ERROR			-- 该通知不允许返回 HR_ERROR(调试模式下引发断言错误)
	*/
	EnHandleResult OnSend(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
	{
		return HR_OK;
	}

	/*
	* 名称:数据到达通知(PUSH 模型)
	* 描述:对于 PUSH 模型的 Socket 通信组件,成功接收数据后将向 Socket 监听器发送该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	*			pData		-- 已接收数据缓冲区
	*			iLength		-- 已接收数据长度
	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
	*/
	EnHandleResult OnReceive(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
	{
		return HR_OK;
	}

	/*
	* 名称:数据到达通知(PULL 模型)
	* 描述:对于 PULL 模型的 Socket 通信组件,成功接收数据后将向 Socket 监听器发送该通知
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	*			iLength		-- 已接收数据长度
	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
	*/
	EnHandleResult OnReceive(ITcpServer* pSender, CONNID dwConnID, int iLength)
	{
		return HR_OK;
	}

	/*
	* 名称:通信错误通知
	* 描述:通信发生错误后,Socket 监听器将收到该通知,并关闭连接
	*
	* 参数:		pSender		-- 事件源对象
	*			dwConnID	-- 连接 ID
	*			enOperation	-- Socket 操作类型
	*			iErrorCode	-- 错误代码
	* 返回值:	忽略返回值
	*/
	EnHandleResult OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
	{
		return HR_OK;
	}

	/*
	* 名称:关闭通信组件通知
	* 描述:通信组件关闭时,Socket 监听器将收到该通知
	*
	* 参数:		pSender		-- 事件源对象
	* 返回值:忽略返回值
	*/
	EnHandleResult OnShutdown(ITcpServer* pSender)
	{
		return HR_OK;
	}



public:
	~HttpServerListernet() {}
};

做websocket握手时需要使用到SHA1与BASE64,这2个都是网上找的。

//USER_SHA1.cpp

#include "StdAfx.h"
#include "USER_SHA1.h"
#include "string.h"


typedef struct SHAstate_st
{
	unsigned long h[SHA1_SIZE_BYTE / 4]; /* 存放摘要结果(32*5=160 bits)*/
	unsigned long Nl;
	unsigned long Nh;       /*存放信息总位数,Nh:高32位,Nl:低32位*/
	unsigned long data[16]; /*数据从第0个的高8位开始依次放置*/
	int FlagInWord;     /*标识一个data元素中占用的字节数(从高->低),取值0,1,2,3*/
	int msgIndex;       /*当前已填充满的data数组元素数。*/
	int isTooMang;      /*正常为0,当处理的信息超过2^64 bits时为1;*/
} SHA1_Context;

#define INIT_DATA_h0 0x67452301U
#define INIT_DATA_h1 0xEFCDAB89U
#define INIT_DATA_h2 0x98BADCFEU
#define INIT_DATA_h3 0x10325476U
#define INIT_DATA_h4 0xC3D2E1F0U

#define SHA1CircularShift(bits, word) (((word) << (bits)) | ((word) >> (32 - (bits))))

const unsigned long SHA1_Kt[] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
typedef unsigned long(*SHA1_pFun)(unsigned long b, unsigned long c, unsigned long d);

/*定义四个函数*/
static unsigned long SHA1_ft0_19(unsigned long b, unsigned long c, unsigned long d)
{
	return (b&c) | ((~b)&d);
}

static unsigned long SHA1_ft20_39(unsigned long b, unsigned long c, unsigned long d)
{
	return b ^ c ^ d;
}

static unsigned long SHA1_ft40_59(unsigned long b, unsigned long c, unsigned long d)
{
	return (b&c) | (b&d) | (c&d);
}

static unsigned long SHA1_ft60_79(unsigned long b, unsigned long c, unsigned long d)
{
	return b ^ c ^ d;
}

SHA1_pFun ft[] = { SHA1_ft0_19, SHA1_ft20_39, SHA1_ft40_59, SHA1_ft60_79 };

static int SHA1_Init(SHA1_Context *c)
{
	if (NULL == c)
	{
		return -1;
	}

	c->h[0] = INIT_DATA_h0;

	c->h[1] = INIT_DATA_h1;
	c->h[2] = INIT_DATA_h2;
	c->h[3] = INIT_DATA_h3;
	c->h[4] = INIT_DATA_h4;
	c->Nl = 0;
	c->Nh = 0;
	c->FlagInWord = 0;
	c->msgIndex = 0;
	c->isTooMang = 0;
	memset(c->data, 0, 64);

	return 1;
}

int SHA1_GetMsgBits(SHA1_Context *c)
{
	int a = 0;

	if ((NULL == c) || (0 != c->isTooMang))
	{
		return -1;
	}

	a = sizeof(unsigned long) * 8 * c->msgIndex + 8 * c->FlagInWord;

	return a;
}

int SHA1_Clear_data(SHA1_Context *c)
{
	if (NULL == c)
	{
		return -1;
	}

	memset(c->data, 0, 64);

	c->msgIndex = 0;

	c->FlagInWord = 0;

	return 1;
}

int SHA1_One(SHA1_Context *c)
{
	unsigned long AE[5];
	unsigned long w[80];
	unsigned long temp = 0;
	int t = 0;

	if ((NULL == c) || (0 != c->isTooMang))
	{
		return -1;
	}

	for (t = 0; t < 16; ++t)
	{
		w[t] = c->data[t];
	}

	for (t = 16; t < 80; ++t)
	{
		w[t] = SHA1CircularShift(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]);
	}

	for (t = 0; t < 5; ++t)
	{
		AE[t] = c->h[t];
	}

	for (t = 0; t <= 79; ++t)
	{
		temp = SHA1CircularShift(5, AE[0]) + (*ft[t / 20])(AE[1], AE[2], AE[3]) + AE[4] + w[t] + SHA1_Kt[t / 20];
		AE[4] = AE[3];
		AE[3] = AE[2];
		AE[2] = SHA1CircularShift(30, AE[1]);
		AE[1] = AE[0];
		AE[0] = temp;
	}

	for (t = 0; t < 5; ++t)
	{
		c->h[t] += AE[t];
	}

	SHA1_Clear_data(c);

	return 1;
}

int SHA1_PadMessage(SHA1_Context *c)
{
	int msgBits = -1;

	if ((NULL == c) || (0 != c->isTooMang))
	{
		return -1;
	}

	msgBits = SHA1_GetMsgBits(c);

	if (440 < msgBits)
	{
		c->data[c->msgIndex++] |= (1 << (8 * (4 - c->FlagInWord) - 1));
		c->FlagInWord = 0;

		while (c->msgIndex < 16)
		{
			c->data[c->msgIndex++] = 0;
		}

		SHA1_One(c);

		while (c->msgIndex < 14)
		{
			c->data[c->msgIndex++] = 0;
		}

	}
	else
	{
		c->data[c->msgIndex++] |= (1 << (8 * (4 - c->FlagInWord) - 1));
		c->FlagInWord = 0;

		while (c->msgIndex < 14)
		{
			c->data[c->msgIndex++] = 0;
		}
	}

	while (c->msgIndex < 14)
	{
		c->data[c->msgIndex++] = 0;
	}

	c->data[c->msgIndex++] = c->Nh;

	c->data[c->msgIndex++] = c->Nl;

	return 1;
}

static int SHA1_Update(SHA1_Context *c, const unsigned char *chBuff, unsigned int n)
{
	unsigned int lastBytes = 0;
	unsigned int temp = 0;
	unsigned int i = 0;
	unsigned int tempBits = 0;

	if (!c || !chBuff || !n || c->isTooMang)
	{
		return -1;
	}

	if (n > strlen((char *)chBuff))
	{
		n = strlen((char *)chBuff);
	}

	if (c->FlagInWord > 0)
	{
		temp = (unsigned int)(4 - c->FlagInWord) < n ? (unsigned int)(4 - c->FlagInWord) : n;

		for (i = temp; i > 0; --i)
		{
			c->data[c->msgIndex] |= ((unsigned long)chBuff[temp - i]) << (3 - c->FlagInWord++) * 8;
		}

		tempBits = c->Nl;

		c->Nl += 8 * temp;

		if (tempBits > c->Nl)
		{
			++(c->Nh);

			if (c->Nh == 0)
			{
				c->isTooMang = 1;
			}
		}

		if ((c->FlagInWord) / 4 > 0)
		{
			++(c->msgIndex);
		}

		c->FlagInWord = c->FlagInWord % 4;

		if (c->msgIndex == 16)
		{
			SHA1_One(c);
		}
	}

	chBuff += temp;

	n -= temp;

	if (n >= 4)
	{
		for (i = 0; i <= n - 4; i += 4)
		{
			c->data[c->msgIndex] |= ((unsigned long)chBuff[i]) << 24;
			c->data[c->msgIndex] |= ((unsigned long)chBuff[i + 1]) << 16;
			c->data[c->msgIndex] |= ((unsigned long)chBuff[i + 2]) << 8;
			c->data[c->msgIndex] |= ((unsigned long)chBuff[i + 3]);
			++(c->msgIndex);

			tempBits = c->Nl;
			c->Nl += 32;

			if (tempBits > c->Nl)
			{
				c->Nh++;

				if (c->Nh == 0)
				{
					c->isTooMang = 1;
				}
			}

			if (c->msgIndex == 16)
			{
				SHA1_One(c);
			}
		}
	}

	if (n > 0 && n % 4 != 0)
	{
		lastBytes = n - i;

		switch (lastBytes)
		{

			case 3:
				c->data[c->msgIndex] |= ((unsigned long)chBuff[i + 2]) << 8;

			case 2:
				c->data[c->msgIndex] |= ((unsigned long)chBuff[i + 1]) << 16;

			case 1:
				c->data[c->msgIndex] |= ((unsigned long)chBuff[i]) << 24;
		}

		c->FlagInWord = lastBytes;

		tempBits = c->Nl;
		c->Nl += 8 * lastBytes;

		if (tempBits > c->Nl)
		{
			++(c->Nh);

			if (0 == c->Nh)
			{
				c->isTooMang = 1;
			}
		}

		if (16 == c->msgIndex)
		{
			SHA1_One(c);
		}
	}

	return 1;
}

static int SHA1_Final(SHA1_Context *c, unsigned char * md)
{
	int i = 0;

	if ((NULL == md) || (NULL == c) || (c->isTooMang))
	{
		return -1;
	}

	SHA1_PadMessage(c);

	SHA1_One(c);

	for (i = 0; i < 5; ++i)
	{
		md[4 * i] = (unsigned char)((c->h[i] & 0xff000000) >> 24);
		md[4 * i + 1] = (unsigned char)((c->h[i] & 0x00ff0000) >> 16);
		md[4 * i + 2] = (unsigned char)((c->h[i] & 0x0000ff00) >> 8);
		md[4 * i + 3] = (unsigned char)(c->h[i] & 0x000000ff);
	}

	return 1;
}

int SHA1_String(const unsigned char* inputString, unsigned long len, unsigned char* pOutSHA1Buf)
{
	int rt = -1;
	SHA1_Context c;

	if ((NULL == inputString) || (NULL == pOutSHA1Buf))
	{
		return -1;
	}

	rt = SHA1_Init(&c);

	if (-1 == rt)
	{
		return -1;
	}

	SHA1_Update(&c, inputString, len);

	SHA1_Final(&c, pOutSHA1Buf);
	SHA1_Clear_data(&c);
	return 1;
}


int SHA1_String_Compare(const unsigned char* inputString, unsigned long len, const unsigned char* pOutSHA1Buf)
{
	unsigned char buff[SHA1_SIZE_BYTE] = { 0 };
	int rt = -1;
	int i = 0;

	rt = SHA1_String(inputString, len, buff);

	if (1 == rt)
	{
		for (i = 0; i < SHA1_SIZE_BYTE; ++i)
		{
			if (buff[i] != pOutSHA1Buf[i])
			{
				return -1;
			}
		}

		return 1;
	}
	else
	{
		return -1;
	}
}

int SHA1_File(const char* filePath, unsigned char *buff)
{
	int rt = -1;
	FILE *file = NULL;
	SHA1_Context context;
	int len = 0;
	unsigned char buffer[0x0400] = { 0 };

	file = fopen(filePath, "rb");

	if (NULL == file)
	{
		return -1;
	}
	else
	{
		rt = SHA1_Init(&context);

		if (-1 == rt)
		{
			fclose(file);

			return -1;
		}

		while (len = fread(buffer, 1, 1024, file))
		{
			rt = SHA1_Update(&context, buffer, len);

			if (-1 == rt)
			{
				fclose(file);

				return -1;
			}
		}

		rt = SHA1_Final(&context, buff);

		fclose(file);

		return rt;
	}
}

int SHA1_File_Compare(const char* filePathA, const char *filePathB)
{
	char hashValueA[SHA1_SIZE_BYTE] = { 0 };
	char hashValueB[SHA1_SIZE_BYTE] = { 1 };
	int rt = -1;
	int i = 0;

	if ((NULL == filePathA) || (NULL == filePathB))
	{
		return -1;
	}

	rt = SHA1_File(filePathA, (unsigned char *)hashValueA);

	if (1 == rt)
	{
		rt = SHA1_File(filePathB, (unsigned char *)hashValueB);

		if (1 == rt)
		{
			for (i = 0; i < SHA1_SIZE_BYTE; ++i)
			{
				if (hashValueA[i] != hashValueB[i])
				{
					return -1;
				}
			}

			return 1;
		}
		else
		{
			return -1;
		}
	}
	else
	{
		return -1;
	}
}


/**
* @file SHA1.h
* @brief SHA-1 coden take from gnupg 1.3.92.
* @author Don
* @date 2011-7-28 22:49:55
* @version
* <pre><b>copyright: </b></pre>
* <pre><b>email: </b>[email protected]</pre>
* <pre><b>company:
* <pre><b>All rights reserved.</b></pre>
* <pre><b>modification:</b></pre>
* <pre>Write modifications here.</pre>
*/
#ifndef _USER_SHA1_H
#define _USER_SHA1_H

#include <stdio.h>
#include <memory.h>



#define SHA1_SIZE_BYTE 20

	/**
	* @brief SHA1_String
	*
	* Detailed description.
	* @param[in] inputString 要进行处理的无符号字符串指针
	* @param[in] len 要处理的信息长度,n<= strlen(p);
	* @param[out] pOutSHA1Buf 输出摘要信息,长度为20的 unsigned char ,共160 bits
	* @return int
	*/
	int SHA1_String(const unsigned char* inputString, unsigned long len, unsigned char* pOutSHA1Buf);

	/**
	* @brief SHA1_String_Compare
	*
	* Detailed description.
	* @param[in] inputString
	* @param[in] len
	* @param[in] pOutSHA1Buf
	* @return int
	*/
	int SHA1_String_Compare(const unsigned char* inputString, unsigned long len, const unsigned char* pOutSHA1Buf);

	/**
	* @brief SHA1_File
	*
	* Detailed description.
	* @param[in] filePath 要计算MD5的文件的路径
	* @param[in] buff 输出的MD5值,该缓冲区大小应为MD5_SIZE_BYTE
	* @return int
	*/
	int SHA1_File(const char* filePath, unsigned char* buff);

	/**
	* @brief SHA1_File_Compare
	*
	* Detailed description.
	* @param[in] filePathA 要对比MD5的第一个文件的路径
	* @param[in] filePathB 要对比MD5的第二个文件的路径
	* @return int
	*/
	int SHA1_File_Compare(const char* filePathA, const char* filePathB);



#endif /**< _USER_SHA1_H */

//BASE64.c

#include "StdAfx.h"
#include "base64.h"
#include <stdio.h>
#include <string.h>

// 全局常量定义
const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const char padding_char = '=';

/*编码代码
* const unsigned char * sourcedata, 源数组
* char * base64 ,码字保存
*/
int base64_encode(const unsigned char * sourcedata, unsigned int datalength, char * base64)
{
	int i = 0, j = 0;
	unsigned char trans_index = 0;    // 索引是8位,但是高两位都为0
	//const int datalength = strlen((const char*)sourcedata);
	for (; i < datalength; i += 3){
		// 每三个一组,进行编码
		// 要编码的数字的第一个
		trans_index = ((sourcedata[i] >> 2) & 0x3f);
		base64[j++] = base64char[(int)trans_index];
		// 第二个
		trans_index = ((sourcedata[i] << 4) & 0x30);
		if (i + 1 < datalength){
			trans_index |= ((sourcedata[i + 1] >> 4) & 0x0f);
			base64[j++] = base64char[(int)trans_index];
		}
		else{
			base64[j++] = base64char[(int)trans_index];

			base64[j++] = padding_char;

			base64[j++] = padding_char;

			break;   // 超出总长度,可以直接break
		}
		// 第三个
		trans_index = ((sourcedata[i + 1] << 2) & 0x3c);
		if (i + 2 < datalength){ // 有的话需要编码2个
			trans_index |= ((sourcedata[i + 2] >> 6) & 0x03);
			base64[j++] = base64char[(int)trans_index];

			trans_index = sourcedata[i + 2] & 0x3f;
			base64[j++] = base64char[(int)trans_index];
		}
		else{
			base64[j++] = base64char[(int)trans_index];

			base64[j++] = padding_char;

			break;
		}
	}

	base64[j] = '\0';

	return 0;
}


/** 在字符串中查询特定字符位置索引
* const char *str ,字符串
* char c,要查找的字符
*/
inline int num_strchr(const char *str, char c) // 
{
	const char *pindex = strchr(str, c);
	if (NULL == pindex){
		return -1;
	}
	return pindex - str;
}
/* 解码
* const char * base64 码字
* unsigned char * dedata, 解码恢复的数据
*/
int base64_decode(const char * base64, unsigned char * dedata)
{
	int i = 0, j = 0;
	int trans[4] = { 0, 0, 0, 0 };
	for (; base64[i] != '\0'; i += 4){
		// 每四个一组,译码成三个字符
		trans[0] = num_strchr(base64char, base64[i]);
		trans[1] = num_strchr(base64char, base64[i + 1]);
		// 1/3
		dedata[j++] = ((trans[0] << 2) & 0xfc) | ((trans[1] >> 4) & 0x03);

		if (base64[i + 2] == '='){
			continue;
		}
		else{
			trans[2] = num_strchr(base64char, base64[i + 2]);
		}
		// 2/3
		dedata[j++] = ((trans[1] << 4) & 0xf0) | ((trans[2] >> 2) & 0x0f);

		if (base64[i + 3] == '='){
			continue;
		}
		else{
			trans[3] = num_strchr(base64char, base64[i + 3]);
		}

		// 3/3
		dedata[j++] = ((trans[2] << 6) & 0xc0) | (trans[3] & 0x3f);
	}

	dedata[j] = '\0';

	return 0;
}

//BASE64.h

#ifndef base64_h
#define base64_h



int base64_encode(const unsigned char * sourcedata, unsigned int datalength, char * base64);

#endif /* base64_h */

//测试

IHttpServer *mHttpServer;
HttpServerListernet *mHttpServerListernet;

this->mHttpServerListernet = new HttpServerListernet();
			this->mHttpServer = HP_Create_HttpServer(this->mHttpServerListernet);
			if (this->mHttpServer != nullptr)
			{
				
				if (this->mHttpServer->Start(L"0.0.0.0", 4567) == FALSE)
				{
					int error = this->mHttpServer->GetLastError();
					System::Windows::Forms::MessageBox::Show("初始化web服务器失败,错误代码:" + error, "错误", System::Windows::Forms::MessageBoxButtons::OK,
						System::Windows::Forms::MessageBoxIcon::Error);

				}
			}
			else
			{
				System::Windows::Forms::MessageBox::Show("初始化 mHttpServer 失败!", "错误", System::Windows::Forms::MessageBoxButtons::OK,
					System::Windows::Forms::MessageBoxIcon::Error);
			}

html_base_path:web网页目录,默认打开里面的index.html文件

发布了143 篇原创文章 · 获赞 370 · 访问量 81万+

猜你喜欢

转载自blog.csdn.net/cp1300/article/details/85239118
今日推荐