9
votes

I am using node-xmpp to connect to google gcm ccs servers. I followed the from gcm google groups to connect. Now i need to send a downstream message whenever i receive a message from my redis subscriber(i subscribed to a redis channel redis node package). My code is as follows

var gearmanode = require('gearmanode');
var redis = require("redis");
var xmpp = require('node-xmpp');

var gearJob;
var redisSubChan = 'test_channel';
var gearmanJobName = 'reverse';
var jobPayload;
var redisClient;
var xmppClient;
var gearClient;

gearClient = gearmanode.client();

var options = {
    type: 'client',
    jid: '[email protected]',
    password: 'myserverkey',
    port: 5235,
    host: 'gcm.googleapis.com',
    legacySSL: true,
    preferredSaslMechanism: 'PLAIN'
};

console.log('creating xmpp app');

xmppClient = new xmpp.Client(options);

xmppClient.connection.socket.setTimeout(0)
xmppClient.connection.socket.setKeepAlive(true, 10000)

redisClient = redis.createClient();
redisClient.subscribe(redisSubChan);

redisClient.on("message", function(channel, message) {
    console.log('received message');
    console.log(message);
    message = JSON.parse(message);
    //send the messages to google ccs server via xmpp
    var payload = {
        "to": message.to,
        "message_id": message.message_id,
        "data": message.data,
        "time_to_live": message.time_to_live,
        "delay_while_idle": message.delay_while_idle
    };
    var jsonPayload = JSON.stringify(payload);
    console.log(jsonPayload);

    var ackToDevice = new xmpp.Element('message', {'id': ''}).c('gcm', {xmlns: 'google:mobile:data'}).t(jsonPayload);
    console.log('prepared message');
    console.log(ackToDevice.root().toString());
    xmppClient.send(ackToDevice);
    console.log('sent!!!');
});

xmppClient.on('online', function() {
    console.log("online");
});

xmppClient.on('connection', function() {
    console.log('online');
});

xmppClient.on('stanza',
        function(stanza) {
            if (stanza.is('message') && stanza.attrs.type !== 'error') {
                // Best to ignore an error
                console.log("Message received");
                //Message format as per here: https://developer.android.com/google/gcm/ccs.html#upstream
                var messageData = JSON.parse(stanza.getChildText("gcm"));

                if (messageData && messageData.message_type != "ack" && messageData.message_type != "nack") {

                    var ackMsg = new xmpp.Element('message', {'id': ''}).c('gcm', {xmlns: 'google:mobile:data'}).t(JSON.stringify({
                        "to": messageData.from,
                        "message_id": messageData.message_id,
                        "message_type": "ack"
                    }));
                    //send back the ack.
                    xmppClient.send(ackMsg);
                    console.log("Sent ack");
                    //receive messages from ccs and give it to PHP workers
                    gearClient.submitJob(gearmanJobName, JSON.stringify(messageData), {background: true});

                } else {
                    //Need to do something more here for a nack.
                    console.log("message was an ack or nack...discarding");
                }

            } else {
                console.log("error");
                console.log(stanza);
            }

        });

xmppClient.on('authenticate', function(opts, cb) {
    console.log('AUTH' + opts.jid + ' -> ' + opts.password);
    cb(null);
});

xmppClient.on('error', function(e) {
    console.log("Error occured:");
    console.error(e);
    console.error(e.children);
});

I am able to receive the messages from ccs server but can not send the downstream message from redis on message callback.

I get the following error

error
{ name: 'message',
  parent: null,
  attrs: 
   { id: '',
     type: 'error',
     to: '[email protected]/8DF23ED7',
     'xmlns:stream': 'http://etherx.jabber.org/streams' },
  children: 
   [ { name: 'gcm',
       parent: [Circular],
       attrs: [Object],
       children: [Object] },
     { name: 'error',
       parent: [Circular],
       attrs: [Object],
       children: [Object] } ] }

I tried to print(followed node xmpp) the xmpp stanza before sending and its same

//log of my message

<message id=""><gcm xmlns="google:mobile:data">{"to":"APA91bHIGZcbePZ-f1jSyWQkBAJMHorHJiwgtN1GWITzcHf6uyVOZ3k7AasUiB-vBix32ucSypin3xDTYmoxqSc_ZmTDTuKjuDQ8BPQLpC41SqYRimm-hn34ZjSAF4uQO0OP1LSbqUxjh2WF0K5n4KyD3-Vn8ghASQ","message_id":84,"data":{"test":"sample data to send"},"time_to_live":0,"delay_while_idle":false}</gcm></message>

as they mentioned in documentation(Request format). What is wrong with my code ?

2
Please, show full error message, what is behind [Object] and [Circular] entities?vitalyster
Now it works with the same code. Not sure why ?guy_fawkes

2 Answers

1
votes

I had the same issue. It nearly drove me crazy but in the end it was just an Invalid JSON format error.

I suppose messageData.from or messageData.message_id wasn't converted to correct JSON format. In my case I passed a scalar and JSON.stringify() didn't converted it to a string. Hence the result was --> "message_id": 1234 and not "message_id": "1234"

0
votes

The quick answer is you can not use CCS (XMPP) without having your project whitelisted. If you try using smack library instead, you will get an error saying that your project is not whitelisted.