/** * Read data from the input buffer up to len bytes long. Block until there is data available. * * @param dst * @param off * @param len * @return The number of bytes read */ public synchronized int read(byte[] dst, int off, int len) throws SocketException { while ((dataBuffer.getUsed() == 0) && !controlBlock.isReset() && !isEOF()) { try { wait(); } catch (InterruptedException ex) { // Ignore } } if (controlBlock.isReset()) { throw new SocketException("Connection reset"); } else if (isEOF()) { return -1; } else { return dataBuffer.read(dst, off, len); } }
/** * Process the given segment (that must be the next expected segment). The data will be send to * the input data buffer, if there is enough space left in the buffer. * * @param hdr * @param skbuf * @return True if the segment has been fully processed, false otherwise. * @throws SocketException */ private synchronized boolean processNextSegment(TCPHeader hdr, SocketBuffer skbuf) throws SocketException { final int seqNr = hdr.getSequenceNr(); if (seqNr != rcv_next) { throw new IllegalArgumentException("hdr.seqNr != rcv_next"); } // This segment is the first expected segment // Sent it to the application if there is enough space final int dataLength = hdr.getDataLength(); if (dataLength > dataBuffer.getFreeSize()) { // Not enough free space, ignore this segment, it will be retransmitted. log.debug("nextSegment dropped due to lack of space"); return false; } else { // Enough space, save if (dataLength > 0) { dataBuffer.add(skbuf, 0, dataLength); // Update rcv_next rcv_next += dataLength; } final boolean fin = hdr.isFlagFinishedSet(); final boolean syn = hdr.isFlagSynchronizeSet(); if (syn || fin) { // SYN & FIN take up 1 seq-nr rcv_next++; } if ((dataLength > 0) || fin) { // And ACK it controlBlock.sendACK(0, rcv_next); } // Notify threads blocked in read notifyAll(); // We've processed it fully return true; } }
/** * Has the End of the InputChannel been reached? * * @return True if EOF has been reached, false otherwise */ protected final boolean isEOF() { if (!finReceived) { // Other site has not closed return false; } if (dataBuffer.getUsed() > 0) { // Still data in databuffer return false; } if (!futureSegments.isEmpty()) { // Still future segments return false; } // TODO No other requirements here????? return true; }
public int getBufferSize() { return dataBuffer.getLength(); }
/** Return the number of available bytes in the input buffer. */ public int available() { return dataBuffer.getUsed(); }