Atklique @ your workplace

Mon, 09/29/2014 - 12:83

When Marissa Mayer, the CEO of Yahoo inc. announced a ban on their 'work from home' policy, citing the reason that "to become the absolute best place to work, communication and collaboration will be important, so we need to be working side-by-side. That is why it is critical that we are all present in our offices", we at technologically driven company GS Lab got thinking. We felt that if technology can shrink the world, why can't it help employees to communicate and collaborate, irresptive of their location? That gave birth to an idea the ultimately led to an app called Atklique. Atklique is workplace collaboration tool that will help employees communicate and collaborate from anywhere. Today Atklique is a reality. What does it do? Here's a small list.


For comparison of Atklique with other similar solutions please watch out for my next blog.

Author: Kushal Mishra

Openfire XEP-0198 (Stream Management)

Mon, 10/06/2014 - 19:09

This blog has been updated. Please refer 'Stop Message Loss'.

Openfire is a real time collaboration (RTC) server licensed under the Open Source Apache License.

Openfire is incredibly easy to setup and administer however the absence of XEP-0198 Stream Management poses a difficult challenge (especially if the clients are smartphones (or similar devices) with poor bandwidth).
In the absence of XEP-0198 clients may lose messages when the bandwidth is poor. https://igniterealtime.jiveon.com/thread/31022

Atklique uses Openfire but guarantees successful message deliveries. This has been achieved through the development of a Openfire plugin which maintains stream information to ensure seamless message exchanges with no losses.

User A sends message "Atklique is an enterprise communication solution." to user B. Openfire associates a unique 'id' with every message.

A -> B ("Atklique is an enterprise communication solution.")
// Message'id'- 66445936822

A packet interceptor (an element of the plugin) intercepts the packet.
	private class XMLPacketInterceptor implements PacketInterceptor {
		public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed) {
		}
	}
The packet interceptor parses the packet and sends a receipt to the sender.
	try {
		Message message = new Message();
		message.setFrom("server_receipt@server");
		message.setTo(packet.getFrom());
		message.setID(packet.getID());
		router.route(message);
	} 
	catch (Exception exception) {
		exception.printStackTrace();
	}
The receipt confirms successful packet delivery to the Openfire server.
<message xmlns="jabber:client" id='66445936822' to="A@server" from="server_receipt@server">
</message>

The plugin enters the message into a custom table in the database and sends the message to the desired recipient (B).
	try {
		System.out.println("insert into ofStream values ('" + packet.getID());
		Message message = (Message) packet;
		String addToTable = "insert into ofStreamManagement values ('"
			+ packet.getID()
			+ "', '"
			+ new Date().getTime()
			+ "', '"
			+ packet.getFrom()
			+ "', '"
			+ packet.getTo()
			+ "', '" + message.getBody() + "')";
		Connection connection = null;
		try {
			connection = DbConnectionManager.getConnection();
			Statement statement = connection.createStatement();
			statement.executeUpdate(addToTable);
		} catch (Exception exception) {
			exception.printStackTrace();
		} finally {
			DbConnectionManager.closeConnection(connection);
		}
	} catch (Exception exception) {
		exception.printStackTrace();
	}
Server -> B
<message xmlns="jabber:client" id='66445936822' from="A@server" to="B@server" tyep="chat">
<body>Atklique is an enterprise communication solution.</body>
</message>

Whenever a client receives a message, the client sends back an acknowledgement to the Openfire server.
	try {
		Message newMessage = new Message();
		newMessage.setFrom(sendFrom);
		newMessage.setTo(sendTo);
		newMessage.setBody("client_receipt@server");
		newMessage.setType(Message.Type.chat);
		newMessage.setPacketID(packetID);
		chat.sendMessage(newMessage);
	} catch (Exception exception) {
		exception.printStackTrace();
	}
B -> Server
<message to='server@server' from='client_receipt@server' id='66445936822' type='client_receipt' xmlns='jabber:client'/>

This acknowledgement is intercepted by the plugin. The plugin removes the messages acknowledged by the recipient from the custom table. This removal is based on the message 'id'.
	try {
		String deleteFromTable = "delete from ofStream where packetIdentification = ?";
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		try {
			connection = DbConnectionManager.getConnection();
			preparedStatement = connection.prepareStatement(deleteFromTable);
			preparedStatement.setString(1, packet.getID());
			preparedStatement.executeUpdate();
			preparedStatement.close();
		} catch (Exception exception) {
			exception.printStackTrace();
		} finally {
			DbConnectionManager.closeConnection(resultSet, preparedStatement, connection);
		}
	} catch (Exception exception) {
		exception.printStackTrace();
	}
Openfire server is configured to ping idle clients. It disconnects a client after it has been idle for 30 seconds.
A server thread executes every 30 seconds.
For each message, if 45 seconds have passed since it was inserted into the custom table, the thread sends it to the desired participant and deletes it from the custom table.
	Thread thread = new Thread() {
		public void run() {
			while(true) {
				// Send ofStream table content (messages)
				Thread.sleep(30000);
			}
		}
	};
	thread.start();
Please see Stop Message Loss for plugin implementation.

Author: Tejas Inamdar

Tags:
Stream Management
XEP-0198
Openfire

Stop Message Loss

Thu, 26/03/2015 - 10:00

STEPS

sudo apt-get update

sudo apt-get install mysql-server
CREATE DATABASE openfire;

cd /home/server/Desktop/
wget http://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_3_9_3.tar.gz

tar xvf downloadServlet\?filename\=openfire%2Fopenfire_3_9_3.tar.gz rm downloadServlet\?filename\=openfire%2Fopenfire_3_9_3.tar.gz

sudo apt-get install openjdk-7-jdk openjdk-7-jre
sudo update-alternatives --config java
/*
/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java
*/

cd /home/server/Desktop/openfire/bin/
./openfire start

http://localhost:9090/setup/index.jsp







/*
jdbc:mysql://localhost:3306/openfire?rewriteBatchedStatements=true
*/





/*
admin
admin
*/



http://localhost:9090/login.jsp

http://localhost:9090/plugin-admin.jsp





/*
one
one
*/
/*
two
two
*/





'one' sent the message 'Hi' to 'two'
'two' received the message 'Hi' from 'one'
/*
'one' sent the message 'Hi' to 'two'
Plugin 'stop_message_loss' received the message sent by 'one'
Plugin 'stop_message_loss' sent the server_acknowledgement to 'one'
Plugin 'stop_message_loss' placed the message in the table 'stopMessageLoss'
'one' received the server_acknowledgement for the message 'Hi'
Please note that the lack of server_acknowledgement implies that the message was lost
'two' received the message 'Hi' from 'one'
'two' sent the client_acknowledgement to 'one'
Plugin 'stop_message_loss' received the client_acknowledgement sent by 'two'
Plugin 'stop_message_loss' removed the message from the table 'stopMessageLoss'
'one' received the client_acknowledgement for the message 'Hi'
*/

A message may be lost in the following scenarios:

scenarioOne: -
'one' attempts to send a message to 'two'
In the presence of poor bandwidth or network congestion or network breakage/disconnection the message sent by 'one' is lost
The message sent by 'one' does not reach Openfire
The lack of server_acknowledgement by the plugin 'stop_message_loss' implies that the message did not reach the server

scenarioTwo: -
'one' sends a message to 'two'
Plugin 'stop_message_loss' receives the message sent by 'one'
Plugin 'stop_message_loss' sends the server_acknowledgement to 'one'
Plugin 'stop_message_loss' places the message in the table 'stopMessageLoss'
'one' receives the server_acknowledgement for the message 'Hi'
If 'two' is offline then Openfire places the message in the 'ofOffline' table
If 'two' is online then Openfire sends the message to 'two'
In the presence of poor bandwidth or network congestion or network breakage/disconnection the message sent to 'two' by Openfire is lost
The message fails to reach 'two'
The absence of the client_acknowledgement from 'two' to 'one' implies that the message failed to reach the recipient 'two'
The message remains in the table 'stopMessageLoss'

/*
http://localhost:9090/client-connections-settings.jsp
Openfire disconnect clients after they have been idle for 360 seconds
*/

The absence of the client_acknowledgement from 'two' for interval > 360 seconds implies that the message was lost
The presence of a message in the table 'stopMessageLoss' for an interval > 360 seconds implies that the message was lost







To acknowledge a message, send a client receipt message back to the sender as shown below.
Ensure that, the 'id' for the client receipt message is the same as the 'id' for the message received.
	function onMessage(message) {
		var id = message.getAttribute('id');
		var from = message.getAttribute('from');
		var to = message.getAttribute('to');
		var fromSplit = from.split("@");
		var type = message.getAttribute('type');
		var elems = message.getElementsByTagName('body');
		if (type == "chat" && elems.length > 0) {
			var body = elems[0];
			var body = body.textContent;
			console.log("receivedMessage- " + body);
			var toId =  from;
			var fromId = to;
			var messageContent = "client_receipt_atklique"; 
			var reply = $msg({ to: toId, from: fromId, id: id, type:"chat"}).c("client_receipt").t(messageContent);
			connection.send(reply.tree());
			console.log("sentMessage- " + messageContent);
		}
		return true;
	}
		
	/*
		org.xmpp.packet.Message message = new org.xmpp.packet.Message();
		String domainName = "" + packet.getFrom();
		domainName = domainName.split("@")[1];
		message.setTo(packet.getFrom());
		message.setID(packet.getID());
		message.addChildElement("client_receipt","");
		message.getChildElement("client_receipt","").addText("client_receipt_atklique");
		router.route(message);
	*/	
		
Please note that messages are received by the clients at-least-once
A message may be received twice once in a blue moon
Clients should ignore duplicate messages

/*
The plugin sends an acknowledgement from the server and an acknowledgement from the recipient for each message.
This may degrade the performance of the server.
*/

Author: Tejas Inamdar



DISCLAIMER: NO WARRANTY

THE PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY. IT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE IS WITH YOU. SHOULD THE PLUGIN PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. IN NO EVENT THE AUTHOR WILL BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM.


Stop Message Loss