i2p: bob: rework recv() to check for new line character as EOL indicator

This commit is contained in:
sehraf 2020-05-10 13:37:53 +02:00
parent 1da3d262d9
commit f4f08f0379
No known key found for this signature in database
GPG Key ID: DF09F6EAE356B2C6

View File

@ -44,8 +44,8 @@ static const std::string kConfigKeyOutLength = "OUT_LENGTH";
static const std::string kConfigKeyOutQuantity = "OUT_QUANTITY"; static const std::string kConfigKeyOutQuantity = "OUT_QUANTITY";
static const std::string kConfigKeyOutVariance = "OUT_VARIANCE"; static const std::string kConfigKeyOutVariance = "OUT_VARIANCE";
/// Sleep duration for receiving loop /// Sleep duration for receiving loop in error/no-data case
static const useconds_t sleepTimeRecv = 10; // times 1000 = 10ms static const useconds_t sleepTimeRecv = 250; // times 1000 = 250ms
/// Sleep duration for everything else /// Sleep duration for everything else
static const useconds_t sleepTimeWait = 50; // times 1000 = 50ms or 0.05s static const useconds_t sleepTimeWait = 50; // times 1000 = 50ms or 0.05s
static const int sleepFactorDefault = 10; // 0.5s static const int sleepFactorDefault = 10; // 0.5s
@ -1069,38 +1069,62 @@ void p3I2pBob::updateSettings_locked()
std::string p3I2pBob::recv() std::string p3I2pBob::recv()
{ {
// BOB works line based
// -> \n indicates and of the line
constexpr uint16_t bufferSize = 128;
char buffer[bufferSize];
std::string ans; std::string ans;
ssize_t length; uint16_t retry = 10;
const uint16_t bufferSize = 128;
std::vector<char> buffer(bufferSize);
do { do {
doSleep(sleepTimeRecv); memset(buffer, 0, bufferSize);
// there is only one thread that touches mSocket - no need for a lock // peek at data
length = ::recv(mSocket, buffer.data(), buffer.size(), 0); auto length = ::recv(mSocket, buffer, bufferSize, MSG_PEEK);
if (length < 0) if (length <= 0) {
if (length < 0) {
// error
perror(__PRETTY_FUNCTION__);
}
retry--;
doSleep(sleepTimeRecv);
continue; continue;
}
ans.append(buffer.begin(), buffer.end()); // at least one byte was read
// clean received string // search for new line
ans.erase(std::remove(ans.begin(), ans.end(), '\0'), ans.end()); auto bufferStr = std::string(buffer);
ans.erase(std::remove(ans.begin(), ans.end(), '\n'), ans.end()); size_t pos = bufferStr.find('\n');
#if 0 if (pos == std::string::npos) {
std::stringstream ss; // no new line found -> more to read
ss << "recv length: " << length << " (bufferSize: " << bufferSize << ") ans: " << ans.length();
Dbg4() << __PRETTY_FUNCTION__ << " " + ss.str() << std::endl;
#endif
// clear and resize buffer again // sanity check
buffer.clear(); if (length != bufferSize) {
buffer.resize(bufferSize); // expectation: a full buffer was peeked)
Dbg1() << __PRETTY_FUNCTION__ << " peeked less than bufferSize but also didn't found a new line character" << std::endl;
}
// this should never happen
assert(length <= bufferSize);
} else {
// new line found -> end of message
if (this->shouldStop()) // calculate how much there is to read, read the \n, too!
break; length = pos + 1;
} while(length == bufferSize || ans.size() < 4);
// end loop
retry = 0;
}
// now read for real
memset(buffer, 0, bufferSize);
length = ::recv(mSocket, buffer, length, 0);
bufferStr = std::string(buffer);
ans.append(bufferStr);
} while(retry > 0);
return ans; return ans;
} }