-
Notifications
You must be signed in to change notification settings - Fork 1
/
GUDPPacket.java
141 lines (118 loc) · 4.34 KB
/
GUDPPacket.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import java.net.DatagramPacket;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.io.IOException;
public class GUDPPacket {
public static final short GUDP_VERSION = 1;
public static final short HEADER_SIZE = 8;
public static final Integer MAX_DATA_LEN = 1000;
public static final Integer MAX_DATAGRAM_LEN = MAX_DATA_LEN + HEADER_SIZE;
public static final Integer MAX_WINDOW_SIZE = 3;
public static final short TYPE_DATA = 1;
public static final short TYPE_BSN = 2;
public static final short TYPE_ACK = 3;
private InetSocketAddress sockaddr;
private ByteBuffer byteBuffer;
private Integer payloadLength;
/*
* Application send processing: Build a DATA GUDP packet to encaspulate payload
* from the application. The application payload is in the form of a DatagramPacket,
* containing data and socket address.
*/
public static GUDPPacket encapsulate(DatagramPacket packet) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(packet.getLength() + HEADER_SIZE);
buffer.order(ByteOrder.BIG_ENDIAN);
GUDPPacket gudppacket = new GUDPPacket(buffer);
gudppacket.setType(TYPE_DATA);
gudppacket.setVersion(GUDP_VERSION);
byte[] data = packet.getData();
gudppacket.setPayload(data);
gudppacket.setSocketAddress((InetSocketAddress) packet.getSocketAddress());
return gudppacket;
}
/*
* Application receive processing: Extract application payload into a DatagramPacket,
* with data and socket address.
*/
public void decapsulate(DatagramPacket packet) throws IOException {
int plength = getPayloadLength();
getPayload(packet.getData(), plength);
packet.setLength(plength);
packet.setSocketAddress(getSocketAddress());
}
/*
* Input processing: Turn a DatagramPacket received from UDP into a GUDP packet
*/
public static GUDPPacket unpack(DatagramPacket packet) throws IOException {
int plength = packet.getLength();
if (plength < HEADER_SIZE)
throw new IOException(String.format("Too short GUDP packet: %d bytes", plength));
byte[] data = packet.getData();
ByteBuffer buffer = ByteBuffer.wrap(data, 0, plength);
buffer.order(ByteOrder.BIG_ENDIAN);
GUDPPacket gudppacket = new GUDPPacket(buffer);
gudppacket.setPayloadLength(plength - HEADER_SIZE);
gudppacket.setSocketAddress((InetSocketAddress) packet.getSocketAddress());
return gudppacket;
}
/*
* Output processing: Turn headers and payload into a DatagramPacket, for sending with UDP
*/
public DatagramPacket pack() throws IOException {
int totlength = HEADER_SIZE + getPayloadLength();
InetSocketAddress socketAddress = getSocketAddress();
return new DatagramPacket(getBytes(), totlength, sockaddr);
}
/*
* Constructor: create a GUDP packet with a ByteBuffer as back storage
*/
public GUDPPacket(ByteBuffer buffer) {
byteBuffer = buffer;
}
/*
* Serialization: Return packet as a byte array
*/
public byte[] getBytes() {
return byteBuffer.array();
}
public short getVersion() {
return byteBuffer.getShort(0);
}
public short getType() {
return byteBuffer.getShort(2);
}
public int getSeqno() {
return byteBuffer.getInt(4);
}
public InetSocketAddress getSocketAddress() {
return sockaddr;
}
public void setVersion(short version) {
byteBuffer.putShort(0, version);
}
public void setType(short type) {
byteBuffer.putShort(2, type);
}
public void setSeqno(int length) {
byteBuffer.putInt(4, length);
}
public void setPayload(byte[] pload) {
byteBuffer.position(HEADER_SIZE);
byteBuffer.put(pload, 0, pload.length);
payloadLength = pload.length;
}
public void setSocketAddress(InetSocketAddress socketAddress) {
sockaddr = socketAddress;
}
public void setPayloadLength(int length) {
payloadLength = length;
}
public int getPayloadLength() {
return payloadLength;
}
public void getPayload(byte[] dst, int length) {
byteBuffer.position(HEADER_SIZE);
byteBuffer.get(dst, 0, length);
}
}