2
* Whiteboard session manager
3
* Jabber received message processors
6
* David Yip <yipdw@rose-hulman.edu>
8
* Copyright (c) 2005 Authors
10
* Released under GNU GPL, read the file 'COPYING' for more information
14
#include <loudmouth/loudmouth.h>
17
#include <glibmm/i18n.h>
19
#include "xml/session.h"
20
#include "xml/document.h"
22
#include "desktop-handles.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"
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
// *********************************************************************
47
* MessageProcessor for document change and event commit messages.
49
struct ChangeHandler : public MessageProcessor {
56
ChangeHandler(SessionManager* sm) : MessageProcessor(sm)
62
operator()(MessageType mode, JabberMessage& p)
65
bool chatroom = this->_sm->session_data->status[IN_CHATROOM];
67
ReceiveMessageQueue* rmq = this->_sm->session_data->receive_queues[p.sender];
71
case CHANGE_REPEATABLE:
72
case CHANGE_NOT_REPEATABLE:
74
msgNode = new MessageNode(p.sequence, p.sender, "", p.body, mode, false, chatroom);
76
Inkscape::GC::release(msgNode);
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);
82
Inkscape::GC::release(msgNode);
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);
88
Inkscape::GC::release(msgNode);
95
g_warning("Received message from unknown sender %s", p.sender.c_str());
98
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
101
// *********************************************************************
103
// *********************************************************************
106
// *********************************************************************
107
// ConnectRequestHandler begin
108
// *********************************************************************
110
* MessageProcessor for connection request messages.
112
struct ConnectRequestHandler : public MessageProcessor {
114
~ConnectRequestHandler()
119
ConnectRequestHandler(SessionManager* sm) : MessageProcessor(sm)
125
operator()(MessageType mode, JabberMessage& m)
127
std::bitset< NUM_FLAGS >& status = this->_sm->session_data->status;
129
case CONNECT_REQUEST_USER:
130
this->_sm->receiveConnectRequest(m.sender.c_str());
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);
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());
145
sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::INFORMATION_MESSAGE, _("<b>%s</b> has joined the chatroom."), m.sender.c_str());
151
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
154
// *********************************************************************
155
// ConnectRequestHandler end
156
// *********************************************************************
161
// *********************************************************************
162
// ConnectErrorHandler begin
163
// *********************************************************************
165
* MessageProcessor for connection error messages.
167
struct ConnectErrorHandler : public MessageProcessor {
169
~ConnectErrorHandler()
174
ConnectErrorHandler(SessionManager* sm) : MessageProcessor(sm)
180
operator()(MessageType mode, JabberMessage& m)
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);
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);
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());
202
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
205
// *********************************************************************
206
// ConnectErrorHandler end
207
// *********************************************************************
212
// *********************************************************************
213
// ChatSynchronizeHandler begin
214
// *********************************************************************
216
* MessageProcessor for messages specific to chatroom synchronization.
218
struct ChatSynchronizeHandler : public MessageProcessor {
220
~ChatSynchronizeHandler()
225
ChatSynchronizeHandler(SessionManager* sm) : MessageProcessor(sm)
231
operator()(MessageType mode, JabberMessage& m)
234
case CONNECT_REQUEST_RESPONSE_CHAT:
235
this->_sm->receiveConnectRequestResponseChat(m.sender.c_str());
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);
246
case CHATROOM_SYNCHRONIZE_RESPONSE:
247
if (m.sequence != 0) {
248
// Set sequence number
249
this->_sm->session_data->sequence_number = m.sequence;
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);
260
this->_sm->sendMessage(CHATROOM_SYNCHRONIZE_REQUEST, 0, "", this->_sm->session_data->recipient, true);
266
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
269
// *********************************************************************
270
// ChatSynchronizeHandler end
271
// *********************************************************************
276
// *********************************************************************
278
// *********************************************************************
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;
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.
312
destroy_received_message_processors(MessageProcessorMap& mpm)
324
c-file-style:"stroustrup"
325
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
330
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :