Block presence updates from roster - java

I am currently building an chat application for android.
XMPP Server: MongooseIM.
XMPP Client: Smack 4.1.5.
Currently the logged in user keeps getting presence updates from his roaster buddies. I would like to receive these presence updates only when the application is open and block them when the application is closed. Is there a way to achieve this behavior? I have tried using privacy list but with no luck.
This is what i have tried so far.
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(mXMPPConnection);
ArrayList privacyItems = new ArrayList();
PrivacyItem item = new PrivacyItem(PrivacyItem.Type.subscription, "to", false, 1);
item.setFilterPresenceIn(true);
privacyItems.add(item);
privacyManager.createPrivacyList("subscription", privacyItems);

I assume that you want to stay connected to receive message but want to limit the presence traffic.
ejabberd supports XEP-0352 Client State Indication, which does exactly this. When going to background switch your client to inactive mode and presence update will not be send. When going back to foreground, switch CSI state to active and you will receive the relevant presence update, optimised by removing redundant obsolete presence informations.
You can check ejabberd documentation: mod_client_state

Related

Finagle service discovery issue

Here I wanted to register to 2 endpoints and send requests to them. You can see this in the code below. I name one env1 and the other env2.
val client = Http.client
.configured(Transport.Options(noDelay = false, reuseAddr = false))
.newService("gexampleapi-env1.localhost.net:8081,gexampleapi-env2.localhost.net:8081")
So far everything is normal. But env1 instance had to be down for some reason(for a few hours' maintenance etc. not sure why.). Under normal circumstances, our expectation is that it continues to send requests through the env2 instance. But this didn't happen. Could not send requests to both servers. Normally it was working correctly, but it didn't work that day for a reason we don't know.
Since the event took place months ago, I only have the following log.
2022-02-15 12:09:40,181 [finagle/netty4-1-3] INFO com.twitter.finagle
FailureAccrualFactory marking connection to "gExampleAPI" as dead.
Remote Address:
Inet(gexampleapi-env1.localhost.net/10.0.0.1:8081,Map())
To solve the problem, we removed gexampleapi-env1.localhost.net:8081 host from the config file. and after restarting it continued to process requests. If you have any ideas about why we may have experienced this problem and how to avoid this next time, I would appreciate it if you could share them.

How to ensure no duplicates created in DB on connection loss

Евгений Кравцов:
I develop some tiny service with http backend and android app. And recently i felt the lack of knowledge in such a systems.
Case:
- Client makes order in app and send request to server
- Server successfuly recieved data and make a database row for order
- After database work completes, backend tries to respond to App with 200 success code.
- App user faced some internet connection problems and can not receive server response. App gets timeout exception and notify user, that order was not successful
- After some time, internet connection on user device restored and he send another request with same oreder.
- Backend recieves this again and create duplicate for previous order
So i got 2 orders in database, but user wanted to create only one.
Question: How can i prevent such a behavior?
You should add a key to your table in the db, for example defining the key as compound key of user_id, type - so specific user cannot make 2 orders with the same order type.
This will cause the second db insert to fail.

How can I restore handlers after restart and continue receive messages from CurreneX?

I create java service for CurreneX. I use Quiqfix/j library. When i send new QuoteRequest, I get Quotes during 240 sec. But if I restart my service or reset internet connection I will stop recive Quotes. How can I continue recevive Quotes After reconnect/restart? I use options
PersistMessages = Y
ResetOnLogon = N
Mayby I not understand how work it? I need restore handlers after restart and continue receive messages from CurreneX. Or I need create myself logik and database persistence layer? Then why need to store messages in quickfix JdbcStoreFactory?
Yes when you send a QuoteRequest then you receive quotes for that request. Then consider connections from Currenex perspective. They have n clients who send quote requests. They send back responses / streams. If a client disconnects they don't know why that client disconnected or when or if the client will reconnect. It is problematic to handle re-subscriptions on their side, plus it's cleaner and less risky (say the disconnect is during a transaction) to stop open subscriptions and let the client re-subscribe. So that's what you have to do.
As for ResetOnLogon that's about restarting sequence numbers so you won't look for a gap fill of missed messages. Which is all about security for transactions, not for transient quotes that are stale by the time of re-subscription.
You need to handle OnLogout and store your current quote requests then re-subscribe to those requests OnLogon.

WebSockets - correct approach for creating channels and pushing data

I have a scenario whereby I want to inform users of my site that someone has commented on an article on which they have also commented. This is a lot like the way that SO notifies me when someone responds to a question!
Server side, I persist the comment and then look up all users who commented on the same article. I then broadcast (I'm using Atmosphere):
PushContext pushContext = PushContextFactory.getDefault().getPushContext();
for(User u : users){
// channel name, message
pushContext.push("/user_" + u.id, "someone commented! blah blah");
}
The "channel" I am broadcasting to is the user's "own" channel, since I don't want every user to be notified. I use the user's ID in the channel name to achieve this.
Is this the right way to do ensure only relevant users get notified?
I guess I also want to do two more things:
Only push to users whom I believe are still online. If they aren't online, then it's a waste of resources pushing to them.
Encrypt the message, because otherwise anybody could listen for my messages, if they know my user ID.
Is there anything else I need to think of?
SO uses WebSockets, for example when a comment is made on this posting, you get a notification in your status bar at the top left of the SO page.
When the page is loaded, the browser makes a protocol upgrade request which looks like this:
Request URL:ws://sockets-se.or.stackexchange.com/
Request Method:GET
Status Code:101 Switching Protocols
Request Headersview source
Connection:Upgrade
Cookie:__qca=P0-1697817643-1763440830313; __utma=27376923.959753990.1338240830.1353943751.1384115154.33; __utmc=27693525; __utmz=27699983.1356175156.31.31.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)
Host:sockets-se.or.stackexchange.com
Origin:http://stackoverflow.com
Sec-WebSocket-Extensions:x-webkit-deflate-frame
Sec-WebSocket-Key:6qFl45+6gZ526yMMo79zWQ==
Sec-WebSocket-Version:13
Upgrade:websocket
(Key3):00:00:00:00:00:00:00:00
Response Headersview source
Connection:Upgrade
Sec-WebSocket-Accept:B4h2G+gi78iNZZXg+o6iAztgF1I=
Upgrade:websocket
(Challenge Response):00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
The socket is then open, and the server can send updates to the browser. For example, a notification of my comment is received by the browser as:
{"action":"1-question-12993099","data":"{\"a\":\"comment-add\",\"id\":12993099,\"commentid\":19334206,\"acctid\":1298157}"}
It doesn't contain the actual comment; it appears that this is simply used to tell the browser to show the red icon. When you then click, it makes a request to get the page, including the comment. The question ID (12993099), comment ID (19334206) and account ID (1298157) is contained in that frame.
I cannot see anything in the above which would stop some hacker creating a web socket to listen to your notifications. The cookies look to me to be Google Analytics cookies to me, or at least the second and third ones do. Perhaps the first is some code which you wouldn't know, had I not just published it (no worries, I change it!).
In your example of Atmosphere, I know that when Web Sockets does not work, it defaults to long polling, which then requests a URL with the channel name in it. So you could get the client to generate a channel name which only it would know and associate that with the logged in user. But anyone sniffing the network would again have access to your traffic, so you'd have to secure it using secure web sockets (WSS) and HTTPS (for long polling fallback).

How openfire external component can deal with presence and subscriptions?

I have built an external openfire component based on the Whack library by extending the AbstractComponent class. I want clients to subscribe to my component and receive presence notifications when the component goes online and offline. So my question is how we can deal with presence and presence subscriptions for external component based on AbstractComponent?
Currently I can respond to the presence request by using the handlePresence() method but how do should I add clients to the component roster (does external components allow for roster in the first place)?
#Override
protected void handlePresence(Presence presence){
if (presence.getType() == Presence.Type.subscribe){
System.out.println("The component has received Subscribtion request.");
Presence original = presence;
Presence response = new Presence();
//Swap the sender/recipient fields
response.setTo(original.getFrom());
response.setFrom(original.getTo());
//Convert the text to upper case
response.setType(Presence.Type.subscribed);
send(response);
}
}
Components do not have a roster provided by the server. You can store your own roster in a database if you need to. Some applications can get away with no roster at all (when they simply want to appear online to everyone).
To appear online to everyone (simplest approach, no roster storage required):
When you receive <presence type="subscribe"/> reply with <presence type="subscribed"/>
When you receive <presence type="probe"/> reply with <presence/> (or whatever status you want to be shown as)
To store a roster requires a bit more work, but allows you to keep track of who is authorized to see your presence, and whose presence you are authorized to see. In some cases you might prefer to use a normal client connection here, if you don't want to manage your own roster. Jack Moffitt wrote a blog post on the idea here: http://metajack.im/2008/08/04/thoughts-on-scalable-xmpp-bots/
Note that throughout this post I omit the 'to' and 'from' attributes on stanzas. It is up to the component to put a 'to' and 'from' on outgoing stanzas. All incoming stanzas will have a 'to' and 'from'.
Displaying a component's presence to users
The basic incoming stanzas you need to handle are:
<presence type="subscribe">
The sender wants to subscribe to your presence updates. You can either approve or decline this. If you approve, you should store the sender's JID in your database so you know you need to send them your presence updates when necessary.
Specification: http://xmpp.org/rfcs/rfc6121.html#sub-request-handle
<presence type="unsubscribe">
The sender wants to stop receiving presence updates from you. You should remove them from the list of people subscribed to your updates, and then send back <presence type="unsubscribed"> and <presence type="unavailable">.
Specification: http://xmpp.org/rfcs/rfc6121.html#sub-cancel-inbound (though the text is tailored more towards servers than components here).
<presence type="probe">
The sender is asking for your current presence. Simply reply with your latest presence stanza for that user. This is typically sent by the user's server when they log in.
Receiving presence of users in a component
Additionally if you want the component to know the presence of users, you need to send a subscription request to them: <presence type="subscribe">. You should be prepared to receive either an approval (<presence type="subscribed">) or denial (<presence type="unsubscribed">).
When the component first comes online, it can fetch the current presence for a user by sending <presence type="probe"> to each user. There is no need to do this more than once per user while the component is running - the user's server will automatically send you presence updates if the user approved your subscription request as above.

Categories

Resources