/**
  * Send an TCP packet
  *
  * @param skbuf
  */
 protected void send(IPv4Header ipHdr, TCPHeader tcpHdr, SocketBuffer skbuf)
     throws SocketException {
   if (DEBUG) {
     if (log.isDebugEnabled()) {
       log.debug("send(ipHdr, " + tcpHdr + ')');
     }
   }
   skbuf.setTransportLayerHeader(tcpHdr);
   tcpHdr.prefixTo(skbuf);
   ipHdr.setDataLength(skbuf.getSize());
   ipService.transmit(ipHdr, skbuf);
   stat.opackets.inc();
 }
  /** @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);
      }
    }
  }