CoFFEE project tackles nat traversal problem, introducing XMPP container
Aim
The controller on the start up should ask to the user the xmpp login and password and the inforamtion about the collaborative session which he is starting. Then, the controller performs the login on the openfire server and creates the chatroom associated with the session.
Status on 25.11.2010
Currently, the controller login on openfire with fixed information embedded in the code (ilaman@trantor).
Changes on the project it.unisa.coffeeServerCore:
TODO
Aim
At the start up the CoFFEE server has to create a room; The roomm should show information about the identity of the coffee server;
Status on 25.11.2010
TODO
Aim
All the sharedObject used by CoFFEE should be registered on the xmpp container; a the end, the tcp container should be eliminated. The communication should be modified to use the xmpp container; Note that the broadcast should use the chatroom, while the point-to-point communications should use the xmppp global container.
Status on 1.12.2010
Status on 25.11.2010
changes in the class LEADServer:
xmppClient.addSharedObject(id,so);
the method addSharedObject of the XmppClient? adds the sharedObject to both the gloabal and the chatroom container. Currently, CoFFEE Controller adds the shared object of core and of the tools which are activated, but it throws an exception on communication because the broadcast must be managed diffrenetly (the point is that xmpp does not accept "null" as target, while in the existing mechanism the target "null" means "broadcast").
Aim
Sending mechanism: Controller to all discussers, Controller to one discusser, Discusser to Controller and then in broadcast, Dicsusser to Controller and stop (quick chat); This mechanism involves not only the Controller part but also tools and parts common to Discussers.
Controller to ALL discussers
messages sent from the server will be addressed to the id of the room, so that will be sent in broadcast (including then to himself). This mechanism implies two main aspects:
TODO
Status on 10.12.2010
Aim
The Control Panel on the CoFFEE Controller should be updated about the log in and log out of users;
The Control Panel, in the original version of CoFFEE, receives updates from the LEADServerPresenceManager which is a listener of the Container events; this means that the LEADServerPresenceManager receives the connected and disconnected events of clients; This does not happen with XMPP because the clients are connected onto the XMPP server and not on the CoFFEE Controller. The Controller must be changed to receive updates from the XMPP server.
Status on 15.12.2010
Changes on the project it.unisa.coffeeServerCore:
Changes on the project it.unisa.coffeeUtilsCore:
Aim Synchronizing the tools and their content between the Controller and latecomer clients;
Note: this feature involves also the Discusser.
Status on 21.12.2010
Changes on the project it.unisa.coffeeUtilsCore:
in the package it.unisa.coreplugins.ecf
in the package it.unisa.coreplugins.ecf
in the package it.unisa.coreplugins.ecf.core.xmpp
in the package it.unisa.toolplugins.ecf
in the class ServcerStateManagerEventProcessor?,
in the class ECFLEADContext
Changes on the project it.unisa.coffeeServerCore:
in the package it.unisa.coreplugins.coffeeServerCore.ecf
in the package it.unisa.coreplugins.coffeeServerCore.ecf.internal
in the package it.unisa.coreplugins.coffeeServerCore.ecf.xmpp
in tha class XmppClient?,
in the package it.unisa.coreplugins.coffeeServerCore.session
Changes on the project it.unisa.coffeeClientCore:
TODO
Aim
The controller on the start should be able to reload a saved session from a trace file.
Status on 10.01.2011
When the controller reload a saved session, the tools are reloaded fine they are empty: the content is not reloaded.
Status on 14.01.2011
Added the event processors to trace the messages, now all the messages are traced twice (and then reloaded twice). It could depend on the fact that the event processors handle also the messages of the discusses forwarded by the Controller.
Status on 17.01.2011
fixed.
Changes on the project it.unisa.coffeeServerCore:
in the project it.unisa.coffeeServerCore, in the package it.unisa.coreplugins.coffeeServerCore.ecf
in the project it.unisa.coffeeUtilsCore
Aim 1: allowing to choose the protocol (between TCP and XMPP) from command line;
Aim 2: on the basis of the chosen protocol, open an initial dialog with the right fields to fill
Status on 20 Jan 2011
Changes
on the project it,unisa.coffeeServerCore
on the project it.unisa.coffeeController
Problem: closing the Controller (also without tools started), it throws several NullPointerException?
Status on 20 Jan 2011
Changes:
on the project it,unisa.coffeeServerCore
on the project it.unisa.coffeeController
Aim
Allowing to use CoFFEE with TCP OR XMPP protocol;
VERY IMPORTANT NOTE: the tests have been made with CoFFEE Discusser v5.0 THEN WITHOUT ANY CHANGE INVOLVING THE PROTOCOLS.
Problem #1 opening the chat, the Controller throws the following exception:
at it.unisa.coreplugins.ecf.BasicSharedObject?.sendSharedObjectMessage(BasicSharedObject?.java:194) ...
Fix
in the method sendSharedObjectMessage(ID fromID, ID toID, Serializable msg) changed the sending mechanism to select the right destination ID on the basid of the procotol in use:
if (isProtocolXMPP){ ID roomID = roomInfo.getRoomID(); getContext().sendMessage(broadcast ? roomID : toID, cm); }else{ getContext().sendMessage(broadcast ? null : toID, cm); }
Result
Problem #2
java.lang.NullPointerException? at it.unisa.toolplugins.ecf.LEADMessageProcessorECFAdapter.processEvent(LEADMessageProcessorECFAdapter.java:128)
...
Fix
in the method processEvent(Event event), the Controller found XmppConnectionInformation? null when it uses TCP and tries to determine if the message is an XMPP message to discard. Fixed with a check on the field:
if ((connInfo!=null) && (connInfo.isController())) { String roomID_str=connInfo.getRoomInfo().getRoomID().toExternalForm(); StringID toContainerID = (StringID) cm.getToContainerID(); String toContainerID_str = toContainerID.getName(); if(roomID_str.compareTo(toContainerID_str)==0) return true; }
Result
Problem: the Discusser was not able to activate the Quick chat
Status on 20 Jan 2011 Changes
on the project it.unisa.coffeeClientCore
on the project it.unisa.coffeeDiscusser
in the project it.unisa.coffeeServerCore
in the project it.unisa.coffeeUtilsCore
Bug: reload a trace, the presence tool is not updated, shows the old connected dicusser.
Aim
At the start up the CoFFEE client selects a room created from the CoFFEE Server
Status on 29.11.2010
Update of the code 25.01.2011 Currently, the Discusser opens a dialog to select a room, already created on OpenFire Server, and s/he connects to the selected room, adding to the XMPP container the same SharedObject of the CoFFEE Discusser of the generic protocol. At last, the CoFFEE Discusser opens the "the Client Status view", setting as constant string the info of the CoFFEE Controller (eg in LEADClient class, changes of constant strings in the ServerTopic, isConnected(), getServerCoursename(), getServerCoordinator(), getServerClassroom() methods)
{{{...
if (CommProtocol?.isTCP()){
if (! leadClientStartup.tcpClientStart()) {
....
}
} if (CommProtocol?.isXMPP()){
if (! leadClientStartup.xmppClientStart()) {
....
}}}
Status on 15.12.2010
Changed the creation of the selected room in "xmppConnect" method of the "LEADClientStartup" class {{{... leadClientStartUp.xmppConnect(selectedRoom);... leadClientStartUp.xmppAddSharedObject();}}}
Update 25.01.11: in the it.unisa.coreplugins.coffeClientCore.ui.connection
Moved the the following code in the new TCPConnectionWizard class of the new package it.unisa.coffeediscusser.ui.connection
instance = this; setWindowTitle(Platform.getProduct().getName()); beaconListener = new LEADServerBeaconListener(); ImageDescriptor desc = getImgDesc(); setDefaultPageImageDescriptor(desc);
Added a new package: "it.unisa.coreplugins.coffeeClientCore.ecf.xmpp" which contains the classe providing xmpp implementation for coffee
xmppAddSharedObject():
...//Creates the !LeadSharedObject xmppClient.addSharedObject(IDFactory.getDefault() .createStringID(LEADClientSharedObject.AsynchCoreSharedObjectID), leadClientSO);...
The addSharedObject method of the XmppClient class adds the sharedObject to both the gloabal and the chatroom container.
Status on 15.12.2010
The chat tool, client side, works without loop.
LEADClientStartUpInternal
XMMPClient
it.unisatoolplugins.ecf
ECFLEADContext(), when client sends a message the toID must be created
... if(!connInfo.isController()){ Namespace connectNamespace = getSharedObjectContext().getConnectNamespace(); toID = IDFactory.getDefault().createID(connectNamespace, msg.getTo());}
LEADMessageprocessor class
when the client sends message, toID is instaceof XMPPID
String roomID_str=connInfo.getRoomInfo().getRoomID().toExternalForm(); String toContainerID_str; if(cm.getToContainerID() instanceof XMPPID) toContainerID_str = cm.getToContainerID().getName(); else{ StringID toContainerID = (StringID) cm.getToContainerID(); toContainerID_str = toContainerID.getName(); }
to avoid the loop of the messages sending from client
if(obj instanceof LEADMessage){ msg = (LEADMessage) obj; if (msg.isBroadcast()) return true; }
Status on 14.01.2011
When a Discusser disconnects, (close with red cross), s/he sends a message "exit" to update the presence list of Controller and each other discusser.
Status on 14.01.2011
When a discusser closes (red cross at the left corner), in the dispose() method of the groupPresenceComposite class, to send Exit Message
public void dispose() { service.sendExitMessage();
Fixed #2
When the second discusser connects, the presence list is updated changing
In the LEADClient class, the getIdentifier() method changes
public String getIdentifier(){ if (protocolUsed==XMPP_PROTOCOL){ str = xmppClient.getClientID().toExternalForm(); }
In the groups step of a demo session, the control panel of the Controller shows the later in the group #1, indeed, in the view are not in the same group
Status on 11.01.2011
The Discusser works with different protocol
In the it.unisa.coffeeUtilsCore package
In the ClientStateManagerEventProcessor class, the sendStateRequest() method checks which protocol is used
...if (!sharedObject.isProtocolXMPP()) { //THE FOLLOWING ARE THE LINES OF THE ORIGINAL VERSION OF COFFEE WITH THE PROTOCOL TCP ID connectedID = sharedObject.getSharedObjectContext().getConnectedID(); RequestStateMessage rsm = new RequestStateMessage( sharedObject.getSharedObjectContext().getLocalContainerID(), sharedObject.getID(), connectedID, currentSequenceNumber); sharedObject.sendSharedObjectMessage(connectedID, rsm, false); } else{ //the TCP protocol works ID controllerID = XmppConnectionInformation.getInstance().getControllerID(); ID myID = XmppConnectionInformation.getInstance().getUserID(); RequestStateMessage rsm = new RequestStateMessage( myID, sharedObject.getID(), controllerID, currentSequenceNumber); sharedObject.sendSharedObjectMessage(controllerID, rsm, false); globalLogger.finer(getLoggerHeader()+"sent state request: "+rsm); //$NON-NLS-1$ , }
In the ECFContext class,
In the sendMessage method the check of the protocol used
if (isProtocolXMPP){ XmppConnectionInformation connInfo = XmppConnectionInformation.getInstance(); if(!connInfo.isController()){ Namespace connectNamespace = getSharedObjectContext().getConnectNamespace(); toID = IDFactory.getDefault().createID(connectNamespace, msg.getTo()); } else toID = IDFactory.getDefault().createStringID(msg.getTo()); }else //Work the TCP protocol toID = IDFactory.getDefault().createStringID(msg.getTo());
Kind of testing with different protocol
if (isProtocolXMPP) tmpBln = XmppConnectionInformation.getInstance().isController(); else tmpBln = getSharedObjectContext().getConnectedID().equals(getSharedObjectContext().getLocalContainerID());
In the BasicSharedObject class, the isProtocolXMPP boolean variable is protected
On the it.unisa.coffeeDiscusser package, the "ApplicationWorkbenchWindowAdvisor?" class, in the openConnectionWizard() method adding the different protocol to use
if (protocolUsed == TCP_PROTOCOL){ if (! leadClientStartup.clientStart()) { System.exit(0); return; } } if (protocolUsed == XMPP_PROTOCOL){ if (! leadClientStartup.xmppClientStart()) { System.exit(0); return; } } ...
Fixed #1 (18.01.2011): Close each discusser when the Controller closes with exit in the File menu or by closing the workbench window with the red cross on the top right corner
Controller side
(Package it.unisa.coffeeController) In the ApplicationWorkbenchWindowAdvisor class, the preWindowShellClose method adds the close of the Controller when clicking on the red cross on the top right of the workbench window, otherwise a because raise exception in the clientDisconnected method of the SessionPlayerStatusLine class
LEADServer.getInstance().stop();
(it.unisa.coreplugins.coffeeServerCore.ecf.LEADServerPresenceManager package), in the class XmppClient?, added the dispose() method to dispose the xmppContainerClient
(it.unisa.coreplugins.coffeeServerCore.ecf package)In LEADServer class, added in the Stop() method the dispose of the XMPP container
public void stop() { ... if(protocolUsed == XMPP_PROTOCOL){ xmppClient.dispose(); }
(it.unisa.coreplugins.coffeeServerCore.ecf.xmpp; package)In the XmppClient add the dispose() method
public void dispose(){ xmppContainerClient.dispose(); }
(it.unisa.coreplugins.coffeeServerCore.application package), in the SessionPlayerStatusLine class, in the clientDisconnected method, added the following test, because the workbench window is already closed
if(leadServer != null){ String info =authInfo+Messages.getString("SessionPlayerStatusLine._Connected_users2")+ users; //$NON-NLS-1$ ... }
(it.unisa.coreplugins.coffeeServerCore.ui.actions package), the ExitAction class adding the close of the Controller
public void run() {... LEADServer.getInstance().stop(); }
Discusser side
(it.unisa.coreplugins.coffeeClientCore.ecf.internal package), the LEADClientSharedObject class, code about the close of the client is moved when the client receives the ServerDisconnectMsg message from Controller
else if( (data2= som.getData()) instanceof ServerDisconnectMsg) ServerDisconnectMsg closeInfo = (ServerDisconnectMsg) data2; serverDisconnection = closeInfo.isServerDisconnection(); //In XMPP protocol the disconnection event doesn't occur if(serverDisconnection){ if (LEADClient.getInstance()!=null) LEADClient.getInstance().dispose(); // closing the application if (AppOptions.getCloseApplicationOnExit()) System.exit(0); else CoFFEEViewClose(); return; }
and added comment block in the following test:
if(event instanceof IContainerDisconnectedEvent){ //The Disconnection Message is verified when: /** * Client application is closed when * <ul> * <li>Server clicks the window's close button. * <li>Server closes application choosing exit from file menu * </ul> */ /*if(serverDisconnection){ if (LEADClient.getInstance()!=null) LEADClient.getInstance().dispose(); // closing the application if (AppOptions.getCloseApplicationOnExit()) System.exit(0); else CoFFEEViewClose(); return; }*/
Aim 1: allowing to choose the protocol (between TCP and XMPP) from command line;
Aim 2: the dialog of the Discusser shows the following options of the Room: Room Name,Controller Name, Participants
Aim 3: The Client Status shows the following info : Teacher, Room Name and Your name
Status on 24 Jan 2011
Changes about Aim 1:
(it.unisa.coffeeDiscusser package), the ApplicationWorkbenchWindowAdvisor class adds the new method to read param form command line:
private void setProtocolFromArguments() { String args[]=Platform.getCommandLineArgs(); String prot=null; for(int i=0; i<args.length; i++){ if (args[i].startsWith("-prot=")){ prot= (args[i].split("="))[1]; CommProtocol.setProtocolUsed(prot); } }
Changes about Aim 2:
Changes about Aim 3:
Status on 14.01.2011
In the Eclipse workspace, management of the task Tags(Window->Preferences, Compiler->Task Tags), create the following Task Tags:
Documentation about SharedOject over XMPP ECF XMPP room and shared object.pdf documentation