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 | #ifndef CORE_H |
22 | #define CORE_H |
23 | |
24 | #include <QDateTime> |
25 | #include <QString> |
26 | #include <QVariant> |
27 | #include <QTimer> |
28 | |
29 | #ifdef HAVE_SSL |
30 | # include <QSslSocket> |
31 | # include "sslserver.h" |
32 | #else |
33 | # include <QTcpSocket> |
34 | # include <QTcpServer> |
35 | #endif |
36 | |
37 | #include "bufferinfo.h" |
38 | #include "message.h" |
39 | #include "oidentdconfiggenerator.h" |
40 | #include "sessionthread.h" |
41 | #include "storage.h" |
42 | #include "types.h" |
43 | |
44 | class CoreAuthHandler; |
45 | class CoreSession; |
46 | struct NetworkInfo; |
47 | class SessionThread; |
48 | class SignalProxy; |
49 | |
50 | class AbstractSqlMigrationReader; |
51 | class AbstractSqlMigrationWriter; |
52 | |
53 | class Core : public QObject |
54 | { |
55 | Q_OBJECT |
56 | |
57 | public: |
58 | static Core *instance(); |
59 | static void destroy(); |
60 | |
61 | static void saveState(); |
62 | static void restoreState(); |
63 | |
64 | /*** Storage access ***/ |
65 | // These methods are threadsafe. |
66 | |
67 | //! Validate user |
68 | /** |
69 | * \param userName The user's login name |
70 | * \param password The user's uncrypted password |
71 | * \return The user's ID if valid; 0 otherwise |
72 | */ |
73 | static inline UserId validateUser(const QString &userName, const QString &password) { |
74 | return instance()->_storage->validateUser(userName, password); |
75 | } |
76 | |
77 | //! Store a user setting persistently |
78 | /** |
79 | * \param userId The users Id |
80 | * \param settingName The Name of the Setting |
81 | * \param data The Value |
82 | */ |
83 | static inline void setUserSetting(UserId userId, const QString &settingName, const QVariant &data) |
84 | { |
85 | instance()->_storage->setUserSetting(userId, settingName, data); |
86 | } |
87 | |
88 | |
89 | //! Retrieve a persistent user setting |
90 | /** |
91 | * \param userId The users Id |
92 | * \param settingName The Name of the Setting |
93 | * \param defaultValue Value to return in case it's unset. |
94 | * \return the Value of the Setting or the default value if it is unset. |
95 | */ |
96 | static inline QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultValue = QVariant()) |
97 | { |
98 | return instance()->_storage->getUserSetting(userId, settingName, defaultValue); |
99 | } |
100 | |
101 | |
102 | /* Identity handling */ |
103 | static inline IdentityId createIdentity(UserId user, CoreIdentity &identity) |
104 | { |
105 | return instance()->_storage->createIdentity(user, identity); |
106 | } |
107 | |
108 | |
109 | static bool updateIdentity(UserId user, const CoreIdentity &identity) |
110 | { |
111 | return instance()->_storage->updateIdentity(user, identity); |
112 | } |
113 | |
114 | |
115 | static void removeIdentity(UserId user, IdentityId identityId) |
116 | { |
117 | instance()->_storage->removeIdentity(user, identityId); |
118 | } |
119 | |
120 | |
121 | static QList<CoreIdentity> identities(UserId user) |
122 | { |
123 | return instance()->_storage->identities(user); |
124 | } |
125 | |
126 | |
127 | //! Create a Network in the Storage and store it's Id in the given NetworkInfo |
128 | /** \note This method is thredsafe. |
129 | * |
130 | * \param user The core user |
131 | * \param networkInfo a NetworkInfo definition to store the newly created ID in |
132 | * \return true if successfull. |
133 | */ |
134 | static bool createNetwork(UserId user, NetworkInfo &info); |
135 | |
136 | //! Apply the changes to NetworkInfo info to the storage engine |
137 | /** \note This method is thredsafe. |
138 | * |
139 | * \param user The core user |
140 | * \param networkInfo The Updated NetworkInfo |
141 | * \return true if successfull. |
142 | */ |
143 | static inline bool updateNetwork(UserId user, const NetworkInfo &info) |
144 | { |
145 | return instance()->_storage->updateNetwork(user, info); |
146 | } |
147 | |
148 | |
149 | //! Permanently remove a Network and all the data associated with it. |
150 | /** \note This method is thredsafe. |
151 | * |
152 | * \param user The core user |
153 | * \param networkId The network to delete |
154 | * \return true if successfull. |
155 | */ |
156 | static inline bool removeNetwork(UserId user, const NetworkId &networkId) |
157 | { |
158 | return instance()->_storage->removeNetwork(user, networkId); |
159 | } |
160 | |
161 | |
162 | //! Returns a list of all NetworkInfos for the given UserId user |
163 | /** \note This method is thredsafe. |
164 | * |
165 | * \param user The core user |
166 | * \return QList<NetworkInfo>. |
167 | */ |
168 | static inline QList<NetworkInfo> networks(UserId user) |
169 | { |
170 | return instance()->_storage->networks(user); |
171 | } |
172 | |
173 | |
174 | //! Get a list of Networks to restore |
175 | /** Return a list of networks the user was connected at the time of core shutdown |
176 | * \note This method is threadsafe. |
177 | * |
178 | * \param user The User Id in question |
179 | */ |
180 | static inline QList<NetworkId> connectedNetworks(UserId user) |
181 | { |
182 | return instance()->_storage->connectedNetworks(user); |
183 | } |
184 | |
185 | |
186 | //! Update the connected state of a network |
187 | /** \note This method is threadsafe |
188 | * |
189 | * \param user The Id of the networks owner |
190 | * \param networkId The Id of the network |
191 | * \param isConnected whether the network is connected or not |
192 | */ |
193 | static inline void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected) |
194 | { |
195 | return instance()->_storage->setNetworkConnected(user, networkId, isConnected); |
196 | } |
197 | |
198 | |
199 | //! Get a hash of channels with their channel keys for a given network |
200 | /** The keys are channel names and values are passwords (possibly empty) |
201 | * \note This method is threadsafe |
202 | * |
203 | * \param user The id of the networks owner |
204 | * \param networkId The Id of the network |
205 | */ |
206 | static inline QHash<QString, QString> persistentChannels(UserId user, const NetworkId &networkId) |
207 | { |
208 | return instance()->_storage->persistentChannels(user, networkId); |
209 | } |
210 | |
211 | |
212 | //! Update the connected state of a channel |
213 | /** \note This method is threadsafe |
214 | * |
215 | * \param user The Id of the networks owner |
216 | * \param networkId The Id of the network |
217 | * \param channel The name of the channel |
218 | * \param isJoined whether the channel is connected or not |
219 | */ |
220 | static inline void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined) |
221 | { |
222 | return instance()->_storage->setChannelPersistent(user, networkId, channel, isJoined); |
223 | } |
224 | |
225 | |
226 | //! Update the key of a channel |
227 | /** \note This method is threadsafe |
228 | * |
229 | * \param user The Id of the networks owner |
230 | * \param networkId The Id of the network |
231 | * \param channel The name of the channel |
232 | * \param key The key of the channel (possibly empty) |
233 | */ |
234 | static inline void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key) |
235 | { |
236 | return instance()->_storage->setPersistentChannelKey(user, networkId, channel, key); |
237 | } |
238 | |
239 | |
240 | //! retrieve last known away message for session restore |
241 | /** \note This method is threadsafe |
242 | * |
243 | * \param user The Id of the networks owner |
244 | * \param networkId The Id of the network |
245 | */ |
246 | static inline QString awayMessage(UserId user, NetworkId networkId) |
247 | { |
248 | return instance()->_storage->awayMessage(user, networkId); |
249 | } |
250 | |
251 | |
252 | //! Make away message persistent for session restore |
253 | /** \note This method is threadsafe |
254 | * |
255 | * \param user The Id of the networks owner |
256 | * \param networkId The Id of the network |
257 | * \param awayMsg The current away message of own user |
258 | */ |
259 | static inline void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) |
260 | { |
261 | return instance()->_storage->setAwayMessage(user, networkId, awayMsg); |
262 | } |
263 | |
264 | |
265 | //! retrieve last known user mode for session restore |
266 | /** \note This method is threadsafe |
267 | * |
268 | * \param user The Id of the networks owner |
269 | * \param networkId The Id of the network |
270 | */ |
271 | static inline QString userModes(UserId user, NetworkId networkId) |
272 | { |
273 | return instance()->_storage->userModes(user, networkId); |
274 | } |
275 | |
276 | |
277 | //! Make our user modes persistent for session restore |
278 | /** \note This method is threadsafe |
279 | * |
280 | * \param user The Id of the networks owner |
281 | * \param networkId The Id of the network |
282 | * \param userModes The current user modes of own user |
283 | */ |
284 | static inline void setUserModes(UserId user, NetworkId networkId, const QString &userModes) |
285 | { |
286 | return instance()->_storage->setUserModes(user, networkId, userModes); |
287 | } |
288 | |
289 | |
290 | //! Get the unique BufferInfo for the given combination of network and buffername for a user. |
291 | /** \note This method is threadsafe. |
292 | * |
293 | * \param user The core user who owns this buffername |
294 | * \param networkId The network id |
295 | * \param type The type of the buffer (StatusBuffer, Channel, etc.) |
296 | * \param buffer The buffer name (if empty, the net's status buffer is returned) |
297 | * \param create Whether or not the buffer should be created if it doesnt exist |
298 | * \return The BufferInfo corresponding to the given network and buffer name, or 0 if not found |
299 | */ |
300 | static inline BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "" , bool create = true) |
301 | { |
302 | return instance()->_storage->bufferInfo(user, networkId, type, buffer, create); |
303 | } |
304 | |
305 | |
306 | //! Get the unique BufferInfo for a bufferId |
307 | /** \note This method is threadsafe |
308 | * \param user The core user who owns this buffername |
309 | * \param bufferId The id of the buffer |
310 | * \return The BufferInfo corresponding to the given buffer id, or an invalid BufferInfo if not found. |
311 | */ |
312 | static inline BufferInfo getBufferInfo(UserId user, const BufferId &bufferId) |
313 | { |
314 | return instance()->_storage->getBufferInfo(user, bufferId); |
315 | } |
316 | |
317 | |
318 | //! Store a Message in the storage backend and set it's unique Id. |
319 | /** \note This method is threadsafe. |
320 | * |
321 | * \param message The message object to be stored |
322 | * \return true on success |
323 | */ |
324 | static inline bool storeMessage(Message &message) |
325 | { |
326 | return instance()->_storage->logMessage(message); |
327 | } |
328 | |
329 | |
330 | //! Store a list of Messages in the storage backend and set their unique Id. |
331 | /** \note This method is threadsafe. |
332 | * |
333 | * \param messages The list message objects to be stored |
334 | * \return true on success |
335 | */ |
336 | static inline bool storeMessages(MessageList &messages) |
337 | { |
338 | return instance()->_storage->logMessages(messages); |
339 | } |
340 | |
341 | |
342 | //! Request a certain number messages stored in a given buffer. |
343 | /** \param buffer The buffer we request messages from |
344 | * \param first if != -1 return only messages with a MsgId >= first |
345 | * \param last if != -1 return only messages with a MsgId < last |
346 | * \param limit if != -1 limit the returned list to a max of \limit entries |
347 | * \return The requested list of messages |
348 | */ |
349 | static inline QList<Message> requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1) |
350 | { |
351 | return instance()->_storage->requestMsgs(user, bufferId, first, last, limit); |
352 | } |
353 | |
354 | |
355 | //! Request a certain number of messages across all buffers |
356 | /** \param first if != -1 return only messages with a MsgId >= first |
357 | * \param last if != -1 return only messages with a MsgId < last |
358 | * \param limit Max amount of messages |
359 | * \return The requested list of messages |
360 | */ |
361 | static inline QList<Message> requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1) |
362 | { |
363 | return instance()->_storage->requestAllMsgs(user, first, last, limit); |
364 | } |
365 | |
366 | |
367 | //! Request a list of all buffers known to a user. |
368 | /** This method is used to get a list of all buffers we have stored a backlog from. |
369 | * \note This method is threadsafe. |
370 | * |
371 | * \param user The user whose buffers we request |
372 | * \return A list of the BufferInfos for all buffers as requested |
373 | */ |
374 | static inline QList<BufferInfo> requestBuffers(UserId user) |
375 | { |
376 | return instance()->_storage->requestBuffers(user); |
377 | } |
378 | |
379 | |
380 | //! Request a list of BufferIds for a given NetworkId |
381 | /** \note This method is threadsafe. |
382 | * |
383 | * \param user The user whose buffers we request |
384 | * \param networkId The NetworkId of the network in question |
385 | * \return List of BufferIds belonging to the Network |
386 | */ |
387 | static inline QList<BufferId> requestBufferIdsForNetwork(UserId user, NetworkId networkId) |
388 | { |
389 | return instance()->_storage->requestBufferIdsForNetwork(user, networkId); |
390 | } |
391 | |
392 | |
393 | //! Remove permanently a buffer and it's content from the storage backend |
394 | /** This call cannot be reverted! |
395 | * \note This method is threadsafe. |
396 | * |
397 | * \param user The user who is the owner of the buffer |
398 | * \param bufferId The bufferId |
399 | * \return true if successfull |
400 | */ |
401 | static inline bool removeBuffer(const UserId &user, const BufferId &bufferId) |
402 | { |
403 | return instance()->_storage->removeBuffer(user, bufferId); |
404 | } |
405 | |
406 | |
407 | //! Rename a Buffer |
408 | /** \note This method is threadsafe. |
409 | * \param user The id of the buffer owner |
410 | * \param bufferId The bufferId |
411 | * \param newName The new name of the buffer |
412 | * \return true if successfull |
413 | */ |
414 | static inline bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) |
415 | { |
416 | return instance()->_storage->renameBuffer(user, bufferId, newName); |
417 | } |
418 | |
419 | |
420 | //! Merge the content of two Buffers permanently. This cannot be reversed! |
421 | /** \note This method is threadsafe. |
422 | * \param user The id of the buffer owner |
423 | * \param bufferId1 The bufferId of the remaining buffer |
424 | * \param bufferId2 The buffer that is about to be removed |
425 | * \return true if successfulln |
426 | */ |
427 | static inline bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) |
428 | { |
429 | return instance()->_storage->mergeBuffersPermanently(user, bufferId1, bufferId2); |
430 | } |
431 | |
432 | |
433 | //! Update the LastSeenDate for a Buffer |
434 | /** This Method is used to make the LastSeenDate of a Buffer persistent |
435 | * \note This method is threadsafe. |
436 | * |
437 | * \param user The Owner of that Buffer |
438 | * \param bufferId The buffer id |
439 | * \param MsgId The Message id of the message that has been just seen |
440 | */ |
441 | static inline void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) |
442 | { |
443 | return instance()->_storage->setBufferLastSeenMsg(user, bufferId, msgId); |
444 | } |
445 | |
446 | |
447 | //! Get a Hash of all last seen message ids |
448 | /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds |
449 | * \note This method is threadsafe. |
450 | * |
451 | * \param user The Owner of the buffers |
452 | */ |
453 | static inline QHash<BufferId, MsgId> bufferLastSeenMsgIds(UserId user) |
454 | { |
455 | return instance()->_storage->bufferLastSeenMsgIds(user); |
456 | } |
457 | |
458 | |
459 | //! Update the MarkerLineMsgId for a Buffer |
460 | /** This Method is used to make the marker line position of a Buffer persistent |
461 | * \note This method is threadsafe. |
462 | * |
463 | * \param user The Owner of that Buffer |
464 | * \param bufferId The buffer id |
465 | * \param MsgId The Message id where the marker line should be placed |
466 | */ |
467 | static inline void setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) |
468 | { |
469 | return instance()->_storage->setBufferMarkerLineMsg(user, bufferId, msgId); |
470 | } |
471 | |
472 | |
473 | //! Get a Hash of all marker line message ids |
474 | /** This Method is called when the Quassel Core is started to restore the MarkerLineMsgIds |
475 | * \note This method is threadsafe. |
476 | * |
477 | * \param user The Owner of the buffers |
478 | */ |
479 | static inline QHash<BufferId, MsgId> bufferMarkerLineMsgIds(UserId user) |
480 | { |
481 | return instance()->_storage->bufferMarkerLineMsgIds(user); |
482 | } |
483 | |
484 | |
485 | static inline QDateTime startTime() { return instance()->_startTime; } |
486 | static inline bool isConfigured() { return instance()->_configured; } |
487 | static bool sslSupported(); |
488 | static QVariantList backendInfo(); |
489 | |
490 | static QString setup(const QString &adminUser, const QString &adminPassword, const QString &backend, const QVariantMap &setupData); |
491 | |
492 | static inline QTimer &syncTimer() { return instance()->_storageSyncTimer; } |
493 | |
494 | inline OidentdConfigGenerator *oidentdConfigGenerator() const { return _oidentdConfigGenerator; } |
495 | |
496 | static const int AddClientEventId; |
497 | |
498 | public slots: |
499 | //! Make storage data persistent |
500 | /** \note This method is threadsafe. |
501 | */ |
502 | void syncStorage(); |
503 | void setupInternalClientSession(InternalPeer *clientConnection); |
504 | QString setupCore(const QString &adminUser, const QString &adminPassword, const QString &backend, const QVariantMap &setupData); |
505 | |
506 | signals: |
507 | //! Sent when a BufferInfo is updated in storage. |
508 | void bufferInfoUpdated(UserId user, const BufferInfo &info); |
509 | |
510 | //! Relay from CoreSession::sessionState(). Used for internal connection only |
511 | void sessionState(const Protocol::SessionState &sessionState); |
512 | |
513 | protected: |
514 | virtual void customEvent(QEvent *event); |
515 | |
516 | private slots: |
517 | bool startListening(); |
518 | void stopListening(const QString &msg = QString()); |
519 | void incomingConnection(); |
520 | void clientDisconnected(); |
521 | |
522 | bool initStorage(const QString &backend, const QVariantMap &settings, bool setup = false); |
523 | |
524 | void socketError(QAbstractSocket::SocketError err, const QString &errorString); |
525 | void setupClientSession(RemotePeer *, UserId); |
526 | |
527 | private: |
528 | Core(); |
529 | ~Core(); |
530 | void init(); |
531 | static Core *instanceptr; |
532 | |
533 | SessionThread *createSession(UserId userId, bool restoreState = false); |
534 | void addClientHelper(RemotePeer *peer, UserId uid); |
535 | //void processCoreSetup(QTcpSocket *socket, QVariantMap &msg); |
536 | QString setupCoreForInternalUsage(); |
537 | |
538 | void registerStorageBackends(); |
539 | bool registerStorageBackend(Storage *); |
540 | void unregisterStorageBackends(); |
541 | void unregisterStorageBackend(Storage *); |
542 | bool selectBackend(const QString &backend); |
543 | void createUser(); |
544 | void changeUserPass(const QString &username); |
545 | void saveBackendSettings(const QString &backend, const QVariantMap &settings); |
546 | QVariantMap promptForSettings(const Storage *storage); |
547 | |
548 | private: |
549 | QSet<CoreAuthHandler *> _connectingClients; |
550 | QHash<UserId, SessionThread *> sessions; |
551 | Storage *_storage; |
552 | QTimer _storageSyncTimer; |
553 | |
554 | #ifdef HAVE_SSL |
555 | SslServer _server, _v6server; |
556 | #else |
557 | QTcpServer _server, _v6server; |
558 | #endif |
559 | |
560 | OidentdConfigGenerator *_oidentdConfigGenerator; |
561 | |
562 | QHash<QString, Storage *> _storageBackends; |
563 | |
564 | QDateTime _startTime; |
565 | |
566 | bool _configured; |
567 | |
568 | static AbstractSqlMigrationReader *getMigrationReader(Storage *storage); |
569 | static AbstractSqlMigrationWriter *getMigrationWriter(Storage *storage); |
570 | static void stdInEcho(bool on); |
571 | static inline void enableStdInEcho() { stdInEcho(true); } |
572 | static inline void disableStdInEcho() { stdInEcho(false); } |
573 | }; |
574 | |
575 | |
576 | #endif |
577 | |