1/****************************************************************************
2**
3** Copyright (C) 2016 Intel Corporation.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtNetwork module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qnetworkdatagram.h"
41#include "qnetworkdatagram_p.h"
42
43#ifndef QT_NO_UDPSOCKET
44
45QT_BEGIN_NAMESPACE
46
47/*!
48 \class QNetworkDatagram
49 \brief The QNetworkDatagram class provides the data and metadata of a UDP datagram.
50 \since 5.8
51 \ingroup network
52 \inmodule QtNetwork
53 \reentrant
54
55 QNetworkDatagram can be used with the \l QUdpSocket class to represent the full
56 information contained in a UDP (User Datagram Protocol) datagram.
57 QNetworkDatagram encapsulates the following information of a datagram:
58 \list
59 \li the payload data;
60 \li the sender address and port number;
61 \li the destination address and port number;
62 \li the remaining hop count limit (on IPv4, this field is usually called "time to live" - TTL);
63 \li the network interface index the datagram was received on or to be sent on.
64 \endlist
65
66 QUdpSocket will try to match a common behavior as much as possible on all
67 operating systems, but not all of the metadata above can be obtained in
68 some operating systems. Metadata that cannot be set on the datagram when
69 sending with QUdpSocket::writeDatagram() will be silently discarded.
70
71 Upon reception, the senderAddress() and senderPort() properties contain the
72 address and port of the peer that sent the datagram, while
73 destinationAddress() and destinationPort() contain the target that was
74 contained in the datagram. That is usually an address local to the current
75 machine, but it can also be an IPv4 broadcast address (such as
76 "255.255.255.255") or an IPv4 or IPv6 multicast address. Applications may
77 find it useful to determine if the datagram was sent specifically to this
78 machine via unicast addressing or whether it was sent to multiple destinations.
79
80 When sending, the senderAddress() and senderPort() should contain the local
81 address to be used when sending. The sender address must be an address that
82 is assigned to this machine, which can be obtained using
83 \l{QNetworkInterface}, and the port number must be the port number that the
84 socket is bound to. Either field can be left unset and will be filled in by
85 the operating system with default values. The destinationAddress() and
86 destinationPort() fields may be set to a target address different from the
87 one the UDP socket is currently associated with.
88
89 Usually, when sending a datagram in reply to a datagram previously
90 received, one will set the destinationAddress() to be the senderAddress()
91 of the incoming datagram and similarly for the port numbers. To facilitate
92 this common process, QNetworkDatagram provides the function makeReply().
93
94 The hopCount() function contains, for a received datagram, the remaining
95 hop count limit for the packet. When sending, it contains the hop count
96 limit to be set. Most protocols will leave this value set to the default
97 and let the operating system decide on the best value to be used.
98 Multicasting over IPv4 often uses this field to indicate the scope of the
99 multicast group (link-local, local to an organization or global).
100
101 The interfaceIndex() function contains the index of the operating system's
102 interface that received the packet. This value is the same one that can be
103 set on a QHostAddress::scopeId() property and matches the
104 QNetworkInterface::index() property. When sending packets to global
105 addresses, it is not necessary to set the interface index as the operating
106 system will choose the correct one using the system routing table. This
107 property is important when sending datagrams to link-local destinations,
108 whether unicast or multicast.
109
110 \section1 Feature support
111
112 Some features of QNetworkDatagram are not supported in all operating systems.
113 Only the address and ports of the remote host (sender in received packets
114 and destination for outgoing packets) are supported in all systems. On most
115 operating systems, the other features are supported only for IPv6. Software
116 should check at runtime whether the rest could be determined for IPv4
117 addresses.
118
119 The current feature support is as follows:
120
121 \table
122 \header \li Operating system \li Local address \li Hop count \li Interface index
123 \row \li FreeBSD \li Supported \li Supported \li Only for IPv6
124 \row \li Linux \li Supported \li Supported \li Supported
125 \row \li OS X \li Supported \li Supported \li Only for IPv6
126 \row \li Other Unix supporting RFC 3542 \li Only for IPv6 \li Only for IPv6 \li Only for IPv6
127 \row \li Windows (desktop) \li Supported \li Supported \li Supported
128 \row \li Windows RT \li Not supported \li Not supported \li Not supported
129 \endtable
130
131 \sa QUdpSocket, QNetworkInterface
132 */
133
134/*!
135 Creates a QNetworkDatagram object with no payload data and undefined destination address.
136
137 The payload can be modified by using setData() and the destination address
138 can be set with setDestination().
139
140 If the destination address is left undefined, QUdpSocket::writeDatagram()
141 will attempt to send the datagram to the address last associated with, by
142 using QUdpSocket::connectToHost().
143 */
144QNetworkDatagram::QNetworkDatagram()
145 : d(new QNetworkDatagramPrivate)
146{
147}
148
149/*!
150 Creates a QNetworkDatagram object and sets \a data as the payload data, along with
151 \a destinationAddress and \a port as the destination address of the datagram.
152 */
153QNetworkDatagram::QNetworkDatagram(const QByteArray &data, const QHostAddress &destinationAddress, quint16 port)
154 : d(new QNetworkDatagramPrivate(data, destinationAddress, port))
155{
156}
157
158/*!
159 Creates a copy of the \a other datagram, including the payload and metadata.
160
161 To create a datagram suitable for sending in a reply, use QNetworkDatagram::makeReply();
162 */
163QNetworkDatagram::QNetworkDatagram(const QNetworkDatagram &other)
164 : d(new QNetworkDatagramPrivate(*other.d))
165{
166}
167
168/*! \internal */
169QNetworkDatagram::QNetworkDatagram(QNetworkDatagramPrivate &dd)
170 : d(&dd)
171{
172}
173
174/*!
175 Copies the \a other datagram, including the payload and metadata.
176
177 To create a datagram suitable for sending in a reply, use QNetworkDatagram::makeReply();
178 */
179QNetworkDatagram &QNetworkDatagram::operator=(const QNetworkDatagram &other)
180{
181 *d = *other.d;
182 return *this;
183}
184
185/*!
186 Clears the payload data and metadata in this QNetworkDatagram object, resetting
187 them to their default values.
188 */
189void QNetworkDatagram::clear()
190{
191 d->data.clear();
192 d->header.senderAddress.clear();
193 d->header.destinationAddress.clear();
194 d->header.hopLimit = -1;
195 d->header.ifindex = 0;
196}
197
198/*!
199 \fn QNetworkDatagram::isNull() const
200 Returns true if this QNetworkDatagram object is null. This function is the
201 opposite of isValid().
202 */
203
204/*!
205 Returns true if this QNetworkDatagram object is valid. A valid QNetworkDatagram
206 object contains at least one sender or receiver address. Valid datagrams
207 can contain empty payloads.
208 */
209bool QNetworkDatagram::isValid() const
210{
211 return d->header.senderAddress.protocol() != QAbstractSocket::UnknownNetworkLayerProtocol ||
212 d->header.destinationAddress.protocol() != QAbstractSocket::UnknownNetworkLayerProtocol;
213}
214
215/*!
216 Returns the sender address associated with this datagram. For a datagram
217 received from the network, it is the address of the peer node that sent the
218 datagram. For an outgoing datagrams, it is the local address to be used
219 when sending.
220
221 If no sender address was set on this datagram, the returned object will
222 report true to QHostAddress::isNull().
223
224 \sa destinationAddress(), senderPort(), setSender()
225*/
226QHostAddress QNetworkDatagram::senderAddress() const
227{
228 return d->header.senderAddress;
229}
230
231/*!
232 Returns the destination address associated with this datagram. For a
233 datagram received from the network, it is the address the peer node sent
234 the datagram to, which can either be a local address of this machine or a
235 multicast or broadcast address. For an outgoing datagrams, it is the
236 address the datagram should be sent to.
237
238 If no destination address was set on this datagram, the returned object
239 will report true to QHostAddress::isNull().
240
241 \sa senderAddress(), destinationPort(), setDestination()
242*/
243QHostAddress QNetworkDatagram::destinationAddress() const
244{
245 return d->header.destinationAddress;
246}
247
248/*!
249 Returns the port number of the sender associated with this datagram. For a
250 datagram received from the network, it is the port number that the peer
251 node sent the datagram from. For an outgoing datagram, it is the local port
252 the datagram should be sent from.
253
254 If no sender address was associated with this datagram, this function
255 returns -1.
256
257 \sa senderAddress(), destinationPort(), setSender()
258*/
259int QNetworkDatagram::senderPort() const
260{
261 return d->header.senderAddress.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol
262 ? -1 : d->header.senderPort;
263}
264
265/*!
266 Returns the port number of the destination associated with this datagram.
267 For a datagram received from the network, it is the local port number that
268 the peer node sent the datagram to. For an outgoing datagram, it is the
269 peer port the datagram should be sent to.
270
271 If no destination address was associated with this datagram, this function
272 returns -1.
273
274 \sa destinationAddress(), senderPort(), setDestination()
275*/
276int QNetworkDatagram::destinationPort() const
277{
278 return d->header.destinationAddress.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol
279 ? -1 : d->header.destinationPort;
280}
281
282/*!
283 Sets the sender address associated with this datagram to be the address \a
284 address and port number \a port. The sender address and port numbers are
285 usually set by \l QUdpSocket upon reception, so there's no need to call
286 this function on a received datagram.
287
288 For outgoing datagrams, this function can be used to set the address the
289 datagram should carry. The address \a address must usually be one of the
290 local addresses assigned to this machine, which can be obtained using \l
291 QNetworkInterface. If left unset, the operating system will choose the most
292 appropriate address to use given the destination in question.
293
294 The port number \a port must be the port number associated with the socket,
295 if there is one. The value of 0 can be used to indicate that the operating
296 system should choose the port number.
297
298 \sa QUdpSocket::writeDatagram(), senderAddress(), senderPort(), setDestination()
299 */
300void QNetworkDatagram::setSender(const QHostAddress &address, quint16 port)
301{
302 d->header.senderAddress = address;
303 d->header.senderPort = port;
304}
305
306/*!
307 Sets the destination address associated with this datagram to be the
308 address \a address and port number \a port. The destination address and
309 port numbers are usually set by \l QUdpSocket upon reception, so there's no
310 need to call this function on a received datagram.
311
312 For outgoing datagrams, this function can be used to set the address the
313 datagram should be sent to. It can be the unicast address used to
314 communicate with the peer or a broadcast or multicast address to send to a
315 group of devices.
316
317 \sa QUdpSocket::writeDatagram(), destinationAddress(), destinationPort(), setSender()
318 */
319void QNetworkDatagram::setDestination(const QHostAddress &address, quint16 port)
320{
321 d->header.destinationAddress = address;
322 d->header.destinationPort = port;
323}
324
325/*!
326 Returns the hop count limit associated with this datagram. The hop count
327 limit is the number of nodes that are allowed to forward the IP packet
328 before it expires and an error is sent back to the sender of the datagram.
329 In IPv4, this value is usually known as "time to live" (TTL).
330
331 If this datagram was received from the network, this is the remaining hop
332 count of the datagram after reception and was decremented by 1 by each node
333 that forwarded the packet. A value of -1 indicates that the hop limit count
334 not be obtained.
335
336 If this is an outgoing datagram, this is the value to be set in the IP header
337 upon sending. A value of -1 indicates the operating system should choose
338 the value.
339
340 \sa setHopLimit()
341 */
342int QNetworkDatagram::hopLimit() const
343{
344 return d->header.hopLimit;
345}
346
347/*!
348 Sets the hop count limit associated with this datagram to \a count. The hop
349 count limit is the number of nodes that are allowed to forward the IP
350 packet before it expires and an error is sent back to the sender of the
351 datagram. In IPv4, this value is usually known as "time to live" (TTL).
352
353 It is usually not necessary to call this function on datagrams received
354 from the network.
355
356 If this is an outgoing packet, this is the value to be set in the IP header
357 upon sending. The valid range for the value is 1 to 255. This function also
358 accepts a value of -1 to indicate that the operating system should choose
359 the value.
360
361 \sa hopLimit()
362 */
363void QNetworkDatagram::setHopLimit(int count)
364{
365 d->header.hopLimit = count;
366}
367
368/*!
369 Returns the interface index this datagram is associated with. The interface
370 index is a positive number that uniquely identifies the network interface
371 in the operating system. This number matches the value returned by
372 QNetworkInterface::index() for the interface.
373
374 If this datagram was received from the network, this is the index of the
375 interface that the packet was received from. If this is an outgoing
376 datagram, this is the index of the interface that the datagram should be
377 sent on.
378
379 A value of 0 indicates that the interface index is unknown.
380
381 \sa setInterfaceIndex()
382 */
383uint QNetworkDatagram::interfaceIndex() const
384{
385 return d->header.ifindex;
386}
387
388/*!
389 Sets the interface index this datagram is associated with to \a index. The
390 interface index is a positive number that uniquely identifies the network
391 interface in the operating system. This number matches the value returned
392 by QNetworkInterface::index() for the interface.
393
394 It is usually not necessary to call this function on datagrams received
395 from the network.
396
397 If this is an outgoing packet, this is the index of the interface the
398 datagram should be sent on. A value of 0 indicates that the operating
399 system should choose the interface based on other factors.
400
401 Note that the interface index can also be set with
402 QHostAddress::setScopeId() for IPv6 destination addresses and then with
403 setDestination(). If the scope ID set in the destination address and \a
404 index are different and neither is zero, it is undefined which interface
405 the operating system will send the datagram on.
406
407 \sa setInterfaceIndex()
408 */
409void QNetworkDatagram::setInterfaceIndex(uint index)
410{
411 d->header.ifindex = index;
412}
413
414/*!
415 Returns the data payload of this datagram. For a datagram received from the
416 network, it contains the payload of the datagram. For an outgoing datagram,
417 it is the datagram to be sent.
418
419 Note that datagrams can be transmitted with no data, so the returned
420 QByteArray may be empty.
421
422 \sa setData()
423 */
424QByteArray QNetworkDatagram::data() const
425{
426 return d->data;
427}
428
429/*!
430 Sets the data payload of this datagram to \a data. It is usually not
431 necessary to call this function on received datagrams. For outgoing
432 datagrams, this function sets the data to be sent on the network.
433
434 Since datagrams can empty, an empty QByteArray is a valid value for \a
435 data.
436
437 \sa data()
438 */
439void QNetworkDatagram::setData(const QByteArray &data)
440{
441 d->data = data;
442}
443
444/*!
445 \fn QNetworkDatagram QNetworkDatagram::makeReply(const QByteArray &payload) const &
446 \fn QNetworkDatagram QNetworkDatagram::makeReply(const QByteArray &payload) &&
447
448 Creates a new QNetworkDatagram representing a reply to this incoming datagram
449 and sets the payload data to \a payload. This function is a very convenient
450 way of responding to a datagram back to the original sender.
451
452 Example:
453 \snippet code/src_network_kernel_qnetworkdatagram.cpp 0
454
455 This function is especially convenient since it will automatically copy
456 parameters from this datagram to the new datagram as appropriate:
457
458 \list
459 \li this datagram's sender address and port are copied to the new
460 datagram's destination address and port;
461 \li this datagram's interface index, if any, is copied to the new
462 datagram's interface index;
463 \li this datagram's destination address and port are copied to the new
464 datagram's sender address and port only if the address is IPv6
465 global (non-multicast) address;
466 \li the hop count limit on the new datagram is reset to the default (-1);
467 \endlist
468
469 If QNetworkDatagram is modified in a future version of Qt to carry further
470 metadata, this function will copy that metadata as appropriate.
471
472 This datagram's destination address is not copied if it is an IPv4 address
473 because it is not possible to tell an IPv4 broadcast address apart from a
474 regular IPv4 address without an exhaustive search of all addresses assigned
475 to this machine. Attempting to send a datagram with the sender address
476 equal to the broadcast address is likely to fail. However, this should not
477 affect the communication as network interfaces with multiple IPv4 addresses
478 are uncommon, so the address the operating system will select will likely
479 be one the peer will understand.
480
481 \note This function comes with both rvalue- and lvalue-reference qualifier
482 overloads, so it is a good idea to make sure this object is rvalue, if
483 possible, before calling makeReply, so as to make better use of move
484 semantics. To achieve that, the example above would use:
485 \snippet code/src_network_kernel_qnetworkdatagram.cpp 1
486 */
487
488
489static bool isNonMulticast(const QHostAddress &addr)
490{
491 // is it a multicast address?
492 return !addr.isMulticast();
493}
494
495QNetworkDatagram QNetworkDatagram::makeReply_helper(const QByteArray &data) const
496{
497 QNetworkDatagramPrivate *x = new QNetworkDatagramPrivate(data, d->header.senderAddress, d->header.senderPort);
498 x->header.ifindex = d->header.ifindex;
499 if (isNonMulticast(d->header.destinationAddress)) {
500 x->header.senderAddress = d->header.destinationAddress;
501 x->header.senderPort = d->header.destinationPort;
502 }
503 return QNetworkDatagram(*x);
504}
505
506void QNetworkDatagram::makeReply_helper_inplace(const QByteArray &data)
507{
508 d->data = data;
509 d->header.hopLimit = -1;
510 qSwap(d->header.destinationPort, d->header.senderPort);
511 qSwap(d->header.destinationAddress, d->header.senderAddress);
512 if (!isNonMulticast(d->header.senderAddress))
513 d->header.senderAddress.clear();
514}
515
516void QNetworkDatagram::destroy(QNetworkDatagramPrivate *d)
517{
518 Q_ASSUME(d);
519 delete d;
520}
521
522/*! \fn void QNetworkDatagram::swap(QNetworkDatagram &other)
523 Swaps this instance with \a other.
524*/
525
526
527QT_END_NAMESPACE
528
529#endif // QT_NO_UDPSOCKET
530