diff --git a/xwords4/android/app/build.gradle b/xwords4/android/app/build.gradle
index 00aecdfef..f0b1862ae 100644
--- a/xwords4/android/app/build.gradle
+++ b/xwords4/android/app/build.gradle
@@ -1,6 +1,6 @@
def INITIAL_CLIENT_VERS = 9
-def VERSION_CODE_BASE = 148
-def VERSION_NAME = '4.4.152'
+def VERSION_CODE_BASE = 149
+def VERSION_NAME = '4.4.153'
def FABRIC_API_KEY = System.getenv("FABRIC_API_KEY")
def BUILD_INFO_NAME = "build-info.txt"
diff --git a/xwords4/android/app/src/main/assets/changes.html b/xwords4/android/app/src/main/assets/changes.html
index 28a3ab1f7..f6ca79a17 100644
--- a/xwords4/android/app/src/main/assets/changes.html
+++ b/xwords4/android/app/src/main/assets/changes.html
@@ -13,9 +13,9 @@
- CrossWords 4.4.152 release
+ CrossWords 4.4.153 release
- This release fixes a nasty crash in some non-English versions.
+ This release fixes a crash sending invitations via SMS/Text.
- New with this (and previous) release
+ New with this release
- - Fix crash with some localized versions (Weblate problem...)
- - Tweak network traffic arrows on game board
- - Fix crash dragging tiles
- - Fix invite-via-NFC for Android 10 (and improve for earlier
- Android versions)
- - Add ability to send moves via NFC
- - More translations (via Weblate) in Catalan, French, German,
- Japanese, Norwegian, Polish, and Spanish
- - Fix a couple of other crashes reported via Google (thanks!)
+ - Stop crashing when attempting to send an invitation via SMS (Text message)
+ - Fix email invitations
+ - Add don't-show-again checkbox to request for permission to check state of phone
+ - Include new translations in French and Spanish (via Weblate)
+ - Change copyright date: Happy 2020!
(The full changelog
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java
index 025567323..8ddbaaf49 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java
@@ -755,9 +755,10 @@ public class BoardDelegate extends DelegateBase
// straight to asking for the permission.
private void callInviteChoices( final SentInvitesInfo info )
{
- Perms23.tryGetPerms( this, Perm.READ_PHONE_STATE,
- R.string.phone_state_rationale,
- Action.ASKED_PHONE_STATE, info );
+ Perms23.tryGetPermsNA( this, Perm.READ_PHONE_STATE,
+ R.string.phone_state_rationale,
+ R.string.key_na_perms_phonestate,
+ Action.ASKED_PHONE_STATE, info );
}
private void showInviteChoicesThen( Object[] params )
@@ -1260,7 +1261,8 @@ public class BoardDelegate extends DelegateBase
break;
default:
- handled = false;
+ handled = super.onDismissed( action, params );
+ break;
}
return handled;
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java
index b739af7ca..093a5f296 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java
@@ -792,9 +792,20 @@ public class DelegateBase implements DlgClickNotify,
public boolean onDismissed( Action action, Object[] params )
{
- Log.d( TAG, "%s.dlgDismissed(%s)", getClass().getSimpleName(),
+ boolean handled = false;
+ Log.d( TAG, "%s.onDismissed(%s)", getClass().getSimpleName(),
action.toString() );
- return false;
+
+ switch( action ) {
+ case PERMS_QUERY:
+ handled = true;
+ Perms23.onGotPermsAction( this, false, params );
+ break;
+ default:
+ Log.e( TAG, "onDismissed(): not handling action %s", action );
+ }
+
+ return handled;
}
public void inviteChoiceMade( Action action, DlgClickNotify.InviteMeans means, Object... params )
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameConfigDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameConfigDelegate.java
index 33be78a13..dd545ec7b 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameConfigDelegate.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameConfigDelegate.java
@@ -783,9 +783,10 @@ public class GameConfigDelegate extends DelegateBase
private void showConnAfterCheck()
{
if ( null == SMSPhoneInfo.get( m_activity ) ) {
- Perms23.tryGetPerms( this, Perms23.Perm.READ_PHONE_STATE,
- R.string.phone_state_rationale,
- Action.ASKED_PHONE_STATE );
+ Perms23.tryGetPermsNA( this, Perms23.Perm.READ_PHONE_STATE,
+ R.string.phone_state_rationale,
+ R.string.key_na_perms_phonestate,
+ Action.ASKED_PHONE_STATE );
} else {
showDialogFragment( DlgID.CHANGE_CONN, m_conTypes );
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java
index 183d9edce..aff0be752 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java
@@ -217,9 +217,13 @@ public class NetLaunchInfo implements Serializable {
p2pMacAddress = data.getQueryParameter( P2P_MAC_KEY );
doAdd = !hasAddrs && null != p2pMacAddress;
break;
+ case COMMS_CONN_NFC:
+ doAdd = true;
+ break;
default:
doAdd = false;
- Assert.fail();
+ Log.d( TAG, "unexpected type: %s", typ );
+ Assert.assertFalse( BuildConfig.DEBUG );
}
if ( doAdd ) {
m_addrs.add( typ );
@@ -691,7 +695,7 @@ public class NetLaunchInfo implements Serializable {
private void calcValid()
{
boolean valid = hasCommon() && null != m_addrs;
- // DbgUtils.logf( "calcValid(%s)", toString() );
+ // Log.d( TAG, "calcValid(%s); valid (so far): %b", this, valid );
if ( valid ) {
for ( Iterator iter = m_addrs.iterator();
valid && iter.hasNext(); ) {
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Perms23.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Perms23.java
index f8efdf580..ebc106c6b 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Perms23.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Perms23.java
@@ -203,23 +203,26 @@ public class Perms23 {
private static class QueryInfo {
private Action m_action;
private Perm[] m_perms;
+ private int mNAKey;
private DelegateBase m_delegate;
private String m_rationaleMsg;
private Object[] m_params;
private QueryInfo( DelegateBase delegate, Action action,
- Perm[] perms, String msg, Object[] params ) {
+ Perm[] perms, String msg, int naKey,
+ Object[] params ) {
m_delegate = delegate;
m_action = action;
m_perms = perms;
m_rationaleMsg = msg;
+ mNAKey = naKey;
m_params = params;
}
private QueryInfo( DelegateBase delegate, Object[] params )
{
this( delegate, (Action)params[0], (Perm[])params[1], (String)params[2],
- (Object[])params[3] );
+ 0, (Object[])params[3] );
}
private Object[] getParams()
@@ -260,6 +263,7 @@ public class Perms23 {
.setPosButton( R.string.button_ask_again )
.setNegButton( R.string.button_skip )
.setParams( QueryInfo.this.getParams() )
+ .setNAKey( mNAKey )
.show();
}
} );
@@ -319,30 +323,36 @@ public class Perms23 {
* Request permissions, giving rationale once, then call with action and
* either positive or negative, the former if permission granted.
*/
+ private static void tryGetPermsImpl( DelegateBase delegate, Perm[] perms,
+ String rationaleMsg, int naKey,
+ final Action action, Object... params )
+ {
+ // Log.d( TAG, "tryGetPerms(%s)", perm.toString() );
+ new QueryInfo( delegate, action, perms, rationaleMsg, naKey, params )
+ .doIt( true );
+ }
+
public static void tryGetPerms( DelegateBase delegate, Perm[] perms, int rationaleId,
final Action action, Object... params )
{
// Log.d( TAG, "tryGetPerms(%s)", perm.toString() );
- Context context = XWApp.getContext();
- String msg = rationaleId == 0
- ? null : LocUtils.getString( context, rationaleId );
- tryGetPerms( delegate, perms, msg, action, params );
+ String msg = LocUtils.getStringOrNull( rationaleId );
+ tryGetPermsImpl( delegate, perms, msg, 0, action, params );
}
public static void tryGetPerms( DelegateBase delegate, Perm[] perms,
String rationaleMsg, final Action action,
Object... params )
{
- // Log.d( TAG, "tryGetPerms(%s)", perm.toString() );
- new QueryInfo( delegate, action, perms, rationaleMsg, params )
- .doIt( true );
+ tryGetPermsImpl( delegate, perms, rationaleMsg, 0, action, params );
}
public static void tryGetPerms( DelegateBase delegate, Perm perm,
String rationaleMsg, final Action action,
Object... params )
{
- tryGetPerms( delegate, new Perm[]{ perm }, rationaleMsg, action, params );
+ tryGetPermsImpl( delegate, new Perm[]{ perm }, rationaleMsg, 0,
+ action, params );
}
public static void tryGetPerms( DelegateBase delegate, Perm perm, int rationaleId,
@@ -351,6 +361,15 @@ public class Perms23 {
tryGetPerms( delegate, new Perm[]{perm}, rationaleId, action, params );
}
+ public static void tryGetPermsNA( DelegateBase delegate, Perm perm,
+ int rationaleId, int naKey,
+ Action action, Object... params )
+ {
+ tryGetPermsImpl( delegate, new Perm[] {perm},
+ LocUtils.getStringOrNull( rationaleId ), naKey,
+ action, params );
+ }
+
public static void onGotPermsAction( DelegateBase delegate, boolean positive,
Object[] params )
{
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/loc/LocUtils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/loc/LocUtils.java
index 3e65f491c..a2e74fcee 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/loc/LocUtils.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/loc/LocUtils.java
@@ -265,6 +265,16 @@ public class LocUtils {
return getString( context, true, id );
}
+ public static String getStringOrNull( int id )
+ {
+ String result = null;
+ if ( 0 != id ) {
+ Context context = XWApp.getContext();
+ result = getString( context, true, id );
+ }
+ return result;
+ }
+
public static String getString( Context context, boolean canUseDB, int id )
{
String result = null;
diff --git a/xwords4/android/app/src/main/res/values/common_rsrc.xml b/xwords4/android/app/src/main/res/values/common_rsrc.xml
index 56e50c8bc..f213c014e 100644
--- a/xwords4/android/app/src/main/res/values/common_rsrc.xml
+++ b/xwords4/android/app/src/main/res/values/common_rsrc.xml
@@ -145,6 +145,7 @@
key_na_bt_badproto
key_na_sms_banned
key_na_longtap_lookup
+ key_na_perms_phonestate
xwords@eehouse.org
diff --git a/xwords4/common/config.mk b/xwords4/common/config.mk
index ac15f4e62..c85f602fe 100644
--- a/xwords4/common/config.mk
+++ b/xwords4/common/config.mk
@@ -49,6 +49,7 @@ COMMONSRC = \
$(COMMONDIR)/dictmgr.c \
$(COMMONDIR)/dbgutil.c \
$(COMMONDIR)/smsproto.c \
+ $(COMMONDIR)/device.c \
# PENDING: define this in terms of above!!!
@@ -87,5 +88,6 @@ COMMON5 = \
$(COMMONOBJDIR)/dictmgr.o \
$(COMMONOBJDIR)/dbgutil.o \
$(COMMONOBJDIR)/smsproto.o \
+ $(COMMONOBJDIR)/device.o \
COMMONOBJ = $(COMMON1) $(COMMON2) $(COMMON3) $(COMMON4) $(COMMON5)
diff --git a/xwords4/common/device.c b/xwords4/common/device.c
new file mode 100644
index 000000000..7eedaf462
--- /dev/null
+++ b/xwords4/common/device.c
@@ -0,0 +1,79 @@
+/* -*- compile-command: "cd ../linux && make MEMDEBUG=TRUE -j3"; -*- */
+/*
+ * Copyright 2020 by Eric House (xwords@eehouse.org). All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "device.h"
+#include "comtypes.h"
+#include "memstream.h"
+#include "xwstream.h"
+
+#ifdef XWFEATURE_DEVICE
+
+# define KEY_DEVSTATE PERSIST_KEY("devState")
+
+typedef struct _DevCtxt {
+ XP_U16 devCount;
+} DevCtxt;
+
+static XWStreamCtxt*
+mkStream( XW_DUtilCtxt* dutil )
+{
+ XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(dutil->mpool)
+ dutil_getVTManager(dutil) );
+ return stream;
+}
+
+static DevCtxt*
+load( XW_DUtilCtxt* dutil )
+{
+ LOG_FUNC();
+ DevCtxt* state = (DevCtxt*)dutil->devCtxt;
+ if ( NULL == state ) {
+ XWStreamCtxt* stream = mkStream( dutil );
+ dutil_loadStream( dutil, KEY_DEVSTATE, stream );
+
+ state = XP_CALLOC( dutil->mpool, sizeof(*state) );
+ dutil->devCtxt = state;
+
+ if ( 0 < stream_getSize( stream ) ) {
+ state->devCount = stream_getU16( stream );
+ ++state->devCount; /* for testing until something's there */
+ XP_LOGF( "%s(): read devCount: %d", __func__, state->devCount );
+ } else {
+ XP_LOGF( "%s(): empty stream!!", __func__ );
+ }
+ stream_destroy( stream );
+ }
+
+ return state;
+}
+
+void
+device_store( XW_DUtilCtxt* dutil )
+{
+ LOG_FUNC();
+ DevCtxt* state = load( dutil );
+ XWStreamCtxt* stream = mkStream( dutil );
+ stream_putU16( stream, state->devCount );
+ dutil_storeStream( dutil, KEY_DEVSTATE, stream );
+ stream_destroy( stream );
+
+ XP_FREEP( dutil->mpool, &dutil->devCtxt );
+}
+
+#endif
diff --git a/xwords4/common/device.h b/xwords4/common/device.h
new file mode 100644
index 000000000..6868cb5ba
--- /dev/null
+++ b/xwords4/common/device.h
@@ -0,0 +1,33 @@
+/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
+/*
+ * Copyright 2020 by Eric House (xwords@eehouse.org). All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _DEVICE_H_
+#define _DEVICE_H_
+
+#include "dutil.h"
+
+// void device_load( XW_DUtilCtxt dctxt );
+# ifdef XWFEATURE_DEVICE
+void device_store( XW_DUtilCtxt* dctxt );
+# else
+# define device_store(dctxt)
+# endif
+
+#endif
diff --git a/xwords4/common/dutil.h b/xwords4/common/dutil.h
index 70aa8c70c..9771e8a09 100644
--- a/xwords4/common/dutil.h
+++ b/xwords4/common/dutil.h
@@ -60,8 +60,8 @@ typedef struct _DUtilVtable {
struct XW_DUtilCtxt {
DUtilVtable vtable;
-
void* closure;
+ void* devCtxt; /* owned by device.c */
VTableMgr* vtMgr;
MPSLOT
};
diff --git a/xwords4/common/nli.c b/xwords4/common/nli.c
index a49802443..c65d708b9 100644
--- a/xwords4/common/nli.c
+++ b/xwords4/common/nli.c
@@ -42,9 +42,21 @@ nli_init( NetLaunchInfo* nli, const CurGameInfo* gi, const CommsAddrRec* addr,
nli->nPlayersH = nPlayers;
nli->forceChannel = forceChannel;
- if ( addr_hasType( addr, COMMS_CONN_RELAY ) ) {
- types_addType( &nli->_conTypes, COMMS_CONN_RELAY );
- XP_STRCAT( nli->room, addr->u.ip_relay.invite );
+ CommsConnType typ;
+ for ( XP_U32 st = 0; addr_iter( addr, &typ, &st ); ) {
+ types_addType( &nli->_conTypes, typ );
+ switch ( typ ) {
+ case COMMS_CONN_RELAY:
+ XP_STRCAT( nli->room, addr->u.ip_relay.invite );
+ break;
+ case COMMS_CONN_SMS:
+ XP_STRCAT( nli->phone, addr->u.sms.phone );
+ // nli->port = addr->u.sms.port; <-- I wish
+ break;
+ default:
+ XP_ASSERT(0);
+ break;
+ }
}
}
@@ -159,9 +171,8 @@ nli_makeFromStream( NetLaunchInfo* nli, XWStreamCtxt* stream )
void
nli_makeAddrRec( const NetLaunchInfo* nli, CommsAddrRec* addr )
{
- XP_U32 state = 0;
CommsConnType type;
- while ( types_iter( nli->_conTypes, &type, &state ) ) {
+ for ( XP_U32 state = 0; types_iter( nli->_conTypes, &type, &state ); ) {
addr_addType( addr, type );
switch( type ) {
case COMMS_CONN_RELAY:
@@ -176,6 +187,7 @@ nli_makeAddrRec( const NetLaunchInfo* nli, CommsAddrRec* addr )
break;
case COMMS_CONN_SMS:
XP_STRCAT( addr->u.sms.phone, nli->phone );
+ addr->u.sms.port = 1; /* BAD, but 0 is worse */
break;
default:
XP_ASSERT(0);
diff --git a/xwords4/linux/Makefile b/xwords4/linux/Makefile
index 6e927ab16..dc52a8abf 100644
--- a/xwords4/linux/Makefile
+++ b/xwords4/linux/Makefile
@@ -163,6 +163,8 @@ DEFINES += -DXWFEATURE_DIRECTIP
# Robot can be made to think, to simulate for relay mostly
DEFINES += -DXWFEATURE_SLOW_ROBOT
+DEFINES += -DXWFEATURE_DEVICE
+
# Support device-to-device connection via UDP, e.g. using wifi on a
# LAN or where the host/server isn't behind a firewall.
# DEFINES += -DXWFEATURE_IP_DIRECT
diff --git a/xwords4/linux/cursesmain.c b/xwords4/linux/cursesmain.c
index bed4a4838..c6807c391 100644
--- a/xwords4/linux/cursesmain.c
+++ b/xwords4/linux/cursesmain.c
@@ -65,6 +65,7 @@
#include "gamesdb.h"
#include "relaycon.h"
#include "smsproto.h"
+#include "device.h"
#ifdef CURSES_SMALL_SCREEN
# define MENU_WINDOW_HEIGHT 1
@@ -2239,8 +2240,11 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
endwin();
+ device_store( params->dutil );
+
if ( !!params->dbName ) {
closeGamesDB( params->pDb );
+ params->pDb = NULL;
}
relaycon_cleanup( params );
diff --git a/xwords4/linux/gamesdb.c b/xwords4/linux/gamesdb.c
index e80a4de8d..efe30f397 100644
--- a/xwords4/linux/gamesdb.c
+++ b/xwords4/linux/gamesdb.c
@@ -533,8 +533,9 @@ db_fetch( sqlite3* pDb, const gchar* key, gchar* buf, gint* buflen )
XP_ASSERT( !!pDb );
FetchResult result = NOT_THERE;
char query[256];
- snprintf( query, sizeof(query),
- "SELECT value from pairs where key = '%s'", key );
+ int len = snprintf( query, sizeof(query),
+ "SELECT value from pairs where key = '%s'", key );
+ XP_ASSERT( len < sizeof(query) );
sqlite3_stmt *ppStmt;
int sqlResult = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
XP_Bool found = SQLITE_OK == sqlResult;
diff --git a/xwords4/linux/gtkboard.c b/xwords4/linux/gtkboard.c
index 17e62780f..0393bf9f5 100644
--- a/xwords4/linux/gtkboard.c
+++ b/xwords4/linux/gtkboard.c
@@ -85,7 +85,7 @@ static void handle_invite_button( GtkWidget* widget, GtkGameGlobals* globals );
static void gtkShowFinalScores( const GtkGameGlobals* globals,
XP_Bool ignoreTimeout );
static void send_invites( CommonGlobals* cGlobals, XP_U16 nPlayers,
- XP_U32 devID, const XP_UCHAR* relayID,
+ XP_U32 relayDevID, const XP_UCHAR* relayID,
const CommsAddrRec* addrs );
@@ -1556,18 +1556,19 @@ handle_invite_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
CommsAddrRec inviteAddr = {0};
gint nPlayers = nMissing;
- XP_U32 devID;
- XP_Bool confirmed = gtkInviteDlg( globals, &inviteAddr, &nPlayers, &devID );
+ XP_U32 relayDevID = 0;
+ XP_Bool confirmed = gtkInviteDlg( globals, &inviteAddr, &nPlayers,
+ &relayDevID );
XP_LOGF( "%s: inviteDlg => %d", __func__, confirmed );
if ( confirmed ) {
- send_invites( cGlobals, nPlayers, devID, NULL, &inviteAddr );
+ send_invites( cGlobals, nPlayers, relayDevID, NULL, &inviteAddr );
}
} /* handle_invite_button */
static void
send_invites( CommonGlobals* cGlobals, XP_U16 nPlayers,
- XP_U32 devID, const XP_UCHAR* relayID,
+ XP_U32 relayDevID, const XP_UCHAR* relayID,
const CommsAddrRec* addrs )
{
CommsAddrRec addr = {0};
@@ -1579,10 +1580,12 @@ send_invites( CommonGlobals* cGlobals, XP_U16 nPlayers,
NetLaunchInfo nli = {0};
nli_init( &nli, cGlobals->gi, &addr, nPlayers, forceChannel );
- XP_UCHAR buf[32];
- snprintf( buf, sizeof(buf), "%X", makeRandomInt() );
- nli_setInviteID( &nli, buf );
- nli_setDevID( &nli, linux_getDevIDRelay( cGlobals->params ) );
+ if ( addr_hasType( &addr, COMMS_CONN_RELAY ) ) {
+ XP_UCHAR buf[32];
+ snprintf( buf, sizeof(buf), "%X", makeRandomInt() );
+ nli_setInviteID( &nli, buf ); /* should not be relay only!!! */
+ }
+ // nli_setDevID( &nli, linux_getDevIDRelay( cGlobals->params ) );
#ifdef DEBUG
{
@@ -1603,9 +1606,9 @@ send_invites( CommonGlobals* cGlobals, XP_U16 nPlayers,
linux_sms_invite( cGlobals->params, &nli,
addrs->u.sms.phone, addrs->u.sms.port );
}
- if ( 0 != devID || !!relayID ) {
- XP_ASSERT( 0 != devID || (!!relayID && !!relayID[0]) );
- relaycon_invite( cGlobals->params, devID, relayID, &nli );
+ if ( 0 != relayDevID || !!relayID ) {
+ XP_ASSERT( 0 != relayDevID || (!!relayID && !!relayID[0]) );
+ relaycon_invite( cGlobals->params, relayDevID, relayID, &nli );
}
/* while ( gtkaskm( "Invite how many and how?", infos, VSIZE(infos) ) ) { */
diff --git a/xwords4/linux/gtkinvit.c b/xwords4/linux/gtkinvit.c
index d2ca40fc1..c85a85f48 100644
--- a/xwords4/linux/gtkinvit.c
+++ b/xwords4/linux/gtkinvit.c
@@ -38,7 +38,7 @@ typedef struct _GtkInviteState {
GtkGameGlobals* globals;
CommsAddrRec* addr;
gint* nPlayersP;
- XP_U32* devIDp;
+ XP_U32* relayDevIDp;
gint maxPlayers;
GtkWidget* nPlayersCombo;
@@ -96,7 +96,7 @@ handle_ok( GtkWidget* XP_UNUSED(widget), gpointer closure )
case COMMS_CONN_RELAY:
txt = gtk_entry_get_text( GTK_ENTRY(state->devID) );
snprintf( s_devIDBuf, sizeof(s_devIDBuf), "%s", txt );
- *state->devIDp = atoi( txt );
+ *state->relayDevIDp = atoi( txt );
break;
#endif
#ifdef XWFEATURE_BLUETOOTH
@@ -275,18 +275,15 @@ onPageChanged( GtkNotebook* XP_UNUSED(notebook), gpointer XP_UNUSED(arg1),
XP_Bool
gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr,
- gint* nPlayersP, XP_U32* devIDp )
-
-
+ gint* nPlayersP, XP_U32* relayDevIDp )
{
- GtkInviteState state;
- XP_MEMSET( &state, 0, sizeof(state) );
-
- state.globals = globals;
- state.addr = addr;
- state.nPlayersP = nPlayersP;
- state.devIDp = devIDp;
- state.maxPlayers = *nPlayersP;
+ GtkInviteState state = {
+ .globals = globals,
+ .addr = addr,
+ .nPlayersP = nPlayersP,
+ .relayDevIDp = relayDevIDp,
+ .maxPlayers = *nPlayersP,
+ };
GtkWidget* dialog;
GtkWidget* hbox;
diff --git a/xwords4/linux/gtkinvit.h b/xwords4/linux/gtkinvit.h
index 5bb1b02f2..3f5cb960d 100644
--- a/xwords4/linux/gtkinvit.h
+++ b/xwords4/linux/gtkinvit.h
@@ -24,7 +24,7 @@
/* return true if not cancelled */
XP_Bool gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr,
- /*inout*/ gint* nPlayers, /* out */ XP_U32* devID );
+ /*inout*/ gint* nPlayers, /* out */ XP_U32* relayDevID );
#endif
diff --git a/xwords4/linux/gtkmain.c b/xwords4/linux/gtkmain.c
index f44912bd7..ee7451f91 100644
--- a/xwords4/linux/gtkmain.c
+++ b/xwords4/linux/gtkmain.c
@@ -31,6 +31,7 @@
#include "relaycon.h"
#include "linuxsms.h"
#include "gtkask.h"
+#include "device.h"
static void onNewData( GtkAppGlobals* apg, sqlite3_int64 rowid,
XP_Bool isNew );
@@ -941,8 +942,9 @@ gtkmain( LaunchParams* params )
}
gtk_main();
-
+ device_store( params->dutil );
closeGamesDB( params->pDb );
+ params->pDb = NULL;
relaycon_cleanup( params );
#ifdef XWFEATURE_SMS
linux_sms_cleanup( params );
diff --git a/xwords4/linux/lindutil.c b/xwords4/linux/lindutil.c
index 3be0a333d..1ea819945 100644
--- a/xwords4/linux/lindutil.c
+++ b/xwords4/linux/lindutil.c
@@ -205,12 +205,8 @@ linux_dutil_loadStream( XW_DUtilCtxt* duc, const XP_UCHAR* key,
if ( 0 < len ) {
XP_U8 buf[len];
linux_dutil_loadPtr( duc, key, buf, &len );
- XP_ASSERT( buf[len-1] == '\0' );
- gsize out_len;
- guchar* txt = g_base64_decode( (const gchar*)buf, &out_len ); /* BAD */
- stream_putBytes( stream, txt, out_len );
- g_free( txt );
+ stream_putBytes( stream, buf, len );
}
XP_LOGF( "%s(key=%s) => len: %d", __func__, key, stream_getSize(stream) );
@@ -218,7 +214,7 @@ linux_dutil_loadStream( XW_DUtilCtxt* duc, const XP_UCHAR* key,
static void
linux_dutil_storePtr( XW_DUtilCtxt* duc, const XP_UCHAR* key,
- const void* data, XP_U16 len )
+ const void* data, const XP_U16 len )
{
LaunchParams* params = (LaunchParams*)duc->closure;
sqlite3* pDb = params->pDb;
@@ -238,18 +234,23 @@ linux_dutil_loadPtr( XW_DUtilCtxt* duc, const XP_UCHAR* key,
gint buflen = 0;
FetchResult res = db_fetch( pDb, key, NULL, &buflen );
if ( res == BUFFER_TOO_SMALL ) { /* expected: I passed 0 */
- void* tmp = XP_MALLOC( duc->mpool, buflen );
- res = db_fetch( pDb, key, tmp, &buflen );
- XP_ASSERT( res == SUCCESS );
+ if ( 0 == *lenp ) {
+ *lenp = buflen;
+ } else {
+ gchar* tmp = XP_MALLOC( duc->mpool, buflen );
+ res = db_fetch( pDb, key, tmp, &buflen );
+ XP_ASSERT( res == SUCCESS );
+ XP_ASSERT( tmp[buflen-1] == '\0' );
- gsize out_len;
- guchar* txt = g_base64_decode( (const gchar*)tmp, &out_len );
- if ( out_len <= *lenp ) {
- XP_MEMCPY( data, txt, out_len );
- *lenp = out_len;
+ gsize out_len;
+ guchar* txt = g_base64_decode( (const gchar*)tmp, &out_len );
+ if ( out_len <= *lenp ) {
+ XP_MEMCPY( data, txt, out_len );
+ *lenp = out_len;
+ }
+ XP_FREEP( duc->mpool, &tmp );
+ g_free( txt );
}
- XP_FREEP( duc->mpool, &tmp );
- g_free( txt );
} else {
*lenp = 0; /* doesn't exist */
}
diff --git a/xwords4/linux/relaycon.c b/xwords4/linux/relaycon.c
index 03b2e69b5..7ffbeab9f 100644
--- a/xwords4/linux/relaycon.c
+++ b/xwords4/linux/relaycon.c
@@ -313,7 +313,7 @@ relaycon_reg( LaunchParams* params, const XP_UCHAR* rDevID,
}
void
-relaycon_invite( LaunchParams* params, XP_U32 destDevID,
+relaycon_invite( LaunchParams* params, XP_U32 destRelayDevID,
const XP_UCHAR* relayID, NetLaunchInfo* invit )
{
XP_U8 tmpbuf[256];
@@ -326,13 +326,13 @@ relaycon_invite( LaunchParams* params, XP_U32 destDevID,
/* write relayID /, or if we have an actual devID write a
null byte plus it. */
- if ( 0 == destDevID ) {
+ if ( 0 == destRelayDevID ) {
XP_ASSERT( '\0' != relayID[0] );
indx += writeBytes( &tmpbuf[indx], sizeof(tmpbuf) - indx,
(XP_U8*)relayID, 1 + XP_STRLEN( relayID ) );
} else {
tmpbuf[indx++] = '\0'; /* null byte: zero-len str */
- indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, destDevID );
+ indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, destRelayDevID );
}
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(params->mpool)