2020-01-08 10:19:01 -08:00
|
|
|
/*
|
|
|
|
* Copyright 2020 by Eric House (xwords@eehouse.org). All rights reserved.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2020-05-31 12:56:37 -07:00
|
|
|
#include <endian.h>
|
2020-11-29 11:43:19 -08:00
|
|
|
#include <inttypes.h>
|
2020-05-31 12:56:37 -07:00
|
|
|
|
2020-01-08 10:19:01 -08:00
|
|
|
#include "device.h"
|
2024-02-15 08:54:48 -08:00
|
|
|
#include "dllist.h"
|
2020-01-08 10:19:01 -08:00
|
|
|
#include "comtypes.h"
|
|
|
|
#include "memstream.h"
|
|
|
|
#include "xwstream.h"
|
2020-05-20 13:58:53 -07:00
|
|
|
#include "strutils.h"
|
|
|
|
#include "nli.h"
|
2022-12-16 13:33:36 -08:00
|
|
|
#include "dbgutil.h"
|
2024-08-12 21:04:46 -07:00
|
|
|
#include "timers.h"
|
2024-08-19 06:56:33 -07:00
|
|
|
#include "xwmutex.h"
|
2020-01-08 10:19:01 -08:00
|
|
|
|
2024-02-13 14:38:52 -08:00
|
|
|
#ifdef DEBUG
|
|
|
|
# define MAGIC_INITED 0x8283413F
|
2024-11-02 20:54:47 -07:00
|
|
|
# define ASSERT_MAGIC() { \
|
|
|
|
if ( dutil->magic != MAGIC_INITED ) { \
|
|
|
|
XP_LOGFF( "bad magic %X", dutil->magic ); \
|
|
|
|
XP_ASSERT(0); \
|
|
|
|
} \
|
|
|
|
}
|
2024-02-13 14:38:52 -08:00
|
|
|
#else
|
|
|
|
# define ASSERT_MAGIC()
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define LAST_REG_KEY FULL_KEY("device_last_reg")
|
2024-02-15 08:54:48 -08:00
|
|
|
#define KEY_GITREV FULL_KEY("device_gitrev")
|
2024-02-13 14:38:52 -08:00
|
|
|
|
2024-04-05 11:17:12 -07:00
|
|
|
#define PD_VERSION_1 2
|
|
|
|
|
2024-08-29 15:40:27 -07:00
|
|
|
#ifndef ACK_TIMER_INTERVAL_MS
|
|
|
|
# define ACK_TIMER_INTERVAL_MS 5000
|
|
|
|
#endif
|
|
|
|
|
2024-08-07 08:01:48 -07:00
|
|
|
XWStreamCtxt*
|
2020-01-08 10:19:01 -08:00
|
|
|
mkStream( XW_DUtilCtxt* dutil )
|
|
|
|
{
|
|
|
|
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(dutil->mpool)
|
|
|
|
dutil_getVTManager(dutil) );
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
2024-02-15 16:48:14 -08:00
|
|
|
typedef enum { WSR_REGISTER, } WSR;
|
|
|
|
|
|
|
|
typedef struct WSData {
|
|
|
|
DLHead links;
|
|
|
|
XP_U32 resultKey;
|
|
|
|
WSR code;
|
|
|
|
} WSData;
|
2020-05-20 13:58:53 -07:00
|
|
|
|
2024-04-05 11:17:12 -07:00
|
|
|
typedef struct _PhoniesDataStrs {
|
|
|
|
DLHead links;
|
|
|
|
XP_UCHAR* phony;
|
|
|
|
} PhoniesDataStrs;
|
|
|
|
|
|
|
|
typedef struct _PhoniesDataCodes {
|
|
|
|
DLHead links;
|
|
|
|
XP_UCHAR* isoCode;
|
|
|
|
PhoniesDataStrs* head;
|
|
|
|
} PhoniesDataCodes;
|
|
|
|
|
2020-05-20 13:58:53 -07:00
|
|
|
typedef struct _DevCtxt {
|
2024-09-01 22:03:49 -07:00
|
|
|
|
2020-05-20 13:58:53 -07:00
|
|
|
XP_U16 devCount;
|
2024-09-01 22:03:49 -07:00
|
|
|
XP_U8 mqttQOS;
|
|
|
|
XP_Bool dirty;
|
|
|
|
MutexState mutex;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
WSData* data;
|
|
|
|
XP_U32 key;
|
|
|
|
MutexState mutex;
|
|
|
|
} webSend;
|
2024-08-19 06:56:33 -07:00
|
|
|
|
|
|
|
struct {
|
|
|
|
MutexState mutex;
|
|
|
|
cJSON* msgs; /* pending acks saved here */
|
|
|
|
TimerKey key;
|
|
|
|
} ackTimer;
|
2024-04-05 11:17:12 -07:00
|
|
|
|
|
|
|
PhoniesDataCodes* pd;
|
|
|
|
|
2024-02-15 16:48:14 -08:00
|
|
|
#ifdef DEBUG
|
|
|
|
XP_U32 magic;
|
|
|
|
#endif
|
|
|
|
|
2020-05-20 13:58:53 -07:00
|
|
|
} DevCtxt;
|
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
// PENDING: Actually use a timer, or rename this function
|
|
|
|
static void setSaveDCTimer( XW_DUtilCtxt* dutil, XWEnv xwe,
|
|
|
|
DevCtxt* dc );
|
2024-02-15 16:48:14 -08:00
|
|
|
|
2020-01-08 10:19:01 -08:00
|
|
|
static DevCtxt*
|
2020-04-26 11:28:18 -07:00
|
|
|
load( XW_DUtilCtxt* dutil, XWEnv xwe )
|
2020-01-08 10:19:01 -08:00
|
|
|
{
|
|
|
|
DevCtxt* state = (DevCtxt*)dutil->devCtxt;
|
|
|
|
if ( NULL == state ) {
|
2024-02-15 16:48:14 -08:00
|
|
|
#ifdef XWFEATURE_DEVICE
|
2024-09-01 22:03:49 -07:00
|
|
|
dutil->devCtxt = state = XP_CALLOC( dutil->mpool, sizeof(*state) );
|
|
|
|
|
2020-01-08 10:19:01 -08:00
|
|
|
XWStreamCtxt* stream = mkStream( dutil );
|
2024-11-01 08:18:06 -07:00
|
|
|
dutil_loadStream( dutil, xwe, KEY_DEVSTATE, stream );
|
2020-01-08 10:19:01 -08:00
|
|
|
|
|
|
|
if ( 0 < stream_getSize( stream ) ) {
|
|
|
|
state->devCount = stream_getU16( stream );
|
|
|
|
++state->devCount; /* for testing until something's there */
|
2024-09-01 22:03:49 -07:00
|
|
|
/* XP_LOGFF( "read devCount: %d", state->devCount ); */
|
|
|
|
if ( stream_gotU8( stream, &state->mqttQOS ) ) {
|
|
|
|
XP_LOGFF( "read qos: %d", state->mqttQOS );
|
|
|
|
} else {
|
|
|
|
state->mqttQOS = 1;
|
|
|
|
setSaveDCTimer( dutil, xwe, state );
|
|
|
|
}
|
2020-01-08 10:19:01 -08:00
|
|
|
} else {
|
2024-09-01 22:03:49 -07:00
|
|
|
XP_LOGFF( "empty stream!!" );
|
2020-01-08 10:19:01 -08:00
|
|
|
}
|
2023-02-03 22:00:47 -08:00
|
|
|
stream_destroy( stream );
|
2024-02-15 16:48:14 -08:00
|
|
|
#endif
|
2020-01-08 10:19:01 -08:00
|
|
|
}
|
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
// LOG_RETURNF( "%p", state );
|
2020-01-08 10:19:01 -08:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
XP_U8
|
|
|
|
dvc_getQOS( XW_DUtilCtxt* dutil, XWEnv xwe )
|
2020-01-08 10:19:01 -08:00
|
|
|
{
|
2020-04-26 11:28:18 -07:00
|
|
|
DevCtxt* state = load( dutil, xwe );
|
2024-10-31 20:06:30 -07:00
|
|
|
// LOG_RETURNF("%d", state->mqttQOS);
|
2024-09-01 22:03:49 -07:00
|
|
|
return state->mqttQOS;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef XWFEATURE_DEVICE
|
|
|
|
static void
|
|
|
|
dvcStoreLocked( XW_DUtilCtxt* dutil, XWEnv xwe, DevCtxt* state )
|
|
|
|
{
|
2020-01-08 10:19:01 -08:00
|
|
|
XWStreamCtxt* stream = mkStream( dutil );
|
|
|
|
stream_putU16( stream, state->devCount );
|
2024-09-01 22:03:49 -07:00
|
|
|
stream_putU8( stream, state->mqttQOS );
|
2024-11-01 08:18:06 -07:00
|
|
|
dutil_storeStream( dutil, xwe, KEY_DEVSTATE, stream );
|
2023-02-03 22:00:47 -08:00
|
|
|
stream_destroy( stream );
|
2020-01-08 10:19:01 -08:00
|
|
|
}
|
2024-09-01 22:03:49 -07:00
|
|
|
|
|
|
|
void
|
|
|
|
dvc_store( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|
|
|
{
|
|
|
|
ASSERT_MAGIC();
|
|
|
|
DevCtxt* state = load( dutil, xwe );
|
|
|
|
WITH_MUTEX( &state->mutex );
|
|
|
|
dvcStoreLocked( dutil, xwe, state );
|
|
|
|
END_WITH_MUTEX();
|
|
|
|
}
|
2020-01-08 10:19:01 -08:00
|
|
|
#endif
|
2020-05-20 13:58:53 -07:00
|
|
|
|
2020-09-13 14:48:36 -07:00
|
|
|
// #define BOGUS_ALL_SAME_DEVID
|
2020-11-29 11:43:19 -08:00
|
|
|
#define NUM_RUNS 1 /* up this to see how random things look */
|
2020-09-13 14:48:36 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
getMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe, XP_Bool forceNew, MQTTDevID* devID )
|
2020-05-20 13:58:53 -07:00
|
|
|
{
|
2020-09-13 14:48:36 -07:00
|
|
|
#ifdef BOGUS_ALL_SAME_DEVID
|
|
|
|
XP_USE(forceNew);
|
|
|
|
MQTTDevID bogusID = 0;
|
|
|
|
XP_UCHAR* str = "ABCDEF0123456789";
|
|
|
|
XP_Bool ok = strToMQTTCDevID( str, &bogusID );
|
|
|
|
XP_ASSERT( ok );
|
|
|
|
|
2020-05-20 13:58:53 -07:00
|
|
|
MQTTDevID tmp = 0;
|
2021-03-05 09:03:32 -08:00
|
|
|
XP_U32 len = sizeof(tmp);
|
2024-11-01 08:18:06 -07:00
|
|
|
dutil_loadPtr( dutil, xwe, MQTT_DEVID_KEY, &tmp, &len );
|
2020-09-13 14:48:36 -07:00
|
|
|
if ( len != sizeof(tmp) || 0 != XP_MEMCMP( &bogusID, &tmp, sizeof(tmp) ) ) {
|
2024-11-01 08:18:06 -07:00
|
|
|
dutil_storePtr( dutil, xwe, MQTT_DEVID_KEY, &bogusID, sizeof(bogusID) );
|
2020-09-13 14:48:36 -07:00
|
|
|
}
|
|
|
|
*devID = bogusID;
|
|
|
|
|
|
|
|
#else
|
2024-12-03 21:07:45 -08:00
|
|
|
/* Use the cached value if present and if we're not forcing new */
|
|
|
|
if ( !dutil->devID || forceNew ) {
|
|
|
|
XP_U32 len = sizeof(dutil->devID);
|
|
|
|
if ( !forceNew ) {
|
|
|
|
dutil_loadPtr( dutil, xwe, MQTT_DEVID_KEY, &dutil->devID, &len );
|
|
|
|
}
|
2020-06-19 11:50:44 -07:00
|
|
|
|
2024-12-03 21:07:45 -08:00
|
|
|
/* XP_LOGFF( "len: %d; sizeof(tmp): %zu", len, sizeof(tmp) ); */
|
|
|
|
if ( forceNew || len != sizeof(dutil->devID) ) { /* not found, or bogus somehow */
|
|
|
|
int total = 0;
|
|
|
|
MQTTDevID tmp;
|
|
|
|
for ( int ii = 0; ii < NUM_RUNS; ++ii ) {
|
|
|
|
tmp = XP_RANDOM();
|
|
|
|
tmp <<= 27;
|
|
|
|
tmp ^= XP_RANDOM();
|
|
|
|
tmp <<= 27;
|
|
|
|
tmp ^= XP_RANDOM();
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
MQTTDevID tmp2 = tmp;
|
|
|
|
while ( 0 != tmp2 ) {
|
|
|
|
if ( 0 != (1 & tmp2) ) {
|
|
|
|
++count;
|
|
|
|
++total;
|
|
|
|
}
|
|
|
|
tmp2 >>= 1;
|
2020-11-29 11:43:19 -08:00
|
|
|
}
|
2024-12-03 21:07:45 -08:00
|
|
|
XP_LOGFF( "got: %" PRIX64 " (set: %d/%zd)", tmp, count, sizeof(tmp2)*8 );
|
2020-11-29 11:43:19 -08:00
|
|
|
}
|
2024-12-03 21:07:45 -08:00
|
|
|
XP_LOGFF( "average bits set: %d", total / NUM_RUNS );
|
2020-11-29 11:43:19 -08:00
|
|
|
|
2024-12-03 21:07:45 -08:00
|
|
|
dutil->devID = tmp;
|
|
|
|
dutil_storePtr( dutil, xwe, MQTT_DEVID_KEY, &dutil->devID, sizeof(dutil->devID) );
|
|
|
|
}
|
2020-09-13 14:48:36 -07:00
|
|
|
|
|
|
|
# ifdef DEBUG
|
2020-05-20 13:58:53 -07:00
|
|
|
XP_UCHAR buf[32];
|
2024-12-03 21:07:45 -08:00
|
|
|
formatMQTTDevID( &dutil->devID, buf, VSIZE(buf) );
|
2020-05-20 13:58:53 -07:00
|
|
|
/* This log statement is required by discon_ok2.py!!! (keep in sync) */
|
2020-09-05 14:56:03 -07:00
|
|
|
XP_LOGFF( "generated id: %s; key: %s", buf, MQTT_DEVID_KEY );
|
2020-09-13 14:48:36 -07:00
|
|
|
# endif
|
2020-05-20 13:58:53 -07:00
|
|
|
}
|
2024-12-03 21:07:45 -08:00
|
|
|
XP_ASSERT( dutil->devID );
|
|
|
|
*devID = dutil->devID;
|
2020-09-13 14:48:36 -07:00
|
|
|
#endif
|
2021-03-15 07:52:54 -07:00
|
|
|
// LOG_RETURNF( MQTTDevID_FMT " key: %s", *devID, MQTT_DEVID_KEY );
|
2020-09-13 14:48:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dvc_getMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe, MQTTDevID* devID )
|
|
|
|
{
|
2024-02-14 10:43:51 -08:00
|
|
|
ASSERT_MAGIC();
|
2020-09-13 14:48:36 -07:00
|
|
|
getMQTTDevID( dutil, xwe, XP_FALSE, devID );
|
|
|
|
}
|
|
|
|
|
2023-04-26 13:57:21 -07:00
|
|
|
void
|
|
|
|
dvc_setMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe, const MQTTDevID* devID )
|
|
|
|
{
|
2024-12-03 21:07:45 -08:00
|
|
|
dutil->devID = *devID;
|
2024-11-01 08:18:06 -07:00
|
|
|
dutil_storePtr( dutil, xwe, MQTT_DEVID_KEY, devID, sizeof(*devID) );
|
2023-04-26 13:57:21 -07:00
|
|
|
}
|
|
|
|
|
2020-09-13 14:48:36 -07:00
|
|
|
void
|
|
|
|
dvc_resetMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|
|
|
{
|
|
|
|
#ifdef BOGUS_ALL_SAME_DEVID
|
|
|
|
XP_LOGFF( "doing nothing" );
|
|
|
|
XP_USE( dutil );
|
|
|
|
XP_USE( xwe );
|
|
|
|
#else
|
|
|
|
MQTTDevID ignored;
|
|
|
|
getMQTTDevID( dutil, xwe, XP_TRUE, &ignored );
|
|
|
|
#endif
|
2020-05-20 13:58:53 -07:00
|
|
|
}
|
|
|
|
|
2022-12-16 13:33:36 -08:00
|
|
|
static XP_UCHAR*
|
|
|
|
appendToStorage( XP_UCHAR* storage, int* offset,
|
|
|
|
const XP_UCHAR* str )
|
|
|
|
{
|
|
|
|
XP_UCHAR* start = &storage[*offset];
|
|
|
|
start[0] = '\0';
|
|
|
|
XP_STRCAT( start, str );
|
|
|
|
*offset += 1 + XP_STRLEN(str);
|
|
|
|
return start;
|
|
|
|
}
|
|
|
|
|
2024-11-11 06:41:55 -08:00
|
|
|
/* #ifdef DEBUG */
|
|
|
|
/* static void */
|
|
|
|
/* logPtrs( const char* func, int nTopics, char* topics[] ) */
|
|
|
|
/* { */
|
|
|
|
/* for ( int ii = 0; ii < nTopics; ++ii ) { */
|
|
|
|
/* XP_LOGFF( "from %s; topics[%d] = %s", func, ii, topics[ii] ); */
|
|
|
|
/* } */
|
|
|
|
/* } */
|
|
|
|
/* #else */
|
|
|
|
/* # define logPtrs(func, nTopics, topics) */
|
|
|
|
/* #endif */
|
2022-12-16 13:33:36 -08:00
|
|
|
|
|
|
|
void
|
|
|
|
dvc_getMQTTSubTopics( XW_DUtilCtxt* dutil, XWEnv xwe,
|
2022-12-21 10:27:12 -08:00
|
|
|
XP_UCHAR* storage, XP_U16 XP_UNUSED_DBG(storageLen),
|
2024-09-01 22:03:49 -07:00
|
|
|
XP_U16* nTopics, XP_UCHAR* topics[], XP_U8* qos )
|
2022-12-16 13:33:36 -08:00
|
|
|
{
|
2024-02-14 10:43:51 -08:00
|
|
|
ASSERT_MAGIC();
|
2022-12-16 13:33:36 -08:00
|
|
|
int offset = 0;
|
|
|
|
XP_U16 count = 0;
|
|
|
|
storage[0] = '\0';
|
|
|
|
|
|
|
|
MQTTDevID devid;
|
|
|
|
getMQTTDevID( dutil, xwe, XP_FALSE, &devid );
|
|
|
|
XP_UCHAR buf[64];
|
2022-12-19 19:53:57 -08:00
|
|
|
formatMQTTDevTopic( &devid, buf, VSIZE(buf) );
|
2022-12-16 13:33:36 -08:00
|
|
|
|
2022-12-19 19:53:57 -08:00
|
|
|
#ifdef MQTT_DEV_TOPICS
|
2022-12-16 13:33:36 -08:00
|
|
|
/* First, the main device topic */
|
|
|
|
topics[count++] = appendToStorage( storage, &offset, buf );
|
2022-12-19 19:53:57 -08:00
|
|
|
#endif
|
2022-12-16 13:33:36 -08:00
|
|
|
|
2022-12-18 16:17:05 -08:00
|
|
|
#ifdef MQTT_GAMEID_TOPICS
|
2022-12-16 13:33:36 -08:00
|
|
|
/* Then the pattern that includes gameIDs */
|
2022-12-19 19:53:57 -08:00
|
|
|
XP_UCHAR buf2[64];
|
|
|
|
size_t siz = XP_SNPRINTF( buf2, VSIZE(buf2), "%s/+", buf );
|
|
|
|
XP_ASSERT( siz < VSIZE(buf) );
|
2022-12-21 10:27:12 -08:00
|
|
|
XP_USE(siz);
|
2022-12-19 19:53:57 -08:00
|
|
|
topics[count++] = appendToStorage( storage, &offset, buf2 );
|
2022-12-18 16:17:05 -08:00
|
|
|
#endif
|
2022-12-16 13:33:36 -08:00
|
|
|
|
|
|
|
/* Finally, the control pattern */
|
|
|
|
formatMQTTCtrlTopic( &devid, buf, VSIZE(buf) );
|
|
|
|
topics[count++] = appendToStorage( storage, &offset, buf );
|
|
|
|
|
|
|
|
for ( int ii = 0; ii < count; ++ii ) {
|
2024-02-15 08:54:48 -08:00
|
|
|
XP_LOGFFV( "AFTER: got %d: %s", ii, topics[ii] );
|
2022-12-16 13:33:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
XP_ASSERT( count <= *nTopics );
|
|
|
|
*nTopics = count;
|
|
|
|
XP_ASSERT( offset < storageLen );
|
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
*qos = dvc_getQOS( dutil, xwe );
|
|
|
|
|
2024-11-02 20:54:47 -07:00
|
|
|
// logPtrs( __func__, *nTopics, topics );
|
2022-12-16 13:33:36 -08:00
|
|
|
}
|
|
|
|
|
2020-05-20 13:58:53 -07:00
|
|
|
typedef enum { CMD_INVITE, CMD_MSG, CMD_DEVGONE, } MQTTCmd;
|
|
|
|
|
2020-09-07 17:59:53 -07:00
|
|
|
// #define PROTO_0 0
|
2020-06-03 09:21:12 -07:00
|
|
|
#define PROTO_1 1 /* moves gameID into "header" relay2 knows about */
|
2022-12-30 15:33:51 -08:00
|
|
|
#define _PROTO_2 2 /* never used, and now deprecated (value 2 is) */
|
|
|
|
#define PROTO_3 3 /* adds multi-message, removes gameID and timestamp */
|
2022-06-29 12:29:32 -07:00
|
|
|
#ifndef MQTT_USE_PROTO
|
|
|
|
# define MQTT_USE_PROTO PROTO_1
|
|
|
|
#endif
|
2020-05-20 13:58:53 -07:00
|
|
|
|
|
|
|
static void
|
2020-06-03 09:21:12 -07:00
|
|
|
addHeaderGameIDAndCmd( XW_DUtilCtxt* dutil, XWEnv xwe, MQTTCmd cmd,
|
2022-12-30 15:33:51 -08:00
|
|
|
XP_U32 gameID, XWStreamCtxt* stream )
|
2020-05-20 13:58:53 -07:00
|
|
|
{
|
2022-06-29 12:29:32 -07:00
|
|
|
stream_putU8( stream, MQTT_USE_PROTO );
|
2020-05-20 13:58:53 -07:00
|
|
|
|
|
|
|
MQTTDevID myID;
|
|
|
|
dvc_getMQTTDevID( dutil, xwe, &myID );
|
2020-05-31 12:56:37 -07:00
|
|
|
myID = htobe64( myID );
|
2020-05-20 13:58:53 -07:00
|
|
|
stream_putBytes( stream, &myID, sizeof(myID) );
|
|
|
|
|
2020-06-03 09:21:12 -07:00
|
|
|
stream_putU32( stream, gameID );
|
2020-05-31 12:56:37 -07:00
|
|
|
|
2020-06-03 09:21:12 -07:00
|
|
|
stream_putU8( stream, cmd );
|
2020-05-31 12:56:37 -07:00
|
|
|
}
|
|
|
|
|
2022-12-19 19:53:57 -08:00
|
|
|
#ifdef MQTT_GAMEID_TOPICS
|
|
|
|
static void
|
|
|
|
addProto3HeaderCmd( XW_DUtilCtxt* dutil, XWEnv xwe, MQTTCmd cmd,
|
2022-12-30 15:33:51 -08:00
|
|
|
XWStreamCtxt* stream )
|
2022-12-19 19:53:57 -08:00
|
|
|
{
|
|
|
|
stream_putU8( stream, PROTO_3 );
|
|
|
|
|
|
|
|
MQTTDevID myID;
|
|
|
|
dvc_getMQTTDevID( dutil, xwe, &myID );
|
|
|
|
myID = htobe64( myID );
|
|
|
|
stream_putBytes( stream, &myID, sizeof(myID) );
|
|
|
|
|
|
|
|
stream_putU8( stream, cmd );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-12-20 11:55:30 -08:00
|
|
|
static void
|
2023-03-13 12:25:08 -07:00
|
|
|
callProc( MsgAndTopicProc proc, void* closure, const XP_UCHAR* topic,
|
2024-09-01 22:03:49 -07:00
|
|
|
XWStreamCtxt* stream, XP_U8 qos )
|
2022-12-20 11:55:30 -08:00
|
|
|
{
|
2023-01-24 17:23:30 -08:00
|
|
|
const XP_U8* msgBuf = !!stream ? stream_getPtr(stream) : NULL;
|
|
|
|
XP_U16 msgLen = !!stream ? stream_getSize(stream) : 0;
|
2024-09-01 22:03:49 -07:00
|
|
|
(*proc)( closure, topic, msgBuf, msgLen, qos );
|
2022-12-20 11:55:30 -08:00
|
|
|
}
|
|
|
|
|
2020-05-31 12:56:37 -07:00
|
|
|
void
|
2022-12-20 09:20:02 -08:00
|
|
|
dvc_makeMQTTInvites( XW_DUtilCtxt* dutil, XWEnv xwe,
|
|
|
|
MsgAndTopicProc proc, void* closure,
|
|
|
|
const MQTTDevID* addressee,
|
2022-12-30 15:33:51 -08:00
|
|
|
const NetLaunchInfo* nli )
|
2020-05-31 12:56:37 -07:00
|
|
|
{
|
2024-02-14 10:43:51 -08:00
|
|
|
ASSERT_MAGIC();
|
2022-12-20 09:20:02 -08:00
|
|
|
XP_UCHAR devTopic[64]; /* used by two below */
|
|
|
|
formatMQTTDevTopic( addressee, devTopic, VSIZE(devTopic) );
|
|
|
|
/* Stream format is identical for both topics */
|
|
|
|
XWStreamCtxt* stream = mkStream( dutil );
|
2022-12-30 15:33:51 -08:00
|
|
|
addHeaderGameIDAndCmd( dutil, xwe, CMD_INVITE, nli->gameID, stream );
|
2020-05-31 12:56:37 -07:00
|
|
|
nli_saveToStream( nli, stream );
|
2022-12-20 09:20:02 -08:00
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
XP_U8 qos = dvc_getQOS( dutil, xwe );
|
2022-12-20 09:20:02 -08:00
|
|
|
#ifdef MQTT_DEV_TOPICS
|
2024-09-01 22:03:49 -07:00
|
|
|
callProc( proc, closure, devTopic, stream, qos );
|
2022-12-20 09:20:02 -08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MQTT_GAMEID_TOPICS
|
|
|
|
XP_UCHAR gameTopic[64];
|
|
|
|
size_t siz = XP_SNPRINTF( gameTopic, VSIZE(gameTopic),
|
|
|
|
"%s/%X", devTopic, nli->gameID );
|
|
|
|
XP_ASSERT( siz < VSIZE(gameTopic) );
|
2022-12-21 10:27:12 -08:00
|
|
|
XP_USE(siz);
|
2024-09-01 22:03:49 -07:00
|
|
|
callProc( proc, closure, gameTopic, stream, qos );
|
2022-12-20 09:20:02 -08:00
|
|
|
#endif
|
|
|
|
|
2023-02-03 22:00:47 -08:00
|
|
|
stream_destroy( stream );
|
2020-05-20 13:58:53 -07:00
|
|
|
}
|
|
|
|
|
2023-01-24 17:23:30 -08:00
|
|
|
void
|
|
|
|
dvc_makeMQTTNukeInvite( XW_DUtilCtxt* dutil, XWEnv xwe,
|
|
|
|
MsgAndTopicProc proc, void* closure,
|
|
|
|
const NetLaunchInfo* nli )
|
|
|
|
{
|
2024-02-14 10:43:51 -08:00
|
|
|
ASSERT_MAGIC();
|
2023-01-24 17:23:30 -08:00
|
|
|
#ifdef MQTT_GAMEID_TOPICS
|
|
|
|
MQTTDevID myID;
|
|
|
|
dvc_getMQTTDevID( dutil, xwe, &myID );
|
|
|
|
XP_UCHAR devTopic[32];
|
|
|
|
formatMQTTDevTopic( &myID, devTopic, VSIZE(devTopic) );
|
|
|
|
XP_UCHAR gameTopic[64];
|
|
|
|
size_t siz = XP_SNPRINTF( gameTopic, VSIZE(gameTopic),
|
|
|
|
"%s/%X", devTopic, nli->gameID );
|
|
|
|
XP_ASSERT( siz < VSIZE(gameTopic) );
|
|
|
|
XP_USE(siz);
|
2024-09-01 22:03:49 -07:00
|
|
|
callProc( proc, closure, gameTopic, NULL, dvc_getQOS(dutil, xwe) );
|
2023-01-24 17:23:30 -08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2023-03-17 19:21:57 -07:00
|
|
|
XP_S16
|
2022-12-19 19:53:57 -08:00
|
|
|
dvc_makeMQTTMessages( XW_DUtilCtxt* dutil, XWEnv xwe,
|
|
|
|
MsgAndTopicProc proc, void* closure,
|
2023-03-18 15:31:20 -07:00
|
|
|
const SendMsgsPacket* const msgs,
|
2022-12-19 19:53:57 -08:00
|
|
|
const MQTTDevID* addressee,
|
2023-03-17 19:21:57 -07:00
|
|
|
XP_U32 gameID, XP_U16 streamVersion )
|
2020-05-20 13:58:53 -07:00
|
|
|
{
|
2024-02-14 10:43:51 -08:00
|
|
|
ASSERT_MAGIC();
|
2023-03-17 19:21:57 -07:00
|
|
|
XP_S16 nSent0 = 0;
|
|
|
|
XP_S16 nSent1 = 0;
|
2023-03-24 20:28:45 -07:00
|
|
|
XP_U8 nBufs = 0;
|
2024-07-19 22:48:34 -07:00
|
|
|
// XP_LOGFF( "(streamVersion: %X)", streamVersion );
|
2022-12-19 19:53:57 -08:00
|
|
|
XP_UCHAR devTopic[64]; /* used by two below */
|
|
|
|
formatMQTTDevTopic( addressee, devTopic, VSIZE(devTopic) );
|
|
|
|
|
2023-02-05 08:59:37 -08:00
|
|
|
/* If streamVersion is >= STREAM_VERS_NORELAY then we know that the remote
|
|
|
|
supports PROTO_3. If it's 0, it *might*, and as people upgrade it'll be
|
|
|
|
more likely we just aren't in that point in the game, but send both. If
|
|
|
|
it's > 0 but < STREAM_VERS_NORELAY, no point sending PROTO_3 */
|
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
XP_U8 qos = dvc_getQOS( dutil, xwe );
|
2023-03-24 20:28:45 -07:00
|
|
|
for ( SendMsgsPacket* packet = (SendMsgsPacket*)msgs;
|
|
|
|
!!packet; packet = (SendMsgsPacket* const)packet->next ) {
|
|
|
|
++nBufs;
|
|
|
|
if ( 0 == streamVersion || STREAM_VERS_NORELAY > streamVersion ) {
|
2023-03-17 19:21:57 -07:00
|
|
|
XWStreamCtxt* stream = mkStream( dutil );
|
|
|
|
addHeaderGameIDAndCmd( dutil, xwe, CMD_MSG, gameID, stream );
|
2023-03-18 15:31:20 -07:00
|
|
|
stream_putBytes( stream, packet->buf, packet->len );
|
2024-09-01 22:03:49 -07:00
|
|
|
callProc( proc, closure, devTopic, stream, qos );
|
2023-03-17 19:21:57 -07:00
|
|
|
stream_destroy( stream );
|
2023-03-18 15:31:20 -07:00
|
|
|
nSent0 += packet->len;
|
2023-03-17 19:21:57 -07:00
|
|
|
}
|
2022-12-19 19:53:57 -08:00
|
|
|
}
|
|
|
|
|
2023-02-05 08:59:37 -08:00
|
|
|
if ( 0 == streamVersion || STREAM_VERS_NORELAY <= streamVersion ) {
|
2022-12-19 19:53:57 -08:00
|
|
|
XWStreamCtxt* stream = mkStream( dutil );
|
2022-12-30 15:33:51 -08:00
|
|
|
addProto3HeaderCmd( dutil, xwe, CMD_MSG, stream );
|
2022-12-19 19:53:57 -08:00
|
|
|
|
|
|
|
/* For now, we ship one message per packet. But the receiving code
|
|
|
|
should be ready */
|
2023-03-17 19:21:57 -07:00
|
|
|
stream_putU8( stream, nBufs );
|
2023-03-24 20:28:45 -07:00
|
|
|
if ( 1 < nBufs ) {
|
|
|
|
XP_LOGFF( "nBufs > 1: %d", nBufs );
|
|
|
|
}
|
2023-03-18 15:31:20 -07:00
|
|
|
for ( SendMsgsPacket* packet = (SendMsgsPacket*)msgs;
|
|
|
|
!!packet; packet = (SendMsgsPacket* const)packet->next ) {
|
|
|
|
XP_U32 len = packet->len;
|
2023-04-20 14:24:10 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
if ( 0 == len ) {
|
|
|
|
XP_LOGFF( "ERROR: msg len 0" );
|
|
|
|
}
|
|
|
|
#endif
|
2022-12-19 19:53:57 -08:00
|
|
|
stream_putU32VL( stream, len );
|
2023-03-18 15:31:20 -07:00
|
|
|
stream_putBytes( stream, packet->buf, len );
|
2023-03-17 19:21:57 -07:00
|
|
|
nSent1 += len;
|
2022-12-19 19:53:57 -08:00
|
|
|
}
|
|
|
|
|
2023-03-17 19:21:57 -07:00
|
|
|
XP_ASSERT( nSent0 == nSent1 || nSent0 == 0 || nSent1 == 0 );
|
|
|
|
|
2022-12-19 19:53:57 -08:00
|
|
|
XP_UCHAR gameTopic[64];
|
|
|
|
size_t siz = XP_SNPRINTF( gameTopic, VSIZE(gameTopic),
|
|
|
|
"%s/%X", devTopic, gameID );
|
|
|
|
XP_ASSERT( siz < VSIZE(gameTopic) );
|
2022-12-21 10:27:12 -08:00
|
|
|
XP_USE(siz);
|
2022-12-19 19:53:57 -08:00
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
callProc( proc, closure, gameTopic, stream, qos );
|
2023-02-03 22:00:47 -08:00
|
|
|
stream_destroy( stream );
|
2022-06-29 12:29:32 -07:00
|
|
|
}
|
2023-03-17 19:21:57 -07:00
|
|
|
return XP_MAX( nSent0, nSent1 );
|
2020-05-20 13:58:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-12-20 11:55:30 -08:00
|
|
|
dvc_makeMQTTNoSuchGames( XW_DUtilCtxt* dutil, XWEnv xwe,
|
|
|
|
MsgAndTopicProc proc, void* closure,
|
|
|
|
const MQTTDevID* addressee,
|
2022-12-30 15:33:51 -08:00
|
|
|
XP_U32 gameID )
|
2020-05-20 13:58:53 -07:00
|
|
|
{
|
2024-02-14 10:43:51 -08:00
|
|
|
ASSERT_MAGIC();
|
2023-04-04 19:54:41 -07:00
|
|
|
XP_LOGFF( "(gameID: %X)", gameID );
|
2022-12-20 11:55:30 -08:00
|
|
|
XP_UCHAR devTopic[64]; /* used by two below */
|
|
|
|
formatMQTTDevTopic( addressee, devTopic, VSIZE(devTopic) );
|
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
XP_U8 qos = dvc_getQOS( dutil, xwe );
|
2022-12-20 11:55:30 -08:00
|
|
|
XWStreamCtxt* stream = mkStream( dutil );
|
2022-12-30 15:33:51 -08:00
|
|
|
addHeaderGameIDAndCmd( dutil, xwe, CMD_DEVGONE, gameID, stream );
|
2022-12-20 11:55:30 -08:00
|
|
|
#ifdef MQTT_DEV_TOPICS
|
2024-09-01 22:03:49 -07:00
|
|
|
callProc( proc, closure, devTopic, stream, qos );
|
2022-12-20 11:55:30 -08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MQTT_GAMEID_TOPICS
|
|
|
|
XP_UCHAR gameTopic[64];
|
|
|
|
size_t siz = XP_SNPRINTF( gameTopic, VSIZE(gameTopic),
|
|
|
|
"%s/%X", devTopic, gameID );
|
|
|
|
XP_ASSERT( siz < VSIZE(gameTopic) );
|
2022-12-21 10:27:12 -08:00
|
|
|
XP_USE(siz);
|
2024-09-01 22:03:49 -07:00
|
|
|
callProc( proc, closure, gameTopic, stream, qos );
|
2022-12-20 11:55:30 -08:00
|
|
|
#endif
|
|
|
|
|
2023-02-03 22:00:47 -08:00
|
|
|
stream_destroy( stream );
|
2020-05-20 13:58:53 -07:00
|
|
|
}
|
|
|
|
|
2022-12-16 13:33:36 -08:00
|
|
|
static XP_Bool
|
2024-12-03 21:06:36 -08:00
|
|
|
isDevMsg( const MQTTDevID* myID, const XP_UCHAR* topic, XP_U32* gameIDP )
|
2022-12-16 13:33:36 -08:00
|
|
|
{
|
|
|
|
XP_UCHAR buf[64];
|
|
|
|
formatMQTTDevTopic( myID, buf, VSIZE(buf) );
|
2022-12-19 19:53:57 -08:00
|
|
|
size_t topicLen = XP_STRLEN(buf);
|
2024-12-03 21:06:36 -08:00
|
|
|
XP_ASSERT( topicLen < VSIZE(buf)-1 );
|
|
|
|
/* Does topic match xw4/device/<devid> at least */
|
2022-12-19 19:53:57 -08:00
|
|
|
XP_Bool success = 0 == strncmp( buf, topic, topicLen );
|
|
|
|
if ( success ) {
|
2024-12-03 21:06:36 -08:00
|
|
|
/* Now get the gameID if it's there */
|
2022-12-19 19:53:57 -08:00
|
|
|
const XP_UCHAR* gameIDPart = topic + topicLen;
|
2024-12-26 11:12:10 -08:00
|
|
|
#ifdef DEBUG
|
2024-12-03 21:06:36 -08:00
|
|
|
int count =
|
2024-12-26 11:12:10 -08:00
|
|
|
#endif
|
2024-12-03 21:06:36 -08:00
|
|
|
sscanf( gameIDPart, "/%X", gameIDP );
|
|
|
|
XP_ASSERT( 1 == count || 0 == *gameIDP ); /* firing */
|
2022-12-19 19:53:57 -08:00
|
|
|
}
|
2024-12-03 21:06:36 -08:00
|
|
|
XP_LOGFF( "(%s) => %s (gameID=%X)", topic, boolToStr(success), *gameIDP );
|
2022-12-16 13:33:36 -08:00
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static XP_Bool
|
|
|
|
isCtrlMsg( const MQTTDevID* myID, const XP_UCHAR* topic )
|
|
|
|
{
|
|
|
|
XP_UCHAR buf[64];
|
|
|
|
formatMQTTCtrlTopic( myID, buf, VSIZE(buf) );
|
|
|
|
XP_Bool success = 0 == strncmp( buf, topic, XP_STRLEN(buf) );
|
|
|
|
XP_LOGFF( "(%s) => %s", topic, boolToStr(success) );
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2022-12-19 19:53:57 -08:00
|
|
|
static void
|
|
|
|
dispatchMsgs( XW_DUtilCtxt* dutil, XWEnv xwe, XP_U8 proto, XWStreamCtxt* stream,
|
|
|
|
XP_U32 gameID, const CommsAddrRec* from )
|
|
|
|
{
|
|
|
|
int msgCount = proto >= PROTO_3 ? stream_getU8( stream ) : 1;
|
2023-03-24 20:28:45 -07:00
|
|
|
if ( 1 < msgCount ) {
|
|
|
|
XP_LOGFF( "nBufs > 1: %d", msgCount );
|
|
|
|
}
|
2022-12-19 19:53:57 -08:00
|
|
|
for ( int ii = 0; ii < msgCount; ++ii ) {
|
|
|
|
XP_U32 msgLen;
|
|
|
|
if ( PROTO_1 == proto ) {
|
|
|
|
msgLen = stream_getSize( stream );
|
|
|
|
} else {
|
|
|
|
msgLen = stream_getU32VL( stream );
|
|
|
|
}
|
|
|
|
if ( msgLen > stream_getSize( stream ) ) {
|
|
|
|
XP_LOGFF( "msglen %d too large", msgLen );
|
|
|
|
msgLen = 0;
|
|
|
|
XP_ASSERT(0);
|
|
|
|
}
|
|
|
|
if ( 0 < msgLen ) {
|
|
|
|
XP_U8 msgBuf[msgLen];
|
|
|
|
stream_getBytes( stream, msgBuf, msgLen );
|
|
|
|
dutil_onMessageReceived( dutil, xwe, gameID,
|
|
|
|
from, msgBuf, msgLen );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-12 14:49:15 -08:00
|
|
|
static void
|
2024-08-19 06:56:33 -07:00
|
|
|
onAckSendTimer( void* closure, XWEnv xwe, XP_Bool fired )
|
2024-02-12 14:49:15 -08:00
|
|
|
{
|
2024-08-19 06:56:33 -07:00
|
|
|
XP_LOGFF( "(fired: %s)", boolToStr(fired) );
|
|
|
|
XW_DUtilCtxt* dutil = (XW_DUtilCtxt*)closure;
|
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
|
|
|
cJSON* ackMsgs;
|
|
|
|
WITH_MUTEX( &dc->ackTimer.mutex );
|
|
|
|
ackMsgs = dc->ackTimer.msgs;
|
|
|
|
dc->ackTimer.msgs = NULL;
|
|
|
|
dc->ackTimer.key = 0;
|
|
|
|
END_WITH_MUTEX();
|
|
|
|
|
|
|
|
XP_ASSERT( 0 < cJSON_GetArraySize( ackMsgs ) );
|
|
|
|
|
|
|
|
if ( fired ) {
|
|
|
|
cJSON* params = cJSON_CreateObject();
|
|
|
|
cJSON_AddItemToObject( params, "msgs", ackMsgs );
|
|
|
|
dutil_sendViaWeb( dutil, xwe, 0, "ack2", params );
|
|
|
|
cJSON_Delete( params );
|
|
|
|
} else {
|
|
|
|
XP_LOGFF( "Dropping ack messages -- but should store them!" );
|
|
|
|
cJSON_Delete( ackMsgs );
|
|
|
|
}
|
|
|
|
}
|
2024-07-28 15:34:37 -07:00
|
|
|
|
2024-08-19 06:56:33 -07:00
|
|
|
static void
|
|
|
|
setAckSendTimerLocked( XW_DUtilCtxt* dutil, XWEnv xwe, DevCtxt* dc )
|
|
|
|
{
|
|
|
|
if ( 0 == dc->ackTimer.key ) {
|
2024-08-29 15:40:27 -07:00
|
|
|
dc->ackTimer.key = tmr_set( dutil, xwe,
|
|
|
|
ACK_TIMER_INTERVAL_MS,
|
|
|
|
onAckSendTimer, dutil );
|
2024-08-19 06:56:33 -07:00
|
|
|
XP_ASSERT( 0 != dc->ackTimer.key );
|
2024-07-28 15:34:37 -07:00
|
|
|
}
|
2024-08-19 06:56:33 -07:00
|
|
|
}
|
2024-07-28 15:34:37 -07:00
|
|
|
|
2024-08-19 06:56:33 -07:00
|
|
|
static void
|
|
|
|
ackMQTTMsg( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* topic,
|
|
|
|
XP_U32 gameID, const XP_U8* buf, XP_U16 len )
|
|
|
|
{
|
|
|
|
cJSON* msg = cJSON_CreateObject();
|
|
|
|
cJSON_AddStringToObject( msg, "topic", topic );
|
2024-02-12 14:49:15 -08:00
|
|
|
|
|
|
|
Md5SumBuf sb;
|
|
|
|
dutil_md5sum( dutil, xwe, buf, len, &sb );
|
2024-08-19 06:56:33 -07:00
|
|
|
cJSON_AddStringToObject( msg, "sum", sb.buf );
|
2024-02-12 14:49:15 -08:00
|
|
|
|
2024-08-19 06:56:33 -07:00
|
|
|
cJSON_AddNumberToObject( msg, "gid", gameID );
|
2024-02-12 14:49:15 -08:00
|
|
|
|
2024-08-19 06:56:33 -07:00
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
|
|
|
WITH_MUTEX( &dc->ackTimer.mutex );
|
|
|
|
if ( !dc->ackTimer.msgs ) {
|
|
|
|
dc->ackTimer.msgs = cJSON_CreateArray();
|
|
|
|
}
|
|
|
|
cJSON_AddItemToArray( dc->ackTimer.msgs, msg );
|
|
|
|
setAckSendTimerLocked( dutil, xwe, dc );
|
|
|
|
END_WITH_MUTEX();
|
2024-02-12 14:49:15 -08:00
|
|
|
}
|
|
|
|
|
2020-05-20 13:58:53 -07:00
|
|
|
void
|
2022-12-16 13:33:36 -08:00
|
|
|
dvc_parseMQTTPacket( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* topic,
|
2022-06-29 12:29:32 -07:00
|
|
|
const XP_U8* buf, XP_U16 len )
|
2020-05-20 13:58:53 -07:00
|
|
|
{
|
2024-10-31 20:06:30 -07:00
|
|
|
XP_LOGFF( "(topic=%s, len=%d)", topic, len );
|
2024-02-14 10:43:51 -08:00
|
|
|
ASSERT_MAGIC();
|
2022-12-16 13:33:36 -08:00
|
|
|
|
|
|
|
MQTTDevID myID;
|
|
|
|
dvc_getMQTTDevID( dutil, xwe, &myID );
|
|
|
|
|
2024-12-03 21:06:36 -08:00
|
|
|
// XP_LOGFF( "got myID" ); /* gets here */
|
2024-11-02 20:54:47 -07:00
|
|
|
|
2022-12-19 19:53:57 -08:00
|
|
|
XP_U32 gameID = 0;
|
|
|
|
if ( isDevMsg( &myID, topic, &gameID ) ) {
|
2022-12-16 13:33:36 -08:00
|
|
|
XWStreamCtxt* stream = mkStream( dutil );
|
|
|
|
stream_putBytes( stream, buf, len );
|
2020-05-20 13:58:53 -07:00
|
|
|
|
2022-12-28 23:19:52 -08:00
|
|
|
XP_U8 proto = 0;
|
2023-11-17 19:39:45 -08:00
|
|
|
if ( !stream_gotU8( stream, &proto ) ) {
|
|
|
|
XP_LOGFF( "bad message: too short" );
|
|
|
|
} else if ( proto == PROTO_1 || proto == PROTO_3 ) {
|
2022-12-16 13:33:36 -08:00
|
|
|
MQTTDevID senderID;
|
2024-03-04 10:21:08 -08:00
|
|
|
if ( stream_gotBytes( stream, &senderID, sizeof(senderID) ) ) {
|
|
|
|
senderID = be64toh( senderID );
|
2021-04-19 07:04:58 -07:00
|
|
|
#ifdef DEBUG
|
2024-03-04 10:21:08 -08:00
|
|
|
XP_UCHAR tmp[32];
|
|
|
|
formatMQTTDevID( &senderID, tmp, VSIZE(tmp) );
|
|
|
|
XP_LOGFF( "senderID: %s", tmp );
|
2021-04-19 07:04:58 -07:00
|
|
|
#endif
|
2024-03-04 10:21:08 -08:00
|
|
|
if ( proto < PROTO_3 ) {
|
|
|
|
gameID = stream_getU32( stream );
|
|
|
|
} else {
|
|
|
|
XP_ASSERT( 0 != gameID );
|
|
|
|
}
|
2020-06-03 09:21:12 -07:00
|
|
|
|
2024-03-04 10:21:08 -08:00
|
|
|
MQTTCmd cmd = stream_getU8( stream );
|
2020-06-03 09:21:12 -07:00
|
|
|
|
2024-03-04 10:21:08 -08:00
|
|
|
/* Need to ack even if discarded/malformed */
|
|
|
|
ackMQTTMsg( dutil, xwe, topic, gameID, buf, len );
|
2021-04-19 07:04:58 -07:00
|
|
|
|
2024-03-04 10:21:08 -08:00
|
|
|
switch ( cmd ) {
|
|
|
|
case CMD_INVITE: {
|
2024-08-07 22:29:46 -07:00
|
|
|
NetLaunchInfo nli = {};
|
2024-03-04 10:21:08 -08:00
|
|
|
if ( nli_makeFromStream( &nli, stream ) ) {
|
|
|
|
dutil_onInviteReceived( dutil, xwe, &nli );
|
|
|
|
}
|
2022-12-16 13:33:36 -08:00
|
|
|
}
|
2024-03-04 10:21:08 -08:00
|
|
|
break;
|
|
|
|
case CMD_DEVGONE:
|
|
|
|
case CMD_MSG: {
|
2024-08-07 22:29:46 -07:00
|
|
|
CommsAddrRec from = {};
|
2024-03-04 10:21:08 -08:00
|
|
|
addr_addType( &from, COMMS_CONN_MQTT );
|
|
|
|
from.u.mqtt.devID = senderID;
|
|
|
|
if ( CMD_MSG == cmd ) {
|
|
|
|
dispatchMsgs( dutil, xwe, proto, stream, gameID, &from );
|
|
|
|
} else if ( CMD_DEVGONE == cmd ) {
|
|
|
|
dutil_onGameGoneReceived( dutil, xwe, gameID, &from );
|
|
|
|
}
|
2022-06-29 12:29:32 -07:00
|
|
|
}
|
2024-03-04 10:21:08 -08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
XP_LOGFF( "unknown command %d; dropping message", cmd );
|
|
|
|
// XP_ASSERT(0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
XP_LOGFF( "no senderID found; bailing" );
|
2022-12-16 13:33:36 -08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
XP_LOGFF( "bad proto %d; dropping packet", proto );
|
2020-05-31 12:56:37 -07:00
|
|
|
}
|
2023-02-03 22:00:47 -08:00
|
|
|
stream_destroy( stream );
|
2022-12-16 13:33:36 -08:00
|
|
|
} else if ( isCtrlMsg( &myID, topic ) ) {
|
|
|
|
dutil_onCtrlReceived( dutil, xwe, buf, len );
|
2024-11-02 20:54:47 -07:00
|
|
|
} else {
|
|
|
|
XP_LOGFF( "OTHER" );
|
2020-05-20 13:58:53 -07:00
|
|
|
}
|
2024-10-31 20:06:30 -07:00
|
|
|
LOG_RETURN_VOID();
|
2024-03-04 10:45:11 -08:00
|
|
|
} /* dvc_parseMQTTPacket */
|
2024-02-13 14:38:52 -08:00
|
|
|
|
2024-02-15 08:54:48 -08:00
|
|
|
typedef struct _GetByKeyData {
|
|
|
|
XP_U32 resultKey;
|
|
|
|
WSData* found;
|
|
|
|
} GetByKeyData;
|
|
|
|
|
|
|
|
static ForEachAct
|
|
|
|
getByKeyProc(const DLHead* elem, void* closure)
|
|
|
|
{
|
|
|
|
ForEachAct result = FEA_OK;
|
|
|
|
GetByKeyData* gbkdp = (GetByKeyData*)closure;
|
|
|
|
WSData* wsdp = (WSData*)elem;
|
|
|
|
if ( wsdp->resultKey == gbkdp->resultKey ) {
|
|
|
|
gbkdp->found = wsdp;
|
|
|
|
result = FEA_REMOVE | FEA_EXIT;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static WSData*
|
2024-02-15 16:48:14 -08:00
|
|
|
popForKey( XW_DUtilCtxt* dutil, XWEnv xwe, XP_U32 key )
|
2024-02-15 08:54:48 -08:00
|
|
|
{
|
|
|
|
WSData* item = NULL;
|
2024-02-15 16:48:14 -08:00
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
WITH_MUTEX(&dc->webSend.mutex);
|
2024-02-15 08:54:48 -08:00
|
|
|
|
|
|
|
GetByKeyData gbkd = { .resultKey = key, };
|
2024-09-01 22:03:49 -07:00
|
|
|
dc->webSend.data = (WSData*)dll_map( &dc->webSend.data->links,
|
|
|
|
getByKeyProc, NULL, &gbkd );
|
2024-02-15 08:54:48 -08:00
|
|
|
item = gbkd.found;
|
|
|
|
|
2024-08-19 06:56:33 -07:00
|
|
|
END_WITH_MUTEX();
|
2024-02-27 14:32:50 -08:00
|
|
|
XP_LOGFFV( "(key: %d) => %p", key, item );
|
2024-02-15 08:54:48 -08:00
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
static XP_U32
|
2024-02-15 16:48:14 -08:00
|
|
|
addWithKey( XW_DUtilCtxt* dutil, XWEnv xwe, WSData* wsdp )
|
2024-02-15 08:54:48 -08:00
|
|
|
{
|
2024-02-15 16:48:14 -08:00
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
2024-09-01 22:03:49 -07:00
|
|
|
WITH_MUTEX(&dc->webSend.mutex);
|
|
|
|
wsdp->resultKey = ++dc->webSend.key;
|
|
|
|
dc->webSend.data = (WSData*)
|
|
|
|
dll_insert( &dc->webSend.data->links, &wsdp->links, NULL );
|
2024-08-19 06:56:33 -07:00
|
|
|
END_WITH_MUTEX();
|
2024-02-27 14:32:50 -08:00
|
|
|
XP_LOGFFV( "(%p) => %d", wsdp, wsdp->resultKey );
|
2024-02-15 08:54:48 -08:00
|
|
|
return wsdp->resultKey;
|
|
|
|
}
|
|
|
|
|
2024-07-08 19:19:52 -07:00
|
|
|
static void
|
|
|
|
delWSDatum( DLHead* elem, void* closure )
|
|
|
|
{
|
|
|
|
XW_DUtilCtxt* dutil = (XW_DUtilCtxt*)closure;
|
2024-08-20 22:03:08 -07:00
|
|
|
XP_USE(dutil); /* for release builds */
|
2024-07-08 19:19:52 -07:00
|
|
|
XP_FREEP( dutil->mpool, &elem );
|
|
|
|
}
|
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
static void
|
|
|
|
setSaveDCTimerLocked( XW_DUtilCtxt* dutil, XWEnv xwe, DevCtxt* dc )
|
|
|
|
{
|
|
|
|
dvcStoreLocked( dutil, xwe, dc );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
setSaveDCTimer( XW_DUtilCtxt* dutil, XWEnv xwe, DevCtxt* dc )
|
|
|
|
{
|
|
|
|
WITH_MUTEX( &dc->mutex );
|
|
|
|
setSaveDCTimerLocked( dutil, xwe, dc );
|
|
|
|
END_WITH_MUTEX();
|
|
|
|
}
|
|
|
|
|
2024-02-15 08:54:48 -08:00
|
|
|
void
|
|
|
|
dvc_onWebSendResult( XW_DUtilCtxt* dutil, XWEnv xwe, XP_U32 resultKey,
|
|
|
|
XP_Bool succeeded, const XP_UCHAR* resultJson )
|
|
|
|
{
|
|
|
|
XP_ASSERT( 0 != resultKey );
|
|
|
|
if ( 0 != resultKey ) {
|
2024-02-15 16:48:14 -08:00
|
|
|
WSData* wsdp = popForKey( dutil, xwe, resultKey );
|
2024-02-29 12:29:35 -08:00
|
|
|
XP_ASSERT( !!wsdp );
|
|
|
|
if ( !!wsdp ) {
|
|
|
|
cJSON* result = cJSON_Parse( resultJson ); /* ok if resultJson is NULL... */
|
|
|
|
switch ( wsdp->code ) {
|
|
|
|
case WSR_REGISTER:
|
|
|
|
if ( succeeded ) {
|
|
|
|
cJSON* tmp = cJSON_GetObjectItem( result, "success" ); /* returns null if result is null */
|
|
|
|
if ( !!tmp && cJSON_IsTrue( tmp ) ) {
|
|
|
|
tmp = cJSON_GetObjectItem( result, "atNext" );
|
|
|
|
if ( !!tmp ) {
|
|
|
|
XP_U32 atNext = tmp->valueint;
|
2024-11-01 08:18:06 -07:00
|
|
|
dutil_storePtr( dutil, xwe, LAST_REG_KEY, &atNext,
|
|
|
|
sizeof(atNext) );
|
|
|
|
dutil_storePtr( dutil, xwe, KEY_GITREV, GITREV,
|
|
|
|
XP_STRLEN(GITREV) );
|
2024-02-15 08:54:48 -08:00
|
|
|
}
|
2024-09-01 22:03:49 -07:00
|
|
|
|
|
|
|
tmp = cJSON_GetObjectItem( result, "qos" );
|
|
|
|
if ( !!tmp ) {
|
|
|
|
XP_U8 qos = (XP_U8)tmp->valueint;
|
|
|
|
XP_ASSERT( 0 <= qos && qos <= 2 );
|
|
|
|
if ( 0 <= qos && qos <= 2 ) {
|
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
|
|
|
WITH_MUTEX( &dc->mutex );
|
|
|
|
if ( dc->mqttQOS != qos ) {
|
|
|
|
dc->dirty = XP_TRUE;
|
|
|
|
dc->mqttQOS = qos;
|
|
|
|
setSaveDCTimerLocked( dutil, xwe, dc );
|
|
|
|
}
|
|
|
|
END_WITH_MUTEX();
|
|
|
|
}
|
|
|
|
}
|
2024-02-15 08:54:48 -08:00
|
|
|
}
|
|
|
|
}
|
2024-02-29 12:29:35 -08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
XP_ASSERT(0);
|
|
|
|
break;
|
2024-02-15 08:54:48 -08:00
|
|
|
}
|
|
|
|
|
2024-02-29 12:29:35 -08:00
|
|
|
cJSON_Delete( result );
|
2024-07-08 19:19:52 -07:00
|
|
|
delWSDatum( &wsdp->links, dutil );
|
2024-02-29 12:29:35 -08:00
|
|
|
}
|
2024-02-15 08:54:48 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-08 19:19:52 -07:00
|
|
|
static void
|
|
|
|
freeWSState( XW_DUtilCtxt* dutil, DevCtxt* dc )
|
|
|
|
{
|
2024-09-01 22:03:49 -07:00
|
|
|
WITH_MUTEX( &dc->webSend.mutex );
|
|
|
|
dll_removeAll( &dc->webSend.data->links, delWSDatum, dutil );
|
2024-08-19 06:56:33 -07:00
|
|
|
END_WITH_MUTEX();
|
2024-07-08 19:19:52 -07:00
|
|
|
}
|
|
|
|
|
2024-04-25 12:18:04 -07:00
|
|
|
typedef struct _PhoniesMapState {
|
|
|
|
XW_DUtilCtxt* dutil;
|
2024-04-05 11:17:12 -07:00
|
|
|
const XP_UCHAR* isoCode;
|
2024-04-25 12:18:04 -07:00
|
|
|
const XP_UCHAR* phony;
|
|
|
|
const DLHead* found;
|
|
|
|
} PhoniesMapState;
|
2024-04-05 11:17:12 -07:00
|
|
|
|
|
|
|
static ForEachAct
|
|
|
|
findIsoProc( const DLHead* elem, void* closure )
|
|
|
|
{
|
|
|
|
ForEachAct result = FEA_OK;
|
|
|
|
PhoniesDataCodes* pdc = (PhoniesDataCodes*)elem;
|
|
|
|
|
2024-04-25 12:18:04 -07:00
|
|
|
PhoniesMapState* pms = (PhoniesMapState*)closure;
|
|
|
|
if ( 0 == XP_STRCMP( pms->isoCode, pdc->isoCode ) ) {
|
|
|
|
pms->found = elem;
|
2024-04-05 11:17:12 -07:00
|
|
|
result = FEA_EXIT;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PhoniesDataCodes*
|
2024-04-13 17:09:05 -07:00
|
|
|
findForIso( XW_DUtilCtxt* XP_UNUSED_DBG(dutil), DevCtxt* dc, const XP_UCHAR* isoCode )
|
2024-04-05 11:17:12 -07:00
|
|
|
{
|
2024-04-25 12:18:04 -07:00
|
|
|
PhoniesMapState ms = {
|
2024-04-05 11:17:12 -07:00
|
|
|
.isoCode = isoCode,
|
|
|
|
};
|
2024-04-25 12:18:04 -07:00
|
|
|
dll_map( &dc->pd->links, findIsoProc, NULL, &ms );
|
|
|
|
PhoniesDataCodes* pdc = (PhoniesDataCodes*)ms.found;
|
2024-04-05 11:17:12 -07:00
|
|
|
|
|
|
|
if ( !pdc ) {
|
|
|
|
pdc = XP_CALLOC( dutil->mpool, sizeof(*pdc) );
|
|
|
|
pdc->isoCode = copyString( dutil->mpool, isoCode );
|
|
|
|
dc->pd = (PhoniesDataCodes*)dll_insert( &dc->pd->links, &pdc->links, NULL );
|
|
|
|
XP_ASSERT( pdc == dc->pd );
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
addPhony( XW_DUtilCtxt* dutil, DevCtxt* dc, const XP_UCHAR* isoCode,
|
|
|
|
const XP_UCHAR* phony )
|
|
|
|
{
|
|
|
|
PhoniesDataCodes* pdc = findForIso( dutil, dc, isoCode );
|
|
|
|
XP_ASSERT( !!pdc );
|
|
|
|
|
|
|
|
PhoniesDataStrs* pd = XP_CALLOC( dutil->mpool, sizeof(*pd) );
|
|
|
|
pd->phony = copyString( dutil->mpool, phony );
|
|
|
|
|
|
|
|
pdc->head = (PhoniesDataStrs*)dll_insert( &pdc->head->links, &pd->links, NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
static ForEachAct
|
|
|
|
storeStrs( const DLHead* elem, void* closure )
|
|
|
|
{
|
|
|
|
const PhoniesDataStrs* pds = (PhoniesDataStrs*)elem;
|
|
|
|
XWStreamCtxt* stream = (XWStreamCtxt*)closure;
|
|
|
|
stringToStream( stream, pds->phony );
|
|
|
|
return FEA_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ForEachAct
|
|
|
|
storeIso( const DLHead* elem, void* closure )
|
|
|
|
{
|
|
|
|
const PhoniesDataCodes* pdc = (PhoniesDataCodes*)elem;
|
|
|
|
XWStreamCtxt* stream = (XWStreamCtxt*)closure;
|
|
|
|
stringToStream( stream, pdc->isoCode );
|
|
|
|
|
|
|
|
PhoniesDataStrs* pds = pdc->head;
|
|
|
|
XP_U16 numStrs = dll_length( &pds->links );
|
|
|
|
XP_ASSERT( 0 < numStrs );
|
|
|
|
stream_putU32VL( stream, numStrs );
|
|
|
|
|
|
|
|
dll_map( &pds->links, storeStrs, NULL, stream );
|
|
|
|
|
|
|
|
return FEA_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Storage format for PD_VERSION_1:
|
|
|
|
* version (byte)
|
|
|
|
* isoCount (byte)
|
|
|
|
** (repeats isoCount times)
|
|
|
|
** isoCode (string)
|
|
|
|
** strCount (var len XP_U32)
|
|
|
|
*** (repeats strCount times)
|
|
|
|
*** phony (string)
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
storePhoniesData( XW_DUtilCtxt* dutil, XWEnv xwe, DevCtxt* dc )
|
|
|
|
{
|
|
|
|
XWStreamCtxt* stream = mkStream( dutil );
|
|
|
|
if ( !!dc->pd ) {
|
|
|
|
stream_putU8( stream, PD_VERSION_1 );
|
|
|
|
|
|
|
|
PhoniesDataCodes* pdc = dc->pd;
|
|
|
|
XP_U16 numIsos = dll_length( &pdc->links );
|
|
|
|
XP_ASSERT( 0 < numIsos );
|
|
|
|
stream_putU8( stream, numIsos );
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
PhoniesDataCodes* pdc1 = (PhoniesDataCodes*)
|
|
|
|
#endif
|
|
|
|
dll_map( &pdc->links, storeIso, NULL, stream );
|
|
|
|
XP_ASSERT( pdc1 == pdc );
|
|
|
|
}
|
|
|
|
|
2024-11-01 08:18:06 -07:00
|
|
|
dutil_storeStream( dutil, xwe, KEY_LEGAL_PHONIES, stream );
|
2024-04-05 11:17:12 -07:00
|
|
|
stream_destroy( stream );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
loadPhoniesData( XW_DUtilCtxt* dutil, XWEnv xwe, DevCtxt* dc )
|
|
|
|
{
|
|
|
|
LOG_FUNC();
|
|
|
|
XP_ASSERT ( !dc->pd );
|
|
|
|
|
|
|
|
XWStreamCtxt* stream = mkStream( dutil );
|
2024-11-01 08:18:06 -07:00
|
|
|
dutil_loadStream( dutil, xwe, KEY_LEGAL_PHONIES, stream );
|
2024-04-05 11:17:12 -07:00
|
|
|
|
|
|
|
XP_U8 flags;
|
|
|
|
if ( stream_gotU8( stream, &flags ) && PD_VERSION_1 == flags ) {
|
|
|
|
XP_U8 numIsos;
|
|
|
|
if ( stream_gotU8( stream, &numIsos ) ) {
|
|
|
|
for ( int ii = 0; ii < numIsos; ++ii ) {
|
|
|
|
XP_UCHAR isoCode[32];
|
|
|
|
stringFromStreamHere( stream, isoCode, VSIZE(isoCode) );
|
|
|
|
XP_U32 numStrs = stream_getU32VL( stream );
|
|
|
|
for ( int jj = 0; jj < numStrs; ++jj ) {
|
|
|
|
XP_UCHAR phony[32];
|
|
|
|
stringFromStreamHere( stream, phony, VSIZE(phony) );
|
|
|
|
addPhony( dutil, dc, isoCode, phony );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
XP_LOGFF( "nothing there???" );
|
|
|
|
}
|
|
|
|
|
|
|
|
stream_destroy( stream );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dvc_addLegalPhony( XW_DUtilCtxt* dutil, XWEnv xwe,
|
|
|
|
const XP_UCHAR* isoCode,
|
|
|
|
const XP_UCHAR* phony )
|
|
|
|
{
|
|
|
|
if ( ! dvc_isLegalPhony( dutil, xwe, isoCode, phony ) ) {
|
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
|
|
|
addPhony( dutil, dc, isoCode, phony );
|
|
|
|
storePhoniesData( dutil, xwe, dc );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XP_Bool
|
|
|
|
dvc_haveLegalPhonies( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|
|
|
{
|
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
|
|
|
XP_Bool result = 0 < dll_length( &dc->pd->links );
|
|
|
|
LOG_RETURNF( "%s", boolToStr(result) );
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-04-26 09:39:39 -07:00
|
|
|
freeOnePhony( DLHead* elem, void* XP_UNUSED_DBG(closure) )
|
2024-04-05 11:17:12 -07:00
|
|
|
{
|
2024-04-26 09:39:39 -07:00
|
|
|
#ifdef DEBUG
|
2024-04-25 12:18:04 -07:00
|
|
|
PhoniesMapState* ms = (PhoniesMapState*)closure;
|
2024-04-26 09:39:39 -07:00
|
|
|
#endif
|
2024-04-05 11:17:12 -07:00
|
|
|
const PhoniesDataStrs* pds = (PhoniesDataStrs*)elem;
|
2024-04-25 12:18:04 -07:00
|
|
|
XP_FREE( ms->dutil->mpool, pds->phony );
|
|
|
|
XP_FREE( ms->dutil->mpool, elem );
|
2024-04-05 11:17:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
freeOneCode( DLHead* elem, void* closure)
|
|
|
|
{
|
|
|
|
const PhoniesDataCodes* pdc = (PhoniesDataCodes*)elem;
|
|
|
|
|
2024-04-09 11:21:57 -07:00
|
|
|
dll_removeAll( &pdc->head->links, freeOnePhony, closure );
|
2024-04-05 11:17:12 -07:00
|
|
|
|
2024-04-13 17:09:05 -07:00
|
|
|
#ifdef MEM_DEBUG
|
2024-04-25 12:18:04 -07:00
|
|
|
PhoniesMapState* ms = (PhoniesMapState*)closure;
|
2024-04-13 17:09:05 -07:00
|
|
|
#endif
|
2024-04-25 12:18:04 -07:00
|
|
|
XP_FREE( ms->dutil->mpool, pdc->isoCode );
|
|
|
|
XP_FREE( ms->dutil->mpool, elem );
|
2024-04-05 11:17:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static DevCtxt*
|
2024-04-25 12:18:04 -07:00
|
|
|
freePhonyState( XW_DUtilCtxt* dutil, XWEnv xwe )
|
2024-04-05 11:17:12 -07:00
|
|
|
{
|
2024-04-25 12:18:04 -07:00
|
|
|
PhoniesMapState ms = { .dutil = dutil, };
|
2024-04-05 11:17:12 -07:00
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
2024-04-25 12:18:04 -07:00
|
|
|
dll_removeAll( &dc->pd->links, freeOneCode, &ms );
|
2024-04-05 11:17:12 -07:00
|
|
|
dc->pd = NULL;
|
|
|
|
return dc;
|
|
|
|
}
|
|
|
|
|
2024-04-25 12:18:04 -07:00
|
|
|
static ForEachAct
|
|
|
|
clearPhonyProc( const DLHead* elem, void* closure )
|
|
|
|
{
|
|
|
|
ForEachAct result = FEA_OK;
|
|
|
|
const PhoniesDataStrs* pds = (PhoniesDataStrs*)elem;
|
|
|
|
PhoniesMapState* ms = (PhoniesMapState*)closure;
|
|
|
|
if ( 0 == XP_STRCMP( ms->phony, pds->phony ) ) {
|
|
|
|
result = FEA_EXIT | FEA_REMOVE;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dvc_clearLegalPhony( XW_DUtilCtxt* dutil, XWEnv xwe,
|
|
|
|
const XP_UCHAR* isoCode,
|
|
|
|
const XP_UCHAR* phony )
|
2024-04-05 11:17:12 -07:00
|
|
|
{
|
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
2024-04-25 12:18:04 -07:00
|
|
|
PhoniesDataCodes* pdc = findForIso( dutil, dc, isoCode );
|
|
|
|
|
|
|
|
PhoniesMapState ms = { .dutil = dutil, .phony = phony, };
|
|
|
|
pdc->head = (PhoniesDataStrs*)
|
|
|
|
dll_map( &pdc->head->links, clearPhonyProc, freeOnePhony, &ms );
|
|
|
|
if ( !pdc->head ) {
|
|
|
|
dc->pd = (PhoniesDataCodes*)dll_remove( &dc->pd->links, &pdc->links );
|
|
|
|
freeOneCode( &pdc->links, &ms );
|
|
|
|
}
|
2024-04-05 11:17:12 -07:00
|
|
|
storePhoniesData( dutil, xwe, dc );
|
|
|
|
}
|
|
|
|
|
2024-04-25 12:18:04 -07:00
|
|
|
typedef struct _GetWordsState {
|
|
|
|
WordCollector proc;
|
|
|
|
void* closure;
|
|
|
|
} GetWordsState;
|
|
|
|
|
2024-04-05 11:17:12 -07:00
|
|
|
static ForEachAct
|
2024-04-25 12:18:04 -07:00
|
|
|
getIsosProc( const DLHead* elem, void* closure )
|
2024-04-05 11:17:12 -07:00
|
|
|
{
|
2024-04-25 12:18:04 -07:00
|
|
|
const PhoniesDataCodes* pdc = (PhoniesDataCodes*)elem;
|
|
|
|
GetWordsState* gws = (GetWordsState*)closure;
|
|
|
|
(*gws->proc)( pdc->isoCode, gws->closure );
|
2024-04-05 11:17:12 -07:00
|
|
|
return FEA_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ForEachAct
|
2024-04-25 12:18:04 -07:00
|
|
|
getWordsProc( const DLHead* elem, void* closure )
|
2024-04-05 11:17:12 -07:00
|
|
|
{
|
2024-04-25 12:18:04 -07:00
|
|
|
const PhoniesDataStrs* pds = (PhoniesDataStrs*)elem;
|
|
|
|
GetWordsState* gws = (GetWordsState*)closure;
|
|
|
|
(*gws->proc)( pds->phony, gws->closure );
|
2024-04-05 11:17:12 -07:00
|
|
|
return FEA_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2024-04-25 12:18:04 -07:00
|
|
|
dvc_getIsoCodes( XW_DUtilCtxt* dutil, XWEnv xwe,
|
|
|
|
WordCollector proc, void* closure )
|
2024-04-05 11:17:12 -07:00
|
|
|
{
|
2024-04-25 12:18:04 -07:00
|
|
|
GetWordsState gws = {
|
|
|
|
.proc = proc,
|
|
|
|
.closure = closure,
|
|
|
|
};
|
|
|
|
|
2024-04-05 11:17:12 -07:00
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
2024-04-25 12:18:04 -07:00
|
|
|
dll_map( &dc->pd->links, getIsosProc, NULL, &gws );
|
2024-04-05 11:17:12 -07:00
|
|
|
}
|
|
|
|
|
2024-04-25 12:18:04 -07:00
|
|
|
void
|
|
|
|
dvc_getPhoniesFor( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* code,
|
|
|
|
WordCollector proc, void* closure )
|
|
|
|
{
|
|
|
|
GetWordsState gws = {
|
|
|
|
.proc = proc,
|
|
|
|
.closure = closure,
|
|
|
|
};
|
|
|
|
|
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
|
|
|
PhoniesDataCodes* pdc = findForIso( dutil, dc, code );
|
|
|
|
dll_map( &pdc->head->links, getWordsProc, NULL, &gws );
|
|
|
|
}
|
2024-04-05 11:17:12 -07:00
|
|
|
|
2024-08-12 21:04:46 -07:00
|
|
|
#ifdef DUTIL_TIMERS
|
|
|
|
void
|
|
|
|
dvc_onTimerFired( XW_DUtilCtxt* dutil, XWEnv xwe, TimerKey key )
|
|
|
|
{
|
2024-12-03 21:20:21 -08:00
|
|
|
// XP_LOGFF( "(key: %d)", key );
|
2024-08-12 21:04:46 -07:00
|
|
|
tmr_fired( dutil, xwe, key );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-04-05 11:17:12 -07:00
|
|
|
static ForEachAct
|
|
|
|
findPhonyProc2( const DLHead* elem, void* closure )
|
|
|
|
{
|
|
|
|
ForEachAct result = FEA_OK;
|
2024-04-25 12:18:04 -07:00
|
|
|
PhoniesMapState* ms = (PhoniesMapState*)closure;
|
2024-04-05 11:17:12 -07:00
|
|
|
const PhoniesDataStrs* pds = (PhoniesDataStrs*)elem;
|
2024-04-25 12:18:04 -07:00
|
|
|
if ( 0 == XP_STRCMP( ms->phony, pds->phony ) ) {
|
|
|
|
ms->found = elem;
|
2024-04-05 11:17:12 -07:00
|
|
|
result |= FEA_EXIT;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ForEachAct
|
|
|
|
findPhonyProc1( const DLHead* elem, void* closure )
|
|
|
|
{
|
|
|
|
ForEachAct result = FEA_OK;
|
2024-04-25 12:18:04 -07:00
|
|
|
PhoniesMapState* ms = (PhoniesMapState*)closure;
|
2024-04-05 11:17:12 -07:00
|
|
|
const PhoniesDataCodes* pdc = (PhoniesDataCodes*)elem;
|
2024-04-25 12:18:04 -07:00
|
|
|
if ( 0 == XP_STRCMP( ms->isoCode, pdc->isoCode ) ) {
|
2024-04-05 11:17:12 -07:00
|
|
|
dll_map( &pdc->head->links, findPhonyProc2, NULL, closure );
|
|
|
|
result |= FEA_EXIT;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
XP_Bool
|
|
|
|
dvc_isLegalPhony( XW_DUtilCtxt* dutil, XWEnv xwe,
|
|
|
|
const XP_UCHAR* isoCode, const XP_UCHAR* phony )
|
|
|
|
{
|
|
|
|
DevCtxt* dc = load( dutil, xwe );
|
|
|
|
|
2024-04-25 12:18:04 -07:00
|
|
|
PhoniesMapState ms = {
|
2024-04-05 11:17:12 -07:00
|
|
|
.isoCode = isoCode,
|
|
|
|
.phony = phony,
|
|
|
|
};
|
2024-04-25 12:18:04 -07:00
|
|
|
dll_map( &dc->pd->links, findPhonyProc1, NULL, &ms );
|
2024-04-05 11:17:12 -07:00
|
|
|
|
2024-04-25 12:18:04 -07:00
|
|
|
return NULL != ms.found;
|
2024-04-05 11:17:12 -07:00
|
|
|
}
|
|
|
|
|
2024-02-13 14:38:52 -08:00
|
|
|
static void
|
|
|
|
registerIf( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|
|
|
{
|
2024-02-15 08:54:48 -08:00
|
|
|
XP_U32 atNext = 0;
|
|
|
|
XP_U32 len = sizeof(atNext);
|
2024-11-01 08:18:06 -07:00
|
|
|
dutil_loadPtr( dutil, xwe, LAST_REG_KEY, &atNext, &len );
|
2024-02-15 08:54:48 -08:00
|
|
|
XP_UCHAR gitrev[128];
|
|
|
|
len = VSIZE(gitrev);
|
2024-11-01 08:18:06 -07:00
|
|
|
dutil_loadPtr( dutil, xwe, KEY_GITREV, gitrev, &len );
|
2024-02-15 08:54:48 -08:00
|
|
|
if ( len >= VSIZE(gitrev) ) {
|
|
|
|
len = VSIZE(gitrev) - 1;
|
|
|
|
}
|
|
|
|
gitrev[len] = '\0';
|
2024-02-13 14:38:52 -08:00
|
|
|
|
|
|
|
XP_U32 now = dutil_getCurSeconds( dutil, xwe );
|
2024-02-15 08:54:48 -08:00
|
|
|
if ( atNext < now || 0 != XP_STRCMP( gitrev, GITREV ) ) {
|
2024-02-14 10:43:51 -08:00
|
|
|
|
|
|
|
/* Start with the platform's values */
|
|
|
|
cJSON* params = dutil_getRegValues( dutil, xwe );
|
2024-02-13 14:38:52 -08:00
|
|
|
|
|
|
|
MQTTDevID myID;
|
|
|
|
dvc_getMQTTDevID( dutil, xwe, &myID );
|
|
|
|
XP_UCHAR tmp[32];
|
|
|
|
formatMQTTDevID( &myID, tmp, VSIZE(tmp) );
|
|
|
|
cJSON_AddStringToObject( params, "devid", tmp );
|
|
|
|
|
2024-02-15 08:54:48 -08:00
|
|
|
cJSON_AddStringToObject( params, "gitrev", GITREV );
|
2024-02-13 14:38:52 -08:00
|
|
|
#ifdef DEBUG
|
|
|
|
cJSON_AddBoolToObject( params, "dbg", XP_TRUE );
|
|
|
|
#endif
|
|
|
|
char* loc = getenv("LANG");
|
|
|
|
cJSON_AddStringToObject( params, "loc", loc );
|
|
|
|
|
|
|
|
cJSON_AddNumberToObject( params, "myNow", now );
|
|
|
|
|
2024-02-15 08:54:48 -08:00
|
|
|
WSData* wsdp = XP_CALLOC( dutil->mpool, sizeof(*wsdp) );
|
|
|
|
wsdp->code = WSR_REGISTER;
|
2024-02-15 16:48:14 -08:00
|
|
|
XP_U32 resultKey = addWithKey( dutil, xwe, wsdp );
|
2024-02-13 14:38:52 -08:00
|
|
|
|
2024-02-15 08:54:48 -08:00
|
|
|
dutil_sendViaWeb( dutil, xwe, resultKey, "register", params );
|
|
|
|
cJSON_Delete( params );
|
2024-02-13 14:38:52 -08:00
|
|
|
}
|
|
|
|
} /* registerIf */
|
|
|
|
|
|
|
|
void
|
|
|
|
dvc_init( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|
|
|
{
|
|
|
|
LOG_FUNC();
|
2024-02-14 10:43:51 -08:00
|
|
|
XP_ASSERT( 0 == dutil->magic );
|
2024-02-15 08:54:48 -08:00
|
|
|
|
2024-02-15 16:48:14 -08:00
|
|
|
XP_ASSERT( !dutil->devCtxt );
|
2024-09-01 22:03:49 -07:00
|
|
|
DevCtxt* dc = dutil->devCtxt = load( dutil, xwe );
|
|
|
|
dc->webSend.data = NULL;
|
|
|
|
dc->webSend.key = 0;
|
2024-08-19 06:56:33 -07:00
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
MUTEX_INIT( &dc->mutex, XP_FALSE );
|
|
|
|
MUTEX_INIT( &dc->webSend.mutex, XP_FALSE );
|
2024-08-20 22:03:08 -07:00
|
|
|
MUTEX_INIT( &dc->ackTimer.mutex, XP_FALSE );
|
2024-02-15 08:54:48 -08:00
|
|
|
|
2024-04-05 11:17:12 -07:00
|
|
|
loadPhoniesData( dutil, xwe, dc );
|
|
|
|
|
2024-02-27 16:07:47 -08:00
|
|
|
#ifdef DEBUG
|
2024-02-13 14:38:52 -08:00
|
|
|
dutil->magic = MAGIC_INITED;
|
2024-02-27 16:07:47 -08:00
|
|
|
#endif
|
2024-02-13 14:38:52 -08:00
|
|
|
registerIf( dutil, xwe );
|
|
|
|
}
|
2024-02-15 16:48:14 -08:00
|
|
|
|
|
|
|
void
|
|
|
|
dvc_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|
|
|
{
|
2024-04-25 12:18:04 -07:00
|
|
|
DevCtxt* dc = freePhonyState( dutil, xwe );
|
2024-07-08 19:19:52 -07:00
|
|
|
freeWSState( dutil, dc );
|
|
|
|
|
2024-09-01 22:03:49 -07:00
|
|
|
MUTEX_DESTROY( &dc->webSend.mutex );
|
2024-08-20 22:03:08 -07:00
|
|
|
MUTEX_DESTROY( &dc->ackTimer.mutex );
|
2024-09-01 22:03:49 -07:00
|
|
|
MUTEX_DESTROY( &dc->mutex );
|
2024-04-05 11:17:12 -07:00
|
|
|
|
2024-02-15 16:48:14 -08:00
|
|
|
XP_FREEP( dutil->mpool, &dc );
|
|
|
|
}
|