kextsock.cpp

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

CPP
2,280
字号
#ifdef HAVE_RES_INIT  if (err == EAI_NONAME || err == EAI_NODATA || err == EAI_AGAIN)    {      // A loookup error occurred and nothing was resolved      // However, since the user could have just dialed up to the ISP      // and new nameservers were written to /etc/resolv.conf, we have      // to re-parse that      res_init();      // Now try looking up again      err = kde_getaddrinfo(_host, _serv, &hint, res);    }#endif  return err;}// sets the emission of the readyRead signalvoid KExtendedSocket::enableRead(bool enable){  // check if we can disable the socket notifier  // saves us a few cycles  // this is so because in buffering mode, we rely on these signals  // being emitted to do our I/O. We couldn't disable them here  if (!enable && (m_flags & inputBufferedSocket) == 0 && d->qsnIn)    d->qsnIn->setEnabled(false);  else if (enable && d->qsnIn)    // we can enable it always    d->qsnIn->setEnabled(true);  d->emitRead = enable;}// sets the emission of the readyWrite signalvoid KExtendedSocket::enableWrite(bool enable){  // same thing as above  if (!enable && (m_flags & outputBufferedSocket) == 0 && d->qsnOut)    d->qsnOut->setEnabled(false);  else if (enable && d->qsnOut)    // we can enable it always    d->qsnOut->setEnabled(true);  d->emitWrite = enable;}// protected slot// this is connected to d->qsnIn::activated(int)void KExtendedSocket::socketActivityRead(){  if (m_flags & passiveSocket)    return;  if (m_status == connecting)    {      connectionEvent();      return;    }  if (m_status != connected)    return;  // do we need to do I/O here?  if (m_flags & inputBufferedSocket)    {      // aye. Do read from the socket and feed our buffer      QByteArray a;      char buf[1024];      int len, totalread = 0;      // LOCK MUTEX      unsigned cursize = readBufferSize();      if (d->inMaxSize == -1 || cursize < (unsigned)d->inMaxSize)	{	  do	    {	      // check that we can read that many bytes	      if (d->inMaxSize != -1 && d->inMaxSize - (cursize + totalread) < sizeof(buf))		// no, that would overrun the buffer		// note that this will also make us exit the loop		len = d->inMaxSize - (cursize + totalread);	      else		len = sizeof(buf);	      len = KSocks::self()->read(sockfd, buf, len);	      if (len > 0)		{		  // normal read operation		  a.resize(a.size() + len);		  memcpy(a.data() + totalread, buf, len);		  totalread += len;	// totalread == a.size() now		}	      else if (len == 0)		{		  // EOF condition here		  d->qsnIn->setEnabled(false);		  emit closed(involuntary |			      (readBufferSize() ? availRead : 0) |			      (writeBufferSize() ? dirtyWrite : 0));		  sockfd = -1;	// we're closed		  m_status = done;		  return;		}	      else		{		  // error!		  setError(IO_ReadError, errno);		  return;		}	      // will loop only for normal read operations	    }	  while (len == sizeof(buf));	  feedReadBuffer(a.size(), a.data());	}      // UNLOCK MUTEX    }  if (d->emitRead)    emit readyRead();}void KExtendedSocket::socketActivityWrite(){  if (m_flags & passiveSocket)    return;  if (m_status == connecting)    {      connectionEvent();      return;    }  if (m_status != connected && m_status != closing)    return;  flush();  bool empty = writeBufferSize() == 0;  if (d->emitWrite && empty)    emit readyWrite();  else if (!d->emitWrite)    {      // check if we can disable the notifier      d->qsnOut->setEnabled(!empty); // leave it enabled only if we have more data to send    }  if (m_status == closing && empty)    {      // done sending the missing data!      m_status = done;      emit closed(delayed | (readBufferSize() ? availRead : 0));      delete d->qsnOut;      ::close(sockfd);      d->qsnOut = NULL;      sockfd = -1;    }}// this function is called whenever we have a "connection event"// that is, whenever our asynchronously connecting socket throws// an eventvoid KExtendedSocket::connectionEvent(){  if (m_status != connecting)    return;			// move along. There's nothing to see here  int errcode = 0;  if (sockfd != -1)    {      // our socket has activity      // find out what it was      int retval;      socklen_t len = sizeof(errcode);      retval = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len);      if (retval == -1 || errcode != 0)	{	  // socket activity and there was error?	  // that means the socket probably did not connect	  if (d->qsnIn)	    delete d->qsnIn;	  if (d->qsnOut)	    delete d->qsnOut;	  ::close(sockfd);	  sockfd = -1;	  d->qsnIn = d->qsnOut = NULL;	  setError(IO_ConnectError, errcode);	}      else	{	  // hmm, socket activity and there was no error?	  // that means it connected	  // YAY!	  cleanError();	  m_status = connected;	  setBlockingMode(true);	  setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);	  setBufferSize(m_flags & inputBufferedSocket ? -1 : 0,			m_flags & outputBufferedSocket ? -1 : 0);	  emit connectionSuccess();	  return;	}    }  // ok, we have to try something here  // and sockfd == -1  addrinfo *p, *q;  if (d->current == 0)    p = d->current = d->resolution->data;  else    p = d->current->ai_next;  for (q = d->bindres->data; p; p = p->ai_next)    {      // same code as in connect()      if (q != NULL)	{	  if (q->ai_family != d->current->ai_family)	    // differing families, scan bindres for a matching family	    for (q = d->bindres->data; q; q = q->ai_next)	      if (q->ai_family == p->ai_family)		break;	  if (q == NULL || q->ai_family != p->ai_family)	    {	      // no matching families for this	      q = d->bindres->data;	      continue;	    }	  errno = 0;	  sockfd = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol);	  setError(IO_ConnectError, errno);	  errcode = errno;	  if (sockfd == -1)	    continue;		// cannot create this socket	  if (KSocks::self()->bind(sockfd, q->ai_addr, q->ai_addrlen) == -1)	    {	      ::close(sockfd);	      sockfd = -1;	      continue;	    }	}      else	{	  // no need to bind, just create	  sockfd = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol);	  if (sockfd == -1)	    {	      setError(IO_ConnectError, errno);	      errcode = errno;	      continue;	    }	}      setBlockingMode(false);      if (KSocks::self()->connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)	{	  if (errno != EWOULDBLOCK && errno != EINPROGRESS)	    {	      setError(IO_ConnectError, errno);	      ::close(sockfd);	      sockfd = -1;	      errcode = errno;	      continue;	    }	  // error here is either EWOULDBLOCK or EINPROGRESS	  // so, it is a good condition	  d->qsnIn = new QSocketNotifier(sockfd, QSocketNotifier::Read);	  QObject::connect(d->qsnIn, SIGNAL(activated(int)), this, SLOT(socketActivityRead()));	  d->qsnOut = new QSocketNotifier(sockfd, QSocketNotifier::Write);	  QObject::connect(d->qsnOut, SIGNAL(activated(int)), this, SLOT(socketActivityWrite()));	  // ok, let the Qt event loop do the selecting for us	  // just make sure we know where to go on in the next iteration	  d->current = p;	  return;	}      // eh, what?      // the non-blocking socket returned valid connection?      // already?      // I suppose that could happen...      cleanError();      m_status = connected;      setBlockingMode(true);      setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);      setBufferSize(m_flags & inputBufferedSocket ? -1 : 0,		    m_flags & outputBufferedSocket ? -1 : 0);      emit connectionSuccess();      return;    }  // if we got here, it means that there are no more options to connect  emit connectionFailed(errcode);  m_status = lookupDone;	// go back}  void KExtendedSocket::dnsResultsReady(){  // check that this function was called in a valid state  if (m_status != lookupInProgress)    return;  // valid state. Are results fully ready?  if ((d->dns != NULL && d->dns->isWorking()) ||      (d->dnsLocal != NULL && d->dnsLocal->isWorking()))    // no, still waiting for answer in one of the lookups    return;  // ok, we have all results  if (d->dns)    d->resolution = d->dns->results();  if (d->dnsLocal)    d->bindres = d->dnsLocal->results();  // count how many results we have  int n = 0;  addrinfo *p;  for (p = d->resolution->data; p; p = p->ai_next)    n++;  for (p = d->bindres->data; p; p = p->ai_next)    n++;  m_status = lookupDone;  emit lookupFinished(n);  return;}void KExtendedSocket::startAsyncConnectSlot(){  startAsyncConnect();}int KExtendedSocket::resolve(sockaddr *sock, ksocklen_t len, QString &host,			     QString &port, int flags){  int err;  char h[NI_MAXHOST], s[NI_MAXSERV];  h[0] = s[0] = '\0';  err = getnameinfo(sock, len, h, sizeof(h) - 1, s, sizeof(s) - 1, flags);  host = QString::fromUtf8(h);  port = QString::fromUtf8(s);  return err;}int KExtendedSocket::resolve(KSocketAddress *sock, QString &host, QString &port,			     int flags){  return resolve(sock->data, sock->datasize, host, port, flags);}QList<KAddressInfo> KExtendedSocket::lookup(const QString& host, const QString& port,					    int flags, int *error){  int err;  addrinfo hint, *p;  kde_addrinfo *res;  QList<KAddressInfo> l;  memset(&hint, 0, sizeof(hint));  if (!process_flags(flags, hint))    {      if (error)	*error = EAI_BADFLAGS;      return l;    }//  kdDebug(170) << "Performing lookup on " << host << "|" << port << endl;  err = doLookup(host, port, hint, &res);  if (err)    {      if (error)	*error = err;      return l;    }  for (p = res->data; p; p = p->ai_next)    if (valid_family(p, flags))      {	KAddressInfo *ai = new KAddressInfo(p);//	kdDebug(170) << "Using socket " << pretty_sock(p) << endl;	l.append(ai);      }  kde_freeaddrinfo(res);	// this one we know where it came from  return l;}KSocketAddress *KExtendedSocket::localAddress(int fd){  KSocketAddress *local;  struct sockaddr static_sa, *sa = &static_sa;  ksocklen_t len = sizeof(static_sa);  /* find out the socket length, in advance   * we use a sockaddr allocated on the heap just not to pass down   * a NULL pointer to the first call. Some systems are reported to   * set len to 0 if we pass NULL as the sockaddr */  if (KSocks::self()->getsockname(fd, sa, &len) == -1)    return NULL;		// error!  /* was it enough? */  if (len > sizeof(static_sa)#ifdef HAVE_SOCKADDR_SA_LEN      || sa->sa_len > sizeof(static_sa)#endif      )    {      /* nope, malloc a new socket with the proper size */#ifdef HAVE_SOCKADDR_SA_LEN      if (sa->sa_len != len)        len = sa->sa_len;#endif      sa = (sockaddr*)malloc(len);      if (sa == NULL)	return NULL;		// out of memory      if (KSocks::self()->getsockname(fd, sa, &len) == -1)	{	  free(sa);	  return NULL;	}      local = KSocketAddress::newAddress(sa, len);      free(sa);    }  else    local = KSocketAddress::newAddress(sa, len);  return local;}/* This is exactly the same code as localAddress, except * we call getpeername here */KSocketAddress *KExtendedSocket::peerAddress(int fd){  KSocketAddress *peer;  struct sockaddr static_sa, *sa = &static_sa;  ksocklen_t len = sizeof(static_sa);  /* find out the socket length, in advance   * we use a sockaddr allocated on the heap just not to pass down   * a NULL pointer to the first call. Some systems are reported to   * set len to 0 if we pass NULL as the sockaddr */  if (KSocks::self()->getpeername(fd, sa, &len) == -1)    return NULL;		// error!  /* was it enough? */  if (len > sizeof(static_sa)#ifdef HAVE_SOCKADDR_SA_LEN      || sa->sa_len > sizeof(static_sa)#endif      )    {      /* nope, malloc a new socket with the proper size */#ifdef HAVE_SOCKADDR_SA_LEN      if (sa->sa_len != len)        len = sa->sa_len;#endif      sa = (sockaddr*)malloc(len);      if (sa == NULL)	return NULL;		// out of memory      if (KSocks::self()->getpeername(fd, sa, &len) == -1)	{	  free(sa);	  return NULL;	}      peer = KSocketAddress::newAddress(sa, len);      free(sa);    }  else    peer = KSocketAddress::newAddress(sa, len);  return peer;}QString KExtendedSocket::strError(int code, int syserr){  const char * msg;  if (code == IO_LookupError)    msg = gai_strerror(syserr);  else    msg = strerror(syserr);  return QString::fromLocal8Bit(msg);}/* * class KAddressInfo */KAddressInfo::KAddressInfo(addrinfo *p){   ai = (addrinfo *) malloc(sizeof(addrinfo));   memcpy(ai, p, sizeof(addrinfo));   ai->ai_next = NULL;   if (p->ai_canonname)   {      ai->ai_canonname = (char *) malloc(strlen(p->ai_canonname)+1);      strcpy(ai->ai_canonname, p->ai_canonname);   }   if (p->ai_addr && p->ai_addrlen)   {      ai->ai_addr = (struct sockaddr *) malloc(p->ai_addrlen);      memcpy(ai->ai_addr, p->ai_addr, p->ai_addrlen);   }   else   {      ai->ai_addr = 0;      ai->ai_addrlen = 0;   }   addr = KSocketAddress::newAddress(ai->ai_addr, ai->ai_addrlen);}KAddressInfo::~KAddressInfo(){  if (ai && ai->ai_canonname)    free(ai->ai_canonname);  if (ai && ai->ai_addr)    free(ai->ai_addr);    if (ai)    free(ai);  delete addr;}int KAddressInfo::flags() const{  return ai->ai_flags;}int KAddressInfo::family() const{  return ai->ai_family;}int KAddressInfo::socktype() const{  return ai->ai_socktype;}int KAddressInfo::protocol() const{  return ai->ai_protocol;}const char* KAddressInfo::canonname() const{  return ai->ai_canonname;}#include "kextsock.moc"#include "kextsocklookup.moc"

⌨️ 快捷键说明

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