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