Example #1
0
  public final void handleReceive(DatagramPacket packet, AsyncDatagramSocket dgram_socket) {
    synchronized (this) {
      try {
        TcpSegment segment = new TcpSegment(packet);
        Object[] args = new Object[1];

        // Generate the appropriate transition based on
        // the header flags.
        args[0] = segment;

        // DEBUG
        //                 System.out.println(
        //                     "Receive event from " +
        //                     packet.getAddress() +
        //                     ":" +
        //                     Integer.toString(packet.getPort()) +
        //                     ":\n" +
        //                     segment);

        // REFLECTION
        // Uncomment the following line to output
        // transitions.
        // _outputTransitions();

        _transition_table[segment.getFlags()].invoke(_fsm, args);
      } catch (Exception jex) {
        System.err.println(jex);
        jex.printStackTrace();
      } finally {
        this.notify();
      }
    }

    return;
  }
Example #2
0
  private int getAck(TcpSegment segment) {
    int retval;

    // The ack # depends on the segment's flags.
    switch (segment.getFlags()) {
      case TcpSegment.FIN:
      case TcpSegment.SYN:
      case TcpSegment.FIN_ACK:
      case TcpSegment.SYN_ACK:
        retval = segment.getSequenceNumber() + 1;
        break;

      case TcpSegment.PSH:
      case TcpSegment.PSH_ACK:
        retval = segment.getSequenceNumber() + segment.getDataSize();
        break;

      case TcpSegment.ACK:
      default:
        retval = segment.getSequenceNumber();
        break;
    }

    return (retval);
  }
Example #3
0
 /* package */ void send(int flags, byte[] data, int offset, int size, TcpSegment recv_segment) {
   send(
       flags,
       data,
       offset,
       size,
       recv_segment.getSourceAddress(),
       recv_segment.getSourcePort(),
       recv_segment);
   return;
 }
Example #4
0
  /* package */ void setDestinationPort(TcpSegment segment) {
    byte[] data;

    // The server socket is telling us the accepted client's
    // port number. Reset the destination port to that.
    data = segment.getData();
    _port = ((((int) data[0]) & 0x000000ff) << 8) | (((int) data[1]) & 0x000000ff);

    // Modify the segment's source port so that the ack will
    // go to the correct destination.
    segment.setSourcePort(_port);

    return;
  }
Example #5
0
  /* package */ void receive(TcpSegment segment) {
    // Send the TCP segment's data to the socket listener.
    if (_listener != null) {
      _listener.receive(segment.getData(), this);
    }

    return;
  }
Example #6
0
  // Create a client socket to handle a new connection.
  /* package */ void accept(TcpSegment segment) {
    TcpClient accept_client;
    DatagramSocket dgram_socket;

    try {
      _address = segment.getSourceAddress();
      _port = segment.getSourcePort();

      // Create a new client socket to handle this side of
      // the socket pair.
      dgram_socket = new DatagramSocket();
      accept_client =
          new TcpClient(
              _address, _port, dgram_socket, _sequence_number, (TcpServer) this, _listener);

      ((TcpConnection) accept_client).acceptOpen(segment);
    } catch (Exception jex) {
      // If the open fails, send a reset to the peer.
      send(TcpSegment.RST, null, 0, 0, segment);
    }

    return;
  }
Example #7
0
  /* package */ void send(
      int flags,
      byte[] data,
      int offset,
      int size,
      InetAddress address,
      int port,
      TcpSegment recv_segment) {
    DatagramSocket socket;

    // Quietly quit if there is no socket.
    if (_async_socket != null && (socket = _async_socket.getDatagramSocket()) != null) {
      int local_port;
      int ack_number;
      TcpSegment send_segment;
      DatagramPacket packet = null;

      // If the address and port were not specified, then
      // send this segment to whatever client socket we are
      // currently speaking.
      if (address == null) {
        address = _address;
        port = _port;
      }

      // If there is a recv_segment, then use its
      // destination port as the local port. Otherwise, use
      // the local datagram socket's local port.
      if (recv_segment != null) {
        local_port = recv_segment.getDestinationPort();
      } else {
        local_port = _async_socket.getDatagramSocket().getLocalPort();
      }

      // Send the ack number only if the ack flag is set.
      if ((flags & TcpSegment.ACK) == 0) {
        ack_number = 0;
      } else {
        // Figure out the ack number based on the
        // received segment's sequence number and data
        // size.
        ack_number = getAck(recv_segment);
      }

      send_segment =
          new TcpSegment(
              local_port, address, port, _sequence_number, ack_number, flags, data, offset, size);

      // Advance the sequence number depending on the
      // message sent. Don't do this if message came from
      // an interloper.
      if (address.equals(_address) && port == _port) {
        _sequence_number = getAck(send_segment);
      }

      // Now send the data.
      try {
        packet = send_segment.packetize();

        // DEBUG
        //                 System.out.println(
        //                     "Sending packet to " +
        //                     packet.getAddress() +
        //                     ":" +
        //                     Integer.toString(packet.getPort()) +
        //                     ":\n" +
        //                     send_segment);

        _async_socket.getDatagramSocket().send(packet);
      } catch (IOException io_exception) {
        // Ignore - the ack timer will figure out this
        // packet was never sent.

        // DEBUG
        //                 System.out.println(
        //                     "Send to " +
        //                     packet.getAddress() +
        //                     ": " +
        //                     io_exception.getMessage());
      }
    }

    return;
  }