How to manage XMPP connection - xmpp

I am designing a chat application using ejabberd as XMPP server and Smack 4.1 API. Below is a code snippet for managing connection.
// Create a connection to the server.com server on 5222 port.
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
.setUsernameAndPassword("user", "password")
.setServiceName("server.com")
.setHost("server.com_ip")
.setPort(5222)
.setSecurityMode(SecurityMode.disabled)
.build();
XMPPTCPConnection conn = new XMPPTCPConnection(config);
try {
conn.connect();
System.out.println("Connection established.");
conn.login();
System.out.println("Logged in.");
} catch (SmackException | IOException | XMPPException e) {
System.out.println("Connection not established: " + e.getMessage());
}
Some processing for chat and muc.
// Disconnect
conn.disconnect();
System.out.println("Connection Closed.");
My Requirement:
Once a user logs into the app, they might not log out for months at a time. Exactly the way Whatsapp works.
My question is:
Is it a good idea to keep the connection open as long as user is logged in?
If not then is it a good idea to open and close the connection for every chat message?
Need Suggestion:
What is the most efficient way to handle a connection with XMPP server?

Although the question is different, this SO I answered might help (comments too), but in a nutshell:
Opening and closing the connection for each and every message is Not what you should do.
Regarding keeping the connection Idle (like WhatsApp), it's one of the options (look into Services), the other would be to connect when your application comes up and stay connected as long as it's up, and use push notifications when the app is not running.
Another option would be a combination of both (more close to what WhatApp does).
Hope This Helps.

Related

Connecting to Strophe.js in Angular 6

I have connected to Strophe.js by placing the Strophe.js files in assets and Connection is successful. But after connecting to it, UI is getting hanged. Can any one please help
what means hanged? Strophe.js does't block the process.
i remeber connect like this(not exact code):
var callback = function(condition){
// according to condition decide if connected or not
// and if connected, UI: form login panel to main panel(include friends list and so on)
}
Strophe.connection(jid, password, callback);
and there is no reason UI hanged. you may use broswer debug tool to follow your code and find out where it hanged

How to receive publish/message event from Sails server using Socket.io swift client

Currently i am building app using Sails server as a backend and iOS Swift as a client.
I am able to emit from iOS side to create user and receive data from server side, but i am not able to get PubSub methods(message, publishAdd, Update,etc) provided by sails.
Here is my server side code
User.subscribe(req, [userdata.id]);
Now when there is any update occurred on above User recored then i need to receive event like
socket.on("userupdate") { data in
print("user 1 ------------>", socket)
}
But i am not receiving any event on client side.
Any help will be appreciated :)
Thanks
Actually i am missing watch on server side also need to do changes on client side like below
socket.onAny({ data in
print("ANy event =====> \(data)" )
})
socket.on("user", callback: {
data,ack in
print("call back called \(data) \(ack)")
})
socket.OnAny user to trace which event being called while there is any event for publish, update,etc
Here are server side changes i have done
User.subscribe(req, newUser, ['message']);
User.watch(req);
User.publishCreate(newUser);
Hope this will be useful for developer looking to implemented socket with Sails server.

Web Sockets - Send messages to all clients

I am completely new to Web Sockets, I have applied them to my chat so now it looks something like this:
<script type='text/javascript'>
var connection = new WebSocket("ws://echo.websocket.org"); //"public" websocket server
connection.onopen = function () {
console.log('Connection: OK.');
};
connection.onerror = function (error) {
console.log(Error: ' + error);
};
connection.onmessage = function () {
$('#chatbox').load('/chatbox.php');
};
$(document).ready(function() {
$('#chatOK').click(function(event) {
//something
connection.send('Get new messages.');
});
});
</script>
It works well for one client, when I enter message it updates the chatbox but only mine, but I want to update it for everyone (=all users who have opened chat window). So how can I send with WebSockets message to all clients?
You cannot do this with the websocket.org echo server - this just echos whatever you send it back to the sender.
You need a server which handles the distribution to all clients. This is easiest done using the Publish & Subscribe messaging pattern:
All chat messages are published to a common topic, e.g. "myChatRoom_1".
All connected clients indicate to the server that they are interested in messages to "myChatRoom_1" (that's the subscription).
Now when the server receives a published event for "myChatRoom_1" it can distribute it to all subscribers.
Take a look at this demo to see this in action.
It's based on Crossbar.io, an open source application router, which does PubSub out of the box, without an additional backend. So if you used this, you'd need to implement just the changes to your browser chat clients.
If you want to integrate with your PHP backend (e.g. since this stores the chat messages somewhere), there is a PHP library for connecting to Crossbar.io as well.
Full disclosure: I work for Tavendo, who are the maintainers of the Crossbar.io project.

XMPP Smack chat using openfire

Few questions around getting Chat working with Smack (3.2.1)/Openfire(3.7.1Alpha).
I am currently testing it using a unit test. My unit test creates a connection, creates account, logs in, adds a new user to its roster, attempts to send a chat message to the new user and eventually deletes the users. Apart from my confusions around getting chat to work, others seem to work (verified using openfire admin dashboard).
A. When I do the following
public void sendChatMessage(String sender, String receiver, String message) {
Chat chat = chatManager.createChat(receiver, messageListener);
chat.sendMessage(message);
}
Current connection is of the 'sender' (i.e. sender is logged in) and my attempt is to send a message to 'receiver'. When I get callback in my listener, message.getFrom() returns the 'receiver' and message.getBody() returns null. I am obviously trying to send a message on behalf of 'sender' to 'receiver'. What am I missing?
B. My 'sender' and 'receiver' are simply unique 'usernames' (without
any #domain) and my server is simply 'localhost'.
connection = new XMPPConnection("localhost");
Do I need to modify the 'receiver' to be of different value to make it a valid JID (there are no errors at the moment)? What if I change my server (& the openfire server configurations)?
C. I am assuming there will always be one XMPPConnection per user? Is this correct?
D.
XMPPConnection.DEBUG_ENABLED = true;
When I have XMPPConnection in debug mode, a new window opens up, however, it is tied with my IDE. How can I have it not tied to the ide so I can look into the logs while trying to debug the code?

Play 2.0 Comet using a persistant connection

I am using play 2.0 for a realtime web application that connects to a backend socket in order to listen for data on that stream.
The following example does what I want but I don't know how to disconnect the socket if the clients webpage is closed or page has changed.
def comet = Action {
val out = Enumerator.imperative[String]()
val socketClient = new SocketClientModel("localhost", "testclient",
Option("username"), "password", out)
socketClient.listen
Ok.stream(out &> Comet(callback = "console.log"))
}
The problem that I am having is figuring out how to call socketClient.disconnect when the page has been closed or changed. Currently when I close the browser session I can still see the connection is established and data is being received on the server side.
A hacky solution could be for you to have a ping call in the other direction (client to server):
You setup a timer that will destroy the connection if it hasn't been canceled before 10 seconds (you can always setup a longer period):
var timer;
def comet = Action {
timer = Akka.system.scheduler.scheduleOnce(10 seconds) {
socketClient.disconnect
}
...
}
You setup an Action that receives pings and setup a timer in the javascript code to send requests to that route every 9 seconds:
def keepAlive = Action {
cancel.cancel
timer = Akka.system.scheduler.scheduleOnce(10 seconds) {
socketClient.disconnect
}
}
When the user goes to another page, or cancel the connection to the comet Action, then it should also cancel the ping timer on the client side (if the user change page, this should be automatic, but you will have to have some health check on the comet connection if you stay in the same page, etc.). When the client stops pinging your action, the timer will eventually kill the socket.
It's really ugly as you need to use a var that is shared between your two actions and it's not really thread safe. It also would only be able to support one client. But the code example you have given is the same I guess. You would need to track which session has open which socket to support multiple client. You would loose stateless behaviour though.
A cleaner solution would be to use a small actor system to encapsulate this behaviour:
- you have a SocketActor that, when it receives a Start message, opens a socket and pushes things on a PushEnumerator, it keeps doing this as long as it doesn't receive a Stop message.
- you also have a KeepAliveActor that will after a given amount of time send a Stop message to the SocketActor, unless it has received a KeepAlive message before (so, what's going on here).
When you receive a comet connection, you spawn two new actors (you should have a manager actor to hide the two actors and relay the messages, etc.) and keep a ref to them linked to the session. The keepalive action would then fetch the ref for the right session and send KeepAlive messages to the actor.
The SocketActor would, when it receive a Stop message close the socket and destroy the actors that were linked to him.
It's a bit more involved coding, so I am not including snippets, but it would be a simple AKKA system, so you should be able to set it up by checking out the AKKA tutorials if you are not yet used to it.