}
+//
+// Discard any data still in the input buffer.
+// This is used to cope with unexpected garbage (protocol violations
+// from the server), and shouldn't be used indiscriminately.
+//
+void TransferEngine::Client::flushInput()
+{
+ if (!mReadBuffer.isEmpty()) {
+ debug("engineio", "flushing %ld bytes of input", mReadBuffer.length());
+ mReadBuffer.clear();
+ mInputFlushed = true; // inhibit normal buffer ops
+ }
+}
+
+
//
// Given that autoCopyOut mode is active, try to transfer some bytes
// into the write buffer. This is a lazy, fast push, suitable for tacking on
this, fd, io.iocget<int>(FIONREAD)));
do {
+ mInputFlushed = false; // preset normal
+
//@@@ break out after partial buffer to give Equal Time to other transfers? good idea?!
- if (mReadBuffer.read(*this) == 0) {
+ if (!atEnd() && mReadBuffer.read(*this) == 0 && !atEnd()) {
mReadBuffer.read(*this, true);
}
rawInputTransit();
break;
case lineInput:
- lineInputTransit();
+ if (!lineInputTransit())
+ return; // no full line; try again later
break;
case autoReadInput:
autoReadInputTransit();
assert(false);
}
if (!io) // client has unhooked; clear buffer and exit loop
- mReadBuffer.clear();
+ flushInput();
} while (!mReadBuffer.isEmpty());
//@@@ feed back for more output here? But also see comments above...
//@@@ probably better to take the trip through the Selector
IFDEBUG(debug("engineio", "%p(%d) --> %d bytes RAW",
this, fileDesc(), io.iocget<int>(FIONREAD)));
transit(inputAvailable, addr, length);
- mReadBuffer.usePut(length);
+ if (!mInputFlushed)
+ mReadBuffer.useGet(length);
}
-void TransferEngine::Client::lineInputTransit()
+bool TransferEngine::Client::lineInputTransit()
{
char *line; size_t length = mReadBuffer.length();
mReadBuffer.locateGet(line, length);
char *nl;
for (nl = line; nl < line + length && *nl != '\n'; nl++) ;
if (nl == line + length) // no end-of-line, wait for more
- return;
+ return false;
if (nl > line && nl[-1] == '\r') { // proper \r\n termination
nl[-1] = '\0'; // terminate for transit convenience
debug("engineio", "%p(%d) [IMPROPER] --> %s", this, fileDesc(), line);
transit(inputAvailable, line, nl - line);
}
- mReadBuffer.useGet(nl - line + 1);
+ if (!mInputFlushed)
+ mReadBuffer.useGet(nl - line + 1);
+ return true;
}
void TransferEngine::Client::autoReadInputTransit()
mReadBuffer.locateGet(data, length);
debug("engineio", "%p(%d) --> %ld bytes autoReadInput", this, fileDesc(), length);
mSink->consume(data, length);
- mReadBuffer.useGet(length);
+ if (!mInputFlushed)
+ mReadBuffer.useGet(length);
if (mResidualReadCount && (mResidualReadCount -= length) == 0)
mMode = autoIODone;
}