Code

added functionality to for users to register jabber accounts within the whiteboard...
[inkscape.git] / src / jabber_whiteboard / message-processors.cpp
1 /**
2  * Whiteboard session manager
3  * Jabber received message processors
4  *
5  * Authors:
6  * David Yip <yipdw@rose-hulman.edu>
7  *
8  * Copyright (c) 2005 Authors
9  *
10  * Released under GNU GPL, read the file 'COPYING' for more information
11  */
13 extern "C" {
14 #include <loudmouth/loudmouth.h>
15 }
17 #include <glibmm/i18n.h>
19 #include "xml/session.h"
20 #include "xml/document.h"
22 #include "desktop-handles.h"
23 #include "document.h"
24 #include "message-stack.h"
26 #include "jabber_whiteboard/undo-stack-observer.h"
27 #include "jabber_whiteboard/session-manager.h"
28 #include "jabber_whiteboard/message-node.h"
29 #include "jabber_whiteboard/message-queue.h"
30 #include "jabber_whiteboard/message-processors.h"
31 #include "jabber_whiteboard/typedefs.h"
33 namespace Inkscape {
35 namespace Whiteboard {
37 // Message processors are here!
39 // TODO: Remove unnecessary status checks from processors --
40 // we do all of that in MessageHandler::_hasValidReceiveContext
42 // *********************************************************************
43 // ChangeHandler begin
44 // *********************************************************************
46 /**
47  * MessageProcessor for document change and event commit messages.
48  */
49 struct ChangeHandler : public MessageProcessor {
50 public:
51         ~ChangeHandler()
52         {
54         }
56         ChangeHandler(SessionManager* sm) : MessageProcessor(sm)
57         {
59         }
61         LmHandlerResult
62         operator()(MessageType mode, JabberMessage& p)
63         {
64                 MessageNode* msgNode;
65                 bool chatroom = this->_sm->session_data->status[IN_CHATROOM];
67                 ReceiveMessageQueue* rmq = this->_sm->session_data->receive_queues[p.sender];
69                 if (rmq != NULL) {
70                         switch (mode) {
71                                 case CHANGE_REPEATABLE:
72                                 case CHANGE_NOT_REPEATABLE:
73                                 case DOCUMENT_BEGIN:
74                                         msgNode = new MessageNode(p.sequence, p.sender, "", p.body, mode, false, chatroom);
75                                         rmq->insert(msgNode);
76                                         Inkscape::GC::release(msgNode);
77                                         break;
78                                 case DOCUMENT_END:
79                                         this->_sm->session_data->recipients_committed_queue.push_back(p.sender);
80                                         msgNode = new MessageNode(p.sequence, p.sender, "", p.body, mode, false, chatroom);
81                                         rmq->insert(msgNode);
82                                         Inkscape::GC::release(msgNode);
83                                         break;
84                                 case CHANGE_COMMIT:
85                                         this->_sm->session_data->recipients_committed_queue.push_back(p.sender);
86                                         msgNode = new MessageNode(p.sequence, p.sender, "", p.body, CHANGE_COMMIT, false, chatroom);
87                                         rmq->insert(msgNode);
88                                         Inkscape::GC::release(msgNode);
89                                         break;
90                                 case DUMMY_CHANGE:
91                                 default:
92                                         break;
93                         }
94                 } else {
95                         g_warning("Received message from unknown sender %s", p.sender.c_str());
96                 }
97                 
98                 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
99         }
100 };
101 // *********************************************************************
102 // ChangeHandler end
103 // *********************************************************************
106 // *********************************************************************
107 // ConnectRequestHandler begin
108 // *********************************************************************
109 /**
110  * MessageProcessor for connection request messages.
111  */
112 struct ConnectRequestHandler : public MessageProcessor {
113 public:
114         ~ConnectRequestHandler()
115         {
117         }
119         ConnectRequestHandler(SessionManager* sm) : MessageProcessor(sm) 
120         {
122         }
124         LmHandlerResult 
125         operator()(MessageType mode, JabberMessage& m)
126         {
127                 std::bitset< NUM_FLAGS >& status = this->_sm->session_data->status;
128                 switch(mode) {
129                         case CONNECT_REQUEST_USER:
130                                 this->_sm->receiveConnectRequest(m.sender.c_str());
131                                 break;
132                         case CONNECT_REQUEST_RESPONSE_USER:
133                                 if (m.sequence == 0) {
134                                         this->_sm->receiveConnectRequestResponse(DECLINE_INVITATION, m.sender);
135                                 } else { // FIXME: this has got to be buggy...
136                                         this->_sm->setRecipient(m.sender.c_str());
137                                         this->_sm->receiveConnectRequestResponse(ACCEPT_INVITATION, m.sender);
138                                 }
139                                 break;
140                         case Inkscape::Whiteboard::CONNECTED_SIGNAL:
141                                 if (!status[IN_CHATROOM] && !status[CONNECTING_TO_CHAT] && !status[SYNCHRONIZING_WITH_CHAT] && !status[WAITING_TO_SYNC_TO_CHAT]) {
142                                         this->_sm->userConnectedToWhiteboard(m.sender.c_str());
143                                         this->_sm->setRecipient(m.sender.c_str());
144                                 } else {
145                                         sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::INFORMATION_MESSAGE, _("<b>%s</b> has joined the chatroom."), m.sender.c_str());
146                                 }
147                                 break;
148                         default:
149                                 break;
150                 }
151                 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
152         }
153 };
154 // *********************************************************************
155 // ConnectRequestHandler end
156 // *********************************************************************
161 // *********************************************************************
162 // ConnectErrorHandler begin
163 // *********************************************************************
164 /**
165  * MessageProcessor for connection error messages.  
166  */
167 struct ConnectErrorHandler : public MessageProcessor {
168 public:
169         ~ConnectErrorHandler()
170         {
172         }
174         ConnectErrorHandler(SessionManager* sm) : MessageProcessor(sm) 
175         {
177         }
179         LmHandlerResult 
180         operator()(MessageType mode, JabberMessage& m)
181         {
182                 switch(mode) {
183                         case CONNECT_REQUEST_REFUSED_BY_PEER:
184                                 if (this->_sm->session_data->status[WAITING_FOR_INVITE_RESPONSE]) {
185                                         this->_sm->receiveConnectRequestResponse(DECLINE_INVITATION, m.sender);
186                                 }
187                                 break;
188                         case Inkscape::Whiteboard::ALREADY_IN_SESSION:
189                                 if (this->_sm->session_data->status[WAITING_FOR_INVITE_RESPONSE]) {
190                                         this->_sm->receiveConnectRequestResponse(PEER_ALREADY_IN_SESSION, m.sender);
191                                 }
192                                 break;
193                         case Inkscape::Whiteboard::DISCONNECTED_FROM_USER_SIGNAL:
194                                 if (!this->_sm->session_data->status[IN_CHATROOM]) {
195                                         this->_sm->closeSession();
196                                         this->_sm->userDisconnectedFromWhiteboard(m.sender.c_str());
197                                 }
198                                 break;
199                         default:
200                                 break;
201                 }
202                 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
203         }
204 };
205 // *********************************************************************
206 // ConnectErrorHandler end
207 // *********************************************************************
212 // *********************************************************************
213 // ChatSynchronizeHandler begin
214 // *********************************************************************
215 /**
216  * MessageProcessor for messages specific to chatroom synchronization.
217  */
218 struct ChatSynchronizeHandler : public MessageProcessor {
219 public:
220         ~ChatSynchronizeHandler()
221         {
223         }
225         ChatSynchronizeHandler(SessionManager* sm) : MessageProcessor(sm) 
226         {
228         }
230         LmHandlerResult 
231         operator()(MessageType mode, JabberMessage& m)
232         {
233                 switch(mode) {
234                         case CONNECT_REQUEST_RESPONSE_CHAT:
235                                 this->_sm->receiveConnectRequestResponseChat(m.sender.c_str());
236                                 break;
237                         case CHATROOM_SYNCHRONIZE_REQUEST:
238                                 if (this->_sm->session_data->status[IN_CHATROOM] && this->_sm->session_data->status[IN_WHITEBOARD]) {
239                                         // Send response.  Everyone in the chatroom will do this,
240                                         // but the client will accept only one response.
241                                         // The response is sent privately to the client
242                                         // <http://www.jabber.org/jeps/jep-0045.html#privatemessage>
243                                         this->_sm->sendMessage(CHATROOM_SYNCHRONIZE_RESPONSE, this->_sm->session_data->sequence_number, "", m.sender.c_str(), false);
244                                 }
245                                 break;
246                         case CHATROOM_SYNCHRONIZE_RESPONSE:
247                                 if (m.sequence != 0) {
248                                         // Set sequence number
249                                         this->_sm->session_data->sequence_number = m.sequence;
251                                         // Set status flags
252                                         this->_sm->session_data->status.set(WAITING_TO_SYNC_TO_CHAT, 0);
253                                         this->_sm->session_data->status.set(SYNCHRONIZING_WITH_CHAT, 1);
255                                         // Send document synchronization request
256                                         this->_sm->clearDocument();
257                                         this->_sm->setupInkscapeInterface();
258                                         this->_sm->sendMessage(CONNECT_REQUEST_RESPONSE_CHAT, m.sequence, "", m.sender.c_str(), false);
259                                 } else {
260                                         this->_sm->sendMessage(CHATROOM_SYNCHRONIZE_REQUEST, 0, "", this->_sm->session_data->recipient, true);
261                                 }
262                                 break;
263                         default:
264                                 break;
265                 }
266                 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
267         }
268 };
269 // *********************************************************************
270 // ChatSynchronizeHandler end
271 // *********************************************************************
276 // *********************************************************************
277 // Initializer
278 // *********************************************************************
279 void
280 initialize_received_message_processors(SessionManager* sm, MessageProcessorMap& mpm)
282         MessageProcessor* ch = new ChangeHandler(sm);
283         MessageProcessor* crh = new ConnectRequestHandler(sm);
284         MessageProcessor* ceh = new ConnectErrorHandler(sm);
285         MessageProcessor* csh = new ChatSynchronizeHandler(sm);
287         mpm[CHANGE_REPEATABLE] = ch;
288         mpm[CHANGE_NOT_REPEATABLE] = ch;
289         mpm[DUMMY_CHANGE] = ch;
290         mpm[CHANGE_COMMIT] = ch;
291         mpm[DOCUMENT_BEGIN] = ch;
292         mpm[DOCUMENT_END] = ch;
294         mpm[CONNECT_REQUEST_USER] = crh;
295         mpm[CONNECT_REQUEST_RESPONSE_USER] = crh;
296         mpm[CONNECTED_SIGNAL] = crh;
298         mpm[CONNECT_REQUEST_REFUSED_BY_PEER] = ceh;
299         mpm[ALREADY_IN_SESSION] = ceh;
300         mpm[DISCONNECTED_FROM_USER_SIGNAL] = ceh;
302         mpm[CONNECT_REQUEST_RESPONSE_CHAT] = csh;
303         mpm[CHATROOM_SYNCHRONIZE_REQUEST] = csh;
304         mpm[CHATROOM_SYNCHRONIZE_RESPONSE] = csh;
307 /*
308  * This function is provided solely for convenience and style.  You can, of course,
309  * delete every MessageProcessor in the map with your own loop.
310  */
311 void
312 destroy_received_message_processors(MessageProcessorMap& mpm)
314         mpm.clear();
321 /*
322   Local Variables:
323   mode:c++
324   c-file-style:"stroustrup"
325   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
326   indent-tabs-mode:nil
327   fill-column:99
328   End:
329 */
330 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :