mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-27 09:58:45 +01:00
beginning of support for invite-by-relay (which is mostly interesting
for Rematch): works for linux version, provided you know the relayID of the device you're inviting. Added to common/ a stream-saving version of java's NetLaunchInfo I'll probably want to use there too for cross-platform compatibility (there being no jni support for json.)
This commit is contained in:
parent
6d768972db
commit
8f794fbd32
18 changed files with 919 additions and 77 deletions
|
@ -2697,9 +2697,14 @@ countAddrRecs( const CommsCtxt* comms )
|
|||
|
||||
XP_Bool
|
||||
addr_iter( const CommsAddrRec* addr, CommsConnType* typp, XP_U32* state )
|
||||
{
|
||||
return types_iter( addr->_conTypes, typp, state );
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
types_iter( XP_U32 conTypes, CommsConnType* typp, XP_U32* state )
|
||||
{
|
||||
CommsConnType typ = *state;
|
||||
XP_U16 conTypes = addr->_conTypes;
|
||||
while ( ++typ < COMMS_CONN_NTYPES ) {
|
||||
*state = typ;
|
||||
XP_U16 mask = 1 << (typ - 1);
|
||||
|
@ -2717,11 +2722,17 @@ addr_iter( const CommsAddrRec* addr, CommsConnType* typp, XP_U32* state )
|
|||
|
||||
XP_Bool
|
||||
addr_hasType( const CommsAddrRec* addr, CommsConnType typ )
|
||||
{
|
||||
return types_hasType( addr->_conTypes, typ );
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
types_hasType( XP_U16 conTypes, CommsConnType typ )
|
||||
{
|
||||
/* Any address has NONE */
|
||||
XP_Bool hasType = COMMS_CONN_NONE == typ;
|
||||
if ( !hasType ) {
|
||||
hasType = 0 != (addr->_conTypes & (1 << (typ - 1)));
|
||||
hasType = 0 != (conTypes & (1 << (typ - 1)));
|
||||
}
|
||||
// XP_LOGF( "%s(%s) => %d", __func__, ConnType2Str(typ), hasType );
|
||||
return hasType;
|
||||
|
@ -2741,11 +2752,17 @@ addr_getType( const CommsAddrRec* addr )
|
|||
}
|
||||
|
||||
void
|
||||
addr_addType( CommsAddrRec* addr, CommsConnType type )
|
||||
types_addType( XP_U16* conTypes, CommsConnType type )
|
||||
{
|
||||
XP_ASSERT( COMMS_CONN_NONE != type );
|
||||
// XP_LOGF( "%s(%s)", __func__, ConnType2Str(type) );
|
||||
addr->_conTypes |= 1 << (type - 1);
|
||||
*conTypes |= 1 << (type - 1);
|
||||
}
|
||||
|
||||
void
|
||||
addr_addType( CommsAddrRec* addr, CommsConnType type )
|
||||
{
|
||||
types_addType( &addr->_conTypes, type );
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -240,11 +240,13 @@ XP_Bool comms_isConnected( const CommsCtxt* const comms );
|
|||
CommsConnType addr_getType( const CommsAddrRec* addr );
|
||||
void addr_setType( CommsAddrRec* addr, CommsConnType type );
|
||||
void addr_addType( CommsAddrRec* addr, CommsConnType type );
|
||||
void types_addType( XP_U16* conTypes, CommsConnType type );
|
||||
void addr_rmType( CommsAddrRec* addr, CommsConnType type );
|
||||
XP_Bool addr_hasType( const CommsAddrRec* addr, CommsConnType type );
|
||||
XP_Bool types_hasType( XP_U16 conTypes, CommsConnType type );
|
||||
XP_Bool addr_iter( const CommsAddrRec* addr, CommsConnType* typp,
|
||||
XP_U32* state );
|
||||
|
||||
XP_Bool types_iter( XP_U32 conTypes, CommsConnType* typp, XP_U32* state );
|
||||
|
||||
# ifdef DEBUG
|
||||
void comms_getStats( CommsCtxt* comms, XWStreamCtxt* stream );
|
||||
|
|
|
@ -40,6 +40,7 @@ COMMONSRC = \
|
|||
$(COMMONDIR)/engine.c \
|
||||
$(COMMONDIR)/memstream.c \
|
||||
$(COMMONDIR)/comms.c \
|
||||
$(COMMONDIR)/invit.c \
|
||||
$(COMMONDIR)/mempool.c \
|
||||
$(COMMONDIR)/movestak.c \
|
||||
$(COMMONDIR)/strutils.c \
|
||||
|
@ -74,6 +75,7 @@ COMMON4 = \
|
|||
$(COMMONOBJDIR)/dragdrpp.o \
|
||||
$(COMMONOBJDIR)/memstream.o \
|
||||
$(COMMONOBJDIR)/comms.o \
|
||||
$(COMMONOBJDIR)/invit.o \
|
||||
$(COMMONOBJDIR)/mempool.o \
|
||||
|
||||
COMMON5 = \
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#ifndef _GAME_H_
|
||||
#define _GAME_H_
|
||||
|
||||
#include "comtypes.h"
|
||||
#include "gameinfo.h"
|
||||
#include "model.h"
|
||||
#include "board.h"
|
||||
|
|
157
xwords4/common/invit.c
Normal file
157
xwords4/common/invit.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
/* -*- compile-command: "cd ../linux && make MEMDEBUG=TRUE -j3"; -*- */
|
||||
/*
|
||||
* Copyright 2001 - 2015 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 "invit.h"
|
||||
#include "comms.h"
|
||||
#include "strutils.h"
|
||||
|
||||
void
|
||||
invit_init( InviteInfo* invit, const CurGameInfo* gi, const CommsAddrRec* addr,
|
||||
XP_U16 nPlayers, XP_U16 forceChannel )
|
||||
{
|
||||
XP_MEMSET( invit, 0, sizeof(*invit) );
|
||||
invit->gameID = gi->gameID;
|
||||
XP_STRCAT( invit->dict, gi->dictName );
|
||||
invit->lang = gi->dictLang;
|
||||
invit->nPlayersT = gi->nPlayers;
|
||||
invit->nPlayersH = nPlayers;
|
||||
invit->forceChannel = forceChannel;
|
||||
|
||||
if ( addr_hasType( addr, COMMS_CONN_RELAY ) ) {
|
||||
types_addType( &invit->_conTypes, COMMS_CONN_RELAY );
|
||||
XP_STRCAT( invit->room, addr->u.ip_relay.invite );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static XP_U32
|
||||
gameID( const InviteInfo* invit )
|
||||
{
|
||||
XP_U32 gameID = invit->gameID;
|
||||
if ( 0 == gameID ) {
|
||||
sscanf( invit->inviteID, "%X", &gameID );
|
||||
}
|
||||
return gameID;
|
||||
}
|
||||
|
||||
void
|
||||
invit_setDevID( InviteInfo* invit, XP_U32 devID )
|
||||
{
|
||||
invit->devID = devID;
|
||||
}
|
||||
|
||||
void
|
||||
invit_saveToStream( const InviteInfo* invit, XWStreamCtxt* stream )
|
||||
{
|
||||
LOG_FUNC();
|
||||
stream_putU8( stream, invit->version );
|
||||
stream_putU16( stream, invit->_conTypes );
|
||||
stream_putU16( stream, invit->lang );
|
||||
stringToStream( stream, invit->dict );
|
||||
stringToStream( stream, invit->gameName );
|
||||
stream_putU8( stream, invit->nPlayersT );
|
||||
stream_putU8( stream, invit->nPlayersH );
|
||||
stream_putU32( stream, gameID( invit ) );
|
||||
stream_putU8( stream, invit->forceChannel );
|
||||
|
||||
if ( types_hasType( invit->_conTypes, COMMS_CONN_RELAY ) ) {
|
||||
stringToStream( stream, invit->room );
|
||||
XP_LOGF( "%s: wrote room %s", __func__, invit->room );
|
||||
stringToStream( stream, invit->inviteID );
|
||||
stream_putU32( stream, invit->devID );
|
||||
XP_LOGF( "%s: wrote devID %d", __func__, invit->devID );
|
||||
}
|
||||
if ( types_hasType( invit->_conTypes, COMMS_CONN_BT ) ) {
|
||||
stringToStream( stream, invit->btName );
|
||||
stringToStream( stream, invit->btAddress );
|
||||
}
|
||||
if ( types_hasType( invit->_conTypes, COMMS_CONN_SMS ) ) {
|
||||
stringToStream( stream, invit->phone );
|
||||
stream_putU8( stream, invit->isGSM );
|
||||
stream_putU8( stream, invit->osType );
|
||||
stream_putU32( stream, invit->osVers );
|
||||
}
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
invit_makeFromStream( InviteInfo* invit, XWStreamCtxt* stream )
|
||||
{
|
||||
LOG_FUNC();
|
||||
XP_MEMSET( invit, 0, sizeof(*invit) );
|
||||
invit->version = stream_getU8( stream );
|
||||
XP_Bool success = 0 == invit->version;
|
||||
if ( success ) {
|
||||
invit->_conTypes = stream_getU16( stream );
|
||||
invit->lang = stream_getU16( stream );
|
||||
stringFromStreamHere( stream, invit->dict, sizeof(invit->dict) );
|
||||
stringFromStreamHere( stream, invit->gameName, sizeof(invit->gameName) );
|
||||
invit->nPlayersT = stream_getU8( stream );
|
||||
invit->nPlayersH = stream_getU8( stream );
|
||||
invit->gameID = stream_getU32( stream );
|
||||
invit->forceChannel = stream_getU8( stream );
|
||||
|
||||
if ( types_hasType( invit->_conTypes, COMMS_CONN_RELAY ) ) {
|
||||
stringFromStreamHere( stream, invit->room, sizeof(invit->room) );
|
||||
XP_LOGF( "%s: read room %s", __func__, invit->room );
|
||||
stringFromStreamHere( stream, invit->inviteID, sizeof(invit->inviteID) );
|
||||
invit->devID = stream_getU32( stream );
|
||||
XP_LOGF( "%s: read devID %d", __func__, invit->devID );
|
||||
}
|
||||
if ( types_hasType( invit->_conTypes, COMMS_CONN_BT ) ) {
|
||||
stringFromStreamHere( stream, invit->btName, sizeof(invit->btName) );
|
||||
stringFromStreamHere( stream, invit->btAddress, sizeof(invit->btAddress) );
|
||||
}
|
||||
if ( types_hasType( invit->_conTypes, COMMS_CONN_SMS ) ) {
|
||||
stringFromStreamHere( stream, invit->phone, sizeof(invit->phone) );
|
||||
invit->isGSM = stream_getU8( stream );
|
||||
invit->osType= stream_getU8( stream );
|
||||
invit->osVers = stream_getU32( stream );
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
invit_makeAddrRec( const InviteInfo* invit, CommsAddrRec* addr )
|
||||
{
|
||||
XP_U32 state = 0;
|
||||
CommsConnType type;
|
||||
while ( types_iter( invit->_conTypes, &type, &state ) ) {
|
||||
addr_addType( addr, type );
|
||||
switch( type ) {
|
||||
case COMMS_CONN_RELAY:
|
||||
XP_STRCAT( addr->u.ip_relay.invite, invit->room );
|
||||
/* String relayName = XWPrefs.getDefaultRelayHost( context ); */
|
||||
/* int relayPort = XWPrefs.getDefaultRelayPort( context ); */
|
||||
/* result.setRelayParams( relayName, relayPort, room ); */
|
||||
break;
|
||||
case COMMS_CONN_BT:
|
||||
XP_STRCAT( addr->u.bt.btAddr.chars, invit->btAddress );
|
||||
XP_STRCAT( addr->u.bt.hostName, invit->btName );
|
||||
break;
|
||||
case COMMS_CONN_SMS:
|
||||
XP_STRCAT( addr->u.sms.phone, invit->phone );
|
||||
break;
|
||||
default:
|
||||
XP_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
75
xwords4/common/invit.h
Normal file
75
xwords4/common/invit.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||
/*
|
||||
* Copyright 2001 - 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef _INVIT_H_
|
||||
#define _INVIT_H_
|
||||
|
||||
// #include "comms.h"
|
||||
#include "xwstream.h"
|
||||
#include "game.h"
|
||||
|
||||
#define MAX_GAME_NAME_LEN 64
|
||||
#define MAX_DICT_NAME_LEN 32
|
||||
|
||||
typedef enum {OSType_NONE, OSType_LINUX, OSType_ANDROID, } XP_OSType;
|
||||
|
||||
typedef struct _InviteInfo {
|
||||
XP_U8 version; /* struct version for backward compatibility */
|
||||
XP_U16 _conTypes;
|
||||
|
||||
XP_UCHAR gameName[MAX_GAME_NAME_LEN];
|
||||
XP_UCHAR dict[MAX_DICT_NAME_LEN];
|
||||
XP_LangCode lang;
|
||||
XP_U8 forceChannel;
|
||||
XP_U8 nPlayersT;
|
||||
XP_U8 nPlayersH;
|
||||
|
||||
/* Relay */
|
||||
XP_UCHAR room[MAX_INVITE_LEN + 1];
|
||||
XP_U32 devID;
|
||||
|
||||
/* BT */
|
||||
XP_UCHAR btName[32];
|
||||
XP_UCHAR btAddress[32];
|
||||
|
||||
// SMS
|
||||
XP_UCHAR phone[32];
|
||||
XP_Bool isGSM;
|
||||
XP_OSType osType;
|
||||
XP_U32 osVers;
|
||||
|
||||
XP_U32 gameID;
|
||||
XP_UCHAR inviteID[32];
|
||||
} InviteInfo;
|
||||
|
||||
void
|
||||
invit_init( InviteInfo* invit, const CurGameInfo* gi, const CommsAddrRec* addr,
|
||||
XP_U16 nPlayers, XP_U16 forceChannel );
|
||||
|
||||
|
||||
XP_Bool invit_makeFromStream( InviteInfo* invit, XWStreamCtxt* stream );
|
||||
void invit_saveToStream( const InviteInfo* invit, XWStreamCtxt* stream );
|
||||
|
||||
void invit_makeAddrRec( const InviteInfo* invit, CommsAddrRec* addr );
|
||||
|
||||
void invit_setDevID( InviteInfo* invit, XP_U32 devID );
|
||||
|
||||
|
||||
#endif
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "comtypes.h"
|
||||
#include "nwgamest.h"
|
||||
#include "strutils.h"
|
||||
#include "LocalizedStrIncludes.h"
|
||||
|
|
|
@ -187,6 +187,7 @@ GTK_OBJS = \
|
|||
$(BUILD_PLAT_DIR)/gtkpasswdask.o \
|
||||
$(BUILD_PLAT_DIR)/gtknewgame.o \
|
||||
$(BUILD_PLAT_DIR)/gtkconnsdlg.o \
|
||||
$(BUILD_PLAT_DIR)/gtkinvit.o \
|
||||
$(BUILD_PLAT_DIR)/gtkutils.o \
|
||||
$(BUILD_PLAT_DIR)/gtkntilesask.o \
|
||||
$(BUILD_PLAT_DIR)/gtkaskdict.o \
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
|
||||
/*
|
||||
* Copyright 2000-2013 by Eric House (xwords@eehouse.org). All rights
|
||||
* Copyright 2000-2015 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -55,6 +55,7 @@
|
|||
#include "game.h"
|
||||
#include "movestak.h"
|
||||
#include "gtkask.h"
|
||||
#include "gtkinvit.h"
|
||||
#include "gtkaskm.h"
|
||||
#include "gtkchat.h"
|
||||
#include "gtknewgame.h"
|
||||
|
@ -969,15 +970,16 @@ static XP_Bool
|
|||
new_game_impl( GtkGameGlobals* globals, XP_Bool fireConnDlg )
|
||||
{
|
||||
XP_Bool success = XP_FALSE;
|
||||
CommonGlobals* cGlobals = &globals->cGlobals;
|
||||
CommsAddrRec addr;
|
||||
|
||||
if ( !!globals->cGlobals.game.comms ) {
|
||||
comms_getAddr( globals->cGlobals.game.comms, &addr );
|
||||
if ( !!cGlobals->game.comms ) {
|
||||
comms_getAddr( cGlobals->game.comms, &addr );
|
||||
} else {
|
||||
comms_getInitialAddr( &addr, RELAY_NAME_DEFAULT, RELAY_PORT_DEFAULT );
|
||||
}
|
||||
|
||||
CurGameInfo* gi = globals->cGlobals.gi;
|
||||
CurGameInfo* gi = cGlobals->gi;
|
||||
success = newGameDialog( globals, gi, &addr, XP_TRUE, fireConnDlg );
|
||||
if ( success ) {
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
|
@ -991,9 +993,9 @@ new_game_impl( GtkGameGlobals* globals, XP_Bool fireConnDlg )
|
|||
#endif
|
||||
};
|
||||
|
||||
if ( !game_reset( MEMPOOL &globals->cGlobals.game, gi,
|
||||
globals->cGlobals.util,
|
||||
&globals->cGlobals.cp, &procs ) ) {
|
||||
if ( !game_reset( MEMPOOL &cGlobals->game, gi,
|
||||
cGlobals->util,
|
||||
&cGlobals->cp, &procs ) ) {
|
||||
/* if ( NULL == globals->draw ) { */
|
||||
/* globals->draw = (GtkDrawCtx*)gtkDrawCtxtMake( globals->drawing_area, */
|
||||
/* globals ); */
|
||||
|
@ -1013,24 +1015,24 @@ new_game_impl( GtkGameGlobals* globals, XP_Bool fireConnDlg )
|
|||
}
|
||||
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
if ( !!globals->cGlobals.game.comms ) {
|
||||
comms_setAddr( globals->cGlobals.game.comms, &addr );
|
||||
if ( !!cGlobals->game.comms ) {
|
||||
comms_setAddr( cGlobals->game.comms, &addr );
|
||||
} else if ( gi->serverRole != SERVER_STANDALONE ) {
|
||||
XP_ASSERT(0);
|
||||
}
|
||||
|
||||
if ( isClient ) {
|
||||
XWStreamCtxt* stream =
|
||||
mem_stream_make( MEMPOOL globals->cGlobals.params->vtMgr,
|
||||
&globals->cGlobals, CHANNEL_NONE,
|
||||
mem_stream_make( MEMPOOL cGlobals->params->vtMgr,
|
||||
cGlobals, CHANNEL_NONE,
|
||||
sendOnClose );
|
||||
(void)server_initClientConnection( globals->cGlobals.game.server,
|
||||
(void)server_initClientConnection( cGlobals->game.server,
|
||||
stream );
|
||||
}
|
||||
#endif
|
||||
(void)server_do( globals->cGlobals.game.server ); /* assign tiles, etc. */
|
||||
board_invalAll( globals->cGlobals.game.board );
|
||||
board_draw( globals->cGlobals.game.board );
|
||||
(void)server_do( cGlobals->game.server ); /* assign tiles, etc. */
|
||||
board_invalAll( cGlobals->game.board );
|
||||
board_draw( cGlobals->game.board );
|
||||
}
|
||||
return success;
|
||||
} /* new_game_impl */
|
||||
|
@ -1559,63 +1561,108 @@ handle_commit_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
|||
static void
|
||||
handle_invite_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||
{
|
||||
const CurGameInfo* gi = globals->cGlobals.gi;
|
||||
CommonGlobals* cGlobals = &globals->cGlobals;
|
||||
const CurGameInfo* gi = cGlobals->gi;
|
||||
|
||||
gchar* countStr;
|
||||
gchar* phone = NULL;
|
||||
gchar* portstr = NULL;
|
||||
gchar* forceChannelStr;
|
||||
AskMInfo infos[] = {
|
||||
{ "Number of players", &countStr },
|
||||
{ "Remote phone#", &phone },
|
||||
{ "Remote port", &portstr },
|
||||
{ "Force channel", &forceChannelStr },
|
||||
};
|
||||
/* gchar* countStr; */
|
||||
/* gchar* phone = NULL; */
|
||||
/* gchar* portstr = NULL; */
|
||||
/* gchar* forceChannelStr; */
|
||||
/* AskMInfo infos[] = { */
|
||||
/* { "Number of players", &countStr }, */
|
||||
/* { "Remote phone#", &phone }, */
|
||||
/* { "Remote port", &portstr }, */
|
||||
/* { "Force channel", &forceChannelStr }, */
|
||||
/* }; */
|
||||
|
||||
XP_U16 nMissing = server_getPendingRegs( globals->cGlobals.game.server );
|
||||
gchar buf[64];
|
||||
sprintf( buf, "%d", nMissing );
|
||||
countStr = buf;
|
||||
gchar forceChannelBuf[64];
|
||||
sprintf( forceChannelBuf, "%d", 1 );
|
||||
forceChannelStr = forceChannelBuf;
|
||||
/* gchar buf[64]; */
|
||||
/* sprintf( buf, "%d", nMissing ); */
|
||||
/* countStr = buf; */
|
||||
/* gchar forceChannelBuf[64]; */
|
||||
/* sprintf( forceChannelBuf, "%d", 1 ); */
|
||||
/* forceChannelStr = forceChannelBuf; */
|
||||
|
||||
while ( gtkaskm( "Invite how many and how?", infos, VSIZE(infos) ) ) {
|
||||
int nPlayers = atoi( countStr );
|
||||
if ( 0 >= nPlayers || nPlayers > nMissing ) {
|
||||
gchar buf[128];
|
||||
sprintf( buf, "Please invite between 1 and %d players (inclusive).",
|
||||
nMissing );
|
||||
gtktell( globals->window, buf );
|
||||
break;
|
||||
}
|
||||
|
||||
int port = atoi( portstr );
|
||||
if ( 0 == port ) {
|
||||
gtktell( globals->window, "Port must be a number and not 0." );
|
||||
break;
|
||||
}
|
||||
int forceChannel = atoi( forceChannelStr );
|
||||
if ( 1 > forceChannel || 4 <= forceChannel ) {
|
||||
gtktell( globals->window, "Channel must be between 1 and the number of client devices." );
|
||||
break;
|
||||
}
|
||||
CommsAddrRec inviteAddr = {0};
|
||||
gint nPlayers = nMissing;
|
||||
XP_U32 devID;
|
||||
XP_Bool confirmed = gtkInviteDlg( globals, &inviteAddr, &nPlayers, &devID );
|
||||
XP_LOGF( "%s: inviteDlg => %d", __func__, confirmed );
|
||||
|
||||
if ( confirmed ) {
|
||||
gchar gameName[64];
|
||||
snprintf( gameName, VSIZE(gameName), "Game %d", gi->gameID );
|
||||
|
||||
CommsAddrRec addr;
|
||||
CommsCtxt* comms = globals->cGlobals.game.comms;
|
||||
CommsCtxt* comms = cGlobals->game.comms;
|
||||
XP_ASSERT( comms );
|
||||
comms_getAddr( comms, &addr );
|
||||
|
||||
linux_sms_invite( globals->cGlobals.params, gi, &addr, gameName,
|
||||
nPlayers, forceChannel, phone, port );
|
||||
break;
|
||||
}
|
||||
for ( int ii = 0; ii < VSIZE(infos); ++ii ) {
|
||||
g_free( *infos[ii].result );
|
||||
gint forceChannel = 0; /* PENDING */
|
||||
|
||||
InviteInfo invit = {0};
|
||||
invit_init( &invit, gi, &addr, nPlayers, forceChannel );
|
||||
invit_setDevID( &invit, linux_getDevIDRelay( cGlobals->params ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(cGlobals->util->mpool)
|
||||
cGlobals->params->vtMgr,
|
||||
NULL, CHANNEL_NONE, NULL );
|
||||
invit_saveToStream( &invit, stream );
|
||||
InviteInfo tmp;
|
||||
invit_makeFromStream( &tmp, stream );
|
||||
stream_destroy( stream );
|
||||
XP_ASSERT( 0 == memcmp( &invit, &tmp, sizeof(invit) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( addr_hasType( &inviteAddr, COMMS_CONN_SMS ) ) {
|
||||
linux_sms_invite( cGlobals->params, gi, &addr, gameName,
|
||||
nPlayers, forceChannel,
|
||||
inviteAddr.u.sms.phone, inviteAddr.u.sms.port );
|
||||
}
|
||||
if ( addr_hasType( &addr, COMMS_CONN_RELAY ) ) {
|
||||
relaycon_invite( cGlobals->params, devID, &invit );
|
||||
}
|
||||
}
|
||||
|
||||
/* while ( gtkaskm( "Invite how many and how?", infos, VSIZE(infos) ) ) { */
|
||||
/* int nPlayers = atoi( countStr ); */
|
||||
/* if ( 0 >= nPlayers || nPlayers > nMissing ) { */
|
||||
/* gchar buf[128]; */
|
||||
/* sprintf( buf, "Please invite between 1 and %d players (inclusive).", */
|
||||
/* nMissing ); */
|
||||
/* gtktell( globals->window, buf ); */
|
||||
/* break; */
|
||||
/* } */
|
||||
|
||||
/* int port = atoi( portstr ); */
|
||||
/* if ( 0 == port ) { */
|
||||
/* gtktell( globals->window, "Port must be a number and not 0." ); */
|
||||
/* break; */
|
||||
/* } */
|
||||
/* int forceChannel = atoi( forceChannelStr ); */
|
||||
/* if ( 1 > forceChannel || 4 <= forceChannel ) { */
|
||||
/* gtktell( globals->window, "Channel must be between 1 and the number of client devices." ); */
|
||||
/* break; */
|
||||
/* } */
|
||||
|
||||
/* gchar gameName[64]; */
|
||||
/* snprintf( gameName, VSIZE(gameName), "Game %d", gi->gameID ); */
|
||||
|
||||
/* CommsAddrRec addr; */
|
||||
/* CommsCtxt* comms = globals->cGlobals.game.comms; */
|
||||
/* XP_ASSERT( comms ); */
|
||||
/* comms_getAddr( comms, &addr ); */
|
||||
|
||||
/* linux_sms_invite( globals->cGlobals.params, gi, &addr, gameName, */
|
||||
/* nPlayers, forceChannel, phone, port ); */
|
||||
/* break; */
|
||||
/* } */
|
||||
/* for ( int ii = 0; ii < VSIZE(infos); ++ii ) { */
|
||||
/* g_free( *infos[ii].result ); */
|
||||
/* } */
|
||||
} /* handle_invite_button */
|
||||
|
||||
static void
|
||||
|
|
378
xwords4/linux/gtkinvit.c
Normal file
378
xwords4/linux/gtkinvit.c
Normal file
|
@ -0,0 +1,378 @@
|
|||
/* -*- compile-command: "make MEMDEBUG=TRUE -j5"; -*- */
|
||||
/*
|
||||
* Copyright 2001-2014 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.
|
||||
*/
|
||||
#ifdef PLATFORM_GTK
|
||||
|
||||
#include "gtkinvit.h"
|
||||
#include "gtkutils.h"
|
||||
#include "linuxbt.h"
|
||||
#include "comtypes.h"
|
||||
|
||||
typedef struct _PageData {
|
||||
CommsConnType pageType;
|
||||
gboolean doUse;
|
||||
const char* labelText;
|
||||
GtkWidget* label;
|
||||
const char* okButtonTxt;
|
||||
} PageData;
|
||||
|
||||
typedef struct _GtkInviteState {
|
||||
GtkGameGlobals* globals;
|
||||
CommsAddrRec* addr;
|
||||
gint* nPlayersP;
|
||||
XP_U32* devIDP;
|
||||
gint maxPlayers;
|
||||
XP_UCHAR devIDBuf[32];
|
||||
|
||||
GtkWidget* nPlayersCombo;
|
||||
/* relay */
|
||||
GtkWidget* devID;
|
||||
/* BT */
|
||||
GtkWidget* bthost;
|
||||
/* SMS */
|
||||
GtkWidget* smsphone;
|
||||
GtkWidget* smsport;
|
||||
|
||||
GtkWidget* bgScanButton;
|
||||
GtkWidget* okButton;
|
||||
|
||||
GtkWidget* notebook;
|
||||
guint curPage;
|
||||
|
||||
XP_U16 nTypes;
|
||||
PageData pageData[COMMS_CONN_NTYPES];
|
||||
|
||||
gboolean cancelled;
|
||||
} GtkInviteState;
|
||||
|
||||
/* Make it static so we remember user's late entry */
|
||||
|
||||
static gint
|
||||
conTypeToPageNum( const GtkInviteState* state, CommsConnType conType )
|
||||
{
|
||||
gint pageNum = 0; /* default */
|
||||
int ii;
|
||||
for ( ii = 0; ; ++ii ) {
|
||||
const PageData* pageData = &state->pageData[ii];
|
||||
CommsConnType thisType = pageData->pageType;
|
||||
if ( thisType == COMMS_CONN_NONE || thisType == conType ) {
|
||||
pageNum = ii;
|
||||
break;
|
||||
}
|
||||
XP_ASSERT( ii < VSIZE(state->pageData) );
|
||||
}
|
||||
return pageNum;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_ok( GtkWidget* XP_UNUSED(widget), gpointer closure )
|
||||
{
|
||||
GtkInviteState* state = (GtkInviteState*)closure;
|
||||
const gchar* txt;
|
||||
guint curPage = state->curPage;
|
||||
PageData* data = &state->pageData[curPage];
|
||||
CommsConnType conType = data->pageType;
|
||||
|
||||
addr_addType( state->addr, conType );
|
||||
switch ( conType ) {
|
||||
#ifdef XWFEATURE_RELAY
|
||||
case COMMS_CONN_RELAY:
|
||||
txt = gtk_entry_get_text( GTK_ENTRY(state->devID) );
|
||||
*(state->devIDP) = atoi( txt );
|
||||
break;
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
case COMMS_CONN_BT:
|
||||
txt = gtk_entry_get_text( GTK_ENTRY(state->bthost) );
|
||||
XP_STRNCPY( state->addr->u.bt.hostName, txt,
|
||||
sizeof(state->addr->u.bt.hostName) );
|
||||
break;
|
||||
#endif
|
||||
case COMMS_CONN_SMS:
|
||||
txt = gtk_entry_get_text( GTK_ENTRY(state->smsphone) );
|
||||
XP_STRNCPY( state->addr->u.sms.phone, txt,
|
||||
sizeof(state->addr->u.sms.phone) );
|
||||
txt = gtk_entry_get_text( GTK_ENTRY(state->smsport) );
|
||||
state->addr->u.sms.port = atoi( txt );
|
||||
break;
|
||||
default:
|
||||
XP_ASSERT( 0 ); /* keep compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* get the number to invite */
|
||||
gchar* num =
|
||||
gtk_combo_box_get_active_text( GTK_COMBO_BOX(state->nPlayersCombo) );
|
||||
*(state->nPlayersP) = atoi( num );
|
||||
XP_LOGF( "num players: %d", *(state->nPlayersP) );
|
||||
|
||||
state->cancelled = XP_FALSE;
|
||||
gtk_main_quit();
|
||||
} /* handle_ok */
|
||||
|
||||
static void
|
||||
handle_scan( GtkWidget* XP_UNUSED(widget), gpointer closure )
|
||||
{
|
||||
GtkInviteState* state = (GtkInviteState*)closure;
|
||||
XP_USE(state);
|
||||
LOG_FUNC();
|
||||
|
||||
GSList* devNames = linux_bt_scan();
|
||||
if ( !devNames ) {
|
||||
XP_LOGF( "%s: got nothing", __func__ );
|
||||
} else {
|
||||
GSList* iter;
|
||||
for ( iter = devNames; !!iter; iter = iter->next ) {
|
||||
#ifdef DEBUG
|
||||
gchar* name = iter->data;
|
||||
XP_LOGF( "%s: got %s", __func__, name );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_cancel( GtkWidget* XP_UNUSED(widget), void* closure )
|
||||
{
|
||||
GtkInviteState* state = (GtkInviteState*)closure;
|
||||
state->cancelled = XP_TRUE;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Invite: _____
|
||||
* Relay: _____
|
||||
* Port: _____
|
||||
* Cancel OK
|
||||
*/
|
||||
|
||||
static GtkWidget*
|
||||
makeRelayPage( GtkInviteState* state, PageData* data )
|
||||
{
|
||||
data->okButtonTxt = "Invite via Relay";
|
||||
|
||||
GtkWidget* vbox = gtk_vbox_new( FALSE, 0 );
|
||||
GtkWidget* hbox;
|
||||
|
||||
hbox = makeLabeledField( "Invitee DeviceID", &state->devID, NULL );
|
||||
XP_Bool hasRelay = addr_hasType( state->addr, COMMS_CONN_RELAY );
|
||||
if ( hasRelay ) {
|
||||
gtk_entry_set_text( GTK_ENTRY(state->devID), state->devIDBuf );
|
||||
}
|
||||
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
|
||||
|
||||
gtk_widget_show( vbox );
|
||||
|
||||
return vbox;
|
||||
} /* makeRelayPage */
|
||||
|
||||
static GtkWidget*
|
||||
makeBTPage( GtkInviteState* state, PageData* data )
|
||||
{
|
||||
data->okButtonTxt = "Invite via Bluetooth";
|
||||
|
||||
GtkWidget* vbox = gtk_vbox_new( FALSE, 0 );
|
||||
|
||||
GtkWidget* hbox = makeLabeledField( "Invitee device", &state->bthost, NULL );
|
||||
if ( addr_hasType( state->addr, data->pageType ) ) {
|
||||
gtk_entry_set_text( GTK_ENTRY(state->bthost), state->addr->u.bt.hostName );
|
||||
}
|
||||
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
|
||||
|
||||
state->bgScanButton = makeButton( "Scan", GTK_SIGNAL_FUNC(handle_scan),
|
||||
state );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), state->bgScanButton, FALSE, TRUE, 0 );
|
||||
|
||||
gtk_widget_show( vbox );
|
||||
|
||||
return vbox;
|
||||
} /* makeBTPage */
|
||||
|
||||
/* #ifdef XWFEATURE_DIRECTIP */
|
||||
/* static GtkWidget* */
|
||||
/* makeIPDirPage( GtkInviteState* state, PageData* data ) */
|
||||
/* { */
|
||||
/* GtkWidget* vbox = boxWithUseCheck( state, data ); */
|
||||
|
||||
/* /\* XP_UCHAR hostName_ip[MAX_HOSTNAME_LEN + 1]; *\/ */
|
||||
/* /\* XP_U16 port_ip; *\/ */
|
||||
|
||||
/* XP_Bool hasIP = addr_hasType( state->addr, data->pageType ); */
|
||||
/* const gchar* name = hasIP ? */
|
||||
/* state->addr->u.ip.hostName_ip : state->globals->cGlobals.params->connInfo.ip.hostName; */
|
||||
/* GtkWidget* hbox = makeLabeledField( "Hostname", &state->iphost, name ); */
|
||||
/* gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 ); */
|
||||
|
||||
/* hbox = makeLabeledField( "Relay port", &state->ipport, NULL ); */
|
||||
/* if ( hasIP ) { */
|
||||
/* char buf[16]; */
|
||||
/* snprintf( buf, sizeof(buf), "%d", state->addr->u.ip.port_ip ); */
|
||||
/* gtk_entry_set_text( GTK_ENTRY(state->ipport), buf ); */
|
||||
/* } */
|
||||
/* gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 ); */
|
||||
|
||||
/* return vbox; */
|
||||
/* } */
|
||||
/* #endif */
|
||||
|
||||
static GtkWidget*
|
||||
makeSMSPage( GtkInviteState* state, PageData* data )
|
||||
{
|
||||
data->okButtonTxt = "Invite via SMS";
|
||||
|
||||
GtkWidget* vbox = gtk_vbox_new( FALSE, 0 );
|
||||
XP_Bool hasSMS = addr_hasType( state->addr, data->pageType );
|
||||
const gchar* phone = hasSMS ?
|
||||
state->addr->u.sms.phone : state->globals->cGlobals.params->connInfo.sms.phone;
|
||||
GtkWidget* hbox = makeLabeledField( "Invitee phone", &state->smsphone, phone );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
|
||||
|
||||
int portVal = hasSMS ? state->addr->u.sms.port
|
||||
: state->globals->cGlobals.params->connInfo.sms.port;
|
||||
gchar port[32];
|
||||
snprintf( port, sizeof(port), "%d", portVal );
|
||||
hbox = makeLabeledField( "Invitee port", &state->smsport, port );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
|
||||
|
||||
gtk_widget_show( vbox );
|
||||
|
||||
return vbox;
|
||||
} /* makeBTPage */
|
||||
|
||||
static PageData*
|
||||
getNextData( GtkInviteState* state, CommsConnType typ, gchar* label )
|
||||
{
|
||||
PageData* result = &state->pageData[state->nTypes++];
|
||||
result->pageType = typ;
|
||||
result->label = gtk_label_new( label );
|
||||
result->labelText = label;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
onPageChanged( GtkNotebook* XP_UNUSED(notebook), gpointer XP_UNUSED(arg1),
|
||||
guint arg2, gpointer data )
|
||||
{
|
||||
GtkInviteState* state = (GtkInviteState*)data;
|
||||
state->curPage = arg2;
|
||||
PageData* pageData = &state->pageData[arg2];
|
||||
gtk_button_set_label(GTK_BUTTON(state->okButton), pageData->okButtonTxt );
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr, gint* nPlayers,
|
||||
XP_U32* devIDP )
|
||||
{
|
||||
GtkInviteState state;
|
||||
XP_MEMSET( &state, 0, sizeof(state) );
|
||||
|
||||
state.globals = globals;
|
||||
state.addr = addr;
|
||||
state.nPlayersP = nPlayers;
|
||||
state.maxPlayers = *nPlayers;
|
||||
state.devIDP = devIDP;
|
||||
|
||||
GtkWidget* dialog;
|
||||
GtkWidget* hbox;
|
||||
GtkWidget* vbox = gtk_vbox_new( FALSE, 0 );
|
||||
|
||||
hbox = gtk_hbox_new( FALSE, 0 );
|
||||
GtkWidget* label = gtk_label_new( "Invite how many:" );
|
||||
gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, TRUE, 0 );
|
||||
|
||||
state.nPlayersCombo = gtk_combo_box_new_text();
|
||||
for ( int ii = 1; ii <= state.maxPlayers; ++ii ) {
|
||||
gchar buf[8];
|
||||
sprintf( buf, "%d", ii );
|
||||
gtk_combo_box_append_text( GTK_COMBO_BOX(state.nPlayersCombo), buf );
|
||||
}
|
||||
gtk_combo_box_set_active( GTK_COMBO_BOX(state.nPlayersCombo), 0 );
|
||||
gtk_box_pack_start( GTK_BOX(hbox), state.nPlayersCombo, FALSE, TRUE, 0 );
|
||||
gtk_widget_show( state.nPlayersCombo );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
|
||||
|
||||
state.notebook = gtk_notebook_new();
|
||||
g_signal_connect( GTK_OBJECT(state.notebook), "switch-page",
|
||||
G_CALLBACK(onPageChanged), &state );
|
||||
|
||||
PageData* data;
|
||||
|
||||
#ifdef XWFEATURE_RELAY
|
||||
data = getNextData( &state, COMMS_CONN_RELAY, "Relay" );
|
||||
(void)gtk_notebook_append_page( GTK_NOTEBOOK(state.notebook),
|
||||
makeRelayPage( &state, data ),
|
||||
data->label );
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
data = getNextData( &state, COMMS_CONN_BT, "Bluetooth" );
|
||||
(void)gtk_notebook_append_page( GTK_NOTEBOOK(state.notebook),
|
||||
makeBTPage( &state, data ),
|
||||
data->label );
|
||||
#endif
|
||||
/* #ifdef XWFEATURE_DIRECTIP */
|
||||
/* data = getNextData( &state, COMMS_CONN_IP_DIRECT, "Direct" ); */
|
||||
/* (void)gtk_notebook_append_page( GTK_NOTEBOOK(state.notebook), */
|
||||
/* makeIPDirPage(&state, data), */
|
||||
/* data->label ); */
|
||||
/* #endif */
|
||||
#ifdef XWFEATURE_SMS
|
||||
data = getNextData( &state, COMMS_CONN_SMS, "SMS" );
|
||||
(void)gtk_notebook_append_page( GTK_NOTEBOOK(state.notebook),
|
||||
makeSMSPage( &state, data ),
|
||||
data->label );
|
||||
#endif
|
||||
|
||||
gtk_box_pack_start( GTK_BOX(vbox), state.notebook, FALSE, TRUE, 0 );
|
||||
|
||||
/* Set page to the first we actually have */
|
||||
XP_U32 st = 0;
|
||||
CommsConnType firstType;
|
||||
if ( addr_iter( addr, &firstType, &st ) ) {
|
||||
gint pageNo = conTypeToPageNum( &state, firstType );
|
||||
gtk_notebook_set_current_page( GTK_NOTEBOOK(state.notebook), pageNo );
|
||||
}
|
||||
|
||||
gtk_widget_show( state.notebook );
|
||||
|
||||
/* buttons at the bottom */
|
||||
hbox = gtk_hbox_new( FALSE, 0 );
|
||||
state.okButton = makeButton( state.pageData[0].okButtonTxt,
|
||||
GTK_SIGNAL_FUNC(handle_ok), &state );
|
||||
gtk_box_pack_start( GTK_BOX(hbox), state.okButton, FALSE, TRUE, 0 );
|
||||
gtk_box_pack_start( GTK_BOX(hbox),
|
||||
makeButton( "Cancel",
|
||||
GTK_SIGNAL_FUNC(handle_cancel),
|
||||
&state ),
|
||||
FALSE, TRUE, 0 );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
|
||||
|
||||
gtk_widget_show( vbox );
|
||||
|
||||
dialog = gtk_dialog_new();
|
||||
gtk_window_set_modal( GTK_WINDOW( dialog ), TRUE );
|
||||
gtk_container_add( GTK_CONTAINER( GTK_DIALOG(dialog)->action_area), vbox );
|
||||
|
||||
|
||||
gtk_widget_show_all( dialog );
|
||||
gtk_main();
|
||||
gtk_widget_destroy( dialog );
|
||||
|
||||
return !state.cancelled;
|
||||
} /* gtkInviteDlg */
|
||||
#endif
|
31
xwords4/linux/gtkinvit.h
Normal file
31
xwords4/linux/gtkinvit.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* -*- compile-command: "make MEMDEBUG=TRUE -j5"; -*- */
|
||||
/*
|
||||
* Copyright 2001-2014 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.
|
||||
*/
|
||||
#ifdef PLATFORM_GTK
|
||||
|
||||
#include "xptypes.h"
|
||||
#include "gtkboard.h"
|
||||
|
||||
/* return true if not cancelled */
|
||||
XP_Bool gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr,
|
||||
/*inout*/ gint* nPlayers, XP_U32* devID );
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -336,16 +336,12 @@ addButton( gchar* label, GtkWidget* parent, GCallback proc, void* closure )
|
|||
return button;
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
makeGamesWindow( GtkAppGlobals* apg )
|
||||
static void
|
||||
setWindowTitle( GtkAppGlobals* apg )
|
||||
{
|
||||
GtkWidget* window;
|
||||
GtkWidget* window = apg->window;
|
||||
LaunchParams* params = apg->params;
|
||||
|
||||
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
|
||||
g_signal_connect( G_OBJECT(window), "destroy",
|
||||
G_CALLBACK(handle_destroy), apg );
|
||||
|
||||
gchar title[128] = {0};
|
||||
if ( !!params->dbName ) {
|
||||
strcat( title, params->dbName );
|
||||
|
@ -354,8 +350,26 @@ makeGamesWindow( GtkAppGlobals* apg )
|
|||
int len = strlen( title );
|
||||
snprintf( &title[len], VSIZE(title) - len, " (phone: %s, port: %d)",
|
||||
params->connInfo.sms.phone, params->connInfo.sms.port );
|
||||
#endif
|
||||
#ifdef XWFEATURE_RELAY
|
||||
XP_U32 relayID = linux_getDevIDRelay( params );
|
||||
len = strlen( title );
|
||||
snprintf( &title[len], VSIZE(title) - len, " (relayid: %d)", relayID );
|
||||
#endif
|
||||
gtk_window_set_title( GTK_WINDOW(window), title );
|
||||
}
|
||||
|
||||
static void
|
||||
makeGamesWindow( GtkAppGlobals* apg )
|
||||
{
|
||||
GtkWidget* window;
|
||||
LaunchParams* params = apg->params;
|
||||
|
||||
apg->window = window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
|
||||
g_signal_connect( G_OBJECT(window), "destroy",
|
||||
G_CALLBACK(handle_destroy), apg );
|
||||
|
||||
setWindowTitle( apg );
|
||||
|
||||
GtkWidget* vbox = gtk_vbox_new( FALSE, 0 );
|
||||
gtk_container_add( GTK_CONTAINER(window), vbox );
|
||||
|
@ -388,7 +402,6 @@ makeGamesWindow( GtkAppGlobals* apg )
|
|||
updateButtons( apg );
|
||||
|
||||
gtk_widget_show( window );
|
||||
return window;
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
|
@ -459,6 +472,38 @@ gtkSocketAdded( void* closure, int newSock, GIOFunc proc )
|
|||
LOG_RETURN_VOID();
|
||||
} /* gtk_socket_changed */
|
||||
|
||||
|
||||
static void
|
||||
relayInviteReceived( void* closure, InviteInfo* invite )
|
||||
{
|
||||
GtkAppGlobals* apg = (GtkAppGlobals*)closure;
|
||||
LaunchParams* params = apg->params;
|
||||
|
||||
CurGameInfo gi = {0};
|
||||
gi_copy( MPPARM(params->mpool) &gi, ¶ms->pgi );
|
||||
|
||||
gi_setNPlayers( &gi, invite->nPlayersT, invite->nPlayersH );
|
||||
gi.gameID = invite->gameID;
|
||||
gi.dictLang = invite->lang;
|
||||
gi.forceChannel = invite->forceChannel;
|
||||
replaceStringIfDifferent( params->mpool, &gi.dictName, invite->dict );
|
||||
|
||||
GtkGameGlobals* globals = malloc( sizeof(*globals) );
|
||||
params->needsNewGame = XP_FALSE;
|
||||
initGlobals( globals, params, &gi );
|
||||
|
||||
invit_makeAddrRec( invite, &globals->cGlobals.addr );
|
||||
// globals->cGlobals.addr = *returnAddr;
|
||||
|
||||
GtkWidget* gameWindow = globals->window;
|
||||
globals->cGlobals.pDb = apg->params->pDb;
|
||||
globals->cGlobals.selRow = -1;
|
||||
recordOpened( apg, globals );
|
||||
gtk_widget_show( gameWindow );
|
||||
|
||||
gi_disposePlayerInfo( MPPARM(params->mpool) &gi );
|
||||
}
|
||||
|
||||
static void
|
||||
gtkGotBuf( void* closure, const CommsAddrRec* from,
|
||||
const XP_U8* buf, XP_U16 len )
|
||||
|
@ -570,6 +615,8 @@ gtkDevIDReceived( void* closure, const XP_UCHAR* devID, XP_U16 maxInterval )
|
|||
XP_LOGF( "%s(devID=%s)", __func__, devID );
|
||||
db_store( params->pDb, KEY_RDEVID, devID );
|
||||
(void)g_timeout_add_seconds( maxInterval, keepalive_timer, apg );
|
||||
|
||||
setWindowTitle( apg );
|
||||
} else {
|
||||
XP_LOGF( "%s: bad relayid", __func__ );
|
||||
db_remove( params->pDb, KEY_RDEVID );
|
||||
|
@ -647,6 +694,7 @@ gtkmain( LaunchParams* params )
|
|||
.devIDReceived = gtkDevIDReceived,
|
||||
.msgErrorMsg = gtkErrorMsgRcvd,
|
||||
.socketAdded = gtkSocketAdded,
|
||||
.inviteReceived = relayInviteReceived,
|
||||
};
|
||||
|
||||
relaycon_init( params, &procs, &apg,
|
||||
|
@ -685,7 +733,7 @@ gtkmain( LaunchParams* params )
|
|||
|
||||
|
||||
#endif
|
||||
apg.window = makeGamesWindow( &apg );
|
||||
makeGamesWindow( &apg );
|
||||
} else if ( !!params->dbFileName ) {
|
||||
apg.window = openDBFile( &apg );
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "gtkutils.h"
|
||||
|
||||
GtkWidget*
|
||||
makeButton( char* text, GCallback func, gpointer data )
|
||||
makeButton( const char* text, GCallback func, gpointer data )
|
||||
{
|
||||
GtkWidget* button = gtk_button_new_with_label( text );
|
||||
g_signal_connect( GTK_OBJECT(button), "clicked", func, data );
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include "gtkboard.h"
|
||||
|
||||
GtkWidget* makeButton( char* text, GCallback func, gpointer data );
|
||||
GtkWidget* makeButton( const char* text, GCallback func, gpointer data );
|
||||
GtkWidget* makeLabeledField( const char* labelText, GtkWidget** field,
|
||||
const gchar* initialVal );
|
||||
|
||||
|
|
|
@ -895,6 +895,19 @@ linShiftFocus( CommonGlobals* cGlobals, XP_Key key, const BoardObjectType* order
|
|||
} /* linShiftFocus */
|
||||
#endif
|
||||
|
||||
const XP_U32
|
||||
linux_getDevIDRelay( LaunchParams* params )
|
||||
{
|
||||
XP_U32 result = 0;
|
||||
gchar buf[32];
|
||||
if ( db_fetch( params->pDb, KEY_RDEVID, buf, sizeof(buf) ) ) {
|
||||
sscanf( buf, "%X", &result );
|
||||
XP_LOGF( "%s(): %s => %x", __func__, buf, result );
|
||||
}
|
||||
LOG_RETURNF( "%d", result );
|
||||
return result;
|
||||
}
|
||||
|
||||
const XP_UCHAR*
|
||||
linux_getDevID( LaunchParams* params, DevIDType* typ )
|
||||
{
|
||||
|
@ -2088,7 +2101,7 @@ main( int argc, char** argv )
|
|||
mainParams.showRobotScores = XP_FALSE;
|
||||
mainParams.useMmap = XP_TRUE;
|
||||
mainParams.useUdp = true;
|
||||
mainParams.dbName = "xwgames.sql";
|
||||
mainParams.dbName = "xwgames.sqldb";
|
||||
|
||||
char* envDictPath = getenv( "XW_DICTDIR" );
|
||||
XP_LOGF( "%s: envDictPath=%s", __func__, envDictPath );
|
||||
|
|
|
@ -106,6 +106,7 @@ void gameGotBuf( CommonGlobals* globals, XP_Bool haveDraw,
|
|||
const XP_U8* buf, XP_U16 len, const CommsAddrRec* from );
|
||||
gboolean app_socket_proc( GIOChannel* source, GIOCondition condition,
|
||||
gpointer data );
|
||||
const XP_U32 linux_getDevIDRelay( LaunchParams* params );
|
||||
const XP_UCHAR* linux_getDevID( LaunchParams* params, DevIDType* typ );
|
||||
void linux_doInitialReg( LaunchParams* params, XP_Bool idIsNew );
|
||||
XP_Bool linux_setupDevidParams( LaunchParams* params );
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "relaycon.h"
|
||||
#include "linuxmain.h"
|
||||
#include "comtypes.h"
|
||||
|
||||
typedef struct _RelayConStorage {
|
||||
|
@ -31,6 +32,7 @@ typedef struct _RelayConStorage {
|
|||
struct sockaddr_in saddr;
|
||||
uint32_t nextID;
|
||||
XWPDevProto proto;
|
||||
LaunchParams* params;
|
||||
} RelayConStorage;
|
||||
|
||||
typedef struct _MsgHeader {
|
||||
|
@ -53,6 +55,7 @@ static int writeHeader( RelayConStorage* storage, XP_U8* dest, XWRelayReg cmd );
|
|||
static bool readHeader( const XP_U8** buf, MsgHeader* header );
|
||||
static size_t writeDevID( XP_U8* buf, size_t len, const XP_UCHAR* str );
|
||||
static size_t writeShort( XP_U8* buf, size_t len, XP_U16 shrt );
|
||||
static size_t writeLong( XP_U8* buf, size_t len, XP_U32 lng );
|
||||
static size_t writeVLI( XP_U8* out, uint32_t nn );
|
||||
static size_t un2vli( int nn, uint8_t* buf );
|
||||
static bool vli2un( const uint8_t** inp, uint32_t* outp );
|
||||
|
@ -75,6 +78,8 @@ relaycon_init( LaunchParams* params, const RelayConnProcs* procs,
|
|||
storage->saddr.sin_addr.s_addr = htonl( hostNameToIP(host) );
|
||||
storage->saddr.sin_port = htons(port);
|
||||
|
||||
storage->params = params;
|
||||
|
||||
storage->proto = XWPDEV_PROTO_VERSION_1;
|
||||
}
|
||||
|
||||
|
@ -107,6 +112,34 @@ relaycon_reg( LaunchParams* params, const XP_UCHAR* rDevID,
|
|||
sendIt( storage, tmpbuf, indx );
|
||||
}
|
||||
|
||||
void
|
||||
relaycon_invite( LaunchParams* params, XP_U32 dest, InviteInfo* invit )
|
||||
{
|
||||
XP_U8 tmpbuf[256];
|
||||
int indx = 0;
|
||||
|
||||
RelayConStorage* storage = getStorage( params );
|
||||
indx += writeHeader( storage, tmpbuf, XWPDEV_INVITE );
|
||||
XP_U32 me = linux_getDevIDRelay( params );
|
||||
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, me );
|
||||
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, dest );
|
||||
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(params->mpool)
|
||||
params->vtMgr, params,
|
||||
CHANNEL_NONE, NULL );
|
||||
invit_saveToStream( invit, stream );
|
||||
XP_U16 len = stream_getSize( stream );
|
||||
indx += writeShort( &tmpbuf[indx], sizeof(tmpbuf) - indx, len );
|
||||
XP_ASSERT( indx + len < sizeof(tmpbuf) );
|
||||
const XP_U8* ptr = stream_getPtr( stream );
|
||||
XP_MEMCPY( &tmpbuf[indx], ptr, len );
|
||||
indx += len;
|
||||
stream_destroy( stream );
|
||||
|
||||
sendIt( storage, tmpbuf, indx );
|
||||
LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
XP_S16
|
||||
relaycon_send( LaunchParams* params, const XP_U8* buf, XP_U16 buflen,
|
||||
XP_U32 gameToken, const CommsAddrRec* XP_UNUSED(addrRec) )
|
||||
|
@ -295,6 +328,27 @@ relaycon_receive( GIOChannel* source, GIOCondition XP_UNUSED_DBG(condition), gpo
|
|||
XP_LOGF( "%s: got message: %s", __func__, buf );
|
||||
break;
|
||||
}
|
||||
case XWPDEV_GOTINVITE: {
|
||||
XP_LOGF( "%s(): got XWPDEV_GOTINVITE", __func__ );
|
||||
XP_U32 sender = getNetLong( &ptr );
|
||||
XP_U16 len = getNetShort( &ptr );
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(storage->params->mpool)
|
||||
storage->params->vtMgr, storage,
|
||||
CHANNEL_NONE, NULL );
|
||||
stream_putBytes( stream, ptr, len );
|
||||
InviteInfo invit;
|
||||
XP_Bool success = invit_makeFromStream( &invit, stream );
|
||||
XP_LOGF( "sender: %d; invit.devID: %d", sender, invit.devID );
|
||||
XP_ASSERT( sender == invit.devID );
|
||||
stream_destroy( stream );
|
||||
|
||||
if ( success ) {
|
||||
(*storage->procs.inviteReceived)( storage->procsClosure,
|
||||
&invit );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
XP_LOGF( "%s: Unexpected cmd %d", __func__, header.cmd );
|
||||
XP_ASSERT( 0 );
|
||||
|
@ -388,6 +442,15 @@ writeShort( XP_U8* buf, size_t len, XP_U16 shrt )
|
|||
return sizeof(shrt);
|
||||
}
|
||||
|
||||
static size_t
|
||||
writeLong( XP_U8* buf, size_t len, XP_U32 lng )
|
||||
{
|
||||
lng = htonl( lng );
|
||||
assert( sizeof( lng ) <= len );
|
||||
memcpy( buf, &lng, sizeof(lng) );
|
||||
return sizeof(lng);
|
||||
}
|
||||
|
||||
static size_t
|
||||
writeVLI( XP_U8* out, uint32_t nn )
|
||||
{
|
||||
|
@ -430,6 +493,7 @@ writeHeader( RelayConStorage* storage, XP_U8* dest, XWRelayReg cmd )
|
|||
{
|
||||
int indx = 0;
|
||||
dest[indx++] = storage->proto;
|
||||
XP_LOGF( "%s: wrote proto %d", __func__, storage->proto );
|
||||
uint32_t packetNum = 0;
|
||||
if ( XWPDEV_ACK != cmd ) {
|
||||
packetNum = storage->nextID++;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
|
||||
/*
|
||||
* Copyright 2013 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
* Copyright 2013 - 2015 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
|
||||
|
@ -21,6 +22,7 @@
|
|||
#define _RELAYCON_H_
|
||||
|
||||
#include "main.h"
|
||||
#include "invit.h"
|
||||
|
||||
typedef struct _Procs {
|
||||
void (*msgReceived)( void* closure, const CommsAddrRec* from,
|
||||
|
@ -29,6 +31,7 @@ typedef struct _Procs {
|
|||
void (*devIDReceived)( void* closure, const XP_UCHAR* devID,
|
||||
XP_U16 maxInterval );
|
||||
void (*msgErrorMsg)( void* closure, const XP_UCHAR* msg );
|
||||
void (*inviteReceived)( void* closure, InviteInfo* invit );
|
||||
SocketAddedFunc socketAdded;
|
||||
} RelayConnProcs;
|
||||
|
||||
|
@ -36,6 +39,7 @@ void relaycon_init( LaunchParams* params, const RelayConnProcs* procs,
|
|||
void* procsClosure, const char* host, int port );
|
||||
void relaycon_reg( LaunchParams* params, const XP_UCHAR* rDevID,
|
||||
DevIDType typ, const XP_UCHAR* devID );
|
||||
void relaycon_invite( LaunchParams* params, XP_U32 dest, InviteInfo* invite );
|
||||
XP_S16 relaycon_send( LaunchParams* params, const XP_U8* buf, XP_U16 buflen,
|
||||
XP_U32 gameToken, const CommsAddrRec* addrRec );
|
||||
XP_S16 relaycon_sendnoconn( LaunchParams* params, const XP_U8* buf,
|
||||
|
|
Loading…
Reference in a new issue