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
18package 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 */
27public 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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
173    public synchronized void setAddress(InetAddress addr) {
174        address = addr;
175    }
176
177    /**
178     * Sets the data buffer for this datagram packet.
179     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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