shuffle between curl and httpc

This commit is contained in:
Sorunome 2019-10-18 12:40:19 +02:00
parent 29a44c9371
commit 48bdefe5db
No known key found for this signature in database
GPG key ID: 63E31F7B5993A9C4
2 changed files with 160 additions and 23 deletions

View file

@ -29,6 +29,8 @@ public:
json_t* doSync(std::string token); json_t* doSync(std::string token);
void startSync(); void startSync();
json_t* doRequest(const char* method, std::string path, json_t* body = NULL); json_t* doRequest(const char* method, std::string path, json_t* body = NULL);
json_t* doRequestCurl(const char* method, std::string url, json_t* body = NULL);
json_t* doRequestHttpc(const char* method, std::string url, json_t* body = NULL);
public: public:
Client(std::string homeserverUrl, std::string matrixToken = "", Store* clientStore = NULL); Client(std::string homeserverUrl, std::string matrixToken = "", Store* clientStore = NULL);
std::string getToken(); std::string getToken();
@ -42,9 +44,9 @@ public:
std::string sendEvent(std::string roomId, std::string eventType, json_t* content); std::string sendEvent(std::string roomId, std::string eventType, json_t* content);
std::string sendStateEvent(std::string roomId, std::string type, std::string stateKey, json_t* content); std::string sendStateEvent(std::string roomId, std::string type, std::string stateKey, json_t* content);
std::string redactEvent(std::string roomId, std::string eventId, std::string reason = ""); std::string redactEvent(std::string roomId, std::string eventId, std::string reason = "");
void setSyncEventCallback(void (*cb)(std::string roomId, json_t* event));
void startSyncLoop(); void startSyncLoop();
void stopSyncLoop(); void stopSyncLoop();
void setSyncEventCallback(void (*cb)(std::string roomId, json_t* event));
}; };
}; // namespace Matrix }; // namespace Matrix

View file

@ -15,7 +15,7 @@
#define SOC_BUFFERSIZE 0x100000 #define SOC_BUFFERSIZE 0x100000
#define SYNC_TIMEOUT 10000 #define SYNC_TIMEOUT 10000
#define DEBUG 0 #define DEBUG 1
#if DEBUG #if DEBUG
#define D #define D
@ -23,9 +23,16 @@
#define D for(;0;) #define D for(;0;)
#endif #endif
PrintConsole* topScreenConsole = NULL;
#define printf_top(f_, ...) do {consoleSelect(topScreenConsole);printf((f_), ##__VA_ARGS__);} while(0)
namespace Matrix { namespace Matrix {
#define POST_BUFFERSIZE 0x100000
static u32 *SOC_buffer = NULL; static u32 *SOC_buffer = NULL;
bool HTTPC_inited = false;
Client::Client(std::string homeserverUrl, std::string matrixToken, Store* clientStore) { Client::Client(std::string homeserverUrl, std::string matrixToken, Store* clientStore) {
hsUrl = homeserverUrl; hsUrl = homeserverUrl;
@ -34,6 +41,10 @@ Client::Client(std::string homeserverUrl, std::string matrixToken, Store* client
clientStore = new MemoryStore(); clientStore = new MemoryStore();
} }
store = clientStore; store = clientStore;
if (!topScreenConsole) {
topScreenConsole = new PrintConsole;
consoleInit(GFX_TOP, topScreenConsole);
}
} }
std::string Client::getToken() { std::string Client::getToken() {
@ -79,7 +90,7 @@ std::string Client::getUserId() {
json_decref(ret); json_decref(ret);
return ""; return "";
} }
const char* userIdStr = json_string_value(userId); std::string userIdStr = json_string_value(userId);
json_decref(ret); json_decref(ret);
userIdCache = std::string(userIdStr); userIdCache = std::string(userIdStr);
return userIdCache; return userIdCache;
@ -98,7 +109,8 @@ std::string Client::resolveRoom(std::string alias) {
json_decref(ret); json_decref(ret);
return ""; return "";
} }
const char* roomIdStr = json_string_value(roomId); std::string roomIdStr = json_string_value(roomId);
D printf_top("Room ID: %s\n", roomIdStr.c_str());
json_decref(ret); json_decref(ret);
return roomIdStr; return roomIdStr;
} }
@ -147,7 +159,7 @@ std::string Client::sendEvent(std::string roomId, std::string eventType, json_t*
json_decref(ret); json_decref(ret);
return ""; return "";
} }
const char* eventIdStr = json_string_value(eventId); std::string eventIdStr = json_string_value(eventId);
json_decref(ret); json_decref(ret);
return eventIdStr; return eventIdStr;
} }
@ -164,7 +176,7 @@ std::string Client::sendStateEvent(std::string roomId, std::string type, std::st
json_decref(ret); json_decref(ret);
return ""; return "";
} }
const char* eventIdStr = json_string_value(eventId); std::string eventIdStr = json_string_value(eventId);
json_decref(ret); json_decref(ret);
return eventIdStr; return eventIdStr;
} }
@ -201,7 +213,6 @@ void Client::startSyncLoop() {
isSyncing = true; isSyncing = true;
stopSyncing = false; stopSyncing = false;
s32 prio = 0; s32 prio = 0;
D printf("%lld\n", (u64)this);
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
syncThread = threadCreate(startSyncLoopWithoutClass, this, 8*1024, prio-1, -2, true); syncThread = threadCreate(startSyncLoopWithoutClass, this, 8*1024, prio-1, -2, true);
} }
@ -249,20 +260,20 @@ void Client::processSync(json_t* sync) {
if (joinedRooms) { if (joinedRooms) {
json_object_foreach(joinedRooms, roomId, room) { json_object_foreach(joinedRooms, roomId, room) {
// rooms that we are joined // rooms that we are joined
D printf("%s:\n", roomId); D printf_top("%s:\n", roomId);
json_t* timeline = json_object_get(room, "timeline"); json_t* timeline = json_object_get(room, "timeline");
if (!timeline) { if (!timeline) {
D printf("no timeline\n"); D printf_top("no timeline\n");
continue; continue;
} }
json_t* events = json_object_get(timeline, "events"); json_t* events = json_object_get(timeline, "events");
if (!events) { if (!events) {
D printf("no events\n"); D printf_top("no events\n");
continue; continue;
} }
json_array_foreach(events, index, event) { json_array_foreach(events, index, event) {
json_t* eventType = json_object_get(event, "type"); json_t* eventType = json_object_get(event, "type");
D printf("%s\n", json_string_value(eventType)); D printf_top("%s\n", json_string_value(eventType));
if (sync_event_callback) { if (sync_event_callback) {
sync_event_callback(roomId, event); sync_event_callback(roomId, event);
} }
@ -282,10 +293,8 @@ void Client::startSync() {
// set the token for the next batch // set the token for the next batch
json_t* token = json_object_get(ret, "next_batch"); json_t* token = json_object_get(ret, "next_batch");
if (token) { if (token) {
D printf("Found next batch\n");
store->setSyncToken(json_string_value(token)); store->setSyncToken(json_string_value(token));
} else { } else {
D printf("No next batch\n");
store->setSyncToken(""); store->setSyncToken("");
} }
processSync(ret); processSync(ret);
@ -296,13 +305,13 @@ void Client::startSync() {
} }
json_t* Client::doSync(std::string token) { json_t* Client::doSync(std::string token) {
D printf("Doing sync with token %s\n", token.c_str()); // D printf_top("Doing sync with token %s\n", token.c_str());
std::string query = "?full_state=false&timeout=" + std::to_string(SYNC_TIMEOUT); std::string query = "?full_state=false&timeout=" + std::to_string(SYNC_TIMEOUT);
if (token != "") { if (token != "") {
query += "&since=" + token; query += "&since=" + token;
} }
return doRequest("GET", "/_matrix/client/r0/sync" + query); return doRequest("GET", "/_matrix/client/r0/sync" + query, NULL);
} }
size_t DoRequestWriteCallback(char *contents, size_t size, size_t nmemb, void *userp) { size_t DoRequestWriteCallback(char *contents, size_t size, size_t nmemb, void *userp) {
@ -310,18 +319,30 @@ size_t DoRequestWriteCallback(char *contents, size_t size, size_t nmemb, void *u
return size * nmemb; return size * nmemb;
} }
bool doingCurlRequest = false;
json_t* Client::doRequest(const char* method, std::string path, json_t* body) { json_t* Client::doRequest(const char* method, std::string path, json_t* body) {
std::string url = hsUrl + path; std::string url = hsUrl + path;
requestId++; requestId++;
if (!doingCurlRequest) {
D printf("Opening Request %d\n%s\n", requestId, url.c_str()); doingCurlRequest = true;
json_t* ret = doRequestCurl(method, url, body);
doingCurlRequest = false;
return ret;
} else {
return doRequestHttpc(method, url, body);
}
}
json_t* Client::doRequestCurl(const char* method, std::string url, json_t* body) {
D printf_top("Opening Request %d with CURL\n%s\n", requestId, url.c_str());
if (!SOC_buffer) { if (!SOC_buffer) {
SOC_buffer = (u32*)memalign(0x1000, 0x100000); SOC_buffer = (u32*)memalign(0x1000, POST_BUFFERSIZE);
if (!SOC_buffer) { if (!SOC_buffer) {
return NULL; return NULL;
} }
if (socInit(SOC_buffer, 0x100000) != 0) { if (socInit(SOC_buffer, POST_BUFFERSIZE) != 0) {
return NULL; return NULL;
} }
} }
@ -329,7 +350,7 @@ json_t* Client::doRequest(const char* method, std::string path, json_t* body) {
CURL* curl = curl_easy_init(); CURL* curl = curl_easy_init();
CURLcode res; CURLcode res;
if (!curl) { if (!curl) {
D printf("curl init failed\n"); D printf_top("curl init failed\n");
return NULL; return NULL;
} }
std::string readBuffer; std::string readBuffer;
@ -361,15 +382,129 @@ json_t* Client::doRequest(const char* method, std::string path, json_t* body) {
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
if (res != CURLE_OK) { if (res != CURLE_OK) {
D printf("curl res not ok %d\n", res); D printf_top("curl res not ok %d\n", res);
return NULL; return NULL;
} }
// D printf("%s\n", readBuffer.c_str()); // D printf_top("%s\n", readBuffer.c_str());
json_error_t error; json_error_t error;
json_t* content = json_loads(readBuffer.c_str(), 0, &error); json_t* content = json_loads(readBuffer.c_str(), 0, &error);
if (!content) { if (!content) {
D printf("Failed to parse json\n"); D printf_top("Failed to parse json\n");
return NULL;
}
return content;
}
json_t* Client::doRequestHttpc(const char* method, std::string url, json_t* body) {
D printf_top("Opening Request %d with HTTPC\n%s\n", requestId, url.c_str());
if (!HTTPC_inited) {
if (httpcInit(POST_BUFFERSIZE) != 0) {
return NULL;
}
HTTPC_inited = true;
}
Result ret = 0;
httpcContext context;
HTTPC_RequestMethod methodReal = HTTPC_METHOD_GET;
u32 statusCode = 0;
u32 contentSize = 0, readsize = 0, size = 0;
u8* buf, *lastbuf;
if (strcmp(method, "GET") == 0) {
D printf_top("method GET\n");
methodReal = HTTPC_METHOD_GET;
} else if (strcmp(method, "PUT") == 0) {
D printf_top("method PUT\n");
methodReal = HTTPC_METHOD_PUT;
} else if (strcmp(method, "POST") == 0) {
D printf_top("method POST\n");
methodReal = HTTPC_METHOD_POST;
} else if (strcmp(method, "DELETE") == 0) {
D printf_top("method DELETE\n");
methodReal = HTTPC_METHOD_DELETE;
}
do {
httpcOpenContext(&context, methodReal, url.c_str(), 1);
httpcSetSSLOpt(&context, SSLCOPT_DisableVerify);
httpcSetKeepAlive(&context, HTTPC_KEEPALIVE_ENABLED);
httpcAddRequestHeaderField(&context, "User-Agent", "3ds");
if (token != "") {
httpcAddRequestHeaderField(&context, "Authorization", ("Bearer " + token).c_str());
}
httpcAddRequestHeaderField(&context, "Connection", "Keep-Alive");
if (body) {
httpcAddRequestHeaderField(&context, "Content-Type", "application/json");
const char* bodyStr = json_dumps(body, JSON_ENSURE_ASCII | JSON_ESCAPE_SLASH);
httpcAddPostDataRaw(&context, (u32*)bodyStr, strlen(bodyStr));
}
ret = httpcBeginRequest(&context);
if (ret) {
D printf_top("Failed to perform request\n");
httpcCloseContext(&context);
return NULL;
}
httpcGetResponseStatusCode(&context, &statusCode);
if ((statusCode >= 301 && statusCode <= 303) || (statusCode >= 307 && statusCode <= 308)) {
char newUrl[0x100];
ret = httpcGetResponseHeader(&context, "Location", newUrl, 0x100);
url = std::string(newUrl);
}
} while ((statusCode >= 301 && statusCode <= 303) || (statusCode >= 307 && statusCode <= 308));
ret = httpcGetDownloadSizeState(&context, NULL, &contentSize);
if (ret != 0) {
httpcCloseContext(&context);
return NULL;
}
// Start with a single page buffer
buf = (u8*)malloc(0x1000);
if (!buf) {
httpcCloseContext(&context);
return NULL;
}
do {
// This download loop resizes the buffer as data is read.
ret = httpcDownloadData(&context, buf+size, 0x1000, &readsize);
size += readsize;
if (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING) {
lastbuf = buf; // Save the old pointer, in case realloc() fails.
buf = (u8*)realloc(buf, size + 0x1000);
if (!buf) {
httpcCloseContext(&context);
free(lastbuf);
return NULL;
}
}
} while (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING);
if (ret) {
httpcCloseContext(&context);
free(buf);
return NULL;
}
// Resize the buffer back down to our actual final size
lastbuf = buf;
buf = (u8*)realloc(buf, size + 1); // +1 for zero-termination
if (!buf) { // realloc() failed.
httpcCloseContext(&context);
free(lastbuf);
return NULL;
}
buf[size] = '\0'; // zero-terminate
httpcCloseContext(&context);
//D printf_top("%s\n", buf);
json_error_t error;
json_t* content = json_loads((char*)buf, 0, &error);
free(buf);
if (!content) {
D printf_top("Failed to parse json\n");
return NULL; return NULL;
} }
return content; return content;