diff --git a/xwords4/common/config.mk b/xwords4/common/config.mk index 413139618..1516adaef 100644 --- a/xwords4/common/config.mk +++ b/xwords4/common/config.mk @@ -52,6 +52,7 @@ COMMONSRC = \ $(COMMONDIR)/dutil.c \ $(COMMONDIR)/device.c \ $(COMMONDIR)/knownplyr.c \ + $(COMMONDIR)/md5.c \ # PENDING: define this in terms of above!!! @@ -93,5 +94,6 @@ COMMON5 = \ $(COMMONOBJDIR)/dutil.o \ $(COMMONOBJDIR)/device.o \ $(COMMONOBJDIR)/knownplyr.o \ + $(COMMONOBJDIR)/md5.o \ COMMONOBJ = $(COMMON1) $(COMMON2) $(COMMON3) $(COMMON4) $(COMMON5) diff --git a/xwords4/common/md5.c b/xwords4/common/md5.c index f79a427b7..cfded5b07 100644 --- a/xwords4/common/md5.c +++ b/xwords4/common/md5.c @@ -1,9 +1,14 @@ +// as copied from https://github.com/Zunawe/md5-c /* * Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm * and modified slightly to be functionally identical but condensed into control structures. */ +#ifdef NO_NATIVE_MD5SDUM #include "md5.h" +#include "comtypes.h" + +static void md5Step(uint32_t *buffer, uint32_t *input); /* * Constants defined by the MD5 algorithm @@ -62,11 +67,17 @@ uint32_t rotateLeft(uint32_t x, uint32_t n){ return (x << n) | (x >> (32 - n)); } +typedef struct { + uint64_t size; // Size of input in bytes + uint32_t buffer[4]; // Current accumulation of hash + uint8_t input[64]; // Input to be used in the next step + uint8_t digest[16]; // Result of algorithm +} MD5Context; /* * Initialize a context */ -void md5Init(MD5Context *ctx){ +static void md5Init(MD5Context *ctx){ ctx->size = (uint64_t)0; ctx->buffer[0] = (uint32_t)A; @@ -81,7 +92,7 @@ void md5Init(MD5Context *ctx){ * If the input fills out a block of 512 bits, apply the algorithm (md5Step) * and save the result in the buffer. Also updates the overall size. */ -void md5Update(MD5Context *ctx, uint8_t *input_buffer, size_t input_len){ +static void md5Update(MD5Context *ctx, uint8_t *input_buffer, size_t input_len){ uint32_t input[16]; unsigned int offset = ctx->size % 64; ctx->size += (uint64_t)input_len; @@ -114,7 +125,7 @@ void md5Update(MD5Context *ctx, uint8_t *input_buffer, size_t input_len){ * Pad the current input to get to 448 bytes, append the size in bits to the very end, * and save the result of the final iteration into digest. */ -void md5Finalize(MD5Context *ctx){ +static void md5Finalize(MD5Context *ctx){ uint32_t input[16]; unsigned int offset = ctx->size % 64; unsigned int padding_length = offset < 56 ? 56 - offset : (56 + 64) - offset; @@ -148,7 +159,8 @@ void md5Finalize(MD5Context *ctx){ /* * Step on 512 bits of input with the main MD5 algorithm. */ -void md5Step(uint32_t *buffer, uint32_t *input){ +static void +md5Step(uint32_t *buffer, uint32_t *input){ uint32_t AA = buffer[0]; uint32_t BB = buffer[1]; uint32_t CC = buffer[2]; @@ -191,33 +203,18 @@ void md5Step(uint32_t *buffer, uint32_t *input){ buffer[3] += DD; } -/* - * Functions that run the algorithm on the provided input and put the digest into result. - * result should be able to store 16 bytes. - */ -void md5String(char *input, uint8_t *result){ - MD5Context ctx; - md5Init(&ctx); - md5Update(&ctx, (uint8_t *)input, strlen(input)); - md5Finalize(&ctx); - - memcpy(result, ctx.digest, 16); -} - -void md5File(FILE *file, uint8_t *result){ - char *input_buffer = malloc(1024); - size_t input_size = 0; - - MD5Context ctx; - md5Init(&ctx); - - while((input_size = fread(input_buffer, 1, 1024, file)) > 0){ - md5Update(&ctx, (uint8_t *)input_buffer, input_size); +void +calcMD5Sum( MD5Result* out, uint8_t* data, size_t len ) +{ + MD5Context ctx = {0}; + md5Init( &ctx ); + md5Update( &ctx, data, len ); + md5Finalize( &ctx ); + char* output = out->output; + for ( unsigned int ii = 0; ii < VSIZE(ctx.digest); ++ii ) { + uint8_t byt = ctx.digest[ii]; + sprintf( output, "%02x", byt ); + output += 2; } - - md5Finalize(&ctx); - - free(input_buffer); - - memcpy(result, ctx.digest, 16); } +#endif diff --git a/xwords4/common/md5.h b/xwords4/common/md5.h index ca172f193..c11b63e1f 100644 --- a/xwords4/common/md5.h +++ b/xwords4/common/md5.h @@ -1,24 +1,18 @@ +// as copied from https://github.com/Zunawe/md5-c + #ifndef MD5_H #define MD5_H -#include +#ifdef NO_NATIVE_MD5SDUM + #include -#include #include -typedef struct{ - uint64_t size; // Size of input in bytes - uint32_t buffer[4]; // Current accumulation of hash - uint8_t input[64]; // Input to be used in the next step - uint8_t digest[16]; // Result of algorithm -}MD5Context; +typedef struct _MD5Result { + char output[33]; +} MD5Result; -void md5Init(MD5Context *ctx); -void md5Update(MD5Context *ctx, uint8_t *input, size_t input_len); -void md5Finalize(MD5Context *ctx); -void md5Step(uint32_t *buffer, uint32_t *input); - -void md5String(char *input, uint8_t *result); -void md5File(FILE *file, uint8_t *result); +void calcMD5Sum( MD5Result* out, uint8_t* data, size_t len ); +#endif #endif diff --git a/xwords4/wasm/Makefile b/xwords4/wasm/Makefile index 1984a33a6..0a27f441e 100644 --- a/xwords4/wasm/Makefile +++ b/xwords4/wasm/Makefile @@ -52,6 +52,8 @@ DEFINES += -DXWFEATURE_COMMS_INVITE DEFINES += -DMQTT_DEV_TOPICS DEFINES += -DMQTT_GAMEID_TOPICS DEFINES += -DXWFEATURE_NLI_FROM_ARGV +DEFINES += -DNO_NATIVE_MD5SDUM + DEFINES += -Wno-switch DEFINES += -DGITREV=\"$(shell git describe --tags --dirty)\" diff --git a/xwords4/wasm/main.c b/xwords4/wasm/main.c index d26ac3b9d..3252339d1 100644 --- a/xwords4/wasm/main.c +++ b/xwords4/wasm/main.c @@ -42,6 +42,7 @@ #include "movestak.h" #include "knownplyr.h" #include "dbgutil.h" +#include "md5.h" #include "main.h" #include "wasmdraw.h" @@ -307,6 +308,11 @@ EM_JS( void, js_notify, (const char* msg), { ); }); +EM_JS( void, js_ackMsg, (const char* sum, int gameID), { + const jsum = UTF8ToString(sum); + postAck(jsum, gameID); + }) + static void loadPrefs( Globals* globals ) { @@ -880,6 +886,14 @@ main_getLocalName( Globals* globals, char* playerName, size_t buflen ) return haveName; } +void +main_ackMQTTMsg( Globals* globals, const XP_U8* msg, XP_U16 len, int gameID ) +{ + MD5Result out; + calcMD5Sum( &out, (uint8_t*)msg, len ); + js_ackMsg( out.output, gameID ); +} + static void onPlayerNamed( void* closure, const char* name ) { diff --git a/xwords4/wasm/main.h b/xwords4/wasm/main.h index 8e85ea96f..8602e1ce9 100644 --- a/xwords4/wasm/main.h +++ b/xwords4/wasm/main.h @@ -121,5 +121,5 @@ void main_pickBlank( GameState* gs, int playerNum, int col, int row, void main_updateScreen( GameState* gs ); void main_needDictForGame(GameState* gs, const char* lc, const XP_UCHAR* dictName); bool main_getLocalName( Globals* globals, char* playerName, size_t buflen ); - +void main_ackMQTTMsg( Globals* globals, const XP_U8* msg, XP_U16 len, int gameID ); #endif diff --git a/xwords4/wasm/wasmdutil.c b/xwords4/wasm/wasmdutil.c index 06e295b45..9a1d94e25 100644 --- a/xwords4/wasm/wasmdutil.c +++ b/xwords4/wasm/wasmdutil.c @@ -509,9 +509,8 @@ wasm_dutil_ackMQTTMsg( XW_DUtilCtxt* duc, XWEnv xwe, XP_U32 gameID, const MQTTDevID* senderID, const XP_U8* msg, XP_U16 len ) { - /* There's no native md5 hash in js, so not using this right now. Messages - * will go unack'd. */ - XP_LOGFF("unimplemented"); + Globals* globals = (Globals*)duc->closure; + main_ackMQTTMsg( globals, msg, len, gameID ); } static void diff --git a/xwords4/wasm/xwutils.js b/xwords4/wasm/xwutils.js index d2e87c6a2..86686e22f 100644 --- a/xwords4/wasm/xwutils.js +++ b/xwords4/wasm/xwutils.js @@ -59,6 +59,24 @@ function registerOnce(devid, gitrev, now, dbg) { } } +function postAck(sum, gameID) { + fetch('/xw4/api/v1/ack', { + method: 'post', + body: JSON.stringify({ "sum": sum, "gid": gameID, }), + headers: { + 'Content-Type': 'application/json' + }, + }) + .then(handleFetchErrors) + .then(res => { + return res.json(); + }).then(data => { + console.log('data from ack: ' + JSON.stringify(data)); + }).catch(ex => { + console.error('postAck(): fetch()=>' + ex); + }); +} + function handleFetchErrors(response) { if ( response.ok ) { return response;