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 | |
45 | QT_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 | */ |
144 | QNetworkDatagram::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 | */ |
153 | QNetworkDatagram::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 | */ |
163 | QNetworkDatagram::QNetworkDatagram(const QNetworkDatagram &other) |
164 | : d(new QNetworkDatagramPrivate(*other.d)) |
165 | { |
166 | } |
167 | |
168 | /*! \internal */ |
169 | QNetworkDatagram::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 | */ |
179 | QNetworkDatagram &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 | */ |
189 | void 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 | */ |
209 | bool 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 | */ |
226 | QHostAddress 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 | */ |
243 | QHostAddress 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 | */ |
259 | int 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 | */ |
276 | int 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 | */ |
300 | void 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 | */ |
319 | void 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 | */ |
342 | int 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 | */ |
363 | void 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 | */ |
383 | uint 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 | */ |
409 | void 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 | */ |
424 | QByteArray 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 | */ |
439 | void 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 | |
489 | static bool isNonMulticast(const QHostAddress &addr) |
490 | { |
491 | // is it a multicast address? |
492 | return !addr.isMulticast(); |
493 | } |
494 | |
495 | QNetworkDatagram 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 | |
506 | void 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 | |
516 | void 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 | |
527 | QT_END_NAMESPACE |
528 | |
529 | #endif // QT_NO_UDPSOCKET |
530 | |