Code

31f536616334cb7ba8b4a3cebe7b6c9279c9fb82
[inkscape.git] / src / jabber_whiteboard / callbacks.cpp
1 /**
2  * Whiteboard session manager
3  * Message dispatch devices and timeout triggers
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 "message-stack.h"
20 #include "document.h"
21 #include "desktop-handles.h"
23 #include "jabber_whiteboard/undo-stack-observer.h"
24 #include "jabber_whiteboard/jabber-handlers.h"
25 #include "jabber_whiteboard/defines.h"
26 #include "jabber_whiteboard/typedefs.h"
27 #include "jabber_whiteboard/session-manager.h"
28 #include "jabber_whiteboard/message-queue.h"
29 #include "jabber_whiteboard/message-handler.h"
30 #include "jabber_whiteboard/message-node.h"
31 #include "jabber_whiteboard/callbacks.h"
33 namespace Inkscape {
35 namespace Whiteboard {
37 Callbacks::Callbacks(SessionManager* sm) : _sm(sm) 
38 {
39         this->_sd = this->_sm->session_data;
40 }
42 Callbacks::~Callbacks() 
43 {
44 }
46 bool
47 Callbacks::dispatchSendQueue()
48 {
49         // If we're not in a whiteboard session, don't dispatch anything
50         if (!(this->_sd->status[IN_WHITEBOARD])) {
51                 return false;
52         }
54         // If the connection is not open, inform the user that an error has occurred
55         // and stop the queue
56         LmConnectionState state = lm_connection_get_state(this->_sd->connection);
58         if (state != LM_CONNECTION_STATE_OPEN && state != LM_CONNECTION_STATE_AUTHENTICATED) {
59                 sp_desktop_message_stack(this->_sm->desktop())->flash(Inkscape::INFORMATION_MESSAGE, _("Jabber connection lost."));
60                 return false;
61         }
63         // If there's nothing to send, don't do anything
64         if (this->_sd->send_queue->empty()) {
65                 return true;
66         }
68         // otherwise, send out the first change
69         MessageNode* first = this->_sd->send_queue->first();
71         sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::NORMAL_MESSAGE,
72                                                      ngettext("Sending message; %u message remaining in send queue.",
73                                                               "Sending message; %u messages remaining in send queue.",
74                                                               this->_sd->send_queue->size()),
75                                                      this->_sd->send_queue->size());
77         if (this->_sd->send_queue->empty()) {
78                 sp_desktop_message_stack(this->_sm->desktop())->flash(Inkscape::NORMAL_MESSAGE, _("Receive queue empty."));
79         }
81         switch (first->type()) {
82                 case CHANGE_REPEATABLE:
83                 case CHANGE_NOT_REPEATABLE:
84                 case CHANGE_COMMIT:
85                 case DOCUMENT_BEGIN:
86                 case DOCUMENT_END:
87                         this->_sm->sendMessage(first->type(), first->sequence(), first->message(), first->recipient().c_str(), first->chatroom());
88                         break;
89                 default:
90                         g_warning("MessageNode with unknown change type found in send queue; discarding message.  This may lead to desynchronization!");
91                         break;
92         }
94         this->_sd->send_queue->popFront();
96         return true;
97 }
99 bool
100 Callbacks::dispatchReceiveQueue()
102         CommitsQueue& rcq = this->_sd->recipients_committed_queue;
103         // See if we have any commits submitted. 
104         if (!rcq.empty()) {
105                 // Pick the first one off the queue.
106                 ReceivedCommitEvent& committer = rcq.front();
108                 // Find the commit event sender's receive queue.
109                 ReceiveMessageQueue* rmq = this->_sd->receive_queues[committer];
111                 if (rmq != NULL) {
112                         if (!rmq->empty()) {
113                                 // Get the first message off the sender's receive queue.
114                                 MessageNode* msg = rmq->first();
116                                 // There are a few message change types that demand special processing;
117                                 // handle them here.
118                                 //
119                                 // TODO: clean this up.  This should be a simple dispatching routine,
120                                 // and should not be performing operations like it's doing right now.
121                                 // These really should go into connection-establishment.cpp
122                                 // (although that should only happen after SessionManager itself
123                                 // is cleaned up).
124                                 switch(msg->type()) {
125                                         case CHANGE_COMMIT:
126                                                 rcq.pop_front();
127                                                 break;
128                                         case DOCUMENT_BEGIN:
129                                                 if (this->_sm->session_data->status[WAITING_TO_SYNC_TO_CHAT]) {
130                                                         this->_sm->session_data->status.set(WAITING_TO_SYNC_TO_CHAT, 0);
131                                                         this->_sm->session_data->status.set(SYNCHRONIZING_WITH_CHAT, 1);
132                                                 }
133                                                 break;
134                                         case DOCUMENT_END:
135                                                 rcq.pop_front();
136                                                 if (this->_sm->session_data->status[SYNCHRONIZING_WITH_CHAT]) {
137                                                         this->_sm->sendMessage(CONNECTED_SIGNAL, 0, "", this->_sm->session_data->recipient, true);
138                                                         this->_sm->session_data->status.set(SYNCHRONIZING_WITH_CHAT, 0);
139                                                         this->_sm->session_data->status.set(IN_CHATROOM, 1);
140                                                 } else {
141                                                         this->_sm->sendMessage(CONNECTED_SIGNAL, 0, "", msg->sender().c_str(), false);
142                                                 }
143                                                 break;
144                                         case CHANGE_REPEATABLE:
145                                         case CHANGE_NOT_REPEATABLE:
146                                         default:
147                                                 break;
148                                 }
149                                 
151                                 // Pass the message to the received change handler.
152                                 this->_sm->receiveChange(msg->message());
153                                 sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::NORMAL_MESSAGE,
154                                                                              ngettext("Receiving change; %u change left to process.",
155                                                                                       "Receiving change; %u changes left to process.",
156                                                                                       rmq->size()),
157                                                                              rmq->size());
159                                 
160                                 // Register this message as the latest message received from this
161                                 // sender.
162                                 rmq->setLatestProcessedPacket(msg->sequence());
164                                 // Pop this message off the receive queue.
165                                 rmq->popFront();
166                                 return true;
167                         } else {
168                                 // This really shouldn't happen.
169                                 // If we have a commit request from a valid sender, there should
170                                 // be something in the receive queue to process.  However, 
171                                 // if a client is buggy or has managed to trick us into accepting
172                                 // a commit, we should handle the event gracefully.
173                                 g_warning("Processing commit, but no changes to commit were found; ignoring commit event.");
175                                 // Remove this sender from the commit list.  If they want to commit
176                                 // later, they can.
177                                 rcq.pop_front();
178                                 return true;
179                         }
180                 } else {
181                         // If the receive queue returned is NULL, then we don't know about
182                         // this sender.  Remove the sender from the commit list.
183                         g_warning("Attempting to process commit from unknown sender; ignoring.");
184                         rcq.pop_front();
185                         return true;
186                 }
187         } else {
188                 return true;
189         }
197 /*
198   Local Variables:
199   mode:c++
200   c-file-style:"stroustrup"
201   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
202   indent-tabs-mode:nil
203   fill-column:99
204   End:
205 */
206 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :