@Override
public int read(byte []buf, int offset, int length)
throws IOException
{
int sublen = _pendingData;
ReadStream is = _is;
if (sublen <= 0)
return -1;
if (length < sublen)
sublen = length;
_os.flush();
int readLen = is.read(buf, offset, sublen);
_pendingData -= readLen;
if (log.isLoggable(Level.FINEST))
log.finest(new String(buf, offset, readLen));
while (_pendingData == 0) {
_os.flush();
int code = is.read();
switch (code) {
case HMUX_DATA: {
int len = (is.read() << 8) + is.read();
if (log.isLoggable(Level.FINE))
log.fine(_request.dbgId() + "D-r:post-data " + len);
_pendingData = len;
if (len > 0)
return readLen;
break;
}
case HMUX_QUIT: {
if (log.isLoggable(Level.FINE))
log.fine(_request.dbgId() + "Q-r:quit");
return readLen;
}
case HMUX_EXIT: {
if (log.isLoggable(Level.FINE))
log.fine(_request.dbgId() + "X-r:exit");
_request.killKeepalive("hmux request exit");
return readLen;
}
case HMUX_YIELD: {
_request.flushResponseBuffer();
_os.write(HMUX_ACK);
_os.write(0);
_os.write(0);
_os.flush();
if (log.isLoggable(Level.FINE)) {
log.fine(_request.dbgId() + "Y-r:yield");
log.fine(_request.dbgId() + "A-w:ack");
}
break;
}
case HMUX_CHANNEL: {
int channel = (is.read() << 8) + is.read();
if (log.isLoggable(Level.FINE))
log.fine(_request.dbgId() + "channel-r " + channel);
break;
}
case ' ': case '\n':
break;
default:
if (code < 0) {
_request.killKeepalive("hmux request end-of-file");
return readLen;
}
else {
_request.killKeepalive("hmux unknown request: " + (char) code);
int len = (is.read() << 8) + is.read();
if (log.isLoggable(Level.FINE))
log.fine(_request.dbgId() + "unknown-r '" + (char) code + "' " + len);
is.skip(len);
}
}
}
return readLen;