Project

General

Profile

Send Message From Server

John Catron
Added about 5 years ago

Hello!

My team and I are looking for a way to send a message from the server OR from the current user programatically.

We cannot use Admin ad-hoc commands for this as we need it to be a response to a stimulus and not something for an admin to execute manually..

It looks like SessionManager has an 'addOutPacket' method. Or XMPPIOService has 'addPacketToSend'.

Either of these should work but we have no way to get a working instance of either of these. What we need is some public static method to get one of those. or even better a public static method to send a message either with the from field set to null (from server) or set to current user.

=====================================

Reasoning:

We are trying to trigger a roster-reload just like we had discussed on the forums here before.

When a user logs in and our external roster service returns the buddylist: If the buddylist is a different than what we previously had cached, we want to send a roster reload packet.

This means that the server (or the current user via their XMPPResourceConnection) needs to send a packet to each member of buddylist to notify them that it has been changed. We need some way to send a packet to each of these users programatically.

The only things we will have access to is:

Current User's XMPPResourceConnection.

List of BareJIDs for users we need to message.

What can we do to get this message out. Currently our only thought is to extend XMPPResourceConnection to provide public access to the SessionManager(loginHandler) stored inside of it.

We would very much like to do this without needing to extend anythign as I'm sure there must be SOME way to send a message from server OR to leave the context of UserA and enter context of UserB.

(To be perfectly honest though the users will never receive this packet our PacketProcessor will intercept it on the user's behalf we just need something to get from User_A into User_B's packet processor)


Replies (7)

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 5 years ago

We cannot use Admin ad-hoc commands for this as we need it to be a response to a stimulus and not something for an admin to execute manually..

In most deployments we were assisting, our customers use ad-hoc commands in an automated way. There are many ways you can call ad-hoc commands triggered by some event. We have this command line Tigase Management Tool which can be called by some external services/code or even from a cron job.

Some of our customers implement kind of an XMPP bot tool which connects to Tigase to an admin account and executes admin commands as necessary.

For the admin commands there is either XMPP interface or REST API available.

It looks like SessionManager has an 'addOutPacket' method. Or XMPPIOService has 'addPacketToSend'.

Either of these should work but we have no way to get a working instance of either of these. What we need is some public static method to get one of those. or even better a public static method to send a message either with the from field set to null (from server) or set to current user.

There is a reason that these methods are not exposed as a public API. And no, these cannot be public static methods. For each user connection (and you can have hundreds of thousands of them on a single machine) you have a different XMPPIOService object, so you cannot have a static methods for sending data through these objects. As for the SM, everything in Tigase is highly concurrent, multiple threads are utilized with multiple data queues, however, a great care is taken to prevent packets reordering, etc... You really do not want to mess this up.

A suggestion for an optimal approach to your problem, roster push update really depends on your use case. How Tigase blends with your other systems, what triggers the roster change update, where this information is available, etc...

Admin ad-hoc commands are a logical solution in most cases and it does not require any code changes in the Tigase server, however, maybe in your case a Tigase component would be more appropriate? It depends on all these details which are currently unknown to us.

=====================================

Reasoning:

We are trying to trigger a roster-reload just like we had discussed on the forums here before.

When a user logs in and our external roster service returns the buddylist: If the buddylist is a different than what we previously had cached, we want to send a roster reload packet.

This means that the server (or the current user via their XMPPResourceConnection) needs to send a packet to each member of buddylist to notify them that it has been changed. We need some way to send a packet to each of these users programatically.

The only things we will have access to is:

Current User's XMPPResourceConnection.

List of BareJIDs for users we need to message.

Where do you have access to this data from? I mean, I suppose you have some own code loading to the Tigase which has access to objects above? Which API do you use? SM Plugins or something else?

What can we do to get this message out. Currently our only thought is to extend XMPPResourceConnection to provide public access to the SessionManager(loginHandler) stored inside of it.

We would very much like to do this without needing to extend anythign as I'm sure there must be SOME way to send a message from server OR to leave the context of UserA and enter context of UserB.

Admin ad-hoc commands might be the best solution. You can perform user's roster reload from an external system connecting as an admin to Tigase. Another approach would be to have a custom SM plugin (processor). But SM Plugins are triggered only with a XMPP stanza passing through the server, so really depends on what triggers the roster update in your system.

Added by John Catron about 5 years ago

For our use-case tigase itself is what is triggering the roster reload.

Use case:

UserA requests the dynamic roster.

Tigase asks our API for a list of buddies.

Tigase then compares the list of this buddies against the list it gave to others on UserA's domain.

If the new set is different than the previous set it needs to then trigger a roster-reload.

The way this happens is in Tigase will send a message to each user on the buddylist (This is the step we can't figure out how to do)

Then as each user receives the message our PacketProcessor drops the message and instead issues a roster set iq packet to update the roster.

From the naming we assumed that admin ad-hoc commands were meant to be run manually not from within Tigase itself. We just need a method that we can use to send a message to a list of users. IF admin commands are the way to do this then that is fine.

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 5 years ago

In such a case a real trigger to roster change update is: roster get XMPP packet sent from a user to the server

In such a case, indeed, admin ad-hoc command does not seem like a good solution. I would implement this in the following way:

  1. The server receives roster get request from a user

  2. The server does the roster checking you describe above

  3. If the roster needs update then the plugin which is processing all the logic we describe here (a custom roster plugin) sends a custom * * packet to all users which need to update the roster

  4. You need another custom plugin which intercepts the custom roster-update packet on behalf of the receiving user which can perform roster push form the server to the user

I think this would be the simplest and most effective way to do it. Just a side note. You realize that if nobody logins (retrieves roster) for a long time, many users may have outdated rosters for a long time. XMPP connections tend to last for a very long time, so if many users never relogin for a day, 2 or more they may not get update roster and may not get a roster push.

This is why, usually, our other customers do the roster push via admin ad-hoc commands initiated from an external service. So the roster update is more real-time thing.

Added by John Catron about 5 years ago

The steps you are suggesting is Exactly what we are doing like word for word.

The issue is ("(a custom roster plugin) sends a custom * * packet to all users which need to update the roster") -- We don't know how to do this step.

That is the part we are asking for help with we can't figure out how to send that packet.

As far as the roster retrieval drawback we understand this.

But our roster consists of everyone on your domain. so Worst case scenario someone new is added to your domain. But you don't care if someone new is added if they never login so it might as well wait until they login to retrieve a new one. Otherwise you would just have a new contact that is eternally offline.

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 5 years ago

Well, in your custom roster plugin you have access to the user's roster, that is, you have access to all friends who need to receive a roster update.

Let's call them: buddy1, buddy2, buddy3, ...

So you simply send a packet roster-update to each of the buddies, something like:

<iq id="123" to="buddy1@domain">
  <query xmlns="custom-roster-update"/>
</iq>

<iq id="123" to="buddy2@domain">
  <query xmlns="custom-roster-update"/>
</iq>

<iq id="123" to="buddy3@domain">
  <query xmlns="custom-roster-update"/>
</iq>

Then you need your custom roster plugin (or maybe just another custom plugin dedicated only to roster-update packets) to intercept the custom-roster-update stanza on behalf of each buddy. Then this stanza is then processed within a context to the buddy's session. So you have access to this buddy XMPPResourceConnection - assuming he is online. Then you can just push a roster set stanza to all user's connections.

Added by John Catron about 5 years ago

I understand all of that. I just need to know how to do the 'simply send' part. I have the Packet object built for each buddy. I just need the way to actually Send it.

I already have the Packets built, and I already have the custom plugin to process and intercept the custom-roster-update packets.

But I don't have access to any type of Queue with which to send my Packets. Is there some other way for me to send these? Or is there a way for me to Get a Queue that will work?

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 5 years ago

I am sorry. Stuff are obvious to me and I do not realize they are not so obvious actually.

In the plugin you actually "send" a packet (or many packets) by adding them to a results queue which is passed as an argument to the process() method of the plugin.

    (1-7/7)