void BufferedSocket::threadRead() throw(SocketException) { dcassert(sock); if(!sock) return; DownloadManager *dm = DownloadManager::getInstance(); size_t readsize = inbuf.size(); bool throttling = false; if(mode == MODE_DATA) { uint32_t getMaximum; throttling = dm && dm->throttle() && getSuperUser() == false; if (throttling) { getMaximum = dm->throttleGetSlice(); readsize = (uint32_t)min((int64_t)inbuf.size(), (int64_t)getMaximum); if (readsize <= 0 || readsize > inbuf.size()) { // FIX Thread::sleep(dm->throttleCycleTime()); return; } } } int left = sock->read(&inbuf[0], (int)readsize); if(left == -1) { // EWOULDBLOCK, no data received... return; } else if(left == 0) { // This socket has been closed... throw EOFSocketException(); } int bufpos = 0; const int total = left; while (left > 0) { switch (mode) { case MODE_ZPIPE: if (filterIn != NULL){ const int BufSize = 1024; AutoArray<uint8_t> buffer (BufSize); string l = line; // decompress all input data and store in l. while (left) { size_t in = BufSize; size_t used = left; bool ret = (*filterIn) ((void *)(&inbuf[0] + total - left), used, &buffer[0], in); left -= used; l.append ((const char *)&buffer[0], in); // if the stream ends before the data runs out, keep remainder of data in inbuf if (!ret) { bufpos = total-left; setMode (MODE_LINE, rollback); break; } } // process all lines string::size_type pos; while ((pos = l.find(separator)) != string::npos) { if(pos > 0) // check empty (only pipe) command and don't waste cpu with it ;o) fire(BufferedSocketListener::Line(), l.substr(0, pos)); l.erase (0, pos + 1 /* seperator char */); } // store remainder line = l; break; } case MODE_LINE: // Special to autodetect nmdc connections... if(separator == 0) { if(inbuf[0] == '$') { separator = '|'; } else { separator = '\n'; } } { #if 0 string l = line + string((char*)&inbuf[bufpos], left); size_t linePos = 0; string::size_type pos; while ((pos = l.find(separator, linePos)) != string::npos) { if(pos > linePos) // check empty (only pipe) command and don't waste cpu with it ;o) fire(BufferedSocketListener::Line(), l.substr(linePos, pos - linePos)); left -= (pos - linePos + 1); if (mode != MODE_LINE) { // we changed mode; remainder of line is invalid. line.clear(); bufpos = total - left; break; } linePos = pos + 1; } if (pos == string::npos) { // no more separators; keep remainder of line left = 0; line = l.substr(linePos); } #else string l = line + string ((char*)&inbuf[bufpos], left); string::size_type pos; while ((pos = l.find(separator)) != string::npos) { if(pos > 0) // check empty (only pipe) command and don't waste cpu with it ;o) fire(BufferedSocketListener::Line(), l.substr(0, pos)); l.erase (0, pos + 1 /* separator char */); if (l.length() < (size_t)left) left = l.length(); if (mode != MODE_LINE) { // we changed mode; remainder of l is invalid. l.clear(); bufpos = total - left; break; } } if (pos == string::npos) left = 0; line = l; #endif } break; case MODE_DATA: while(left > 0) { if(dataBytes == -1) { fire(BufferedSocketListener::Data(), &inbuf[bufpos], left); bufpos += (left - rollback); left = rollback; rollback = 0; } else { int high = (int)min(dataBytes, (int64_t)left); fire(BufferedSocketListener::Data(), &inbuf[bufpos], high); bufpos += high; left -= high; dataBytes -= high; if(dataBytes == 0) { mode = MODE_LINE; fire(BufferedSocketListener::ModeChange()); } } if (throttling) { if (left > 0 && left < (int)readsize) { dm->throttleReturnBytes(left - readsize); } Thread::sleep(dm->throttleCycleTime()); } } break; } } if(mode == MODE_LINE && line.size() > 16777216) { throw SocketException(STRING(COMMAND_TOO_LONG)); } }
void BufferedSocket::threadRead() throw(SocketException) { if(state != RUNNING) return; DownloadManager *dm = DownloadManager::getInstance(); size_t readsize = inbuf.size(); bool throttling = false; if(mode == MODE_DATA) { uint32_t getMaximum; throttling = dm->throttle(); if (throttling) { getMaximum = dm->throttleGetSlice(); readsize = (uint32_t)min((int64_t)inbuf.size(), (int64_t)getMaximum); if (readsize <= 0 || readsize > inbuf.size()) { // FIX sleep(dm->throttleCycleTime()); return; } } } int left = sock->read(&inbuf[0], (int)readsize); if(left == -1) { // EWOULDBLOCK, no data received... return; } else if(left == 0) { // This socket has been closed... throw SocketException(_("Connection closed")); } string::size_type pos = 0; // always uncompressed data string l; int bufpos = 0, total = left; while (left > 0) { switch (mode) { case MODE_ZPIPE: { const int BUF_SIZE = 1024; // Special to autodetect nmdc connections... string::size_type pos = 0; boost::scoped_array<char> buffer(new char[BUF_SIZE]); l = line; // decompress all input data and store in l. while (left) { size_t in = BUF_SIZE; size_t used = left; bool ret = (*filterIn) (&inbuf[0] + total - left, used, &buffer[0], in); left -= used; l.append (&buffer[0], in); // if the stream ends before the data runs out, keep remainder of data in inbuf if (!ret) { bufpos = total-left; setMode (MODE_LINE, rollback); break; } } // process all lines while ((pos = l.find(separator)) != string::npos) { fire(BufferedSocketListener::Line(), l.substr(0, pos)); l.erase (0, pos + 1 /* separator char */); } // store remainder line = l; break; } case MODE_LINE: // Special to autodetect nmdc connections... if(separator == 0) { if(inbuf[0] == '$') { separator = '|'; } else { separator = '\n'; } } l = line + string ((char*)&inbuf[bufpos], left); while ((pos = l.find(separator)) != string::npos) { fire(BufferedSocketListener::Line(), l.substr(0, pos)); l.erase (0, pos + 1 /* separator char */); if (l.length() < (size_t)left) left = l.length(); if (mode != MODE_LINE) { // we changed mode; remainder of l is invalid. l.clear(); bufpos = total - left; break; } } if (pos == string::npos) left = 0; line = l; break; case MODE_DATA: while(left > 0) { if(dataBytes == -1) { fire(BufferedSocketListener::Data(), &inbuf[bufpos], left); bufpos += (left - rollback); left = rollback; rollback = 0; } else { int high = (int)min(dataBytes, (int64_t)left); fire(BufferedSocketListener::Data(), &inbuf[bufpos], high); bufpos += high; left -= high; dataBytes -= high; if(dataBytes == 0) { mode = MODE_LINE; fire(BufferedSocketListener::ModeChange()); } } if (throttling) { if (left > 0 && left < (int)readsize) { dm->throttleReturnBytes(left - readsize); } uint32_t sleep_interval = dm->throttleCycleTime(); Thread::sleep(sleep_interval); } } break; } } if(mode == MODE_LINE && line.size() > static_cast<size_t>(SETTING(MAX_COMMAND_LENGTH))) { throw SocketException(_("Maximum command length exceeded")); } }