powered by Jive Software

Push notifications are not published on the enabled node

Hello, please find out the cause of the problem.
On the server side (Openfire 4.6.0) I am using the pushnotification.jar 0.9.0-SNAPSHOT plugin compiled locally from the master branch (https://github.com/igniterealtime/openfire-pushnotification-plugin)
On the client I use the smack library, build.gradle like:

      implementation 'org.igniterealtime.smack:smack-java7:4.4.0-beta2'
     // Optional for XMPPTCPConnection
      implementation "org.igniterealtime.smack:smack-tcp:4.4.0"
     // Optional for XMPP-IM (RFC 6121) support (Roster, Threaded Chats, …)
      implementation "org.igniterealtime.smack:smack-im:4.4.0"
     // Optional for XMPP extensions support
      implementation "org.igniterealtime.smack:smack-extensions:4.4.0"
      implementation 'org.igniterealtime.smack:smack-experimental:4.4.0'

But in the process I ran into a problem, the publication of messages does not work on the node enabled for push notifications
First, I create a collection node:

<iq to='pubsub.mydomain.com' id='SSHFW-15' type='set'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='/PushServiceNode'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE'>
          <value>
            http://jabber.org/protocol/pubsub#node_config
          </value>
        </field>
        <field var='pubsub#node_type'>
          <value>
            collection
          </value>
        </field>
        <field var='pubsub#notify_retract'>
          <value>
            true
          </value>
        </field>
        <field var='pubsub#publish_model'>
          <value>
            publishers
          </value>
        </field>
        <field var='pubsub#persist_items'>
          <value>
            false
          </value>
        </field>
        <field var='pubsub#access_model'>
          <value>
            whitelist
          </value>
        </field>
        <field var='pubsub#deliver_payloads'>
          <value>
            true
          </value>
        </field>
      </x>
    </configure>
  </pubsub>
</iq>

Next, I create a child (leaf):

<iq to='pubsub.mydomain.com' id='SSHFW-45' type='set'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='/PushServiceNode/user1'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE'>
          <value>
            http://jabber.org/protocol/pubsub#node_config
          </value>
        </field>
        <field var='pubsub#node_type'>
          <value>
            leaf
          </value>
        </field>
        <field var='pubsub#notify_retract'>
          <value>
            true
          </value>
        </field>
        <field var='pubsub#publish_model'>
          <value>
            publishers
          </value>
        </field>
        <field var='pubsub#persist_items'>
          <value>
            false
          </value>
        </field>
        <field var='pubsub#access_model'>
          <value>
            whitelist
          </value>
        </field>
        <field var='pubsub#collection'>
          <value>
            /PushServiceNode
          </value>
        </field>
        <field var='pubsub#deliver_payloads'>
          <value>
            true
          </value>
        </field>
      </x>
    </configure>
  </pubsub>
</iq>

After that I subscribe the administrator to it and also make it the owner:

    BareJid serverJID = mConnection.getXMPPServiceDomain();
    BareJid adminJID = JidCreate.bareFrom(Localpart.from(mAdminUserName), mConnection.getXMPPServiceDomain());
    Affiliation server_affilation = new Affiliation(serverJID, Affiliation.Type.owner);
    Affiliation admin_affilation = new Affiliation(adminJID, Affiliation.Type.owner);
    mPushLeafNode.modifyAffiliationAsOwner(Arrays.asList(server_affilation, admin_affilation));
   
    List<Subscription> ChangeSubs = Arrays.asList(
             new Subscription(JidCreate.from(mAdminUserName + "@" + serverJID.toString()), Subscription.State.subscribed));
   
    mPushLeafNode.modifySubscriptionsAsOwner(ChangeSubs);

Next, I turn on push notifications on it:

<iq id='SSHFW-57' type='set'>
  <enable xmlns='urn:xmpp:push:0' jid='pubsub.mydomain.com' node='/PushServiceNode/user1'>
    <x xmlns='jabber:x:data' type='submit'>
      <field var='FORM_TYPE'>
        <value>
          http://jabber.org/protocol/pubsub#publish-options
        </value>
      </field>
      <field var='silent'>
        <value>
          false
        </value>
      </field>
      <field var='device_id'>
        <value>
          sercretId
        </value>
      </field>
      <field var='service'>
        <value>
          FCM
        </value>
      </field>
      <field var='topic'>
        <value>
          SomeTopic
        </value>
      </field>
      <field var='priority'>
        <value>
          high
        </value>
      </field>
    </x>
  </enable>
</iq>

Then I start sending normal messages to the client via xmpp in the Openfire log, I see that the plugin is finding a notification service for this client:

2021.02.24 06:39:56 TRACE [socket_c2s-thread-2]: org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor - For user 'user1', found service 'pubsub.mydomain.com'
2021.02.24 06:39:56 TRACE [socket_c2s-thread-2]: org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor - For user 'user1', found node '/PushServiceNode/user1' of service 'pubsub.mydomain.com'
2021.02.24 06:39:56 TRACE [socket_c2s-thread-2]: org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor - For user 'user1', Routing push notification to 'pubsub.mydomain.com' , push : 
<iq type="set" id="54-53" to="pubsub.mydomain.com" from="mydomain.com">
  <pubsub xmlns="http://jabber.org/protocol/pubsub">
    <publish node="/PushServiceNode/user1">
      <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>admin@mydomain.com/test</value>
            </field>
            <field var="last-message-body" type="text-single">
              <value>XMPP Hello</value>
            </field>
          </x>
        </notification>
      </item>
    </publish>
    <publish-options>
      <x xmlns="jabber:x:data" type="submit">
        <field var="FORM_TYPE">
          <value>http://jabber.org/protocol/pubsub#publish-options</value>
        </field>
        <field var="silent">
          <value>false</value>
        </field>
        <field var="device_id">
          <value>sercretId</value>
        </field>
        <field var="service">
          <value>FCM</value>
        </field>
        <field var="topic">
          <value>SomeTopic</value>
        </field>
        <field var="priority">
          <value>high</value>
        </field>
      </x>
    </publish-options>
  </pubsub>
</iq>

2021.02.24 06:39:56 DEBUG [socket_c2s-thread-3]: org.igniterealtime.openfire.plugins.pushnotification.PushInterceptor - Delivered a notification for user 'user1' to node '/PushServiceNode/user1' on service 'pubsub.mydomain.com'.

But the message is not published, no notifications are received, and also in the admin panel Node Summary for the node Items is zero.

As I understand the PushInterceptor.java:

XMPPServer.getInstance().GetRoutingTable().RoutePacket (push.getTo (), push, true);

does not publish a message through the PubSub service.

However, if you directly do pubsub publish () with SimplePayload Message to this node, then events come.

After debugging Openfire found out that this problem is related to the inconsistency of the node settings fields (pubsub#node_config)
and the settings applied to enable the push service on it:

<iq id='54719-57' type='set'>
  <enable xmlns='urn:xmpp:push:0' jid='pubsub.mydomain.com' node='/PushServiceNode/user1'>
    <x xmlns='jabber:x:data' type='submit'>
      <field var='FORM_TYPE'>
        <value>
          http://jabber.org/protocol/pubsub#publish-options
        </value>
      </field>
      <field var='silent'>
        <value>
          false
        </value>
      </field>
      <field var='device_id'>
        <value>
          someSecretToken
        </value>
      </field>
      <field var='service'>
        <value>
          FCM
        </value>
      </field>
      <field var='topic'>
        <value>
          weather
        </value>
      </field>
      <field var='priority'>
        <value>
          high
        </value>
      </field>
    </x>
  </enable>
</iq>

According to https://xmpp.org/extensions/xep-0357.html additional information such as auth data should be passed
Through additional fields:

<iq type='set' id='x43'>
  <enable xmlns='urn:xmpp:push:0' jid='push-5.client.example' node='yxs32uqsflafdk3iuqo'>
    <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>eruio234vzxc2kla-91</value></field>
    </x>
  </enable>
</iq>

But in this case, the openfire server starts rejecting (org.jivesoftware.openfire.pubsub.PubSubEngine.java: nodeMeetsPreconditions( … ) ) notification packets generated by the plugin.
Is there any way I can avoid this problem when using Openfire and the pushnotification.jar plugin?

I found an option to avoid this problem by modifying the pushservice.jar plugin
If you add the publish-options element to the notification body, a slight change in :
PushInterceptor.java:224

   if ( publishOptions != null )
   {
       Log.trace( "For user '{}', found publish options for node '{}' of service '{}'", new Object[] { user.toString(), node, service });
       final Element pubOptEl = push.getChildElement().addElement( "publish-options" );
224:  //pubOptEl.add( publishOptions ); // do not add publish-options to the publish body
225:+   notification.add(publishOptions); // add to notification body
   }

then the publish occurs and the event is successfully delivered.

<message from="pubsub.myDomain.com" to="admin@myDomain.com" id="WNWo44rE">
  <event xmlns="http://jabber.org/protocol/pubsub#event">
    <items node="/PushServiceNode/user2">
      <item id="87e9b10f-0036-43a4-ac5d-5f8743570d93">
        <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>
                user1@myDomain.com/test
              </value>
            </field>
            <field var="last-message-body" type="text-single">
              <value>
                XMPP Hello
              </value>
            </field>
          </x>
          <x xmlns="jabber:x:data" type="submit">
            <field var="FORM_TYPE">
              <value>
                http://jabber.org/protocol/pubsub#publish-options
              </value>
            </field>
            <field var="silent">
              <value>
                false
              </value>
            </field>
            <field var="device_id">
              <value>
                MysSecretData
              </value>
            </field>
            <field var="service">
              <value>
                FCM
              </value>
            </field>
            <field var="topic">
              <value>
                weather
              </value>
            </field>
            <field var="priority">
              <value>
                high
              </value>
            </field>
          </x>
        </notification>
      </item>
    </items>
  </event>
  <headers xmlns="http://jabber.org/protocol/shim">
    <header name="SubID">
      npi9OsPjqUPb53y8LuKM3JUyhQzlYsCCAlUuUUvS
    </header>
</message>

You can modify the plugin by adding an additional system setting parameter:

pushnotifications.publish-options.to-notification-body

and change the condition for adding options

 if ( publishOptions != null )
 {
     Log.trace( "For user '{}', found publish options for node '{}' of service '{}'", new Object[] { user.toString(), node, service });
     if ( JiveGlobals.getBooleanProperty( "pushnotifications.publish-options.to-notification-body", false ) ) {
         notification.add(publishOptions);
     }else{
         final Element pubOptEl = push.getChildElement().addElement("publish-options");
         pubOptEl.add(publishOptions);
     }
 }

then the behavior can be changed.