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