Turn RequestBroker::Get/SaveUserInfoAsync into a request derived from Download
Also move everything http_ into Download and DownloadManager and nuke RequestBroker.
This commit is contained in:
parent
af4d022087
commit
1864a8649d
38
src/client/APIRequest.cpp
Normal file
38
src/client/APIRequest.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "APIRequest.h"
|
||||
|
||||
#include "client/Client.h"
|
||||
|
||||
namespace http
|
||||
{
|
||||
APIRequest::APIRequest(ByteString url) : Download(url)
|
||||
{
|
||||
User user = Client::Ref().GetAuthUser();
|
||||
AuthHeaders(ByteString::Build(user.UserID), user.SessionID);
|
||||
}
|
||||
|
||||
APIRequest::~APIRequest()
|
||||
{
|
||||
}
|
||||
|
||||
APIRequest::Result APIRequest::Finish()
|
||||
{
|
||||
Result result;
|
||||
try
|
||||
{
|
||||
ByteString data = Download::Finish(&result.status);
|
||||
Client::Ref().ParseServerReturn(data, result.status, true);
|
||||
if (result.status == 200 && data.size())
|
||||
{
|
||||
std::istringstream dataStream(data);
|
||||
Json::Value objDocument;
|
||||
dataStream >> objDocument;
|
||||
result.document = std::unique_ptr<Json::Value>(new Json::Value(objDocument));
|
||||
}
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
30
src/client/APIRequest.h
Normal file
30
src/client/APIRequest.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef APIREQUEST2_H
|
||||
#define APIREQUEST2_H
|
||||
|
||||
#include "Download.h"
|
||||
#include "common/String.h"
|
||||
#include "json/json.h"
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
namespace http
|
||||
{
|
||||
class APIRequest : public Download
|
||||
{
|
||||
public:
|
||||
struct Result
|
||||
{
|
||||
int status;
|
||||
std::unique_ptr<Json::Value> document;
|
||||
};
|
||||
|
||||
APIRequest(ByteString url);
|
||||
virtual ~APIRequest();
|
||||
|
||||
Result Finish();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // APIREQUEST2_H
|
||||
|
@ -7,5 +7,9 @@ namespace http
|
||||
ImageRequest(ByteString::Build("http://" STATICSERVER "/avatars/", username, ".pti"), width, height)
|
||||
{
|
||||
}
|
||||
|
||||
AvatarRequest::~AvatarRequest()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ namespace http
|
||||
{
|
||||
public:
|
||||
AvatarRequest(ByteString username, int width, int height);
|
||||
virtual ~AvatarRequest();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "Misc.h"
|
||||
#include "Platform.h"
|
||||
#include "Update.h"
|
||||
#include "HTTP.h"
|
||||
|
||||
#include "simulation/SaveRenderer.h"
|
||||
#include "gui/interface/Point.h"
|
||||
@ -45,10 +44,7 @@
|
||||
#include "gui/preview/Comment.h"
|
||||
#include "ClientListener.h"
|
||||
#include "client/Download.h"
|
||||
#include "requestbroker/RequestBroker.h"
|
||||
#include "requestbroker/WebRequest.h"
|
||||
#include "requestbroker/APIRequest.h"
|
||||
#include "requestbroker/APIResultParser.h"
|
||||
#include "client/DownloadManager.h"
|
||||
|
||||
#include "json/json.h"
|
||||
|
||||
@ -115,10 +111,7 @@ void Client::Initialise(ByteString proxyString)
|
||||
update_finish();
|
||||
}
|
||||
|
||||
if (proxyString.length())
|
||||
http_init((char*)proxyString.c_str());
|
||||
else
|
||||
http_init(NULL);
|
||||
http::DownloadManager::Ref().Initialise(proxyString);
|
||||
|
||||
//Read stamps library
|
||||
std::ifstream stampsLib;
|
||||
@ -439,15 +432,6 @@ bool Client::DoInstallation()
|
||||
#endif
|
||||
}
|
||||
|
||||
void Client::SetProxy(ByteString proxy)
|
||||
{
|
||||
http_done();
|
||||
if(proxy.length())
|
||||
http_init((char*)proxy.c_str());
|
||||
else
|
||||
http_init(NULL);
|
||||
}
|
||||
|
||||
std::vector<ByteString> Client::DirectorySearch(ByteString directory, ByteString search, ByteString extension)
|
||||
{
|
||||
std::vector<ByteString> extensions;
|
||||
@ -722,8 +706,6 @@ RequestStatus Client::ParseServerReturn(ByteString &result, int status, bool jso
|
||||
|
||||
void Client::Tick()
|
||||
{
|
||||
//Check thumbnail queue
|
||||
RequestBroker::Ref().FlushThumbQueue();
|
||||
if (versionCheckRequest)
|
||||
{
|
||||
if (CheckUpdate(versionCheckRequest, true))
|
||||
@ -931,8 +913,7 @@ void Client::WritePrefs()
|
||||
|
||||
void Client::Shutdown()
|
||||
{
|
||||
RequestBroker::Ref().Shutdown();
|
||||
http_done();
|
||||
http::DownloadManager::Ref().Shutdown();
|
||||
|
||||
//Save config
|
||||
WritePrefs();
|
||||
@ -1243,86 +1224,6 @@ std::vector<unsigned char> Client::GetSaveData(int saveID, int saveDate)
|
||||
return saveData;
|
||||
}
|
||||
|
||||
RequestBroker::Request * Client::GetSaveDataAsync(int saveID, int saveDate)
|
||||
{
|
||||
ByteString url;
|
||||
if(saveDate){
|
||||
url = ByteString::Build("http://", STATICSERVER, "/", saveID, "_", saveDate, ".cps");
|
||||
} else {
|
||||
url = ByteString::Build("http://", STATICSERVER, "/", saveID, ".cps");
|
||||
}
|
||||
return new WebRequest(url);
|
||||
}
|
||||
|
||||
RequestBroker::Request * Client::SaveUserInfoAsync(UserInfo info)
|
||||
{
|
||||
class StatusParser: public APIResultParser
|
||||
{
|
||||
virtual void * ProcessResponse(unsigned char * data, int dataLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::istringstream dataStream((char*)data);
|
||||
Json::Value objDocument;
|
||||
dataStream >> objDocument;
|
||||
return (void*)(objDocument["Status"].asInt() == 1);
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
virtual void Cleanup(void * objectPtr)
|
||||
{
|
||||
//delete (UserInfo*)objectPtr;
|
||||
}
|
||||
virtual ~StatusParser() { }
|
||||
};
|
||||
std::map<ByteString, ByteString> postData;
|
||||
postData.insert(std::pair<ByteString, ByteString>("Location", info.location.ToUtf8()));
|
||||
postData.insert(std::pair<ByteString, ByteString>("Biography", info.biography.ToUtf8()));
|
||||
return new APIRequest("http://" SERVER "/Profile.json", postData, new StatusParser());
|
||||
}
|
||||
|
||||
RequestBroker::Request * Client::GetUserInfoAsync(ByteString username)
|
||||
{
|
||||
class UserInfoParser: public APIResultParser
|
||||
{
|
||||
virtual void * ProcessResponse(unsigned char * data, int dataLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::istringstream dataStream((char*)data);
|
||||
Json::Value objDocument;
|
||||
dataStream >> objDocument;
|
||||
Json::Value tempUser = objDocument["User"];
|
||||
return new UserInfo(tempUser["ID"].asInt(),
|
||||
tempUser["Age"].asInt(),
|
||||
tempUser["Username"].asString(),
|
||||
ByteString(tempUser["Biography"].asString()).FromUtf8(),
|
||||
ByteString(tempUser["Location"].asString()).FromUtf8(),
|
||||
tempUser["Website"].asString(),
|
||||
tempUser["Saves"]["Count"].asInt(),
|
||||
tempUser["Saves"]["AverageScore"].asInt(),
|
||||
tempUser["Saves"]["HighestScore"].asInt(),
|
||||
tempUser["Forum"]["Topics"].asInt(),
|
||||
tempUser["Forum"]["Replies"].asInt(),
|
||||
tempUser["Forum"]["Reputation"].asInt());
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
virtual void Cleanup(void * objectPtr)
|
||||
{
|
||||
delete (UserInfo*)objectPtr;
|
||||
}
|
||||
virtual ~UserInfoParser() { }
|
||||
};
|
||||
return new APIRequest("http://" SERVER "/User.json?Name=" + username, new UserInfoParser());
|
||||
}
|
||||
|
||||
LoginStatus Client::Login(ByteString username, ByteString password, User & user)
|
||||
{
|
||||
lastError = "";
|
||||
@ -1594,110 +1495,6 @@ SaveInfo * Client::GetSave(int saveID, int saveDate)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RequestBroker::Request * Client::GetSaveAsync(int saveID, int saveDate)
|
||||
{
|
||||
ByteStringBuilder urlStream;
|
||||
urlStream << "http://" << SERVER << "/Browse/View.json?ID=" << saveID;
|
||||
if(saveDate)
|
||||
{
|
||||
urlStream << "&Date=" << saveDate;
|
||||
}
|
||||
|
||||
class SaveInfoParser: public APIResultParser
|
||||
{
|
||||
virtual void * ProcessResponse(unsigned char * data, int dataLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::istringstream dataStream((char*)data);
|
||||
Json::Value objDocument;
|
||||
dataStream >> objDocument;
|
||||
|
||||
int tempID = objDocument["ID"].asInt();
|
||||
int tempScoreUp = objDocument["ScoreUp"].asInt();
|
||||
int tempScoreDown = objDocument["ScoreDown"].asInt();
|
||||
int tempMyScore = objDocument["ScoreMine"].asInt();
|
||||
ByteString tempUsername = objDocument["Username"].asString();
|
||||
String tempName = ByteString(objDocument["Name"].asString()).FromUtf8();
|
||||
String tempDescription = ByteString(objDocument["Description"].asString()).FromUtf8();
|
||||
int tempCreatedDate = objDocument["DateCreated"].asInt();
|
||||
int tempUpdatedDate = objDocument["Date"].asInt();
|
||||
bool tempPublished = objDocument["Published"].asBool();
|
||||
bool tempFavourite = objDocument["Favourite"].asBool();
|
||||
int tempComments = objDocument["Comments"].asInt();
|
||||
int tempViews = objDocument["Views"].asInt();
|
||||
int tempVersion = objDocument["Version"].asInt();
|
||||
|
||||
Json::Value tagsArray = objDocument["Tags"];
|
||||
std::list<ByteString> tempTags;
|
||||
for (Json::UInt j = 0; j < tagsArray.size(); j++)
|
||||
tempTags.push_back(tagsArray[j].asString());
|
||||
|
||||
SaveInfo * tempSave = new SaveInfo(tempID, tempCreatedDate, tempUpdatedDate, tempScoreUp,
|
||||
tempScoreDown, tempMyScore, tempUsername, tempName,
|
||||
tempDescription, tempPublished, tempTags);
|
||||
tempSave->Comments = tempComments;
|
||||
tempSave->Favourite = tempFavourite;
|
||||
tempSave->Views = tempViews;
|
||||
tempSave->Version = tempVersion;
|
||||
return tempSave;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
virtual void Cleanup(void * objectPtr)
|
||||
{
|
||||
delete (SaveInfo*)objectPtr;
|
||||
}
|
||||
virtual ~SaveInfoParser() { }
|
||||
};
|
||||
return new APIRequest(urlStream.Build(), new SaveInfoParser());
|
||||
}
|
||||
|
||||
RequestBroker::Request * Client::GetCommentsAsync(int saveID, int start, int count)
|
||||
{
|
||||
class CommentsParser: public APIResultParser
|
||||
{
|
||||
virtual void * ProcessResponse(unsigned char * data, int dataLength)
|
||||
{
|
||||
std::vector<SaveComment*> * commentArray = new std::vector<SaveComment*>();
|
||||
try
|
||||
{
|
||||
std::istringstream dataStream((char*)data);
|
||||
Json::Value commentsArray;
|
||||
dataStream >> commentsArray;
|
||||
|
||||
for (Json::UInt j = 0; j < commentsArray.size(); j++)
|
||||
{
|
||||
int userID = ByteString(commentsArray[j]["UserID"].asString()).ToNumber<int>();
|
||||
ByteString username = commentsArray[j]["Username"].asString();
|
||||
ByteString formattedUsername = commentsArray[j]["FormattedUsername"].asString();
|
||||
if (formattedUsername == "jacobot")
|
||||
formattedUsername = "\bt" + formattedUsername;
|
||||
String comment = ByteString(commentsArray[j]["Text"].asString()).FromUtf8();
|
||||
commentArray->push_back(new SaveComment(userID, username, formattedUsername, comment));
|
||||
}
|
||||
return commentArray;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
delete commentArray;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
virtual void Cleanup(void * objectPtr)
|
||||
{
|
||||
delete (std::vector<SaveComment*>*)objectPtr;
|
||||
}
|
||||
virtual ~CommentsParser() { }
|
||||
};
|
||||
|
||||
ByteString url = ByteString::Build("http://", SERVER, "/Browse/Comments.json?ID=", saveID, "&Start=", start, "&Count=", count);
|
||||
return new APIRequest(url, new CommentsParser());
|
||||
}
|
||||
|
||||
std::vector<std::pair<ByteString, int> > * Client::GetTags(int start, int count, String query, int & resultCount)
|
||||
{
|
||||
lastError = "";
|
||||
|
@ -14,8 +14,6 @@
|
||||
|
||||
#include "json/json.h"
|
||||
|
||||
#include "requestbroker/RequestBroker.h"
|
||||
|
||||
class SaveInfo;
|
||||
class SaveFile;
|
||||
class SaveComment;
|
||||
@ -121,7 +119,6 @@ public:
|
||||
String GetMessageOfTheDay();
|
||||
|
||||
void Initialise(ByteString proxyString);
|
||||
void SetProxy(ByteString proxy);
|
||||
bool IsFirstRun();
|
||||
|
||||
int MakeDirectory(const char * dirname);
|
||||
@ -147,11 +144,6 @@ public:
|
||||
|
||||
RequestStatus AddComment(int saveID, String comment);
|
||||
|
||||
//Retrieves a "UserInfo" object
|
||||
RequestBroker::Request * GetUserInfoAsync(ByteString username);
|
||||
RequestBroker::Request * SaveUserInfoAsync(UserInfo info);
|
||||
|
||||
RequestBroker::Request * GetSaveDataAsync(int saveID, int saveDate);
|
||||
unsigned char * GetSaveData(int saveID, int saveDate, int & dataLength);
|
||||
std::vector<unsigned char> GetSaveData(int saveID, int saveDate);
|
||||
|
||||
@ -159,10 +151,7 @@ public:
|
||||
std::vector<SaveInfo*> * SearchSaves(int start, int count, String query, ByteString sort, ByteString category, int & resultCount);
|
||||
std::vector<std::pair<ByteString, int> > * GetTags(int start, int count, String query, int & resultCount);
|
||||
|
||||
RequestBroker::Request * GetCommentsAsync(int saveID, int start, int count);
|
||||
|
||||
SaveInfo * GetSave(int saveID, int saveDate);
|
||||
RequestBroker::Request * GetSaveAsync(int saveID, int saveDate);
|
||||
|
||||
RequestStatus DeleteSave(int saveID);
|
||||
RequestStatus ReportSave(int saveID, String message);
|
||||
|
@ -42,6 +42,8 @@ void DownloadManager::Shutdown()
|
||||
pthread_mutex_unlock(&downloadLock);
|
||||
if (threadStarted)
|
||||
pthread_join(downloadThread, NULL);
|
||||
|
||||
http_done();
|
||||
}
|
||||
|
||||
//helper function for download
|
||||
@ -52,6 +54,19 @@ TH_ENTRY_POINT void* DownloadManagerHelper(void* obj)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DownloadManager::Initialise(ByteString Proxy)
|
||||
{
|
||||
proxy = Proxy;
|
||||
if (proxy.length())
|
||||
{
|
||||
http_init((char *)proxy.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
http_init(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadManager::Start()
|
||||
{
|
||||
managerRunning = true;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <ctime>
|
||||
#include <vector>
|
||||
#include "common/Singleton.h"
|
||||
#include "common/String.h"
|
||||
|
||||
namespace http
|
||||
{
|
||||
@ -15,6 +16,7 @@ private:
|
||||
pthread_mutex_t downloadLock;
|
||||
pthread_mutex_t downloadAddLock;
|
||||
bool threadStarted;
|
||||
ByteString proxy;
|
||||
|
||||
int lastUsed;
|
||||
volatile bool managerRunning;
|
||||
@ -27,6 +29,8 @@ public:
|
||||
DownloadManager();
|
||||
~DownloadManager();
|
||||
|
||||
void Initialise(ByteString proxy);
|
||||
|
||||
void Shutdown();
|
||||
void Update();
|
||||
void EnsureRunning();
|
||||
|
39
src/client/GetUserInfoRequest.cpp
Normal file
39
src/client/GetUserInfoRequest.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "GetUserInfoRequest.h"
|
||||
|
||||
namespace http
|
||||
{
|
||||
GetUserInfoRequest::GetUserInfoRequest(ByteString username) :
|
||||
APIRequest("http://" SERVER "/User.json?Name=" + username)
|
||||
{
|
||||
}
|
||||
|
||||
GetUserInfoRequest::~GetUserInfoRequest()
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<UserInfo> GetUserInfoRequest::Finish()
|
||||
{
|
||||
std::unique_ptr<UserInfo> user_info;
|
||||
auto result = APIRequest::Finish();
|
||||
if (result.document)
|
||||
{
|
||||
auto &user = (*result.document)["User"];
|
||||
user_info = std::unique_ptr<UserInfo>(new UserInfo(
|
||||
user["ID"].asInt(),
|
||||
user["Age"].asInt(),
|
||||
user["Username"].asString(),
|
||||
ByteString(user["Biography"].asString()).FromUtf8(),
|
||||
ByteString(user["Location"].asString()).FromUtf8(),
|
||||
user["Website"].asString(),
|
||||
user["Saves"]["Count"].asInt(),
|
||||
user["Saves"]["AverageScore"].asInt(),
|
||||
user["Saves"]["HighestScore"].asInt(),
|
||||
user["Forum"]["Topics"].asInt(),
|
||||
user["Forum"]["Replies"].asInt(),
|
||||
user["Forum"]["Reputation"].asInt()
|
||||
));
|
||||
}
|
||||
return user_info;
|
||||
}
|
||||
}
|
||||
|
26
src/client/GetUserInfoRequest.h
Normal file
26
src/client/GetUserInfoRequest.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef GETUSERINFOREQUEST2_H
|
||||
#define GETUSERINFOREQUEST2_H
|
||||
|
||||
#include "Download.h"
|
||||
#include "common/String.h"
|
||||
#include "json/json.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/APIRequest.h"
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
namespace http
|
||||
{
|
||||
class GetUserInfoRequest : public APIRequest
|
||||
{
|
||||
public:
|
||||
GetUserInfoRequest(ByteString username);
|
||||
virtual ~GetUserInfoRequest();
|
||||
|
||||
std::unique_ptr<UserInfo> Finish();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // GETUSERINFOREQUEST2_H
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "client/DownloadManager.h"
|
||||
#include "Config.h"
|
||||
#include "Misc.h"
|
||||
#include "HTTP.h"
|
||||
@ -205,7 +204,6 @@ void http_done(void)
|
||||
#ifdef WIN
|
||||
WSACleanup();
|
||||
#endif
|
||||
http::DownloadManager::Ref().Shutdown();
|
||||
http_up = 0;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,10 @@ namespace http
|
||||
{
|
||||
}
|
||||
|
||||
ImageRequest::~ImageRequest()
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoBuffer> ImageRequest::Finish()
|
||||
{
|
||||
ByteString data = Download::Finish(nullptr);
|
||||
|
@ -15,6 +15,7 @@ namespace http
|
||||
|
||||
public:
|
||||
ImageRequest(ByteString url, int width, int height);
|
||||
virtual ~ImageRequest();
|
||||
|
||||
std::unique_ptr<VideoBuffer> Finish();
|
||||
};
|
||||
|
31
src/client/SaveUserInfoRequest.cpp
Normal file
31
src/client/SaveUserInfoRequest.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "SaveUserInfoRequest.h"
|
||||
|
||||
namespace http
|
||||
{
|
||||
SaveUserInfoRequest::SaveUserInfoRequest(UserInfo info) :
|
||||
APIRequest("http://" SERVER "/Profile.json")
|
||||
{
|
||||
AddPostData({
|
||||
{ "Location", info.location.ToUtf8() },
|
||||
{ "Biography", info.biography.ToUtf8() }
|
||||
});
|
||||
}
|
||||
|
||||
SaveUserInfoRequest::~SaveUserInfoRequest()
|
||||
{
|
||||
}
|
||||
|
||||
bool SaveUserInfoRequest::Finish()
|
||||
{
|
||||
auto result = APIRequest::Finish();
|
||||
if (result.document)
|
||||
{
|
||||
return (*result.document)["Status"].asInt() == 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
26
src/client/SaveUserInfoRequest.h
Normal file
26
src/client/SaveUserInfoRequest.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef SAVEUSERINFOREQUEST2_H
|
||||
#define SAVEUSERINFOREQUEST2_H
|
||||
|
||||
#include "Download.h"
|
||||
#include "common/String.h"
|
||||
#include "json/json.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/APIRequest.h"
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
namespace http
|
||||
{
|
||||
class SaveUserInfoRequest : public APIRequest
|
||||
{
|
||||
public:
|
||||
SaveUserInfoRequest(UserInfo info);
|
||||
virtual ~SaveUserInfoRequest();
|
||||
|
||||
bool Finish();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SAVEUSERINFOREQUEST2_H
|
||||
|
@ -11,5 +11,9 @@ namespace http
|
||||
), width, height)
|
||||
{
|
||||
}
|
||||
|
||||
ThumbnailRequest::~ThumbnailRequest()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ namespace http
|
||||
{
|
||||
public:
|
||||
ThumbnailRequest(int saveID, int saveDate, int width, int height);
|
||||
virtual ~ThumbnailRequest();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,150 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include "Config.h"
|
||||
#include "Format.h"
|
||||
#include "client/Client.h"
|
||||
#include "APIRequest.h"
|
||||
#include "client/HTTP.h"
|
||||
#include "APIResultParser.h"
|
||||
|
||||
APIRequest::APIRequest(ByteString url, APIResultParser * parser, ListenerHandle listener, int identifier):
|
||||
RequestBroker::Request(API, listener, identifier)
|
||||
{
|
||||
Post = false;
|
||||
HTTPContext = NULL;
|
||||
Parser = parser;
|
||||
URL = url;
|
||||
}
|
||||
|
||||
APIRequest::APIRequest(ByteString url, std::map<ByteString, ByteString> postData, APIResultParser * parser, ListenerHandle listener, int identifier):
|
||||
RequestBroker::Request(API, listener, identifier)
|
||||
{
|
||||
Post = true;
|
||||
PostData = postData;
|
||||
HTTPContext = NULL;
|
||||
Parser = parser;
|
||||
URL = url;
|
||||
}
|
||||
|
||||
RequestBroker::ProcessResponse APIRequest::Process(RequestBroker & rb)
|
||||
{
|
||||
if(HTTPContext)
|
||||
{
|
||||
if(http_async_req_status(HTTPContext))
|
||||
{
|
||||
char * data;
|
||||
int status, data_size;
|
||||
data = http_async_req_stop(HTTPContext, &status, &data_size);
|
||||
|
||||
ByteString nice_data(data);
|
||||
Client::Ref().ParseServerReturn(nice_data, status, true);
|
||||
if (status == 200 && data)
|
||||
{
|
||||
void * resultObject = Parser->ProcessResponse((unsigned char *)data, data_size);
|
||||
|
||||
if(resultObject)
|
||||
{
|
||||
this->ResultObject = resultObject;
|
||||
rb.requestComplete(this);
|
||||
free(data);
|
||||
return RequestBroker::Finished;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Request for " << URL << " could not be parsed: " << data << std::endl;
|
||||
#endif
|
||||
free(data);
|
||||
return RequestBroker::Failed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Request for " << URL << " failed with status " << status << std::endl;
|
||||
#endif
|
||||
free(data);
|
||||
return RequestBroker::Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " New Request for " << URL << std::endl;
|
||||
#endif
|
||||
if(Post)
|
||||
{
|
||||
char ** postNames = new char*[PostData.size() + 1];
|
||||
char ** postData = new char*[PostData.size()];
|
||||
int * postLength = new int[PostData.size()];
|
||||
|
||||
int i = 0;
|
||||
std::map<ByteString, ByteString>::iterator iter = PostData.begin();
|
||||
while(iter != PostData.end())
|
||||
{
|
||||
ByteString name = iter->first;
|
||||
ByteString data = iter->second;
|
||||
char * cName = new char[name.length() + 1];
|
||||
char * cData = new char[data.length() + 1];
|
||||
std::strcpy(cName, name.c_str());
|
||||
std::strcpy(cData, data.c_str());
|
||||
postNames[i] = cName;
|
||||
postData[i] = cData;
|
||||
postLength[i] = data.length();
|
||||
i++;
|
||||
iter++;
|
||||
}
|
||||
postNames[i] = NULL;
|
||||
|
||||
if(Client::Ref().GetAuthUser().UserID)
|
||||
{
|
||||
User user = Client::Ref().GetAuthUser();
|
||||
char userName[12];
|
||||
char *userSession = new char[user.SessionID.length() + 1];
|
||||
std::strcpy(userName, ByteString::Build(user.UserID).c_str());
|
||||
std::strcpy(userSession, user.SessionID.c_str());
|
||||
HTTPContext = http_multipart_post_async((char*)URL.c_str(), postNames, postData, postLength, userName, NULL, userSession);
|
||||
delete[] userSession;
|
||||
}
|
||||
else
|
||||
{
|
||||
HTTPContext = http_multipart_post_async((char*)URL.c_str(), postNames, postData, postLength, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HTTPContext = http_async_req_start(NULL, (char *)URL.c_str(), NULL, 0, 0);
|
||||
if(Client::Ref().GetAuthUser().UserID)
|
||||
{
|
||||
User user = Client::Ref().GetAuthUser();
|
||||
char userName[12];
|
||||
char *userSession = new char[user.SessionID.length() + 1];
|
||||
std::strcpy(userName, ByteString::Build(user.UserID).c_str());
|
||||
std::strcpy(userSession, user.SessionID.c_str());
|
||||
http_auth_headers(HTTPContext, userName, NULL, userSession);
|
||||
delete[] userSession;
|
||||
}
|
||||
}
|
||||
//RequestTime = time(NULL);
|
||||
}
|
||||
return RequestBroker::OK;
|
||||
}
|
||||
|
||||
APIRequest::~APIRequest()
|
||||
{
|
||||
delete Parser;
|
||||
}
|
||||
|
||||
void APIRequest::Cleanup()
|
||||
{
|
||||
Request::Cleanup();
|
||||
if(ResultObject)
|
||||
{
|
||||
Parser->Cleanup(ResultObject);
|
||||
ResultObject = NULL;
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
#include <map>
|
||||
#include "RequestBroker.h"
|
||||
|
||||
class APIResultParser;
|
||||
class APIRequest: public RequestBroker::Request
|
||||
{
|
||||
public:
|
||||
bool Post;
|
||||
APIResultParser * Parser;
|
||||
ByteString URL;
|
||||
std::map<ByteString, ByteString> PostData;
|
||||
void * HTTPContext;
|
||||
APIRequest(ByteString url, APIResultParser * parser, ListenerHandle listener = ListenerHandle(0, (RequestListener*)0), int identifier = 0);
|
||||
APIRequest(ByteString url, std::map<ByteString, ByteString>, APIResultParser * parser, ListenerHandle listener = ListenerHandle(0, (RequestListener*)0), int identifier = 0);
|
||||
virtual RequestBroker::ProcessResponse Process(RequestBroker & rb);
|
||||
virtual ~APIRequest();
|
||||
virtual void Cleanup();
|
||||
};
|
||||
|
@ -1,16 +0,0 @@
|
||||
#ifndef APIRESULTPARSER_H
|
||||
#define APIRESULTPARSER_H
|
||||
|
||||
class APIResultParser
|
||||
{
|
||||
public:
|
||||
//Process the raw API response into a result object to be returned to the requester
|
||||
virtual void * ProcessResponse(unsigned char * data, int dataLength) { return 0; }
|
||||
|
||||
//A method to clean up the result of ProcessResponse in the event of a callback failure in APIRequest/RequestBroker
|
||||
virtual void Cleanup(void * objectPtr) { }
|
||||
|
||||
virtual ~APIResultParser() { }
|
||||
};
|
||||
|
||||
#endif
|
@ -1,158 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
#include <ctime>
|
||||
#include "ImageRequest.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "client/HTTP.h"
|
||||
|
||||
ImageRequest::ImageRequest(ByteString url, int width, int height, ListenerHandle listener, int identifier):
|
||||
Request(Image, listener, identifier)
|
||||
{
|
||||
URL = url;
|
||||
HTTPContext = NULL;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
ImageRequest::~ImageRequest()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
RequestBroker::ProcessResponse ImageRequest::Process(RequestBroker & rb)
|
||||
{
|
||||
VideoBuffer * image = NULL;
|
||||
|
||||
//Have a look at the thumbnail cache
|
||||
for(std::deque<std::pair<ByteString, VideoBuffer*> >::iterator iter = rb.imageCache.begin(), end = rb.imageCache.end(); iter != end; ++iter)
|
||||
{
|
||||
if((*iter).first == URL)
|
||||
{
|
||||
image = (*iter).second;
|
||||
/*#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " " << URL << " found in cache" << std::endl;
|
||||
#endif*/
|
||||
}
|
||||
}
|
||||
|
||||
if(!image)
|
||||
{
|
||||
if(HTTPContext)
|
||||
{
|
||||
if(http_async_req_status(HTTPContext))
|
||||
{
|
||||
pixel * imageData;
|
||||
char * data;
|
||||
int status, data_size, imgw, imgh;
|
||||
data = http_async_req_stop(HTTPContext, &status, &data_size);
|
||||
started = false;
|
||||
|
||||
if (status == 200 && data)
|
||||
{
|
||||
imageData = Graphics::ptif_unpack(data, data_size, &imgw, &imgh);
|
||||
free(data);
|
||||
|
||||
if(imageData)
|
||||
{
|
||||
//Success!
|
||||
image = new VideoBuffer(imageData, imgw, imgh);
|
||||
free(imageData);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Error thumbnail
|
||||
image = new VideoBuffer(32, 32);
|
||||
image->SetCharacter(14, 14, 'x', 255, 255, 255, 255);
|
||||
}
|
||||
|
||||
if(rb.imageCache.size() >= THUMB_CACHE_SIZE)
|
||||
{
|
||||
//Remove unnecessary from thumbnail cache
|
||||
delete rb.imageCache.front().second;
|
||||
rb.imageCache.pop_front();
|
||||
}
|
||||
rb.imageCache.push_back(std::pair<ByteString, VideoBuffer*>(URL, image));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Request for " << URL << " failed with status " << status << std::endl;
|
||||
#endif
|
||||
free(data);
|
||||
|
||||
return RequestBroker::Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Check for ongoing requests
|
||||
for(std::vector<Request*>::iterator iter = rb.activeRequests.begin(), end = rb.activeRequests.end(); iter != end; ++iter)
|
||||
{
|
||||
if((*iter)->Type != Request::Image)
|
||||
continue;
|
||||
ImageRequest * otherReq = (ImageRequest*)(*iter);
|
||||
if(otherReq->URL == URL && otherReq != this)
|
||||
{
|
||||
/*#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Request for " << URL << " found, appending." << std::endl;
|
||||
#endif*/
|
||||
//Add the current listener to the item already being requested
|
||||
(*iter)->Children.push_back(this);
|
||||
return RequestBroker::Duplicate;
|
||||
}
|
||||
}
|
||||
|
||||
//If it's not already being requested, request it
|
||||
/*#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Creating new request for " << URL << std::endl;
|
||||
#endif*/
|
||||
HTTPContext = http_async_req_start(NULL, (char *)URL.c_str(), NULL, 0, 0);
|
||||
started = true;
|
||||
RequestTime = time(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if(image)
|
||||
{
|
||||
|
||||
//Create a copy, to separate from the cache
|
||||
std::vector<Request *> children(Children.begin(), Children.end());
|
||||
Children.clear();
|
||||
|
||||
VideoBuffer * myVB = new VideoBuffer(*image);
|
||||
myVB->Resize(Width, Height, true);
|
||||
ResultObject = (void*)myVB;
|
||||
rb.requestComplete(this);
|
||||
for(std::vector<Request*>::iterator childIter = children.begin(), childEnd = children.end(); childIter != childEnd; ++childIter)
|
||||
{
|
||||
if((*childIter)->Type == Request::Image)
|
||||
{
|
||||
ImageRequest * childReq = (ImageRequest*)*childIter;
|
||||
VideoBuffer * tempImage = new VideoBuffer(*image);
|
||||
tempImage->Resize(childReq->Width, childReq->Height, true);
|
||||
childReq->ResultObject = (void*)tempImage;
|
||||
rb.requestComplete(*childIter);
|
||||
}
|
||||
}
|
||||
return RequestBroker::Finished;
|
||||
}
|
||||
|
||||
return RequestBroker::OK;
|
||||
}
|
||||
|
||||
void ImageRequest::Cleanup()
|
||||
{
|
||||
Request::Cleanup();
|
||||
if(ResultObject)
|
||||
{
|
||||
delete ((VideoBuffer*)ResultObject);
|
||||
ResultObject = NULL;
|
||||
}
|
||||
if (HTTPContext && started)
|
||||
{
|
||||
http_force_close(HTTPContext);
|
||||
http_async_req_stop(HTTPContext, nullptr, nullptr);
|
||||
started = false;
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
#include "RequestBroker.h"
|
||||
|
||||
class ImageRequest: public RequestBroker::Request
|
||||
{
|
||||
public:
|
||||
int Width, Height;
|
||||
ByteString URL;
|
||||
int RequestTime;
|
||||
void * HTTPContext;
|
||||
bool started = false;
|
||||
ImageRequest(ByteString url, int width, int height, ListenerHandle listener, int identifier = 0);
|
||||
virtual RequestBroker::ProcessResponse Process(RequestBroker & rb);
|
||||
virtual ~ImageRequest();
|
||||
virtual void Cleanup();
|
||||
};
|
@ -1,264 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
#include <ctime>
|
||||
#include "RequestBroker.h"
|
||||
#include "RequestListener.h"
|
||||
#include "ThumbRenderRequest.h"
|
||||
#include "ImageRequest.h"
|
||||
#include "Platform.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/GameSave.h"
|
||||
#include "graphics/Graphics.h"
|
||||
|
||||
//Asynchronous Thumbnail render & request processing
|
||||
|
||||
unsigned int RequestListener::nextListenerID = 0;
|
||||
|
||||
RequestBroker::RequestBroker()
|
||||
{
|
||||
thumbnailQueueRunning = false;
|
||||
|
||||
//listenersMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_init (&listenersMutex, NULL);
|
||||
|
||||
|
||||
pthread_mutex_init (&runningMutex, NULL);
|
||||
|
||||
|
||||
pthread_mutex_init (&requestQueueMutex, NULL);
|
||||
|
||||
|
||||
pthread_mutex_init (&completeQueueMutex, NULL);
|
||||
}
|
||||
|
||||
RequestBroker::~RequestBroker()
|
||||
{
|
||||
for(std::deque<std::pair<ByteString, VideoBuffer*> >::iterator iter = imageCache.begin(), end = imageCache.end(); iter != end; ++iter)
|
||||
{
|
||||
delete (*iter).second;
|
||||
}
|
||||
}
|
||||
|
||||
void RequestBroker::assureRunning()
|
||||
{
|
||||
pthread_mutex_lock(&runningMutex);
|
||||
bool running = thumbnailQueueRunning;
|
||||
thumbnailQueueRunning = true;
|
||||
pthread_mutex_unlock(&runningMutex);
|
||||
|
||||
if(!running)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Starting background thread for new " << __FUNCTION__ << " request" << std::endl;
|
||||
#endif
|
||||
pthread_create(&thumbnailQueueThread, 0, &RequestBroker::thumbnailQueueProcessHelper, this);
|
||||
}
|
||||
}
|
||||
|
||||
void RequestBroker::Shutdown()
|
||||
{
|
||||
pthread_mutex_lock(&runningMutex);
|
||||
if(thumbnailQueueRunning)
|
||||
{
|
||||
thumbnailQueueRunning = false;
|
||||
pthread_mutex_unlock(&runningMutex);
|
||||
pthread_join(thumbnailQueueThread, NULL);
|
||||
}
|
||||
else
|
||||
pthread_mutex_unlock(&runningMutex);
|
||||
|
||||
std::vector<Request*>::iterator req = activeRequests.begin();
|
||||
while(req != activeRequests.end())
|
||||
{
|
||||
(*req)->Cleanup();
|
||||
delete (*req);
|
||||
req++;
|
||||
}
|
||||
}
|
||||
|
||||
void RequestBroker::Start(Request * request, RequestListener * tListener, int identifier)
|
||||
{
|
||||
ListenerHandle handle = AttachRequestListener(tListener);
|
||||
|
||||
request->Identifier = identifier;
|
||||
request->Listener = handle;
|
||||
pthread_mutex_lock(&requestQueueMutex);
|
||||
requestQueue.push_back(request);
|
||||
pthread_mutex_unlock(&requestQueueMutex);
|
||||
|
||||
assureRunning();
|
||||
}
|
||||
|
||||
TH_ENTRY_POINT void * RequestBroker::thumbnailQueueProcessHelper(void * ref)
|
||||
{
|
||||
((RequestBroker*)ref)->thumbnailQueueProcessTH();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RequestBroker::FlushThumbQueue()
|
||||
{
|
||||
pthread_mutex_lock(&completeQueueMutex);
|
||||
while(completeQueue.size())
|
||||
{
|
||||
if(CheckRequestListener(completeQueue.front()->Listener))
|
||||
{
|
||||
completeQueue.front()->Listener.second->OnResponseReady(completeQueue.front()->ResultObject, completeQueue.front()->Identifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Listener lost, discarding request" << std::endl;
|
||||
#endif
|
||||
completeQueue.front()->Cleanup();
|
||||
}
|
||||
delete completeQueue.front();
|
||||
completeQueue.pop();
|
||||
}
|
||||
pthread_mutex_unlock(&completeQueueMutex);
|
||||
}
|
||||
|
||||
void RequestBroker::thumbnailQueueProcessTH()
|
||||
{
|
||||
time_t lastAction = time(NULL);
|
||||
pthread_mutex_lock(&runningMutex);
|
||||
thumbnailQueueRunning = true;
|
||||
pthread_mutex_unlock(&runningMutex);
|
||||
while(true)
|
||||
{
|
||||
//Shutdown after 2 seconds of idle
|
||||
if(time(NULL) - lastAction > 2)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Idle shutdown" << std::endl;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_lock(&runningMutex);
|
||||
bool running = thumbnailQueueRunning;
|
||||
pthread_mutex_unlock(&runningMutex);
|
||||
if(!running)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Requested shutdown" << std::endl;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if(activeRequests.size())
|
||||
{
|
||||
std::vector<Request*>::iterator req = activeRequests.begin();
|
||||
while(req != activeRequests.end())
|
||||
{
|
||||
ProcessResponse resultStatus = OK;
|
||||
Request * r = *req;
|
||||
resultStatus = r->Process(*this);
|
||||
if(resultStatus == Duplicate || resultStatus == Failed || resultStatus == Finished)
|
||||
{
|
||||
if ((resultStatus == Duplicate || resultStatus == Failed) && CheckRequestListener(r->Listener))
|
||||
r->Listener.second->OnResponseFailed(r->Identifier);
|
||||
req = activeRequests.erase(req);
|
||||
}
|
||||
else
|
||||
{
|
||||
req++;
|
||||
}
|
||||
}
|
||||
lastAction = time(NULL);
|
||||
}
|
||||
|
||||
//Move any items from the request queue to the processing queue
|
||||
pthread_mutex_lock(&requestQueueMutex);
|
||||
std::vector<Request*>::iterator newReq = requestQueue.begin();
|
||||
while(newReq != requestQueue.end())
|
||||
{
|
||||
if(activeRequests.size() > 5)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
activeRequests.push_back(*newReq);
|
||||
newReq = requestQueue.erase(newReq);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&requestQueueMutex);
|
||||
Platform::Millisleep(1);
|
||||
}
|
||||
pthread_mutex_lock(&runningMutex);
|
||||
thumbnailQueueRunning = false;
|
||||
pthread_mutex_unlock(&runningMutex);
|
||||
}
|
||||
|
||||
void RequestBroker::requestComplete(Request * completedRequest)
|
||||
{
|
||||
pthread_mutex_lock(&completeQueueMutex);
|
||||
completeQueue.push(completedRequest);
|
||||
pthread_mutex_unlock(&completeQueueMutex);
|
||||
}
|
||||
|
||||
bool RequestBroker::CheckRequestListener(ListenerHandle handle)
|
||||
{
|
||||
pthread_mutex_lock(&listenersMutex);
|
||||
int count = std::count(validListeners.begin(), validListeners.end(), handle);
|
||||
pthread_mutex_unlock(&listenersMutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
ListenerHandle RequestBroker::AttachRequestListener(RequestListener * tListener)
|
||||
{
|
||||
ListenerHandle handle = ListenerHandle(tListener->ListenerID, tListener);
|
||||
pthread_mutex_lock(&listenersMutex);
|
||||
validListeners.push_back(handle);
|
||||
pthread_mutex_unlock(&listenersMutex);
|
||||
return handle;
|
||||
}
|
||||
|
||||
void RequestBroker::DetachRequestListener(RequestListener * tListener)
|
||||
{
|
||||
if (!validListeners.size())
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&listenersMutex);
|
||||
|
||||
std::vector<ListenerHandle>::iterator iter = validListeners.begin();
|
||||
while (iter != validListeners.end())
|
||||
{
|
||||
if(*iter == ListenerHandle(tListener->ListenerID, tListener))
|
||||
iter = validListeners.erase(iter);
|
||||
else
|
||||
++iter;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&listenersMutex);
|
||||
}
|
||||
|
||||
RequestBroker::Request::Request(RequestType type, ListenerHandle listener, int identifier)
|
||||
{
|
||||
Type = type;
|
||||
Listener = listener;
|
||||
ResultObject = NULL;
|
||||
Identifier = identifier;
|
||||
}
|
||||
RequestBroker::Request::~Request()
|
||||
{
|
||||
std::vector<Request*>::iterator iter = Children.begin();
|
||||
while(iter != Children.end())
|
||||
{
|
||||
delete (*iter);
|
||||
iter++;
|
||||
}
|
||||
Children.clear();
|
||||
}
|
||||
void RequestBroker::Request::Cleanup()
|
||||
{
|
||||
std::vector<Request*>::iterator iter = Children.begin();
|
||||
while(iter != Children.end())
|
||||
{
|
||||
(*iter)->Cleanup();
|
||||
iter++;
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
#pragma once
|
||||
#include <queue>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
#include <deque>
|
||||
#include "common/String.h"
|
||||
#include "common/tpt-thread.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "common/Singleton.h"
|
||||
|
||||
class GameSave;
|
||||
class VideoBuffer;
|
||||
class RequestListener;
|
||||
typedef std::pair<int, RequestListener*> ListenerHandle;
|
||||
class RequestBroker: public Singleton<RequestBroker>
|
||||
{
|
||||
friend class ImageRequest;
|
||||
friend class APIRequest;
|
||||
friend class WebRequest;
|
||||
friend class ThumbRenderRequest;
|
||||
public:
|
||||
class Request;
|
||||
private:
|
||||
|
||||
pthread_mutex_t listenersMutex;
|
||||
pthread_mutex_t runningMutex;
|
||||
pthread_mutex_t requestQueueMutex;
|
||||
pthread_mutex_t completeQueueMutex;
|
||||
|
||||
pthread_t thumbnailQueueThread;
|
||||
bool thumbnailQueueRunning;
|
||||
|
||||
std::vector<ListenerHandle> validListeners;
|
||||
|
||||
std::deque<std::pair<ByteString, VideoBuffer*> > imageCache;
|
||||
|
||||
std::queue<Request*> completeQueue;
|
||||
std::vector<Request*> requestQueue;
|
||||
std::vector<Request*> activeRequests;
|
||||
|
||||
TH_ENTRY_POINT static void * thumbnailQueueProcessHelper(void * ref);
|
||||
void thumbnailQueueProcessTH();
|
||||
void assureRunning();
|
||||
|
||||
void requestComplete(Request * completedRequest);
|
||||
|
||||
public:
|
||||
RequestBroker();
|
||||
virtual ~RequestBroker();
|
||||
void Shutdown();
|
||||
|
||||
void FlushThumbQueue();
|
||||
void Start(Request * request, RequestListener * tLIstener, int identifier = 0);
|
||||
|
||||
bool CheckRequestListener(ListenerHandle handle);
|
||||
ListenerHandle AttachRequestListener(RequestListener * tListener);
|
||||
void DetachRequestListener(RequestListener * tListener);
|
||||
enum ProcessResponse { Finished, OK, Canceled, Failed, Duplicate };
|
||||
class Request
|
||||
{
|
||||
public:
|
||||
enum RequestType { ThumbnailRender, Image, API, Web };
|
||||
int Identifier;
|
||||
RequestType Type;
|
||||
void * ResultObject;
|
||||
ListenerHandle Listener;
|
||||
std::vector<Request*> Children;
|
||||
Request(RequestType type, ListenerHandle listener, int identifier);
|
||||
virtual ProcessResponse Process(RequestBroker & rb) { return Failed; }
|
||||
virtual ~Request();
|
||||
virtual void Cleanup();
|
||||
};
|
||||
};
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class RequestListener
|
||||
{
|
||||
public:
|
||||
static unsigned int nextListenerID;
|
||||
int ListenerID;
|
||||
RequestListener() { ListenerID = nextListenerID++; }
|
||||
virtual ~RequestListener() {}
|
||||
|
||||
virtual void OnResponseReady(void * response, int identifier) {}
|
||||
virtual void OnResponseFailed(int identifier) {}
|
||||
};
|
@ -1,66 +0,0 @@
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
#include "ThumbRenderRequest.h"
|
||||
#include "client/GameSave.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "simulation/SaveRenderer.h"
|
||||
|
||||
ThumbRenderRequest::ThumbRenderRequest(GameSave * save, bool decorations, bool fire, int width, int height, bool autoRescale, ListenerHandle listener, int identifier):
|
||||
RequestBroker::Request(ThumbnailRender, listener, identifier),
|
||||
Save(save),
|
||||
Width(width),
|
||||
Height(height),
|
||||
Decorations(decorations),
|
||||
Fire(fire),
|
||||
autoRescale(autoRescale)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
RequestBroker::ProcessResponse ThumbRenderRequest::Process(RequestBroker & rb)
|
||||
{
|
||||
VideoBuffer * thumbnail = SaveRenderer::Ref().Render(Save, Decorations, Fire);
|
||||
|
||||
delete Save;
|
||||
Save = NULL;
|
||||
|
||||
if (thumbnail)
|
||||
{
|
||||
if (!autoRescale)
|
||||
thumbnail->Resize(Width, Height, true);
|
||||
else
|
||||
{
|
||||
int scaleX = (int)std::ceil((float)thumbnail->Width / Width);
|
||||
int scaleY = (int)std::ceil((float)thumbnail->Height / Height);
|
||||
int scale = scaleX > scaleY ? scaleX : scaleY;
|
||||
int newWidth = thumbnail->Width / scale, newHeight = thumbnail->Height / scale;
|
||||
thumbnail->Resize(newWidth, newHeight, true);
|
||||
Width = newWidth;
|
||||
Height = newHeight;
|
||||
}
|
||||
ResultObject = (void*)thumbnail;
|
||||
rb.requestComplete((Request*)this);
|
||||
return RequestBroker::Finished;
|
||||
}
|
||||
else
|
||||
{
|
||||
return RequestBroker::Failed;
|
||||
}
|
||||
return RequestBroker::Failed;
|
||||
}
|
||||
|
||||
ThumbRenderRequest::~ThumbRenderRequest()
|
||||
{
|
||||
delete Save;
|
||||
}
|
||||
|
||||
void ThumbRenderRequest::Cleanup()
|
||||
{
|
||||
Request::Cleanup();
|
||||
if(ResultObject)
|
||||
{
|
||||
delete ((VideoBuffer*)ResultObject);
|
||||
ResultObject = NULL;
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#include "RequestBroker.h"
|
||||
|
||||
class GameSave;
|
||||
class ThumbRenderRequest: public RequestBroker::Request
|
||||
{
|
||||
public:
|
||||
GameSave * Save;
|
||||
int Width, Height;
|
||||
bool Decorations;
|
||||
bool Fire;
|
||||
bool autoRescale;
|
||||
|
||||
ThumbRenderRequest(GameSave * save, bool decorations, bool fire, int width, int height, bool autoRescale, ListenerHandle listener, int identifier = 0);
|
||||
virtual RequestBroker::ProcessResponse Process(RequestBroker & rb);
|
||||
virtual ~ThumbRenderRequest();
|
||||
virtual void Cleanup();
|
||||
};
|
||||
|
@ -1,151 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <typeinfo>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include "Config.h"
|
||||
#include "Format.h"
|
||||
#include "client/Client.h"
|
||||
#include "WebRequest.h"
|
||||
#include "client/HTTP.h"
|
||||
#include "APIResultParser.h"
|
||||
|
||||
WebRequest::WebRequest(ByteString url, ListenerHandle listener, int identifier):
|
||||
RequestBroker::Request(API, listener, identifier)
|
||||
{
|
||||
Post = false;
|
||||
HTTPContext = NULL;
|
||||
URL = url;
|
||||
}
|
||||
|
||||
WebRequest::WebRequest(ByteString url, std::map<ByteString, ByteString> postData, ListenerHandle listener, int identifier):
|
||||
RequestBroker::Request(API, listener, identifier)
|
||||
{
|
||||
Post = true;
|
||||
PostData = postData;
|
||||
HTTPContext = NULL;
|
||||
URL = url;
|
||||
}
|
||||
|
||||
RequestBroker::ProcessResponse WebRequest::Process(RequestBroker & rb)
|
||||
{
|
||||
if(HTTPContext)
|
||||
{
|
||||
if(http_async_req_status(HTTPContext))
|
||||
{
|
||||
char * data;
|
||||
int status, data_size;
|
||||
data = http_async_req_stop(HTTPContext, &status, &data_size);
|
||||
|
||||
ByteString nothing;
|
||||
Client::Ref().ParseServerReturn(nothing, status, true);
|
||||
if (status == 200 && data)
|
||||
{
|
||||
void * resultObject = new std::vector<unsigned char>(data, data+data_size);
|
||||
|
||||
if(resultObject)
|
||||
{
|
||||
this->ResultObject = resultObject;
|
||||
rb.requestComplete(this);
|
||||
free(data);
|
||||
return RequestBroker::Finished;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Request for " << URL << " could not be parsed: " << data << std::endl;
|
||||
#endif
|
||||
free(data);
|
||||
return RequestBroker::Failed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Request for " << URL << " failed with status " << status << std::endl;
|
||||
#endif
|
||||
free(data);
|
||||
|
||||
return RequestBroker::Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " New Request for " << URL << std::endl;
|
||||
#endif
|
||||
if(Post)
|
||||
{
|
||||
char ** postNames = new char*[PostData.size() + 1];
|
||||
char ** postData = new char*[PostData.size()];
|
||||
int * postLength = new int[PostData.size()];
|
||||
|
||||
int i = 0;
|
||||
std::map<ByteString, ByteString>::iterator iter = PostData.begin();
|
||||
while(iter != PostData.end())
|
||||
{
|
||||
ByteString name = iter->first;
|
||||
ByteString data = iter->second;
|
||||
char * cName = new char[name.length() + 1];
|
||||
char * cData = new char[data.length() + 1];
|
||||
std::strcpy(cName, name.c_str());
|
||||
std::strcpy(cData, data.c_str());
|
||||
postNames[i] = cName;
|
||||
postData[i] = cData;
|
||||
postLength[i] = data.length();
|
||||
i++;
|
||||
iter++;
|
||||
}
|
||||
postNames[i] = NULL;
|
||||
|
||||
if(Client::Ref().GetAuthUser().UserID)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << typeid(*this).name() << " Authenticated " << std::endl;
|
||||
#endif
|
||||
User user = Client::Ref().GetAuthUser();
|
||||
char userName[12];
|
||||
char *userSession = new char[user.SessionID.length() + 1];
|
||||
std::strcpy(userName, ByteString::Build(user.UserID).c_str());
|
||||
std::strcpy(userSession, user.SessionID.c_str());
|
||||
HTTPContext = http_multipart_post_async((char*)URL.c_str(), postNames, postData, postLength, userName, NULL, userSession);
|
||||
delete[] userSession;
|
||||
}
|
||||
else
|
||||
{
|
||||
HTTPContext = http_multipart_post_async((char*)URL.c_str(), postNames, postData, postLength, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HTTPContext = http_async_req_start(NULL, (char *)URL.c_str(), NULL, 0, 0);
|
||||
if(Client::Ref().GetAuthUser().UserID)
|
||||
{
|
||||
User user = Client::Ref().GetAuthUser();
|
||||
char userName[12];
|
||||
char *userSession = new char[user.SessionID.length() + 1];
|
||||
std::strcpy(userName, ByteString::Build(user.UserID).c_str());
|
||||
std::strcpy(userSession, user.SessionID.c_str());
|
||||
http_auth_headers(HTTPContext, userName, NULL, userSession);
|
||||
delete[] userSession;
|
||||
}
|
||||
}
|
||||
}
|
||||
return RequestBroker::OK;
|
||||
}
|
||||
|
||||
WebRequest::~WebRequest()
|
||||
{
|
||||
}
|
||||
|
||||
void WebRequest::Cleanup()
|
||||
{
|
||||
Request::Cleanup();
|
||||
if(ResultObject)
|
||||
{
|
||||
delete (std::vector<unsigned char>*)ResultObject;
|
||||
ResultObject = NULL;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
#include <map>
|
||||
#include "RequestBroker.h"
|
||||
|
||||
class WebRequest: public RequestBroker::Request
|
||||
{
|
||||
public:
|
||||
bool Post;
|
||||
ByteString URL;
|
||||
std::map<ByteString, ByteString> PostData;
|
||||
void * HTTPContext;
|
||||
WebRequest(ByteString url, ListenerHandle listener = ListenerHandle(0, (RequestListener*)0), int identifier = 0);
|
||||
WebRequest(ByteString url, std::map<ByteString, ByteString>, ListenerHandle listener = ListenerHandle(0, (RequestListener*)0), int identifier = 0);
|
||||
virtual RequestBroker::ProcessResponse Process(RequestBroker & rb);
|
||||
virtual ~WebRequest();
|
||||
virtual void Cleanup();
|
||||
};
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "gui/Style.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/UserInfo.h"
|
||||
#include "client/requestbroker/RequestListener.h"
|
||||
#include "Format.h"
|
||||
#include "Platform.h"
|
||||
|
||||
@ -49,7 +48,8 @@ ProfileActivity::ProfileActivity(ByteString username) :
|
||||
a->saving = true;
|
||||
a->info.location = ((ui::Textbox*)a->location)->GetText();
|
||||
a->info.biography = ((ui::Textbox*)a->bio)->GetText();
|
||||
RequestBroker::Ref().Start(Client::Ref().SaveUserInfoAsync(a->info), a);
|
||||
a->SaveUserInfoRequestMonitor::RequestSetup(a->info);
|
||||
a->SaveUserInfoRequestMonitor::RequestStart();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -69,7 +69,9 @@ ProfileActivity::ProfileActivity(ByteString username) :
|
||||
AddComponent(closeButton);
|
||||
|
||||
loading = true;
|
||||
RequestBroker::Ref().Start(Client::Ref().GetUserInfoAsync(username), this);
|
||||
|
||||
GetUserInfoRequestMonitor::RequestSetup(username);
|
||||
GetUserInfoRequestMonitor::RequestStart();
|
||||
}
|
||||
|
||||
void ProfileActivity::setUserInfo(UserInfo newInfo)
|
||||
@ -229,27 +231,31 @@ void ProfileActivity::setUserInfo(UserInfo newInfo)
|
||||
scrollPanel->InnerSize = ui::Point(Size.X, currentY);
|
||||
}
|
||||
|
||||
void ProfileActivity::OnResponseReady(void * userDataPtr, int identifier)
|
||||
void ProfileActivity::OnResponse(bool SaveUserInfoStatus)
|
||||
{
|
||||
if (loading)
|
||||
{
|
||||
loading = false;
|
||||
setUserInfo(*(UserInfo*)userDataPtr);
|
||||
delete (UserInfo*)userDataPtr;
|
||||
}
|
||||
else if (saving)
|
||||
if (SaveUserInfoStatus)
|
||||
{
|
||||
Exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
doError = true;
|
||||
doErrorMessage = "Could not save user info: " + Client::Ref().GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileActivity::OnResponseFailed(int identifier)
|
||||
void ProfileActivity::OnResponse(std::unique_ptr<UserInfo> getUserInfoResult)
|
||||
{
|
||||
doError = true;
|
||||
if (loading)
|
||||
if (getUserInfoResult)
|
||||
{
|
||||
loading = false;
|
||||
setUserInfo(*getUserInfoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
doError = true;
|
||||
doErrorMessage = "Could not load user info: " + Client::Ref().GetLastError();
|
||||
else if (saving)
|
||||
doErrorMessage = "Could not save user info: " + Client::Ref().GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileActivity::OnTick(float dt)
|
||||
@ -259,6 +265,9 @@ void ProfileActivity::OnTick(float dt)
|
||||
ErrorMessage::Blocking("Error", doErrorMessage);
|
||||
Exit();
|
||||
}
|
||||
|
||||
SaveUserInfoRequestMonitor::RequestPoll();
|
||||
GetUserInfoRequestMonitor::RequestPoll();
|
||||
}
|
||||
|
||||
void ProfileActivity::OnDraw()
|
||||
@ -284,6 +293,5 @@ void ProfileActivity::ResizeArea()
|
||||
|
||||
ProfileActivity::~ProfileActivity()
|
||||
{
|
||||
RequestBroker::Ref().DetachRequestListener(this);
|
||||
}
|
||||
|
||||
|
@ -3,16 +3,20 @@
|
||||
|
||||
#include "common/String.h"
|
||||
#include "Activity.h"
|
||||
#include "client/requestbroker/RequestListener.h"
|
||||
#include "client/UserInfo.h"
|
||||
#include "gui/interface/Window.h"
|
||||
#include "client/SaveUserInfoRequest.h"
|
||||
#include "client/GetUserInfoRequest.h"
|
||||
#include "client/RequestMonitor.h"
|
||||
|
||||
namespace ui
|
||||
{
|
||||
class Label;
|
||||
class ScrollPanel;
|
||||
}
|
||||
class ProfileActivity: public WindowActivity, public RequestListener {
|
||||
using SaveUserInfoRequestMonitor = http::RequestMonitor<http::SaveUserInfoRequest>;
|
||||
using GetUserInfoRequestMonitor = http::RequestMonitor<http::GetUserInfoRequest>;
|
||||
class ProfileActivity: public WindowActivity, public SaveUserInfoRequestMonitor, public GetUserInfoRequestMonitor {
|
||||
ui::ScrollPanel *scrollPanel;
|
||||
ui::Label *location;
|
||||
ui::Label *bio;
|
||||
@ -26,12 +30,13 @@ class ProfileActivity: public WindowActivity, public RequestListener {
|
||||
public:
|
||||
ProfileActivity(ByteString username);
|
||||
virtual ~ProfileActivity();
|
||||
virtual void OnResponseReady(void * userDataPtr, int identifier);
|
||||
virtual void OnResponseFailed(int identifier);
|
||||
virtual void OnTick(float dt);
|
||||
virtual void OnDraw();
|
||||
virtual void OnTryExit(ExitMethod method);
|
||||
|
||||
void OnResponse(bool saveUserInfoStatus) override;
|
||||
void OnResponse(std::unique_ptr<UserInfo> getUserInfoResult) override;
|
||||
|
||||
void ResizeArea();
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user