don't enqueue dupes of messages already in queue

No point in giving a spot to something the receiver will drop as a
duplicate.
This commit is contained in:
Eric House 2019-02-20 10:29:24 -08:00
parent 87a27e7630
commit c2a4c07746
3 changed files with 74 additions and 26 deletions

View file

@ -48,6 +48,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -119,6 +120,7 @@ public class BTService extends XWJIService {
}; };
private static final String MSG_KEY = "MSG"; private static final String MSG_KEY = "MSG";
private static final String MSGID_KEY = "MSGID";
private static final String GAMENAME_KEY = "NAM"; private static final String GAMENAME_KEY = "NAM";
private static final String ADDR_KEY = "ADR"; private static final String ADDR_KEY = "ADR";
private static final String SCAN_TIMEOUT_KEY = "SCAN_TIMEOUT"; private static final String SCAN_TIMEOUT_KEY = "SCAN_TIMEOUT";
@ -333,7 +335,7 @@ public class BTService extends XWJIService {
enqueueWork( context, intent ); enqueueWork( context, intent );
} }
public static int sendPacket( Context context, byte[] buf, public static int sendPacket( Context context, byte[] buf, String msgID,
CommsAddrRec targetAddr, int gameID ) CommsAddrRec targetAddr, int gameID )
{ {
int nSent = -1; int nSent = -1;
@ -342,6 +344,7 @@ public class BTService extends XWJIService {
if ( null != btAddr && 0 < btAddr.length() ) { if ( null != btAddr && 0 < btAddr.length() ) {
Intent intent = getIntentTo( context, BTAction.SEND ) Intent intent = getIntentTo( context, BTAction.SEND )
.putExtra( MSG_KEY, buf ) .putExtra( MSG_KEY, buf )
.putExtra( MSGID_KEY, msgID )
.putExtra( ADDR_KEY, btAddr ) .putExtra( ADDR_KEY, btAddr )
.putExtra( GAMEID_KEY, gameID ); .putExtra( GAMEID_KEY, gameID );
enqueueWork( context, intent ); enqueueWork( context, intent );
@ -447,9 +450,10 @@ public class BTService extends XWJIService {
case SEND: case SEND:
byte[] buf = intent.getByteArrayExtra( MSG_KEY ); byte[] buf = intent.getByteArrayExtra( MSG_KEY );
btAddr = intent.getStringExtra( ADDR_KEY ); btAddr = intent.getStringExtra( ADDR_KEY );
String msgID = intent.getStringExtra( MSGID_KEY );
gameID = intent.getIntExtra( GAMEID_KEY, -1 ); gameID = intent.getIntExtra( GAMEID_KEY, -1 );
if ( -1 != gameID ) { if ( -1 != gameID ) {
getSenderFor( btAddr ).addMsg( gameID, buf ); getSenderFor( btAddr ).addMsg( gameID, buf, msgID );
} }
break; break;
case RADIO: case RADIO:
@ -1076,12 +1080,13 @@ public class BTService extends XWJIService {
public BTMsgSink() { super( BTService.this ); } public BTMsgSink() { super( BTService.this ); }
@Override @Override
public int sendViaBluetooth( byte[] buf, int gameID, CommsAddrRec addr ) public int sendViaBluetooth( byte[] buf, String msgID, int gameID,
CommsAddrRec addr )
{ {
int nSent = -1; int nSent = -1;
String btAddr = getSafeAddr( addr ); String btAddr = getSafeAddr( addr );
if ( null != btAddr && 0 < btAddr.length() ) { if ( null != btAddr && 0 < btAddr.length() ) {
getSenderFor( btAddr ).addMsg( gameID, buf ); getSenderFor( btAddr ).addMsg( gameID, buf, msgID );
BTSenderThread.startYourself( BTService.this ); BTSenderThread.startYourself( BTService.this );
nSent = buf.length; nSent = buf.length;
} else { } else {
@ -1122,13 +1127,15 @@ public class BTService extends XWJIService {
private static class MsgElem { private static class MsgElem {
BTCmd mCmd; BTCmd mCmd;
String mMsgID;
int mGameID; int mGameID;
long mStamp; long mStamp;
byte[] mData; byte[] mData;
MsgElem( BTCmd cmd, int gameID, OutputPair op ) MsgElem( BTCmd cmd, int gameID, String msgID, OutputPair op )
{ {
mCmd = cmd; mCmd = cmd;
mMsgID = msgID;
mGameID = gameID; mGameID = gameID;
mStamp = System.currentTimeMillis(); mStamp = System.currentTimeMillis();
@ -1148,7 +1155,27 @@ public class BTService extends XWJIService {
} }
} }
boolean isSameAs( MsgElem other )
{
boolean result = mCmd == other.mCmd
&& mGameID == other.mGameID
&& Arrays.equals( mData, other.mData );
if ( result ) {
if ( null != mMsgID && !mMsgID.equals( other.mMsgID ) ) {
Log.e( TAG, "hmmm: identical but msgIDs differ: new %s vs old %s",
mMsgID, other.mMsgID );
Assert.assertFalse( BuildConfig.DEBUG );
}
}
return result;
}
int size() { return mData.length; } int size() { return mData.length; }
@Override
public String toString()
{
return String.format("{cmd: %s, msgID: %s}", mCmd, mMsgID );
}
} }
private String mAddr; private String mAddr;
@ -1382,14 +1409,14 @@ public class BTService extends XWJIService {
} }
} }
void addMsg( int gameID, byte[] buf ) void addMsg( int gameID, byte[] buf, String msgID )
{ {
try { try {
OutputPair op = new OutputPair(); OutputPair op = new OutputPair();
op.dos.writeInt( gameID ); op.dos.writeInt( gameID );
op.dos.writeShort( buf.length ); op.dos.writeShort( buf.length );
op.dos.write( buf, 0, buf.length ); op.dos.write( buf, 0, buf.length );
append( BTCmd.MESG_SEND, gameID, op ); append( BTCmd.MESG_SEND, gameID, msgID, op );
} catch ( IOException ioe ) { } catch ( IOException ioe ) {
Assert.assertFalse( BuildConfig.DEBUG ); Assert.assertFalse( BuildConfig.DEBUG );
} }
@ -1408,20 +1435,40 @@ public class BTService extends XWJIService {
private void append( BTCmd cmd, OutputPair op ) throws IOException private void append( BTCmd cmd, OutputPair op ) throws IOException
{ {
append( cmd, 0, op ); append( cmd, 0, null, op );
} }
private boolean append( BTCmd cmd, int gameID, OutputPair op ) throws IOException private void append( BTCmd cmd, int gameID, OutputPair op ) throws IOException
{
append( cmd, gameID, null, op );
}
private boolean append( BTCmd cmd, int gameID, String msgID,
OutputPair op ) throws IOException
{ {
boolean haveSpace; boolean haveSpace;
try ( DbgUtils.DeadlockWatch dw = new DbgUtils.DeadlockWatch( this ) ) { try ( DbgUtils.DeadlockWatch dw = new DbgUtils.DeadlockWatch( this ) ) {
synchronized ( this ) { synchronized ( this ) {
MsgElem newElem = new MsgElem( cmd, gameID, op ); MsgElem newElem = new MsgElem( cmd, gameID, msgID, op );
haveSpace = mLength + newElem.size() < MAX_PACKET_LEN; haveSpace = mLength + newElem.size() < MAX_PACKET_LEN;
if ( haveSpace ) { if ( haveSpace ) {
mElems.add( newElem ); // Let's check for duplicates....
mLength += newElem.size(); boolean dupFound = false;
mFailCount = 0; // for now, we restart timer on new data for ( MsgElem elem : mElems ) {
if ( elem.isSameAs( newElem ) ) {
dupFound = true;
break;
}
}
if ( dupFound ) {
Log.d( TAG, "append(): dropping dupe: %s", newElem );
} else {
mElems.add( newElem );
mLength += newElem.size();
}
// for now, we restart timer on new data, even if a dupe
mFailCount = 0;
tellSomebody(); tellSomebody();
} }
} }

View file

@ -354,7 +354,7 @@ public class CommsTransport implements TransportProcs,
} }
@Override @Override
public int transportSend( byte[] buf, String msgNo, CommsAddrRec addr, public int transportSend( byte[] buf, String msgID, CommsAddrRec addr,
CommsConnType conType, int gameID ) CommsConnType conType, int gameID )
{ {
Log.d( TAG, "transportSend(len=%d, typ=%s)", buf.length, Log.d( TAG, "transportSend(len=%d, typ=%s)", buf.length,
@ -380,7 +380,7 @@ public class CommsTransport implements TransportProcs,
} }
} else { } else {
nSent = sendForAddr( m_context, addr, conType, m_rowid, nSent = sendForAddr( m_context, addr, conType, m_rowid,
gameID, buf ); gameID, buf, msgID );
} }
// Keep this while debugging why the resend_all that gets // Keep this while debugging why the resend_all that gets
@ -404,20 +404,20 @@ public class CommsTransport implements TransportProcs,
} }
@Override @Override
public boolean relayNoConnProc( byte[] buf, String msgNo, String relayID ) public boolean relayNoConnProc( byte[] buf, String msgID, String relayID )
{ {
Assert.assertTrue( TRANSPORT_DOES_NOCONN ); Assert.assertTrue( TRANSPORT_DOES_NOCONN );
int nSent = RelayService.sendNoConnPacket( m_context, m_rowid, int nSent = RelayService.sendNoConnPacket( m_context, m_rowid,
relayID, buf, msgNo ); relayID, buf, msgID );
boolean success = buf.length == nSent; boolean success = buf.length == nSent;
Log.d( TAG, "relayNoConnProc(msgNo=%s, len=%d) => %b", msgNo, Log.d( TAG, "relayNoConnProc(msgID=%s, len=%d) => %b", msgID,
buf.length, success ); buf.length, success );
return success; return success;
} }
private static int sendForAddr( Context context, CommsAddrRec addr, private static int sendForAddr( Context context, CommsAddrRec addr,
CommsConnType conType, long rowID, CommsConnType conType, long rowID,
int gameID, byte[] buf ) int gameID, byte[] buf, String msgID )
{ {
int nSent = -1; int nSent = -1;
switch ( conType ) { switch ( conType ) {
@ -430,7 +430,7 @@ public class CommsTransport implements TransportProcs,
gameID, buf ); gameID, buf );
break; break;
case COMMS_CONN_BT: case COMMS_CONN_BT:
nSent = BTService.sendPacket( context, buf, addr, gameID ); nSent = BTService.sendPacket( context, buf, msgID, addr, gameID );
break; break;
case COMMS_CONN_P2P: case COMMS_CONN_P2P:
nSent = WiDirService nSent = WiDirService

View file

@ -62,9 +62,10 @@ public class MultiMsgSink implements TransportProcs {
return RelayService.sendPacket( m_context, getRowID(), buf ); return RelayService.sendPacket( m_context, getRowID(), buf );
} }
public int sendViaBluetooth( byte[] buf, int gameID, CommsAddrRec addr ) public int sendViaBluetooth( byte[] buf, String msgID, int gameID,
CommsAddrRec addr )
{ {
return BTService.sendPacket( m_context, buf, addr, gameID ); return BTService.sendPacket( m_context, buf, msgID, addr, gameID );
} }
public int sendViaSMS( byte[] buf, int gameID, CommsAddrRec addr ) public int sendViaSMS( byte[] buf, int gameID, CommsAddrRec addr )
@ -88,7 +89,7 @@ public class MultiMsgSink implements TransportProcs {
public int getFlags() { return COMMS_XPORT_FLAGS_HASNOCONN; } public int getFlags() { return COMMS_XPORT_FLAGS_HASNOCONN; }
@Override @Override
public int transportSend( byte[] buf, String msgNo, CommsAddrRec addr, public int transportSend( byte[] buf, String msgID, CommsAddrRec addr,
CommsConnType typ, int gameID ) CommsConnType typ, int gameID )
{ {
int nSent = -1; int nSent = -1;
@ -97,7 +98,7 @@ public class MultiMsgSink implements TransportProcs {
nSent = sendViaRelay( buf, gameID ); nSent = sendViaRelay( buf, gameID );
break; break;
case COMMS_CONN_BT: case COMMS_CONN_BT:
nSent = sendViaBluetooth( buf, gameID, addr ); nSent = sendViaBluetooth( buf, msgID, gameID, addr );
break; break;
case COMMS_CONN_SMS: case COMMS_CONN_SMS:
nSent = sendViaSMS( buf, gameID, addr ); nSent = sendViaSMS( buf, gameID, addr );
@ -112,8 +113,8 @@ public class MultiMsgSink implements TransportProcs {
Log.i( TAG, "transportSend(): sent %d msgs for game %d/%x via %s", Log.i( TAG, "transportSend(): sent %d msgs for game %d/%x via %s",
nSent, gameID, gameID, typ.toString() ); nSent, gameID, gameID, typ.toString() );
if ( 0 < nSent ) { if ( 0 < nSent ) {
Log.d( TAG, "transportSend: adding %s", msgNo ); Log.d( TAG, "transportSend: adding %s", msgID );
m_sentSet.add( msgNo ); m_sentSet.add( msgID );
} }
return nSent; return nSent;