kextsock.cpp

来自「将konqueror浏览器移植到ARM9 2410中」· C++ 代码 · 共 2,280 行 · 第 1/4 页

CPP
2,280
字号
 * returns the binding port */QString KExtendedSocket::bindPort() const{  return d->localservice;}/* * 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 (m_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 (m_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 (m_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();  if (m_status < created)    return false;  if (sockfd == -1)    return false;		// error!  int on = (int)enable;		// just to be on the safe side  if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1)    {      setError(IO_UnspecifiedError, errno);      return false;    }  return true;}/* * Retrieves the reusability flag for this socket */bool KExtendedSocket::addressReusable(){  cleanError();  if (m_status < created)    return false;  if (sockfd == -1)    return false;  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;}/* * Sets the buffer sizes in this socket * Also, we create or delete the socket notifiers */bool KExtendedSocket::setBufferSize(int rsize, int wsize){  cleanError();  if (m_status < created)    return false;  if (sockfd == -1)    return false;  if (m_flags & passiveSocket)    return false;		// no I/O on passive sockets  if (rsize < -2)    return false;  if (wsize < -2)    return false;  // LOCK BUFFER MUTEX  if (rsize == 0 && m_flags & inputBufferedSocket)    {      // user wants to disable input buffering      m_flags &= ~inputBufferedSocket;      if (d->qsnIn && !d->emitRead)	d->qsnIn->setEnabled(false);      consumeReadBuffer(readBufferSize(), NULL, true);      d->inMaxSize = 0;    }  else if (rsize != -2)    {      // enabling input buffering      if (rsize)	m_flags |= inputBufferedSocket;      d->inMaxSize = rsize;      if (rsize > 0 && (unsigned)rsize < readBufferSize())	// input buffer has more data than the new size; discard	consumeReadBuffer(readBufferSize() - rsize, NULL, true);      if (d->qsnIn == NULL)	{	  d->qsnIn = new QSocketNotifier(sockfd, QSocketNotifier::Read);	  QObject::connect(d->qsnIn, SIGNAL(activated(int)), this, SLOT(socketActivityRead()));	}    }  if (wsize == 0 & m_flags & outputBufferedSocket)    {      // disabling output buffering      m_flags &= ~outputBufferedSocket;      if (d->qsnOut && !d->emitWrite)	d->qsnOut->setEnabled(false);      consumeWriteBuffer(writeBufferSize());      d->outMaxSize = 0;    }  else if (wsize != -2)    {      // enabling input buffering      if (wsize)	m_flags |= outputBufferedSocket;      d->outMaxSize = wsize;      if (wsize > 0 && (unsigned)wsize < writeBufferSize())	// output buffer is bigger than it is to become; shrink	consumeWriteBuffer(writeBufferSize() - wsize);      if (d->qsnOut == NULL)	{	  d->qsnOut = new QSocketNotifier(sockfd, QSocketNotifier::Write);	  QObject::connect(d->qsnOut, SIGNAL(activated(int)), this, SLOT(socketActivityWrite()));	  // if the class is being created now, there's nothing to write yet	  // so socketActivityWrite() will get called once and disable	  // the notifier	}    }  // UNLOCK BUFFER MUTEX  setFlags((mode() & ~IO_Raw) | ((m_flags & bufferedSocket) ? 0 : IO_Raw));  return true;}/* * Finds the local address for this socket * if we have done this already, we return it. Otherwise, we'll have * to find the socket name */const KSocketAddress *KExtendedSocket::localAddress(){  if (d->local != NULL)    return d->local;  if (m_status < bound)    return NULL;  return d->local = localAddress(sockfd);}/* * Same thing, but for peer address. Which means this does not work on * passiveSocket and that we require to be connected already. Also note that * the behaviour on connectionless sockets is not defined here. */const KSocketAddress* KExtendedSocket::peerAddress(){  if (d->peer != NULL)    return d->peer;  if (m_flags & passiveSocket || m_status < connected)    return NULL;  return d->peer = peerAddress(sockfd);}/* * Perform the lookup on the addresses given */int KExtendedSocket::lookup(){  cleanError();  if (m_status >= lookupInProgress)    return EAI_BADFLAGS;	// we needed an error...  addrinfo hint;  memset(&hint, 0, sizeof(hint));  hint.ai_family = AF_UNSPEC;  // perform the global lookup before  if (d->resolution == NULL)    {      /* check socket type flags */      if (!process_flags(m_flags, hint))	return EAI_BADFLAGS;      int err = doLookup(d->host, d->service, hint, &d->resolution);      if (err != 0)	{	  setError(IO_LookupError, err);	  return err;	}    }  if (d->bindres == NULL && (d->localhost.length() > 0 || d->localservice.length() > 0))    {      /* leave hint.ai_socktype the same */      hint.ai_flags |= AI_PASSIVE;  // this is passive, for bind()      int err = doLookup(d->localhost, d->localservice, hint, &d->bindres);      if (err != 0)	{	  setError(IO_LookupError, err);	  return err;	}    }  m_status = lookupDone;  return 0;}/* * Performs an asynchronous lookup on the given address(es) */int KExtendedSocket::startAsyncLookup(){  cleanError();  if (m_status > lookupInProgress)    return -1;  if (m_status == lookupInProgress)    // already in progress    return 0;  addrinfo hint;  memset(&hint, 0, sizeof(hint));  hint.ai_family = AF_UNSPEC;  if (!process_flags(m_flags, hint))    return -1;  int n = 0;			// number of asynchronous lookups  if (d->host.length() > 0)    {      if ((m_flags & noResolve) == 0)	{	  d->dns = new KExtendedSocketLookup(d->host, d->service, hint);	  QObject::connect(d->dns, SIGNAL(resultsReady()), this, SLOT(dnsResultsReady()));	  n++;	}      else	{	  int err = doLookup(d->host, d->service, hint, &d->resolution);	  if (err != 0)	    {	      setError(IO_LookupError, err);	      return -1;	    }	}    }  if (d->localhost.length() > 0)    {      if ((m_flags & noResolve) == 0)	{	  hint.ai_flags |= AI_PASSIVE;	  d->dnsLocal = new KExtendedSocketLookup(d->localhost, d->localservice, hint);	  QObject::connect(d->dnsLocal, SIGNAL(resultsReady()), this, SLOT(dnsResultsReady()));	  n++;	}      else	{	  int err = doLookup(d->localhost, d->localservice, hint, &d->bindres);	  if (err != 0)	    {	      // damn! Early error in the lookup	      setError(IO_LookupError, err);	      if (d->dns != NULL)		{		  delete d->dns;		  d->dns = NULL;		}	      return -1;	    }	}    }  // if we are here, there were no errors  if (n)    m_status = lookupInProgress; // only if there actually is a running lookup  else    {      m_status = lookupDone;      dnsResultsReady();    }  return 0;}void KExtendedSocket::cancelAsyncLookup(){  cleanError();  if (m_status != lookupInProgress)    return;			// what's to cancel?  m_status = nothing;  if (d->dns)    {      delete d->dns;      d->dns = 0;    }  if (d->dnsLocal)    {      delete d->dnsLocal;      d->dnsLocal = 0;    }  local_freeaddrinfo(d->resolution);  local_freeaddrinfo(d->bindres);}int KExtendedSocket::listen(int N){  cleanError();  if ((m_flags & passiveSocket) == 0 || m_status >= listening)    return -2;  if (m_status < lookupDone)    if (lookup() < 0)      return -2;		// error!  addrinfo *p;  // doing the loop:  for (p = d->resolution->data; p; p = p->ai_next)    {      // check for family restriction      if (!valid_family(p, m_flags))	continue;      //kdDebug(170) << "Trying to listen on " << pretty_sock(p) << endl;      sockfd = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol);      if (sockfd == -1)	{	  // socket failed creating	  kdDebug(170) << "Failed to create: " << perror << endl;	  continue;	}      if (KSocks::self()->bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)	{	  kdDebug(170) << "Failed to bind: " << perror << endl;	  ::close(sockfd);	  sockfd = -1;	  continue;	}      // ok, socket has bound      // kdDebug(170) << "Socket bound: " << sockfd << endl;      m_status = bound;      break;    }  if (sockfd == -1)    {      setError(IO_ListenError, errno);      kdDebug(170) << "Listen error - sockfd is -1 " << endl;      return -1;    }  m_status = listening;  setFlags(IO_Sequential | IO_Raw | IO_ReadWrite);  int retval = KSocks::self()->listen(sockfd, N);  if (retval == -1)    setError(IO_ListenError, errno);  return retval == -1 ? -1 : 0;}int KExtendedSocket::accept(KExtendedSocket *&sock){  cleanError();  sock = NULL;  if ((m_flags & passiveSocket) == 0 || m_status >= accepting)    return -2;  if (m_status < listening)    if (listen() < 0)      return -2;		// error!  // let's see  // if we have a timeout in place, we have to place this socket in non-blocking  // mode  bool block = blockingMode();  struct sockaddr sa;  ksocklen_t len = sizeof(sa);  sock = NULL;  if (d->timeout.tv_sec > 0 || d->timeout.tv_usec > 0)    {      fd_set set;      setBlockingMode(false);	// turn on non-blocking      FD_ZERO(&set);      FD_SET(sockfd, &set);      //kdDebug(170).form("Accepting on %d with %d.%06d second timeout\n",      //	     sockfd, d->timeout.tv_sec, d->timeout.tv_usec);      // check if there is anything to accept now      int retval = KSocks::self()->select(sockfd + 1, &set, NULL, NULL, &d->timeout);      if (retval == -1)	{	  setError(IO_UnspecifiedError, errno);	  return -1;		// system error	}      else if (retval == 0 || !FD_ISSET(sockfd, &set))	{	  setError(IO_TimeOutError, 0);	  return -3;		// timeout	}    }  // it's common stuff here  int newfd = KSocks::self()->accept(sockfd, &sa, &len);  if (newfd == -1)    {      setError(IO_AcceptError, errno);      kdWarning(170) << "Error accepting on socket " << sockfd << ":"		     << perror << endl;      return -1;    }  //kdDebug(170).form("Socket %d accepted socket %d\n", sockfd, newfd);  setBlockingMode(block);	// restore blocking mode  sock = new KExtendedSocket;  sock->m_status = connected;  sock->sockfd = newfd;  sock->setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);  sock->setBufferSize(0, 0);	// always unbuffered here. User can change that later  return 0;}/* * tries to connect * * FIXME! * This function is critical path. It has to be cleaned up and made faster */int KExtendedSocket::connect(){  cleanError();  if (m_flags & passiveSocket)    return -2;  if (m_status < lookupDone)    if (lookup() < 0)      return -2;  addrinfo *p, *q;  timeval end, now;  // Ok, things are a little tricky here  // Let me explain  // getaddrinfo() will return several different families of sockets  // When we have to bind before we connect, we have to make sure we're binding  // and connecting to the same family, or things won't work  bool doingtimeout = d->timeout.tv_sec > 0 || d->timeout.tv_usec > 0;  if (doingtimeout)    {      gettimeofday(&end, NULL);      end.tv_usec += d->timeout.tv_usec;      end.tv_sec += d->timeout.tv_sec;      if (end.tv_usec > 1000*1000)	{	  end.tv_usec -= 1000*1000;	  end.tv_sec++;	}//	kdDebug(170).form("Connection with timeout of %d.%06d seconds (ends in %d.%06d)\n",

⌨️ 快捷键说明

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