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 + -
显示快捷键?