/** 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; }
/** * tries to send an unreliable message to a connection, and handles the transmition / * retransmition of the reliable messages. * * <p>A 0 length will still generate a packet and deal with the reliable messages. */ public static void Transmit(NetworkChannel chan, int length, byte data[]) { int send_reliable; int w1, w2; // check for message overflow if (chan.message.overflowed) { chan.fatal_error = true; Com.Printf(NET.AdrToString(chan.remote_address) + ":Outgoing message overflow\n"); return; } send_reliable = chan.Netchan_NeedReliable() ? 1 : 0; if (chan.reliable_length == 0 && chan.message.cursize != 0) { System.arraycopy(chan.message_buf, 0, chan.reliable_buf, 0, chan.message.cursize); chan.reliable_length = chan.message.cursize; chan.message.cursize = 0; chan.reliable_sequence ^= 1; } // write the packet header Buffer send = Buffer.wrap(send_buf).order(ByteOrder.LITTLE_ENDIAN); w1 = (chan.outgoing_sequence & ~(1 << 31)) | (send_reliable << 31); w2 = (chan.incoming_sequence & ~(1 << 31)) | (chan.incoming_reliable_sequence << 31); chan.outgoing_sequence++; chan.last_sent = (int) Globals.curtime; send.putInt(w1); send.putInt(w2); // send the qport if we are a client if (chan.sock == Constants.NS_CLIENT) send.WriteShort((int) consoleQport.value); // copy the reliable message to the packet first if (send_reliable != 0) { Buffers.Write(send, chan.reliable_buf, chan.reliable_length); chan.last_reliable_sequence = chan.outgoing_sequence; } // add the unreliable part if space is available if (send.maxsize - send.cursize >= length) Buffers.Write(send, data, length); else Com.Printf("Netchan_Transmit: dumped unreliable\n"); // send the datagram NET.SendPacket(chan.sock, send.cursize, send.data, chan.remote_address); if (showpackets.value != 0) { if (send_reliable != 0) Com.Printf( // "send %4i : s=%i reliable=%i ack=%i rack=%i\n" "send " + send.cursize + " : s=" + (chan.outgoing_sequence - 1) + " reliable=" + chan.reliable_sequence + " ack=" + chan.incoming_sequence + " rack=" + chan.incoming_reliable_sequence + "\n"); else Com.Printf( // "send %4i : s=%i ack=%i rack=%i\n" "send " + send.cursize + " : s=" + (chan.outgoing_sequence - 1) + " ack=" + chan.incoming_sequence + " rack=" + chan.incoming_reliable_sequence + "\n"); } }
/** * 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; }