python-2.7herokugoogle-cloud-messagingxmppxmpppy

why my XMPP client resend messages?


i have a XMPP cliente on heroku and it works with Google Cloud Messaging but i have a bad behavior on my app i have cheked my code many times but i have not found any mistake, but some messages is been resent,the problem is not for Acknowledging of my messages, because i am Acknowledging each message and i am not receiving any nack message from GCM server, so i can not know what is the problem

i would appreciate for any help

this is my code

SERVER = 'gcm.googleapis.com'
PORT = 5235
USERNAME = "secret"
PASSWORD = "secret"
N_TIMER=40 
EXP_TIMER=1 
unacked_messages_quota = 100
send_queue = [] 
error_send_queue = []   
lock=threading.Lock()

def unique_id():    
    return  str(uuid.uuid4().hex)

@synchronized
def message_callback(session, message):  
    global unacked_messages_quota   
    gcm = message.getTags('gcm')
    if gcm:
        gcm_json = gcm[0].getData()
        msg = json.loads(gcm_json)
    if not msg.has_key('message_type'):     
      # Acknowledge the incoming message immediately.           
      send({'to': msg['from'],
            'message_type': 'ack',
            'message_id': msg['message_id']})
      # Queue a response back to the server.
      if msg.has_key('from'):
        # Send a response back to the app that sent the upstream message.
        try:            
            msg['data']['idCel'] = msg['from']
            payloadObj= payload("command", msg['data']['command'] , msg['data'])
            rpc = RpcClient()       
            response = rpc.call(payloadObj)     
            if  'response' in response and response['response'] == 'ok':                    
                pass
            elif  response['type'] == 'response'  :             
                send_queue.append({'to': msg['from'],
                                    'priority':'high',
                                    'delay_while_idle':True,                                                        
                                   'message_id': unique_id(),
                                   'data': {'response': response['response'],'type': 'response'}
                                   })  
            else:
                send_queue.append({'to': msg['from'],                                                          
                                   'message_id': unique_id(),
                                   'data': {'error': response['error'],'type': 'error'}})                   
        except Exception as e:              
             traceback.print_exc()
             print str(e)                   

    elif msg['message_type'] == 'ack' or msg['message_type'] == 'nack':     
        if  msg['message_type'] == 'nack':
            error_send_queue.append(
                {'to': msg['from'],
                'message_type': 'ack',
                'message_id': msg['message_id']})           
        unacked_messages_quota += 1     

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

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         

def flush_queued_errors_messages():
    lock.acquire()  
    global unacked_messages_quota   
    global error_send_queue
    global EXP_TIMER    
    while len(error_send_queue) and unacked_messages_quota > 0:         
        send(error_send_queue.pop(0))
        unacked_messages_quota -= 1 
        time.sleep( (2**EXP_TIMER) )        
        EXP_TIMER += 1
    EXP_TIMER=1 
    lock.release()

client = xmpp.Client('gcm.googleapis.com',debug=['always', 'roster'],
            port=int(os.environ.get("PORT")))                             
client.connect(server=(SERVER,PORT), secure=1, use_srv=False)           
auth = client.auth(USERNAME, PASSWORD)
if not auth:
  print 'Authentication failed!'
  sys.exit(1)   
client.RegisterHandler('message', message_callback)
t1 = threading.Thread(target=flush_queued_errors_messages)      
while True:     
    client.Process(1)
    flush_queued_messages()     
    if N_TIMER == 0:
        client.send(" ")    
        N_TIMER = 40        
        if not t1.isAlive():            
            t1 = threading.Thread(target=flush_queued_errors_messages)  
            t1.start()          
    N_TIMER -= 1    

Solution

  • I could know my real problem, the problem was not from my code but the problem was from GCM servers.

    Here is the explication.