astropop / gcm

Automatically exported from code.google.com/p/gcm
Apache License 2.0
0 stars 0 forks source link

Google Cloud Messaging (GCM) duplicates and loses some messages #50

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Google Cloud Messaging service is higly unreliable under some circumstances: 
when the target device temporarily loses connectivity, some messages are lost 
and others are sent two times from the GCM server to the device. I tested this 
behaviour using this simple server, written in python, that establish an XMPP 
connection to Google's server and send a GCM message to a (previously 
registered) device every 5 seconds:

#!/usr/bin/python
import sys, json, string, xmpp, time

SERVER = 'gcm.googleapis.com'
PORT = 5235
USERNAME = "Your GCM Sender Id"
PASSWORD = "Your API Key"
REGISTRATION_ID = "Registration Id of the target device"

unacked_messages_quota = 100
send_queue = []

def send(json_dict):
  template = ("<message><gcm xmlns='google:mobile:data'>{1}</gcm></message>")
  client.send(xmpp.protocol.Message(
      node=template.format(client.Bind.bound[0], json.dumps(json_dict))))

def flush_queued_messages():
  global unacked_messages_quota
  while len(send_queue) and unacked_messages_quota > 0:
    send(send_queue.pop(0))
    unacked_messages_quota -= 1

client = xmpp.Client('gcm.googleapis.com', debug=['socket'])
client.connect(server=(SERVER,PORT), secure=1, use_srv=False)
auth = client.auth(USERNAME, PASSWORD)
if not auth:
  print 'Authentication failed!'
  sys.exit(1)

last = int(round(time.time()))
count = 0
while True:
  client.Process(1)
  flush_queued_messages()
  now = int(round(time.time()))
  elapsed = now - last
  if (elapsed > 5):
    count += 1
    last = int(round(time.time()))
    print 'Sending GCM message with message_id: ' + 'id-' + str(count)
    send_queue.append({'to': REGISTRATION_ID,
                       'message_id': 'id-' + str(count),
                       'data': {'message_destination': 'test',
                                'message_id': 'id-' + str(count)},
                       'delivery_receipt_requested': True})

On the target device (a Nexus 5 with Android 5.0.1) I installed a client app 
that register for GCM and receive the messages with a BroadcastReceiver:

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("GCM Demo", "Received GCM message with message_id: " + intent.getExtras().getString("message_id"));

        // Release the wake lock provided by the WakefulBroadcastReceiver.
        GcmBroadcastReceiver.completeWakefulIntent(intent);
    }
}

Now I execute the python server and at some point simulate a connectivity loss 
on the device (enabling airplane mode) for some seconds. The logacat on the 
target device shows:

--- Start the python server ---
01-16 12:03:04.373 I/GCM Demo( 8667): Received GCM with id: id-1
01-16 12:03:10.380 I/GCM Demo( 8667): Received GCM with id: id-2
01-16 12:03:16.544 I/GCM Demo( 8667): Received GCM with id: id-3
--- Device disconnected (airplane mode enabled) ---
[...]
--- Device reconnected (airplane mode disabled) ---
01-16 12:04:09.993 I/GCM Demo(11376): Received GCM with id: id-1  <-- duplicate
01-16 12:04:09.996 I/GCM Demo(11376): Received GCM with id: id-2  <-- duplicate
01-16 12:04:10.002 I/GCM Demo(11376): Received GCM with id: id-3  <-- duplicate
01-16 12:04:10.008 I/GCM Demo(11376): Received GCM with id: id-4
01-16 12:04:10.013 I/GCM Demo(11376): Received GCM with id: id-5
01-16 12:04:10.018 I/GCM Demo(11376): Received GCM with id: id-6
01-16 12:04:10.138 I/GCM Demo(11376): Received GCM with id: id-7
01-16 12:04:10.173 I/GCM Demo(11376): Received GCM with id: id-8
01-16 12:04:10.189 I/GCM Demo(11376): Received GCM with id: id-9
                                                                  <-- id-10 missing!
                                                                  <-- id-11 missing!
01-16 12:04:10.210 I/GCM Demo(11376): Received GCM with id: id-12
01-16 12:04:36.161 I/GCM Demo(11376): Received GCM with id: id-12 <-- duplicate
01-16 12:04:36.183 I/GCM Demo(11376): Received GCM with id: id-13
                                                                  <-- id-14 missing!
                                                                  <-- id-15 missing!
                                                                  <-- id-16 missing!
                                                                  <-- id-17 missing!
                                                                  <-- id-18 missing!
01-16 12:04:52.415 I/GCM Demo(11376): Received GCM with id: id-19
01-16 12:04:58.401 I/GCM Demo(11376): Received GCM with id: id-20
--- Stop the python server ---

As you can see, after the device reconnect to the internet, Google resend 
duplicate messages for ids 1,2 and 3 (and after some time for the id 12 too), 
and the messages with ids 10,11,14,15,16,17,18 are never delivered to the 
device. Note that when the python server send the messages to Google's server, 
it immediately receive an ACK for all the 20 messages, so all the messages are 
correctly sent to Google GCM infrastucture.

Original issue reported on code.google.com by kungu...@gmail.com on 16 Jan 2015 at 11:28