📄 udpconnectionset.java
字号:
byte[] packet_bytes = new byte[ header_size + payload_to_send ];
ByteBuffer packet_buffer = ByteBuffer.wrap( packet_bytes );
packet_buffer.put( header, 0, header_size );
int rem = payload_to_send;
for (int i=offset;i<offset+length;i++){
ByteBuffer buffer = buffers[i];
int limit = buffer.limit();
try{
if ( buffer.remaining() > rem ){
buffer.limit( buffer.position() + rem );
}
rem -= buffer.remaining();
packet_buffer.put( buffer );
}finally{
buffer.limit( limit );
}
if ( rem == 0 ){
break;
}
}
packet_to_send = new UDPPacket( connection, sequence_numbers, UDPPacket.COMMAND_DATA, packet_bytes, unack_in_sequence_count );
transmit_unack_packets.add( packet_to_send );
}
if ( manager.trace() ){
trace( connection, "sendData: seq=" + packet_to_send.getSequence() + ",data="+ payload_to_send );
}
send( packet_to_send );
return( payload_to_send );
}
protected void
receiveDataCommand(
int sequence,
ByteBuffer buffer,
int header_length )
throws IOException
{
int connection_id = buffer.getInt();
UDPConnection connection = null;
boolean new_connection = false;
synchronized( connections ){
if ( failed ){
throw( new IOException( "Connection set has failed" ));
}
connection = (UDPConnection)connections.get( new Integer( connection_id ));
if ( connection == null ){
connection = (UDPConnection)connections.remove( new Integer( -1 ));
if ( connection != null ){
connection.setID( connection_id );
connections.put( new Integer( connection_id ), connection );
}
}
if ( connection == null ){
if ( connections.size() == 128 ){
throw( new IOException( "Connection limit reached" ));
}
connection = new UDPConnection( this, connection_id );
connections.put( new Integer( connection.getID()), connection );
new_connection = true;
}
}
buffer.position( header_length );
if ( new_connection ){
manager.accept( local_port, remote_address, connection );
}
if ( manager.trace() ){
trace( connection, "receiveData: seq=" + sequence + ",data="+ buffer.remaining());
}
connection.receive( buffer );
}
protected void
sendAckCommand(
boolean timer_expired )
throws IOException
{
UDPPacket packet_to_send = null;
synchronized( this ){
// if there's already an ACK packet outstanding then we just resend that one
Iterator it = transmit_unack_packets.iterator();
while( it.hasNext()){
UDPPacket packet = (UDPPacket)it.next();
if ( packet.getCommand() == UDPPacket.COMMAND_ACK ){
if ( total_tick_count - packet.getSendTickCount() >= getExplicitAckTicks() ){
if ( manager.trace() ){
trace( packet.getConnection(), "retransAck:" + packet.getString());
}
packet_to_send = packet;
break;
}else{
// sent too recently, bail out
return;
}
}
}
if ( packet_to_send == null ){
byte[] header_bytes = new byte[256 + (RECEIVE_OUT_OF_ORDER_PACKETS_MAX+1)*4];
ByteBuffer header = ByteBuffer.wrap( header_bytes );
long unack_in_sequence_count = current_receive_unack_in_sequence_count;
// if this is the only packet, contains nothing out-of-sequence and timer invoked then the connection has
// gone idle - don't auto-retransmit to allow things to quiesce
boolean no_retrans = transmit_unack_packets.size() == 0 && timer_expired && receive_out_of_order_packets.size() == 0;
int[] sequences = writeHeaderStart( header, UDPPacket.COMMAND_ACK, no_retrans?UDPPacket.FLAG_LAZY_ACK:UDPPacket.FLAG_NONE );
it = receive_out_of_order_packets.iterator();
String oos_str = "";
int count = 0;
while( it.hasNext() && count < MAX_CONTIGUOUS_RETRANS_FOR_ACK ){
Object[] entry = (Object[])it.next();
if ( entry[2] != null ){
int out_of_order_seq = ((Integer)entry[0]).intValue();
int out_of_rep_seq = ((Integer)entry[1]).intValue();
oos_str += (oos_str.length()==0?"":",") + out_of_order_seq + "/" + out_of_rep_seq;
header.putInt(out_of_order_seq);
count++;
}
}
header.putInt( -1 );
if ( count == 0 ){
sent_receive_out_of_order_count = current_receive_out_of_order_count;
}else{
sent_receive_out_of_order_count += count;
if ( sent_receive_out_of_order_count > current_receive_out_of_order_count ){
sent_receive_out_of_order_count = current_receive_out_of_order_count;
}
}
int size = writeHeaderEnd( header, true );
byte[] packet_bytes = new byte[size];
System.arraycopy( header_bytes, 0, packet_bytes, 0, size );
packet_to_send = new UDPPacket( lead_connection, sequences, UDPPacket.COMMAND_ACK, packet_bytes, unack_in_sequence_count );
if ( no_retrans){
packet_to_send.setAutoRetransmit( false );
startKeepAliveTimer();
}
transmit_unack_packets.add( packet_to_send );
if ( manager.trace() ){
trace( lead_connection, "sendAck: in_seq=" + receive_last_inorder_sequence + ",out_of_seq=" + oos_str );
}
}
}
/*
if ( timer_expired ){
System.out.println( getName() + ": ack timer");
}
*/
send( packet_to_send );
}
protected void
receiveAckCommand(
ByteBuffer buffer )
throws IOException
{
List resend_list = new ArrayList();
String oos_str = "";
synchronized( this ){
Iterator it = transmit_unack_packets.iterator();
while( resend_list.size() < MAX_CONTIGUOUS_RETRANS_FOR_ACK ){
int out_of_order_seq = buffer.getInt();
if ( out_of_order_seq == -1 ){
break;
}else{
if ( manager.trace() ){
oos_str += (oos_str.length()==0?"":",") + out_of_order_seq;
}
while( it.hasNext() && resend_list.size() < MAX_CONTIGUOUS_RETRANS_FOR_ACK ){
UDPPacket packet = (UDPPacket)it.next();
if ( packet.getSequence() == out_of_order_seq ){
// can't remove the packet here as its presence is required to allow an in-order
// ack to correctly remove prior packets
packet.setHasBeenReceived();
break;
}
if ( total_tick_count - packet.getSendTickCount() >= MIN_RETRANSMIT_TICKS ){
if ( !resend_list.contains( packet )){
resend_list.add( packet );
}
}
}
}
}
total_packets_resent_via_ack += resend_list.size();
}
if ( manager.trace() ){
trace( "receiveAck: in_seq=" + receive_their_last_inorder_sequence + ",out_of_seq=" + oos_str );
}
for (int i=0;i<resend_list.size();i++){
send((UDPPacket)resend_list.get(i));
}
}
protected void
sendStatsRequest()
throws IOException
{
UDPPacket packet_to_send = null;
synchronized( this ){
// if there's already an stats request packet outstanding then we just resend that one
Iterator it = transmit_unack_packets.iterator();
while( it.hasNext()){
UDPPacket packet = (UDPPacket)it.next();
if ( packet.getCommand() == UDPPacket.COMMAND_STAT_REQUEST ){
if ( total_tick_count - packet.getSendTickCount() >= MIN_RETRANSMIT_TICKS ){
if ( manager.trace() ){
trace( packet.getConnection(), "retransStatsRequest:" + packet.getString());
}
packet_to_send = packet;
break;
}else{
// sent too recently, bail out
return;
}
}
}
if ( packet_to_send == null ){
byte[] header_bytes = new byte[256];
ByteBuffer header = ByteBuffer.wrap( header_bytes );
long unack_in_sequence_count = current_receive_unack_in_sequence_count;
int[] sequences = writeHeaderStart( header, UDPPacket.COMMAND_STAT_REQUEST, UDPPacket.FLAG_NONE );
int size = writeHeaderEnd( header, true );
byte[] packet_bytes = new byte[size];
System.arraycopy( header_bytes, 0, packet_bytes, 0, size );
packet_to_send = new UDPPacket( lead_connection, sequences, UDPPacket.COMMAND_STAT_REQUEST, packet_bytes, unack_in_sequence_count );
transmit_unack_packets.add( packet_to_send );
if ( manager.trace() ){
trace( lead_connection, "sendStatsRequest" );
}
}
}
send( packet_to_send );
}
protected void
receiveStatsRequest(
ByteBuffer buffer )
throws IOException
{
UDPPacket packet_to_send = null;
if ( manager.trace() ){
trace( "ReceiveStatsRequest" );
}
synchronized( this ){
// if there's already an stats reply packet outstanding then we just resend that one
Iterator it = transmit_unack_packets.iterator();
while( it.hasNext()){
UDPPacket packet = (UDPPacket)it.next();
if ( packet.getCommand() == UDPPacket.COMMAND_STAT_REPLY ){
if ( total_tick_count - packet.getSendTickCount() >= MIN_RETRANSMIT_TICKS ){
if ( manager.trace() ){
trace( packet.getConnection(), "retransStatsReply:" + packet.getString());
}
packet_to_send = packet;
break;
}else{
// sent too recently, bail out
return;
}
}
}
if ( packet_to_send == null ){
byte[] header_bytes = new byte[256];
ByteBuffer header = ByteBuffer.wrap( header_bytes );
long unack_in_sequence_count = current_receive_unack_in_sequence_count;
boolean no_retrans = transmit_unack_packets.size() == 0 && receive_out_of_order_packets.size() == 0;
int[] sequences = writeHeaderStart( header, UDPPacket.COMMAND_STAT_REPLY, no_retrans?UDPPacket.FLAG_LAZY_ACK:UDPPacket.FLAG_NONE );
int size = writeHeaderEnd( header, true );
byte[] packet_bytes = new byte[size];
System.arraycopy( header_bytes, 0, packet_bytes, 0, size );
packet_to_send = new UDPPacket( lead_connection, sequences, UDPPacket.COMMAND_STAT_REPLY, packet_bytes, unack_in_sequence_count );
if ( no_retrans ){
packet_to_send.setAutoRetransmit( false );
}
transmit_unack_packets.add( packet_to_send );
if ( manager.trace() ){
trace( lead_connection, "sendStatsReply" );
}
}
}
send( packet_to_send );
}
protected void
receiveStatsReply(
ByteBuffer buffer )
throws IOException
{
if ( manager.trace() ){
trace( "receiveStatsReply" );
}
}
protected void
sendCloseCommand(
UDPConnection connection )
throws IOException
{
if ( crypto_done ){
UDPPacket packet_to_send;
synchronized( this ){
byte[] header_bytes = new byte[256];
ByteBuffer header = ByteBuffer.wrap( header_bytes );
long unack_in_sequence_count = current_receive_unack_in_sequence_count;
int[] sequences = writeHeaderStart( header, UDPPacket.COMMAND_CLOSE, UDPPacket.FLAG_NONE );
header.putInt( connection.getID());
int size = writeHeaderEnd( header, true );
byte[] packet_bytes = new byte[size];
System.arraycopy( header_bytes, 0, packet_bytes, 0, size );
if ( manager.trace() ){
trace( connection, "sendClose" );
}
packet_to_send = new UDPPacket( lead_connection, sequences, UDPPacket.COMMAND_CLOSE, packet_bytes, unack_in_sequence_count );
transmit_unack_packets.add( packet_to_send );
}
send( packet_to_send );
}else{
IOException failure = new IOException( "Connection failed during setup phase" );
failed( failure );
throw( failure );
}
}
protected void
receiveCloseCommand(
ByteBuffer buffer )
throws IOException
{
int connection_id = buffer.getInt();
UDPConnection connection = null;
synchronized( connections ){
if ( failed ){
throw( new IOException( "Connection set has failed" ));
}
connection = (UDPConnection)connections.get( new Integer( connection_id ));
}
if ( manager.trace() ){
trace( "receiveClose: con=" + (connection==null?"<null>":(""+connection.getID())));
}
if ( connection != null ){
connection.close( "Remote has closed the connection" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -