1/***************************************************************************
2 * Copyright (C) 2005-2014 by the Quassel Project *
3 * devel@quassel-irc.org *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
20
21#include <QCoreApplication>
22#include <QThread>
23
24#include "internalpeer.h"
25
26using namespace Protocol;
27
28template<class T>
29class PeerMessageEvent : public QEvent
30{
31public:
32 PeerMessageEvent(InternalPeer *sender, InternalPeer::EventType eventType, const T &message)
33 : QEvent(QEvent::Type(eventType)), sender(sender), message(message) {}
34 InternalPeer *sender;
35 T message;
36};
37
38
39InternalPeer::InternalPeer(QObject *parent)
40 : Peer(0, parent),
41 _proxy(0),
42 _peer(0),
43 _isOpen(true)
44{
45
46}
47
48
49InternalPeer::~InternalPeer()
50{
51 if (_isOpen)
52 emit disconnected();
53}
54
55
56QString InternalPeer::description() const
57{
58 return tr("internal connection");
59}
60
61
62bool InternalPeer::isOpen() const
63{
64 return true;
65}
66
67
68bool InternalPeer::isSecure() const
69{
70 return true;
71}
72
73
74bool InternalPeer::isLocal() const
75{
76 return true;
77}
78
79
80void InternalPeer::close(const QString &reason)
81{
82 // FIXME
83 Q_UNUSED(reason)
84 qWarning() << "closing not implemented!";
85}
86
87
88int InternalPeer::lag() const
89{
90 return 0;
91}
92
93
94::SignalProxy *InternalPeer::signalProxy() const
95{
96 return _proxy;
97}
98
99
100void InternalPeer::setSignalProxy(::SignalProxy *proxy)
101{
102 if (!proxy && _proxy) {
103 _proxy = 0;
104 if (_isOpen) {
105 _isOpen = false;
106 emit disconnected();
107 }
108 return;
109 }
110
111 if (proxy && !_proxy) {
112 _proxy = proxy;
113 return;
114 }
115
116 qWarning() << Q_FUNC_INFO << "Changing the SignalProxy is not supported!";
117}
118
119
120void InternalPeer::setPeer(InternalPeer *peer)
121{
122 if (_peer) {
123 qWarning() << Q_FUNC_INFO << "Peer already set, ignoring!";
124 return;
125 }
126 _peer = peer;
127 connect(peer, SIGNAL(disconnected()), SLOT(peerDisconnected()));
128}
129
130
131void InternalPeer::peerDisconnected()
132{
133 disconnect(_peer, 0, this, 0);
134 _peer = 0;
135 if (_isOpen) {
136 _isOpen = false;
137 emit disconnected();
138 }
139}
140
141
142void InternalPeer::dispatch(const SyncMessage &msg)
143{
144 dispatch(SyncMessageEvent, msg);
145}
146
147
148void InternalPeer::dispatch(const RpcCall &msg)
149{
150 dispatch(RpcCallEvent, msg);
151}
152
153
154void InternalPeer::dispatch(const InitRequest &msg)
155{
156 dispatch(InitRequestEvent, msg);
157}
158
159
160void InternalPeer::dispatch(const InitData &msg)
161{
162 dispatch(InitDataEvent, msg);
163}
164
165
166template<class T>
167void InternalPeer::dispatch(EventType eventType, const T &msg)
168{
169 if (!_peer) {
170 qWarning() << Q_FUNC_INFO << "Cannot dispatch a message without a peer!";
171 return;
172 }
173
174 if(QThread::currentThread() == _peer->thread())
175 _peer->handle(msg);
176 else
177 QCoreApplication::postEvent(_peer, new PeerMessageEvent<T>(this, eventType, msg));
178}
179
180
181void InternalPeer::customEvent(QEvent *event)
182{
183 switch ((int)event->type()) {
184 case SyncMessageEvent: {
185 PeerMessageEvent<SyncMessage> *e = static_cast<PeerMessageEvent<SyncMessage> *>(event);
186 handle(e->message);
187 break;
188 }
189 case RpcCallEvent: {
190 PeerMessageEvent<RpcCall> *e = static_cast<PeerMessageEvent<RpcCall> *>(event);
191 handle(e->message);
192 break;
193 }
194 case InitRequestEvent: {
195 PeerMessageEvent<InitRequest> *e = static_cast<PeerMessageEvent<InitRequest> *>(event);
196 handle(e->message);
197 break;
198 }
199 case InitDataEvent: {
200 PeerMessageEvent<InitData> *e = static_cast<PeerMessageEvent<InitData> *>(event);
201 handle(e->message);
202 break;
203 }
204
205 default:
206 qWarning() << Q_FUNC_INFO << "Received unknown custom event:" << event->type();
207 return;
208 }
209
210 event->accept();
211}
212