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:
Eric House 2015-07-01 07:10:45 -07:00
parent 6d768972db
commit 8f794fbd32
18 changed files with 919 additions and 77 deletions

View file

@ -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

View file

@ -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 );

View file

@ -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 = \

View file

@ -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
View 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
View 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

View file

@ -19,6 +19,7 @@
*/
#include "comtypes.h"
#include "nwgamest.h"
#include "strutils.h"
#include "LocalizedStrIncludes.h"

View file

@ -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 \

View file

@ -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
View 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
View 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

View file

@ -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, &params->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 );
}

View file

@ -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 );

View file

@ -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 );

View file

@ -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 );

View file

@ -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 );

View file

@ -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++;

View file

@ -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,