• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDECore

k3sockssocketdevice.cpp

Go to the documentation of this file.
00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2004 Thiago Macieira <thiago@kde.org>
00003  *
00004  *  This library is free software; you can redistribute it and/or
00005  *  modify it under the terms of the GNU Library General Public
00006  *  License as published by the Free Software Foundation; either
00007  *  version 2 of the License, or (at your option) any later version.
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  */
00019 
00020 #include "k3sockssocketdevice.h"
00021 
00022 #include <config.h>
00023 #include <config-network.h>
00024 
00025 #include <errno.h>
00026 #include <sys/types.h>
00027 #include <sys/socket.h>
00028 
00029 #if defined(HAVE_UNISTD_H)
00030 #include <unistd.h>
00031 #endif
00032 
00033 
00034 #include <QCoreApplication>
00035 #ifndef KDE_USE_FINAL
00036 #define I_KNOW_KSOCKS_ISNT_PUBLIC
00037 #include "k3socks.h"
00038 #undef I_KNOW_KSOCKS_ISNT_PUBLIC
00039 #endif
00040 #include "k3socketaddress.h"
00041 #include "k3resolver.h"
00042 
00043 using namespace KNetwork;
00044 
00045 // constructor
00046 // nothing to do
00047 KSocksSocketDevice::KSocksSocketDevice(const KSocketBase* obj)
00048   : KSocketDevice(obj), d(0)
00049 {
00050 }
00051 
00052 // constructor with argument
00053 // nothing to do
00054 KSocksSocketDevice::KSocksSocketDevice(int fd)
00055   : KSocketDevice(fd), d(0)
00056 {
00057 }
00058 
00059 // destructor
00060 // also nothing to do
00061 KSocksSocketDevice::~KSocksSocketDevice()
00062 {
00063 }
00064 
00065 // returns the capabilities
00066 int KSocksSocketDevice::capabilities() const
00067 {
00068   return 0;         // can do everything!
00069 }
00070 
00071 // From here on, the code is almost exactly a copy of KSocketDevice
00072 // the differences are the use of KSocks where appropriate
00073 
00074 bool KSocksSocketDevice::bind(const KResolverEntry& address)
00075 {
00076   resetError();
00077 
00078   if (m_sockfd == -1 && !create(address))
00079     return false;       // failed creating
00080 
00081   // we have a socket, so try and bind
00082   if (KSocks::self()->bind(m_sockfd, address.address(), address.length()) == -1)
00083     {
00084       if (errno == EADDRINUSE)
00085     setError(AddressInUse);
00086       else if (errno == EINVAL)
00087     setError(AlreadyBound);
00088       else
00089     // assume the address is the cause
00090     setError(NotSupported);
00091       return false;
00092     }
00093 
00094   return true;
00095 }
00096 
00097 
00098 bool KSocksSocketDevice::listen(int backlog)
00099 {
00100   if (m_sockfd != -1)
00101     {
00102       if (KSocks::self()->listen(m_sockfd, backlog) == -1)
00103     {
00104       setError(NotSupported);
00105       return false;
00106     }
00107 
00108       resetError();
00109       setOpenMode(ReadWrite | Unbuffered);
00110       return true;
00111     }
00112 
00113   // we don't have a socket
00114   // can't listen
00115   setError(NotCreated);
00116   return false;
00117 }
00118 
00119 bool KSocksSocketDevice::connect(const KResolverEntry& address)
00120 {
00121   resetError();
00122 
00123   if (m_sockfd == -1 && !create(address))
00124     return false;       // failed creating!
00125 
00126   int retval;
00127   if (KSocks::self()->hasWorkingAsyncConnect())
00128     retval = KSocks::self()->connect(m_sockfd, address.address(),
00129                      address.length());
00130   else
00131     {
00132       // work around some SOCKS implementation bugs
00133       // we will do a *synchronous* connection here!
00134       // FIXME: KDE4, write a proper SOCKS implementation
00135       bool isBlocking = blocking();
00136       setBlocking(true);
00137       retval = KSocks::self()->connect(m_sockfd, address.address(),
00138                        address.length());
00139       setBlocking(isBlocking);
00140     }
00141 
00142   if (retval == -1)
00143     {
00144       if (errno == EISCONN)
00145     return true;        // we're already connected
00146       else if (errno == EALREADY || errno == EINPROGRESS)
00147     {
00148       setError(InProgress);
00149       return true;
00150     }
00151       else if (errno == ECONNREFUSED)
00152     setError(ConnectionRefused);
00153       else if (errno == ENETDOWN || errno == ENETUNREACH ||
00154            errno == ENETRESET || errno == ECONNABORTED ||
00155            errno == ECONNRESET || errno == EHOSTDOWN ||
00156            errno == EHOSTUNREACH)
00157     setError(NetFailure);
00158       else
00159     setError(NotSupported);
00160 
00161       return false;
00162     }
00163 
00164   setOpenMode(ReadWrite | Unbuffered);
00165   return true;          // all is well
00166 }
00167 
00168 KSocksSocketDevice* KSocksSocketDevice::accept()
00169 {
00170   if (m_sockfd == -1)
00171     {
00172       // can't accept without a socket
00173       setError(NotCreated);
00174       return 0L;
00175     }
00176 
00177   struct sockaddr sa;
00178   kde_socklen_t len = sizeof(sa);
00179   int newfd = KSocks::self()->accept(m_sockfd, &sa, &len);
00180   if (newfd == -1)
00181     {
00182       if (errno == EAGAIN || errno == EWOULDBLOCK)
00183     setError(WouldBlock);
00184       else
00185     setError(UnknownError);
00186       return NULL;
00187     }
00188 
00189   return new KSocksSocketDevice(newfd);
00190 }
00191 
00192 static int socks_read_common(int sockfd, char *data, quint64 maxlen, KSocketAddress* from, ssize_t &retval, bool peek = false)
00193 {
00194   kde_socklen_t len;
00195   if (from)
00196     {
00197       from->setLength(len = 128); // arbitrary length
00198       retval = KSocks::self()->recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, from->address(), &len);
00199     }
00200   else
00201     retval = KSocks::self()->recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, NULL, NULL);
00202 
00203   if (retval == -1)
00204     {
00205       if (errno == EAGAIN || errno == EWOULDBLOCK)
00206     return KSocketDevice::WouldBlock;
00207       else
00208     return KSocketDevice::UnknownError;
00209     }
00210 
00211   if (from)
00212     from->setLength(len);
00213   return 0;
00214 }
00215 
00216 qint64 KSocksSocketDevice::readBlock(char *data, quint64 maxlen)
00217 {
00218   resetError();
00219   if (m_sockfd == -1)
00220     return -1;
00221 
00222   if (maxlen == 0 || data == 0L)
00223     return 0;           // can't read
00224 
00225   ssize_t retval;
00226   int err = socks_read_common(m_sockfd, data, maxlen, 0L, retval);
00227 
00228   if (err)
00229     {
00230       setError(static_cast<SocketError>(err));
00231       return -1;
00232     }
00233 
00234   return retval;
00235 }
00236 
00237 qint64 KSocksSocketDevice::readBlock(char *data, quint64 maxlen, KSocketAddress &from)
00238 {
00239   resetError();
00240   if (m_sockfd == -1)
00241     return -1;          // nothing to do here
00242 
00243   if (data == 0L || maxlen == 0)
00244     return 0;           // user doesn't want to read
00245 
00246   ssize_t retval;
00247   int err = socks_read_common(m_sockfd, data, maxlen, &from, retval);
00248 
00249   if (err)
00250     {
00251       setError(static_cast<SocketError>(err));
00252       return -1;
00253     }
00254 
00255   return retval;
00256 }
00257 
00258 qint64 KSocksSocketDevice::peekBlock(char *data, quint64 maxlen)
00259 {
00260   resetError();
00261   if (m_sockfd == -1)
00262     return -1;
00263 
00264   if (maxlen == 0 || data == 0L)
00265     return 0;           // can't read
00266 
00267   ssize_t retval;
00268   int err = socks_read_common(m_sockfd, data, maxlen, 0L, retval, true);
00269 
00270   if (err)
00271     {
00272       setError(static_cast<SocketError>(err));
00273       return -1;
00274     }
00275 
00276   return retval;
00277 }
00278 
00279 qint64 KSocksSocketDevice::peekBlock(char *data, quint64 maxlen, KSocketAddress& from)
00280 {
00281   resetError();
00282   if (m_sockfd == -1)
00283     return -1;          // nothing to do here
00284 
00285   if (data == 0L || maxlen == 0)
00286     return 0;           // user doesn't want to read
00287 
00288   ssize_t retval;
00289   int err = socks_read_common(m_sockfd, data, maxlen, &from, retval, true);
00290 
00291   if (err)
00292     {
00293       setError(static_cast<SocketError>(err));
00294       return -1;
00295     }
00296 
00297   return retval;
00298 }
00299 
00300 qint64 KSocksSocketDevice::writeBlock(const char *data, quint64 len)
00301 {
00302   return writeBlock(data, len, KSocketAddress());
00303 }
00304 
00305 qint64 KSocksSocketDevice::writeBlock(const char *data, quint64 len, const KSocketAddress& to)
00306 {
00307   resetError();
00308   if (m_sockfd == -1)
00309     return -1;          // can't write to unopen socket
00310 
00311   if (data == 0L || len == 0)
00312     return 0;           // nothing to be written
00313 
00314   ssize_t retval = KSocks::self()->sendto(m_sockfd, data, len, 0, to.address(), to.length());
00315   if (retval == -1)
00316     {
00317       if (errno == EAGAIN || errno == EWOULDBLOCK)
00318     setError(WouldBlock);
00319       else
00320     setError(UnknownError);
00321       return -1;        // nothing written
00322     }
00323 
00324   return retval;
00325 }
00326 
00327 KSocketAddress KSocksSocketDevice::localAddress() const
00328 {
00329   if (m_sockfd == -1)
00330     return KSocketAddress();    // not open, empty value
00331 
00332   kde_socklen_t len;
00333   KSocketAddress localAddress;
00334   localAddress.setLength(len = 32); // arbitrary value
00335   if (KSocks::self()->getsockname(m_sockfd, localAddress.address(), &len) == -1)
00336     // error!
00337     return KSocketAddress();
00338 
00339   if (len <= localAddress.length())
00340     {
00341       // it has fit already
00342       localAddress.setLength(len);
00343       return localAddress;
00344     }
00345 
00346   // no, the socket address is actually larger than we had anticipated
00347   // call again
00348   localAddress.setLength(len);
00349   if (KSocks::self()->getsockname(m_sockfd, localAddress.address(), &len) == -1)
00350     // error!
00351     return KSocketAddress();
00352 
00353   return localAddress;
00354 }
00355 
00356 KSocketAddress KSocksSocketDevice::peerAddress() const
00357 {
00358   if (m_sockfd == -1)
00359     return KSocketAddress();    // not open, empty value
00360 
00361   kde_socklen_t len;
00362   KSocketAddress peerAddress;
00363   peerAddress.setLength(len = 32);  // arbitrary value
00364   if (KSocks::self()->getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00365     // error!
00366     return KSocketAddress();
00367 
00368   if (len <= peerAddress.length())
00369     {
00370       // it has fit already
00371       peerAddress.setLength(len);
00372       return peerAddress;
00373     }
00374 
00375   // no, the socket address is actually larger than we had anticipated
00376   // call again
00377   peerAddress.setLength(len);
00378   if (KSocks::self()->getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00379     // error!
00380     return KSocketAddress();
00381 
00382   return peerAddress;
00383 }
00384 
00385 KSocketAddress KSocksSocketDevice::externalAddress() const
00386 {
00387   // return empty, indicating unknown external address
00388   return KSocketAddress();
00389 }
00390 
00391 bool KSocksSocketDevice::poll(bool *input, bool *output, bool *exception,
00392                   int timeout, bool *timedout)
00393 {
00394   if (m_sockfd == -1)
00395     {
00396       setError(NotCreated);
00397       return false;
00398     }
00399 
00400   resetError();
00401   fd_set readfds, writefds, exceptfds;
00402   fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L;
00403 
00404   if (input)
00405     {
00406       preadfds = &readfds;
00407       FD_ZERO(preadfds);
00408       FD_SET(m_sockfd, preadfds);
00409       *input = false;
00410     }
00411   if (output)
00412     {
00413       pwritefds = &writefds;
00414       FD_ZERO(pwritefds);
00415       FD_SET(m_sockfd, pwritefds);
00416       *output = false;
00417     }
00418   if (exception)
00419     {
00420       pexceptfds = &exceptfds;
00421       FD_ZERO(pexceptfds);
00422       FD_SET(m_sockfd, pexceptfds);
00423       *exception = false;
00424     }
00425 
00426   int retval;
00427   if (timeout < 0)
00428     retval = KSocks::self()->select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L);
00429   else
00430     {
00431       // convert the milliseconds to timeval
00432       struct timeval tv;
00433       tv.tv_sec = timeout / 1000;
00434       tv.tv_usec = timeout % 1000 * 1000;
00435 
00436       retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv);
00437     }
00438 
00439   if (retval == -1)
00440     {
00441       setError(UnknownError);
00442       return false;
00443     }
00444   if (retval == 0)
00445     {
00446       // timeout
00447       if (timedout)
00448     *timedout = true;
00449       return true;
00450     }
00451 
00452   if (input && FD_ISSET(m_sockfd, preadfds))
00453     *input = true;
00454   if (output && FD_ISSET(m_sockfd, pwritefds))
00455     *output = true;
00456   if (exception && FD_ISSET(m_sockfd, pexceptfds))
00457     *exception = true;
00458 
00459   return true;
00460 }
00461 
00462 void KSocksSocketDevice::initSocks()
00463 {
00464   static bool init = false;
00465 
00466   if (init)
00467     return;
00468 
00469   if (QCoreApplication::instance() == 0L)
00470     return;         // no KApplication, so don't initialize
00471                                 // this should, however, test for KComponentData
00472 
00473   init = true;
00474 
00475   if (KSocks::self()->hasSocks())
00476     delete KSocketDevice::setDefaultImpl(new KSocketDeviceFactory<KSocksSocketDevice>);
00477 }
00478 
00479 #if 0
00480 static bool register()
00481 {
00482   KSocketDevice::addNewImpl(new KSocketDeviceFactory<KSocksSocketDevice>, 0);
00483 }
00484 
00485 static bool register = registered();
00486 #endif

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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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