KDECore
k3httpproxysocketdevice.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "k3httpproxysocketdevice.h"
00026
00027 #include <config.h>
00028 #include <config-network.h>
00029
00030 #include <sys/types.h>
00031 #include <sys/socket.h>
00032
00033 #include <QSocketNotifier>
00034 #include <QByteArray>
00035
00036 #include "k3resolver.h"
00037 #include "k3socketaddress.h"
00038 #include "k3socketdevice.h"
00039
00040 using namespace KNetwork;
00041
00042 KResolverEntry KHttpProxySocketDevice::defaultProxy;
00043
00044 class KNetwork::KHttpProxySocketDevicePrivate
00045 {
00046 public:
00047 KResolverEntry proxy;
00048 QByteArray request;
00049 QByteArray reply;
00050 KSocketAddress peer;
00051
00052 KHttpProxySocketDevicePrivate()
00053 : proxy(KHttpProxySocketDevice::defaultProxy)
00054 { }
00055 };
00056
00057 KHttpProxySocketDevice::KHttpProxySocketDevice(const KSocketBase* parent)
00058 : KSocketDevice(parent), d(new KHttpProxySocketDevicePrivate)
00059 {
00060 }
00061
00062 KHttpProxySocketDevice::KHttpProxySocketDevice(const KResolverEntry& proxy)
00063 : d(new KHttpProxySocketDevicePrivate)
00064 {
00065 d->proxy = proxy;
00066 }
00067
00068 KHttpProxySocketDevice::~KHttpProxySocketDevice()
00069 {
00070
00071
00072
00073 delete d;
00074 }
00075
00076 int KHttpProxySocketDevice::capabilities() const
00077 {
00078 return CanConnectString | CanNotBind | CanNotListen | CanNotUseDatagrams;
00079 }
00080
00081 const KResolverEntry&
00082 KHttpProxySocketDevice::proxyServer() const
00083 {
00084 return d->proxy;
00085 }
00086
00087 void KHttpProxySocketDevice::setProxyServer(const KResolverEntry& proxy)
00088 {
00089 d->proxy = proxy;
00090 }
00091
00092 void KHttpProxySocketDevice::close()
00093 {
00094 d->reply = d->request = QByteArray();
00095 d->peer = KSocketAddress();
00096 KSocketDevice::close();
00097 }
00098
00099 KSocketAddress KHttpProxySocketDevice::peerAddress() const
00100 {
00101 if (isOpen())
00102 return d->peer;
00103 return KSocketAddress();
00104 }
00105
00106 KSocketAddress KHttpProxySocketDevice::externalAddress() const
00107 {
00108 return KSocketAddress();
00109 }
00110
00111 bool KHttpProxySocketDevice::connect(const KResolverEntry& address)
00112 {
00113 if (d->proxy.family() == AF_UNSPEC)
00114
00115 return KSocketDevice::connect(address);
00116
00117 if (isOpen())
00118 {
00119
00120 resetError();
00121 return true;
00122 }
00123
00124 if (m_sockfd == -1)
00125
00126 return connect(address.address().nodeName(),
00127 address.address().serviceName());
00128
00129 d->peer = address.address();
00130 return parseServerReply();
00131 }
00132
00133 bool KHttpProxySocketDevice::connect(const QString& node, const QString& service)
00134 {
00135
00136 if (m_sockfd == -1 && (d->proxy.family() == AF_UNSPEC ||
00137 node.isEmpty() || service.isEmpty()))
00138 {
00139
00140 setError(NotSupported);
00141 return false;
00142 }
00143
00144 if (isOpen())
00145 {
00146
00147 return true;
00148 }
00149
00150 if (m_sockfd == -1)
00151 {
00152
00153 if (!KSocketDevice::connect(d->proxy))
00154 return false;
00155 KActiveSocketBase::close();
00156
00157
00158 QString request = QLatin1String("CONNECT %1:%2 HTTP/1.1\r\n"
00159 "Cache-Control: no-cache\r\n"
00160 "Host: \r\n"
00161 "\r\n");
00162 QString node2 = node;
00163 if (node.contains(':'))
00164 node2 = '[' + node + ']';
00165
00166 d->request = request.arg(node2).arg(service).toLatin1();
00167 }
00168
00169 return parseServerReply();
00170 }
00171
00172 bool KHttpProxySocketDevice::parseServerReply()
00173 {
00174
00175 if (!KSocketDevice::connect(d->proxy))
00176 if (error() == InProgress)
00177 return true;
00178 else if (error() != NoError)
00179 return false;
00180
00181 if (!d->request.isEmpty())
00182 {
00183
00184 qint64 written = writeData(d->request, d->request.length());
00185 if (written < 0)
00186 {
00187 qDebug("KHttpProxySocketDevice: would block writing request!");
00188 if (error() == WouldBlock)
00189 setError(InProgress);
00190 return error() == WouldBlock;
00191 }
00192 qDebug("KHttpProxySocketDevice: request written");
00193
00194 d->request.remove(0, written);
00195
00196 if (!d->request.isEmpty())
00197 {
00198 setError(InProgress);
00199 return true;
00200 }
00201 }
00202
00203
00204
00205
00206
00207 int index;
00208 if (!blocking())
00209 {
00210 qint64 avail = bytesAvailable();
00211 qDebug("KHttpProxySocketDevice: %lld bytes available", avail);
00212 KActiveSocketBase::close();
00213 if (avail == 0)
00214 {
00215 setError(InProgress);
00216 return true;
00217 }
00218 else if (avail < 0)
00219 return false;
00220
00221 QByteArray buf;
00222 buf.resize(avail);
00223 if (peekData(buf.data(), avail) < 0)
00224 return false;
00225
00226 QByteArray fullHeaders = d->reply + buf;
00227
00228 index = fullHeaders.indexOf("\r\n\r\n");
00229 if (index == -1)
00230 {
00231
00232
00233 readData(buf.data(), avail);
00234 d->reply += buf.data();
00235 setError(InProgress);
00236 return true;
00237 }
00238
00239
00240 index -= d->reply.length();
00241 d->reply += fullHeaders.mid(d->reply.length(), index + 4);
00242
00243
00244 readData(buf.data(), index + 4);
00245 }
00246 else
00247 {
00248 int state = 0;
00249 if (d->reply.endsWith("\r\n\r"))
00250 state = 3;
00251 else if (d->reply.endsWith("\r\n"))
00252 state = 2;
00253 else if (d->reply.endsWith('\r'))
00254 state = 1;
00255 while (state != 4)
00256 {
00257 char c;
00258 getChar(&c);
00259 d->reply += c;
00260
00261 if ((state == 3 && c == '\n') ||
00262 (state == 1 && c == '\n') ||
00263 c == '\r')
00264 ++state;
00265 else
00266 state = 0;
00267 }
00268 }
00269
00270
00271 qDebug("KHttpProxySocketDevice: get reply: %s\n",
00272 d->reply.left(d->reply.indexOf('\r')).data());
00273 if (d->reply.left(7) != "HTTP/1." ||
00274 (index = d->reply.indexOf(' ')) == -1 ||
00275 d->reply[index + 1] != '2')
00276 {
00277 setError(NetFailure);
00278 return false;
00279 }
00280
00281
00282 resetError();
00283 KActiveSocketBase::open(ReadOnly);
00284 return true;
00285 }