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