/** * The reading loop will continually read until an error occurs or the stream is gracefully ended * by the peer. * * <p>("resource" warning suppression applies to 'bis'. It's not valid because socket itself gets * closed) */ @SuppressWarnings("resource") private void readTextLoop(Socket socket) throws Exception { InputStream in = socket.getInputStream(); BufferedInputStream bis = new BufferedInputStream( new CountableInputStream(in, _counterRecvOps, _counterRecvRate), 1024); // create a buffer that'll be reused // start off small, will grow as needed BufferBuilder bb = new BufferBuilder(256); while (!_shutdown) { int c = bis.read(); if (c < 0) break; if (charMatches((char) c, _receiveDelimiters)) { String str = bb.getTrimmedString(); if (str != null) handleReceivedData(str); bb.reset(); } else { if (bb.getSize() >= MAX_SEGMENT_ALLOWED) { // drop the connection throw new IOException( "Too much data arrived (at least " + bb.getSize() / 1024 + " KB) before any delimeter was present; dropping connection."); } bb.append((byte) c); } } // (while) // the peer has gracefully closed down the connection or we're shutting down if (!_shutdown) { // send out last data String str = bb.getTrimmedString(); if (str != null) handleReceivedData(str); // then fire the disconnected callback Handler.tryHandle(_disconnectedCallback, _callbackErrorHandler); } }
/** * The reading loop will continually read until an error occurs or the stream is gracefully ended * by the peer. * * <p>(Suppress 'resource' ignored because 'in' stream is closed in calling function.) */ @SuppressWarnings("resource") private void readLengthDelimitedLoop(Socket socket, char startFlag, Character optStopFlag) throws Exception { InputStream in = socket.getInputStream(); BufferedInputStream bis = new BufferedInputStream( new CountableInputStream(in, _counterRecvOps, _counterRecvRate), 1024); // create a buffer that'll be reused // start off small, will grow as needed BufferBuilder bb = new BufferBuilder(256); // create an additional temporary buffer which can be used with 'length' delimited parsing byte[] buffer = new byte[1024]; // got 'start flag'? boolean synced = false; // how many bytes to read int bytesToRead = 0; while (!_shutdown) { int c = bis.read(); if (c < 0) break; // discard data until we sync up with the 'start' flag if (!synced) { if (c == startFlag) { synced = true; // (put back) bb.append(c); // read 'length' (value excludes 'start', 'stop' flags) int len1 = Stream.readUnsignedByte(bis); int len2 = Stream.readUnsignedByte(bis); int length = Stream.readUnsignedShort(len1, len2); if (length >= MAX_SEGMENT_ALLOWED) // drop the connection throw new IOException( "Packet length indicates it is too large to accept (" + Formatting.formatByteLength(length) + ")."); // (put back) bb.append(len1); bb.append(len2); // already read 2 ('length') length bytesToRead = length - 2; } else { // not synced, so keep discarding continue; } } while (!_shutdown) { // we're synced, so can read as much as we need to if (bytesToRead > 0) { int bytesRead = bis.read(buffer, 0, Math.min(bytesToRead, buffer.length)); if (bytesRead < 0) throw new EOFException(); bytesToRead -= bytesRead; // 'copy' the buffer bb.append(buffer, 0, bytesRead); } else { // we've read enough break; } } if (optStopFlag != null) { c = Stream.readUnsignedByte(bis); if (c != optStopFlag.charValue()) throw new IOException("Stop flag was not matched after reading the packet bytes."); // (put back) bb.append(c); // fire the handled event String str = bb.getRawString(); handleReceivedData(str); bb.reset(); synced = false; } } // (while) // the peer has gracefully closed down the connection or we're shutting down if (!_shutdown) { // drop left over data and fire the disconnected callback Handler.tryHandle(_disconnectedCallback, _callbackErrorHandler); } }