欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

mysocket.cpp

AsynSocketDemo.rar网络代码,可以设置代理,ssl加密. AsynSocketDemo.rar网络代码,可以设置代理,ssl加密. AsynSocketDemo.rar网络代码,
CPP
字号:
// MySocket.cpp: Implementierung der Klasse CMySocket.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "stdafx.h"
#include "MySocket.h"

#include <sstream>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////

char e[3] = "@/";
/**************************************************************
功能:从 src 中找出前面的字母、数字等内含,即一个网页地址中主机名后面的部分
***************************************************************/
void GetAfterPosWithSlash(char * src, char ** d)
{
char * x;
if(src) x = src;
else {*d = 0; return ;}
while(x) {
if(*x >= 'a' && *x <= 'z') {x++; continue;}
else if(*x >= 'A' && *x <= 'Z') {x++; continue;}
else if(*x >= '0' && *x <= '9') {x++; continue;}
else if(*x == '.' || *x == '-' || *x == '_' || *x == '=') {x++; continue;}
else if(*x == ':' || *x == '/' || *x == '?' || *x == '&') {x++; continue;}
else {break;}
}
if(x) *d = x;
else *d = 0;
}

/**************************************************************
功能:为 myanchor 分配 len 大小的内存
***************************************************************/
void GetMemory(char ** myanchor, int len)
{
if(!(*myanchor)) (*myanchor) = (char *)malloc(len + 1);
else (*myanchor) = (char *)realloc((void *)(*myanchor), len + 1);
memset((*myanchor), 0, len + 1);
}



/**************************************************************
功能:在字符串 s 里搜索 x 字符,并设置指针 d 指向该位置
***************************************************************/
void Rstrchr(char * s, int x, char ** d)
{
        int len = strlen(s) - 1;
        while(len >= 0)        {
                if(x == s[len]) {(*d) = s + len; return;}
                len--;
        }
        (*d) = 0;
}
/**************************************************************
功能:从字符串 src 中分析出网站地址和端口,并得到文件和目录
***************************************************************/
int GetHost( char * src, char ** web, char ** file, unsigned short * port, char ** dir)  {
  char * pA, * pB, * pC;
  int len;

  *port = 0;
  if(!(*src))  return -1;
  pA = src;
  if(!strncmp(pA, "http://", strlen("http://")))  pA = src+strlen("http://");
  /* else if(!strncmp(pA, "https://", strlen("https://")))  pA = src+strlen("https://"); */
  else return 1;
  pB = strchr(pA, '/');
  if(pB)  {
    len = strlen(pA) - strlen(pB);
    GetMemory(web, len);
    memcpy((*web), pA, len);
    if(*(pB+1))  {
      Rstrchr(pB + 1, '/', &pC);
      if(pC) len = strlen(pB + 1) - strlen(pC);
      else len = 0;
      if(len > 0) {
        GetMemory(dir, len);
        memcpy((*dir), pB + 1, len);

        if(pC + 1) {
          len = strlen(pC + 1);
          GetMemory(file, len);
          memcpy((*file), pC + 1, len);
        }
        else {
          len = 1;
          GetMemory(file, len);
          memcpy((*file), e, len);
        }
      }
      else {
        len = 1;
        GetMemory(dir, len);
        memcpy((*dir), e + 1, len);

        len = strlen(pB + 1);
        GetMemory(file, len);
        memcpy((*file), pB + 1, len);
      }
    }
    else {
      len = 1;
      GetMemory(dir, len);
      memcpy((*dir), e + 1, len);

      len = 1;
      GetMemory(file, len);
      memcpy((*file), e, len);
    }
  }
  else  {
    len = strlen(pA);
    GetMemory(web, len);
    memcpy((*web), pA, strlen(pA));
    len = 1;
    GetMemory(dir, len);
    memcpy((*dir), e + 1, len);
    len = 1;
    GetMemory(file, len);
    memcpy((*file), e, len);
  }

  pA = strchr((*web), ':');
  if(pA)
  {
	  *port = atoi(pA + 1);
	  *pA = 0;
  }
  else *port = 80;

  return 0;
}

CMySocket::CMySocket(CEdit *pResponse, t_HashList *pSslTrustedCertHashList)
{
	ASSERT(pResponse);
	ASSERT(pSslTrustedCertHashList);

	m_pResponse = pResponse;
	m_pSslTrustedCertHashList = pSslTrustedCertHashList;

	m_pProxyLayer = new CAsyncProxySocketLayer;
	m_pSslLayer = new CAsyncSslSocketLayer;

	m_downloadLength = 0;
	m_headSize = 0;

	m_state = HTTP_STATE_CONNECTING;
	m_beginTick = ::GetTickCount();


	//
	m_urlPath		= "";
	m_host			= "";
	m_port			= 0;
	m_firstRange	= 0;
	m_cookie		= "";
	m_referer		= "";
	m_userAgent		= "";
	m_user			= "";
	m_password		= "";
	m_extraHeader	= "";
}

CMySocket::~CMySocket()
{
	Close();
	delete m_pSslLayer;
	delete m_pProxyLayer;
}

void CMySocket::OnReceive(int nErrorCode)
{
	if (nErrorCode)
	{
		AfxMessageBox("Fatal error! Network subsystem failed!", MB_ICONSTOP);
		Close();
		return;
	}

	char buffer[16*1024+1];
	int res=Receive(&buffer, 16*1024);
	if (res==SOCKET_ERROR || !res)
	{
		if (GetLastError()!=WSAEWOULDBLOCK || !res)
		{
			AddStringToLog(_T("Error: Connection has been closed."));
			return;
		}
		return;
	}
	buffer[res]=0;
	m_downloadLength += res;
	//AddStringToLog(_T("Server reply:"));
	//AddStringToLog(buffer);

	//Close();


	if( m_state == HTTP_STATE_CONNECTED )
	{
		//分析HTTPHEAD		
		/*if( memcmp( buffer, "HTTP/1.1 302 RedirectConnection",31 ) )
		{
			string strHttpHead = buffer;
			int pos = strHttpHead.find("Location:");
			if( string::npos != pos && strHttpHead.length() > pos+9 )
			{
				this->m_referer = strHttpHead.substr( pos+1,strHttpHead.length() );
				pos = this->m_referer.find("\r\n");
				if( string::npos != pos )
				{
					this->m_referer = this->m_referer.substr( 0, pos );
				}
			}
			sendRequest( this->m_urlPath.c_str(), m_host.c_str(), this->m_port, m_firstRange, m_cookie.c_str(), m_referer.c_str(), m_userAgent.c_str(), m_user.c_str(), m_password.c_str(), m_extraHeader.c_str() );
			return ;
		}*/
		m_contentLength = parseHttpHead( buffer, res, m_headSize );
		if( 0 != m_contentLength )
			m_state = HTTP_STATE_GETDATAED; 
	}
	else if( m_state == HTTP_STATE_GETDATAED )
	{
		if( m_downloadLength >= m_headSize + m_contentLength )
		{
			CString str;
			DWORD t = ::GetTickCount();
			int s = (m_downloadLength*1024)/( t - m_beginTick);
			str.Format("接收到足够的数据tick:%d  速度:%d  收到数据大小为:%d ", t, s, m_downloadLength);
			AddStringToLog( str.GetBuffer(0));
		}
	}
	CString strTick;
	DWORD t = ::GetTickCount();
	if( 0 != t-m_beginTick )
	{
		strTick.Format("\n====接收%d字节数据用时%d,平均速度:%d", res, t-this->m_lastTick, m_downloadLength*1000/(t-m_beginTick));
		ATLTRACE( strTick.GetBuffer(0));
	}
	m_lastTick = t;

}

int CMySocket::parseHttpHead( string data, int size, int &headSize )
{
	headSize = data.find("\r\n\r\n") + 4;
	int pos = data.find("Content-Length:");
	if( string::npos != pos && data.length() > pos+15 )
	{
		string str = data.substr( pos+15, data.length());
		int pos1 = str.find("\r\n");
		string strContentLength = str.substr( 0, pos1);
		return atoi( strContentLength.c_str() );
	}
	return 0;
}

void CMySocket::OnConnect(int nErrorCode)
{
	if (nErrorCode)
	{
		AddStringToLog("Error: Could not connect to server.");
		Close();
	}
	else
		AddStringToLog("Status: Connected to server.");
	m_state = HTTP_STATE_CONNECTED;

	//sendRequest("/www.codeexchange.net/codes/downloads55/sourcecode/game/25811217Mir2Ei1.rar", "source.cenxi.net", 8000, 0, "", "http://source.cenxi.net:8000/www.codeexchange.net/dl_nolog.asp-id=188892");
	sendRequest( this->m_urlPath.c_str(), m_host.c_str(), this->m_port, m_firstRange, m_cookie.c_str(), m_referer.c_str(), m_userAgent.c_str(), m_user.c_str(), m_password.c_str(), m_extraHeader.c_str() );
	m_lastTick = ::GetTickCount();
	CString str;
	m_beginTick = ::GetTickCount();
	str.Format("开始tick:%d", m_beginTick);
	AddStringToLog( str.GetBuffer(0) );
}
void CMySocket::OnClose(int nErrorCode)
{
	if( nErrorCode )
	{
		Close();
	}
	
	CString str;
	str.Format("关闭tick:%d 收到数据大小为:%d",::GetTickCount(), m_downloadLength);
	AddStringToLog( str.GetBuffer(0));
	//MessageBox( NULL, str, "", 0);
}

int CMySocket::OnLayerCallback(const CAsyncSocketExLayer *pLayer, int nType, int nParam1, int nParam2)
{
	ASSERT(pLayer);
	if (nType==LAYERCALLBACK_STATECHANGE)
	{
		CString str;
		if (pLayer==m_pProxyLayer)
			str.Format(_T("Layer Status: m_pProxyLayer changed state from %d to %d"), nParam2, nParam1);
		else if (pLayer==m_pSslLayer)
			str.Format(_T("Layer Status: m_pSslLayer changed state from %d to %d"), nParam2, nParam1);
		else
			str.Format(_T("Layer Status: Layer @ %d changed state from %d to %d"), pLayer, nParam2, nParam1);
		AddStringToLog(str);
		return 1;
	}
	else if (nType == LAYERCALLBACK_LAYERSPECIFIC)
	{
		if (pLayer == m_pProxyLayer)
		{
			switch (nParam1)
			{
			case PROXYERROR_NOCONN:
				AddStringToLog(_T("Proxy error: Can't connect to proxy server."));
				break;
			case PROXYERROR_REQUESTFAILED:
				AddStringToLog(_T("Proxy error: Proxy request failed, can't connect through proxy server."));
				if (nParam2)
					AddStringToLog((LPCTSTR)nParam2);
				break;
			case PROXYERROR_AUTHTYPEUNKNOWN:
				AddStringToLog(_T("Proxy error: Required authtype reported by proxy server is unknown or not supported."));
				break;
			case PROXYERROR_AUTHFAILED:
				AddStringToLog(_T("Proxy error: Authentication failed"));
				break;
			case PROXYERROR_AUTHNOLOGON:
				AddStringToLog(_T("Proxy error: Proxy requires authentication"));
				break;
			case PROXYERROR_CANTRESOLVEHOST:
				AddStringToLog(_T("Proxy error: Can't resolve host of proxy server."));
				break;
			default:
				AddStringToLog(_T("Proxy error: Unknown proxy error") );
			}
		}
		else if (pLayer == m_pSslLayer)
		{
			switch (nParam1)
			{
			case SSL_INFO:
				switch (nParam2)
				{
				case SSL_INFO_ESTABLISHED:
					AddStringToLog(_T("SSL connection established"));
					break;
				}
				break;
			case SSL_FAILURE:
				switch (nParam2)
				{
				case SSL_FAILURE_UNKNOWN:
					AddStringToLog(_T("Unknown error in SSL layer"));
					break;
				case SSL_FAILURE_ESTABLISH:
					AddStringToLog(_T("Could not establish SSL connection"));
					break;
				case SSL_FAILURE_LOADDLLS:
					AddStringToLog(_T("Failed to load OpenSSL DLLs"));
					break;
				case SSL_FAILURE_INITSSL:
					AddStringToLog(_T("Failed to initialize SSL"));
					break;
				case SSL_FAILURE_VERIFYCERT:
					AddStringToLog(_T("Could not verify SSL certificate"));
					break;
				}
				break;
			case SSL_VERBOSE_INFO:
			case SSL_VERBOSE_WARNING:
				AddStringToLog((char *)nParam2);
				break;
			case SSL_VERIFY_CERT:
				t_SslCertData *pData = new t_SslCertData;
				if (m_pSslLayer->GetPeerCertificateData(*pData))
				{
					/* Do a first validation of the certificate here, return 1 if it's valid
					 * and 0 if not.
					 * If still unsure, let the user decide and return 2;
					 */
					for (t_HashList::iterator iter = m_pSslTrustedCertHashList->begin(); iter != m_pSslTrustedCertHashList->end(); iter++)
						if (!memcmp(pData->hash, *iter, 20))
							return 1;

					
					AfxGetMainWnd()->PostMessage(WM_USER, (WPARAM)pData, 0);
					return 2;
				}
				else
					return 1;
			}
		}
	}

	return 1;
}

void CMySocket::AddStringToLog(LPCTSTR pszString)
{
	CString str;
	m_pResponse->GetWindowText(str);
	str+=pszString;
	str+=_T("\r\n");
	m_pResponse->SetWindowText(str);
}

BOOL CMySocket::AddSslCertHashToTrustedList(unsigned char * pHash)
{
	if (!pHash)
		return FALSE;
	for (t_HashList::iterator iter = m_pSslTrustedCertHashList->begin(); iter != m_pSslTrustedCertHashList->end(); iter++)
		if (!memcmp(pHash, *iter, 20))
			return FALSE;

	unsigned char* pData = new unsigned char[20];
	memcpy(pData, pHash, 20);
	m_pSslTrustedCertHashList->push_back(pData);
	
	return TRUE;
}

char * basic_authentication_encode (const char *user, const char *passwd);
string str_ultoa(unsigned long l)
{
	ostringstream ss;
	ss << l;
	return ss.str();
}

void CMySocket::sendRequest( string urlPath, string host, unsigned short port,  __int64 firstRange, string cookie ,  \
										  string referer, string userAgent, string user, string password,  \
										  string extraHeader)
{
	string req;
	req = "GET ";

	req += urlPath;
	req += " HTTP/1.0\r\n";
	req += "Host: " + host;

	if(port != 80) {
		char tmpbuf[50];
		wsprintf(tmpbuf, "%d", port);
		req += ":";
		req += tmpbuf;
	}
	req += "\r\n";

	if(cookie.size() > 0)
		req += "Cookie: " + cookie + "\r\n";

	if(firstRange > 0) {
		req += "Range: bytes=";
		req += str_ultoa(firstRange) + "-";
		req += "\r\n";
	}


	if(referer.size() > 0)
		req += "Referer: " + referer + "\r\n";

	if(userAgent.size() > 0)
		req += "User-Agent: " + userAgent + "\r\n";
	else
		req += "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\n";

	if(user.size() > 0) {
		req += "Authorization: ";
		char* pass = basic_authentication_encode(user.c_str(), password.c_str());
		req += pass;
		free(pass);
		req += "\r\n";
	}

	if(extraHeader.size() > 0)
		req += extraHeader;
	
	req += "Accept: */*\r\n"
			"Pragma: no-cache\r\n"
			"Cache-Control: no-cache\r\n"
			"Connection: close\r\n"
			"\r\n";

	
	Send(req.c_str(), req.size());
	AddStringToLog( req.c_str() );
}

bool CMySocket::init( string url, __int64 firstRange, string cookie, string referer, string userAgent, string user, string password, string extraHeader)
{
	if( !parseURL( url, m_urlPath, m_host, m_fileName, m_port ) )
		return false;
	if( m_urlPath.find("/") != 0 )
		m_urlPath = "/" + m_urlPath;

	m_firstRange = firstRange;
	m_cookie	 = cookie;
	m_referer	 = referer;
	m_userAgent	 = userAgent;
	m_user		 = user;
	m_password	 = password;
	m_extraHeader= extraHeader;

	return true;
}

bool CMySocket::parseURL( string _url, string &_urlPath, string &_host, string _fileName, unsigned short &_port )
{
	char url[2048];
	char *urlPath = new char[1024];
	char *host    = new char[1024];
	char *fileName= new char[1024];
	unsigned short port;
	memset( url, 0, sizeof( url));
	memcpy( url, _url.c_str(), _url.size() );

	if( -1 == GetHost( (char *)url, (char **)&host, (char **)&fileName, &port, (char **)&urlPath ) )
	{
		delete []urlPath;
		delete []host;
		delete []fileName;

		return false;
	}
	_urlPath = urlPath;
	_urlPath += "/";
	_urlPath += fileName;
	_host    = host;
	_port	 = port;
	_fileName = fileName;

	delete []urlPath;
	delete []host;
	delete []fileName;
	return true;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -