2020-09-21 11:31:49 -07:00
|
|
|
/* -*- compile-command: "cd ../linux && make MEMDEBUG=TRUE -j3"; -*- */
|
|
|
|
/*
|
2024-02-07 20:03:55 -08:00
|
|
|
* Copyright 2020-2024 by Eric House (xwords@eehouse.org). All rights
|
2022-12-06 07:44:00 -08:00
|
|
|
* reserved.
|
2020-09-21 11:31:49 -07:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2024-02-10 10:23:43 -08:00
|
|
|
// #define ENABLE_LOGFFV 1
|
|
|
|
|
2020-09-21 11:31:49 -07:00
|
|
|
#include "knownplyr.h"
|
|
|
|
#include "strutils.h"
|
|
|
|
#include "comms.h"
|
|
|
|
#include "dbgutil.h"
|
2024-02-07 20:03:55 -08:00
|
|
|
#include "dllist.h"
|
2020-09-21 11:31:49 -07:00
|
|
|
|
2020-09-22 20:35:59 -07:00
|
|
|
#ifdef XWFEATURE_KNOWNPLAYERS
|
|
|
|
|
2020-09-21 11:31:49 -07:00
|
|
|
typedef struct _KnownPlayer {
|
2024-02-07 20:03:55 -08:00
|
|
|
DLHead links;
|
2020-09-25 10:17:47 -07:00
|
|
|
XP_U32 newestMod;
|
2020-09-21 11:31:49 -07:00
|
|
|
XP_UCHAR* name;
|
|
|
|
CommsAddrRec addr;
|
|
|
|
} KnownPlayer;
|
|
|
|
|
|
|
|
typedef struct _KPState {
|
|
|
|
KnownPlayer* players;
|
2024-02-09 10:07:09 -08:00
|
|
|
// XP_U16 nPlayers;
|
2020-09-21 11:31:49 -07:00
|
|
|
XP_Bool dirty;
|
2020-09-21 20:27:03 -07:00
|
|
|
XP_Bool inUse;
|
2020-09-21 11:31:49 -07:00
|
|
|
} KPState;
|
|
|
|
|
2020-09-24 16:37:50 -07:00
|
|
|
static void addPlayer( XW_DUtilCtxt* dutil, KPState* state,
|
2020-09-25 10:17:47 -07:00
|
|
|
const XP_UCHAR* name, const CommsAddrRec* addr,
|
|
|
|
XP_U32 newestMod );
|
2020-09-24 16:37:50 -07:00
|
|
|
static void getPlayersImpl( const KPState* state, const XP_UCHAR** players,
|
|
|
|
XP_U16* nFound );
|
2020-09-21 11:31:49 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
loadFromStream( XW_DUtilCtxt* dutil, KPState* state, XWStreamCtxt* stream )
|
|
|
|
{
|
|
|
|
while ( 0 < stream_getSize( stream ) ) {
|
2020-09-25 10:17:47 -07:00
|
|
|
XP_U32 newestMod = stream_getU32( stream );
|
2020-09-21 11:31:49 -07:00
|
|
|
XP_UCHAR buf[64];
|
|
|
|
stringFromStreamHere( stream, buf, VSIZE(buf) );
|
|
|
|
|
|
|
|
CommsAddrRec addr = {0};
|
|
|
|
addrFromStream( &addr, stream );
|
|
|
|
|
2020-09-25 10:17:47 -07:00
|
|
|
addPlayer( dutil, state, buf, &addr, newestMod );
|
2020-09-21 11:31:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static KPState*
|
|
|
|
loadState( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|
|
|
{
|
2021-01-04 08:12:05 -08:00
|
|
|
// LOG_FUNC();
|
2020-09-30 17:21:18 -07:00
|
|
|
pthread_mutex_lock( &dutil->kpMutex );
|
|
|
|
|
2020-09-21 11:31:49 -07:00
|
|
|
KPState* state = (KPState*)dutil->kpCtxt;
|
|
|
|
if ( NULL == state ) {
|
|
|
|
dutil->kpCtxt = state = XP_CALLOC( dutil->mpool, sizeof(*state) );
|
|
|
|
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(dutil->mpool)
|
|
|
|
dutil_getVTManager(dutil) );
|
2021-03-05 09:03:32 -08:00
|
|
|
const XP_UCHAR* keys[] = { KNOWN_PLAYERS_KEY, NULL };
|
|
|
|
dutil_loadStream( dutil, xwe, keys, stream );
|
2020-09-21 11:31:49 -07:00
|
|
|
if ( 0 < stream_getSize( stream ) ) {
|
|
|
|
XP_U8 vers = stream_getU8( stream );
|
|
|
|
stream_setVersion( stream, vers );
|
|
|
|
loadFromStream( dutil, state, stream );
|
|
|
|
}
|
|
|
|
|
2023-02-03 22:00:47 -08:00
|
|
|
stream_destroy( stream );
|
2020-09-21 11:31:49 -07:00
|
|
|
}
|
2020-09-21 20:27:03 -07:00
|
|
|
XP_ASSERT( !state->inUse );
|
|
|
|
state->inUse = XP_TRUE;
|
2020-09-21 11:31:49 -07:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2024-02-08 20:38:19 -08:00
|
|
|
static ForEachAct
|
2024-02-07 20:03:55 -08:00
|
|
|
saveProc( const DLHead* dl, void* closure )
|
|
|
|
{
|
|
|
|
XWStreamCtxt* stream = (XWStreamCtxt*)closure;
|
|
|
|
KnownPlayer* kp = (KnownPlayer*)dl;
|
|
|
|
stream_putU32( stream, kp->newestMod );
|
|
|
|
stringToStream( stream, kp->name );
|
|
|
|
addrToStream( stream, &kp->addr );
|
2024-02-08 20:38:19 -08:00
|
|
|
return FEA_OK;
|
2024-02-07 20:03:55 -08:00
|
|
|
}
|
|
|
|
|
2020-09-21 11:31:49 -07:00
|
|
|
static void
|
|
|
|
saveState( XW_DUtilCtxt* dutil, XWEnv xwe, KPState* state )
|
|
|
|
{
|
|
|
|
if ( state->dirty ) {
|
|
|
|
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(dutil->mpool)
|
|
|
|
dutil_getVTManager(dutil) );
|
2023-02-16 21:36:46 -08:00
|
|
|
stream_setVersion( stream, CUR_STREAM_VERS );
|
2020-09-21 11:31:49 -07:00
|
|
|
stream_putU8( stream, CUR_STREAM_VERS );
|
2024-02-07 20:03:55 -08:00
|
|
|
|
2024-02-08 20:38:19 -08:00
|
|
|
dll_map( &state->players->links, saveProc, NULL, stream );
|
2024-02-07 20:03:55 -08:00
|
|
|
|
2021-03-05 09:03:32 -08:00
|
|
|
const XP_UCHAR* keys[] = { KNOWN_PLAYERS_KEY, NULL };
|
|
|
|
dutil_storeStream( dutil, xwe, keys, stream );
|
2023-02-03 22:00:47 -08:00
|
|
|
stream_destroy( stream );
|
2020-09-21 11:31:49 -07:00
|
|
|
state->dirty = XP_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-21 20:27:03 -07:00
|
|
|
static void
|
|
|
|
releaseState( XW_DUtilCtxt* dutil, XWEnv xwe, KPState* state )
|
|
|
|
{
|
|
|
|
XP_ASSERT( state->inUse );
|
|
|
|
saveState( dutil, xwe, state );
|
|
|
|
state->inUse = XP_FALSE;
|
2020-09-30 17:21:18 -07:00
|
|
|
|
|
|
|
pthread_mutex_unlock( &dutil->kpMutex );
|
2020-09-21 20:27:03 -07:00
|
|
|
}
|
|
|
|
|
2020-09-21 11:31:49 -07:00
|
|
|
static const XP_UCHAR*
|
|
|
|
figureNameFor( XP_U16 posn, const CurGameInfo* gi )
|
|
|
|
{
|
|
|
|
const XP_UCHAR* result = NULL;
|
|
|
|
for ( int ii = 0, nthRemote = 0;
|
|
|
|
NULL == result && ii < gi->nPlayers;
|
|
|
|
++ii ) {
|
|
|
|
const LocalPlayer* lp = &gi->players[ii];
|
|
|
|
if ( lp->isLocal ) {
|
|
|
|
continue;
|
|
|
|
} else if ( nthRemote++ == posn ) {
|
|
|
|
result = lp->name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-09-24 16:37:50 -07:00
|
|
|
static void
|
|
|
|
makeUniqueName( const KPState* state, const XP_UCHAR* name,
|
|
|
|
XP_UCHAR newName[], XP_U16 len )
|
|
|
|
{
|
2024-02-09 10:07:09 -08:00
|
|
|
XP_U16 nPlayers = dll_length( &state->players->links );
|
2020-09-24 16:37:50 -07:00
|
|
|
const XP_UCHAR* names[nPlayers];
|
|
|
|
getPlayersImpl( state, names, &nPlayers );
|
|
|
|
for ( int ii = 2; ; ++ii ) {
|
|
|
|
XP_SNPRINTF( newName, len, "%s %d", name, ii );
|
|
|
|
XP_Bool found = XP_FALSE;
|
|
|
|
for ( int jj = 0; !found && jj < nPlayers; ++jj ) {
|
|
|
|
found = 0 == XP_STRCMP( names[jj], newName );
|
|
|
|
}
|
|
|
|
if ( !found ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2024-02-10 10:23:43 -08:00
|
|
|
XP_LOGFFV( "created new name: %s", newName );
|
2020-09-24 16:37:50 -07:00
|
|
|
}
|
|
|
|
|
2024-02-07 20:03:55 -08:00
|
|
|
static int
|
|
|
|
compByName(const DLHead* dl1, const DLHead* dl2)
|
|
|
|
{
|
|
|
|
const KnownPlayer* kp1 = (const KnownPlayer*)dl1;
|
|
|
|
const KnownPlayer* kp2 = (const KnownPlayer*)dl2;
|
|
|
|
return XP_STRCMP( kp1->name, kp2->name );
|
|
|
|
}
|
|
|
|
|
2024-02-08 18:56:57 -08:00
|
|
|
static int
|
|
|
|
compByDate(const DLHead* dl1, const DLHead* dl2)
|
|
|
|
{
|
|
|
|
const KnownPlayer* kp1 = (const KnownPlayer*)dl1;
|
|
|
|
const KnownPlayer* kp2 = (const KnownPlayer*)dl2;
|
|
|
|
int result = 0;
|
|
|
|
if ( kp1->newestMod < kp2->newestMod ) {
|
|
|
|
result = 1;
|
|
|
|
} else if ( kp1->newestMod > kp2->newestMod ) {
|
|
|
|
result = -1;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-09-24 16:37:50 -07:00
|
|
|
/* Adding players is the hard part. There will be a lot with the same name and
|
|
|
|
* representing the same device. That's easy: skip adding a new entry, but if
|
|
|
|
* there's a change or addition, make it. For changes, e.g. a different
|
|
|
|
* BlueTooth device name, the newer one wins.
|
|
|
|
*
|
|
|
|
* If two different names have the same mqtt devID, they're the same
|
|
|
|
* device!!. Change the name to be that of the newer of the two, making sure
|
|
|
|
* it's not a duplicate.
|
|
|
|
*
|
|
|
|
* For early testing, however, just make a new name.
|
|
|
|
*/
|
2024-02-08 20:38:19 -08:00
|
|
|
|
|
|
|
typedef struct _AddData {
|
|
|
|
const XP_UCHAR* name;
|
|
|
|
const CommsAddrRec* addr;
|
|
|
|
KnownPlayer* withSameDevID;
|
|
|
|
KnownPlayer* withSameName;
|
|
|
|
} AddData;
|
|
|
|
|
|
|
|
static ForEachAct
|
|
|
|
addProc( const DLHead* dl, void* closure )
|
|
|
|
{
|
|
|
|
AddData* adp = (AddData*)closure;
|
|
|
|
KnownPlayer* kp = (KnownPlayer*)dl;
|
|
|
|
if ( 0 == XP_STRCMP( kp->name, adp->name ) ) {
|
|
|
|
adp->withSameName = kp;
|
|
|
|
}
|
|
|
|
if ( adp->addr->u.mqtt.devID == kp->addr.u.mqtt.devID ) {
|
|
|
|
adp->withSameDevID = kp;
|
|
|
|
}
|
|
|
|
ForEachAct result = !!adp->withSameName && !!adp->withSameDevID
|
|
|
|
? FEA_EXIT : FEA_OK;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-09-21 11:31:49 -07:00
|
|
|
static void
|
2024-02-08 20:38:19 -08:00
|
|
|
addPlayer( XW_DUtilCtxt* XP_UNUSED_DBG(dutil), KPState* state,
|
|
|
|
const XP_UCHAR* name, const CommsAddrRec* addr, XP_U32 newestMod )
|
2020-09-21 11:31:49 -07:00
|
|
|
{
|
2024-02-08 11:59:12 -08:00
|
|
|
XP_LOGFF( "(name=%s, newestMod: %d)", name, newestMod );
|
2024-02-08 20:38:19 -08:00
|
|
|
AddData ad = {.name = name, .addr = addr, };
|
|
|
|
dll_map( &state->players->links, addProc, NULL, &ad );
|
2020-09-24 16:37:50 -07:00
|
|
|
|
|
|
|
XP_UCHAR tmpName[64];
|
2024-02-08 20:38:19 -08:00
|
|
|
if ( !!ad.withSameDevID ) { /* only one allowed */
|
|
|
|
XP_Bool isNewer = newestMod > ad.withSameDevID->newestMod;
|
|
|
|
XP_Bool changed = augmentAddr( &ad.withSameDevID->addr,
|
|
|
|
addr, isNewer );
|
2020-09-25 10:17:47 -07:00
|
|
|
if ( isNewer ) {
|
2024-02-08 20:38:19 -08:00
|
|
|
XP_LOGFF( "updating newestMod from %d to %d",
|
|
|
|
ad.withSameDevID->newestMod, newestMod );
|
|
|
|
ad.withSameDevID->newestMod = newestMod;
|
2022-12-06 07:44:00 -08:00
|
|
|
changed = XP_TRUE;
|
2020-09-25 10:17:47 -07:00
|
|
|
}
|
|
|
|
state->dirty = changed || state->dirty;
|
2020-09-24 16:37:50 -07:00
|
|
|
} else {
|
2024-02-08 20:38:19 -08:00
|
|
|
if ( !!ad.withSameName ) {
|
2020-09-24 16:37:50 -07:00
|
|
|
/* Same name but different devID? Create a unique name */
|
|
|
|
makeUniqueName( state, name, tmpName, VSIZE(tmpName) );
|
|
|
|
name = tmpName;
|
|
|
|
}
|
2022-01-24 20:45:53 -08:00
|
|
|
/* XP_LOGFF( "adding new player %s!", name ); */
|
2020-09-21 11:31:49 -07:00
|
|
|
KnownPlayer* newPlayer = XP_CALLOC( dutil->mpool, sizeof(*newPlayer) );
|
|
|
|
newPlayer->name = copyString( dutil->mpool, name );
|
|
|
|
newPlayer->addr = *addr;
|
2024-02-08 11:55:24 -08:00
|
|
|
newPlayer->newestMod = newestMod;
|
2024-02-07 20:03:55 -08:00
|
|
|
state->players
|
|
|
|
= (KnownPlayer*)dll_insert( &state->players->links,
|
|
|
|
&newPlayer->links, compByName );
|
2020-09-21 11:31:49 -07:00
|
|
|
state->dirty = XP_TRUE;
|
|
|
|
}
|
2024-02-10 10:23:43 -08:00
|
|
|
XP_LOGFFV( "nPlayers now: %d", dll_length( &state->players->links ) );
|
2020-09-21 11:31:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
XP_Bool
|
|
|
|
kplr_addAddrs( XW_DUtilCtxt* dutil, XWEnv xwe, const CurGameInfo* gi,
|
2020-09-25 10:17:47 -07:00
|
|
|
CommsAddrRec addrs[], XP_U16 nAddrs, XP_U32 modTime )
|
2020-09-21 11:31:49 -07:00
|
|
|
{
|
2024-02-10 10:23:43 -08:00
|
|
|
XP_LOGFFV( "(nAddrs=%d)", nAddrs );
|
2024-02-08 18:56:57 -08:00
|
|
|
XP_ASSERT( modTime );
|
2020-09-21 11:31:49 -07:00
|
|
|
XP_Bool canUse = XP_TRUE;
|
|
|
|
for ( int ii = 0; ii < nAddrs && canUse; ++ii ) {
|
|
|
|
canUse = addr_hasType( &addrs[ii], COMMS_CONN_MQTT );
|
|
|
|
if ( !canUse ) {
|
|
|
|
XP_LOGFF( "addr %d has no mqqt id", ii );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( canUse ) {
|
|
|
|
KPState* state = loadState( dutil, xwe );
|
|
|
|
for ( int ii = 0; ii < nAddrs && canUse; ++ii ) {
|
|
|
|
const XP_UCHAR* name = figureNameFor( ii, gi );
|
|
|
|
if ( !!name ) {
|
2020-09-25 10:17:47 -07:00
|
|
|
addPlayer( dutil, state, name, &addrs[ii], modTime );
|
2020-09-21 11:31:49 -07:00
|
|
|
} else {
|
|
|
|
XP_LOGFF( "unable to find %dth name", ii );
|
|
|
|
}
|
|
|
|
}
|
2020-09-21 20:27:03 -07:00
|
|
|
releaseState( dutil, xwe, state );
|
2020-09-21 11:31:49 -07:00
|
|
|
}
|
|
|
|
|
2024-02-10 10:23:43 -08:00
|
|
|
XP_LOGFFV( "=>%s", boolToStr(canUse) );
|
2020-09-21 11:31:49 -07:00
|
|
|
return canUse;
|
|
|
|
}
|
|
|
|
|
|
|
|
XP_Bool
|
|
|
|
kplr_havePlayers( XW_DUtilCtxt* dutil, XWEnv xwe )
|
|
|
|
{
|
|
|
|
KPState* state = loadState( dutil, xwe );
|
2024-02-09 10:07:09 -08:00
|
|
|
XP_Bool result = 0 < dll_length( &state->players->links );
|
2020-09-21 20:27:03 -07:00
|
|
|
releaseState( dutil, xwe, state );
|
2020-09-21 11:31:49 -07:00
|
|
|
LOG_RETURNF( "%s", boolToStr(result) );
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-02-07 20:03:55 -08:00
|
|
|
typedef struct _GetState {
|
|
|
|
const XP_UCHAR** players;
|
|
|
|
int indx;
|
|
|
|
} GetState;
|
|
|
|
|
|
|
|
|
2024-02-08 20:38:19 -08:00
|
|
|
static ForEachAct
|
2024-02-07 20:03:55 -08:00
|
|
|
getProc( const DLHead* dl, void* closure )
|
|
|
|
{
|
|
|
|
GetState* gsp = (GetState*)closure;
|
|
|
|
const KnownPlayer* kp = (KnownPlayer*)dl;
|
|
|
|
gsp->players[gsp->indx++] = kp->name;
|
2024-02-08 20:38:19 -08:00
|
|
|
return FEA_OK;
|
2024-02-07 20:03:55 -08:00
|
|
|
}
|
|
|
|
|
2020-09-24 16:37:50 -07:00
|
|
|
static void
|
2024-02-07 20:03:55 -08:00
|
|
|
getPlayersImpl( const KPState* state, const XP_UCHAR** players,
|
|
|
|
XP_U16* nFound )
|
2020-09-21 11:31:49 -07:00
|
|
|
{
|
2024-02-09 10:07:09 -08:00
|
|
|
XP_U16 nPlayers = dll_length( &state->players->links );
|
|
|
|
if ( nPlayers <= *nFound && !!players ) {
|
2024-02-08 20:38:19 -08:00
|
|
|
GetState gs = { .players = players, .indx = 0, };
|
|
|
|
DLHead* head = dll_map( &state->players->links, getProc, NULL, &gs );
|
|
|
|
XP_ASSERT( head == &state->players->links );
|
2020-09-21 11:31:49 -07:00
|
|
|
}
|
2024-02-09 10:07:09 -08:00
|
|
|
*nFound = nPlayers;
|
2020-09-24 16:37:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2024-02-08 18:56:57 -08:00
|
|
|
kplr_getNames( XW_DUtilCtxt* dutil, XWEnv xwe, XP_Bool byDate,
|
2020-09-25 10:17:47 -07:00
|
|
|
const XP_UCHAR** players, XP_U16* nFound )
|
2020-09-24 16:37:50 -07:00
|
|
|
{
|
|
|
|
KPState* state = loadState( dutil, xwe );
|
2024-02-08 18:56:57 -08:00
|
|
|
if ( byDate ) {
|
|
|
|
state->players = (KnownPlayer*)dll_sort( &state->players->links,
|
|
|
|
compByDate );
|
|
|
|
}
|
2020-09-24 16:37:50 -07:00
|
|
|
getPlayersImpl( state, players, nFound );
|
2024-02-08 18:56:57 -08:00
|
|
|
if ( byDate ) {
|
|
|
|
state->players = (KnownPlayer*)dll_sort( &state->players->links,
|
|
|
|
compByName );
|
|
|
|
}
|
2020-09-21 20:27:03 -07:00
|
|
|
releaseState( dutil, xwe, state );
|
2020-09-21 11:31:49 -07:00
|
|
|
}
|
|
|
|
|
2024-02-08 20:38:19 -08:00
|
|
|
typedef struct _FindState {
|
|
|
|
const XP_UCHAR* name;
|
|
|
|
const KnownPlayer* result;
|
|
|
|
} FindState;
|
|
|
|
|
|
|
|
static ForEachAct
|
|
|
|
findProc( const DLHead* dl, void* closure )
|
2020-09-28 08:59:39 -07:00
|
|
|
{
|
2024-02-08 20:38:19 -08:00
|
|
|
ForEachAct result = FEA_OK;
|
|
|
|
FindState* fsp = (FindState*)closure;
|
|
|
|
const KnownPlayer* kp = (KnownPlayer*)dl;
|
|
|
|
if ( 0 == XP_STRCMP( kp->name, fsp->name ) ) {
|
|
|
|
fsp->result = kp;
|
|
|
|
result = FEA_EXIT;
|
2020-09-28 08:59:39 -07:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-02-08 20:38:19 -08:00
|
|
|
static KnownPlayer*
|
|
|
|
findByName( KPState* state, const XP_UCHAR* name )
|
|
|
|
{
|
|
|
|
FindState fs = { .name = name, };
|
|
|
|
DLHead* head = dll_map( &state->players->links, findProc, NULL, &fs );
|
|
|
|
XP_ASSERT( head == &state->players->links );
|
|
|
|
return (KnownPlayer*)fs.result;
|
|
|
|
}
|
|
|
|
|
2020-09-21 13:41:01 -07:00
|
|
|
XP_Bool
|
|
|
|
kplr_getAddr( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* name,
|
2021-01-04 08:12:05 -08:00
|
|
|
CommsAddrRec* addr, XP_U32* lastMod )
|
2020-09-21 13:41:01 -07:00
|
|
|
{
|
|
|
|
KPState* state = loadState( dutil, xwe );
|
|
|
|
XP_Bool found = XP_FALSE;
|
2020-09-28 08:59:39 -07:00
|
|
|
KnownPlayer* kp = findByName( state, name );
|
|
|
|
found = NULL != kp;
|
|
|
|
if ( found ) {
|
|
|
|
*addr = kp->addr;
|
2021-01-04 08:12:05 -08:00
|
|
|
if ( !!lastMod ) {
|
|
|
|
*lastMod = kp->newestMod;
|
|
|
|
}
|
2020-09-21 13:41:01 -07:00
|
|
|
}
|
2020-09-21 20:27:03 -07:00
|
|
|
releaseState( dutil, xwe, state );
|
2020-09-21 13:41:01 -07:00
|
|
|
LOG_RETURNF( "%s", boolToStr(found) );
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2024-02-08 20:38:19 -08:00
|
|
|
typedef struct _MDevState {
|
|
|
|
MQTTDevID devID;
|
|
|
|
const XP_UCHAR* name;
|
|
|
|
} MDevState;
|
|
|
|
|
|
|
|
static ForEachAct
|
|
|
|
mqttProc( const DLHead* dl, void* closure )
|
|
|
|
{
|
|
|
|
ForEachAct result = FEA_OK;
|
|
|
|
const KnownPlayer* kp = (KnownPlayer*)dl;
|
|
|
|
MDevState* msp = (MDevState*)closure;
|
|
|
|
const CommsAddrRec* addr = &kp->addr;
|
|
|
|
if ( addr_hasType( addr, COMMS_CONN_MQTT )
|
|
|
|
&& 0 == XP_MEMCMP( &addr->u.mqtt.devID, &msp->devID,
|
|
|
|
sizeof(msp->devID) ) ) {
|
|
|
|
msp->name = kp->name;
|
|
|
|
result = FEA_EXIT;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-09-30 10:10:43 -07:00
|
|
|
const XP_UCHAR*
|
2024-02-08 20:38:19 -08:00
|
|
|
kplr_nameForMqttDev( XW_DUtilCtxt* dutil, XWEnv xwe,
|
|
|
|
const XP_UCHAR* mqttDevID )
|
2020-09-30 10:10:43 -07:00
|
|
|
{
|
2024-02-08 20:38:19 -08:00
|
|
|
MDevState ms = {0};
|
|
|
|
if ( strToMQTTCDevID( mqttDevID, &ms.devID ) ) {
|
2020-09-30 10:10:43 -07:00
|
|
|
KPState* state = loadState( dutil, xwe );
|
2024-02-08 20:38:19 -08:00
|
|
|
DLHead* head = dll_map( &state->players->links, mqttProc, NULL, &ms );
|
|
|
|
XP_ASSERT( head == &state->players->links );
|
2020-09-30 10:10:43 -07:00
|
|
|
releaseState( dutil, xwe, state );
|
|
|
|
}
|
2024-02-08 20:38:19 -08:00
|
|
|
LOG_RETURNF( "%s", ms.name );
|
|
|
|
return ms.name;
|
2020-09-30 10:10:43 -07:00
|
|
|
}
|
|
|
|
|
2020-09-27 20:52:56 -07:00
|
|
|
static void
|
2021-03-19 13:03:39 -07:00
|
|
|
freeKP( XW_DUtilCtxt* XP_UNUSED_DBG(dutil), KnownPlayer* kp )
|
2020-09-27 20:52:56 -07:00
|
|
|
{
|
|
|
|
XP_FREEP( dutil->mpool, &kp->name );
|
|
|
|
XP_FREE( dutil->mpool, kp );
|
|
|
|
}
|
|
|
|
|
2020-09-28 11:17:51 -07:00
|
|
|
KP_Rslt
|
2020-09-28 08:59:39 -07:00
|
|
|
kplr_renamePlayer( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* oldName,
|
|
|
|
const XP_UCHAR* newName )
|
|
|
|
{
|
2020-09-28 11:17:51 -07:00
|
|
|
KP_Rslt result;
|
2020-09-28 08:59:39 -07:00
|
|
|
KPState* state = loadState( dutil, xwe );
|
2020-09-28 11:17:51 -07:00
|
|
|
|
2020-09-28 08:59:39 -07:00
|
|
|
KnownPlayer* kp = findByName( state, oldName );
|
2020-09-28 11:17:51 -07:00
|
|
|
if ( !kp ) {
|
|
|
|
result = KP_NAME_NOT_FOUND;
|
|
|
|
} else if ( NULL != findByName( state, newName ) ) {
|
|
|
|
result = KP_NAME_IN_USE;
|
|
|
|
} else {
|
2020-09-28 08:59:39 -07:00
|
|
|
XP_FREEP( dutil->mpool, &kp->name );
|
|
|
|
kp->name = copyString( dutil->mpool, newName );
|
|
|
|
state->dirty = XP_TRUE;
|
2020-09-28 11:17:51 -07:00
|
|
|
result = KP_OK;
|
2020-09-28 08:59:39 -07:00
|
|
|
}
|
2020-09-28 11:17:51 -07:00
|
|
|
|
2020-09-28 08:59:39 -07:00
|
|
|
releaseState( dutil, xwe, state );
|
2020-09-28 11:17:51 -07:00
|
|
|
return result;
|
2020-09-28 08:59:39 -07:00
|
|
|
}
|
|
|
|
|
2024-02-08 20:38:19 -08:00
|
|
|
typedef struct _DelState {
|
|
|
|
XW_DUtilCtxt* dutil;
|
|
|
|
const XP_UCHAR* name;
|
|
|
|
KPState* state;
|
|
|
|
} DelState;
|
|
|
|
|
|
|
|
static ForEachAct
|
|
|
|
delMapProc( const DLHead* dl, void* closure )
|
|
|
|
{
|
|
|
|
ForEachAct result = FEA_OK;
|
|
|
|
|
|
|
|
const KnownPlayer* kp = (KnownPlayer*)dl;
|
|
|
|
DelState* dsp = (DelState*)closure;
|
|
|
|
if ( 0 == XP_STRCMP( kp->name, dsp->name ) ) {
|
|
|
|
result = FEA_REMOVE | FEA_EXIT;
|
|
|
|
dsp->state->dirty = XP_TRUE;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
delFreeProc( DLHead* elem, void* closure )
|
|
|
|
{
|
|
|
|
DelState* dsp = (DelState*)closure;
|
|
|
|
freeKP( dsp->dutil, (KnownPlayer*)elem );
|
|
|
|
}
|
|
|
|
|
2020-09-28 11:17:51 -07:00
|
|
|
KP_Rslt
|
2020-09-27 20:52:56 -07:00
|
|
|
kplr_deletePlayer( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* name )
|
|
|
|
{
|
2024-02-08 20:38:19 -08:00
|
|
|
KP_Rslt result = KP_OK;
|
2020-09-27 20:52:56 -07:00
|
|
|
KPState* state = loadState( dutil, xwe );
|
|
|
|
|
2024-02-08 20:38:19 -08:00
|
|
|
DelState ds = { .name = name, .state = state, .dutil = dutil,};
|
|
|
|
state->players = (KnownPlayer*)
|
|
|
|
dll_map( &state->players->links, delMapProc, delFreeProc, &ds );
|
2020-09-27 20:52:56 -07:00
|
|
|
releaseState( dutil, xwe, state );
|
|
|
|
|
2020-09-28 11:17:51 -07:00
|
|
|
return result;
|
2020-09-27 20:52:56 -07:00
|
|
|
}
|
|
|
|
|
2020-09-21 11:31:49 -07:00
|
|
|
void
|
|
|
|
kplr_cleanup( XW_DUtilCtxt* dutil )
|
|
|
|
{
|
2024-02-07 20:03:55 -08:00
|
|
|
KPState** statep = (KPState**)&dutil->kpCtxt;
|
|
|
|
KPState* state = *statep;
|
|
|
|
if ( !!state ) {
|
|
|
|
XP_ASSERT( !state->inUse );
|
|
|
|
while ( !!state->players ) {
|
|
|
|
KnownPlayer* node = state->players;
|
|
|
|
state->players = (KnownPlayer*)
|
|
|
|
dll_remove( &state->players->links, &node->links );
|
|
|
|
freeKP( dutil, node );
|
2020-09-21 11:31:49 -07:00
|
|
|
}
|
2024-02-07 20:03:55 -08:00
|
|
|
XP_FREEP( dutil->mpool, statep );
|
2020-09-21 11:31:49 -07:00
|
|
|
}
|
|
|
|
}
|
2020-09-22 20:35:59 -07:00
|
|
|
#endif
|