New Openfire plugin: Push Server!

The Ignite Realtime Community is pleased to announce the 1.0.0 release of the Push Server plugin for Openfire. This plugin is developed by the company Busoft Teknoloji A.Ş. It is inspired by Conversations Push Proxy and developed for Openfire.

Your instance of Openfire should automatically display the availability of the new plugin in the next few hours. Alternatively, you can download the the plugin directly from the Push Server plugin archive page.

Stop by our support groupchat to get in touch, or leave a message on our community site.

For other release announcements and news follow us on Twitter

What is this plugin for

Due to the restrictions in push services (FCM or APNS), only the developer can create push notifications for their apps. For this reason a user’s server wouldn’t be able to wake up a user’s device directly but has to proxy that wake up signal through the infrastructure of the app developer.

Push Server Plugin is an XEP-0357: Push Notifications app server that relays push messages between the user’s server and FCM (Firebase Cloud Messaging) or APNS (Apple Push Notification Service).

Here is a quick description of how this relationship is set up.

XMPP Client sends to the app server

- Device Token
- Device Id

App Server generates

- Node Id
- Secret

App Server stores

- Device Token
- Device Id
- Node
- Secret

App Server returns to XMPP Client

- Node Id

XMPP Client sends to the user's server

- Node ID
- The jid of the app server (push.example.com)

The user’s server sends to the app server

(Achived by Openfire Push Notification plugin)

When a push is required the user’s server will send the node id to the app server. The user’s server can also add additonal information like number of messages pending, the sender jid of the last message and even the body of the last message.

An example of that communication can be found in XEP-0357 Section 7.

5 Likes

Hi hamzaozturk,
I have problems with the correct number/date of this plugin’s last release.

  • In your 16-set-2022 message is announced the 1.0.0 release;
  • In my server’s Admin Console I see the 1.0.0 release number but dated 2-set-2021;
  • In the plugin’s archive page the last release is dated 16-set-2022 but the number is 1.0.1;

Maybe it’s only a typo, but I don’t know which is the correct .jar to install.
Thanks for your attention!

Hi francesco,

Unfortunately, it is only a typo. You can use the one with version number 1.0.0 released at Sep 2, 2021 in the plugin’s archive page. It is also the same one published in the Plugin’s Admin Console.

1 Like

Thanks!

Hi hamzaozturk,
That’s a great plug-in, I’m waiting for.

I already installed Push Notification Plugin on my Openfire server node and about to build an app server with tigase or some other.

If I install Push Server Plugin at the node, can I deliver the push notification without any additional node?

Even if yes, do I need to add a domain for a virtual host at the node?

Finally, I’m just wondering if it’s possible to do both xmpp service and push app service on one node of Openfire with this plugin.

If it is not appropriate to ask such a question here, please let me know.

Hi hoonlee,

Thanks for your interest to the plugin.

If I install Push Server Plugin at the node, can I deliver the push notification without any additional node?
Yes

Even if yes, do I need to add a domain for a virtual host at the node?
No

Finally, I’m just wondering if it’s possible to do both xmpp service and push app service on one node of Openfire with this plugin.
Yes

If you have more questions, please feel free to ask.

1 Like

Thank you!
I’ll try it with my Openfire server.

Hi Hamzaozturk,

I’m trying to make push notification on my openfire server as the way I mentioned in the last question.

I installed the both of Push Notification plugin and Push Server plugin to my openfire host.
So the XMPP server and push server have a same domain name commonly.

I registered my client successfully to the push server and then sent a message stanza from an other client when that client is away.
But the away client couldn’t get a push notification.

Then I found following logs from my openfire server.

it seems that the “Push Notification” plugin cannot route the message to the “Push Server” of the same host.

Can you guess what I’ve missed?

2022.10.22 13:44:55 e[30mTRACEe[m [socket_c2s-thread-4]: org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor - Message stored to offline storage. Try to send push notification.
2022.10.22 13:44:55 e[30mTRACEe[m [socket_c2s-thread-4]: org.igniterealtime.openfire.plugins.pushnotification.PushServiceManager - User 'apptest' has 1 push notification services configured.
2022.10.22 13:44:55 e[30mTRACEe[m [socket_c2s-thread-4]: org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor - For user 'apptest', 1 push service(s) are configured.
2022.10.22 13:44:55 e[30mTRACEe[m [socket_c2s-thread-4]: org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor - For user 'apptest', found service 'otherhome.au'
2022.10.22 13:44:55 e[30mTRACEe[m [socket_c2s-thread-4]: org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor - For user 'apptest', found node 'register-push-apns' of service 'otherhome.au'
2022.10.22 13:44:55 e[30mTRACEe[m [socket_c2s-thread-4]: org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor - For user 'apptest', Routing push notification to 'otherhome.au'
2022.10.22 13:44:55 e[1;31mERRORe[m [socket_c2s-thread-4]: org.jivesoftware.openfire.spi.RoutingTableImpl - Primary packet routing failed**
**org.jivesoftware.openfire.PacketException: Cannot route packet of type IQ or Presence to bare JID: <iq type="set" id="459-4920" to="otherhome.au" from="myopenfire.com"><pubsub xmlns="http://jabber.org/protocol/pubsub"><publish node="register-push-apns"><item><notification xmlns="urn:xmpp:push:0"><x xmlns="jabber:x:data" type="form"><field var="FORM_TYPE" type="hidden"><value>urn:xmpp:push:summary</value></field><field var="message-count" type="text-single"><value>1</value></field><field var="last-message-sender" type="text-single"><value>kei@myopenfire.com/gajim.MOTKEHWO</value></field><field var="last-message-body" type="text-single"><value>hi</value></field></x></notification></item></publish></pubsub></iq>
	at org.jivesoftware.openfire.spi.RoutingTableImpl.routeToLocalDomain(RoutingTableImpl.java:419) ~[xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.spi.RoutingTableImpl.routePacket(RoutingTableImpl.java:350) [xmppserver-4.7.3.jar:4.7.3]
	at org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor.tryPushNotification(PushInterceptor.java:226) [pushnotification-0.9.2-SNAPSHOT.jar!/:?]
	at org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor.messageStored(PushInterceptor.java:265) [pushnotification-0.9.2-SNAPSHOT.jar!/:?]
	at org.jivesoftware.openfire.OfflineMessageStrategy.store(OfflineMessageStrategy.java:201) [xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.OfflineMessageStrategy.storeOffline(OfflineMessageStrategy.java:145) [xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.MessageRouter.routingFailed(MessageRouter.java:268) [xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.spi.RoutingTableImpl.routePacket(RoutingTableImpl.java:378) [xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.MessageRouter.route(MessageRouter.java:134) [xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.spi.PacketRouterImpl.route(PacketRouterImpl.java:79) [xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.net.StanzaHandler.processMessage(StanzaHandler.java:411) [xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.net.ClientStanzaHandler.processMessage(ClientStanzaHandler.java:109) [xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.net.StanzaHandler.process(StanzaHandler.java:235) [xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.net.StanzaHandler.process(StanzaHandler.java:198) [xmppserver-4.7.3.jar:4.7.3]
	at org.jivesoftware.openfire.nio.ConnectionHandler.messageReceived(ConnectionHandler.java:183) [xmppserver-4.7.3.jar:4.7.3]
	at org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.messageReceived(DefaultIoFilterChain.java:1015) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:650) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:49) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1128) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived(IoFilterAdapter.java:122) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:650) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:49) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1128) [mina-core-2.1.3.jar:?]
	at org.apache.mina.filter.codec.ProtocolCodecFilter$ProtocolDecoderOutputImpl.flush(ProtocolCodecFilter.java:413) [mina-core-2.1.3.jar:?]
	at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:257) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:650) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:49) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1128) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.filterchain.IoFilterEvent.fire(IoFilterEvent.java:106) [mina-core-2.1.3.jar:?]
	at org.apache.mina.core.session.IoEvent.run(IoEvent.java:89) [mina-core-2.1.3.jar:?]
	at org.apache.mina.filter.executor.OrderedThreadPoolExecutor$Worker.runTask(OrderedThreadPoolExecutor.java:766) [mina-core-2.1.3.jar:?]
	at org.apache.mina.filter.executor.OrderedThreadPoolExecutor$Worker.runTasks(OrderedThreadPoolExecutor.java:758) [mina-core-2.1.3.jar:?]
	at org.apache.mina.filter.executor.OrderedThreadPoolExecutor$Worker.run(OrderedThreadPoolExecutor.java:697) [mina-core-2.1.3.jar:?]
	at java.lang.Thread.run(Thread.java:750) [?:1.8.0_342]
2022.10.22 13:44:55 e[36mDEBUGe[m [socket_c2s-thread-4]: org.jivesoftware.openfire.spi.RoutingTableImpl - Failed to route packet to JID: myopenfire.com packet: <iq type="set" id="459-4920" to="myopenfire.com" from="myopenfire.com"><pubsub xmlns="http://jabber.org/protocol/pubsub"><publish node="register-push-apns"><item><notification xmlns="urn:xmpp:push:0"><x xmlns="jabber:x:data" type="form"><field var="FORM_TYPE" type="hidden"><value>urn:xmpp:push:summary</value></field><field var="message-count" type="text-single"><value>1</value></field><field var="last-message-sender" type="text-single"><value>kei@myopenfire.com/gajim.MOTKEHWO</value></field><field var="last-message-body" type="text-single"><value>hi</value></field></x></notification></item></publish></pubsub></iq>
2022.10.22 13:44:55 e[36mDEBUGe[m [socket_c2s-thread-4]: org.jivesoftware.openfire.IQRouter - IQ sent to unreachable address 'myopenfire.com': <iq type="set" id="459-4920" to="myopenfire.com" from="myopenfire.com"><pubsub xmlns="http://jabber.org/protocol/pubsub"><publish node="register-push-apns"><item><notification xmlns="urn:xmpp:push:0"><x xmlns="jabber:x:data" type="form"><field var="FORM_TYPE" type="hidden"><value>urn:xmpp:push:summary</value></field><field var="message-count" type="text-single"><value>1</value></field><field var="last-message-sender" type="text-single"><value>kei@myopenfire.com/gajim.MOTKEHWO</value></field><field var="last-message-body" type="text-single"><value>hi</value></field></x></notification></item></publish></pubsub></iq>
2022.10.22 13:44:55 e[36mDEBUGe[m [socket_c2s-thread-4]: org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor - Delivered a notification for user 'apptest' to node 'register-push-apns' on service 'myopenfire.com'.

Hi hoonlee,

It looks like your configuration is not correct. Let me help you how to configure your client.

From your iOS/Android client, you need to send an iq like below to register push server. You need to change only the token and device-id values.

<iq from="user@example.com/mobile" id="x20" to="push.example.com" type="set">
    <command xmlns="http://jabber.org/protocol/commands" action="execute" node="register-push-apns">
        <x xmlns="jabber:x:data" type="submit">
            <field var="token">
                <value>243CA5F2A4EE00B66E3208CD05C962A30EFA80B2D9F8DD508CE8182E04EAB695</value>
            </field>
            <field var="device-id">
                <value>0523AD60-ADD0-45A4-8D05-DC1AC59BB1CA</value>
            </field>
        </x>
    </command>
</iq>

You will get an iq response as blow:

<iq from="push.example.com" id="x20" to="user@example.com/mobile" type="result">
    <command xmlns="http://jabber.org/protocol/commands" action="complete" node="register-push-apns">
        <x xmlns="jabber:x:data" type="form">
            <field type="text-single" var="node">
                <value>37Ni514izxHG</value>
            </field>
            <field type="text-single" var="secret">
                <value>Zt9z9wOtAUOSYCtYC7a5OORa</value>
            </field>
        </x>
    </command>
</iq>

After getting the node and secret values from the iq response, you need to send an iq again to enable push notification for your client.

<iq type='set' id='x42'>
  <enable xmlns='urn:xmpp:push:0' jid='push.example.com' node='37Ni514izxHG'>
    <x xmlns='jabber:x:data' type='submit'>
      <field var='FORM_TYPE'><value>http://jabber.org/protocol/pubsub#publish-options</value></field>
      <field var='secret'><value>Zt9z9wOtAUOSYCtYC7a5OORa</value></field>
    </x>
  </enable>
</iq>

Also be aware that, jid is push.example.com not example.com. In your logs, it looks like otherhome.au not push.otherhome.au.

If you have more questions, please feel free to ask.

Thank you so much for your kind answer.

I have only a single host of Openfire server and it has only one domain name “example.com”.

I’m wondering If above was just my misunderstanding of you.

Do I need 2 domains “example.com” (XMPP server) and “push.exampl.com” (XMPP push server)?

If yes, now since I’m trying to set everything in a single node, finally do I need to add a virtual host of “push.example.com” for that node to work as taking the both roles of XMPP server and XMPP push server?

Is my understanding correct?

And following is my registration iq for the logs.

<iq id='644753DA-DA55-4A21-94A0-7EC928A53579' type='set' to='example.com'>
  <command xmlns='http://jabber.org/protocol/commands' node='register-push-apns' action='execute'>
    <x xmlns='jabber:x:data' type='submit'>
      <field var='token' type='text-single'>
        <value>243CA5F2A4EE00B66E3208CD05C9.......</value>
      </field>
      <field type='text-single' var='device-id'> 
        <value>9A53A213768B50E0A3AC4711A264312A99D.....</value>
      </field>
    </x>
  </command>
</iq>

Hi hoonlee,

You do not need another domain for push server.

Could you just please change the to part of the iq as “push.example.com” and try?

Thank you, Hamzaozturk.
As you adviced, I just changed the ‘to’ part of the registration IQ as “push.example.com”.
And above problem was solved and I passed that.

However, I faced another error following.

[1;31mERRORe[m [socket_c2s-thread-3]: org.igniterealtime.openfire.plugins.pushserver.PushServerIQHandler - 'publish-options' element should be set.

Could you share your wisdom for this situation?

Hi hoonlee,

Could you please share the iq you are sending to enable push notifications. It should look like as below:

<iq type='set' id='x42'>
  <enable xmlns='urn:xmpp:push:0' jid='push.example.com' node='37Ni514izxHG'>
    <x xmlns='jabber:x:data' type='submit'>
      <field var='FORM_TYPE'><value>http://jabber.org/protocol/pubsub#publish-options</value></field>
      <field var='secret'><value>Zt9z9wOtAUOSYCtYC7a5OORa</value></field>
    </x>
  </enable>
</iq>

Hi, Hamzaoztruk.
Thank you for your prompt answer.

Following is mine, used in my testing of push server plugin.

<iq type="set" id="073E0737-1725-424E-82F7-FCF8CE1FC716" from="apptest@example.com/iosclient" to="apptest@example.com">
  <enable xmlns="urn:xmpp:push:0" node="5LkCFR4pkUn1" jid="push.example.com"></enable>
</iq>

Differnet from yours, I’ve omitted the child element ‘x’.

But I have no base knowledges for that.
Especially, I cannot understand what the “<field var=‘secret’>” element means.

Could you tell me what it means or where I can get any documents which explain about it?

Hi, Hamzaoztruk.
I got the meaning of ‘secret’.
You already explained about it at the ‘readme’ of the Push Server Plugin and I just have missed it in there.

I’ll try my mobile app to get push notifications after ‘enable’ push notificatoin with ‘secret’ from the result of the registration.

Hi, Hamzaoztruk.

Finally, the push notificaion on my iOS app is working beautifully with push notification plugin and push server plugin.

I hope others will be as happy as I was with this plugin.

1 Like

hi @hamzaozturk .
i try push notification same down here

<iq to='to@push.example.com' id='2B1Q2-9' type='set'>
  <command xmlns='http://jabber.org/protocol/commands' node='register-push-fcm' action='execute'>
    <x xmlns='jabber:x:data' type='submit'>
      <field var='token'>
        <value>
          eBUgc5sSQKaDzE0ZXgmfG9...
        </value>
      </field>
      <field var='device-id'>
        <value>
          4cc718b9f0f223a5
        </value>
      </field>
    </x>
  </command>
</iq>

then i got problem with item not found

<iq type="error" id="2B1Q2-9" from="from@push.example.com" to="to@example.com/5bms4iyy89">
  <error code="404" type="cancel">
    <item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
  </error>
</iq>

Could you share your wisdom for this situation?