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