ksockssocketdevice.cpp
/* -*- C++ -*-
* Copyright (C) 2004 Thiago Macieira <thiago.macieira@kdemail.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <config.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif
#ifdef __CYGWIN__
#undef kde_socklen_t
#define kde_socklen_t ksocklen_t
#endif
#include "kapplication.h"
#include "ksocks.h"
#include "ksocketaddress.h"
#include "kresolver.h"
#include "ksockssocketdevice.h"
using namespace KNetwork;
// constructor
// nothing to do
KSocksSocketDevice::KSocksSocketDevice(const KSocketBase* obj)
: KSocketDevice(obj)
{
}
// constructor with argument
// nothing to do
KSocksSocketDevice::KSocksSocketDevice(int fd)
: KSocketDevice(fd)
{
}
// destructor
// also nothing to do
KSocksSocketDevice::~KSocksSocketDevice()
{
}
// returns the capabilities
int KSocksSocketDevice::capabilities() const
{
return 0; // can do everything!
}
// From here on, the code is almost exactly a copy of KSocketDevice
// the differences are the use of KSocks where appropriate
bool KSocksSocketDevice::bind(const KResolverEntry& address)
{
resetError();
if (m_sockfd == -1 && !create(address))
return false; // failed creating
// we have a socket, so try and bind
if (KSocks::self()->bind(m_sockfd, address.address(), address.length()) == -1)
{
if (errno == EADDRINUSE)
setError(IO_BindError, AddressInUse);
else if (errno == EINVAL)
setError(IO_BindError, AlreadyBound);
else
// assume the address is the cause
setError(IO_BindError, NotSupported);
return false;
}
return true;
}
bool KSocksSocketDevice::listen(int backlog)
{
if (m_sockfd != -1)
{
if (KSocks::self()->listen(m_sockfd, backlog) == -1)
{
setError(IO_ListenError, NotSupported);
return false;
}
resetError();
setFlags(IO_Sequential | IO_Raw | IO_ReadWrite);
setState(IO_Open);
return true;
}
// we don't have a socket
// can't listen
setError(IO_ListenError, NotCreated);
return false;
}
bool KSocksSocketDevice::connect(const KResolverEntry& address)
{
resetError();
if (m_sockfd == -1 && !create(address))
return false; // failed creating!
int retval;
if (KSocks::self()->hasWorkingAsyncConnect())
retval = KSocks::self()->connect(m_sockfd, address.address(),
address.length());
else
{
// work around some SOCKS implementation bugs
// we will do a *synchronous* connection here!
// FIXME: KDE4, write a proper SOCKS implementation
bool isBlocking = blocking();
setBlocking(true);
retval = KSocks::self()->connect(m_sockfd, address.address(),
address.length());
setBlocking(isBlocking);
}
if (retval == -1)
{
if (errno == EISCONN)
return true; // we're already connected
else if (errno == EALREADY || errno == EINPROGRESS)
{
setError(IO_ConnectError, InProgress);
return true;
}
else if (errno == ECONNREFUSED)
setError(IO_ConnectError, ConnectionRefused);
else if (errno == ENETDOWN || errno == ENETUNREACH ||
errno == ENETRESET || errno == ECONNABORTED ||
errno == ECONNRESET || errno == EHOSTDOWN ||
errno == EHOSTUNREACH)
setError(IO_ConnectError, NetFailure);
else
setError(IO_ConnectError, NotSupported);
return false;
}
setFlags(IO_Sequential | IO_Raw | IO_ReadWrite);
setState(IO_Open);
return true; // all is well
}
KSocksSocketDevice* KSocksSocketDevice::accept()
{
if (m_sockfd == -1)
{
// can't accept without a socket
setError(IO_AcceptError, NotCreated);
return 0L;
}
struct sockaddr sa;
kde_socklen_t len = sizeof(sa);
int newfd = KSocks::self()->accept(m_sockfd, &sa, &len);
if (newfd == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
setError(IO_AcceptError, WouldBlock);
else
setError(IO_AcceptError, UnknownError);
return NULL;
}
return new KSocksSocketDevice(newfd);
}
static int socks_read_common(int sockfd, char *data, Q_ULONG maxlen, KSocketAddress* from, ssize_t &retval, bool peek = false)
{
kde_socklen_t len;
if (from)
{
from->setLength(len = 128); // arbitrary length
retval = KSocks::self()->recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, from->address(), &len);
}
else
retval = KSocks::self()->recvfrom(sockfd, data, maxlen, peek ? MSG_PEEK : 0, NULL, NULL);
if (retval == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
return KSocketDevice::WouldBlock;
else
return KSocketDevice::UnknownError;
}
if (from)
from->setLength(len);
return 0;
}
Q_LONG KSocksSocketDevice::readBlock(char *data, Q_ULONG maxlen)
{
resetError();
if (m_sockfd == -1)
return -1;
if (maxlen == 0 || data == 0L)
return 0; // can't read
ssize_t retval;
int err = socks_read_common(m_sockfd, data, maxlen, 0L, retval);
if (err)
{
setError(IO_ReadError, static_cast<SocketError>(err));
return -1;
}
return retval;
}
Q_LONG KSocksSocketDevice::readBlock(char *data, Q_ULONG maxlen, KSocketAddress &from)
{
resetError();
if (m_sockfd == -1)
return -1; // nothing to do here
if (data == 0L || maxlen == 0)
return 0; // user doesn't want to read
ssize_t retval;
int err = socks_read_common(m_sockfd, data, maxlen, &from, retval);
if (err)
{
setError(IO_ReadError, static_cast<SocketError>(err));
return -1;
}
return retval;
}
Q_LONG KSocksSocketDevice::peekBlock(char *data, Q_ULONG maxlen)
{
resetError();
if (m_sockfd == -1)
return -1;
if (maxlen == 0 || data == 0L)
return 0; // can't read
ssize_t retval;
int err = socks_read_common(m_sockfd, data, maxlen, 0L, retval, true);
if (err)
{
setError(IO_ReadError, static_cast<SocketError>(err));
return -1;
}
return retval;
}
Q_LONG KSocksSocketDevice::peekBlock(char *data, Q_ULONG maxlen, KSocketAddress& from)
{
resetError();
if (m_sockfd == -1)
return -1; // nothing to do here
if (data == 0L || maxlen == 0)
return 0; // user doesn't want to read
ssize_t retval;
int err = socks_read_common(m_sockfd, data, maxlen, &from, retval, true);
if (err)
{
setError(IO_ReadError, static_cast<SocketError>(err));
return -1;
}
return retval;
}
Q_LONG KSocksSocketDevice::writeBlock(const char *data, Q_ULONG len)
{
return writeBlock(data, len, KSocketAddress());
}
Q_LONG KSocksSocketDevice::writeBlock(const char *data, Q_ULONG len, const KSocketAddress& to)
{
resetError();
if (m_sockfd == -1)
return -1; // can't write to unopen socket
if (data == 0L || len == 0)
return 0; // nothing to be written
ssize_t retval = KSocks::self()->sendto(m_sockfd, data, len, 0, to.address(), to.length());
if (retval == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
setError(IO_WriteError, WouldBlock);
else
setError(IO_WriteError, UnknownError);
return -1; // nothing written
}
return retval;
}
KSocketAddress KSocksSocketDevice::localAddress() const
{
if (m_sockfd == -1)
return KSocketAddress(); // not open, empty value
kde_socklen_t len;
KSocketAddress localAddress;
localAddress.setLength(len = 32); // arbitrary value
if (KSocks::self()->getsockname(m_sockfd, localAddress.address(), &len) == -1)
// error!
return KSocketAddress();
if (len <= localAddress.length())
{
// it has fit already
localAddress.setLength(len);
return localAddress;
}
// no, the socket address is actually larger than we had anticipated
// call again
localAddress.setLength(len);
if (KSocks::self()->getsockname(m_sockfd, localAddress.address(), &len) == -1)
// error!
return KSocketAddress();
return localAddress;
}
KSocketAddress KSocksSocketDevice::peerAddress() const
{
if (m_sockfd == -1)
return KSocketAddress(); // not open, empty value
kde_socklen_t len;
KSocketAddress peerAddress;
peerAddress.setLength(len = 32); // arbitrary value
if (KSocks::self()->getpeername(m_sockfd, peerAddress.address(), &len) == -1)
// error!
return KSocketAddress();
if (len <= peerAddress.length())
{
// it has fit already
peerAddress.setLength(len);
return peerAddress;
}
// no, the socket address is actually larger than we had anticipated
// call again
peerAddress.setLength(len);
if (KSocks::self()->getpeername(m_sockfd, peerAddress.address(), &len) == -1)
// error!
return KSocketAddress();
return peerAddress;
}
KSocketAddress KSocksSocketDevice::externalAddress() const
{
// return empty, indicating unknown external address
return KSocketAddress();
}
bool KSocksSocketDevice::poll(bool *input, bool *output, bool *exception,
int timeout, bool *timedout)
{
if (m_sockfd == -1)
{
setError(IO_UnspecifiedError, NotCreated);
return false;
}
resetError();
fd_set readfds, writefds, exceptfds;
fd_set *preadfds = 0L, *pwritefds = 0L, *pexceptfds = 0L;
if (input)
{
preadfds = &readfds;
FD_ZERO(preadfds);
FD_SET(m_sockfd, preadfds);
*input = false;
}
if (output)
{
pwritefds = &writefds;
FD_ZERO(pwritefds);
FD_SET(m_sockfd, pwritefds);
*output = false;
}
if (exception)
{
pexceptfds = &exceptfds;
FD_ZERO(pexceptfds);
FD_SET(m_sockfd, pexceptfds);
*exception = false;
}
int retval;
if (timeout < 0)
retval = KSocks::self()->select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, 0L);
else
{
// convert the milliseconds to timeval
struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = timeout % 1000 * 1000;
retval = select(m_sockfd + 1, preadfds, pwritefds, pexceptfds, &tv);
}
if (retval == -1)
{
setError(IO_UnspecifiedError, UnknownError);
return false;
}
if (retval == 0)
{
// timeout
if (timedout)
*timedout = true;
return true;
}
if (input && FD_ISSET(m_sockfd, preadfds))
*input = true;
if (output && FD_ISSET(m_sockfd, pwritefds))
*output = true;
if (exception && FD_ISSET(m_sockfd, pexceptfds))
*exception = true;
return true;
}
void KSocksSocketDevice::initSocks()
{
static bool init = false;
if (init)
return;
if (kapp == 0L)
return; // no KApplication, so don't initialise
// this should, however, test for KInstance
init = true;
if (KSocks::self()->hasSocks())
delete KSocketDevice::setDefaultImpl(new KSocketDeviceFactory<KSocksSocketDevice>);
}
#if 0
static bool register()
{
KSocketDevice::addNewImpl(new KSocketDeviceFactory<KSocksSocketDevice>, 0);
}
static bool register = registered();
#endif
KNetwork::KSocketBase::blocking
bool blocking() const
Retrieves this socket's blocking mode.
Definition: ksocketbase.cpp:81
KNetwork::KSocksSocketDevice::capabilities
virtual int capabilities() const
Sets our capabilities.
Definition: ksockssocketdevice.cpp:65
KNetwork::KSocketAddress::length
Q_UINT16 length() const
Returns the length of this socket address structure.
Definition: ksocketaddress.cpp:475
KNetwork::KSocksSocketDevice::listen
virtual bool listen(int backlog)
Overrides listening.
Definition: ksockssocketdevice.cpp:97
KNetwork::KResolverEntry
One resolution entry.
Definition: kresolver.h:66
KNetwork::KActiveSocketBase::resetError
void resetError()
Resets the socket error code and the I/O Device's status.
Definition: ksocketbase.cpp:315
KNetwork::KSocksSocketDevice::accept
virtual KSocksSocketDevice * accept()
Overrides accepting.
Definition: ksockssocketdevice.cpp:169
KNetwork::KSocksSocketDevice::localAddress
virtual KSocketAddress localAddress() const
Overrides getting socket address.
Definition: ksockssocketdevice.cpp:328
KNetwork::KSocketAddress
A generic socket address.
Definition: ksocketaddress.h:423
KSocks::sendto
int sendto(int s, const void *msg, unsigned long int len, int flags, const sockaddr *to, ksocklen_t tolen)
This is the re-implementation of libc's function of the same name.
Definition: ksocks.cpp:514
KNetwork::KSocketAddress::address
const sockaddr * address() const
Returns the socket address structure, to be passed down to low level functions.
Definition: ksocketaddress.cpp:451
KNetwork::KSocksSocketDevice::peerAddress
virtual KSocketAddress peerAddress() const
Overrides getting peer address.
Definition: ksockssocketdevice.cpp:357
KNetwork::KSocksSocketDevice::bind
virtual bool bind(const KResolverEntry &address)
Overrides binding.
Definition: ksockssocketdevice.cpp:73
KSocks::self
static KSocks * self()
Return an instance of class KSocks *.
Definition: ksocks.cpp:212
KNetwork::KSocksSocketDevice
The low-level class for SOCKS proxying.
Definition: ksockssocketdevice.h:40
KNetwork::KSocketDevice::addNewImpl
static void addNewImpl(KSocketDeviceFactoryBase *factory, int capabilities)
Adds a factory of KSocketDevice objects to the list, along with its capabilities flag.
Definition: ksocketdevice.cpp:879
KNetwork::KSocketDevice::create
virtual bool create(int family, int type, int protocol)
Creates a socket but don't connect or bind anywhere.
Definition: ksocketdevice.cpp:201
KNetwork::KActiveSocketBase::setError
void setError(int status, SocketError error)
Sets the socket's error code and the I/O Device's status.
Definition: ksocketbase.cpp:309
KNetwork::KSocksSocketDevice::poll
virtual bool poll(bool *input, bool *output, bool *exception=0L, int timeout=-1, bool *timedout=0L)
Overrides polling.
Definition: ksockssocketdevice.cpp:392
KSocks::accept
int accept(int s, sockaddr *addr, ksocklen_t *addrlen)
This is the re-implementation of libc's function of the same name.
Definition: ksocks.cpp:560
KNetwork::KSocksSocketDevice::writeBlock
virtual Q_LONG writeBlock(const char *data, Q_ULONG len)
Overrides writing.
Definition: ksockssocketdevice.cpp:301
KNetwork::KSocksSocketDevice::readBlock
virtual Q_LONG readBlock(char *data, Q_ULONG maxlen)
Overrides reading.
Definition: ksockssocketdevice.cpp:217
KNetwork::KResolverEntry::address
KSocketAddress address() const
Retrieves the socket address associated with this entry.
Definition: kresolver.cpp:138
KNetwork::KSocketDevice::setDefaultImpl
static KSocketDeviceFactoryBase * setDefaultImpl(KSocketDeviceFactoryBase *factory)
Sets the default KSocketDevice implementation to use and return the old factory.
Definition: ksocketdevice.cpp:871
KNetwork::KSocketDeviceFactory
This class provides functionality for creating and registering socket implementations.
Definition: ksocketdevice.h:416
KNetwork::KSocksSocketDevice::externalAddress
virtual KSocketAddress externalAddress() const
Overrides getting external address.
Definition: ksockssocketdevice.cpp:386
KSocks::select
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
This is the re-implementation of libc's function of the same name.
Definition: ksocks.cpp:572
KNetwork::KResolverEntry::length
Q_UINT16 length() const
Retrieves the length of the socket address structure.
Definition: kresolver.cpp:144
KNetwork::KSocketDevice::m_sockfd
int m_sockfd
The socket file descriptor.
Definition: ksocketdevice.h:95
KSocks::recvfrom
int recvfrom(int s, void *buf, unsigned long int len, int flags, sockaddr *from, ksocklen_t *fromlen)
This is the re-implementation of libc's function of the same name.
Definition: ksocks.cpp:501
KNetwork::KSocksSocketDevice::peekBlock
virtual Q_LONG peekBlock(char *data, Q_ULONG maxlen)
Overrides peeking.
Definition: ksockssocketdevice.cpp:259
KSocks::connect
int connect(int sockfd, const sockaddr *serv_addr, ksocklen_t addrlen)
This is the re-implementation of libc's function of the same name.
Definition: ksocks.cpp:479
KNetwork::KSocketBase::setBlocking
virtual bool setBlocking(bool enable)
Sets this socket's blocking mode.
Definition: ksocketbase.cpp:76
KNetwork::KSocketDevice
Low-level socket functionality.
Definition: ksocketdevice.h:50
KNetwork::KSocksSocketDevice::KSocksSocketDevice
KSocksSocketDevice(const KSocketBase *=0L)
Constructor.
Definition: ksockssocketdevice.cpp:46
KNetwork::KSocketBase
Basic socket functionality.
Definition: ksocketbase.h:97
KNetwork::KSocksSocketDevice::~KSocksSocketDevice
virtual ~KSocksSocketDevice()
Destructor.
Definition: ksockssocketdevice.cpp:60
KNetwork::KSocketAddress::setLength
KSocketAddress & setLength(Q_UINT16 len)
Sets the length of this socket structure.
Definition: ksocketaddress.cpp:482
KNetwork::KSocksSocketDevice::connect
virtual bool connect(const KResolverEntry &address)
Overrides connection.
Definition: ksockssocketdevice.cpp:119

KDE Home | KDE Accessibility Home | Description of Access Keys