mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-02 20:46:15 +01:00
499 lines
17 KiB
C
499 lines
17 KiB
C
|
/* -*- compile-command: "make MEMDEBUG=TRUE -j5"; -*- */
|
||
|
/*
|
||
|
* Copyright 2023 - 2024 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.
|
||
|
*/
|
||
|
|
||
|
#include <sys/socket.h>
|
||
|
#include <sys/un.h>
|
||
|
|
||
|
#include "extcmds.h"
|
||
|
#include "device.h"
|
||
|
#include "strutils.h"
|
||
|
#include "linuxmain.h"
|
||
|
#include "gamesdb.h"
|
||
|
#include "dbgutil.h"
|
||
|
|
||
|
static XP_U32
|
||
|
castGid( cJSON* obj )
|
||
|
{
|
||
|
XP_U32 gameID;
|
||
|
sscanf( obj->valuestring, "%X", &gameID );
|
||
|
return gameID;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
makeObjIfNot( cJSON** objp )
|
||
|
{
|
||
|
if ( NULL == *objp ) {
|
||
|
*objp = cJSON_CreateObject();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
addStringToObject( cJSON** objp, const char* key, const char* value )
|
||
|
{
|
||
|
makeObjIfNot( objp );
|
||
|
cJSON_AddStringToObject( *objp, key, value );
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
addGIDToObject( cJSON** objp, XP_U32 gid, const char* key )
|
||
|
{
|
||
|
char buf[16];
|
||
|
sprintf( buf, "%08X", gid );
|
||
|
addStringToObject( objp, key, buf );
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
addObjectToObject( cJSON** objp, const char* key, cJSON* value )
|
||
|
{
|
||
|
makeObjIfNot( objp );
|
||
|
cJSON_AddItemToObject( *objp, key, value );
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
addSuccessToObject( cJSON** objp, XP_Bool success )
|
||
|
{
|
||
|
makeObjIfNot( objp );
|
||
|
cJSON_AddBoolToObject( *objp, "success", success );
|
||
|
}
|
||
|
|
||
|
static XP_U32
|
||
|
gidFromObject( const cJSON* obj )
|
||
|
{
|
||
|
cJSON* tmp = cJSON_GetObjectItem( obj, "gid" );
|
||
|
XP_ASSERT( !!tmp );
|
||
|
return castGid( tmp );
|
||
|
}
|
||
|
|
||
|
static XP_Bool
|
||
|
inviteFromArgs( CmdWrapper* wr, cJSON* args )
|
||
|
{
|
||
|
XP_U32 gameID = gidFromObject( args );
|
||
|
|
||
|
cJSON* remotes = cJSON_GetObjectItem( args, "remotes" );
|
||
|
|
||
|
int nRemotes = cJSON_GetArraySize(remotes);
|
||
|
CommsAddrRec destAddrs[nRemotes];
|
||
|
XP_MEMSET( destAddrs, 0, sizeof(destAddrs) );
|
||
|
XP_U16 channels[nRemotes];
|
||
|
XP_MEMSET( channels, 0, sizeof(channels) );
|
||
|
|
||
|
for ( int ii = 0; ii < nRemotes; ++ii ) {
|
||
|
cJSON* item = cJSON_GetArrayItem( remotes, ii );
|
||
|
cJSON* tmp = cJSON_GetObjectItem( item, "channel" );
|
||
|
XP_ASSERT( !!tmp );
|
||
|
channels[ii] = tmp->valueint;
|
||
|
XP_LOGFF( "read channel: %X", channels[ii] );
|
||
|
|
||
|
cJSON* addr = cJSON_GetObjectItem( item, "addr" );
|
||
|
XP_ASSERT( !!addr );
|
||
|
tmp = cJSON_GetObjectItem( addr, "mqtt" );
|
||
|
if ( !!tmp ) {
|
||
|
XP_LOGFF( "parsing mqtt: %s", tmp->valuestring );
|
||
|
addr_addType( &destAddrs[ii], COMMS_CONN_MQTT );
|
||
|
XP_Bool success = strToMQTTCDevID( tmp->valuestring, &destAddrs[ii].u.mqtt.devID );
|
||
|
XP_ASSERT( success );
|
||
|
}
|
||
|
tmp = cJSON_GetObjectItem( addr, "sms" );
|
||
|
if ( !!tmp ) {
|
||
|
XP_LOGFF( "parsing sms: %s", tmp->valuestring );
|
||
|
addr_addType( &destAddrs[ii], COMMS_CONN_SMS );
|
||
|
XP_STRCAT( destAddrs[ii].u.sms.phone, tmp->valuestring );
|
||
|
destAddrs[ii].u.sms.port = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
(*wr->procs.addInvites)( wr->closure, gameID, nRemotes, channels, destAddrs );
|
||
|
|
||
|
LOG_RETURN_VOID();
|
||
|
return XP_TRUE;
|
||
|
}
|
||
|
|
||
|
static XP_Bool
|
||
|
moveifFromArgs( CmdWrapper* wr, cJSON* args )
|
||
|
{
|
||
|
XP_U32 gameID = gidFromObject( args );
|
||
|
cJSON* tmp = cJSON_GetObjectItem( args, "tryTrade" );
|
||
|
XP_Bool tryTrade = !!tmp && cJSON_IsTrue( tmp );
|
||
|
return (*wr->procs.makeMoveIf)( wr->closure, gameID, tryTrade );
|
||
|
}
|
||
|
|
||
|
static XP_Bool
|
||
|
chatFromArgs( CmdWrapper* wr, cJSON* args )
|
||
|
{
|
||
|
XP_U32 gameID = gidFromObject( args );
|
||
|
cJSON* tmp = cJSON_GetObjectItem( args, "msg" );
|
||
|
const char* msg = tmp->valuestring;
|
||
|
return (*wr->procs.sendChat)( wr->closure, gameID, msg );
|
||
|
}
|
||
|
|
||
|
/* Return 'gid' of new game */
|
||
|
static XP_U32
|
||
|
rematchFromArgs( CmdWrapper* wr, cJSON* args )
|
||
|
{
|
||
|
XP_U32 result = 0;
|
||
|
|
||
|
XP_U32 gameID = gidFromObject( args );
|
||
|
|
||
|
cJSON* tmp = cJSON_GetObjectItem( args, "rematchOrder" );
|
||
|
RematchOrder ro = roFromStr( tmp->valuestring );
|
||
|
|
||
|
XP_U32 newGameID = 0;
|
||
|
if ( (*wr->procs.makeRematch)( wr->closure, gameID, ro, &newGameID ) ) {
|
||
|
result = newGameID;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static XP_Bool
|
||
|
getGamesStateForArgs( CmdWrapper* wr, cJSON* args, cJSON** states, cJSON** orders )
|
||
|
{
|
||
|
LOG_FUNC();
|
||
|
LaunchParams* params = wr->params;
|
||
|
|
||
|
*states = cJSON_CreateArray();
|
||
|
|
||
|
cJSON* gids = cJSON_GetObjectItem( args, "gids" );
|
||
|
XP_Bool success = !!gids;
|
||
|
for ( int ii = 0 ; success && ii < cJSON_GetArraySize(gids) ; ++ii ) {
|
||
|
XP_U32 gameID = castGid( cJSON_GetArrayItem( gids, ii ) );
|
||
|
|
||
|
GameInfo gib;
|
||
|
if ( gdb_getGameInfoForGID( params->pDb, gameID, &gib ) ) {
|
||
|
cJSON* item = NULL;
|
||
|
addGIDToObject( &item, gameID, "gid" );
|
||
|
cJSON_AddBoolToObject( item, "gameOver", gib.gameOver );
|
||
|
cJSON_AddNumberToObject( item, "nPending", gib.nPending );
|
||
|
cJSON_AddNumberToObject( item, "nMoves", gib.nMoves );
|
||
|
cJSON_AddNumberToObject( item, "nTiles", gib.nTiles );
|
||
|
|
||
|
cJSON_AddItemToArray( *states, item );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
XP_LOGFF( "done with states" ); /* got here */
|
||
|
|
||
|
if ( success && !!orders ) {
|
||
|
cJSON* gids = cJSON_GetObjectItem( args, "orders" );
|
||
|
if ( !gids ) {
|
||
|
*orders = NULL;
|
||
|
} else {
|
||
|
*orders = cJSON_CreateArray();
|
||
|
for ( int ii = 0 ; ii < cJSON_GetArraySize(gids) ; ++ii ) {
|
||
|
XP_U32 gameID = castGid( cJSON_GetArrayItem( gids, ii ) );
|
||
|
|
||
|
const CommonGlobals* cg =
|
||
|
(*wr->procs.getForGameID)( wr->closure, gameID );
|
||
|
if ( !cg ) {
|
||
|
continue;
|
||
|
}
|
||
|
const XWGame* game = &cg->game;
|
||
|
if ( server_getGameIsConnected( game->server ) ) {
|
||
|
const CurGameInfo* gi = cg->gi;
|
||
|
LOGGI( gi, __func__ );
|
||
|
cJSON* order = NULL;
|
||
|
addGIDToObject( &order, gameID, "gid" );
|
||
|
cJSON* players = cJSON_CreateArray();
|
||
|
for ( int jj = 0; jj < gi->nPlayers; ++jj ) {
|
||
|
XP_LOGFF( "looking at player %d", jj );
|
||
|
const LocalPlayer* lp = &gi->players[jj];
|
||
|
XP_LOGFF( "adding player %d: %s", jj, lp->name );
|
||
|
cJSON* cName = cJSON_CreateString( lp->name );
|
||
|
cJSON_AddItemToArray( players, cName);
|
||
|
}
|
||
|
cJSON_AddItemToObject( order, "players", players );
|
||
|
cJSON_AddItemToArray( *orders, order );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOG_RETURNF( "%s", boolToStr(success) );
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
/* Return for each gid and array of player names, in play order, and including
|
||
|
for each whether it's the host and if a robot. For now let's try by opening
|
||
|
each game (yeah! yuck!) to read the info directly. Later add to a the db
|
||
|
accessed by gamesdb.c
|
||
|
*/
|
||
|
static cJSON*
|
||
|
getPlayersForArgs( CmdWrapper* wr, cJSON* args )
|
||
|
{
|
||
|
cJSON* result = cJSON_CreateArray();
|
||
|
cJSON* gids = cJSON_GetObjectItem( args, "gids" );
|
||
|
for ( int ii = 0 ; ii < cJSON_GetArraySize(gids) ; ++ii ) {
|
||
|
XP_U32 gameID = castGid( cJSON_GetArrayItem( gids, ii ) );
|
||
|
|
||
|
const CommonGlobals* cg = (*wr->procs.getForGameID)( wr->closure, gameID );
|
||
|
const CurGameInfo* gi = cg->gi;
|
||
|
LOGGI( gi, __func__ );
|
||
|
const XWGame* game = &cg->game;
|
||
|
|
||
|
cJSON* players = cJSON_CreateArray();
|
||
|
for ( int jj = 0; jj < gi->nPlayers; ++jj ) {
|
||
|
cJSON* playerObj = NULL;
|
||
|
const LocalPlayer* lp = &gi->players[jj];
|
||
|
XP_LOGFF( "adding player %d: %s", jj, lp->name );
|
||
|
addStringToObject( &playerObj, "name", lp->name );
|
||
|
XP_Bool isLocal = lp->isLocal;
|
||
|
cJSON_AddBoolToObject( playerObj, "isLocal", isLocal );
|
||
|
|
||
|
/* Roles: I don't think a guest in a 3- or 4-device game knows
|
||
|
which of the other players is host. Host is who it sends its
|
||
|
moves to, but is there an order there? */
|
||
|
XP_Bool isHost = game_getIsHost( game );
|
||
|
isHost = isHost && isLocal;
|
||
|
cJSON_AddBoolToObject( playerObj, "isHost", isHost );
|
||
|
|
||
|
cJSON_AddItemToArray( players, playerObj );
|
||
|
}
|
||
|
cJSON_AddItemToArray( result, players );
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static XP_U32
|
||
|
makeGameFromArgs( CmdWrapper* wr, cJSON* args )
|
||
|
{
|
||
|
LaunchParams* params = wr->params;
|
||
|
CurGameInfo gi = {0};
|
||
|
gi_copy( MPPARM(params->mpool) &gi, ¶ms->pgi );
|
||
|
gi.boardSize = 15;
|
||
|
gi.traySize = 7;
|
||
|
|
||
|
cJSON* tmp = cJSON_GetObjectItem( args, "nPlayers" );
|
||
|
XP_ASSERT( !!tmp );
|
||
|
gi.nPlayers = tmp->valueint;
|
||
|
|
||
|
tmp = cJSON_GetObjectItem( args, "boardSize" );
|
||
|
if ( !!tmp ) {
|
||
|
gi.boardSize = tmp->valueint;
|
||
|
}
|
||
|
tmp = cJSON_GetObjectItem( args, "traySize" );
|
||
|
if ( !!tmp ) {
|
||
|
gi.traySize = tmp->valueint;
|
||
|
}
|
||
|
|
||
|
tmp = cJSON_GetObjectItem( args, "allowSub7" );
|
||
|
gi.tradeSub7 = !!tmp && cJSON_IsTrue( tmp );
|
||
|
|
||
|
tmp = cJSON_GetObjectItem( args, "isSolo" );
|
||
|
XP_ASSERT( !!tmp );
|
||
|
XP_Bool isSolo = cJSON_IsTrue( tmp );
|
||
|
|
||
|
tmp = cJSON_GetObjectItem( args, "timerSeconds" );
|
||
|
if ( !!tmp ) {
|
||
|
gi.gameSeconds = tmp->valueint;
|
||
|
if ( 0 != gi.gameSeconds ) {
|
||
|
gi.timerEnabled = XP_TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
tmp = cJSON_GetObjectItem( args, "hostPosn" );
|
||
|
XP_ASSERT( !!tmp );
|
||
|
int hostPosn = tmp->valueint;
|
||
|
replaceStringIfDifferent( params->mpool, &gi.players[hostPosn].name,
|
||
|
params->localName );
|
||
|
for ( int ii = 0; ii < gi.nPlayers; ++ii ) {
|
||
|
LocalPlayer* lp = &gi.players[ii];
|
||
|
lp->isLocal = isSolo || ii == hostPosn;
|
||
|
if ( isSolo ) {
|
||
|
lp->robotIQ = ii == hostPosn ? 0 : 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gi.serverRole = isSolo ? SERVER_STANDALONE : SERVER_ISHOST;
|
||
|
|
||
|
tmp = cJSON_GetObjectItem( args, "dict" );
|
||
|
XP_ASSERT( tmp );
|
||
|
replaceStringIfDifferent( params->mpool, &gi.dictName, tmp->valuestring );
|
||
|
|
||
|
/* cb_dims dims; */
|
||
|
/* figureDims( aGlobals, &dims ); */
|
||
|
|
||
|
XP_U32 newGameID;
|
||
|
bool success = (*wr->procs.newGame)( wr->closure, &gi, &newGameID );
|
||
|
XP_ASSERT( success );
|
||
|
|
||
|
gi_disposePlayerInfo( MPPARM(params->mpool) &gi );
|
||
|
return newGameID;
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
on_incoming_signal( GSocketService* XP_UNUSED(service),
|
||
|
GSocketConnection* connection,
|
||
|
GObject* XP_UNUSED(source_object), gpointer user_data )
|
||
|
{
|
||
|
XP_LOGFF( "called" );
|
||
|
CmdWrapper* wr = (CmdWrapper*)user_data;
|
||
|
// CursesAppGlobals* aGlobals = (CursesAppGlobals*)user_data;
|
||
|
LaunchParams* params = wr->params;
|
||
|
XP_U32 startTime = dutil_getCurSeconds( params->dutil, NULL_XWE );
|
||
|
|
||
|
GInputStream* istream = g_io_stream_get_input_stream( G_IO_STREAM(connection) );
|
||
|
|
||
|
short len;
|
||
|
gssize nread = g_input_stream_read( istream, &len, sizeof(len), NULL, NULL );
|
||
|
XP_ASSERT( nread == sizeof(len) );
|
||
|
len = ntohs(len);
|
||
|
|
||
|
gchar buf[len+1];
|
||
|
nread = g_input_stream_read( istream, buf, len, NULL, NULL );
|
||
|
if ( 0 <= nread ) {
|
||
|
XP_ASSERT( nread == len );
|
||
|
buf[nread] = '\0';
|
||
|
XP_LOGFF( "Message: \"%s\"\n", buf );
|
||
|
|
||
|
cJSON* reply = cJSON_CreateArray();
|
||
|
|
||
|
cJSON* cmds = cJSON_Parse( buf );
|
||
|
XP_LOGFF( "got msg with array of len %d", cJSON_GetArraySize(cmds) );
|
||
|
for ( int ii = 0 ; ii < cJSON_GetArraySize(cmds) ; ++ii ) {
|
||
|
cJSON* item = cJSON_GetArrayItem( cmds, ii );
|
||
|
cJSON* cmd = cJSON_GetObjectItem( item, "cmd" );
|
||
|
cJSON* key = cJSON_GetObjectItem( item, "key" );
|
||
|
cJSON* args = cJSON_GetObjectItem( item, "args" );
|
||
|
const char* cmdStr = cmd->valuestring;
|
||
|
|
||
|
cJSON* response = NULL;
|
||
|
XP_Bool success = XP_TRUE;
|
||
|
|
||
|
if ( 0 == strcmp( cmdStr, "quit" ) ) {
|
||
|
cJSON* gids;
|
||
|
if ( getGamesStateForArgs( wr, args, &gids, NULL ) ) {
|
||
|
addObjectToObject( &response, "states", gids );
|
||
|
}
|
||
|
(*wr->procs.quit)( wr->closure );
|
||
|
} else if ( 0 == strcmp( cmdStr, "getMQTTDevID" ) ) {
|
||
|
MQTTDevID devID;
|
||
|
dvc_getMQTTDevID( params->dutil, NULL_XWE, &devID );
|
||
|
char buf[64];
|
||
|
formatMQTTDevID( &devID, buf, sizeof(buf) );
|
||
|
cJSON* devid = cJSON_CreateString( buf );
|
||
|
addObjectToObject( &response, "mqtt", devid );
|
||
|
} else if ( 0 == strcmp( cmdStr, "makeGame" ) ) {
|
||
|
XP_U32 newGameID = makeGameFromArgs( wr, args );
|
||
|
success = 0 != newGameID;
|
||
|
if ( success ) {
|
||
|
addGIDToObject( &response, newGameID, "newGid" );
|
||
|
}
|
||
|
} else if ( 0 == strcmp( cmdStr, "invite" ) ) {
|
||
|
success = inviteFromArgs( wr, args );
|
||
|
} else if ( 0 == strcmp( cmdStr, "moveIf" ) ) {
|
||
|
success = moveifFromArgs( wr, args );
|
||
|
} else if ( 0 == strcmp( cmdStr, "rematch" ) ) {
|
||
|
XP_U32 newGameID = rematchFromArgs( wr, args );
|
||
|
success = 0 != newGameID;
|
||
|
if ( success ) {
|
||
|
addGIDToObject( &response, newGameID, "newGid" );
|
||
|
}
|
||
|
} else if ( 0 == strcmp( cmdStr, "getStates" ) ) {
|
||
|
cJSON* gids;
|
||
|
cJSON* orders;
|
||
|
success = getGamesStateForArgs( wr, args, &gids, &orders );
|
||
|
if ( success ) {
|
||
|
addObjectToObject( &response, "states", gids );
|
||
|
addObjectToObject( &response, "orders", orders );
|
||
|
}
|
||
|
} else if ( 0 == strcmp( cmdStr, "getPlayers" ) ) {
|
||
|
cJSON* players = getPlayersForArgs( wr, args );
|
||
|
addObjectToObject( &response, "players", players );
|
||
|
} else if ( 0 == strcmp( cmdStr, "sendChat" ) ) {
|
||
|
success = chatFromArgs( wr, args );
|
||
|
} else {
|
||
|
success = XP_FALSE;
|
||
|
XP_ASSERT(0);
|
||
|
}
|
||
|
|
||
|
addSuccessToObject( &response, success );
|
||
|
|
||
|
cJSON* tmp = cJSON_CreateObject();
|
||
|
cJSON_AddStringToObject( tmp, "cmd", cmdStr );
|
||
|
cJSON_AddNumberToObject( tmp, "key", key->valueint );
|
||
|
cJSON_AddItemToObject( tmp, "response", response );
|
||
|
|
||
|
/*(void)*/cJSON_AddItemToArray( reply, tmp );
|
||
|
}
|
||
|
cJSON_Delete( cmds ); /* this apparently takes care of all children */
|
||
|
|
||
|
char* replyStr = cJSON_PrintUnformatted( reply );
|
||
|
short replyStrLen = strlen(replyStr);
|
||
|
XP_LOGFF( "len(%s): %d", replyStr, replyStrLen );
|
||
|
short replyStrNBOLen = htons(replyStrLen);
|
||
|
|
||
|
GOutputStream* ostream = g_io_stream_get_output_stream( G_IO_STREAM(connection) );
|
||
|
gsize nwritten;
|
||
|
gboolean wroteall = g_output_stream_write_all( ostream, &replyStrNBOLen, sizeof(replyStrNBOLen),
|
||
|
&nwritten, NULL, NULL );
|
||
|
XP_ASSERT( wroteall && nwritten == sizeof(replyStrNBOLen) );
|
||
|
wroteall = g_output_stream_write_all( ostream, replyStr, replyStrLen, &nwritten, NULL, NULL );
|
||
|
XP_ASSERT( wroteall && nwritten == replyStrLen );
|
||
|
GError* error = NULL;
|
||
|
g_output_stream_close( ostream, NULL, &error );
|
||
|
if ( !!error ) {
|
||
|
XP_LOGFF( "g_output_stream_close()=>%s", error->message );
|
||
|
g_error_free( error );
|
||
|
}
|
||
|
cJSON_Delete( reply );
|
||
|
free( replyStr );
|
||
|
}
|
||
|
|
||
|
XP_U32 consumed = dutil_getCurSeconds( params->dutil, NULL_XWE ) - startTime;
|
||
|
if ( 0 < consumed ) {
|
||
|
XP_LOGFF( "took %d seconds", consumed );
|
||
|
}
|
||
|
LOG_RETURN_VOID();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
GSocketService*
|
||
|
cmds_addCmdListener( const CmdWrapper* wr )
|
||
|
{
|
||
|
LOG_FUNC();
|
||
|
XP_ASSERT( !!wr && !!wr->params );
|
||
|
const XP_UCHAR* cmdsSocket = wr->params->cmdsSocket;
|
||
|
GSocketService* service = NULL;
|
||
|
if ( !!cmdsSocket ) {
|
||
|
service = g_socket_service_new();
|
||
|
|
||
|
struct sockaddr_un addr = {0};
|
||
|
addr.sun_family = AF_UNIX;
|
||
|
strncpy( addr.sun_path, cmdsSocket, sizeof(addr.sun_path) - 1);
|
||
|
GSocketAddress* gsaddr
|
||
|
= g_socket_address_new_from_native (&addr, sizeof(addr) );
|
||
|
GError* error = NULL;
|
||
|
if ( g_socket_listener_add_address( (GSocketListener*)service, gsaddr,
|
||
|
G_SOCKET_TYPE_STREAM,
|
||
|
G_SOCKET_PROTOCOL_DEFAULT, NULL, NULL,
|
||
|
&error ) ) {
|
||
|
} else {
|
||
|
XP_LOGFF( "g_socket_listener_add_address() failed: %s", error->message );
|
||
|
}
|
||
|
g_object_unref( gsaddr );
|
||
|
|
||
|
g_signal_connect( service, "incoming", G_CALLBACK(on_incoming_signal),
|
||
|
(void*)wr );
|
||
|
} else {
|
||
|
XP_LOGFF( "cmdsSocket not set" );
|
||
|
}
|
||
|
LOG_RETURNF( "%p", service );
|
||
|
return service;
|
||
|
}
|