• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • kdecore
  • network
k3httpproxysocketdevice.cpp
Go to the documentation of this file.
1/* -*- C++ -*-
2 * Copyright (C) 2003 Thiago Macieira <thiago@kde.org>
3 *
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include "k3httpproxysocketdevice.h"
26
27#include <config.h>
28#include <config-network.h>
29
30#include <sys/types.h>
31#include <sys/socket.h>
32
33#include <QSocketNotifier>
34#include <QByteArray>
35
36#include "k3resolver.h"
37#include "k3socketaddress.h"
38#include "k3socketdevice.h"
39
40using namespace KNetwork;
41
42KResolverEntry KHttpProxySocketDevice::defaultProxy;
43
44class KNetwork::KHttpProxySocketDevicePrivate
45{
46public:
47 KResolverEntry proxy;
48 QByteArray request;
49 QByteArray reply;
50 KSocketAddress peer;
51
52 KHttpProxySocketDevicePrivate()
53 : proxy(KHttpProxySocketDevice::defaultProxy)
54 { }
55};
56
57KHttpProxySocketDevice::KHttpProxySocketDevice(const KSocketBase* parent)
58 : KSocketDevice(parent), d(new KHttpProxySocketDevicePrivate)
59{
60}
61
62KHttpProxySocketDevice::KHttpProxySocketDevice(const KResolverEntry& proxy)
63 : d(new KHttpProxySocketDevicePrivate)
64{
65 d->proxy = proxy;
66}
67
68KHttpProxySocketDevice::~KHttpProxySocketDevice()
69{
70 // nothing special to be done during closing
71 // KSocketDevice::~KSocketDevice closes the socket
72
73 delete d;
74}
75
76int KHttpProxySocketDevice::capabilities() const
77{
78 return CanConnectString | CanNotBind | CanNotListen | CanNotUseDatagrams;
79}
80
81const KResolverEntry&
82KHttpProxySocketDevice::proxyServer() const
83{
84 return d->proxy;
85}
86
87void KHttpProxySocketDevice::setProxyServer(const KResolverEntry& proxy)
88{
89 d->proxy = proxy;
90}
91
92void KHttpProxySocketDevice::close()
93{
94 d->reply = d->request = QByteArray();
95 d->peer = KSocketAddress();
96 KSocketDevice::close();
97}
98
99KSocketAddress KHttpProxySocketDevice::peerAddress() const
100{
101 if (isOpen())
102 return d->peer;
103 return KSocketAddress();
104}
105
106KSocketAddress KHttpProxySocketDevice::externalAddress() const
107{
108 return KSocketAddress();
109}
110
111bool KHttpProxySocketDevice::connect(const KResolverEntry& address)
112{
113 if (d->proxy.family() == AF_UNSPEC)
114 // no proxy server set !
115 return KSocketDevice::connect(address);
116
117 if (isOpen())
118 {
119 // socket is already open
120 resetError();
121 return true;
122 }
123
124 if (m_sockfd == -1)
125 // socket isn't created yet
126 return connect(address.address().nodeName(),
127 address.address().serviceName());
128
129 d->peer = address.address();
130 return parseServerReply();
131}
132
133bool KHttpProxySocketDevice::connect(const QString& node, const QString& service)
134{
135 // same safety checks as above
136 if (m_sockfd == -1 && (d->proxy.family() == AF_UNSPEC ||
137 node.isEmpty() || service.isEmpty()))
138 {
139 // no proxy server set !
140 setError(NotSupported);
141 return false;
142 }
143
144 if (isOpen())
145 {
146 // socket is already open
147 return true;
148 }
149
150 if (m_sockfd == -1)
151 {
152 // must create the socket
153 if (!KSocketDevice::connect(d->proxy))
154 return false; // also unable to contact proxy server
155 KActiveSocketBase::close();
156
157 // prepare the request
158 QString request = QLatin1String("CONNECT %1:%2 HTTP/1.1\r\n"
159 "Cache-Control: no-cache\r\n"
160 "Host: \r\n"
161 "\r\n");
162 QString node2 = node;
163 if (node.contains(QLatin1Char(':')))
164 node2 = QLatin1Char('[') + node + QLatin1Char(']');
165
166 d->request = request.arg(node2).arg(service).toLatin1();
167 }
168
169 return parseServerReply();
170}
171
172bool KHttpProxySocketDevice::parseServerReply()
173{
174 // make sure we're connected
175 if (!KSocketDevice::connect(d->proxy))
176 if (error() == InProgress)
177 return true;
178 else if (error() != NoError)
179 return false;
180
181 if (!d->request.isEmpty())
182 {
183 // send request
184 qint64 written = writeData(d->request, d->request.length());
185 if (written < 0)
186 {
187 qDebug("KHttpProxySocketDevice: would block writing request!");
188 if (error() == WouldBlock)
189 setError(InProgress);
190 return error() == WouldBlock; // error
191 }
192 qDebug("KHttpProxySocketDevice: request written");
193
194 d->request.remove(0, written);
195
196 if (!d->request.isEmpty())
197 {
198 setError(InProgress);
199 return true; // still in progress
200 }
201 }
202
203 // request header is sent
204 // must parse reply, but must also be careful not to read too much
205 // from the buffer
206
207 int index;
208 if (!blocking())
209 {
210 qint64 avail = bytesAvailable();
211 qDebug("KHttpProxySocketDevice: %lld bytes available", avail);
212 KActiveSocketBase::close();
213 if (avail == 0)
214 {
215 setError(InProgress);
216 return true;
217 }
218 else if (avail < 0)
219 return false; // error!
220
221 QByteArray buf;
222 buf.resize(avail);
223 if (peekData(buf.data(), avail) < 0)
224 return false; // error!
225
226 QByteArray fullHeaders = d->reply + buf;
227 // search for the end of the headers
228 index = fullHeaders.indexOf("\r\n\r\n");
229 if (index == -1)
230 {
231 // no, headers not yet finished...
232 // consume data from socket
233 readData(buf.data(), avail);
234 d->reply += buf.data();
235 setError(InProgress);
236 return true;
237 }
238
239 // headers are finished
240 index -= d->reply.length();
241 d->reply += fullHeaders.mid(d->reply.length(), index + 4);
242
243 // consume from socket
244 readData(buf.data(), index + 4);
245 }
246 else
247 {
248 int state = 0;
249 if (d->reply.endsWith("\r\n\r")) // krazy:exclude=strings
250 state = 3;
251 else if (d->reply.endsWith("\r\n")) // krazy:exclude=strings
252 state = 2;
253 else if (d->reply.endsWith('\r'))// krazy:exclude=strings
254 state = 1;
255 while (state != 4)
256 {
257 char c;
258 getChar(&c);
259 d->reply += c;
260
261 if ((state == 3 && c == '\n') ||
262 (state == 1 && c == '\n') ||
263 c == '\r')
264 ++state;
265 else
266 state = 0;
267 }
268 }
269
270 // now really parse the reply
271 qDebug("KHttpProxySocketDevice: get reply: %s\n",
272 d->reply.left(d->reply.indexOf('\r')).data());
273 if (d->reply.left(7) != "HTTP/1." ||
274 (index = d->reply.indexOf(' ')) == -1 ||
275 d->reply[index + 1] != '2')
276 {
277 setError(NetFailure);
278 return false;
279 }
280
281 // we've got it
282 resetError();
283 KActiveSocketBase::open(ReadOnly);
284 return true;
285}
KNetwork::KActiveSocketBase::resetError
void resetError()
Resets the socket error code and the I/O Device's status.
Definition: k3socketbase.cpp:441
KNetwork::KActiveSocketBase::open
virtual bool open(OpenMode mode)
Reimplemented from QIODevice.
Definition: k3socketbase.cpp:339
KNetwork::KActiveSocketBase::setError
void setError(SocketError error)
Sets the socket's error code.
Definition: k3socketbase.cpp:435
KNetwork::KHttpProxySocketDevice
The low-level backend for HTTP proxying.
Definition: k3httpproxysocketdevice.h:45
KNetwork::KHttpProxySocketDevice::capabilities
virtual int capabilities() const
Sets our capabilities.
Definition: k3httpproxysocketdevice.cpp:76
KNetwork::KHttpProxySocketDevice::peerAddress
virtual KSocketAddress peerAddress() const
Return the peer address.
Definition: k3httpproxysocketdevice.cpp:99
KNetwork::KHttpProxySocketDevice::externalAddress
virtual KSocketAddress externalAddress() const
Return the externally visible address.
Definition: k3httpproxysocketdevice.cpp:106
KNetwork::KHttpProxySocketDevice::defaultProxy
static KResolverEntry defaultProxy
This is the default proxy server to be used.
Definition: k3httpproxysocketdevice.h:118
KNetwork::KHttpProxySocketDevice::setProxyServer
void setProxyServer(const KResolverEntry &proxy)
Sets the proxy server address.
Definition: k3httpproxysocketdevice.cpp:87
KNetwork::KHttpProxySocketDevice::proxyServer
const KResolverEntry & proxyServer() const
Retrieves the proxy server address.
Definition: k3httpproxysocketdevice.cpp:82
KNetwork::KHttpProxySocketDevice::close
virtual void close()
Closes the socket.
Definition: k3httpproxysocketdevice.cpp:92
KNetwork::KHttpProxySocketDevice::connect
virtual bool connect(const KResolverEntry &address)
Overrides connection.
Definition: k3httpproxysocketdevice.cpp:111
KNetwork::KHttpProxySocketDevice::~KHttpProxySocketDevice
virtual ~KHttpProxySocketDevice()
Destructor.
Definition: k3httpproxysocketdevice.cpp:68
KNetwork::KHttpProxySocketDevice::KHttpProxySocketDevice
KHttpProxySocketDevice(const KSocketBase *=0L)
Constructor.
Definition: k3httpproxysocketdevice.cpp:57
KNetwork::KResolverEntry
One resolution entry.
Definition: k3resolver.h:69
KNetwork::KResolverEntry::address
KSocketAddress address() const
Retrieves the socket address associated with this entry.
Definition: k3resolver.cpp:135
KNetwork::KSocketAddress
A generic socket address.
Definition: k3socketaddress.h:415
KNetwork::KSocketAddress::nodeName
virtual QString nodeName() const
Returns the node name of this socket.
Definition: k3socketaddress.cpp:560
KNetwork::KSocketAddress::serviceName
virtual QString serviceName() const
Returns the service name for this socket.
Definition: k3socketaddress.cpp:586
KNetwork::KSocketBase
Basic socket functionality.
Definition: k3socketbase.h:86
KNetwork::KSocketBase::NotSupported
@ NotSupported
Definition: k3socketbase.h:159
KNetwork::KSocketBase::InProgress
@ InProgress
Definition: k3socketbase.h:157
KNetwork::KSocketBase::NoError
@ NoError
Definition: k3socketbase.h:145
KNetwork::KSocketBase::NetFailure
@ NetFailure
Definition: k3socketbase.h:158
KNetwork::KSocketBase::WouldBlock
@ WouldBlock
Definition: k3socketbase.h:154
KNetwork::KSocketBase::blocking
bool blocking() const
Retrieves this socket's blocking mode.
Definition: k3socketbase.cpp:102
KNetwork::KSocketBase::error
SocketError error() const
Retrieves the socket error code.
Definition: k3socketbase.cpp:197
KNetwork::KSocketDevice
Low-level socket functionality.
Definition: k3socketdevice.h:52
KNetwork::KSocketDevice::close
virtual void close()
Closes the socket.
Definition: k3socketdevice.cpp:232
KNetwork::KSocketDevice::CanNotListen
@ CanNotListen
Can not listen.
Definition: k3socketdevice.h:80
KNetwork::KSocketDevice::CanConnectString
@ CanConnectString
Can connect to hostnames.
Definition: k3socketdevice.h:68
KNetwork::KSocketDevice::CanNotUseDatagrams
@ CanNotUseDatagrams
Can not use datagrams.
Definition: k3socketdevice.h:91
KNetwork::KSocketDevice::CanNotBind
@ CanNotBind
Can not bind.
Definition: k3socketdevice.h:76
KNetwork::KSocketDevice::readData
virtual qint64 readData(char *data, qint64 maxlen, KSocketAddress *from=0L)
Reads data and the source address from this socket.
Definition: k3socketdevice.cpp:494
KNetwork::KSocketDevice::peekData
virtual qint64 peekData(char *data, qint64 maxlen, KSocketAddress *from=0L)
Peeks the data in the socket and the source address.
Definition: k3socketdevice.cpp:515
KNetwork::KSocketDevice::bytesAvailable
virtual qint64 bytesAvailable() const
Returns the number of bytes available for reading without blocking.
Definition: k3socketdevice.cpp:439
KNetwork::KSocketDevice::connect
virtual bool connect(const KResolverEntry &address, OpenMode mode=ReadWrite)
Connect to a remote host.
Definition: k3socketdevice.cpp:345
KNetwork::KSocketDevice::writeData
virtual qint64 writeData(const char *data, qint64 len, const KSocketAddress *to=0L)
Writes the given data to the given destination address.
Definition: k3socketdevice.cpp:536
KNetwork::KSocketDevice::m_sockfd
int m_sockfd
The socket file descriptor.
Definition: k3socketdevice.h:96
QString
qint64
k3httpproxysocketdevice.h
k3resolver.h
k3socketaddress.h
k3socketdevice.h
KNetwork
A namespace to store all networking-related (socket) classes.
Definition: k3bufferedsocket.h:35
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal