QStringList QuasarSocket::recv(int timeout) { int timeoutCnt = 0; while (true) { char buffer[8192]; int count = readBlock(buffer, 8191); if (count == -1) { QStringList results; results.push_back("error:"); results.push_back("Error reading from server"); return results; } if (count == 0) { waitForMore(1000); if (++timeoutCnt < timeout || timeout == 0) continue; QStringList results; results.push_back("error:"); results.push_back("Timeout reading from server"); return results; } buffer[count] = 0; _readLine += QString::fromUtf8(buffer); timeoutCnt = 0; QString data; if (_readLine.left(1) == "\002") { int index = _readLine.find('\003'); if (index == -1) continue; data = _readLine.mid(1, index - 1); _readLine = _readLine.mid(index + 1); } else { int index = _readLine.find('\n'); if (index == -1) continue; data = _readLine.left(index); _readLine = _readLine.mid(index + 1); while (data.right(1) == "\r") data = data.left(data.length() - 1); } return TclObject(data).toStringList(); } return QStringList(); }
Q_ULONG Q3Socket::waitForMore( int msecs ) const { return waitForMore( msecs, 0 ); }
/*! Writes \a len bytes to the socket from \a data and returns the number of bytes written. Returns -1 if an error occurred. This is used for MSocketDevice::Stream sockets. */ qint64 MSocketDevice::writeData( const char *data, qint64 len ) { if ( len == 0 ) return 0; if ( data == 0 ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::writeBlock: Null pointer error"); return -1; } if ( !isValid() ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::writeBlock: Invalid socket"); return -1; } if ( !isOpen() ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::writeBlock: Device is not open"); return -1; } if ( !isWritable() ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::writeBlock: Write operation not permitted"); return -1; } bool done = false; int r = 0; bool timeout; while ( !done ) { r = ::write( fd, data, len ); done = true; if ( r < 0 && e == NoError && errno != EAGAIN && errno != EWOULDBLOCK ) { switch( errno ) { case EINTR: // signal - call read() or whatever again done = false; break; case EPIPE: case ECONNRESET: // connection closed close(); r = 0; break; case ENOSPC: case EIO: case EISDIR: case EBADF: case EINVAL: case EFAULT: case ENOTCONN: case ENOTSOCK: e = Impossible; break; #if defined(ENONET) case ENONET: #endif case EHOSTUNREACH: case ENETDOWN: case ENETUNREACH: case ETIMEDOUT: e = NetworkFailure; break; default: e = UnknownError; break; } } else if ( waitForMore( 0, &timeout ) == 0 ) { if ( !timeout ) { // connection closed close(); } } } return r; }
bool MythSocket::readStringList(QStringList &list, uint timeoutMS) { list.clear(); if (state() != Connected) { VERBOSE(VB_IMPORTANT, LOC + "readStringList: Error, called with unconnected socket."); return false; } MythTimer timer; timer.start(); int elapsed = 0; while (waitForMore(5) < 8) { elapsed = timer.elapsed(); if (elapsed >= (int)timeoutMS) { VERBOSE(VB_IMPORTANT, LOC + "readStringList: " + QString("Error, timed out after %1 ms.").arg(timeoutMS)); close(); return false; } if (state() != Connected) { VERBOSE(VB_IMPORTANT, LOC + "readStringList: Connection died."); return false; } { struct timeval tv; int maxfd; fd_set rfds; FD_ZERO(&rfds); FD_SET(socket(), &rfds); maxfd = socket(); tv.tv_sec = 0; tv.tv_usec = 0; int rval = select(maxfd + 1, &rfds, NULL, NULL, &tv); if (rval) { if (bytesAvailable() == 0) { VERBOSE(VB_IMPORTANT, LOC + "readStringList: Connection died (select)."); return false; } } } } QByteArray sizestr(8 + 1, '\0'); if (readBlock(sizestr.data(), 8) < 0) { VERBOSE(VB_GENERAL, LOC + QString("readStringList: Error, readBlock return error (%1)") .arg(errorToString())); close(); return false; } QString sizes = sizestr; qint64 btr = sizes.trimmed().toInt(); if (btr < 1) { int pending = bytesAvailable(); QByteArray dump(pending + 1, 0); readBlock(dump.data(), pending); VERBOSE(VB_IMPORTANT, LOC + QString("Protocol error: '%1' is not a valid size " "prefix. %2 bytes pending.") .arg(sizestr.data()).arg(pending)); return false; } QByteArray utf8(btr + 1, 0); qint64 read = 0; int errmsgtime = 0; timer.start(); while (btr > 0) { qint64 sret = readBlock(utf8.data() + read, btr); if (sret > 0) { read += sret; btr -= sret; if (btr > 0) { timer.start(); } } else if (sret < 0 && error() != MSocketDevice::NoError) { VERBOSE(VB_GENERAL, LOC + QString("readStringList: Error, readBlock %1") .arg(errorToString())); close(); return false; } else if (!isValid()) { VERBOSE(VB_IMPORTANT, LOC + "readStringList: Error, socket went unconnected"); close(); return false; } else { elapsed = timer.elapsed(); if (elapsed > 10000) { if ((elapsed - errmsgtime) > 10000) { errmsgtime = elapsed; VERBOSE(VB_GENERAL, LOC + QString("readStringList: Waiting for data: %1 %2") .arg(read).arg(btr)); } } if (elapsed > 100000) { VERBOSE(VB_GENERAL, LOC + "Error, readStringList timeout (readBlock)"); return false; } usleep(500); } } QString str = QString::fromUtf8(utf8.data()); QByteArray payload; payload = payload.setNum(str.length()); payload += " "; payload.truncate(8); payload += str; if (VERBOSE_LEVEL_CHECK(VB_NETWORK)) { QString msg = QString("read <- %1 %2").arg(socket(), 2) .arg(payload.data()); if (!VERBOSE_LEVEL_CHECK(VB_EXTRA) && msg.length() > 88) { msg.truncate(85); msg += "..."; } VERBOSE(VB_NETWORK, LOC + msg); } list = str.split("[]:[]"); m_notifyread = false; s_readyread_thread->WakeReadyReadThread(); return true; }