From 9e67dda5a91d3dfec77542ea5e503452fd27326c Mon Sep 17 00:00:00 2001 From: Eric House Date: Thu, 9 May 2013 21:53:54 -0700 Subject: [PATCH 01/10] make use of base-64 encoding runtime-configurable --- xwords4/relay/dbmgr.cpp | 5 +++-- xwords4/relay/xwrelay.conf_tmplate | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/xwords4/relay/dbmgr.cpp b/xwords4/relay/dbmgr.cpp index 75246fef1..71014f8e3 100644 --- a/xwords4/relay/dbmgr.cpp +++ b/xwords4/relay/dbmgr.cpp @@ -62,8 +62,9 @@ DBMgr::Get() DBMgr::DBMgr() { - logf( XW_LOGINFO, "%s called", __func__ ); - m_useB64 = false; + int tmp; + RelayConfigs::GetConfigs()->GetValueFor( "USE_B64", &tmp ); + m_useB64 = tmp != 0; pthread_key_create( &m_conn_key, destr_function ); diff --git a/xwords4/relay/xwrelay.conf_tmplate b/xwords4/relay/xwrelay.conf_tmplate index 27d79ec06..66d455a6b 100644 --- a/xwords4/relay/xwrelay.conf_tmplate +++ b/xwords4/relay/xwrelay.conf_tmplate @@ -63,3 +63,8 @@ LOGFILE_PATH=./xwrelay.log # Delay sending packets so devices/emulators on the same machine as # relay have a bit more natural experience # SEND_DELAY_MILLIS=500 + +# Use base64 encoding rather than PQescapeByteaConn for stored +# messages. The latter doesn't seem as reliable with newer psql +# servers. Anything but 0 is treated as true. +USE_B64=1 From b58fe30ecc1883c7b2466f512a0af14ca4a52128 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 14 May 2013 22:00:22 -0700 Subject: [PATCH 02/10] add synonyms to tile counts/values summary --- xwords4/common/dictnry.c | 2 +- xwords4/common/server.c | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/xwords4/common/dictnry.c b/xwords4/common/dictnry.c index b9412521a..86be38243 100644 --- a/xwords4/common/dictnry.c +++ b/xwords4/common/dictnry.c @@ -110,7 +110,7 @@ dict_getNextTileString( const DictionaryCtxt* dict, Tile tile, } else { cur += XP_STRLEN( cur ) + 1; XP_Bool isSpecial = dict_faceIsBitmap( dict, tile ); - if ( isSpecial ) { + if ( isSpecial || tile == dict->blankTile ) { const XP_UCHAR* facep = dict_getTileStringRaw( dict, tile ); if ( cur < dict->charEnds[(XP_U16)*facep] ) { result = cur; diff --git a/xwords4/common/server.c b/xwords4/common/server.c index aebb41ab2..98e47cc39 100644 --- a/xwords4/common/server.c +++ b/xwords4/common/server.c @@ -2856,17 +2856,27 @@ server_formatDictCounts( ServerCtxt* server, XWStreamCtxt* stream, nChars = dict_numTileFaces( dict ); for ( tile = 0, nPrinted = 0; ; ) { - XP_UCHAR buf[24]; + XP_UCHAR buf[128]; XP_U16 count, value; count = dict_numTiles( dict, tile ); if ( count > 0 ) { - const XP_UCHAR* face = dict_getTileString( dict, tile ); + const XP_UCHAR* face = NULL; + XP_UCHAR faces[48] = {0}; + XP_U16 len = 0; + for ( ; ; ) { + face = dict_getNextTileString( dict, tile, face ); + if ( !face ) { + break; + } + const XP_UCHAR* fmt = len == 0? "%s" : ",%s"; + len += XP_SNPRINTF( faces + len, sizeof(faces) - len, fmt, face ); + } value = dict_getTileValue( dict, tile ); XP_SNPRINTF( buf, sizeof(buf), (XP_UCHAR*)"%s: %d/%d", - face, count, value ); + faces, count, value ); stream_catString( stream, buf ); } From 2a2157b504e90fea291ec053d1a5e28e973dca01 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 21 May 2013 06:58:53 -0700 Subject: [PATCH 03/10] add DICTNOTE --- xwords4/dawg/Portuguese/Makefile.ptbr4422 | 1 + 1 file changed, 1 insertion(+) diff --git a/xwords4/dawg/Portuguese/Makefile.ptbr4422 b/xwords4/dawg/Portuguese/Makefile.ptbr4422 index d7c8ae6a6..fcb87a777 100644 --- a/xwords4/dawg/Portuguese/Makefile.ptbr4422 +++ b/xwords4/dawg/Portuguese/Makefile.ptbr4422 @@ -19,6 +19,7 @@ XWLANG = PTBR4422 LANGCODE = pt_PT ENC = UTF-8 +DICTNOTE = "Lista com as 4422 palavras mais frequentes nas legendas em português brasileiro do site www.opensubtitles.org." TARGET_TYPE ?= WINCE From 9b5607d8295ffcfcef9ad2470b0def83b59fab7f Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 21 May 2013 19:35:34 -0700 Subject: [PATCH 04/10] send message along with GCM notification that ... there's a message. Should eventually allow GCM-aware clients to skip connecting on launch, and for now to make them a tiny bit snappier. --- xwords4/relay/scripts/gcm_loop.py | 60 +++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/xwords4/relay/scripts/gcm_loop.py b/xwords4/relay/scripts/gcm_loop.py index 11b9b59de..1914d6367 100755 --- a/xwords4/relay/scripts/gcm_loop.py +++ b/xwords4/relay/scripts/gcm_loop.py @@ -32,6 +32,7 @@ g_con = None g_sent = None g_debug = False g_skipSend = False # for debugging +g_columns = [ 'id', 'devid', 'connname', 'hid', 'msg64' ] DEVTYPE_GCM = 3 # 3 == GCM LINE_LEN = 76 @@ -55,19 +56,41 @@ def init(): def getPendingMsgs( con, typ ): cur = con.cursor() - query = """SELECT id, devid FROM msgs + query = """SELECT %s FROM msgs WHERE devid IN (SELECT id FROM devices WHERE devtype=%d and NOT unreg) AND NOT connname IN (SELECT connname FROM games WHERE dead); """ - cur.execute(query % typ) - result = cur.fetchall() + cur.execute(query % (",".join( g_columns ), typ)) + + result = [] + for row in cur: + rowObj = {} + for ii in range( len( g_columns ) ): + rowObj[g_columns[ii]] = row[ii] + result.append( rowObj ) if g_debug: print "getPendingMsgs=>", result return result +def deleteMsgs( con, msgIDs ): + if 0 < len( msgIDs ): + query = "DELETE from msgs where id in (%s);" % ",".join(msgIDs) + try: + cur = con.cursor() + cur.execute(query) + con.commit() + except psycopg2.DatabaseError, e: + print 'Error %s' % e + except Exception as inst: + print "failed to execute", query + print type(inst) + print inst.args + print inst + def unregister( gcmid ): global g_con print "unregister(", gcmid, ")" query = "UPDATE devices SET unreg=TRUE WHERE devid = '%s' and devtype = 3" % gcmid g_con.cursor().execute( query ) + g_con.commit() def asGCMIds(con, devids, typ): cur = con.cursor() @@ -76,10 +99,15 @@ def asGCMIds(con, devids, typ): cur.execute( query ) return [elem[0] for elem in cur.fetchall()] -def notifyGCM( devids, typ ): +def notifyGCM( devids, typ, msg, connname, hid ): + success = False if typ == DEVTYPE_GCM: + connname = "%s/%d" % (connname, hid) values = { - 'data' : { 'getMoves': True, }, + 'data' : { 'getMoves': True, + 'msg64': msg, + 'connname': connname, + }, 'registration_ids': devids, } params = json.dumps( values ) @@ -92,11 +120,13 @@ def notifyGCM( devids, typ ): if 'success' in asJson and 'failure' in asJson and len(devids) == asJson['success'] and 0 == asJson['failure']: print "OK" + success = True else: print "Errors: " print response else: print "not sending to", len(devids), "devices because typ ==", typ + return success def shouldSend(val): return val == 1 @@ -113,14 +143,14 @@ def targetsAfterBackoff( msgs ): global g_sent targets = {} for row in msgs: - msgid = row[0] - devid = row[1] + msgid = row['id'] + devid = row['devid'] if not msgid in g_sent: g_sent[msgid] = 0 g_sent[msgid] += 1 if shouldSend( g_sent[msgid] ): - targets[devid] = True - return targets.keys() + targets[devid] = row + return targets # devids is an array of (msgid, devid) tuples def pruneSent( devids ): @@ -129,7 +159,7 @@ def pruneSent( devids ): lenBefore = len(g_sent) msgids = [] for row in devids: - msgids.append(row[0]) + msgids.append(row['id']) for msgid in g_sent.keys(): if not msgid in msgids: del g_sent[msgid] @@ -187,8 +217,16 @@ def main(): emptyCount = 0 print strftime("%Y-%m-%d %H:%M:%S", time.localtime()), print "devices needing notification:", targets, '=>', - notifyGCM( asGCMIds( g_con, targets, typ ), typ ) + toDelete = [] + for devid in targets.keys(): + target = targets[devid] + connname = target['connname'] + hid = target['hid'] + msg = target['msg64'] + if notifyGCM( asGCMIds( g_con, [devid], typ ), typ, msg, connname, hid ): + toDelete.append( str(target['id']) ) pruneSent( devids ) + deleteMsgs( g_con, toDelete ) elif g_debug: print "no targets after backoff" else: emptyCount += 1 From 7d81083d7d8021474f5e327dbc9cc8d54766434b Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 22 May 2013 05:39:20 -0700 Subject: [PATCH 05/10] send using old message format to old clients, new to new --- xwords4/relay/scripts/gcm_loop.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/xwords4/relay/scripts/gcm_loop.py b/xwords4/relay/scripts/gcm_loop.py index 1914d6367..22f2c5e3d 100755 --- a/xwords4/relay/scripts/gcm_loop.py +++ b/xwords4/relay/scripts/gcm_loop.py @@ -70,6 +70,16 @@ def getPendingMsgs( con, typ ): if g_debug: print "getPendingMsgs=>", result return result +def addClntVers( con, rows ): + query = """select clntVers[%s] from games where connname = '%s';""" + cur = con.cursor() + for row in rows: + cur.execute( query % (row['hid'], row['connname'])) + if cur.rowcount == 1: row['clntVers'] = cur.fetchone()[0] + else: print "bad row count: ", cur.rowcount + con.commit() + return rows + def deleteMsgs( con, msgIDs ): if 0 < len( msgIDs ): query = "DELETE from msgs where id in (%s);" % ",".join(msgIDs) @@ -99,18 +109,22 @@ def asGCMIds(con, devids, typ): cur.execute( query ) return [elem[0] for elem in cur.fetchall()] -def notifyGCM( devids, typ, msg, connname, hid ): +def notifyGCM( target, devids, typ, msg, connname, hid ): success = False if typ == DEVTYPE_GCM: - connname = "%s/%d" % (connname, hid) + if 3 <= target['clntVers']: + connname = "%s/%d" % (connname, hid) + data = { 'msg64': msg, + 'connname': connname, + } + else: + data = { 'getMoves': True, } values = { - 'data' : { 'getMoves': True, - 'msg64': msg, - 'connname': connname, - }, + 'data' : data, 'registration_ids': devids, } params = json.dumps( values ) + req = urllib2.Request("https://android.googleapis.com/gcm/send", params ) req.add_header( 'Content-Type' , 'application/x-www-form-urlencoded;charset=UTF-8' ) req.add_header( 'Authorization' , 'key=' + mykey.myKey ) @@ -211,6 +225,7 @@ def main(): if g_debug: print devids = getPendingMsgs( g_con, typ ) if 0 < len(devids): + devids = addClntVers( g_con, devids ) targets = targetsAfterBackoff( devids ) if 0 < len(targets): if 0 < emptyCount: print "" @@ -223,7 +238,9 @@ def main(): connname = target['connname'] hid = target['hid'] msg = target['msg64'] - if notifyGCM( asGCMIds( g_con, [devid], typ ), typ, msg, connname, hid ): + if notifyGCM( target, asGCMIds( g_con, [devid], typ ), \ + typ, msg, connname, hid ) \ + and 3 <= target['clntVers']: toDelete.append( str(target['id']) ) pruneSent( devids ) deleteMsgs( g_con, toDelete ) From 11709b21bd6b74250e9920eab6a4b937a34bde12 Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 22 May 2013 05:51:33 -0700 Subject: [PATCH 06/10] remove redundant parameters --- xwords4/relay/scripts/gcm_loop.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/xwords4/relay/scripts/gcm_loop.py b/xwords4/relay/scripts/gcm_loop.py index 22f2c5e3d..e16f0eadc 100755 --- a/xwords4/relay/scripts/gcm_loop.py +++ b/xwords4/relay/scripts/gcm_loop.py @@ -109,12 +109,12 @@ def asGCMIds(con, devids, typ): cur.execute( query ) return [elem[0] for elem in cur.fetchall()] -def notifyGCM( target, devids, typ, msg, connname, hid ): +def notifyGCM( devids, typ, target ): success = False if typ == DEVTYPE_GCM: if 3 <= target['clntVers']: - connname = "%s/%d" % (connname, hid) - data = { 'msg64': msg, + connname = "%s/%d" % (target['connname'], target['hid']) + data = { 'msg64': target['msg64'], 'connname': connname, } else: @@ -235,12 +235,8 @@ def main(): toDelete = [] for devid in targets.keys(): target = targets[devid] - connname = target['connname'] - hid = target['hid'] - msg = target['msg64'] - if notifyGCM( target, asGCMIds( g_con, [devid], typ ), \ - typ, msg, connname, hid ) \ - and 3 <= target['clntVers']: + if notifyGCM( asGCMIds(g_con, [devid], typ), typ, target )\ + and 3 <= target['clntVers']: toDelete.append( str(target['id']) ) pruneSent( devids ) deleteMsgs( g_con, toDelete ) From 78b3a9192525ada290a6fd57571b7b8defd65743 Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 22 May 2013 06:40:02 -0700 Subject: [PATCH 07/10] format: send array of message bodies rather than just one --- xwords4/relay/scripts/gcm_loop.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xwords4/relay/scripts/gcm_loop.py b/xwords4/relay/scripts/gcm_loop.py index e16f0eadc..e93378f8f 100755 --- a/xwords4/relay/scripts/gcm_loop.py +++ b/xwords4/relay/scripts/gcm_loop.py @@ -114,7 +114,7 @@ def notifyGCM( devids, typ, target ): if typ == DEVTYPE_GCM: if 3 <= target['clntVers']: connname = "%s/%d" % (target['connname'], target['hid']) - data = { 'msg64': target['msg64'], + data = { 'msgs64': [ target['msg64'] ], 'connname': connname, } else: From 076b1b7543d8a9633d0b6dcc499bcac38513e823 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 21 May 2013 06:53:20 -0700 Subject: [PATCH 08/10] remove logging --- .../XWords4/src/org/eehouse/android/xw4/ExpiringTextView.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/ExpiringTextView.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/ExpiringTextView.java index 8bc674dc8..a122ee817 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/ExpiringTextView.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/ExpiringTextView.java @@ -49,8 +49,6 @@ class ExpiringTextView extends TextView { { if ( null != m_delegate ) { m_delegate.configure( haveTurn, haveTurnLocal, startSecs ); - } else { - DbgUtils.logf( "m_delegate null; skipping" ); } } From 120748416b7fc1640604f9496461ff3c5fc0f3f2 Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 22 May 2013 06:15:07 -0700 Subject: [PATCH 09/10] handle GCM messages containing data, changing clientVers so server knows we can. And send to relay in AsyncTask rather than UI thread. --- xwords4/android/XWords4/jni/Android.mk | 2 +- .../eehouse/android/xw4/GCMIntentService.java | 9 + .../org/eehouse/android/xw4/RelayService.java | 155 +++++++++++++----- 3 files changed, 120 insertions(+), 46 deletions(-) diff --git a/xwords4/android/XWords4/jni/Android.mk b/xwords4/android/XWords4/jni/Android.mk index 67a4961aa..2c72a0f92 100644 --- a/xwords4/android/XWords4/jni/Android.mk +++ b/xwords4/android/XWords4/jni/Android.mk @@ -36,7 +36,7 @@ local_DEFINES += \ -DHASH_STREAM \ -DXWFEATURE_BASE64 \ -DXWFEATURE_DEVID \ - -DINITIAL_CLIENT_VERS=2 \ + -DINITIAL_CLIENT_VERS=3 \ -DRELAY_ROOM_DEFAULT=\"\" \ -D__LITTLE_ENDIAN \ diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java index 532e70329..23285a1fa 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java @@ -62,6 +62,15 @@ public class GCMIntentService extends GCMBaseIntentService { if ( null != value && Boolean.parseBoolean( value ) ) { RelayReceiver.RestartTimer( context, true ); } + + value = intent.getStringExtra( "msg64" ); + if ( null != value ) { + String connname = intent.getStringExtra( "connname" ); + if ( null != connname ) { + RelayService.processMsg( context, connname, value ); + } + } + value = intent.getStringExtra( "checkUpdates" ); if ( null != value && Boolean.parseBoolean( value ) ) { UpdateCheckReceiver.checkVersions( context, true ); 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 bc4d2d179..0c2afed9f 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java @@ -23,6 +23,7 @@ package org.eehouse.android.xw4; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.os.AsyncTask; import android.os.IBinder; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -32,11 +33,34 @@ import java.util.HashMap; import java.util.Iterator; import org.eehouse.android.xw4.jni.GameSummary; +import org.eehouse.android.xw4.jni.XwJNI; public class RelayService extends Service { private static final int MAX_SEND = 1024; private static final int MAX_BUF = MAX_SEND - 2; + private static final String CMD_STR = "CMD"; + private static final int PROCESS_MSG = 1; + private static final String MSG = "MSG"; + private static final String RELAY_ID = "RELAY_ID"; + + public static void processMsg( Context context, String relayId, + String msg64 ) + { + byte[] msg = XwJNI.base64Decode( msg64 ); + Intent intent = getIntentTo( context, PROCESS_MSG ) + .putExtra( MSG, msg ) + .putExtra( RELAY_ID, relayId ); + context.startService( intent ); + } + + private static Intent getIntentTo( Context context, int cmd ) + { + Intent intent = new Intent( context, RelayService.class ); + intent.putExtra( CMD_STR, cmd ); + return intent; + } + @Override public void onCreate() { @@ -57,6 +81,26 @@ public class RelayService extends Service { return null; } + @Override + public int onStartCommand( Intent intent, int flags, int startId ) + { + int cmd = intent.getIntExtra( CMD_STR, -1 ); + switch( cmd ) { + case PROCESS_MSG: + String[] relayIDs = new String[1]; + relayIDs[0] = intent.getStringExtra( RELAY_ID ); + long[] rowIDs = DBUtils.getRowIDsFor( this, relayIDs[0] ); + if ( 0 < rowIDs.length ) { + byte[][][] msgs = new byte[1][1][1]; + msgs[0][0] = intent.getByteArrayExtra( MSG ); + process( msgs, rowIDs, relayIDs ); + } + break; + } + stopSelf( startId ); + return Service.START_NOT_STICKY; + } + private void setupNotification( String[] relayIDs ) { for ( String relayID : relayIDs ) { @@ -80,67 +124,80 @@ public class RelayService extends Service { long[][] rowIDss = new long[1][]; String[] relayIDs = DBUtils.getRelayIDs( this, rowIDss ); if ( null != relayIDs && 0 < relayIDs.length ) { - long[] rowIDs = rowIDss[0]; byte[][][] msgs = NetUtils.queryRelay( this, relayIDs ); - - if ( null != msgs ) { - RelayMsgSink sink = new RelayMsgSink(); - int nameCount = relayIDs.length; - ArrayList idsWMsgs = - new ArrayList( nameCount ); - for ( int ii = 0; ii < nameCount; ++ii ) { - byte[][] forOne = msgs[ii]; - // if game has messages, open it and feed 'em - // to it. - if ( null == forOne ) { - // Nothing for this relayID - } else if ( BoardActivity.feedMessages( rowIDs[ii], forOne ) - || GameUtils.feedMessages( this, rowIDs[ii], - forOne, null, - sink ) ) { - idsWMsgs.add( relayIDs[ii] ); - } else { - DbgUtils.logf( "dropping message for %s (rowid %d)", - relayIDs[ii], rowIDs[ii] ); - } - } - if ( 0 < idsWMsgs.size() ) { - String[] tmp = new String[idsWMsgs.size()]; - idsWMsgs.toArray( tmp ); - setupNotification( tmp ); - } - sink.send( this ); - } + process( msgs, rowIDss[0], relayIDs ); } } - private static void sendToRelay( Context context, - HashMap> msgHash ) + private void process( byte[][][] msgs, long[] rowIDs, String[] relayIDs ) { - // format: total msg lenth: 2 - // number-of-relayIDs: 2 - // for-each-relayid: relayid + '\n': varies - // message count: 1 - // for-each-message: length: 2 - // message: varies + if ( null != msgs ) { + RelayMsgSink sink = new RelayMsgSink(); + int nameCount = relayIDs.length; + ArrayList idsWMsgs = new ArrayList( nameCount ); - if ( null != msgHash ) { + for ( int ii = 0; ii < nameCount; ++ii ) { + byte[][] forOne = msgs[ii]; + + // if game has messages, open it and feed 'em to it. + if ( null == forOne ) { + // Nothing for this relayID + } else if ( BoardActivity.feedMessages( rowIDs[ii], forOne ) + || GameUtils.feedMessages( this, rowIDs[ii], + forOne, null, + sink ) ) { + idsWMsgs.add( relayIDs[ii] ); + } else { + DbgUtils.logf( "message for %s (rowid %d) not consumed", + relayIDs[ii], rowIDs[ii] ); + } + } + if ( 0 < idsWMsgs.size() ) { + String[] tmp = new String[idsWMsgs.size()]; + idsWMsgs.toArray( tmp ); + setupNotification( tmp ); + } + sink.send( this ); + } + } + + private static class AsyncSender extends AsyncTask { + private Context m_context; + private HashMap> m_msgHash; + + public AsyncSender( Context context, + HashMap> msgHash ) + { + m_context = context; + m_msgHash = msgHash; + } + + @Override + protected Void doInBackground( Void... ignored ) + { + // format: total msg lenth: 2 + // number-of-relayIDs: 2 + // for-each-relayid: relayid + '\n': varies + // message count: 1 + // for-each-message: length: 2 + // message: varies + + // Build up a buffer containing everything but the total + // message length and number of relayIDs in the message. try { - // Build up a buffer containing everything but the total - // message length and number of relayIDs in the message. ByteArrayOutputStream store = new ByteArrayOutputStream( MAX_BUF ); // mem DataOutputStream outBuf = new DataOutputStream( store ); int msgLen = 4; // relayID count + protocol stuff int nRelayIDs = 0; - Iterator iter = msgHash.keySet().iterator(); + Iterator iter = m_msgHash.keySet().iterator(); while ( iter.hasNext() ) { String relayID = iter.next(); int thisLen = 1 + relayID.length(); // string and '\n' thisLen += 2; // message count - ArrayList msgs = msgHash.get( relayID ); + ArrayList msgs = m_msgHash.get( relayID ); for ( byte[] msg : msgs ) { thisLen += 2 + msg.length; } @@ -161,10 +218,9 @@ public class RelayService extends Service { } msgLen += thisLen; } - // Now open a real socket, write size and proto, and // copy in the formatted buffer - Socket socket = NetUtils.makeProxySocket( context, 8000 ); + Socket socket = NetUtils.makeProxySocket( m_context, 8000 ); if ( null != socket ) { DataOutputStream outStream = new DataOutputStream( socket.getOutputStream() ); @@ -179,6 +235,15 @@ public class RelayService extends Service { } catch ( java.io.IOException ioe ) { DbgUtils.loge( ioe ); } + return null; + } // doInBackground + } + + private static void sendToRelay( Context context, + HashMap> msgHash ) + { + if ( null != msgHash ) { + new AsyncSender( context, msgHash ).execute(); } else { DbgUtils.logf( "sendToRelay: null msgs" ); } From 2e30ccd4c6a61178f943b92092576b040cf75ee4 Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 22 May 2013 06:45:34 -0700 Subject: [PATCH 10/10] expect array of message bodies rather than just one --- .../eehouse/android/xw4/GCMIntentService.java | 14 +++++++++-- .../org/eehouse/android/xw4/RelayService.java | 24 +++++++++++-------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java index 23285a1fa..99945ca0a 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java @@ -25,6 +25,7 @@ import android.content.Context; import android.content.Intent; import com.google.android.gcm.GCMBaseIntentService; import com.google.android.gcm.GCMRegistrar; +import org.json.JSONArray; public class GCMIntentService extends GCMBaseIntentService { @@ -63,11 +64,20 @@ public class GCMIntentService extends GCMBaseIntentService { RelayReceiver.RestartTimer( context, true ); } - value = intent.getStringExtra( "msg64" ); + value = intent.getStringExtra( "msgs64" ); if ( null != value ) { String connname = intent.getStringExtra( "connname" ); if ( null != connname ) { - RelayService.processMsg( context, connname, value ); + try { + JSONArray msgs64 = new JSONArray( value ); + String[] strs64 = new String[msgs64.length()]; + for ( int ii = 0; ii < strs64.length; ++ii ) { + strs64[ii] = msgs64.optString(ii); + } + RelayService.processMsgs( context, connname, strs64 ); + } catch (org.json.JSONException jse ) { + DbgUtils.loge( jse ); + } } } 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 0c2afed9f..8a97dc766 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java @@ -40,16 +40,15 @@ public class RelayService extends Service { private static final int MAX_BUF = MAX_SEND - 2; private static final String CMD_STR = "CMD"; - private static final int PROCESS_MSG = 1; - private static final String MSG = "MSG"; + private static final int PROCESS_MSGS = 1; + private static final String MSGS = "MSGS"; private static final String RELAY_ID = "RELAY_ID"; - public static void processMsg( Context context, String relayId, - String msg64 ) + public static void processMsgs( Context context, String relayId, + String[] msgs64 ) { - byte[] msg = XwJNI.base64Decode( msg64 ); - Intent intent = getIntentTo( context, PROCESS_MSG ) - .putExtra( MSG, msg ) + Intent intent = getIntentTo( context, PROCESS_MSGS ) + .putExtra( MSGS, msgs64 ) .putExtra( RELAY_ID, relayId ); context.startService( intent ); } @@ -86,13 +85,18 @@ public class RelayService extends Service { { int cmd = intent.getIntExtra( CMD_STR, -1 ); switch( cmd ) { - case PROCESS_MSG: + case PROCESS_MSGS: String[] relayIDs = new String[1]; relayIDs[0] = intent.getStringExtra( RELAY_ID ); long[] rowIDs = DBUtils.getRowIDsFor( this, relayIDs[0] ); if ( 0 < rowIDs.length ) { - byte[][][] msgs = new byte[1][1][1]; - msgs[0][0] = intent.getByteArrayExtra( MSG ); + String[] msgs64 = intent.getStringArrayExtra( MSGS ); + int count = msgs64.length; + + byte[][][] msgs = new byte[1][count][]; + for ( int ii = 0; ii < count; ++ii ) { + msgs[0][ii] = XwJNI.base64Decode( msgs64[ii] ); + } process( msgs, rowIDs, relayIDs ); } break;