/* * Throttles traffic and writes a packet to the network * Handle this a little bit differently than downloads due to OpenSSL stupidity */ int ThrottleManager::write(Socket* sock, void* buffer, size_t& len) { bool gotToken = false; size_t ups = UploadManager::getInstance()->getUploadCount(); int64_t upLimit = getUpLimit(); // avoid even intra-function races if(!getCurThrottling() || upLimit == 0 || ups == 0) return sock->write(buffer, len); { Lock l(upCS); if(upTokens > 0) { size_t slice = (upLimit * 1024) / ups; len = min(slice, min(len, static_cast<size_t>(upTokens))); upTokens -= len; gotToken = true; // token successfuly assigned } } if(gotToken) { // write to socket int sent = sock->write(buffer, len); Thread::yield(); // give a chance to other transfers get a token return sent; } waitToken(); return 0; // from BufferedSocket: -1 = failed, 0 = retry }
/* * Throttles traffic and reads a packet from the network */ int ThrottleManager::read(Socket* sock, void* buffer, size_t len) { int64_t readSize = -1; size_t downs = DownloadManager::getInstance()->getDownloadCount(); int64_t downLimit = getDownLimit(); // avoid even intra-function races if(!getCurThrottling() || downLimit == 0 || downs == 0) return sock->read(buffer, len); { Lock l(downCS); if(downTokens > 0) { int64_t slice = (downLimit * 1024) / downs; readSize = min(slice, min(static_cast<int64_t>(len), downTokens)); // read from socket readSize = sock->read(buffer, static_cast<size_t>(readSize)); if(readSize > 0) downTokens -= readSize; } } if(readSize != -1) { Thread::yield(); // give a chance to other transfers to get a token return readSize; } waitToken(); return -1; // from BufferedSocket: -1 = retry, 0 = connection close }
static void sendIdle(COUNT count) { waitToken(0xFF,0x00,count - 1); }