1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain 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,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 package java.net;
19 
20 /**
21  * This class represents a datagram packet which contains data either to be sent
22  * or received through a {@code DatagramSocket}. It holds additional information
23  * such as its source or destination host.
24  *
25  * @see DatagramSocket
26  */
27 public final class DatagramPacket {
28 
29     private byte[] data;
30 
31     /**
32      * Length of the data to be sent or size of data that was received via
33      * DatagramSocket#receive() method call.
34      */
35     private int length;
36 
37     /**
38      * The last user-supplied length (as opposed to a length set by simply receiving a packet).
39      * This length (unlike 'length') is sticky, and survives until the user sets another length.
40      * It's used to limit the amount of data that will be taken from future packets.
41      */
42     private int userSuppliedLength;
43 
44     private InetAddress address;
45 
46     private int port = -1; // The default port number is -1
47 
48     private int offset = 0;
49 
50     /**
51      * Constructs a new {@code DatagramPacket} object to receive data up to
52      * {@code length} bytes.
53      *
54      * @param data
55      *            a byte array to store the read characters.
56      * @param length
57      *            the length of the data buffer.
58      */
DatagramPacket(byte[] data, int length)59     public DatagramPacket(byte[] data, int length) {
60         this(data, 0, length);
61     }
62 
63     /**
64      * Constructs a new {@code DatagramPacket} object to receive data up to
65      * {@code length} bytes with a specified buffer offset.
66      *
67      * @param data
68      *            a byte array to store the read characters.
69      * @param offset
70      *            the offset of the byte array where the bytes is written.
71      * @param length
72      *            the length of the data.
73      */
DatagramPacket(byte[] data, int offset, int length)74     public DatagramPacket(byte[] data, int offset, int length) {
75         setData(data, offset, length);
76     }
77 
78     /**
79      * Constructs a new {@code DatagramPacket} object to send data to the port
80      * {@code aPort} of the address {@code host}. The {@code length} must be
81      * lesser than or equal to the size of {@code data}. The first {@code
82      * length} bytes from the byte array position {@code offset} are sent.
83      *
84      * @param data
85      *            a byte array which stores the characters to be sent.
86      * @param offset
87      *            the offset of {@code data} where to read from.
88      * @param length
89      *            the length of data.
90      * @param host
91      *            the address of the target host.
92      * @param aPort
93      *            the port of the target host.
94      */
DatagramPacket(byte[] data, int offset, int length, InetAddress host, int aPort)95     public DatagramPacket(byte[] data, int offset, int length, InetAddress host, int aPort) {
96         this(data, offset, length);
97         setPort(aPort);
98         address = host;
99     }
100 
101     /**
102      * Constructs a new {@code DatagramPacket} object to send data to the port
103      * {@code aPort} of the address {@code host}. The {@code length} must be
104      * lesser than or equal to the size of {@code data}. The first {@code
105      * length} bytes are sent.
106      *
107      * @param data
108      *            a byte array which stores the characters to be sent.
109      * @param length
110      *            the length of data.
111      * @param host
112      *            the address of the target host.
113      * @param port
114      *            the port of the target host.
115      */
DatagramPacket(byte[] data, int length, InetAddress host, int port)116     public DatagramPacket(byte[] data, int length, InetAddress host, int port) {
117         this(data, 0, length, host, port);
118     }
119 
120     /**
121      * Gets the sender or destination IP address of this datagram packet.
122      *
123      * @return the address from where the datagram was received or to which it
124      *         is sent.
125      */
getAddress()126     public synchronized InetAddress getAddress() {
127         return address;
128     }
129 
130     /**
131      * Gets the data of this datagram packet.
132      *
133      * @return the received data or the data to be sent.
134      */
getData()135     public synchronized byte[] getData() {
136         return data;
137     }
138 
139     /**
140      * Gets the length of the data stored in this datagram packet.
141      *
142      * @return the length of the received data or the data to be sent.
143      */
getLength()144     public synchronized int getLength() {
145         return length;
146     }
147 
148     /**
149      * Gets the offset of the data stored in this datagram packet.
150      *
151      * @return the position of the received data or the data to be sent.
152      */
getOffset()153     public synchronized int getOffset() {
154         return offset;
155     }
156 
157     /**
158      * Gets the port number of the target or sender host of this datagram
159      * packet.
160      *
161      * @return the port number of the origin or target host.
162      */
getPort()163     public synchronized int getPort() {
164         return port;
165     }
166 
167     /**
168      * Sets the IP address of the target host.
169      *
170      * @param addr
171      *            the target host address.
172      */
setAddress(InetAddress addr)173     public synchronized void setAddress(InetAddress addr) {
174         address = addr;
175     }
176 
177     /**
178      * Sets the data buffer for this datagram packet.
179      */
setData(byte[] data, int offset, int byteCount)180     public synchronized void setData(byte[] data, int offset, int byteCount) {
181         if ((offset | byteCount) < 0 || offset > data.length || byteCount > data.length - offset) {
182             throw new IllegalArgumentException();
183         }
184         this.data = data;
185         this.offset = offset;
186         this.length = byteCount;
187         this.userSuppliedLength = byteCount;
188     }
189 
190     /**
191      * Sets the data buffer for this datagram packet. The length of the datagram
192      * packet is set to the buffer length.
193      *
194      * @param buf
195      *            the buffer to store the data.
196      */
setData(byte[] buf)197     public synchronized void setData(byte[] buf) {
198         length = buf.length; // This will check for null
199         userSuppliedLength = length;
200         data = buf;
201         offset = 0;
202     }
203 
204     /**
205      * Sets the length of the datagram packet. This length plus the offset must
206      * be lesser than or equal to the buffer size.
207      *
208      * @param length
209      *            the length of this datagram packet.
210      */
setLength(int length)211     public synchronized void setLength(int length) {
212         if (length < 0 || offset + length > data.length) {
213             throw new IndexOutOfBoundsException("length=" + length + ", offset=" + offset +
214                                                 ", buffer size=" + data.length);
215         }
216         this.length = length;
217         this.userSuppliedLength = length;
218     }
219 
220     /**
221      * Resets 'length' to the last user-supplied length, ready to receive another packet.
222      * @hide for PlainDatagramSocketImpl
223      */
resetLengthForReceive()224     public void resetLengthForReceive() {
225         this.length = userSuppliedLength;
226     }
227 
228     /**
229      * Sets 'length' without changing 'userSuppliedLength', after receiving a packet.
230      * @hide for IoBridge
231      */
setReceivedLength(int length)232     public void setReceivedLength(int length) {
233         this.length = length;
234     }
235 
236     /**
237      * Sets the port number of the target host of this datagram packet.
238      *
239      * @param aPort
240      *            the target host port number.
241      */
setPort(int aPort)242     public synchronized void setPort(int aPort) {
243         if (aPort < 0 || aPort > 65535) {
244             throw new IllegalArgumentException("Port out of range: " + aPort);
245         }
246         port = aPort;
247     }
248 
249     /**
250      * Constructs a new {@code DatagramPacket} object to send data to the
251      * address {@code sockAddr}. The {@code length} must be lesser than or equal
252      * to the size of {@code data}. The first {@code length} bytes of the data
253      * are sent.
254      *
255      * @param data
256      *            the byte array to store the data.
257      * @param length
258      *            the length of the data.
259      * @param sockAddr
260      *            the target host address and port.
261      * @throws SocketException
262      *             if an error in the underlying protocol occurs.
263      */
DatagramPacket(byte[] data, int length, SocketAddress sockAddr)264     public DatagramPacket(byte[] data, int length, SocketAddress sockAddr) throws SocketException {
265         this(data, 0, length);
266         setSocketAddress(sockAddr);
267     }
268 
269     /**
270      * Constructs a new {@code DatagramPacket} object to send data to the
271      * address {@code sockAddr}. The {@code length} must be lesser than or equal
272      * to the size of {@code data}. The first {@code length} bytes of the data
273      * are sent.
274      *
275      * @param data
276      *            the byte array to store the data.
277      * @param offset
278      *            the offset of the data.
279      * @param length
280      *            the length of the data.
281      * @param sockAddr
282      *            the target host address and port.
283      * @throws SocketException
284      *             if an error in the underlying protocol occurs.
285      */
DatagramPacket(byte[] data, int offset, int length, SocketAddress sockAddr)286     public DatagramPacket(byte[] data, int offset, int length,
287             SocketAddress sockAddr) throws SocketException {
288         this(data, offset, length);
289         setSocketAddress(sockAddr);
290     }
291 
292     /**
293      * Gets the host address and the port to which this datagram packet is sent
294      * as a {@code SocketAddress} object.
295      *
296      * @return the SocketAddress of the target host.
297      */
getSocketAddress()298     public synchronized SocketAddress getSocketAddress() {
299         return new InetSocketAddress(getAddress(), getPort());
300     }
301 
302     /**
303      * Sets the {@code SocketAddress} for this datagram packet.
304      *
305      * @param sockAddr
306      *            the SocketAddress of the target host.
307      */
setSocketAddress(SocketAddress sockAddr)308     public synchronized void setSocketAddress(SocketAddress sockAddr) {
309         if (!(sockAddr instanceof InetSocketAddress)) {
310             throw new IllegalArgumentException("Socket address not an InetSocketAddress: " +
311                     (sockAddr == null ? null : sockAddr.getClass()));
312         }
313         InetSocketAddress inetAddr = (InetSocketAddress) sockAddr;
314         if (inetAddr.isUnresolved()) {
315             throw new IllegalArgumentException("Socket address unresolved: " + sockAddr);
316         }
317         port = inetAddr.getPort();
318         address = inetAddr.getAddress();
319     }
320 }
321