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 <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 }