Code

whiteboard now works on jep compliant servers only, aka wildfire
[inkscape.git] / src / jabber_whiteboard / session-manager.h
1 /**
2  * Whiteboard session manager
3  *
4  * Authors: 
5  * David Yip <yipdw@rose-hulman.edu>
6  *
7  * Copyright (c) 2005 Authors
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #ifndef __SESSION_MANAGER_H__
13 #define __SESSION_MANAGER_H__
15 #include <glibmm.h>
16 #include <set>
17 #include <bitset>
19 #include <libxml/parser.h>
20 #include <libxml/tree.h>
22 #include <vector>
24 extern "C" {
25 #include <loudmouth/loudmouth.h>
26 }
28 #include "jabber_whiteboard/typedefs.h"
29 #include "jabber_whiteboard/defines.h"
30 #include "jabber_whiteboard/buddy-list-manager.h"
32 #include "gc-alloc.h"
34 struct SPDesktop;
35 struct SPDocument;
37 namespace Inkscape {
38 namespace XML {
39 class Node;
40 }
41 }
43 namespace Inkscape {
45 namespace Whiteboard {
47 class ReceiveMessageQueue;
48 class SendMessageQueue;
49 class XMLNodeTracker;
50 class SessionManager;
51 class MessageHandler;
52 class ChatMessageHandler;
53 class Callbacks;
54 class SessionFile;
55 class SessionFilePlayer;
56 class UndoStackObserver;
57 class Serializer;
58 class Deserializer;
60 /// Jabber resource name
61 #define RESOURCE_NAME   "Inkboard"
63 /// connectToServer return values
64 #define CONNECT_SUCCESS         0
65 #define FAILED_TO_CONNECT       1
66 #define INVALID_AUTH            2
67 #define SSL_INITIALIZATION_ERROR        3
69 /// sendMessage return values
70 #define SEND_SUCCESS                    0
71 #define CONNECTION_ERROR                1
72 #define UNKNOWN_OUTGOING_TYPE   2
73 #define NO_RECIPIENT_JID                3
75 /**
76  * Structure grouping data items pertinent to a whiteboard session.
77  *
78  * SessionData holds all session data for both 1:1 and chatroom conferences.
79  * Access to members should be controlled by first querying the status bitset
80  * to see if useful data will actually exist in that member -- i.e. checking
81  * status[IN_CHATROOM] to see if the chatters set will contain anything.
82  * It usually won't hurt to do a straight query -- there are very few members
83  * that remain uninitialized for very long -- but it's a good idea to check.
84  */
85 struct SessionData {
86 public:
87         /**
88          * Constructor.
89          *
90          * \param sm The SessionManager with which a SessionData instance should be
91          * associated with.
92          */
93         SessionData(SessionManager *sm);
95         ~SessionData();
97         /**
98          * The JID of the recipient: either another user JID or the JID of a chatroom.
99          */
100         gchar const* recipient;
102         /**
103          * Pointer to Loudmouth connection structure.
104          * Used for Loudmouth calls that require it.
105          */
106         LmConnection* connection;
108         /**
109          * SSL information structure for SSL connections.
110          */
111         LmSSL* ssl;
113         /**
114          * Flag indicating whether or not we should ignore further SSL errors for a given session.
115          */
116         bool ignoreFurtherSSLErrors;
119         /**
120          * A user's handle in a Jabber chatroom.
121          */
122         Glib::ustring chat_handle;
124         /**
125          * The Users Jid.
126          */
127         Glib::ustring jid;
129         /**
130          * Name of the chatroom that a user in a chatroom is connected to.
131          */
132         Glib::ustring chat_name;
134         /**
135          * Name of the conference server.
136          */
137         Glib::ustring chat_server;
139         // Message queues
140         
141         /**
142          * Map associating senders to receive queues.
143          */
144         RecipientToReceiveQueueMap receive_queues;
146         /**
147          * Map associating senders to commit events sent by those committers.
148          */
149         CommitsQueue recipients_committed_queue;
151         /**
152          * Pointer to queue for messages to be sent.
153          */
154         SendMessageQueue* send_queue;
156         // Message sequence numbers
157         
158         /**
159          * The sequence number of the latest message sent by this client in a given session.
160          * Used for determining the sequence number of the next message.
161          */
162         unsigned int sequence_number;
164         //unsigned int latest_sent_transaction;
165         //RecipientToLatestTransactionMap latest_processed_transactions;
168         // Status tracking
169         /**
170          * Session state and status flags.
171          */
172         std::bitset< NUM_FLAGS > status;
173         
174         /**
175          * Jabber buddy list data.
176          */
177         BuddyListManager buddyList;
179         /**
180          * List of participants in a Jabber chatroom.
181          */
182         ChatterList chatters;
184         /**
185          * Session file filename; blank if no session file is to be
186          * recorded.
187          */
188         Glib::ustring sessionFile;
190 private:
191         // access to containing class
192         SessionManager *_sm;
194         // noncopyable, nonassignable
195         SessionData(SessionData const&);
196         SessionData& operator=(SessionData const&);
197 };
200 // TODO: This class is huge.  It might be best to refactor it into smaller,
201 // more coherent chunks.
202 //
203 // TODO: convert to pass-by-reference where appropriate.  In particular, a lot of the
204 // string buffers passed to methods in the argument list can be made into references
205 // appropriately and easily.
207 /**
208  * Session management class for Inkboard.
209  *
210  * By "session management", we refer to the management of all events that an Inkboard
211  * session may need to handle: negotiating a connection to a Jabber server, negotiating
212  * sessions with users and chatrooms, sending, receiving, and parsing messages, and so
213  * forth.
214  *
215  * SessionManager instances are associated with Inkscape desktop objects on a 1:1 basis.
216  */
217 class SessionManager {
218 public:
219         /**
220          * Constructor.
221          *
222          * \param desktop The desktop with which this SessionManager is associated.  */
223         SessionManager(::SPDesktop *desktop);
224         ~SessionManager();
226         // Session tracking data
227         
228         /** 
229          * Pointer to SessionData structure.
230          */
231         struct SessionData *session_data;
233         // Inkscape interface
234         
235         /**
236          * Set the desktop with which this SessionManager is associated.
237          *
238          * @param desktop the desktop with which this SessionManager should be associated
239          */
240         void setDesktop(::SPDesktop* desktop);
241         
242         // Session management
243         
244         /**
245          * Connect to a Jabber server.
246          *
247          * @param server Jabber server URL
248          * @param username Jabber username
249          * @param pw password for Jabber account
250          * @param usessl use SSL for connection
251          *
252          * @return CONNECT_SUCCESS if connection successful; FAILED_TO_CONNECT if connection failed or INVALID_AUTH
253          * if authentication invalid
254          */
255         int connectToServer(Glib::ustring const& server, Glib::ustring const& port, Glib::ustring const& username, Glib::ustring const& pw, bool usessl);
256         
257         /**
258          * Register with a Jabber server.
259          *
260          * @param username Jabber username
261          * @param pw password for Jabber account
262          * @param key A list of string elements required for registration
263          * @param val The respective list of value of elements required for registration
264          * @param usessl use SSL for connection
265          *
266          * @return CONNECT_SUCCESS if connection successful; FAILED_TO_CONNECT if connection failed or INVALID_AUTH
267          * if authentication invalid
268          */
269         int registerWithServer(Glib::ustring const& username,Glib::ustring const& pw, std::vector<Glib::ustring> key, std::vector<Glib::ustring> val);
271         /**
272          * Query the Registration information required for a jabber server
273          *
274          * @param server Jabber server URL
275          * @param username Jabber username
276          * @param pw password for Jabber account
277          * @param key A list of string elements required for registration
278          * @param val The respective list of value of elements required for registration
279          * @param usessl use SSL for connection
280          *
281          * @return CONNECT_SUCCESS if connection successful; FAILED_TO_CONNECT if connection failed or INVALID_AUTH
282          * if authentication invalid
283          */
284         std::vector<Glib::ustring> getRegistrationInfo();
285         
286         int finaliseConnection();
287         int initializeConnection(Glib::ustring const& server, Glib::ustring const& port, bool usessl);
288         /**
289          * Handle an SSL error by prompting the user for feedback, and continuing or aborting the connection
290          * process based on that feedback.
291          *
292          * @param ssl pointer to LmSSL structure
293          * @param status The error message
294          *
295          * @return LM_SSL_RESPONSE_CONTINUE if user wishes to continue establishing the connection or LM_SSL_RESPONSE_STOP if user wishes to abort connection
296          */
297         LmSSLResponse handleSSLError(LmSSL* ssl, LmSSLStatus status);
299         /**
300          * Disconnect from a Jabber server.  
301          *
302          * This invokes disconnectFromDocument().
303          *
304          * \see Inkscape::Whiteboard::SessionManager::disconnectFromDocument
305          */
306         void disconnectFromServer();
308         /**
309          * Disconnect from a document session.  The connection to the Jabber server is not 
310          * broken, and may be reused to connect to a new document session.
311          *
312          */
313         void disconnectFromDocument();
315         /**
316          * Perform session teardown.  This method by itself does not disconnect from a document or 
317          * a Jabber server.
318          *
319          */
320         void closeSession();
322         /**
323          * Set the recipient for Inkboard messages.
324          *
325          * @param recipientJID the recipient's JID
326          */
327         void setRecipient(char const* recipientJID);
329         // Message sending utilities
330         
331         /**
332          * Put an Inkboard message into the send queue.
333          * This method does not actually send anything to an Inkboard client.
334          *
335          * \see Inkscape::Whiteboard::SessionManager::sendMessage
336          *
337          *
338          * @param msg the message to send
339          * @param type the type of message (only CHANGE_* types permitted)
340          * @param chatroom whether or not this message is destined for a chatroom
341          */
342         void sendChange(Glib::ustring const& msg, MessageType type, std::string const& recipientJID, bool chatroom);
344         /**
345          * Send a message to an Inkboard client.
346          *
347          *
348          * @param msgtype the type of message to send
349          * @param sequence message sequence number
350          * @param msg the message to send
351          * @param recipientJID the JID of the recipient
352          * @param chatroom whether or not this message is destined for a chatroom
353          *
354          * @return SEND_SUCCESS if successful; otherwise: UNKNOWN_OUTGOING_TYPE if msgtype is not recognized, NO_RECIPIENT_JID if recipientJID is NULL or blank, CONNECTION_ERROR if Jabber connection error occurred
355          */
356         int sendMessage(MessageType msgtype, unsigned int sequence, Glib::ustring const& msg, char const* recipientJID, bool chatroom);
358         /**
359          * Inform the user of a connection error via a Gtk::MessageDialog.
360          *
361          * @param errmsg message to display
362          */
363         void connectionError(Glib::ustring const& errmsg);
365         /**
366          * Stream the contents of the document with which this SessionManager is associated with to the given recipient.
367          * 
368          * @param recipientJID the JID of the recipient
369          * @param newidsbuf buffer to store IDs of new nodes 
370          * @param newnodesbuf buffer to store address of new nodes 
371          */
372         void resendDocument(char const* recipientJID, KeyToNodeMap& newidsbuf, NodeToKeyMap& newnodesbuf);
373         
374         
375         /**
376          * Send a connection request to another Inkboard client.
377          *
378          *
379          * @param recipientJID the JID to connect to
380          * @param document document message to send
381          */
382         void sendRequestToUser(std::string const& recipientJID);
384         /**
385          * Send a connection request to chatroom.
386          * 
387          * @param server server to connect to
388          * @param chatroom name of chatroom
389          * @param handle chatroom handle to use
390          * @param password chatroom password; leave NULL if no password
391          */
392         void sendRequestToChatroom(Glib::ustring const& server, Glib::ustring const& chatroom, Glib::ustring const& handle, Glib::ustring const& password);
394         /**
395          * Send a connection request response to a user who requested to connect to us.
396          *
397          * @param requesterJID the JID of the user whom sent us the request
398          * @param accepted_request whether or not we accepted the request
399          */
400         void sendConnectRequestResponse(char const* requesterJID, gboolean accepted_request); 
402         /**
403          * Method called when a connection request is received.  This method produces a dialog
404          * that asks the user whether or not s/he would like to accept the request.
405          *
406          *
407          * @param requesterJID the JID of the user whom sent us the request
408          * @param msg the message associated with this request
409          */
410         void receiveConnectRequest(gchar const* requesterJID);
412         /**
413          * Method called when a response to a connection request is received.
414          * This method performs any necessary session setup/teardown and user notification
415          * depending on the response received.
416          *
417          *
418          * @param msg the message associated with this request
419          * @param response the response code
420          * @param sender the JID of the user whom responded to our request
421          */
422         void receiveConnectRequestResponse(InvitationResponses response, std::string& sender);
424         /**
425          * Method called when a document synchronization request is received from a new conference
426          * member in a chatroom.
427          *
428          * \param recipient the recipient JID
429          */
430         void receiveConnectRequestResponseChat(gchar const* recipient);
432         // Message parsing and passing
433         
434         /**
435          * Processes a group of document change messages.
436          *
437          * \param changemsg The change message group to process.
438          */
439         void receiveChange(Glib::ustring const& changemsg);
441         // Logging and session file handling
442         /**
443          * Start a session log with the given filename.
444          *
445          * \param filename Full path to the file that the session log should be written to.
446          * \throw Glib::FileError Thrown if an exception is thrown during session file creation.
447          */
448         void startLog(Glib::ustring filename);
450         /**
451          * Load a session file for playback.
452          *
453          * \param filename Full path to the session file that is to be loaded.
454          */
455         void loadSessionFile(Glib::ustring filename);
457         /**
458          * Returns whether or not the session is in session file playback mode.
459          *
460          * \return Whether or not the session is in session file playback mode.
461          */
462         bool isPlayingSessionFile();
464         // User event notification
465         
466         /**
467          * Method to notify the user that a whiteboard session to another user has been successfully
468          * established.
469          *
470          * \param JID The JID with whom the user established a session.
471          */
472         void userConnectedToWhiteboard(gchar const* JID);
474         /**
475          * Method to notify the user that the other user in a user-to-user whiteboard session
476          * has disconnected.
477          *
478          * \param JID The JID of the user who left the whiteboard session.
479          */
480         void userDisconnectedFromWhiteboard(std::string const& JID);
482         // Queue dispatching and UI setup
483         
484         /**
485          * Start the send queue for this session.
486          */
487         void startSendQueueDispatch();
489         /**
490          * Stop the send queue for this session.
491          */
492         void stopSendQueueDispatch();
494         /**
495          * Start the receive queue for this session.
496          */
497         void startReceiveQueueDispatch();
499         /**
500          * Stop the receive queue for this session.
501          */
502         void stopReceiveQueueDispatch();
504         /**
505          * Clear all layers, definitions, and metadata from the document with which a
506          * SessionManager instance is associated. 
507          *
508          * Documents are cleared to assist synchronization between two clients
509          * or a client and a chatroom.
510          */
511         void clearDocument();
513         /**
514          * Set up objects for handling actions generated by the user interacting with
515          * Inkscape.  This includes marking the active session as being in a whiteboard session,
516          * starting send and receive queues, and creating an event serializer and deserializer.
517          *
518          * \see Inkscape::Whiteboard::SendMessageQueue
519          * \see Inkscape::Whiteboard::ReceiveMessageQueue
520          * \see Inkscape::Whiteboard::Serializer
521          * \see Inkscape::Whiteboard::Deserializer
522          */
523         void setupInkscapeInterface();
525         /**
526          * Reset whiteboard verbs to INITIAL state.
527          */
528         void setInitialVerbSensitivity() {
529                 this->_setVerbSensitivity(INITIAL);
530         }
532         /**
533          * Set up the event commit listener.
534          *
535          * The event commit listener watches for events that are committed to the document's undo log,
536          * serializes those events, and then adds them to the message send queue.
537          *
538          * \see Inkscape::Whiteboard::SendMessageQueue
539          * \see Inkscape::Whiteboard::UndoStackObserver
540          */
541         void setupCommitListener();
543         // Private object retrieval
544         ::SPDesktop* desktop();
545         ::SPDocument* document();
546         Callbacks* callbacks();
547         Whiteboard::UndoStackObserver* undo_stack_observer();
548         Serializer* serializer();
549         XMLNodeTracker* node_tracker();
550         Deserializer* deserializer();
551         ChatMessageHandler* chat_handler();
552         SessionFilePlayer* session_player();
553         SessionFile* session_file();
555 private:
556         // Internal logging methods
557         void _log(Glib::ustring const& message);
558         void _commitLog();
559         void _closeLog();
560         void _tryToStartLog();
562         enum SensitivityMode {
563                         INITIAL,
564                         ESTABLISHED_CONNECTION,
565                         ESTABLISHED_SESSION,
566                         DISCONNECTED_FROM_SESSION
567         };
569         void _setVerbSensitivity(SensitivityMode mode);
571         bool _pollReceiveConnectRequest(Glib::ustring const recipient);
573         ::SPDesktop* _myDesktop;
574         ::SPDocument* _myDoc;
575         Whiteboard::UndoStackObserver* _myUndoObserver;
576         XMLNodeTracker* _myTracker;
577         ChatMessageHandler* _myChatHandler;
578         Callbacks* _myCallbacks;
579         SessionFile* _mySessionFile;
580         SessionFilePlayer* _mySessionPlayer;
581         MessageHandler* _myMessageHandler;
582         Serializer* _mySerializer;
583         Deserializer* _myDeserializer; 
585         sigc::connection _send_queue_dispatcher;
586         sigc::connection _receive_queue_dispatcher;
587         sigc::connection _notify_incoming_request;
589         // noncopyable, nonassignable
590         SessionManager(SessionManager const&);
591         SessionManager& operator=(SessionManager const&);
592 };
598 #endif
600 /*
601   Local Variables:
602   mode:c++
603   c-file-style:"stroustrup"
604   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
605   indent-tabs-mode:nil
606   fill-column:99
607   End:
608 */
609 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :