/** Process timeout handling */ public void timeout() { // allocation free looping for (IPv4ControlBlock aList : list) { final TCPControlBlock cb = (TCPControlBlock) aList; cb.timeout(); } }
/** * 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; } }
/** @see org.jnode.net.TransportLayer#receive(org.jnode.net.SocketBuffer) */ public void receive(SocketBuffer skbuf) throws SocketException { // Increment stats stat.ipackets.inc(); // Get the IP header final IPv4Header ipHdr = (IPv4Header) skbuf.getNetworkLayerHeader(); // Read the TCP header final TCPHeader hdr = new TCPHeader(skbuf); // Set the TCP header in the buffer-field skbuf.setTransportLayerHeader(hdr); // Remove the TCP header from the head of the buffer skbuf.pull(hdr.getLength()); // Trim the buffer up to the length in the TCP header skbuf.trim(hdr.getDataLength()); if (!hdr.isChecksumOk()) { if (DEBUG) { if (log.isDebugEnabled()) { log.debug("Receive: badsum: " + hdr); } } stat.badsum.inc(); } else { if (DEBUG) { if (log.isDebugEnabled()) { log.debug("Receive: " + hdr); } } // Find the corresponding control block final TCPControlBlock cb = (TCPControlBlock) controlBlocks.lookup( ipHdr.getSource(), hdr.getSrcPort(), ipHdr.getDestination(), hdr.getDstPort(), true); if (cb == null) { final boolean ack = hdr.isFlagAcknowledgeSet(); final boolean rst = hdr.isFlagResetSet(); stat.noport.inc(); // Port unreachable if (ack && rst) { // the source is also unreachable log.debug( "Dropping segment due to: connection refused as the source is also unreachable"); } else { processPortUnreachable(ipHdr, hdr); } } else { // Let the cb handle the receive cb.receive(hdr, skbuf); } } }