kextsock.cpp

来自「konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版」· C++ 代码 · 共 2,230 行 · 第 1/4 页

CPP
2,230
字号
/* *  This file is part of the KDE libraries *  Copyright (C) 2000-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 <sys/types.h>#include <sys/socket.h>#include <sys/times.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/un.h>#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <netdb.h>#include <stdlib.h>#include <unistd.h>#include <qglobal.h>#include <qstring.h>#include <qiodevice.h>#include <qsocketnotifier.h>#include <qguardedptr.h>#include "kresolver.h"#include "kdebug.h"#include "kextsock.h"#include "ksockaddr.h"#include "ksocks.h"#ifdef __CYGWIN__#include "netsupp.h"#endif using namespace KNetwork;//// Internal class definitions//class KExtendedSocketPrivate{public:  int flags;			// socket flags  int status;			// status  int syserror;			// the system error value  timeval timeout;		// connection/acception timeout  KResolver resRemote;		// the resolved addresses  KResolver resLocal;		// binding resolution  unsigned current;		// used by the asynchronous connection  ::KSocketAddress *local;	// local socket address  ::KSocketAddress *peer;	// peer socket address  QSocketNotifier *qsnIn, *qsnOut;  int inMaxSize, outMaxSize;  bool emitRead : 1, emitWrite : 1;  mutable bool addressReusable : 1, ipv6only : 1;  KExtendedSocketPrivate() :    flags(0), status(0), syserror(0),    current(0), local(0), peer(0),    qsnIn(0), qsnOut(0), inMaxSize(-1), outMaxSize(-1), emitRead(false), emitWrite(false),    addressReusable(false), ipv6only(false)  {    timeout.tv_sec = timeout.tv_usec = 0;  }};// translate KExtendedSocket flags into KResolver onesstatic bool process_flags(int flags, int& socktype, int& familyMask, int& outflags){  switch (flags & (KExtendedSocket::streamSocket | KExtendedSocket::datagramSocket | KExtendedSocket::rawSocket))    {    case 0:      /* No flags given, use default */    case KExtendedSocket::streamSocket:      /* streaming socket requested */      socktype = SOCK_STREAM;      break;    case KExtendedSocket::datagramSocket:      /* datagram packet socket requested */      socktype = SOCK_DGRAM;      break;    case KExtendedSocket::rawSocket:      /* raw socket requested. I wouldn't do this if I were you... */      socktype = SOCK_RAW;      break;    default:      /* the flags were used in an invalid manner */      return false;    }  if (flags & KExtendedSocket::knownSocket)    {      familyMask = 0;      if ((flags & KExtendedSocket::unixSocket) == KExtendedSocket::unixSocket)	familyMask |= KResolver::UnixFamily;      switch ((flags & (KExtendedSocket::ipv6Socket|KExtendedSocket::ipv4Socket)))	{	case KExtendedSocket::ipv4Socket:	  familyMask |= KResolver::IPv4Family;	  break;	case KExtendedSocket::ipv6Socket:	  familyMask |= KResolver::IPv6Family;	  break;	case KExtendedSocket::inetSocket:	  familyMask |= KResolver::InternetFamily;	  break;	}      // those are all the families we know about    }  else    familyMask = KResolver::KnownFamily;  /* check other flags */  outflags = (flags & KExtendedSocket::passiveSocket ? KResolver::Passive : 0) |    (flags & KExtendedSocket::canonName ? KResolver::CanonName : 0) |    (flags & KExtendedSocket::noResolve ? KResolver::NoResolve : 0);  if (getenv("KDE_NO_IPV6"))    familyMask &= ~KResolver::IPv6Family;  return true;}// "skips" at most len bytes from file descriptor fd// that is, we will try and read that much data and discard// it. We will stop when we have read those or when the read// function returns errorstatic int skipData(int fd, unsigned len){  char buf[1024];  unsigned skipped = 0;  while (len)    {      int count = sizeof(buf);      if ((unsigned)count > len)	count = len;      count = KSocks::self()->read(fd, buf, count);      if (count == -1)	return -1;      else	{	  len -= count;	  skipped += count;	}    }  return skipped;}/* * class KExtendedSocket */// default constructorKExtendedSocket::KExtendedSocket() :  sockfd(-1), d(new KExtendedSocketPrivate){}// constructor with hostnameKExtendedSocket::KExtendedSocket(const QString& host, int port, int flags) :  sockfd(-1), d(new KExtendedSocketPrivate){  setAddress(host, port);  setSocketFlags(flags);}// sameKExtendedSocket::KExtendedSocket(const QString& host, const QString& service, int flags) :  sockfd(-1), d(new KExtendedSocketPrivate){  setAddress(host, service);  setSocketFlags(flags);}// destroy the classKExtendedSocket::~KExtendedSocket(){  closeNow();  if (d->local != NULL)    delete d->local;  if (d->peer != NULL)    delete d->peer;  if (d->qsnIn != NULL)    delete d->qsnIn;  if (d->qsnOut != NULL)    delete d->qsnOut;  delete d;}void KExtendedSocket::reset(){  closeNow();  release();  d->current = 0;  d->status = nothing;  d->syserror = 0;}int KExtendedSocket::socketStatus() const{  return d->status;}void KExtendedSocket::setSocketStatus(int newstatus){  d->status = newstatus;}void KExtendedSocket::setError(int errorcode, int syserror){  setStatus(errorcode);  d->syserror = syserror;}int KExtendedSocket::systemError() const{  return d->syserror;}/* * Sets socket flags * This is only allowed if we are in nothing state */int KExtendedSocket::setSocketFlags(int flags){  if (d->status > nothing)    return -1;			// error!  return d->flags = flags;}int KExtendedSocket::socketFlags() const{  return d->flags;}/* * Sets socket target hostname * This is only allowed if we are in nothing state */bool KExtendedSocket::setHost(const QString& host){  if (d->status > nothing)    return false;		// error!  d->resRemote.setNodeName(host);  return true;}/* * returns the hostname */QString KExtendedSocket::host() const{  return d->resRemote.nodeName();}/* * Sets the socket target port/service * Same thing: only state 'nothing' */bool KExtendedSocket::setPort(int port){  return setPort(QString::number(port));}bool KExtendedSocket::setPort(const QString& service){  if (d->status > nothing)    return false;		// error  d->resRemote.setServiceName(service);  return true;}/* * returns the service port number */QString KExtendedSocket::port() const{  return d->resRemote.serviceName();}/* * sets the address */bool KExtendedSocket::setAddress(const QString& host, int port){  return setHost(host) && setPort(port);}/* * the same */bool KExtendedSocket::setAddress(const QString& host, const QString& serv){  return setHost(host) && setPort(serv);}/* * Sets the bind hostname * This is only valid in the 'nothing' state and if this is not a * passiveSocket socket */bool KExtendedSocket::setBindHost(const QString& host){  if (d->status > nothing || d->flags & passiveSocket)    return false;		// error  d->resLocal.setServiceName(host);  return true;}/* * Unsets the bind hostname * same thing */bool KExtendedSocket::unsetBindHost(){  return setBindHost(QString::null);}/* * returns the binding host */QString KExtendedSocket::bindHost() const{  return d->resLocal.serviceName();}/* * Sets the bind port * Same condition as setBindHost */bool KExtendedSocket::setBindPort(int port){  return setBindPort(QString::number(port));}bool KExtendedSocket::setBindPort(const QString& service){  if (d->status > nothing || d->flags & passiveSocket)    return false;		// error  d->resLocal.setServiceName(service);  return true;}/* * unsets the bind port */bool KExtendedSocket::unsetBindPort(){  return setBindPort(QString::null);}/* * returns the binding port */QString KExtendedSocket::bindPort() const{  return d->resLocal.serviceName();}/* * sets the binding address */bool KExtendedSocket::setBindAddress(const QString& host, int port){  return setBindHost(host) && setBindPort(port);}/* * same */bool KExtendedSocket::setBindAddress(const QString& host, const QString& service){  return setBindHost(host) && setBindPort(service);}/* * unsets binding address */bool KExtendedSocket::unsetBindAddress(){  return unsetBindHost() && unsetBindPort();}/* * sets the timeout for the connection */bool KExtendedSocket::setTimeout(int secs, int usecs){  if (d->status >= connected)	// closed?    return false;  d->timeout.tv_sec = secs;  d->timeout.tv_usec = usecs;  return true;}/* * returns the timeout */timeval KExtendedSocket::timeout() const{  return d->timeout;}/* * Sets the blocking mode on this socket */bool KExtendedSocket::setBlockingMode(bool enable){  cleanError();  if (d->status < created)    return false;  if (sockfd == -1)    return false;		// error!  int fdflags = fcntl(sockfd, F_GETFL, 0);  if (fdflags == -1)    return false;		// error!  if (!enable)    fdflags |= O_NONBLOCK;  else    fdflags &= ~O_NONBLOCK;  if (fcntl(sockfd, F_SETFL, fdflags) == -1)    {      setError(IO_UnspecifiedError, errno);      return false;    }  return true;}/* * Returns the blocking mode on the socket */bool KExtendedSocket::blockingMode(){  cleanError();  if (d->status < created)    return false;		// sockets not created are in blocking mode  if (sockfd == -1)    return false;		// error  int fdflags = fcntl(sockfd, F_GETFL, 0);  if (fdflags == -1)    {      setError(IO_UnspecifiedError, errno);      return false;    }  return (fdflags & O_NONBLOCK) == 0; // non-blocking == false}/* * Sets the reusability flag for this socket in the OS */bool KExtendedSocket::setAddressReusable(bool enable){  cleanError();  d->addressReusable = enable;  if (d->status < created)    return true;  if (sockfd == -1)    return true;  if (!setAddressReusable(sockfd, enable))    {      setError(IO_UnspecifiedError, errno);      return false;    }  return true;}bool KExtendedSocket::setAddressReusable(int fd, bool enable){  if (fd == -1)    return false;  int on = enable;		// just to be on the safe side  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1)    return false;  return true;}/* * Retrieves the reusability flag for this socket */bool KExtendedSocket::addressReusable(){  cleanError();  if (d->status < created)    return d->addressReusable;  if (sockfd == -1)    return d->addressReusable;  int on;  socklen_t onsiz = sizeof(on);  if (getsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, &onsiz) == -1)    {      setError(IO_UnspecifiedError, errno);      return false;    }  return on != 0;}/* * Set the IPV6_V6ONLY flag */bool KExtendedSocket::setIPv6Only(bool enable){#ifdef IPV6_V6ONLY  cleanError();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?