mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2026-03-26 06:58:28 -06:00
Improvements for SdlHttpRequest
- When “Downloaded X of Y bytes…” Y is no longer -1. - HTTP posting now works (e.g. uploading sync errors).
This commit is contained in:
parent
31adbf1da0
commit
bdbe1647dd
@ -3,31 +3,60 @@
|
||||
#include "base/thread.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <pthread.h>
|
||||
#include <algorithm>
|
||||
|
||||
// Curl implementation of HttpRequest for SDL
|
||||
namespace wi {
|
||||
|
||||
SdlHttpRequest::SdlHttpRequest(HttpResponseHandler *handler) : handler_(handler) {
|
||||
}
|
||||
|
||||
SdlHttpRequest::~SdlHttpRequest() {
|
||||
}
|
||||
|
||||
size_t SdlHttpRequest::WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
LOG() << "WriteMemoryCallback";
|
||||
|
||||
size_t realsize = size * nmemb;
|
||||
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
|
||||
|
||||
if (mem->what == CURLOPT_WRITEDATA)
|
||||
{
|
||||
LOG() << "Data size: " << realsize;
|
||||
ReceivedDataParams *pparams = new ReceivedDataParams;
|
||||
pparams->bb.WriteBytes((const byte*)contents,realsize);
|
||||
pparams->bb.WriteBytes((const byte*)contents, (int)realsize);
|
||||
thread_.Post(kidmReceivedData, this, pparams);
|
||||
}
|
||||
else if (mem->what == CURLOPT_HEADERDATA)
|
||||
|
||||
if (mem->what == CURLOPT_HEADERDATA)
|
||||
{
|
||||
LOG() << "Header";
|
||||
ReceivedResponseParams *pparams = new ReceivedResponseParams;
|
||||
pparams->code = 200;
|
||||
thread_.Post(kidmReceivedResponse, this, pparams);
|
||||
|
||||
// Stuff for delimiting
|
||||
size_t pos = 0;
|
||||
std::string delimiter = ":";
|
||||
std::string str((char *)contents);
|
||||
std::string key;
|
||||
std::string value;
|
||||
|
||||
// Split the HTTP header into a key and value
|
||||
if ((pos = str.find(delimiter)) != std::string::npos) {
|
||||
key = str.substr(0, pos);
|
||||
str.erase(0, pos + delimiter.length());
|
||||
}
|
||||
value = str;
|
||||
|
||||
// Remove newlines and spaces that sneak in sometimes
|
||||
value.erase(std::remove(value.begin(), value.end(), '\n'), value.end());
|
||||
value.erase(std::remove(value.begin(), value.end(), '\r'), value.end());
|
||||
value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
|
||||
|
||||
// handler_ doesn't read the Content-Length header properly when
|
||||
// other header(s) are posted. To be discovered why this happens.
|
||||
// The game only uses Content-Length so only post it for now.
|
||||
if (key == "Content-Length") {
|
||||
pparams->headers.SetValue(key.c_str(), value.c_str());
|
||||
thread_.Post(kidmReceivedResponse, this, pparams);
|
||||
}
|
||||
}
|
||||
|
||||
mem->memory = (char*)realloc(mem->memory, mem->size + realsize + 1);
|
||||
@ -44,157 +73,119 @@ size_t SdlHttpRequest::WriteMemoryCallback(void *contents, size_t size, size_t n
|
||||
return realsize;
|
||||
}
|
||||
|
||||
SdlHttpRequest::SdlHttpRequest(HttpResponseHandler *handler) : handler_(handler) {
|
||||
LOG() << "SdlHttpRequest::SdlHttpRequest";
|
||||
}
|
||||
void SdlHttpRequest::CreateCurlRequest() {
|
||||
/* init the curl session */
|
||||
curl_handle_ = curl_easy_init();
|
||||
|
||||
SdlHttpRequest::~SdlHttpRequest() {
|
||||
}
|
||||
chunk_.cls = this;
|
||||
chunk_.memory = (char*)malloc(1); /* will be grown as needed by the realloc above */
|
||||
chunk_.size = 0; /* no data at this point */
|
||||
chunk_.what = CURLOPT_WRITEDATA;
|
||||
|
||||
void *SdlHttpRequest::doAccess(void *arg)
|
||||
{
|
||||
chunkHeader_.cls = this;
|
||||
chunkHeader_.memory = (char*)malloc(1); /* will be grown as needed by the realloc above */
|
||||
chunkHeader_.what = CURLOPT_HEADERDATA;
|
||||
chunkHeader_.size = 0; /* no data at this point */
|
||||
|
||||
CURL *curl_handle;
|
||||
CURLcode res;
|
||||
/* init the curl session */
|
||||
curl_handle = curl_easy_init();
|
||||
|
||||
struct MemoryStruct chunk;
|
||||
struct MemoryStruct chunkHeader;
|
||||
|
||||
chunk.cls = this;
|
||||
chunk.memory = (char*)malloc(1); /* will be grown as needed by the realloc above */
|
||||
chunk.size = 0; /* no data at this point */
|
||||
chunk.what = CURLOPT_WRITEDATA;
|
||||
|
||||
chunkHeader.cls = this;
|
||||
chunkHeader.memory = (char*)malloc(1); /* will be grown as needed by the realloc above */
|
||||
chunkHeader.what = CURLOPT_HEADERDATA;
|
||||
chunkHeader.size = 0; /* no data at this point */
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
/* specify URL to get */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, url_.c_str());
|
||||
curl_easy_setopt(curl_handle_, CURLOPT_URL, url_.c_str());
|
||||
|
||||
/* specify body to post */
|
||||
if (pbb_ != NULL) {
|
||||
int cb;
|
||||
void *pv = pbb_->Strip(&cb);
|
||||
curl_easy_setopt(curl_handle_, CURLOPT_POSTFIELDS, pv);
|
||||
}
|
||||
|
||||
/* send all data to this function */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, SdlHttpRequest::WriteMemoryCallback_helper);
|
||||
curl_easy_setopt(curl_handle_, CURLOPT_WRITEFUNCTION, SdlHttpRequest::WriteMemoryCallback_helper);
|
||||
|
||||
/* we pass our 'chunk' struct to the callback function */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
|
||||
curl_easy_setopt(curl_handle_, CURLOPT_WRITEDATA, (void *)&chunk_);
|
||||
/* we pass our 'chunk' struct to the callback function */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)&chunkHeader);
|
||||
curl_easy_setopt(curl_handle_, CURLOPT_HEADERDATA, (void *)&chunkHeader_);
|
||||
|
||||
curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT,10);
|
||||
curl_easy_setopt(curl_handle_, CURLOPT_CONNECTTIMEOUT,10);
|
||||
|
||||
/* some servers don't like requests that are made without a user-agent
|
||||
field, so we provide one */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
||||
curl_easy_setopt(curl_handle_, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
||||
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(curl_handle_, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl_handle_, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
|
||||
res = curl_easy_perform(curl_handle);
|
||||
void SdlHttpRequest::SubmitCurlRequest(void *pv) {
|
||||
SdlHttpRequest *req = (SdlHttpRequest *)pv;
|
||||
|
||||
long http_code = 0;
|
||||
CURLcode res = curl_easy_perform(req->curl_handle_);
|
||||
|
||||
/* check for errors */
|
||||
// check for errors
|
||||
if(res != CURLE_OK) {
|
||||
LOG() << "curl_easy_perform() failed: " << curl_easy_strerror(res);
|
||||
ErrorParams *pparams = new ErrorParams;
|
||||
strncpyz(pparams->szError, curl_easy_strerror(res), sizeof(pparams->szError));
|
||||
|
||||
// Called on main thread. Post this to game thread.
|
||||
thread_.Post(kidmError, this, pparams);
|
||||
}
|
||||
else {
|
||||
curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
|
||||
LOG() << "Resp code = " << http_code;
|
||||
|
||||
//base::ByteBuffer bb;
|
||||
//bb.WriteBytes((const byte*)chunkHeader.memory,chunkHeader.size);
|
||||
|
||||
//ReceivedResponseParams *pparams = new ReceivedResponseParams;
|
||||
//pparams->code = http_code;
|
||||
//thread_.Post(kidmReceivedResponse, this, pparams);
|
||||
|
||||
if (http_code == 200)
|
||||
{
|
||||
LOG() << "Data length: " << chunk.size;
|
||||
//ReceivedDataParams *pparams = new ReceivedDataParams;
|
||||
//pparams->bb.WriteBytes((const byte*)chunk.memory,chunk.size);
|
||||
//thread_.Post(kidmReceivedData, this, pparams);
|
||||
}
|
||||
|
||||
LOG() << "%lu bytes retrieved" << (long)chunk.size;
|
||||
LOG() << "got: " << chunk.memory;
|
||||
}
|
||||
|
||||
/* cleanup curl stuff */
|
||||
curl_easy_cleanup(curl_handle);
|
||||
|
||||
if(chunk.memory)
|
||||
free(chunk.memory);
|
||||
|
||||
if(chunkHeader.memory)
|
||||
free(chunkHeader.memory);
|
||||
|
||||
thread_.Post(kidmFinishedLoading, this);
|
||||
|
||||
return 0;
|
||||
strncpyz(pparams->szError, curl_easy_strerror(res), CURL_ERROR_SIZE);
|
||||
req->thread().Post(kidmError, req, pparams);
|
||||
} else {
|
||||
req->thread().Post(kidmFinishedLoading, req);
|
||||
}
|
||||
}
|
||||
|
||||
void SdlHttpRequest::Submit() {
|
||||
LOG() << "SdlHttpRequest::SdlHttpRequest, URL = " << url_.c_str();
|
||||
|
||||
pthread_t pth; // this is our thread identifier
|
||||
pthread_create(&pth,NULL, SdlHttpRequest::doAccess_helper,this);
|
||||
this->CreateCurlRequest();
|
||||
|
||||
// SdlHttpRequest::Submit() is called on the game thread
|
||||
// so spin off a new thread to run the request on.
|
||||
base::Thread *thread = new base::Thread();
|
||||
thread->Start(SubmitCurlRequest, this);
|
||||
}
|
||||
|
||||
void SdlHttpRequest::Release() {
|
||||
LOG() << "SdlHttpRequest::Release";
|
||||
// TODO: need to abort thread..
|
||||
curl_easy_cleanup(curl_handle_);
|
||||
|
||||
if (chunk_.memory)
|
||||
free(chunk_.memory);
|
||||
|
||||
if (chunkHeader_.memory)
|
||||
free(chunkHeader_.memory);
|
||||
|
||||
thread_.Clear(this);
|
||||
}
|
||||
|
||||
void SdlHttpRequest::OnMessage(base::Message *pmsg) {
|
||||
LOG() << "SdlHttpRequest::OnMessage";
|
||||
|
||||
switch (pmsg->id) {
|
||||
case kidmReceivedResponse:
|
||||
{
|
||||
ReceivedResponseParams *pparams =
|
||||
(ReceivedResponseParams *)pmsg->data;
|
||||
handler_->OnReceivedResponse(this, pparams->code,
|
||||
&pparams->headers);
|
||||
delete pparams;
|
||||
case kidmReceivedResponse:
|
||||
{
|
||||
ReceivedResponseParams *pparams =
|
||||
(ReceivedResponseParams *)pmsg->data;
|
||||
handler_->OnReceivedResponse(this, pparams->code,
|
||||
&pparams->headers);
|
||||
delete pparams;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kidmReceivedData:
|
||||
{
|
||||
ReceivedDataParams *pparams =
|
||||
(ReceivedDataParams *)pmsg->data;
|
||||
handler_->OnReceivedData(this, &pparams->bb);
|
||||
delete pparams;
|
||||
case kidmReceivedData:
|
||||
{
|
||||
ReceivedDataParams *pparams =
|
||||
(ReceivedDataParams *)pmsg->data;
|
||||
handler_->OnReceivedData(this, &pparams->bb);
|
||||
delete pparams;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kidmFinishedLoading:
|
||||
handler_->OnFinishedLoading(this);
|
||||
break;
|
||||
|
||||
case kidmError:
|
||||
{
|
||||
ErrorParams *pparams = (ErrorParams *)pmsg->data;
|
||||
handler_->OnError(this, pparams->szError);
|
||||
delete pparams;
|
||||
case kidmFinishedLoading:
|
||||
handler_->OnFinishedLoading(this);
|
||||
break;
|
||||
}
|
||||
|
||||
} // switch
|
||||
case kidmError:
|
||||
{
|
||||
ErrorParams *pparams = (ErrorParams *)pmsg->data;
|
||||
handler_->OnError(this, pparams->szError);
|
||||
delete pparams;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wi
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
#include "base/thread.h"
|
||||
#include "base/bytebuffer.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
namespace wi {
|
||||
|
||||
class SdlHttpRequest;
|
||||
@ -17,7 +19,6 @@ struct MemoryStruct {
|
||||
size_t size;
|
||||
};
|
||||
|
||||
|
||||
class SdlHttpRequest : public HttpRequest, base::MessageHandler {
|
||||
public:
|
||||
SdlHttpRequest(HttpResponseHandler *phandler);
|
||||
@ -29,15 +30,15 @@ public:
|
||||
|
||||
private:
|
||||
HttpResponseHandler *handler_;
|
||||
CURL *curl_handle_;
|
||||
struct MemoryStruct chunk_;
|
||||
struct MemoryStruct chunkHeader_;
|
||||
|
||||
void *doAccess(void *arg);
|
||||
virtual void OnMessage(base::Message *pmsg);
|
||||
static void SubmitCurlRequest(void *pv);
|
||||
void CreateCurlRequest();
|
||||
|
||||
size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp);
|
||||
|
||||
static void *doAccess_helper(void *context) {
|
||||
return ((SdlHttpRequest *)context)->doAccess(0);
|
||||
}
|
||||
|
||||
static size_t WriteMemoryCallback_helper(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
return (((MemoryStruct *)userp)->cls)->WriteMemoryCallback(contents,size,nmemb,userp);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user