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 CORENETWORK_H |
22 | #define CORENETWORK_H |
23 | |
24 | #include "network.h" |
25 | #include "coreircchannel.h" |
26 | #include "coreircuser.h" |
27 | |
28 | #include <QTimer> |
29 | |
30 | #ifdef HAVE_SSL |
31 | # include <QSslSocket> |
32 | # include <QSslError> |
33 | #else |
34 | # include <QTcpSocket> |
35 | #endif |
36 | |
37 | #ifdef HAVE_QCA2 |
38 | # include "cipher.h" |
39 | #endif |
40 | |
41 | #include "coresession.h" |
42 | |
43 | class CoreIdentity; |
44 | class CoreUserInputHandler; |
45 | class CoreIgnoreListManager; |
46 | class Event; |
47 | |
48 | class CoreNetwork : public Network |
49 | { |
50 | SYNCABLE_OBJECT |
51 | Q_OBJECT |
52 | |
53 | public: |
54 | CoreNetwork(const NetworkId &networkid, CoreSession *session); |
55 | ~CoreNetwork(); |
56 | inline virtual const QMetaObject *syncMetaObject() const { return &Network::staticMetaObject; } |
57 | |
58 | inline CoreIdentity *identityPtr() const { return coreSession()->identity(identity()); } |
59 | inline CoreSession *coreSession() const { return _coreSession; } |
60 | inline CoreNetworkConfig *networkConfig() const { return coreSession()->networkConfig(); } |
61 | |
62 | inline CoreUserInputHandler *userInputHandler() const { return _userInputHandler; } |
63 | inline CoreIgnoreListManager *ignoreListManager() { return coreSession()->ignoreListManager(); } |
64 | |
65 | //! Decode a string using the server (network) decoding. |
66 | inline QString serverDecode(const QByteArray &string) const { return decodeServerString(string); } |
67 | |
68 | //! Decode a string using a channel-specific encoding if one is set (and use the standard encoding else). |
69 | QString channelDecode(const QString &channelName, const QByteArray &string) const; |
70 | |
71 | //! Decode a string using an IrcUser-specific encoding, if one exists (using the standaed encoding else). |
72 | QString userDecode(const QString &userNick, const QByteArray &string) const; |
73 | |
74 | //! Encode a string using the server (network) encoding. |
75 | inline QByteArray serverEncode(const QString &string) const { return encodeServerString(string); } |
76 | |
77 | //! Encode a string using the channel-specific encoding, if set, and use the standard encoding else. |
78 | QByteArray channelEncode(const QString &channelName, const QString &string) const; |
79 | |
80 | //! Encode a string using the user-specific encoding, if set, and use the standard encoding else. |
81 | QByteArray userEncode(const QString &userNick, const QString &string) const; |
82 | |
83 | inline QString channelKey(const QString &channel) const { return _channelKeys.value(channel.toLower(), QString()); } |
84 | |
85 | inline bool isAutoWhoInProgress(const QString &channel) const { return _autoWhoPending.value(channel.toLower(), 0); } |
86 | |
87 | inline UserId userId() const { return _coreSession->user(); } |
88 | |
89 | inline QAbstractSocket::SocketState socketState() const { return socket.state(); } |
90 | inline bool socketConnected() const { return socket.state() == QAbstractSocket::ConnectedState; } |
91 | inline QHostAddress localAddress() const { return socket.localAddress(); } |
92 | inline QHostAddress peerAddress() const { return socket.peerAddress(); } |
93 | inline quint16 localPort() const { return socket.localPort(); } |
94 | inline quint16 peerPort() const { return socket.peerPort(); } |
95 | |
96 | public slots: |
97 | virtual void setMyNick(const QString &mynick); |
98 | |
99 | virtual void requestConnect() const; |
100 | virtual void requestDisconnect() const; |
101 | virtual void requestSetNetworkInfo(const NetworkInfo &info); |
102 | |
103 | virtual void setUseAutoReconnect(bool); |
104 | virtual void setAutoReconnectInterval(quint32); |
105 | virtual void setAutoReconnectRetries(quint16); |
106 | |
107 | void setPingInterval(int interval); |
108 | |
109 | void connectToIrc(bool reconnecting = false); |
110 | void disconnectFromIrc(bool requested = true, const QString &reason = QString(), bool withReconnect = false); |
111 | |
112 | void userInput(BufferInfo bufferInfo, QString msg); |
113 | void putRawLine(QByteArray input); |
114 | void putCmd(const QString &cmd, const QList<QByteArray> ¶ms, const QByteArray &prefix = QByteArray()); |
115 | |
116 | void setChannelJoined(const QString &channel); |
117 | void setChannelParted(const QString &channel); |
118 | void addChannelKey(const QString &channel, const QString &key); |
119 | void removeChannelKey(const QString &channel); |
120 | |
121 | // Blowfish stuff |
122 | #ifdef HAVE_QCA2 |
123 | Cipher *cipher(const QString &recipient); |
124 | QByteArray cipherKey(const QString &recipient) const; |
125 | void setCipherKey(const QString &recipient, const QByteArray &key); |
126 | bool cipherUsesCBC(const QString &target); |
127 | #endif |
128 | |
129 | void setAutoWhoEnabled(bool enabled); |
130 | void setAutoWhoInterval(int interval); |
131 | void setAutoWhoDelay(int delay); |
132 | |
133 | bool setAutoWhoDone(const QString &channel); |
134 | |
135 | void updateIssuedModes(const QString &requestedModes); |
136 | void updatePersistentModes(QString addModes, QString removeModes); |
137 | void resetPersistentModes(); |
138 | |
139 | Server usedServer() const; |
140 | |
141 | inline void resetPingTimeout() { _pingCount = 0; } |
142 | |
143 | inline void displayMsg(Message::Type msgType, BufferInfo::Type bufferType, const QString &target, const QString &text, const QString &sender = "" , Message::Flags flags = Message::None) |
144 | { |
145 | emit displayMsg(networkId(), msgType, bufferType, target, text, sender, flags); |
146 | } |
147 | |
148 | |
149 | signals: |
150 | void recvRawServerMsg(QString); |
151 | void displayStatusMsg(QString); |
152 | void displayMsg(NetworkId, Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "" , Message::Flags flags = Message::None); |
153 | void disconnected(NetworkId networkId); |
154 | void connectionError(const QString &errorMsg); |
155 | |
156 | void quitRequested(NetworkId networkId); |
157 | void sslErrors(const QVariant &errorData); |
158 | |
159 | void newEvent(Event *event); |
160 | void socketInitialized(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); |
161 | void socketDisconnected(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); |
162 | |
163 | protected: |
164 | inline virtual IrcChannel *ircChannelFactory(const QString &channelname) { return new CoreIrcChannel(channelname, this); } |
165 | inline virtual IrcUser *ircUserFactory(const QString &hostmask) { return new CoreIrcUser(hostmask, this); } |
166 | |
167 | protected slots: |
168 | // TODO: remove cached cipher keys, when appropriate |
169 | //virtual void removeIrcUser(IrcUser *ircuser); |
170 | //virtual void removeIrcChannel(IrcChannel *ircChannel); |
171 | //virtual void removeChansAndUsers(); |
172 | |
173 | private slots: |
174 | void socketHasData(); |
175 | void socketError(QAbstractSocket::SocketError); |
176 | void socketInitialized(); |
177 | inline void socketCloseTimeout() { socket.abort(); } |
178 | void socketDisconnected(); |
179 | void socketStateChanged(QAbstractSocket::SocketState); |
180 | void networkInitialized(); |
181 | |
182 | void sendPerform(); |
183 | void restoreUserModes(); |
184 | void doAutoReconnect(); |
185 | void sendPing(); |
186 | void enablePingTimeout(bool enable = true); |
187 | void disablePingTimeout(); |
188 | void sendAutoWho(); |
189 | void startAutoWhoCycle(); |
190 | |
191 | #ifdef HAVE_SSL |
192 | void sslErrors(const QList<QSslError> &errors); |
193 | #endif |
194 | |
195 | void fillBucketAndProcessQueue(); |
196 | |
197 | void writeToSocket(const QByteArray &data); |
198 | |
199 | private: |
200 | CoreSession *_coreSession; |
201 | |
202 | #ifdef HAVE_SSL |
203 | QSslSocket socket; |
204 | #else |
205 | QTcpSocket socket; |
206 | #endif |
207 | |
208 | CoreUserInputHandler *_userInputHandler; |
209 | |
210 | QHash<QString, QString> _channelKeys; // stores persistent channels and their passwords, if any |
211 | |
212 | QTimer _autoReconnectTimer; |
213 | int _autoReconnectCount; |
214 | |
215 | QTimer _socketCloseTimer; |
216 | |
217 | /* this flag triggers quitRequested() once the socket is closed |
218 | * it is needed to determine whether or not the connection needs to be |
219 | * in the automatic session restore. */ |
220 | bool _quitRequested; |
221 | QString _quitReason; |
222 | |
223 | bool _previousConnectionAttemptFailed; |
224 | int _lastUsedServerIndex; |
225 | |
226 | QTimer _pingTimer; |
227 | uint _lastPingTime; |
228 | uint _pingCount; |
229 | bool _sendPings; |
230 | |
231 | QStringList _autoWhoQueue; |
232 | QHash<QString, int> _autoWhoPending; |
233 | QTimer _autoWhoTimer, _autoWhoCycleTimer; |
234 | |
235 | QTimer _tokenBucketTimer; |
236 | int _messageDelay; // token refill speed in ms |
237 | int _burstSize; // size of the token bucket |
238 | int _tokenBucket; // the virtual bucket that holds the tokens |
239 | QList<QByteArray> _msgQueue; |
240 | |
241 | QString _requestedUserModes; // 2 strings separated by a '-' character. first part are requested modes to add, the second to remove |
242 | }; |
243 | |
244 | |
245 | #endif //CORENETWORK_H |
246 | |