src/network/socket/qudpsocket.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtNetwork module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 //#define QUDPSOCKET_DEBUG
       
    43 
       
    44 /*! \class QUdpSocket
       
    45 
       
    46     \reentrant
       
    47     \brief The QUdpSocket class provides a UDP socket.
       
    48 
       
    49     \ingroup network
       
    50     \inmodule QtNetwork
       
    51 
       
    52     UDP (User Datagram Protocol) is a lightweight, unreliable,
       
    53     datagram-oriented, connectionless protocol. It can be used when
       
    54     reliability isn't important. QUdpSocket is a subclass of
       
    55     QAbstractSocket that allows you to send and receive UDP
       
    56     datagrams.
       
    57 
       
    58     The most common way to use this class is to bind to an address and port
       
    59     using bind(), then call writeDatagram() and readDatagram() to transfer
       
    60     data. If you want to use the standard QIODevice functions read(),
       
    61     readLine(), write(), etc., you must first connect the socket directly to a
       
    62     peer by calling connectToHost().
       
    63 
       
    64     The socket emits the bytesWritten() signal every time a datagram
       
    65     is written to the network. If you just want to send datagrams,
       
    66     you don't need to call bind().
       
    67 
       
    68     The readyRead() signal is emitted whenever datagrams arrive. In
       
    69     that case, hasPendingDatagrams() returns true. Call
       
    70     pendingDatagramSize() to obtain the size of the first pending
       
    71     datagram, and readDatagram() to read it.
       
    72 
       
    73     \note An incoming datagram should be read when you receive the readyRead()
       
    74     signal, otherwise this signal will not be emitted for the next datagram.
       
    75 
       
    76     Example:
       
    77 
       
    78     \snippet doc/src/snippets/code/src_network_socket_qudpsocket.cpp 0
       
    79 
       
    80     With QUdpSocket, you can also establish a virtual connection to a
       
    81     UDP server using connectToHost() and then use read() and write()
       
    82     to exchange datagrams without specifying the receiver for each
       
    83     datagram.
       
    84 
       
    85     The \l{network/broadcastsender}{Broadcast Sender} and
       
    86     \l{network/broadcastreceiver}{Broadcast Receiver} examples
       
    87     illustrate how to use QUdpSocket in applications.
       
    88 
       
    89     \sa QTcpSocket
       
    90 */
       
    91 
       
    92 /*! \enum QUdpSocket::BindFlag
       
    93     \since 4.1
       
    94 
       
    95     This enum describes the different flags you can pass to modify the
       
    96     behavior of QUdpSocket::bind().
       
    97 
       
    98     \note On Symbian OS bind flags behaviour depends on process capabilties.
       
    99     If process has NetworkControl capability, the bind attempt with
       
   100     ReuseAddressHint will always succeed even if the address and port is already
       
   101     bound by another socket with any flags. If process does not have
       
   102     NetworkControl capability, the bind attempt to address and port already
       
   103     bound by another socket will always fail.
       
   104 
       
   105     \value ShareAddress Allow other services to bind to the same address
       
   106     and port. This is useful when multiple processes share
       
   107     the load of a single service by listening to the same address and port
       
   108     (e.g., a web server with several pre-forked listeners can greatly
       
   109     improve response time). However, because any service is allowed to
       
   110     rebind, this option is subject to certain security considerations.
       
   111     Note that by combining this option with ReuseAddressHint, you will
       
   112     also allow your service to rebind an existing shared address. On
       
   113     Unix, this is equivalent to the SO_REUSEADDR socket option. On Windows,
       
   114     this option is ignored.
       
   115 
       
   116     \value DontShareAddress Bind the address and port exclusively, so that
       
   117     no other services are allowed to rebind. By passing this option to
       
   118     QUdpSocket::bind(), you are guaranteed that on successs, your service
       
   119     is the only one that listens to the address and port. No services are
       
   120     allowed to rebind, even if they pass ReuseAddressHint. This option
       
   121     provides more security than ShareAddress, but on certain operating
       
   122     systems, it requires you to run the server with administrator privileges.
       
   123     On Unix and Mac OS X, not sharing is the default behavior for binding
       
   124     an address and port, so this option is ignored. On Windows, this
       
   125     option uses the SO_EXCLUSIVEADDRUSE socket option.
       
   126 
       
   127     \value ReuseAddressHint Provides a hint to QUdpSocket that it should try
       
   128     to rebind the service even if the address and port are already bound by
       
   129     another socket. On Windows, this is equivalent to the SO_REUSEADDR
       
   130     socket option. On Unix, this option is ignored.
       
   131 
       
   132     \value DefaultForPlatform The default option for the current platform.
       
   133     On Unix and Mac OS X, this is equivalent to (DontShareAddress
       
   134     + ReuseAddressHint), and on Windows, its equivalent to ShareAddress.
       
   135 */
       
   136 
       
   137 #include "qhostaddress.h"
       
   138 #include "qabstractsocket_p.h"
       
   139 #include "qudpsocket.h"
       
   140 
       
   141 QT_BEGIN_NAMESPACE
       
   142 
       
   143 #ifndef QT_NO_UDPSOCKET
       
   144 
       
   145 #define QT_CHECK_BOUND(function, a) do { \
       
   146     if (!isValid()) { \
       
   147         qWarning(function" called on a QUdpSocket when not in QUdpSocket::BoundState"); \
       
   148         return (a); \
       
   149     } } while (0)
       
   150 
       
   151 class QUdpSocketPrivate : public QAbstractSocketPrivate
       
   152 {
       
   153     Q_DECLARE_PUBLIC(QUdpSocket)
       
   154 
       
   155     bool doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
       
   156                              const QHostAddress &remoteAddress);
       
   157 public:
       
   158     inline bool ensureInitialized(const QHostAddress &bindAddress, quint16 bindPort)
       
   159     { return doEnsureInitialized(bindAddress, bindPort, QHostAddress()); }
       
   160 
       
   161     inline bool ensureInitialized(const QHostAddress &remoteAddress)
       
   162     { return doEnsureInitialized(QHostAddress(), 0, remoteAddress); }
       
   163 };
       
   164 
       
   165 bool QUdpSocketPrivate::doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
       
   166                                             const QHostAddress &remoteAddress)
       
   167 {
       
   168     const QHostAddress *address = &bindAddress;
       
   169     QAbstractSocket::NetworkLayerProtocol proto = address->protocol();
       
   170     if (proto == QUdpSocket::UnknownNetworkLayerProtocol) {
       
   171         address = &remoteAddress;
       
   172         proto = address->protocol();
       
   173     }
       
   174 
       
   175 #if defined(QT_NO_IPV6)
       
   176     Q_Q(QUdpSocket);
       
   177     if (proto == QUdpSocket::IPv6Protocol) {
       
   178         socketError = QUdpSocket::UnsupportedSocketOperationError;
       
   179         q->setErrorString(QUdpSocket::tr("This platform does not support IPv6"));
       
   180         return false;
       
   181     }
       
   182 #endif
       
   183 
       
   184     // now check if the socket engine is initialized and to the right type
       
   185     if (!socketEngine || !socketEngine->isValid() || socketEngine->protocol() != proto) {
       
   186         resolveProxy(remoteAddress.toString(), bindPort);
       
   187         if (!initSocketLayer(address->protocol()))
       
   188             return false;
       
   189     }
       
   190 
       
   191     return true;
       
   192 }
       
   193 
       
   194 /*!
       
   195     Creates a QUdpSocket object.
       
   196 
       
   197     \a parent is passed to the QObject constructor.
       
   198 
       
   199     \sa socketType()
       
   200 */
       
   201 QUdpSocket::QUdpSocket(QObject *parent)
       
   202     : QAbstractSocket(UdpSocket, *new QUdpSocketPrivate, parent)
       
   203 {
       
   204     d_func()->isBuffered = false;
       
   205 }
       
   206 
       
   207 /*!
       
   208     Destroys the socket, closing the connection if necessary.
       
   209 
       
   210     \sa close()
       
   211 */
       
   212 QUdpSocket::~QUdpSocket()
       
   213 {
       
   214 }
       
   215 
       
   216 /*!
       
   217     Binds this socket to the address \a address and the port \a port.
       
   218     When bound, the signal readyRead() is emitted whenever a UDP
       
   219     datagram arrives on the specified address and port. This function
       
   220     is useful to write UDP servers.
       
   221 
       
   222     On success, the functions returns true and the socket enters
       
   223     BoundState; otherwise it returns false.
       
   224 
       
   225     The socket is bound using the DefaultForPlatform BindMode.
       
   226 
       
   227     \sa readDatagram()
       
   228 */
       
   229 bool QUdpSocket::bind(const QHostAddress &address, quint16 port)
       
   230 {
       
   231     Q_D(QUdpSocket);
       
   232     if (!d->ensureInitialized(address, port))
       
   233         return false;
       
   234 
       
   235     bool result = d_func()->socketEngine->bind(address, port);
       
   236     d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
       
   237 
       
   238     if (!result) {
       
   239         d->socketError = d_func()->socketEngine->error();
       
   240         setErrorString(d_func()->socketEngine->errorString());
       
   241         emit error(d_func()->socketError);
       
   242         return false;
       
   243     }
       
   244 
       
   245     d->state = BoundState;
       
   246     d->localAddress = d->socketEngine->localAddress();
       
   247     d->localPort = d->socketEngine->localPort();
       
   248 
       
   249     emit stateChanged(d_func()->state);
       
   250     d_func()->socketEngine->setReadNotificationEnabled(true);
       
   251     return true;
       
   252 }
       
   253 
       
   254 /*!
       
   255     \since 4.1
       
   256     \overload
       
   257 
       
   258     Binds to \a address on port \a port, using the BindMode \a mode.
       
   259 */
       
   260 bool QUdpSocket::bind(const QHostAddress &address, quint16 port, BindMode mode)
       
   261 {
       
   262     Q_D(QUdpSocket);
       
   263     if (!d->ensureInitialized(address, port))
       
   264         return false;
       
   265 
       
   266 #ifdef Q_OS_UNIX
       
   267     if ((mode & ShareAddress) || (mode & ReuseAddressHint))
       
   268         d->socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 1);
       
   269     else
       
   270         d->socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 0);
       
   271 #endif
       
   272 #ifdef Q_OS_WIN
       
   273     if (mode & ReuseAddressHint)
       
   274         d->socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 1);
       
   275     else
       
   276         d->socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 0);
       
   277     if (mode & DontShareAddress)
       
   278         d->socketEngine->setOption(QAbstractSocketEngine::BindExclusively, 1);
       
   279     else
       
   280         d->socketEngine->setOption(QAbstractSocketEngine::BindExclusively, 0);
       
   281 #endif
       
   282     bool result = d_func()->socketEngine->bind(address, port);
       
   283     d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
       
   284 
       
   285     if (!result) {
       
   286         d->socketError = d_func()->socketEngine->error();
       
   287         setErrorString(d_func()->socketEngine->errorString());
       
   288         emit error(d_func()->socketError);
       
   289         return false;
       
   290     }
       
   291 
       
   292     d->state = BoundState;
       
   293     d->localAddress = d->socketEngine->localAddress();
       
   294     d->localPort = d->socketEngine->localPort();
       
   295 
       
   296     emit stateChanged(d_func()->state);
       
   297     d_func()->socketEngine->setReadNotificationEnabled(true);
       
   298     return true;
       
   299 }
       
   300 
       
   301 /*! \overload
       
   302 
       
   303     Binds to QHostAddress:Any on port \a port.
       
   304 */
       
   305 bool QUdpSocket::bind(quint16 port)
       
   306 {
       
   307     return bind(QHostAddress::Any, port);
       
   308 }
       
   309 
       
   310 /*!
       
   311     \since 4.1
       
   312     \overload
       
   313 
       
   314     Binds to QHostAddress:Any on port \a port, using the BindMode \a mode.
       
   315 */
       
   316 bool QUdpSocket::bind(quint16 port, BindMode mode)
       
   317 {
       
   318     return bind(QHostAddress::Any, port, mode);
       
   319 }
       
   320 
       
   321 /*!
       
   322     Returns true if at least one datagram is waiting to be read;
       
   323     otherwise returns false.
       
   324 
       
   325     \sa pendingDatagramSize(), readDatagram()
       
   326 */
       
   327 bool QUdpSocket::hasPendingDatagrams() const
       
   328 {
       
   329     QT_CHECK_BOUND("QUdpSocket::hasPendingDatagrams()", false);
       
   330     return d_func()->socketEngine->hasPendingDatagrams();
       
   331 }
       
   332 
       
   333 /*!
       
   334     Returns the size of the first pending UDP datagram. If there is
       
   335     no datagram available, this function returns -1.
       
   336 
       
   337     \sa hasPendingDatagrams(), readDatagram()
       
   338 */
       
   339 qint64 QUdpSocket::pendingDatagramSize() const
       
   340 {
       
   341     QT_CHECK_BOUND("QUdpSocket::pendingDatagramSize()", -1);
       
   342     return d_func()->socketEngine->pendingDatagramSize();
       
   343 }
       
   344 
       
   345 /*!
       
   346     Sends the datagram at \a data of size \a size to the host
       
   347     address \a address at port \a port. Returns the number of
       
   348     bytes sent on success; otherwise returns -1.
       
   349 
       
   350     Datagrams are always written as one block. The maximum size of a
       
   351     datagram is highly platform-dependent, but can be as low as 8192
       
   352     bytes. If the datagram is too large, this function will return -1
       
   353     and error() will return DatagramTooLargeError.
       
   354 
       
   355     Sending datagrams larger than 512 bytes is in general disadvised,
       
   356     as even if they are sent successfully, they are likely to be
       
   357     fragmented by the IP layer before arriving at their final
       
   358     destination.
       
   359 
       
   360     \warning In S60 5.0 and earlier versions, the writeDatagram return
       
   361     value is not reliable for large datagrams.
       
   362 
       
   363     \warning Calling this function on a connected UDP socket may
       
   364     result in an error and no packet being sent. If you are using a
       
   365     connected socket, use write() to send datagrams.
       
   366 
       
   367     \sa readDatagram(), write()
       
   368 */
       
   369 qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address,
       
   370                                   quint16 port)
       
   371 {
       
   372     Q_D(QUdpSocket);
       
   373 #if defined QUDPSOCKET_DEBUG
       
   374     qDebug("QUdpSocket::writeDatagram(%p, %llu, \"%s\", %i)", data, size,
       
   375            address.toString().toLatin1().constData(), port);
       
   376 #endif
       
   377     if (!d->ensureInitialized(address))
       
   378         return -1;
       
   379 
       
   380     qint64 sent = d->socketEngine->writeDatagram(data, size, address, port);
       
   381 #ifdef Q_OS_SYMBIAN
       
   382     if( QSysInfo::s60Version() <= QSysInfo::SV_S60_5_0 ) {
       
   383         // This is evil hack, but for some reason native RSocket::SendTo returns 0,
       
   384         // for large datagrams (such as 600 bytes). Based on comments from Open C team
       
   385         // this should happen only in platforms <= S60 5.0.
       
   386         // As an workaround, we just set sent = size
       
   387         if( sent == 0 )
       
   388             sent = size;
       
   389     }
       
   390 #endif
       
   391     d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
       
   392 
       
   393     if (sent >= 0) {
       
   394         emit bytesWritten(sent);
       
   395     } else {
       
   396         d->socketError = d->socketEngine->error();
       
   397         setErrorString(d->socketEngine->errorString());
       
   398         emit error(d->socketError);
       
   399     }
       
   400     return sent;
       
   401 }
       
   402 
       
   403 /*!
       
   404     \fn qint64 QUdpSocket::writeDatagram(const QByteArray &datagram,
       
   405                                              const QHostAddress &host, quint16 port)
       
   406     \overload
       
   407 
       
   408     Sends the datagram \a datagram to the host address \a host and at
       
   409     port \a port.
       
   410 */
       
   411 
       
   412 /*!
       
   413     Receives a datagram no larger than \a maxSize bytes and stores
       
   414     it in \a data. The sender's host address and port is stored in
       
   415     *\a address and *\a port (unless the pointers are 0).
       
   416 
       
   417     Returns the size of the datagram on success; otherwise returns
       
   418     -1.
       
   419 
       
   420     If \a maxSize is too small, the rest of the datagram will be
       
   421     lost. To avoid loss of data, call pendingDatagramSize() to
       
   422     determine the size of the pending datagram before attempting to
       
   423     read it. If \a maxSize is 0, the datagram will be discarded.
       
   424 
       
   425     \sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize()
       
   426 */
       
   427 qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address,
       
   428                                     quint16 *port)
       
   429 {
       
   430     Q_D(QUdpSocket);
       
   431 
       
   432 #if defined QUDPSOCKET_DEBUG
       
   433     qDebug("QUdpSocket::readDatagram(%p, %llu, %p, %p)", data, maxSize, address, port);
       
   434 #endif
       
   435     QT_CHECK_BOUND("QUdpSocket::readDatagram()", -1);
       
   436     qint64 readBytes = d->socketEngine->readDatagram(data, maxSize, address, port);
       
   437     d_func()->socketEngine->setReadNotificationEnabled(true);
       
   438     if (readBytes < 0) {
       
   439         d->socketError = d->socketEngine->error();
       
   440         setErrorString(d->socketEngine->errorString());
       
   441         emit error(d->socketError);
       
   442     }
       
   443     return readBytes;
       
   444 }
       
   445 #endif // QT_NO_UDPSOCKET
       
   446 
       
   447 QT_END_NAMESPACE