blob: ec74f46af4f644f383906acc566e27c6f1145bae [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
Ray Milkey269ffb92014-04-03 14:43:30 -07002 * Copyright 2011, Big Switch Networks, Inc.
3 * Originally created by David Erickson, Stanford University
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 * not use this file except in compliance with the License. You may obtain
7 * a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations
15 * under the License.
16 **/
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080017
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070018package net.onrc.onos.core.packet;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080019
20import java.nio.ByteBuffer;
21
22/**
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080023 * @author shudong.zhou@bigswitch.com
24 */
25public class TCP extends BasePacket {
26 protected short sourcePort;
27 protected short destinationPort;
28 protected int sequence;
29 protected int acknowledge;
30 protected byte dataOffset;
31 protected short flags;
32 protected short windowSize;
33 protected short checksum;
34 protected short urgentPointer;
35 protected byte[] options;
36
37 /**
38 * @return the sourcePort
39 */
40 public short getSourcePort() {
41 return sourcePort;
42 }
43
44 /**
45 * @param sourcePort the sourcePort to set
46 */
47 public TCP setSourcePort(short sourcePort) {
48 this.sourcePort = sourcePort;
49 return this;
50 }
51
52 /**
53 * @return the destinationPort
54 */
55 public short getDestinationPort() {
56 return destinationPort;
57 }
58
59 /**
60 * @param destinationPort the destinationPort to set
61 */
62 public TCP setDestinationPort(short destinationPort) {
63 this.destinationPort = destinationPort;
64 return this;
65 }
66
67 /**
68 * @return the checksum
69 */
70 public short getChecksum() {
71 return checksum;
72 }
Ray Milkey269ffb92014-04-03 14:43:30 -070073
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080074 public int getSequence() {
75 return this.sequence;
76 }
Ray Milkey269ffb92014-04-03 14:43:30 -070077
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080078 public TCP setSequence(int seq) {
79 this.sequence = seq;
80 return this;
81 }
Ray Milkey269ffb92014-04-03 14:43:30 -070082
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080083 public int getAcknowledge() {
84 return this.acknowledge;
85 }
Ray Milkey269ffb92014-04-03 14:43:30 -070086
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080087 public TCP setAcknowledge(int ack) {
88 this.acknowledge = ack;
89 return this;
90 }
Ray Milkey269ffb92014-04-03 14:43:30 -070091
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080092 public byte getDataOffset() {
93 return this.dataOffset;
94 }
Ray Milkey269ffb92014-04-03 14:43:30 -070095
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080096 public TCP setDataOffset(byte offset) {
97 this.dataOffset = offset;
98 return this;
99 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700100
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800101 public short getFlags() {
102 return this.flags;
103 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700104
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800105 public TCP setFlags(short flags) {
106 this.flags = flags;
107 return this;
108 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700109
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800110 public short getWindowSize() {
111 return this.windowSize;
112 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700113
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800114 public TCP setWindowSize(short windowSize) {
115 this.windowSize = windowSize;
116 return this;
117 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700118
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800119 public short getTcpChecksum() {
120 return this.checksum;
121 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700122
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800123 public TCP setTcpChecksum(short checksum) {
124 this.checksum = checksum;
125 return this;
126 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700127
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800128 @Override
129 public void resetChecksum() {
130 this.checksum = 0;
131 super.resetChecksum();
132 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700133
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800134 public short getUrgentPointer(short urgentPointer) {
135 return this.urgentPointer;
136 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700137
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800138 public TCP setUrgentPointer(short urgentPointer) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700139 this.urgentPointer = urgentPointer;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800140 return this;
141 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700142
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800143 public byte[] getOptions() {
144 return this.options;
145 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700146
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800147 public TCP setOptions(byte[] options) {
148 this.options = options;
149 this.dataOffset = (byte) ((20 + options.length + 3) >> 2);
150 return this;
151 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700152
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800153 /**
154 * @param checksum the checksum to set
155 */
156 public TCP setChecksum(short checksum) {
157 this.checksum = checksum;
158 return this;
159 }
160
161 /**
162 * Serializes the packet. Will compute and set the following fields if they
163 * are set to specific values at the time serialize is called:
Ray Milkey269ffb92014-04-03 14:43:30 -0700164 * -checksum : 0
165 * -length : 0
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800166 */
167 public byte[] serialize() {
168 int length;
169 if (dataOffset == 0)
170 dataOffset = 5; // default header length
171 length = dataOffset << 2;
172 byte[] payloadData = null;
173 if (payload != null) {
174 payload.setParent(this);
175 payloadData = payload.serialize();
176 length += payloadData.length;
177 }
178
179 byte[] data = new byte[length];
180 ByteBuffer bb = ByteBuffer.wrap(data);
181
182 bb.putShort(this.sourcePort);
183 bb.putShort(this.destinationPort);
184 bb.putInt(this.sequence);
185 bb.putInt(this.acknowledge);
186 bb.putShort((short) (this.flags | (dataOffset << 12)));
187 bb.putShort(this.windowSize);
188 bb.putShort(this.checksum);
189 bb.putShort(this.urgentPointer);
190 if (dataOffset > 5) {
191 int padding;
192 bb.put(options);
193 padding = (dataOffset << 2) - 20 - options.length;
194 for (int i = 0; i < padding; i++)
195 bb.put((byte) 0);
196 }
197 if (payloadData != null)
198 bb.put(payloadData);
199
200 if (this.parent != null && this.parent instanceof IPv4)
Ray Milkey269ffb92014-04-03 14:43:30 -0700201 ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_TCP);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800202
203 // compute checksum if needed
204 if (this.checksum == 0) {
205 bb.rewind();
206 int accumulation = 0;
207
208 // compute pseudo header mac
209 if (this.parent != null && this.parent instanceof IPv4) {
210 IPv4 ipv4 = (IPv4) this.parent;
211 accumulation += ((ipv4.getSourceAddress() >> 16) & 0xffff)
212 + (ipv4.getSourceAddress() & 0xffff);
213 accumulation += ((ipv4.getDestinationAddress() >> 16) & 0xffff)
214 + (ipv4.getDestinationAddress() & 0xffff);
215 accumulation += ipv4.getProtocol() & 0xff;
216 accumulation += length & 0xffff;
217 }
218
219 for (int i = 0; i < length / 2; ++i) {
220 accumulation += 0xffff & bb.getShort();
221 }
222 // pad to an even number of shorts
223 if (length % 2 > 0) {
224 accumulation += (bb.get() & 0xff) << 8;
225 }
226
227 accumulation = ((accumulation >> 16) & 0xffff)
228 + (accumulation & 0xffff);
229 this.checksum = (short) (~accumulation & 0xffff);
230 bb.putShort(16, this.checksum);
231 }
232 return data;
233 }
234
235 /* (non-Javadoc)
236 * @see java.lang.Object#hashCode()
237 */
238 @Override
239 public int hashCode() {
240 final int prime = 5807;
241 int result = super.hashCode();
242 result = prime * result + checksum;
243 result = prime * result + destinationPort;
244 result = prime * result + sourcePort;
245 return result;
246 }
247
248 /* (non-Javadoc)
249 * @see java.lang.Object#equals(java.lang.Object)
250 */
251 @Override
252 public boolean equals(Object obj) {
253 if (this == obj)
254 return true;
255 if (!super.equals(obj))
256 return false;
257 if (!(obj instanceof TCP))
258 return false;
259 TCP other = (TCP) obj;
260 // May want to compare fields based on the flags set
261 return (checksum == other.checksum) &&
Ray Milkey269ffb92014-04-03 14:43:30 -0700262 (destinationPort == other.destinationPort) &&
263 (sourcePort == other.sourcePort) &&
264 (sequence == other.sequence) &&
265 (acknowledge == other.acknowledge) &&
266 (dataOffset == other.dataOffset) &&
267 (flags == other.flags) &&
268 (windowSize == other.windowSize) &&
269 (urgentPointer == other.urgentPointer) &&
270 (dataOffset == 5 || options.equals(other.options));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800271 }
272
273 @Override
274 public IPacket deserialize(byte[] data, int offset, int length) {
275 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
276 this.sourcePort = bb.getShort();
277 this.destinationPort = bb.getShort();
278 this.sequence = bb.getInt();
279 this.acknowledge = bb.getInt();
280 this.flags = bb.getShort();
281 this.dataOffset = (byte) ((this.flags >> 12) & 0xf);
282 this.flags = (short) (this.flags & 0x1ff);
283 this.windowSize = bb.getShort();
284 this.checksum = bb.getShort();
285 this.urgentPointer = bb.getShort();
286 if (this.dataOffset > 5) {
287 int optLength = (dataOffset << 2) - 20;
Ray Milkey269ffb92014-04-03 14:43:30 -0700288 if (bb.limit() < bb.position() + optLength) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800289 optLength = bb.limit() - bb.position();
290 }
291 try {
292 this.options = new byte[optLength];
293 bb.get(this.options, 0, optLength);
294 } catch (IndexOutOfBoundsException e) {
295 this.options = null;
296 }
297 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700298
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800299 this.payload = new Data();
Ray Milkey269ffb92014-04-03 14:43:30 -0700300 this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800301 this.payload.setParent(this);
302 return this;
303 }
304}