Code

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