kdecore Library API Documentation

ksockssocketdevice.cpp

00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2004 Thiago Macieira <thiago.macieira@kdemail.net>
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., 59 Temple Place - Suite 330,
00017  *  Boston, MA 02111-1307, USA.
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <errno.h>
00023 #include <sys/types.h>
00024 #include <sys/socket.h>
00025 
00026 #if defined(HAVE_UNISTD_H)
00027 #include <unistd.h>
00028 #endif
00029 
00030 #include "kapplication.h"
00031 
00032 #include "ksocks.h"
00033 #include "ksocketaddress.h"
00034 #include "kresolver.h"
00035 #include "ksockssocketdevice.h"
00036 
00037 using namespace KNetwork;
00038 
00039 // constructor
00040 // nothing to do
00041 KSocksSocketDevice::KSocksSocketDevice(const KSocketBase* obj)
00042   : KSocketDevice(obj)
00043 {
00044 }
00045 
00046 // constructor with argument
00047 // nothing to do
00048 KSocksSocketDevice::KSocksSocketDevice(int fd)
00049   : KSocketDevice(fd)
00050 {
00051 }
00052 
00053 // destructor
00054 // also nothing to do
00055 KSocksSocketDevice::~KSocksSocketDevice()
00056 {
00057 }
00058 
00059 // returns the capabilities
00060 int KSocksSocketDevice::capabilities() const
00061 {
00062   return 0;         // can do everything!
00063 }
00064 
00065 // From here on, the code is almost exactly a copy of KSocketDevice
00066 // the differences are the use of KSocks where appropriate
00067 
00068 bool KSocksSocketDevice::bind(const KResolverEntry& address)
00069 {
00070   resetError();
00071 
00072   if (m_sockfd == -1 && !create(address))
00073     return false;       // failed creating
00074 
00075   // we have a socket, so try and bind
00076   if (KSocks::self()->bind(m_sockfd, address.address(), address.length()) == -1)
00077     {
00078       if (errno == EADDRINUSE)
00079     setError(IO_BindError, AddressInUse);
00080       else if (errno == EINVAL)
00081     setError(IO_BindError, AlreadyBound);
00082       else
00083     // assume the address is the cause
00084     setError(IO_BindError, NotSupported);
00085       return false;
00086     }
00087 
00088   return true;
00089 }
00090 
00091 
00092 bool KSocksSocketDevice::listen(int backlog)
00093 {
00094   if (m_sockfd != -1)
00095     {
00096       if (KSocks::self()->listen(m_sockfd, backlog) == -1)
00097     {
00098       setError(IO_ListenError, NotSupported);
00099       return false;
00100     }
00101 
00102       resetError();
00103       setFlags(IO_Sequential | IO_Raw | IO_ReadWrite);
00104       setState(IO_Open);
00105       return true;
00106     }
00107 
00108   // we don't have a socket
00109   // can't listen
00110   setError(IO_ListenError, NotCreated);
00111   return false;
00112 }
00113 
00114 bool KSocksSocketDevice::connect(const KResolverEntry& address)
00115 {
00116   resetError();
00117 
00118   if (m_sockfd == -1 && !create(address))
00119     return false;       // failed creating!
00120 
00121   if (KSocks::self()->connect(m_sockfd, address.address(), address.length()) == -1)
00122     {
00123       if (errno == EISCONN)
00124     return true;        // we're already connected
00125       else if (errno == EALREADY || errno == EINPROGRESS)
00126     {
00127       setError(IO_ConnectError, InProgress);
00128       return true;
00129     }
00130       else if (errno == ECONNREFUSED)
00131     setError(IO_ConnectError, ConnectionRefused);
00132       else if (errno == ENETDOWN || errno == ENETUNREACH ||
00133            errno == ENETRESET || errno == ECONNABORTED ||
00134            errno == ECONNRESET || errno == EHOSTDOWN ||
00135            errno == EHOSTUNREACH)
00136     setError(IO_ConnectError, NetFailure);
00137       else
00138     setError(IO_ConnectError, NotSupported);
00139 
00140       return false;
00141     }
00142 
00143   setFlags(IO_Sequential | IO_Raw | IO_ReadWrite);
00144   setState(IO_Open);
00145   return true;          // all is well
00146 }
00147 
00148 KSocksSocketDevice* KSocksSocketDevice::accept()
00149 {
00150   if (m_sockfd == -1)
00151     {
00152       // can't accept without a socket
00153       setError(IO_AcceptError, NotCreated);
00154       return 0L;
00155     }
00156 
00157   struct sockaddr sa;
00158   kde_socklen_t len = sizeof(sa);
00159   int newfd = KSocks::self()->accept(m_sockfd, &sa, &len);
00160   if (newfd == -1)
00161     {
00162       if (errno == EAGAIN || errno == EWOULDBLOCK)
00163     setError(IO_AcceptError, WouldBlock);
00164       else
00165     setError(IO_AcceptError, UnknownError);
00166       return NULL;
00167     }
00168 
00169   return new KSocksSocketDevice(newfd);
00170 }
00171 
00172 static int socks_read_common(int sockfd, char *data, Q_ULONG maxlen, KSocketAddress* from, ssize_t &retval, bool peek = false)
00173 {
00174   kde_socklen_t len;
00175   if (from)
00176     {
00177       from->setLength(len = 128); // arbitrary length
00178       retval = KSocks::self()->recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, from->address(), &len);
00179     }
00180   else
00181     retval = KSocks::self()->recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, NULL, NULL);
00182 
00183   if (retval == -1)
00184     {
00185       if (errno == EAGAIN || errno == EWOULDBLOCK)
00186     return KSocketDevice::WouldBlock;
00187       else
00188     return KSocketDevice::UnknownError;
00189     }
00190 
00191   if (from)
00192     from->setLength(len);
00193   return 0;
00194 }
00195 
00196 Q_LONG KSocksSocketDevice::readBlock(char *data, Q_ULONG maxlen)
00197 {
00198   resetError();
00199   if (m_sockfd == -1)
00200     return -1;
00201 
00202   if (maxlen == 0 || data == 0L)
00203     return 0;           // can't read
00204 
00205   ssize_t retval;
00206   int err = socks_read_common(m_sockfd, data, maxlen, 0L, retval);
00207 
00208   if (err)
00209     {
00210       setError(IO_ReadError, static_cast<SocketError>(err));
00211       return -1;
00212     }
00213 
00214   return retval;
00215 }
00216 
00217 Q_LONG KSocksSocketDevice::readBlock(char *data, Q_ULONG maxlen, KSocketAddress &from)
00218 {
00219   resetError();
00220   if (m_sockfd == -1)
00221     return -1;          // nothing to do here
00222 
00223   if (data == 0L || maxlen == 0)
00224     return 0;           // user doesn't want to read
00225 
00226   ssize_t retval;
00227   int err = socks_read_common(m_sockfd, data, maxlen, &from, retval);
00228 
00229   if (err)
00230     {
00231       setError(IO_ReadError, static_cast<SocketError>(err));
00232       return -1;
00233     }
00234 
00235   return retval;
00236 }
00237 
00238 Q_LONG KSocksSocketDevice::peekBlock(char *data, Q_ULONG maxlen)
00239 {
00240   resetError();
00241   if (m_sockfd == -1)
00242     return -1;
00243 
00244   if (maxlen == 0 || data == 0L)
00245     return 0;           // can't read
00246 
00247   ssize_t retval;
00248   int err = socks_read_common(m_sockfd, data, maxlen, 0L, retval, true);
00249 
00250   if (err)
00251     {
00252       setError(IO_ReadError, static_cast<SocketError>(err));
00253       return -1;
00254     }
00255 
00256   return retval;
00257 }
00258 
00259 Q_LONG KSocksSocketDevice::peekBlock(char *data, Q_ULONG maxlen, KSocketAddress& from)
00260 {
00261   resetError();
00262   if (m_sockfd == -1)
00263     return -1;          // nothing to do here
00264 
00265   if (data == 0L || maxlen == 0)
00266     return 0;           // user doesn't want to read
00267 
00268   ssize_t retval;
00269   int err = socks_read_common(m_sockfd, data, maxlen, &from, retval, true);
00270 
00271   if (err)
00272     {
00273       setError(IO_ReadError, static_cast<SocketError>(err));
00274       return -1;
00275     }
00276 
00277   return retval;
00278 }
00279 
00280 Q_LONG KSocksSocketDevice::writeBlock(const char *data, Q_ULONG len)
00281 {
00282   return writeBlock(data, len, KSocketAddress());
00283 }
00284 
00285 Q_LONG KSocksSocketDevice::writeBlock(const char *data, Q_ULONG len, const KSocketAddress& to)
00286 {
00287   resetError();
00288   if (m_sockfd == -1)
00289     return -1;          // can't write to unopen socket
00290 
00291   if (data == 0L || len == 0)
00292     return 0;           // nothing to be written
00293 
00294   ssize_t retval = KSocks::self()->sendto(m_sockfd, data, len, 0, to.address(), to.length());
00295   if (retval == -1)
00296     {
00297       if (errno == EAGAIN || errno == EWOULDBLOCK)
00298     setError(IO_WriteError, WouldBlock);
00299       else
00300     setError(IO_WriteError, UnknownError);
00301       return -1;        // nothing written
00302     }
00303 
00304   return retval;
00305 }
00306 
00307 KSocketAddress KSocksSocketDevice::localAddress() const
00308 {
00309   if (m_sockfd == -1)
00310     return KSocketAddress();    // not open, empty value
00311 
00312   kde_socklen_t len;
00313   KSocketAddress localAddress;
00314   localAddress.setLength(len = 32); // arbitrary value
00315   if (KSocks::self()->getsockname(m_sockfd, localAddress.address(), &len) == -1)
00316     // error!
00317     return KSocketAddress();
00318 
00319   if (len <= localAddress.length())
00320     {
00321       // it has fit already
00322       localAddress.setLength(len);
00323       return localAddress;
00324     }
00325 
00326   // no, the socket address is actually larger than we had anticipated
00327   // call again
00328   localAddress.setLength(len);
00329   if (KSocks::self()->getsockname(m_sockfd, localAddress.address(), &len) == -1)
00330     // error!
00331     return KSocketAddress();
00332 
00333   return localAddress;
00334 }
00335 
00336 KSocketAddress KSocksSocketDevice::peerAddress() const
00337 {
00338   if (m_sockfd == -1)
00339     return KSocketAddress();    // not open, empty value
00340 
00341   kde_socklen_t len;
00342   KSocketAddress peerAddress;
00343   peerAddress.setLength(len = 32);  // arbitrary value
00344   if (KSocks::self()->getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00345     // error!
00346     return KSocketAddress();
00347 
00348   if (len <= peerAddress.length())
00349     {
00350       // it has fit already
00351       peerAddress.setLength(len);
00352       return peerAddress;
00353     }
00354 
00355   // no, the socket address is actually larger than we had anticipated
00356   // call again
00357   peerAddress.setLength(len);
00358   if (KSocks::self()->getpeername(m_sockfd, peerAddress.address(), &len) == -1)
00359     // error!
00360     return KSocketAddress();
00361 
00362   return peerAddress;
00363 }
00364 
00365 KSocketAddress KSocksSocketDevice::externalAddress() const
00366 {
00367   // return empty, indicating unknown external address
00368   return KSocketAddress();
00369 }
00370 
00371 bool KSocksSocketDevice::poll(bool *input, bool *output, bool *exception,
00372                   int timeout, bool *timedout)
00373 {
00374   if (m_sockfd == -1)
00375     {
00376       setError(IO_UnspecifiedError, NotCreated);
00377       return false;
00378     }
00379 
00380   resetError();
00381   fd_set readfds, writefds, exceptfds;
00382   fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L;
00383 
00384   if (input)
00385     {
00386       preadfds = &readfds;
00387       FD_ZERO(preadfds);
00388       FD_SET(m_sockfd, preadfds);
00389       *input = false;
00390     }
00391   if (output)
00392     {
00393       pwritefds = &writefds;
00394       FD_ZERO(pwritefds);
00395       FD_SET(m_sockfd, pwritefds);
00396       *output = false;
00397     }
00398   if (exception)
00399     {
00400       pexceptfds = &exceptfds;
00401       FD_ZERO(pexceptfds);
00402       FD_SET(m_sockfd, pexceptfds);
00403       *exception = false;
00404     }
00405 
00406   int retval;
00407   if (timeout < 0)
00408     retval = KSocks::self()->select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L);
00409   else
00410     {
00411       // convert the milliseconds to timeval
00412       struct timeval tv;
00413       tv.tv_sec = timeout / 1000;
00414       tv.tv_usec = timeout % 1000 * 1000;
00415 
00416       retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv);
00417     }
00418 
00419   if (retval == -1)
00420     {
00421       setError(IO_UnspecifiedError, UnknownError);
00422       return false;
00423     }
00424   if (retval == 0)
00425     {
00426       // timeout
00427       if (timedout)
00428     *timedout = true;
00429       return true;
00430     }
00431 
00432   if (input && FD_ISSET(m_sockfd, preadfds))
00433     *input = true;
00434   if (output && FD_ISSET(m_sockfd, pwritefds))
00435     *output = true;
00436   if (exception && FD_ISSET(m_sockfd, pexceptfds))
00437     *exception = true;
00438 
00439   return true;
00440 }
00441 
00442 void KSocksSocketDevice::initSocks()
00443 {
00444   static bool init = false;
00445 
00446   if (init)
00447     return;
00448 
00449   if (kapp == 0L)
00450     return;         // no KApplication, so don't initialise
00451                                 // this should, however, test for KInstance
00452 
00453   init = true;
00454 
00455   if (KSocks::self()->hasSocks())
00456     delete KSocketDevice::setDefaultImpl(new KSocketDeviceFactory<KSocksSocketDevice>);
00457 }
00458 
00459 #if 0
00460 static bool register()
00461 {
00462   KSocketDevice::addNewImpl(new KSocketDeviceFactory<KSocksSocketDevice>, 0);
00463 }
00464 
00465 static bool register = registered();
00466 #endif
KDE Logo
This file is part of the documentation for kdecore Library Version 3.3.90.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 30 10:09:40 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003