HttpRequest.cpp
资源名称:p2p_vod.rar [点击查看]
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:17k
源码类别:
P2P编程
开发平台:
Visual C++
- /*
- * Openmysee
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
- // HttpDownload.cpp: implementation of the HttpDownload class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include <LIMITS.H>
- #include <TCHAR.H>
- #include "HttpRequest.h"
- #include <stdlib.h>
- #include <stdio.h>
- #ifdef _MYDEBUG
- #undef THIS_FILE
- static TCHAR THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- BOOL HttpRequest::GetCookieEx(LPCTSTR lpszUrlName, LPCTSTR lpszCookieDataName, LPTSTR lpszCookieData, LPDWORD lpdwSize)
- {
- DWORD len = 0;
- InternetGetCookie(lpszUrlName, NULL, NULL, &len);
- if(len == 0)
- {
- return FALSE; //no cookie exist
- }
- len += 10;
- LPTSTR bufcookiedata = new TCHAR[len];
- memset(bufcookiedata, 0, sizeof(TCHAR)*len);
- if(InternetGetCookie(lpszUrlName, NULL, bufcookiedata, &len) != TRUE)
- {
- delete[] bufcookiedata;
- return FALSE;
- }
- bool parseOK = false;
- while(1)
- {
- LPTSTR datastart = _tcsstr(bufcookiedata, lpszCookieDataName);
- if(datastart == NULL)
- return FALSE;
- LPTSTR indexspace = NULL;
- LPTSTR indexequal = NULL;
- indexequal = _tcschr(datastart, _T('='));
- if(indexequal == NULL)
- break;
- indexequal++;
- indexspace = _tcschr(datastart, _T(';'));
- if(indexspace == NULL) //这是最后一个data
- indexspace = _tcschr(datastart, 0);
- assert(indexspace > indexequal);
- DWORD m_actuallen = indexspace - indexequal + 1; //len + null terminnal
- assert(lpdwSize != NULL);
- if(lpszCookieData == NULL || *lpdwSize < m_actuallen)
- {
- *lpdwSize = m_actuallen;
- }
- else
- {
- memset(lpszCookieData, 0, sizeof(TCHAR)*(*lpdwSize));
- _tcsncpy(lpszCookieData, indexequal, indexspace - indexequal);
- }
- parseOK = true;
- break;
- }
- delete[] bufcookiedata;
- if(!parseOK)
- {
- return FALSE;
- }
- else
- return TRUE;
- }
- //HTTP信标
- #define HTTP_REQUEST_LIMIT_NAME _T("_GAOV_HTTP_REQUEST_LIMIT")
- static HANDLE m_hSemaphore = CreateSemaphore(NULL, 5, 5, HTTP_REQUEST_LIMIT_NAME);
- int HttpRequest::b_useproxy = 0;
- TCHAR HttpRequest::m_proxystr[256] = _T("");
- #define INTERNET_CONNECT_ADAGENT _T("Mysee_Client")
- void HttpRequest::SetProxyName(LPCWSTR s)
- {
- #ifdef _UNICODE
- wcscpy(m_proxystr, s);
- #else
- char* m_innerbufferA = new char[1024];
- WideCharToMultiByte(CP_ACP, 0, s, -1, m_innerbufferA, 1024, NULL, NULL);
- strcpy(m_proxystr, m_innerbufferA);
- delete[] m_innerbufferA;
- #endif
- }
- void HttpRequest::SetProxyName(LPCSTR s)
- {
- #ifdef _UNICODE
- WCHAR* m_innerbufferW = new WCHAR[1024];
- MultiByteToWideChar(CP_ACP, 0, s, -1, m_innerbufferW, 1024);
- wcscpy(m_proxystr, m_innerbufferW);
- delete[] m_innerbufferW;
- #else
- strcpy(m_proxystr, s);
- #endif
- }
- HttpRequest::HttpRequest()
- {
- Connect_timeout = 60000;
- Request_timeout = 120000;
- recvBuf = NULL;
- // HSO = NULL;
- m_hInternet = NULL;
- errorcode = 0;
- // InitializeCriticalSection(&m_hSync);
- for(int j = 0; j<EVENT_SERIES; j++)
- m_hEvent[j] = CreateEvent(NULL, TRUE, FALSE, NULL);
- ResetEvent(m_hEvent[0]);
- fWide = FALSE;
- }
- BOOL HttpRequest::Create(UINT cto, UINT rto, BOOL wide)
- {
- // b_userStop = FALSE;
- fWide = wide;
- h_File = NULL;
- Connect_timeout = cto;
- Request_timeout = rto;
- errorcode = 0;
- m_dwOffset = m_dwOffsetEnd = UINT_MAX;
- // DWORD wtmp;
- // ResetEvent(m_hEvent[0]);
- // ::CreateThread(NULL, 0, InitialCallback, this, 0, &wtmp);
- // WaitForSingleObject(m_hEvent[0], INFINITE);
- // if(errorcode != 0)return FALSE;
- return TRUE;
- }
- HttpRequest::~HttpRequest()
- {
- for(int j = 0; j<EVENT_SERIES;j++)
- CloseHandle(m_hEvent[j]);
- // DeleteCriticalSection(&m_hSync);
- if(recvBuf)delete[] recvBuf;
- }
- void HttpRequest::SetStopRequest()
- {
- SetEvent(m_hEvent[0]);
- }
- void HttpRequest::ResumeStopRequest()
- {
- ResetEvent(m_hEvent[0]);
- }
- UINT HttpRequest::WaitingEvent(DWORD timeout)
- {
- if((errorcode = GetLastError()) != ERROR_IO_PENDING)
- {
- return 1;
- }
- DWORD result = WaitForMultipleObjects(EVENT_SERIES, m_hEvent,
- FALSE, timeout);
- switch(result)
- {
- case WAIT_OBJECT_0: //外部中止
- errorcode = USER_STOP;
- return 1;
- case WAIT_OBJECT_0 + 1: //内部中止
- if(errorcode)
- return 1;
- else
- return 0;
- case WAIT_TIMEOUT: //连接超时
- errorcode = 32808;
- return 1;
- case WAIT_FAILED: //严重错误
- errorcode = ERROR_STOP;
- return 1;
- }
- return 1;
- }
- void HttpRequest::HDResetEvent()
- {
- for(int i = 1; i< EVENT_SERIES; i++)
- ResetEvent(m_hEvent[i]);
- }
- int HttpRequest::ReadStringEx()
- {
- if(recvBuf == NULL)return -1;
- if(readstrpos >= buflength)return -1;
- int oldpos = -1;
- if(fWide)
- {
- WCHAR* head = (WCHAR*) recvBuf;
- for(UINT i = readstrpos; (i*sizeof(WCHAR))<buflength; i++)
- {
- if(*(head + i) == L'n')break;
- }
- oldpos = readstrpos;
- readstrpos = i+1;
- if(i != readstrpos && *(head + i - 1) == L'r')
- *(head + i - 1) = L' ';
- *(head + i) = L' ';
- }
- else
- {
- char* head = (char*) recvBuf;
- for(UINT i = readstrpos; i<buflength; i++)
- {
- if(*(head + i) == 'n')break;
- }
- oldpos = readstrpos;
- readstrpos = i+1;
- if(i != readstrpos && *(head + i - 1) == 'r')
- *(head + i - 1) = ' ';
- *(head + i) = ' ';
- }
- return oldpos;
- }
- BOOL HttpRequest::ReadString(LPWSTR readstr)
- {
- int pos = HttpRequest::ReadStringEx();
- if(pos == -1)return FALSE;
- if(fWide)
- wcscpy(readstr,(LPCWSTR) recvBuf + pos);
- else
- {
- MultiByteToWideChar(CP_ACP, 0, (LPCSTR) recvBuf + pos, -1, readstr, 2048);
- }
- return TRUE;
- }
- BOOL HttpRequest::ReadString(LPSTR readstr)
- {
- int pos = HttpRequest::ReadStringEx();
- if(pos == -1)return FALSE;
- if(!fWide)
- strcpy(readstr,(LPCSTR) recvBuf + pos);
- else
- {
- WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) recvBuf + pos, -1, readstr, 2048, NULL, NULL);
- }
- return TRUE;
- }
- void HttpRequest::InitWrite(DWORD initialbufsize)
- {
- if(h_File)
- {
- if(GetFileSize(h_File, NULL) != -1)
- {
- m_dwOffset = 0;
- buflength = UINT_MAX;
- return; //a valid file
- }
- CloseHandle(h_File);
- h_File = NULL; //clear the invalid file handle and using inner buffer
- initialbufsize = 1024;
- }
- if(recvBuf)delete[] recvBuf;
- recvBuf = new BYTE[initialbufsize + 16];
- memset(recvBuf, 0, initialbufsize + 16);
- buflength = initialbufsize;
- m_dwOffset = 0;
- }
- BOOL HttpRequest::WriteBuffer(const BYTE* buf, const DWORD m_buflength)
- {
- if(h_File)
- {
- DWORD tmpLength = m_buflength;
- const BYTE* start = buf;
- while(tmpLength > 0)
- {
- DWORD tmp = 0;
- if(WriteFile(h_File, start, tmpLength, &tmp, NULL) == FALSE)
- {
- errorcode = GetLastError();
- return FALSE;
- }
- tmpLength -= tmp;
- start += tmp;
- }
- }
- else
- {
- if(m_dwOffset + m_buflength > buflength)
- {
- BYTE* tmp = new BYTE[buflength*3 + 16];
- memset(tmp, 0, buflength*3 + 16);
- memcpy(tmp, recvBuf, buflength);
- delete[] recvBuf;
- recvBuf = tmp;
- buflength = buflength* 3;
- }
- memcpy(recvBuf + m_dwOffset, buf, m_buflength);
- }
- m_dwOffset += m_buflength;
- return TRUE;
- }
- void HttpRequest::InternetCloseHandleAsync(HINTERNET Hcls)
- {
- if(Hcls == NULL)
- return;
- ResetEvent(m_hEvent[1]);
- if(!InternetCloseHandle(Hcls))
- {
- if(GetLastError() == ERROR_IO_PENDING)
- WaitForSingleObject(m_hEvent[1], INFINITE);
- }
- SetEvent(m_hEvent[1]);
- }
- static const TCHAR _defaultContentType[] = _T("Content-Type: application/x-www-form-urlencoded");
- DWORD WINAPI HttpRequest::InitialCallback(LPVOID params)
- {
- /* HttpRequest* pObj = (HttpRequest*) params;
- if(::InternetSetStatusCallback(pObj->HSO, AsyncInternetCallback) == INTERNET_INVALID_STATUS_CALLBACK)
- pObj->errorcode = 1;
- SetEvent(pObj->m_hEvent[0]);*/
- return 0;
- }
- void HttpRequest::MakeHeadMsg(BOOL post, LPTSTR buf)
- {
- LPTSTR start = buf;
- if(post)
- {
- _tcscpy(start, _defaultContentType);
- start += _tcslen(_defaultContentType);
- }
- if(h_File != NULL)
- {
- if(m_dwOffset != UINT_MAX)
- {
- _tcscpy(start, _T("rn"));
- if(m_dwOffsetEnd != UINT_MAX)
- _stprintf(start, _T("Range: bytes= %d-%d"), m_dwOffset, m_dwOffsetEnd);
- else
- _stprintf(start, _T("Range: bytes= %d-"), m_dwOffset);
- }
- }
- }
- BOOL HttpRequest::OpenRequest(LPCWSTR url, BOOL cache, LPCWSTR send)
- {
- #ifdef _UNICODE
- LPCWSTR purl = url;
- #else
- char* purl = new char[2048];
- WideCharToMultiByte(CP_ACP, 0, url, -1, purl, 2048, NULL, NULL);
- #endif
- size_t size = 0;
- if(send != NULL)
- size = wcslen(send) * sizeof(WCHAR);
- LPVOID pdata = (LPVOID) send;
- if(fWide == FALSE && send != NULL)
- {
- pdata = (LPVOID) new char[size];
- WideCharToMultiByte(CP_ACP, 0, send, -1, (char*) pdata, size, NULL, NULL);
- size = strlen((char*) pdata);
- }
- BOOL ret;
- ret = OpenRequestEx(purl, cache, pdata, size);
- #ifndef _UNICODE
- delete[] purl;
- #endif
- if(fWide == FALSE && send != NULL)
- delete[] pdata;
- return ret;
- }
- BOOL HttpRequest::OpenRequest(LPCSTR url, BOOL cache, LPCSTR send)
- {
- #ifndef _UNICODE
- LPCSTR purl = url;
- #else
- WCHAR* purl = new WCHAR[2048];
- MultiByteToWideChar(CP_ACP, 0, url, -1, purl, 2048);
- #endif
- DWORD size = 0;
- if(send != NULL)
- size = strlen(send);
- LPVOID pdata = (LPVOID) send;
- if(fWide != FALSE && send != NULL)
- {
- pdata = (LPVOID) new WCHAR[size];
- MultiByteToWideChar(CP_ACP, 0, send, -1, (WCHAR*) pdata, size);
- size = wcslen((WCHAR*) pdata)*sizeof(WCHAR);
- }
- BOOL ret;
- ret = OpenRequestEx(purl, cache, pdata, size);
- #ifdef _UNICODE
- delete[] purl;
- #endif
- if(fWide != FALSE && send != NULL)
- delete[] pdata;
- return ret;
- }
- BOOL HttpRequest::OpenRequestEx(LPCTSTR url, BOOL cache, const void* send, DWORD sendsize)
- {
- HANDLE hSemaphore = ::OpenSemaphore(SEMAPHORE_ALL_ACCESS | SEMAPHORE_MODIFY_STATE | SYNCHRONIZE
- , NULL, HTTP_REQUEST_LIMIT_NAME);
- BOOL funOK = FALSE;
- HINTERNET HSO = NULL;
- HINTERNET HIO = NULL;
- HINTERNET HQO = NULL;
- TCHAR* p_stN = new TCHAR[256];
- TCHAR* p_flN = new TCHAR[2048];
- TCHAR* p_bufstr = new TCHAR[1024];
- BYTE* p_buf = new BYTE[1024];
- DWORD port = 80;
- __try{
- if(!ParseURL(url, p_stN, p_flN, &port))
- {
- errorcode = ERROR_INTERNET_NAME_NOT_RESOLVED;
- __leave;
- }
- if(hSemaphore)
- {
- DWORD ret = ::WaitForSingleObject(hSemaphore, Connect_timeout*2);
- if(ret == WAIT_TIMEOUT)
- {
- errorcode = 12002;
- __leave;
- }
- else if(ret == WAIT_ABANDONED)
- {
- errorcode = USER_STOP;
- __leave;
- }
- }
- DWORD type; LPCTSTR proxystr = NULL;
- switch(b_useproxy)
- {
- case 0: type = INTERNET_OPEN_TYPE_DIRECT;break;
- case 1: type = INTERNET_OPEN_TYPE_PRECONFIG;break;
- case 2: type = INTERNET_OPEN_TYPE_PROXY;
- proxystr = m_proxystr;
- break;
- default: type = INTERNET_OPEN_TYPE_PRECONFIG;break;
- }
- HSO = ::InternetOpen(INTERNET_CONNECT_ADAGENT, type, proxystr, NULL, INTERNET_FLAG_ASYNC);
- if(HSO == NULL)
- {
- errorcode = GetLastError();
- __leave;
- }
- if(::InternetSetStatusCallback(HSO, AsyncInternetCallback) == INTERNET_INVALID_STATUS_CALLBACK)
- {
- errorcode = GetLastError();
- __leave;
- }
- HDResetEvent();
- HIO = InternetConnect(HSO, p_stN, (WORD) port , NULL,NULL,
- INTERNET_SERVICE_HTTP , 0, reinterpret_cast<DWORD>(this));
- if(HIO == NULL)
- {
- if(WaitingEvent(Connect_timeout))
- __leave;
- HIO = m_hInternet;
- }
- // 3.初始化下载请求
- const TCHAR AcceptType[] = _T("*/*");
- LPCTSTR p_FA[] = {AcceptType, NULL};
- TCHAR Verb[10];
- if(send != NULL)
- _tcscpy(Verb, _T("POST"));
- else
- _tcscpy(Verb, _T("GET"));
- if(!cache)
- type = INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD;
- else
- type = 0;
- HDResetEvent();
- HQO = HttpOpenRequest(HIO,
- Verb, // 从服务器获取数据
- p_flN, // 想读取的文件的名称
- _T("HTTP/1.1"), // 使用的协议
- NULL,
- p_FA,
- type,
- reinterpret_cast<DWORD>(this));
- // 4.发送下载请求
- *p_bufstr = 0;
- MakeHeadMsg(send != NULL, p_bufstr);
- BOOL ret;
- if(*p_bufstr == 0)
- ret = HttpSendRequest(HQO, NULL, 0, NULL, 0);
- else if(send != NULL)
- ret = HttpSendRequest(HQO, p_bufstr, _tcslen(p_bufstr), (LPVOID) send, sendsize);
- else
- ret = HttpSendRequest(HQO, p_bufstr, _tcslen(p_bufstr), NULL, 0);
- if(!ret)
- {
- if(WaitingEvent(Connect_timeout))
- __leave;
- }
- DWORD length, result;
- result = 32774; //ERROR_HTML
- length = sizeof(result);
- if(!::HttpQueryInfo(HQO , HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER
- , &result, &length, NULL))
- {
- errorcode = GetLastError();
- __leave;
- }
- if(result != 200 && result != 206)
- {
- errorcode = result;
- __leave;
- }
- result = UINT_MAX;
- /* TCHAR* tbuf = new TCHAR[1024];
- length = 1024;
- ::HttpQueryInfo(HQO , HTTP_QUERY_RAW_HEADERS_CRLF , tbuf, &length, NULL);*/
- ::HttpQueryInfo(HQO , HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &result, &length, NULL);
- if(result == UINT_MAX)
- result = 1024;
- else
- result += 1; //避免一次无效的扩展缓冲区
- //downloading
- InitWrite(result);
- //**********the internetreadfileexW can't not be used for some reason *************//
- INTERNET_BUFFERSA i_buf = {0};
- i_buf.dwStructSize = sizeof(INTERNET_BUFFERSA);
- i_buf.lpcszHeader = NULL;
- i_buf.dwBufferLength = 1024;
- i_buf.lpvBuffer = p_buf;
- while(1)
- {
- HDResetEvent();
- if (FALSE == ::InternetReadFileExA(HQO , &i_buf, IRF_ASYNC, reinterpret_cast<DWORD>(this)))
- {
- if(WaitingEvent(Request_timeout))
- __leave;
- }
- else
- {
- //在网络传输速度快,步长较小的情况下,
- //InternetReadFileEx 经常会直接返回成功,
- //因此要判断是否发生了用户要求终止子线程事件。
- if (WAIT_OBJECT_0 == ::WaitForSingleObject(m_hEvent[0], 0))
- {
- errorcode = USER_STOP;
- __leave;
- }
- }
- if(i_buf.dwBufferLength == 0)
- break;
- if(!WriteBuffer(p_buf, i_buf.dwBufferLength))
- __leave;
- i_buf.dwBufferLength = 1024;
- i_buf.lpvBuffer = p_buf;
- }
- readstrpos = 0;
- buflength = m_dwOffset;
- funOK = TRUE;
- }
- __finally
- {
- InternetCloseHandleAsync(HQO);
- InternetCloseHandleAsync(HSO);
- if(hSemaphore)
- ::ReleaseSemaphore(hSemaphore, 1, NULL);
- delete[] p_stN;
- delete[] p_flN;
- delete[] p_buf;
- delete[] p_bufstr;
- }
- return funOK;
- }
- BOOL HttpRequest::ParseURL(LPCTSTR src, LPTSTR stN, LPTSTR flN, DWORD* port)
- {
- TCHAR* p_src = new TCHAR[4096];
- _tcscpy(p_src, src);
- TCHAR* tmp = _tcsstr(p_src, _T("http://"));
- if(tmp == NULL || (p_src - tmp) != 0)
- {
- delete[] p_src;
- return FALSE;
- }
- tmp = _tcschr(p_src + 7, _T('/'));
- if(tmp == NULL)
- {
- flN[0] = 0;
- _tcscpy(stN, p_src + 7);
- }
- else
- {
- *tmp = 0;
- _tcscpy(stN, p_src + 7);
- *tmp = _T('/');
- _tcscpy(flN, tmp);
- }
- tmp = _tcschr(stN, _T(':'));
- if(tmp == NULL)
- *port = 80;
- else
- {
- *tmp = 0;
- *port = _ttoi(tmp + 1);
- }
- delete[] p_src;
- return TRUE;
- }
- void CALLBACK HttpRequest::AsyncInternetCallback(
- HINTERNET hInternet,
- DWORD dwContext,
- DWORD dwInternetStatus,
- LPVOID lpvStatusInformation,
- DWORD dwStatusInformationLength)
- {
- HttpRequest * pObj = reinterpret_cast<HttpRequest*>(dwContext);
- switch(dwInternetStatus)
- {
- //句柄被创建
- case INTERNET_STATUS_HANDLE_CREATED:
- pObj->m_hInternet = (HINTERNET)(((LPINTERNET_ASYNC_RESULT)
- (lpvStatusInformation))->dwResult);
- break;
- //句柄被关闭
- case INTERNET_STATUS_HANDLE_CLOSING:
- ::SetEvent(pObj->m_hEvent[1]);
- break;
- //一个请求完成,比如一次句柄创建的请求,或者一次读数据的请求
- case INTERNET_STATUS_REQUEST_COMPLETE:
- //如果发生错误,则设置子线程退出事件
- //这里也是一个陷阱,经常会忽视处理这个错误,
- DWORD ret;
- if (( ret = ((LPINTERNET_ASYNC_RESULT) (lpvStatusInformation))->dwError) != ERROR_SUCCESS)
- pObj->errorcode = ret;
- else
- pObj->errorcode = 0;
- ::SetEvent(pObj->m_hEvent[1]);
- break;
- //连接中断
- case INTERNET_STATUS_CONNECTION_CLOSED:
- break;
- //重定向连接
- case INTERNET_STATUS_REDIRECT:
- break;
- //已连接
- case INTERNET_STATUS_CONNECTED_TO_SERVER:
- break;
- //解析服务器
- case INTERNET_STATUS_RESOLVING_NAME:
- break;
- case INTERNET_STATUS_REQUEST_SENT:
- break;
- }
- }