示例#1
0
void BufferedSocket::threadSendFile(InputStream* file) throw(Exception) {
	dcassert(sock);
	if(!sock)
		return;
	dcassert(file != NULL);
	size_t sockSize = (size_t)sock->getSocketOptInt(SO_SNDBUF);
	size_t bufSize = max(sockSize, (size_t)64*1024);

	vector<uint8_t> readBuf(bufSize);
	vector<uint8_t> writeBuf(bufSize);

	size_t readPos = 0;

	bool readDone = false;
	dcdebug("Starting threadSend\n");
	UploadManager *um = UploadManager::getInstance();
	size_t sendMaximum;
	uint64_t start = 0;
	bool throttling;
	while(true) {
		if(disconnecting)
			return;
                throttling = (BOOLSETTING(THROTTLE_ENABLE) && getSuperUser() == false);
                int UserSleep = getSleep(); // !SMT!-S
		if(!readDone && readBuf.size() > readPos) {
			// Fill read buffer
			size_t bytesRead = readBuf.size() - readPos;

                        // !SMT!-S
                        if (UserSleep >= 0) { // throttleGetSlice() should not be called for superusers, so their downloaded bytes don't count in mUploadLimit
			if(throttling) {
				start = GET_TICK();
				sendMaximum = um->throttleGetSlice();
				if (sendMaximum == (size_t)-1) {
					throttling = false;
					sendMaximum = bytesRead;
				}
				bytesRead = min(bytesRead, sendMaximum);
			}
                           if (UserSleep) { ::Sleep(UserSleep); bytesRead = min(bytesRead, (size_t)1024); } // !SMT!-S
                        }

			size_t actual = file->read(&readBuf[readPos], bytesRead);

			if(bytesRead > 0) {
				fire(BufferedSocketListener::BytesSent(), bytesRead, 0);
			}

			if(actual == 0) {
				readDone = true;
			} else {
				readPos += actual;
			}
		}

		if(readDone && readPos == 0) {
			fire(BufferedSocketListener::TransmitDone());
			return;
		}

		readBuf.swap(writeBuf);
		readBuf.resize(bufSize);
		writeBuf.resize(readPos);
		readPos = 0;

		size_t writePos = 0;

		while(writePos < writeBuf.size()) {
			if(disconnecting)
				return;
			size_t writeSize = min(sockSize / 2, writeBuf.size() - writePos);
			int written = sock->write(&writeBuf[writePos], writeSize);
			if(written > 0) {
				writePos += written;

				fire(BufferedSocketListener::BytesSent(), 0, written);
			} else if(written == -1) {
                                if(!readDone && readPos < readBuf.size() && UserSleep <= 0) { // !SMT!-S
					// Read a little since we're blocking anyway...
					size_t bytesRead = min(readBuf.size() - readPos, readBuf.size() / 2);
					if(throttling) {
						start = GET_TICK();
						sendMaximum = um->throttleGetSlice();
						if (sendMaximum == (size_t)-1)  
						{
							throttling = false;
							sendMaximum = bytesRead;
						}
						bytesRead = (uint32_t)min((int64_t)bytesRead, (int64_t)sendMaximum);
					}
					size_t actual = file->read(&readBuf[readPos], bytesRead);

					if(bytesRead > 0) {
						fire(BufferedSocketListener::BytesSent(), bytesRead, 0);
					}

					if(actual == 0) {
						readDone = true;
					} else {
						readPos += actual;
					}
				} else {
					while(!disconnecting) {
						int w = sock->wait(POLL_TIMEOUT, Socket::WAIT_WRITE | Socket::WAIT_READ);
						if(w & Socket::WAIT_READ) {
							threadRead();
						}
						if(w & Socket::WAIT_WRITE) {
							break;
						}
					}
				}	
			}
			if(throttling) {
				uint32_t cycle_time = um->throttleCycleTime();
				uint64_t sleep_time = cycle_time - (GET_TICK() - start);
				if (sleep_time > 0 && sleep_time <= cycle_time) {
					Thread::sleep(sleep_time);
				}
			}
		}
		Thread::yield();
	}
}
void BufferedSocket::threadSendFile(InputStream* file) throw(Exception) {
	if(state != RUNNING)
		return;
	
	if(disconnecting)
		return;
	dcassert(file != NULL);
	size_t sockSize = (size_t)sock->getSocketOptInt(SO_SNDBUF);
	size_t bufSize = max(sockSize, (size_t)64*1024);

	ByteVector readBuf(bufSize);
	ByteVector writeBuf(bufSize);

	size_t readPos = 0;

	bool readDone = false;
	dcdebug("Starting threadSend\n");
	UploadManager *um = UploadManager::getInstance();
	size_t sendMaximum, start = 0, current= 0;
	bool throttling;
	while(true) {
		if(!readDone && readBuf.size() > readPos) {
			// Fill read buffer
			size_t bytesRead = readBuf.size() - readPos;
			size_t actual = file->read(&readBuf[readPos], bytesRead);

			if(bytesRead > 0) {
				fire(BufferedSocketListener::BytesSent(), bytesRead, 0);
			}

			if(actual == 0) {
				readDone = true;
			} else {
				readPos += actual;
			}
		}

		if(readDone && readPos == 0) {
			fire(BufferedSocketListener::TransmitDone());
			return;
		}

		readBuf.swap(writeBuf);
		readBuf.resize(bufSize);
		writeBuf.resize(readPos);
		readPos = 0;

		size_t writePos = 0;

		while(writePos < writeBuf.size()) {
			if(disconnecting)
				return;
				
			throttling = BOOLSETTING(THROTTLE_ENABLE);
			size_t writeSize;
    		if(throttling) {
    			start = TimerManager::getTick();
    			sendMaximum = um->throttleGetSlice();
    			if(sendMaximum < 0) {
    				throttling = false;
					writeSize = min(sockSize / 2, writeBuf.size() - writePos);
				} else {
					writeSize = min(min(sockSize / 2, writeBuf.size() - writePos), sendMaximum);
				}
			} else {
				writeSize = min(sockSize / 2, writeBuf.size() - writePos);
			}
			
			int written = sock->write(&writeBuf[writePos], writeSize);
			if(written > 0) {
				writePos += written;

				fire(BufferedSocketListener::BytesSent(), 0, written);

				if(throttling) {
					int32_t cycle_time = um->throttleCycleTime();
					current = TimerManager::getTick();
					int32_t sleep_time = cycle_time - (current - start);
					if (sleep_time > 0 && sleep_time <= cycle_time) {
						Thread::sleep(sleep_time);
					}
				}
			} else if(written == -1) {
				if(!readDone && readPos < readBuf.size()) {
					// Read a little since we're blocking anyway...
					size_t bytesRead = min(readBuf.size() - readPos, readBuf.size() / 2);
					size_t actual = file->read(&readBuf[readPos], bytesRead);

					if(bytesRead > 0) {
						fire(BufferedSocketListener::BytesSent(), bytesRead, 0);
					}

					if(actual == 0) {
						readDone = true;
					} else {
						readPos += actual;
					}
				} else {
					while(!disconnecting) {
						int w = sock->wait(POLL_TIMEOUT, Socket::WAIT_WRITE | Socket::WAIT_READ);
						if(w & Socket::WAIT_READ) {
							threadRead();
						}
						if(w & Socket::WAIT_WRITE) {
							break;
						}
					}
				}
			}
		}
	}
}