kextsock.cpp

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

CPP
2,280
字号
//		     d->timeout.tv_sec, d->timeout.tv_usec, end.tv_sec, end.tv_usec);    }  if (d->bindres)    q = d->bindres->data;  else    q = NULL;  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 connect to " << pretty_sock(p) << endl;      if (q != NULL)	{//	  kdDebug(170) << "Searching bind socket for family " << p->ai_family << endl;	  if (q->ai_family != p->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	      kdDebug(170) << "No matching family for bind socket\n";	      q = d->bindres->data;	      continue;	    }	  kdDebug(170) << "Binding on " << pretty_sock(q) << " before connect" << endl;	  errno = 0;	  sockfd = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol);	  setError(IO_ConnectError, errno);	  if (sockfd == -1)	    continue;		// cannot create this socket	  if (KSocks::self()->bind(sockfd, q->ai_addr, q->ai_addrlen) == -1)	    {	      kdDebug(170) << "Bind failed: " << perror << endl;	      ::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);	      continue;	    }	}//      kdDebug(170) << "Socket " << sockfd << " created" << endl;      m_status = created;      // check if we have to do timeout      if (doingtimeout)	{	  fd_set rd, wr;	  setBlockingMode(false);	  // now try and connect	  if (KSocks::self()->connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)	    {	      // this could be EWOULDBLOCK	      if (errno != EWOULDBLOCK && errno != EINPROGRESS && error != ENOENT && errno != 0)		{		  kdDebug(170) << "Socket " << sockfd << " did not connect: " << perror << endl;		  setError(IO_ConnectError, errno);		  ::close(sockfd);		  sockfd = -1;		  continue;	// nope, another error		}	      FD_ZERO(&rd);	      FD_ZERO(&wr);	      FD_SET(sockfd, &rd);	      FD_SET(sockfd, &wr);	      int retval = KSocks::self()->select(sockfd + 1, &rd, &wr, NULL, &d->timeout);	      if (retval == -1)		{		  setError(IO_FatalError, errno);		  continue;	// system error		}	      else if (retval == 0)		{		  ::close(sockfd);		  sockfd = -1;		  kdDebug(170) << "Time out while trying to connect to " <<		    pretty_sock(p) << endl;		  m_status = lookupDone;		  setError(IO_TimeOutError, 0);		  return -3;	// time out		}	      // adjust remaining time	      gettimeofday(&now, NULL);	      d->timeout.tv_sec = end.tv_sec - now.tv_sec;	      d->timeout.tv_usec = end.tv_usec - now.tv_usec;	      if (d->timeout.tv_usec < 0)		{		  d->timeout.tv_usec += 1000*1000;		  d->timeout.tv_sec--;		}//	      kdDebug(170).form("Socket %d activity; %d.%06d seconds remaining\n",//			     sockfd, d->timeout.tv_sec, d->timeout.tv_usec);	      // this means that an event occurred in the socket	      int errcode;	      socklen_t len = sizeof(errcode);	      retval = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&errcode,				  &len);	      if (retval == -1 || errcode != 0)		{		  // socket did not connect		  kdDebug(170) << "Socket " << sockfd << " did not connect: "			    << strerror(errcode) << endl;		  ::close(sockfd);		  sockfd = -1;		  // this is HIGHLY UNLIKELY		  if (d->timeout.tv_sec == 0 && d->timeout.tv_usec == 0)		    {		      m_status = lookupDone;		      setError(IO_TimeOutError, 0);		      return -3; // time out		    }		  setError(IO_ConnectError, errcode);		  continue;		}	    }	  // getting here means it connected	  setBlockingMode(true);	  m_status = connected;	  setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);	  setBufferSize(m_flags & inputBufferedSocket ? -1 : 0,			m_flags & outputBufferedSocket ? -1 : 0);//	  kdDebug(170) << "Socket " << sockfd << " connected\n";	  return 0;	}      else	{	  // without timeouts	  if (KSocks::self()->connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)	    {	      kdDebug(170) << "Socket " << sockfd << " did not connect: " << perror << endl;	      setError(IO_ConnectError, errno);	      ::close(sockfd);	      sockfd = -1;	      continue;	    }	  m_status = connected;	  setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);	  setBufferSize(m_flags & inputBufferedSocket ? -1 : 0,			m_flags & outputBufferedSocket ? -1 : 0);//	  kdDebug(170) << "Socket " << sockfd << " connected\n";	  return 0;		// it connected	}    }  // getting here means no socket connected or stuff like that  kdDebug(170) << "Failed to connect\n";  return -1;}int KExtendedSocket::startAsyncConnect(){  cleanError();  // check status  if (m_status >= connected || m_flags & passiveSocket)    return -2;  if (m_status == connecting)    // already on async connect    return 0;  // check if we have to do lookup  // if we do, then we'll use asynchronous lookup and use  // signal lookupFinished to do connection  if (m_status < lookupDone)    {      QObject::connect(this, SIGNAL(lookupFinished(int)), this, SLOT(startAsyncConnectSlot()));      if (m_status < lookupInProgress)	return startAsyncLookup();      else	return 0;		// we still have to wait    }  // here we have m_status >= lookupDone and <= connecting  // we can do our connection  m_status = connecting;  connectionEvent();  if (m_status < connecting)    return -1;  return 0;}void KExtendedSocket::cancelAsyncConnect(){  if (m_status != connecting)    return;  if (sockfd != -1)    {      // we have a waiting connection      if (d->qsnIn)	delete d->qsnIn;      if (d->qsnOut)	delete d->qsnOut;      d->qsnIn = d->qsnOut = NULL;      ::close(sockfd);      sockfd = -1;    }  m_status = lookupDone;}bool KExtendedSocket::open(int mode){  if (mode != IO_Raw | IO_ReadWrite)    return false;		// invalid open mode  if (m_flags & passiveSocket)    return listen() == 0;  else if (m_status < connecting)    return connect() == 0;  else    return false;}void KExtendedSocket::close(){  if (sockfd == -1)    return;			// nothing to close  // LOCK BUFFER MUTEX  if (m_flags & outputBufferedSocket && writeBufferSize() > 0)    {      // write buffer not empty, go into closing state      m_status = closing;      if (d->qsnIn)	delete d->qsnIn;      d->qsnIn = NULL;      // we keep the outgoing socket notifier because we want      // to send data, but not receive    }  else    {      // nope, write buffer is empty      // we can close now      if (d->qsnIn)	delete d->qsnIn;      if (d->qsnOut)	delete d->qsnOut;      d->qsnIn = d->qsnOut = NULL;      ::close(sockfd);      m_status = done;      emit closed(readBufferSize() != 0 ? availRead : 0);    }  // UNLOCK BUFFER MUTEX}void KExtendedSocket::closeNow(){  m_status = done;  if (sockfd == -1)    return;			// nothing to close  // close the socket  if (d->qsnIn)    delete d->qsnIn;  if (d->qsnOut)    delete d->qsnOut;  d->qsnIn = d->qsnOut = NULL;  if (sockfd != -1)    ::close(sockfd);  emit closed(closedNow | 	      (readBufferSize() != 0 ? availRead : 0) |	      (writeBufferSize() != 0 ? dirtyWrite : 0));}void KExtendedSocket::release(){  // release our hold on the socket  sockfd = -1;  m_status = done;  // also do some garbage collecting  local_freeaddrinfo(d->resolution);  local_freeaddrinfo(d->bindres);  d->host = d->service = d->localhost = d->localservice = (const char *)0;  if (d->local != NULL)    delete d->local;  if (d->peer != NULL)    delete d->peer;  d->peer = d->local = NULL;  if (d->qsnIn != NULL)    delete d->qsnIn;  if (d->qsnOut != NULL)    delete d->qsnOut;  d->qsnIn = d->qsnOut = NULL;  // now that the socket notificators are done with, we can flush out the buffers  consumeReadBuffer(readBufferSize(), NULL, true);  consumeWriteBuffer(writeBufferSize());  // don't delete d  // leave that for the destructor}void KExtendedSocket::flush(){  cleanError();  if (m_status < connected || m_status >= done || m_flags & passiveSocket)    return;  if (sockfd == -1)    return;  if ((m_flags & outputBufferedSocket) == 0)    return;			// nothing to do  // LOCK MUTEX  unsigned written = 0;  unsigned offset = outBufIndex; // this happens only for the first  while (writeBufferSize() - written > 0)    {      // we have to write each output buffer in outBuf      // but since we can have several very small buffers, we can make things      // better by concatenating a few of them into a big buffer      // question is: how big should that buffer be? 16 kB should be enough      QByteArray buf(16384);      QByteArray *a = outBuf.first();      unsigned count = 0;      while (a && count + (a->size() - offset) < buf.size())	{	  memcpy(buf.data() + count, a->data() + offset, a->size() - offset);	  offset = 0;	  count += a->size() - offset;	  a = outBuf.next();	}      // now try to write those bytes      int wrote = KSocks::self()->write(sockfd, buf, count);      if (wrote == -1)	{	  // could be EAGAIN (EWOULDBLOCK)	  setError(IO_WriteError, errno);	  break;	}      written += wrote;      if ((unsigned)wrote != count)	break;    }  if (written)    {      consumeWriteBuffer(written);      emit bytesWritten(written);    }  // UNLOCK MUTEX}int KExtendedSocket::readBlock(char *data, uint maxlen){  cleanError();  if (m_status < connected || m_flags & passiveSocket)    return -2;  if (sockfd == -1)    return -2;  int retval;  if ((m_flags & inputBufferedSocket) == 0)    {      // we aren't buffering this socket, so just pass along      // the call to the real read method      if (data)	retval = KSocks::self()->read(sockfd, data, maxlen);      else	retval = skipData(sockfd, maxlen);      if (retval == -1)	setError(IO_ReadError, errno);    }  else    {      // this socket is being buffered. So read from the buffer      // LOCK BUFFER MUTEX      retval = consumeReadBuffer(maxlen, data);      if (retval == 0)	{	  // consumeReadBuffer returns 0 only if the buffer is	  // empty	  setError(IO_ReadError, EWOULDBLOCK);	  retval = -1;	}      // UNLOCK BUFFER MUTEX    }  return retval;}int KExtendedSocket::writeBlock(const char *data, uint len){  cleanError();  if (m_status < connected || m_status >= closing || m_flags & passiveSocket)    return -2;  if (sockfd == -1)    return -2;  if (len == 0)    return 0;			// what's to write?  int retval;  if ((m_flags & outputBufferedSocket) == 0)    {      // socket not buffered. Just call write      retval = KSocks::self()->write(sockfd, data, len);      if (retval == -1)	setError(IO_WriteError, errno);    }  else    {      // socket is buffered. Feed the write buffer      // LOCK BUFFER MUTEX      register unsigned wsize = writeBufferSize();      if (d->outMaxSize == (int)wsize) // (int) to get rid of annoying warning	{	  // buffer is full!	  setError(IO_WriteError, EWOULDBLOCK);	  retval = -1;	}      else	{	  if (d->outMaxSize != -1 && wsize + len > (unsigned)d->outMaxSize)	    // we cannot write all data. Write just as much as to fill the buffer	    len = d->outMaxSize - wsize;	  // len > 0 here	  retval = feedWriteBuffer(len, data);	  if (wsize == 0 || d->emitWrite)	    // buffer was empty, which means that the notifier is probably disabled	    d->qsnOut->setEnabled(true);	}      // UNLOCK BUFFER MUTEX    }  return retval;}int KExtendedSocket::peekBlock(char *data, uint maxlen){  if (m_status < connected || m_flags & passiveSocket)    return -2;  if (sockfd == -1)    return -2;  // need to LOCK MUTEX around this call...  if (m_flags & inputBufferedSocket)    return consumeReadBuffer(maxlen, data, false);  return 0;}int KExtendedSocket::unreadBlock(const char *, uint){  // Always return -1, indicating this is not supported  setError(IO_ReadError, ENOSYS);  return -1;}int KExtendedSocket::waitForMore(int msecs){  cleanError();  if (m_flags & passiveSocket || m_status < connected || m_status >= closing)    return -2;  if (sockfd == -1)    return -2;  fd_set rd;  FD_ZERO(&rd);  FD_SET(sockfd, &rd);  timeval tv;  tv.tv_sec = msecs / 1000;  tv.tv_usec = (msecs % 1000) * 1000;  int retval = KSocks::self()->select(sockfd + 1, &rd, NULL, NULL, &tv);  if (retval == -1)    {      setError(IO_FatalError, errno);      return -1;    }  else if (retval == 0)    socketActivityRead();	// do read processing  return bytesAvailable();}int KExtendedSocket::getch(){  char c;  int retval;  retval = readBlock(&c, sizeof(c));  if (retval < 0)    return retval;  return c;}int KExtendedSocket::putch(int ch){  char c = (char)ch;  return writeBlock(&c, sizeof(ch));}void KExtendedSocket::setError(int errorcode, int syserror){  setStatus(errorcode);  m_syserror = syserror;}int KExtendedSocket::doLookup(const QString &host, const QString &serv, addrinfo &hint,			      kde_addrinfo** res){  int err;  // FIXME! What is the encoding?  const char *_host = NULL,    *_serv = NULL;  if (!host.isNull())    _host = host.latin1();  if (!serv.isNull())    _serv = serv.latin1();  // Please read the comments before kde_getaddrinfo in netsupp.cpp  // for the reason we're using it  err = kde_getaddrinfo(_host, _serv, &hint, res);

⌨️ 快捷键说明

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