• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

k3httpproxysocketdevice.cpp

Go to the documentation of this file.
00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003 Thiago Macieira <thiago@kde.org>
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 "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   // nothing special to be done during closing
00071   // KSocketDevice::~KSocketDevice closes the socket
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     // no proxy server set !
00115     return KSocketDevice::connect(address);
00116 
00117   if (isOpen())
00118     {
00119       // socket is already open
00120       resetError();
00121       return true;
00122     }
00123 
00124   if (m_sockfd == -1)
00125     // socket isn't created yet
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   // same safety checks as above
00136   if (m_sockfd == -1 && (d->proxy.family() == AF_UNSPEC ||
00137              node.isEmpty() || service.isEmpty()))
00138     {
00139       // no proxy server set !
00140       setError(NotSupported);
00141       return false;
00142     }
00143 
00144   if (isOpen())
00145     {
00146       // socket is already open
00147       return true;
00148     }
00149 
00150   if (m_sockfd == -1)
00151     {
00152       // must create the socket
00153       if (!KSocketDevice::connect(d->proxy))
00154     return false;       // also unable to contact proxy server
00155       KActiveSocketBase::close();
00156 
00157       // prepare the request
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   // make sure we're connected
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       // send request
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; // error
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;      // still in progress
00200     }
00201     }
00202 
00203   // request header is sent
00204   // must parse reply, but must also be careful not to read too much
00205   // from the buffer
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;       // error!
00220 
00221       QByteArray buf;
00222       buf.resize(avail);
00223       if (peekData(buf.data(), avail) < 0)
00224     return false;       // error!
00225 
00226       QByteArray fullHeaders = d->reply + buf;
00227       // search for the end of the headers
00228       index = fullHeaders.indexOf("\r\n\r\n");
00229       if (index == -1)
00230     {
00231       // no, headers not yet finished...
00232       // consume data from socket
00233       readData(buf.data(), avail);
00234       d->reply += buf.data();
00235       setError(InProgress);
00236       return true;
00237     }
00238 
00239       // headers are finished
00240       index -= d->reply.length();
00241       d->reply += fullHeaders.mid(d->reply.length(), index + 4);
00242 
00243       // consume from socket
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   // now really parse the reply
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   // we've got it
00282   resetError();
00283   KActiveSocketBase::open(ReadOnly);
00284   return true;
00285 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal