mysocket.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 + -