kdecore Library API Documentation

khttpproxysocketdevice.cpp

00001 /* -*- C++ -*- 00002 * Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net> 00003 * 00004 * 00005 * Permission is hereby granted, free of charge, to any person obtaining 00006 * a copy of this software and associated documentation files (the 00007 * "Software"), to deal in the Software without restriction, including 00008 * without limitation the rights to use, copy, modify, merge, publish, 00009 * distribute, sublicense, and/or sell copies of the Software, and to 00010 * permit persons to whom the Software is furnished to do so, subject to 00011 * the following conditions: 00012 * 00013 * The above copyright notice and this permission notice shall be included 00014 * in all copies or substantial portions of the Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 00020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 00021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 // nothing special to be done during closing 00069 // KSocketDevice::~KSocketDevice closes the socket 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 // no proxy server set ! 00113 return KSocketDevice::connect(address); 00114 00115 if (isOpen()) 00116 { 00117 // socket is already open 00118 resetError(); 00119 return true; 00120 } 00121 00122 if (m_sockfd == -1) 00123 // socket isn't created yet 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 // same safety checks as above 00134 if (m_sockfd == -1 && (d->proxy.family() == AF_UNSPEC || 00135 node.isEmpty() || service.isEmpty())) 00136 { 00137 // no proxy server set ! 00138 setError(IO_ConnectError, NotSupported); 00139 return false; 00140 } 00141 00142 if (isOpen()) 00143 { 00144 // socket is already open 00145 return true; 00146 } 00147 00148 if (m_sockfd == -1) 00149 { 00150 // must create the socket 00151 if (!KSocketDevice::connect(d->proxy)) 00152 return false; // also unable to contact proxy server 00153 setState(0); // unset open flag 00154 00155 // prepare the request 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 // make sure we're connected 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 // send request 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; // error 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; // still in progress 00198 } 00199 } 00200 00201 // request header is sent 00202 // must parse reply, but must also be careful not to read too much 00203 // from the buffer 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; // error! 00218 00219 QByteArray buf(avail); 00220 if (peekBlock(buf.data(), avail) < 0) 00221 return false; // error! 00222 00223 QCString fullHeaders = d->reply + buf.data(); 00224 // search for the end of the headers 00225 index = fullHeaders.find("\r\n\r\n"); 00226 if (index == -1) 00227 { 00228 // no, headers not yet finished... 00229 // consume data from socket 00230 readBlock(buf.data(), avail); 00231 d->reply += buf.data(); 00232 setError(IO_ConnectError, InProgress); 00233 return true; 00234 } 00235 00236 // headers are finished 00237 index -= d->reply.length(); 00238 d->reply += fullHeaders.mid(d->reply.length(), index + 4); 00239 00240 // consume from socket 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 // now really parse the reply 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 // we've got it 00278 resetError(); 00279 setState(IO_Open); 00280 return true; 00281 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 22:47:35 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003