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