Esempio n. 1
0
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"));
	}
}