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