From 1962371fe211f8fd75db881e8505def1e41a8e97 Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 19 Nov 2014 18:46:35 -0800 Subject: [PATCH] flesh out MultiMsgSink so that subclasses invoked e.g. in response to BT traffic can send messages via other means as well. Relay games with both participants on one device work again. --- xwords4/android/XWords4/jni/xwjni.c | 1 + .../org/eehouse/android/xw4/BTService.java | 27 +++---- .../eehouse/android/xw4/BoardDelegate.java | 11 +-- .../eehouse/android/xw4/CommsTransport.java | 13 +-- .../android/xw4/ConnStatusHandler.java | 3 + .../org/eehouse/android/xw4/GameUtils.java | 49 ++++-------- .../org/eehouse/android/xw4/MultiMsgSink.java | 80 ++++++++++++++++++- .../org/eehouse/android/xw4/RelayService.java | 34 ++++---- .../org/eehouse/android/xw4/SMSService.java | 23 +----- .../eehouse/android/xw4/jni/CommsAddrRec.java | 5 ++ .../eehouse/android/xw4/jni/JNIThread.java | 1 + 11 files changed, 146 insertions(+), 101 deletions(-) diff --git a/xwords4/android/XWords4/jni/xwjni.c b/xwords4/android/XWords4/jni/xwjni.c index 34b80b7ca..daa6c07c7 100644 --- a/xwords4/android/XWords4/jni/xwjni.c +++ b/xwords4/android/XWords4/jni/xwjni.c @@ -1361,6 +1361,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1receiveMessage jstream ); CommsAddrRec* addrp = NULL; CommsAddrRec addr = {0}; + XP_ASSERT( !!jaddr ); if ( NULL != jaddr ) { getJAddrRec( env, &addr, jaddr ); addrp = &addr; diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BTService.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BTService.java index 9beed43e1..3bd6247ed 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BTService.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BTService.java @@ -150,7 +150,7 @@ public class BTService extends XWService { private BluetoothAdapter m_adapter; private Set m_addrs; - private MultiMsgSink m_btMsgSink; + private BTMsgSink m_btMsgSink; private BTListenerThread m_listener; private BTSenderThread m_sender; private static int s_errCount = 0; @@ -1064,10 +1064,8 @@ public class BTService extends XWService { BTCmd result; long[] rowids = DBUtils.getRowIDsFor( BTService.this, nli.gameID ); if ( null == rowids || 0 == rowids.length ) { - CommsAddrRec addr = new CommsAddrRec( sender, senderAddress ); - long rowid = GameUtils.makeNewGame( context, m_btMsgSink, nli.gameID, - addr, nli.lang, nli.dict, nli.nPlayersT, - nli.nPlayersH ); + CommsAddrRec addr = nli.makeAddrRec( context ); + long rowid = GameUtils.makeNewMultiGame( context, nli, m_btMsgSink ); if ( DBUtils.ROWID_NOTFOUND == rowid ) { result = BTCmd.INVITE_FAILED; } else { @@ -1171,20 +1169,15 @@ public class BTService extends XWService { private class BTMsgSink extends MultiMsgSink { - /***** TransportProcs interface *****/ + public BTMsgSink() { super( BTService.this ); } - public int transportSend( byte[] buf, final CommsAddrRec addr, int gameID ) + @Override + public int sendViaBluetooth( byte[] buf, int gameID, CommsAddrRec addr ) { - int sent = -1; - if ( null != addr ) { - m_sender.add( new BTQueueElem( BTCmd.MESG_SEND, buf, - addr.bt_btAddr, gameID ) ); - sent = buf.length; - } else { - DbgUtils.logf( "BTMsgSink.transportSend: " - + "addr null so not sending" ); - } - return sent; + Assert.assertTrue( addr.contains( CommsConnType.COMMS_CONN_BT ) ); + m_sender.add( new BTQueueElem( BTCmd.MESG_SEND, buf, + addr.bt_btAddr, gameID ) ); + return buf.length; } } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardDelegate.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardDelegate.java index 8b05c067f..432188618 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardDelegate.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardDelegate.java @@ -165,12 +165,14 @@ public class BoardDelegate extends DelegateBase return delivered; } - public static boolean feedMessage( long rowid, byte[] msg ) + public static boolean feedMessage( long rowid, byte[] msg, + CommsAddrRec ret ) { - return feedMessages( rowid, new byte[][]{msg} ); + return feedMessages( rowid, new byte[][]{msg}, ret ); } - public static boolean feedMessages( long rowid, byte[][] msgs ) + public static boolean feedMessages( long rowid, byte[][] msgs, + CommsAddrRec ret ) { boolean delivered = false; Assert.assertNotNull( msgs ); @@ -185,8 +187,7 @@ public class BoardDelegate extends DelegateBase if ( rowid == self.m_rowid ) { delivered = true; // even if no messages! for ( byte[] msg : msgs ) { - self.m_jniThread.handle( JNICmd.CMD_RECEIVE, msg, - null ); + self.m_jniThread.handle( JNICmd.CMD_RECEIVE, msg, ret ); } } } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/CommsTransport.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/CommsTransport.java index b6a1d2dba..a172ddf86 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/CommsTransport.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/CommsTransport.java @@ -371,7 +371,7 @@ public class CommsTransport implements TransportProcs, } if ( !XWApp.UDP_ENABLED - && addr.conTypes.contains(CommsConnType.COMMS_CONN_RELAY) ) { + && addr.contains(CommsConnType.COMMS_CONN_RELAY) ) { if ( NetStateCache.netAvail( m_context ) ) { putOut( buf ); // add to queue if ( null == m_thread ) { @@ -434,9 +434,10 @@ public class CommsTransport implements TransportProcs, return false; } - public static int sendForAddr( Context context, CommsAddrRec addr, - long rowID, int gameID, byte[] buf ) + private static int sendForAddr( Context context, CommsAddrRec addr, + long rowID, int gameID, byte[] buf ) { + DbgUtils.logf( "sendForAddr(addr=%s)", addr.conTypes.toString() ); int mostSent = -1; for ( Iterator iter = addr.conTypes.iterator(); iter.hasNext(); ) { @@ -458,10 +459,12 @@ public class CommsTransport implements TransportProcs, Assert.fail(); break; } - if ( nSent < mostSent ) { - nSent = mostSent; + if ( mostSent < nSent ) { + mostSent = nSent; } } + DbgUtils.logf( "sendForAddr(addr=%s)=>%d", addr.conTypes.toString(), + mostSent ); return mostSent; } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/ConnStatusHandler.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/ConnStatusHandler.java index e08793c2d..f360d4764 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/ConnStatusHandler.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/ConnStatusHandler.java @@ -499,6 +499,9 @@ public class ConnStatusHandler { result = XWApp.BTSUPPORTED && BTService.BTEnabled() && !getAirplaneModeOn( context ); break; + case COMMS_CONN_RELAY: + result = NetStateCache.netAvail( context ); + break; default: DbgUtils.logf( "ConnStatusHandler:connTypeEnabled: %s not handled", connType.toString() ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java index 983446506..775c4f9bd 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java @@ -453,11 +453,17 @@ public class GameUtils { } public static long makeNewMultiGame( Context context, NetLaunchInfo nli ) + { + return makeNewMultiGame( context, nli, null ); + } + + public static long makeNewMultiGame( Context context, NetLaunchInfo nli, + MultiMsgSink sink ) { DbgUtils.logf( "makeNewMultiGame(nli=%s)", nli.toString() ); CommsAddrRec addr = nli.makeAddrRec( context ); - return makeNewMultiGame( context, null, DBUtils.GROUPID_UNSPEC, addr, + return makeNewMultiGame( context, sink, DBUtils.GROUPID_UNSPEC, addr, new int[] {nli.lang}, new String[] { nli.dict }, nli.nPlayersT, 1, nli.inviteID, nli.gameID, false ); @@ -509,6 +515,9 @@ public class GameUtils { // work Assert.assertTrue( gi.nPlayers == nPlayersT ); rowid = saveNew( context, gi, groupID ); + if ( null != sink ) { + sink.setRowID( rowid ); + } if ( DBUtils.ROWID_NOTFOUND != rowid ) { GameLock lock = new GameLock( rowid, true ).lock(); @@ -1076,7 +1085,7 @@ public class GameUtils { private HashMap m_games; private boolean m_showUI; private CommsConnType m_filter; - private int m_nSent = 0; + private MultiMsgSink m_sink; public ResendTask( Context context, HashMap games, CommsConnType filter, boolean showUI ) @@ -1103,8 +1112,8 @@ public class GameUtils { GameLock lock = new GameLock( rowid, false ); if ( lock.tryLock() ) { CurGameInfo gi = new CurGameInfo( m_context ); - MsgSink sink = new MsgSink( m_context, rowid ); - int gamePtr = loadMakeGame( m_context, gi, sink, lock ); + m_sink = new MultiMsgSink( m_context, rowid ); + int gamePtr = loadMakeGame( m_context, gi, m_sink, lock ); if ( 0 != gamePtr ) { XwJNI.comms_resendAll( gamePtr, true, false ); } @@ -1121,36 +1130,8 @@ public class GameUtils { protected void onPostExecute( Void unused ) { if ( m_showUI ) { - DbgUtils.showf( m_context, R.string.resend_finished_fmt, m_nSent ); - } - } - - private class MsgSink extends MultiMsgSink { - private Context m_context; - private long m_rowid; - - public MsgSink( Context context, long rowid ) - { - m_context = context; - m_rowid = rowid; - } - - @Override - public boolean relayNoConnProc( byte[] buf, String relayID ) - { - int len = buf.length; - if ( len == RelayService.sendNoConnPacket( m_context, m_rowid, - relayID, buf ) ) { - ++m_nSent; - } - return true; - } - - public int transportSend( byte[] buf, final CommsAddrRec addr, int gameID ) - { - return null == addr ? -1 - : CommsTransport.sendForAddr( m_context, addr, m_rowid, - gameID, buf ); + int nSent = null == m_sink ? 0 : m_sink.numSent(); + DbgUtils.showf( m_context, R.string.resend_finished_fmt, nSent ); } } } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/MultiMsgSink.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/MultiMsgSink.java index 95a663879..69d3b54e6 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/MultiMsgSink.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/MultiMsgSink.java @@ -27,8 +27,51 @@ import java.util.ArrayList; import junit.framework.Assert; import org.eehouse.android.xw4.jni.*; +import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType; public class MultiMsgSink implements TransportProcs { + private long m_rowid; + private Context m_context; + private int m_nSent = 0; + + public MultiMsgSink( Context context, long rowid ) + { + m_context = context; + m_rowid = rowid; + } + + public MultiMsgSink( Context context ) + { + this( context, 0 ); + } + + // rowID is used as token to identify game on relay. Anything that + // uniquely identifies a game on a device would work + public long getRowID() { return m_rowid; }; + public void setRowID( long rowID ) { m_rowid = rowID; }; + + // These will be overridden by e.g. BTService which for sendViaBluetooth() + // can just insert a message into its queue + public int sendViaRelay( byte[] buf, int gameID ) + { + Assert.assertTrue( XWApp.UDP_ENABLED ); + return RelayService.sendPacket( m_context, getRowID(), buf ); + } + + public int sendViaBluetooth( byte[] buf, int gameID, CommsAddrRec addr ) + { + return BTService.enqueueFor( m_context, buf, addr.bt_btAddr, gameID ); + } + + public int sendViaSMS( byte[] buf, int gameID, CommsAddrRec addr ) + { + return SMSService.sendPacket( m_context, addr.sms_phone, gameID, buf ); + } + + public int numSent() + { + return m_nSent; + } /***** TransportProcs interface *****/ @@ -36,8 +79,35 @@ public class MultiMsgSink implements TransportProcs { public int transportSend( byte[] buf, final CommsAddrRec addr, int gameID ) { - Assert.fail(); // implement if this is getting called!!! - return -1; + int maxSent = -1; + for ( CommsConnType typ : addr.conTypes.getTypes() ) { + int nSent = -1; + switch ( typ ) { + case COMMS_CONN_RELAY: + nSent = sendViaRelay( buf, gameID ); + break; + case COMMS_CONN_BT: + nSent = sendViaBluetooth( buf, gameID, addr ); + break; + case COMMS_CONN_SMS: + nSent = sendViaSMS( buf, gameID, addr ); + break; + default: + Assert.fail(); + break; + } + DbgUtils.logf( "MultiMsgSink.transportSend(): sent %d via %s", + nSent, typ.toString() ); + if ( nSent > maxSent ) { + maxSent = nSent; + } + } + + if ( 0 < maxSent ) { + ++m_nSent; + } + + return maxSent; } public void relayStatus( CommsRelayState newState ) @@ -55,7 +125,9 @@ public class MultiMsgSink implements TransportProcs { public boolean relayNoConnProc( byte[] buf, String relayID ) { - Assert.fail(); // implement if this is getting called!!! - return false; + Assert.fail(); + int nSent = RelayService.sendNoConnPacket( m_context, getRowID(), + relayID, buf ); + return buf.length == nSent; } } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java index 03c7cd8cc..913f1ee7a 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java @@ -47,6 +47,7 @@ import junit.framework.Assert; import org.eehouse.android.xw4.MultiService.MultiEvent; import org.eehouse.android.xw4.jni.CommsAddrRec; +import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType; import org.eehouse.android.xw4.jni.GameSummary; import org.eehouse.android.xw4.jni.UtilCtxt; import org.eehouse.android.xw4.jni.UtilCtxt.DevIDType; @@ -86,6 +87,8 @@ public class RelayService extends XWService private static int s_nextPacketID = 1; private static boolean s_gcmWorking = false; private static boolean s_registered = false; + private static CommsAddrRec s_addr = + new CommsAddrRec( CommsConnType.COMMS_CONN_RELAY ); private Thread m_fetchThread = null; private Thread m_UDPReadThread = null; @@ -849,14 +852,14 @@ public class RelayService extends XWService { DbgUtils.logf( "RelayService::feedMessage: %d bytes for rowid %d", msg.length, rowid ); - if ( BoardDelegate.feedMessage( rowid, msg ) ) { + if ( BoardDelegate.feedMessage( rowid, msg, s_addr ) ) { DbgUtils.logf( "feedMessage: board ate it" ); // do nothing } else { RelayMsgSink sink = new RelayMsgSink(); sink.setRowID( rowid ); LastMoveInfo lmi = new LastMoveInfo(); - if ( GameUtils.feedMessage( this, rowid, msg, null, + if ( GameUtils.feedMessage( this, rowid, msg, s_addr, sink, lmi ) ) { GameUtils.postMoveNotification( this, rowid, lmi ); } else { @@ -892,9 +895,9 @@ public class RelayService extends XWService if ( null != forOne ) { LastMoveInfo lmi = new LastMoveInfo(); sink.setRowID( rowIDs[ii] ); - if ( BoardDelegate.feedMessages( rowIDs[ii], forOne ) + if ( BoardDelegate.feedMessages( rowIDs[ii], forOne, s_addr ) || GameUtils.feedMessages( this, rowIDs[ii], - forOne, null, + forOne, s_addr, sink, lmi ) ) { idsWMsgs.add( relayIDs[ii] ); lmis.add( lmi ); @@ -1004,35 +1007,32 @@ public class RelayService extends XWService } // sendToRelay private class RelayMsgSink extends MultiMsgSink { - private HashMap> m_msgLists = null; - private long m_rowid = -1; - public void setRowID( long rowid ) { m_rowid = rowid; } + public RelayMsgSink() { super( RelayService.this ); } public void send( Context context ) { - if ( -1 == m_rowid ) { + if ( -1 == getRowID() ) { sendToRelay( context, m_msgLists ); } else { Assert.assertNull( m_msgLists ); } } - - /***** TransportProcs interface *****/ - - public int transportSend( byte[] buf, final CommsAddrRec addr, - int gameID ) + + @Override + public int sendViaRelay( byte[] buf, int gameID ) { - Assert.assertTrue( -1 != m_rowid ); - sendPacket( RelayService.this, m_rowid, buf ); + Assert.assertTrue( -1 != getRowID() ); + sendPacket( RelayService.this, getRowID(), buf ); return buf.length; } public boolean relayNoConnProc( byte[] buf, String relayID ) { - if ( -1 != m_rowid ) { - sendNoConnMessage( m_rowid, relayID, buf ); + long rowID = getRowID(); + if ( -1 != rowID ) { + sendNoConnMessage( rowID, relayID, buf ); } else { if ( null == m_msgLists ) { m_msgLists = new HashMap>(); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/SMSService.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/SMSService.java index 9fcd42b04..b45bde2ca 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/SMSService.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/SMSService.java @@ -883,29 +883,14 @@ public class SMSService extends XWService { } private class SMSMsgSink extends MultiMsgSink { - private Context m_context; public SMSMsgSink( Context context ) { - super(); - m_context = context; + super( context ); } - /***** TransportProcs interface *****/ - public int transportSend( byte[] buf, final CommsAddrRec addr, int gameID ) + @Override + public int sendViaSMS( byte[] buf, int gameID, CommsAddrRec addr ) { - int nSent = -1; - if ( null != addr ) { - nSent = sendPacket( addr.sms_phone, gameID, buf ); - } else { - DbgUtils.logf( "SMSMsgSink.transportSend: " - + "addr null so not sending" ); - } - return nSent; - } - - public boolean relayNoConnProc( byte[] buf, String relayID ) - { - Assert.fail(); - return false; + return sendPacket( addr.sms_phone, gameID, buf ); } } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/CommsAddrRec.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/CommsAddrRec.java index 122e43608..0c8487c03 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/CommsAddrRec.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/CommsAddrRec.java @@ -155,6 +155,11 @@ public class CommsAddrRec { this.copyFrom( src ); } + public boolean contains( CommsConnType typ ) + { + return null != conTypes && conTypes.contains( typ ); + } + public void setRelayParams( String host, int port, String room ) { setRelayParams( host, port ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java index 5d0ab4af3..ed28cb3b0 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java @@ -391,6 +391,7 @@ public class JNIThread extends Thread { case CMD_RECEIVE: CommsAddrRec ret = (CommsAddrRec)args[1]; + Assert.assertNotNull( ret ); draw = XwJNI.game_receiveMessage( m_jniGamePtr, (byte[])args[0], ret ); handle( JNICmd.CMD_DO );