map<HINTERNET, HttpRequest*> requestMap;
// ======================================================================================
// ======================================================================================
void __stdcall httpRequestsCallback (HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus, LPVOID lpStatusInfo, DWORD dwStatusInfoLen);
// ======================================================================================
// ======================================================================================
HttpRequest::HttpRequest (string domain, string URL) {
this->domain = domain;
this->URL = URL;
this->status = STATUS_OK;
this->openRequestState = 0;
this->sendRequestState = 0;
this->readResponseState = 0;
}
// ======================================================================================
void HttpRequest::openInternet() {
//
this->hInstance = InternetOpenA("asynchttp", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
if (!this->hInstance) this->error();
requestMap[this->hInstance] = this;
}
// ======================================================================================
void HttpRequest::setupCallback() {
//
if (InternetSetStatusCallback(this->hInstance, (INTERNET_STATUS_CALLBACK)&httpRequestsCallback) == INTERNET_INVALID_STATUS_CALLBACK) {
this->error();
}
}
// ======================================================================================
void HttpRequest::openConnection() {
//
this->hConnect = InternetConnectA(this->hInstance, this->domain.c_str(), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
//
if (hConnect != NULL) {
requestMap[this->hConnect] = this;
} else {
//
if (GetLastError() != ERROR_IO_PENDING) {
this->error();
}
}
}
// ======================================================================================
void HttpRequest::openRequest() {
//
this->hRequest = HttpOpenRequestA(this->hConnect, "GET", this->URL.c_str(), NULL, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 2);
//
if (this->hRequest != NULL) {
requestMap[this->hRequest] = this;
} else {
//
if (GetLastError() != ERROR_IO_PENDING) {
this->error();
}
}
}
// ======================================================================================
void HttpRequest::sendRequest() {
//
if (!HttpSendRequestA(this->hRequest, NULL, 0, NULL, 0)) {
//
if (GetLastError() != ERROR_IO_PENDING) {
this->error();
}
}
}
// ======================================================================================
void HttpRequest::readResponse() {
int statusCode;
DWORD statCharLen = 128;
char statChar[128];
// Check the status code
HttpQueryInfoA(this->hRequest, HTTP_QUERY_STATUS_CODE, &statChar, &statCharLen, NULL);
statusCode = atoi(statChar);
output(statChar);
//
bool allDone = false;
char buffer[16368];
do {
//
INTERNET_BUFFERSA InternetBuffer;
FillMemory(&InternetBuffer, sizeof(InternetBuffer), 0);
InternetBuffer.dwStructSize = sizeof(InternetBuffer);
InternetBuffer.lpvBuffer = buffer;
InternetBuffer.dwBufferLength = sizeof(buffer) - 1;
//
if (!InternetReadFileExA(this->hRequest, &InternetBuffer, 0, 2 )) {
this->error();
}
//
buffer[InternetBuffer.dwBufferLength] = 0;
this->result.append(buffer);
output("What was received: ");
output(buffer);
output("dwBufferLength: " + intToStr(InternetBuffer.dwBufferLength));
//
if (InternetBuffer.dwBufferLength == 0) {
allDone = true;
}
// Look for the 'end data' character.
// (NOTE: This is an internal thing: I don't want to receive any data
// that wuold be sent after the dollar character.)
string::size_type endCharPos = this->result.find('$');
if (endCharPos != string::npos) {
this->result = this->result.substr(0, endCharPos);
break;
}
} while (!allDone);
//
this->status = STATUS_SUCCESS;
}
// ======================================================================================
void HttpRequest::send() {
//
this->openInternet();
this->setupCallback();
this->openConnection();
}
// ======================================================================================
void HttpRequest::update() {
//
if (this->openRequestState == 1) {
this->openRequest();
this->openRequestState = 2;
}
if (this->sendRequestState == 1) {
this->sendRequest();
this->sendRequestState = 2;
}
if (this->readResponseState == 1) {
this->readResponse();
this->readResponseState = 2;
}
}
// ======================================================================================
void HttpRequest::error() {
this->status = STATUS_ERROR;
}
// ======================================================================================
// ======================================================================================
void __stdcall httpRequestsCallback (HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus, LPVOID lpStatusInfo, DWORD dwStatusInfoLen) {
//
HttpRequest* httpRequest = requestMap[hInternet];
//
if (dwContext == 1) {
//
if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED) {
//
INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
httpRequest->hConnect = (HINTERNET)pRes->dwResult;
requestMap[httpRequest->hConnect] = httpRequest;
//
if (!httpRequest->openRequestState) httpRequest->openRequestState = 1;
}
}
//
if (dwContext == 2) {
//
if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED) {
//
INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
httpRequest->hRequest = (HINTERNET)pRes->dwResult;
requestMap[httpRequest->hRequest] = httpRequest;
//
if (!httpRequest->sendRequestState) httpRequest->sendRequestState = 1;
}
//
if (dwInternetStatus == INTERNET_STATUS_REQUEST_SENT) {
// In case we would be interested.
DWORD *lpBytesSent = (DWORD*)lpStatusInfo;
}
//
if (dwInternetStatus == INTERNET_STATUS_REQUEST_COMPLETE) {
//
INTERNET_ASYNC_RESULT *pAsyncRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
if (!httpRequest->readResponseState) httpRequest->readResponseState = 1;
}
}
}