/** called to open a channel to a remote system */
  public static void Setup(NetworkChannel chan, int sock, NetworkAddress adr, int qport) {
    // memset (chan, 0, sizeof(*chan));

    chan.clear();
    chan.sock = sock;
    chan.remote_address.set(adr);
    chan.qport = qport;
    chan.last_received = Globals.curtime;
    chan.incoming_sequence = 0;
    chan.outgoing_sequence = 1;

    chan.message = Buffer.wrap(chan.message_buf).order(ByteOrder.LITTLE_ENDIAN);
    chan.message.allowoverflow = true;
  }
  /**
   * called when the current net_message is from remote_address modifies net_message so that it
   * points to the packet payload =================
   */
  public static boolean Process(NetworkChannel chan, Buffer msg) {
    int sequence, sequence_ack;
    int reliable_ack, reliable_message;
    int qport;

    // get sequence numbers
    msg.reset();
    sequence = msg.getInt();
    sequence_ack = msg.getInt();

    // read the qport if we are a server
    if (chan.sock == Constants.NS_SERVER) qport = msg.getShort();

    // achtung unsigned int
    reliable_message = sequence >>> 31;
    reliable_ack = sequence_ack >>> 31;

    sequence &= ~(1 << 31);
    sequence_ack &= ~(1 << 31);

    if (showpackets.value != 0) {
      if (reliable_message != 0)
        Com.Printf(
            // "recv %4i : s=%i reliable=%i ack=%i rack=%i\n"
            "recv "
                + msg.cursize
                + " : s="
                + sequence
                + " reliable="
                + (chan.incoming_reliable_sequence ^ 1)
                + " ack="
                + sequence_ack
                + " rack="
                + reliable_ack
                + "\n");
      else
        Com.Printf(
            // "recv %4i : s=%i ack=%i rack=%i\n"
            "recv "
                + msg.cursize
                + " : s="
                + sequence
                + " ack="
                + sequence_ack
                + " rack="
                + reliable_ack
                + "\n");
    }

    //
    // discard stale or duplicated packets
    //
    if (sequence <= chan.incoming_sequence) {
      if (showdrop.value != 0)
        Com.Printf(
            NET.AdrToString(chan.remote_address)
                + ":Out of order packet "
                + sequence
                + " at "
                + chan.incoming_sequence
                + "\n");
      return false;
    }

    //
    // dropped packets don't keep the message from being used
    //
    chan.dropped = sequence - (chan.incoming_sequence + 1);
    if (chan.dropped > 0) {
      if (showdrop.value != 0)
        Com.Printf(
            NET.AdrToString(chan.remote_address)
                + ":Dropped "
                + chan.dropped
                + " packets at "
                + sequence
                + "\n");
    }

    //
    // if the current outgoing reliable message has been acknowledged
    // clear the buffer to make way for the next
    //
    if (reliable_ack == chan.reliable_sequence) chan.reliable_length = 0; // it has been received

    //
    // if this message contains a reliable message, bump
    // incoming_reliable_sequence
    //
    chan.incoming_sequence = sequence;
    chan.incoming_acknowledged = sequence_ack;
    chan.incoming_reliable_acknowledged = reliable_ack;
    if (reliable_message != 0) {
      chan.incoming_reliable_sequence ^= 1;
    }

    //
    // the message can now be read from the current message pointer
    //
    chan.last_received = (int) Globals.curtime;

    return true;
  }