tdecore
khttpproxysocketdevice.cpp
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 <tqsocketnotifier.h>
00031 #include <tqcstring.h>
00032
00033 #include "kresolver.h"
00034 #include "tdesocketaddress.h"
00035 #include "tdesocketdevice.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 TQCString request;
00047 TQCString reply;
00048 TDESocketAddress peer;
00049
00050 KHttpProxySocketDevicePrivate()
00051 : proxy(KHttpProxySocketDevice::defaultProxy)
00052 { }
00053 };
00054
00055 KHttpProxySocketDevice::KHttpProxySocketDevice(const TDESocketBase* parent)
00056 : TDESocketDevice(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 = TQCString();
00093 d->peer = TDESocketAddress();
00094 TDESocketDevice::close();
00095 }
00096
00097 TDESocketAddress KHttpProxySocketDevice::peerAddress() const
00098 {
00099 if (isOpen())
00100 return d->peer;
00101 return TDESocketAddress();
00102 }
00103
00104 TDESocketAddress KHttpProxySocketDevice::externalAddress() const
00105 {
00106 return TDESocketAddress();
00107 }
00108
00109 bool KHttpProxySocketDevice::connect(const KResolverEntry& address)
00110 {
00111 if (d->proxy.family() == AF_UNSPEC)
00112
00113 return TDESocketDevice::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 TQString& node, const TQString& 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 (!TDESocketDevice::connect(d->proxy))
00152 return false;
00153 setState(0);
00154
00155
00156 TQString request = TQString::fromLatin1("CONNECT %1:%2 HTTP/1.1\r\n"
00157 "Cache-Control: no-cache\r\n"
00158 "Host: \r\n"
00159 "\r\n");
00160 TQString node2 = node;
00161 if (node.contains(':'))
00162 node2 = '[' + node + ']';
00163
00164 d->request = TQString(request.arg(node2).arg(service)).latin1();
00165 }
00166
00167 return parseServerReply();
00168 }
00169
00170 bool KHttpProxySocketDevice::parseServerReply()
00171 {
00172
00173 if (!TDESocketDevice::connect(d->proxy)) {
00174 if (error() == InProgress) {
00175 return true;
00176 }
00177 else if (error() != NoError) {
00178 return false;
00179 }
00180 }
00181
00182 if (!d->request.isEmpty())
00183 {
00184
00185 TQ_LONG written = tqwriteBlock(d->request, d->request.length());
00186 if (written < 0)
00187 {
00188 tqDebug("KHttpProxySocketDevice: would block writing request!");
00189 if (error() == WouldBlock)
00190 setError(IO_ConnectError, InProgress);
00191 return error() == WouldBlock;
00192 }
00193 tqDebug("KHttpProxySocketDevice: request written");
00194
00195 d->request.remove(0, written);
00196
00197 if (!d->request.isEmpty())
00198 {
00199 setError(IO_ConnectError, InProgress);
00200 return true;
00201 }
00202 }
00203
00204
00205
00206
00207
00208 int index;
00209 if (!blocking())
00210 {
00211 TQ_LONG avail = bytesAvailable();
00212 tqDebug("KHttpProxySocketDevice: %ld bytes available", avail);
00213 setState(0);
00214 if (avail == 0)
00215 {
00216 setError(IO_ConnectError, InProgress);
00217 return true;
00218 }
00219 else if (avail < 0)
00220 return false;
00221
00222 TQByteArray buf(avail);
00223 if (peekBlock(buf.data(), avail) < 0)
00224 return false;
00225
00226 TQCString fullHeaders = d->reply + buf.data();
00227
00228 index = fullHeaders.find("\r\n\r\n");
00229 if (index == -1)
00230 {
00231
00232
00233 tqreadBlock(buf.data(), avail);
00234 d->reply += buf.data();
00235 setError(IO_ConnectError, 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 tqreadBlock(buf.data(), index + 4);
00245 }
00246 else
00247 {
00248 int state = 0;
00249 if (d->reply.right(3) == "\r\n\r")
00250 state = 3;
00251 else if (d->reply.right(2) == "\r\n")
00252 state = 2;
00253 else if (d->reply.right(1) == "\r")
00254 state = 1;
00255 while (state != 4)
00256 {
00257 char c = getch();
00258 d->reply += c;
00259
00260 if ((state == 3 && c == '\n') ||
00261 (state == 1 && c == '\n') ||
00262 c == '\r')
00263 ++state;
00264 else
00265 state = 0;
00266 }
00267 }
00268
00269
00270 tqDebug("KHttpProxySocketDevice: get reply: %s\n",
00271 d->reply.left(d->reply.find('\r')).data());
00272 if (d->reply.left(7) != "HTTP/1." ||
00273 (index = d->reply.find(' ')) == -1 ||
00274 d->reply[index + 1] != '2')
00275 {
00276 setError(IO_ConnectError, NetFailure);
00277 return false;
00278 }
00279
00280
00281 resetError();
00282 setState(IO_Open);
00283 return true;
00284 }