Implement support for the HAProxy proxy protocol
[quassel.git] / src / common / proxyline.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2020 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 "proxyline.h"
22
23 #include "ircdecoder.h"
24
25 ProxyLine ProxyLine::parseProxyLine(const QByteArray& line)
26 {
27     ProxyLine result;
28
29     int start = 0;
30     if (line.startsWith("PROXY")) {
31         start = 5;
32     }
33     IrcDecoder::skipEmptyParts(line, start);
34     QByteArray protocol = IrcDecoder::extractFragment(line, start);
35     if (protocol == "TCP4") {
36         result.protocol = QAbstractSocket::IPv4Protocol;
37     } else if (protocol == "TCP6") {
38         result.protocol = QAbstractSocket::IPv6Protocol;
39     } else {
40         result.protocol = QAbstractSocket::UnknownNetworkLayerProtocol;
41     }
42
43     if (result.protocol != QAbstractSocket::UnknownNetworkLayerProtocol) {
44         bool ok;
45         IrcDecoder::skipEmptyParts(line, start);
46         result.sourceHost = QHostAddress(QString::fromLatin1(IrcDecoder::extractFragment(line, start)));
47         IrcDecoder::skipEmptyParts(line, start);
48         result.sourcePort = QString::fromLatin1(IrcDecoder::extractFragment(line, start)).toUShort(&ok);
49         if (!ok) result.sourcePort = 0;
50         IrcDecoder::skipEmptyParts(line, start);
51         result.targetHost = QHostAddress(QString::fromLatin1(IrcDecoder::extractFragment(line, start)));
52         IrcDecoder::skipEmptyParts(line, start);
53         result.targetPort = QString::fromLatin1(IrcDecoder::extractFragment(line, start)).toUShort(&ok);
54         if (!ok) result.targetPort = 0;
55     }
56
57     return result;
58 }
59
60
61 QDebug operator<<(QDebug dbg, const ProxyLine& p) {
62     dbg.nospace();
63     dbg << "(protocol = " << p.protocol;
64     if (p.protocol == QAbstractSocket::UnknownNetworkLayerProtocol) {
65         dbg << ")";
66     } else {
67         dbg << ", sourceHost = " << p.sourceHost << ", sourcePort = " << p.sourcePort << ", targetHost = " << p.targetHost << ", targetPort = " << p.targetPort << ")";
68     }
69     return dbg.space();
70 }