diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2017-09-16 16:11:15 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2017-09-16 16:11:15 -0400 |
commit | 4fe95cc1e7412e309d026e53cd44239bd3ef031d (patch) | |
tree | c1b711ed5a81976d9054da6205f5f9b2c3133248 /source/main.c | |
parent | e2a76d1f0fd978f285edf1dbc0f6e87cf89c63ce (diff) | |
download | gen3uploader-4fe95cc1e7412e309d026e53cd44239bd3ef031d.tar.gz gen3uploader-4fe95cc1e7412e309d026e53cd44239bd3ef031d.tar.bz2 gen3uploader-4fe95cc1e7412e309d026e53cd44239bd3ef031d.zip |
Wii can now send a POST request to a website
The extractor now uses libfat to read a config file off the root of the SD card, a model for which is included in the repository. The extractor is capable of negotiating an HTTPS connection, but it requires a download of the target site's root CA certificate to be on the SD card and pointed at by the config file. TLS/SSL functionality is provided by wolfSSL. I had to make a couple of minor changes to wolfSSL for it to work properly, and those changes are located in the devkitpro branch of my fork, hatkirby/wolfssl. The Wii program now arranges some of the information that the GBA sends it into a JSON object, which is then sent off (along with some authentication information from the config file) to the endpoint defined in the config file. The code used to maintain the network connection is from the WiiTweet project, which was licensed under the GPL. Some of the code used to send the HTTP request also comes from said project.
Diffstat (limited to 'source/main.c')
-rw-r--r-- | source/main.c | 244 |
1 files changed, 229 insertions, 15 deletions
diff --git a/source/main.c b/source/main.c index 3806106..eb5072e 100644 --- a/source/main.c +++ b/source/main.c | |||
@@ -11,10 +11,14 @@ | |||
11 | #include <stdlib.h> | 11 | #include <stdlib.h> |
12 | #include <unistd.h> | 12 | #include <unistd.h> |
13 | #include <string.h> | 13 | #include <string.h> |
14 | #include <fat.h> | ||
15 | #include "cJSON.h" | ||
14 | #include "link.h" | 16 | #include "link.h" |
15 | #include "encoding.h" | 17 | #include "encoding.h" |
16 | #include "multiboot.h" | 18 | #include "multiboot.h" |
17 | #include "pokemon.h" | 19 | #include "pokemon.h" |
20 | #include "http.h" | ||
21 | #include "netinf.h" | ||
18 | 22 | ||
19 | void printmain() | 23 | void printmain() |
20 | { | 24 | { |
@@ -65,8 +69,75 @@ void fatalError(char *msg) | |||
65 | exit(0); | 69 | exit(0); |
66 | } | 70 | } |
67 | 71 | ||
72 | cJSON* getConfig() | ||
73 | { | ||
74 | FILE* fp = fopen("/gen3uploader.cfg", "r"); | ||
75 | if (!fp) | ||
76 | { | ||
77 | fatalError("ERROR: Could not find config file!\n"); | ||
78 | } | ||
79 | |||
80 | fseek(fp, 0L, SEEK_END); | ||
81 | long lSize = ftell(fp); | ||
82 | rewind(fp); | ||
83 | |||
84 | char* buffer = calloc(1, lSize+1); | ||
85 | if (!buffer) | ||
86 | { | ||
87 | fclose(fp); | ||
88 | fatalError("ERROR: Could not allocate memory.\n"); | ||
89 | } | ||
90 | |||
91 | if (fread(buffer, lSize, 1, fp) != 1) | ||
92 | { | ||
93 | fclose(fp); | ||
94 | free(buffer); | ||
95 | fatalError("ERROR: Could not read config file.\n"); | ||
96 | } | ||
97 | |||
98 | cJSON* config = cJSON_Parse(buffer); | ||
99 | |||
100 | fclose(fp); | ||
101 | free(buffer); | ||
102 | |||
103 | return config; | ||
104 | } | ||
105 | |||
68 | void* extractor(void* userdata) | 106 | void* extractor(void* userdata) |
69 | { | 107 | { |
108 | cJSON* config = (cJSON*)userdata; | ||
109 | |||
110 | WOLFSSL_CTX* sslContext = 0; | ||
111 | if (cJSON_HasObjectItem(config, "certificate")) | ||
112 | { | ||
113 | wolfSSL_Init(); | ||
114 | |||
115 | sslContext = wolfSSL_CTX_new(wolfTLSv1_client_method()); | ||
116 | if (sslContext == NULL) | ||
117 | { | ||
118 | fatalError("wolfSSL_CTX_new error.\n"); | ||
119 | } | ||
120 | |||
121 | if (wolfSSL_CTX_load_verify_locations( | ||
122 | sslContext, | ||
123 | cJSON_GetObjectItem(config, "certificate")->valuestring, | ||
124 | 0) != SSL_SUCCESS) | ||
125 | { | ||
126 | fatalError("Error loading certificate file.\n"); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | while (!initializeNetwork()) | ||
131 | { | ||
132 | printf("Could not initialize network.\n"); | ||
133 | printf("Press A to try again, press B to exit.\n"); | ||
134 | |||
135 | if (waitForButtons(PAD_BUTTON_A | PAD_BUTTON_B) == PAD_BUTTON_B) | ||
136 | { | ||
137 | endproc(); | ||
138 | } | ||
139 | } | ||
140 | |||
70 | for (;;) | 141 | for (;;) |
71 | { | 142 | { |
72 | printmain(); | 143 | printmain(); |
@@ -174,6 +245,17 @@ void* extractor(void* userdata) | |||
174 | 245 | ||
175 | sendMsg(1); | 246 | sendMsg(1); |
176 | 247 | ||
248 | cJSON* root = cJSON_CreateObject(); | ||
249 | |||
250 | cJSON_AddItemToObject( | ||
251 | root, | ||
252 | "playerName", | ||
253 | cJSON_CreateString(d_trainerName)); | ||
254 | |||
255 | cJSON_AddNumberToObject(root, "playerId", trainerId); | ||
256 | cJSON_AddNumberToObject(root, "gameId", gameId); | ||
257 | cJSON_AddNumberToObject(root, "language", gameLanguage); | ||
258 | |||
177 | // Get Pokédex data | 259 | // Get Pokédex data |
178 | u32 pokedexSeen[13]; | 260 | u32 pokedexSeen[13]; |
179 | u32 pokedexCaught[13]; | 261 | u32 pokedexCaught[13]; |
@@ -208,6 +290,8 @@ void* extractor(void* userdata) | |||
208 | 290 | ||
209 | u32 partyCount = getMsg(); | 291 | u32 partyCount = getMsg(); |
210 | 292 | ||
293 | cJSON* jParty = cJSON_CreateArray(); | ||
294 | |||
211 | for (u32 i = 0; i < partyCount; i++) | 295 | for (u32 i = 0; i < partyCount; i++) |
212 | { | 296 | { |
213 | usleep(5000); | 297 | usleep(5000); |
@@ -235,22 +319,144 @@ void* extractor(void* userdata) | |||
235 | pki->key[5], | 319 | pki->key[5], |
236 | pki->key[6]); | 320 | pki->key[6]); |
237 | 321 | ||
238 | printf("Species: %d\n", __builtin_bswap16(pki->species)); | 322 | cJSON* jPoke = cJSON_CreateObject(); |
239 | printf("Nickname: %s\n", d_pokename); | 323 | |
240 | printf("OT: %s\n", d_otName); | 324 | cJSON_AddNumberToObject( |
241 | printf("Level: %d\n", pki->level); | 325 | jPoke, |
242 | printf("HP: %ld\n", __builtin_bswap32(pki->hp)); | 326 | "species", |
243 | printf("Attack: %ld\n", __builtin_bswap32(pki->attack)); | 327 | __builtin_bswap16(pki->species)); |
244 | printf("Defense: %ld\n", __builtin_bswap32(pki->defense)); | 328 | |
245 | printf("Special Attack: %ld\n", __builtin_bswap32(pki->spAttack)); | 329 | cJSON_AddItemToObject( |
246 | printf("Special Defense: %ld\n", __builtin_bswap32(pki->spDefense)); | 330 | jPoke, |
247 | printf("Speed: %ld\n", __builtin_bswap32(pki->speed)); | 331 | "nickname", |
248 | printf("Key: %s\n", d_key); | 332 | cJSON_CreateString(d_pokename)); |
249 | 333 | ||
250 | printf("\n"); | 334 | cJSON_AddItemToObject( |
335 | jPoke, | ||
336 | "otName", | ||
337 | cJSON_CreateString(d_otName)); | ||
338 | |||
339 | cJSON_AddNumberToObject( | ||
340 | jPoke, | ||
341 | "otId", | ||
342 | __builtin_bswap16(pki->otId)); | ||
343 | |||
344 | cJSON_AddNumberToObject( | ||
345 | jPoke, | ||
346 | "level", | ||
347 | pki->level); | ||
348 | |||
349 | cJSON_AddNumberToObject( | ||
350 | jPoke, | ||
351 | "hp", | ||
352 | __builtin_bswap32(pki->hp)); | ||
353 | |||
354 | cJSON_AddNumberToObject( | ||
355 | jPoke, | ||
356 | "attack", | ||
357 | __builtin_bswap32(pki->attack)); | ||
358 | |||
359 | cJSON_AddNumberToObject( | ||
360 | jPoke, | ||
361 | "defense", | ||
362 | __builtin_bswap32(pki->defense)); | ||
363 | |||
364 | cJSON_AddNumberToObject( | ||
365 | jPoke, | ||
366 | "speed", | ||
367 | __builtin_bswap32(pki->speed)); | ||
368 | |||
369 | cJSON_AddNumberToObject( | ||
370 | jPoke, | ||
371 | "spAttack", | ||
372 | __builtin_bswap32(pki->spAttack)); | ||
373 | |||
374 | cJSON_AddNumberToObject( | ||
375 | jPoke, | ||
376 | "spDefense", | ||
377 | __builtin_bswap32(pki->spDefense)); | ||
378 | |||
379 | cJSON_AddItemToObject( | ||
380 | jPoke, | ||
381 | "key", | ||
382 | cJSON_CreateString(d_key)); | ||
383 | |||
384 | cJSON_AddNumberToObject( | ||
385 | jPoke, | ||
386 | "experience", | ||
387 | __builtin_bswap32(pki->experience)); | ||
388 | |||
389 | cJSON_AddNumberToObject( | ||
390 | jPoke, | ||
391 | "heldItem", | ||
392 | __builtin_bswap16(pki->heldItem)); | ||
393 | |||
394 | cJSON* jMoves = cJSON_CreateArray(); | ||
395 | |||
396 | for (int j=0; j<4; j++) | ||
397 | { | ||
398 | if (pki->moves[j] != 0) | ||
399 | { | ||
400 | cJSON* jMove = cJSON_CreateObject(); | ||
401 | |||
402 | cJSON_AddNumberToObject( | ||
403 | jMove, | ||
404 | "id", | ||
405 | __builtin_bswap16(pki->moves[j])); | ||
406 | |||
407 | cJSON_AddNumberToObject( | ||
408 | jMove, | ||
409 | "ppBonuses", | ||
410 | (pki->ppBonuses >> (2*j)) & 3); | ||
411 | |||
412 | cJSON_AddItemToArray(jMoves, jMove); | ||
413 | } else { | ||
414 | break; | ||
415 | } | ||
416 | } | ||
417 | |||
418 | cJSON_AddItemToObject( | ||
419 | jPoke, | ||
420 | "moves", | ||
421 | jMoves); | ||
422 | |||
423 | if (pki->otGender) | ||
424 | { | ||
425 | cJSON_AddStringToObject(jPoke, "otGender", "female"); | ||
426 | } else { | ||
427 | cJSON_AddStringToObject(jPoke, "otGender", "male"); | ||
428 | } | ||
429 | |||
430 | cJSON_AddNumberToObject( | ||
431 | jPoke, | ||
432 | "metLevel", | ||
433 | pki->metLevel); | ||
434 | |||
435 | cJSON_AddNumberToObject( | ||
436 | jPoke, | ||
437 | "metLocation", | ||
438 | pki->metLocation); | ||
439 | |||
440 | cJSON_AddItemToArray(jParty, jPoke); | ||
251 | } | 441 | } |
252 | 442 | ||
253 | waitForButtons(PAD_BUTTON_START); | 443 | cJSON_AddItemToObject(root, "party", jParty); |
444 | |||
445 | char *rendered = cJSON_Print(root); | ||
446 | printf("%s\n", rendered); | ||
447 | |||
448 | waitForButtons(PAD_BUTTON_A); | ||
449 | |||
450 | int result = submitToApi( | ||
451 | cJSON_GetObjectItem(config, "url")->valuestring, | ||
452 | sslContext, | ||
453 | root, | ||
454 | cJSON_GetObjectItem(config, "username")->valuestring, | ||
455 | cJSON_GetObjectItem(config, "password")->valuestring); | ||
456 | |||
457 | printf("Result: %d\n", result); | ||
458 | |||
459 | waitForButtons(PAD_BUTTON_A); | ||
254 | } | 460 | } |
255 | 461 | ||
256 | return NULL; | 462 | return NULL; |
@@ -276,6 +482,14 @@ int main(int argc, char *argv[]) | |||
276 | VIDEO_ClearFrameBuffer(rmode, xfb, COLOR_BLACK); | 482 | VIDEO_ClearFrameBuffer(rmode, xfb, COLOR_BLACK); |
277 | PAD_Init(); | 483 | PAD_Init(); |
278 | 484 | ||
485 | if (!fatInitDefault()) | ||
486 | { | ||
487 | printmain(); | ||
488 | fatalError("ERROR: Cannot find config file!\n"); | ||
489 | } | ||
490 | |||
491 | cJSON* config = getConfig(); | ||
492 | |||
279 | initLink(); | 493 | initLink(); |
280 | 494 | ||
281 | lwp_t extractorHandle = (lwp_t)NULL; | 495 | lwp_t extractorHandle = (lwp_t)NULL; |
@@ -283,7 +497,7 @@ int main(int argc, char *argv[]) | |||
283 | LWP_CreateThread( | 497 | LWP_CreateThread( |
284 | &extractorHandle, // thread handle | 498 | &extractorHandle, // thread handle |
285 | extractor, // code | 499 | extractor, // code |
286 | NULL, // userdata | 500 | config, // userdata |
287 | NULL, // stack base | 501 | NULL, // stack base |
288 | 16*1024, // stack size | 502 | 16*1024, // stack size |
289 | LWP_PRIO_HIGHEST); // thread priority | 503 | LWP_PRIO_HIGHEST); // thread priority |