Rename Internal-, Remote- and LegacyConnection to -Peer
[quassel.git] / src / common / remotepeer.cpp
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 #include <QHostAddress>
22 #include <QTimer>
23
24 #ifdef HAVE_SSL
25 #  include <QSslSocket>
26 #endif
27
28 #include "remotepeer.h"
29
30 using namespace Protocol;
31
32 RemotePeer::RemotePeer(QTcpSocket *socket, QObject *parent)
33     : SignalProxy::AbstractPeer(parent),
34     _socket(socket),
35     _signalProxy(0),
36     _heartBeatTimer(new QTimer(this)),
37     _heartBeatCount(0),
38     _lag(0)
39 {
40     socket->setParent(this);
41     connect(socket, SIGNAL(disconnected()), SIGNAL(disconnected()));
42     connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SIGNAL(error(QAbstractSocket::SocketError)));
43
44 #ifdef HAVE_SSL
45     QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
46     if (sslSocket)
47         connect(sslSocket, SIGNAL(encrypted()), SIGNAL(secureStateChanged()));
48 #endif
49
50     connect(_heartBeatTimer, SIGNAL(timeout()), SLOT(sendHeartBeat()));
51 }
52
53
54 QString RemotePeer::description() const
55 {
56     if (socket())
57         return socket()->peerAddress().toString();
58
59     return QString();
60 }
61
62
63 ::SignalProxy *RemotePeer::signalProxy() const
64 {
65     return _signalProxy;
66 }
67
68
69 void RemotePeer::setSignalProxy(::SignalProxy *proxy)
70 {
71     if (proxy == _signalProxy)
72         return;
73
74     if (!proxy) {
75         _heartBeatTimer->stop();
76         disconnect(signalProxy(), 0, this, 0);
77         _signalProxy = 0;
78         if (isOpen())
79             close();
80     }
81     else {
82         if (signalProxy()) {
83             qWarning() << Q_FUNC_INFO << "Setting another SignalProxy not supported, ignoring!";
84             return;
85         }
86         _signalProxy = proxy;
87         connect(proxy, SIGNAL(heartBeatIntervalChanged(int)), SLOT(changeHeartBeatInterval(int)));
88         _heartBeatTimer->setInterval(proxy->heartBeatInterval() * 1000);
89         _heartBeatTimer->start();
90     }
91 }
92
93
94 void RemotePeer::changeHeartBeatInterval(int secs)
95 {
96     if(secs <= 0)
97         _heartBeatTimer->stop();
98     else {
99         _heartBeatTimer->setInterval(secs * 1000);
100         _heartBeatTimer->start();
101     }
102 }
103
104
105 int RemotePeer::lag() const
106 {
107     return _lag;
108 }
109
110
111 QTcpSocket *RemotePeer::socket() const
112 {
113     return _socket;
114 }
115
116
117 bool RemotePeer::isSecure() const
118 {
119     if (socket()) {
120         if (isLocal())
121             return true;
122 #ifdef HAVE_SSL
123         QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket());
124         if (sslSocket && sslSocket->isEncrypted())
125             return true;
126 #endif
127     }
128     return false;
129 }
130
131
132 bool RemotePeer::isLocal() const
133 {
134     if (socket()) {
135         if (socket()->peerAddress() == QHostAddress::LocalHost || socket()->peerAddress() == QHostAddress::LocalHostIPv6)
136             return true;
137     }
138     return false;
139 }
140
141
142 bool RemotePeer::isOpen() const
143 {
144     return socket() && socket()->state() == QTcpSocket::ConnectedState;
145 }
146
147
148 void RemotePeer::close(const QString &reason)
149 {
150     if (!reason.isEmpty()) {
151         qWarning() << "Disconnecting:" << reason;
152     }
153
154     if (socket() && socket()->state() != QTcpSocket::UnconnectedState) {
155         socket()->disconnectFromHost();
156     }
157 }
158
159
160 void RemotePeer::handle(const HeartBeat &heartBeat)
161 {
162     dispatch(HeartBeatReply(heartBeat.timestamp()));
163 }
164
165
166 void RemotePeer::handle(const HeartBeatReply &heartBeatReply)
167 {
168     _heartBeatCount = 0;
169 #if QT_VERSION < 0x040700
170     emit lagUpdated(heartBeatReply.timestamp().time().msecsTo(QTime::currentTime()) / 2);
171 #else
172     emit lagUpdated(heartBeatReply.timestamp().msecsTo(QDateTime::currentDateTime()) / 2);
173 #endif
174 }
175
176
177 void RemotePeer::sendHeartBeat()
178 {
179     if (signalProxy()->maxHeartBeatCount() > 0 && _heartBeatCount >= signalProxy()->maxHeartBeatCount()) {
180         qWarning() << "Disconnecting peer:" << description()
181                    << "(didn't receive a heartbeat for over" << _heartBeatCount *_heartBeatTimer->interval() / 1000 << "seconds)";
182         socket()->close();
183         _heartBeatTimer->stop();
184         return;
185     }
186
187     if (_heartBeatCount > 0) {
188         _lag = _heartBeatCount * _heartBeatTimer->interval();
189         emit lagUpdated(_lag);
190     }
191
192     dispatch(HeartBeat(QDateTime::currentDateTime()));
193     ++_heartBeatCount;
194 }
195
196