Skip to content
UDPLink.h 5.89 KiB
Newer Older
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
pixhawk's avatar
pixhawk committed


pixhawk's avatar
pixhawk committed
 * @file
 *   @brief UDP connection (server) for unmanned vehicles
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

#ifndef UDPLINK_H
#define UDPLINK_H

#include <QString>
#include <QList>
#include <QMap>
#include <QMutex>
#include <QUdpSocket>
#include <QMutexLocker>
#include <QQueue>
#include <QByteArray>
#if defined(QGC_ZEROCONF_ENABLED)
#include <dns_sd.h>
#endif

#define QGC_UDP_LOCAL_PORT  14550
#define QGC_UDP_TARGET_PORT 14555

class UDPConfiguration : public LinkConfiguration
{
Don Gagne's avatar
Don Gagne committed
    Q_OBJECT

    Q_PROPERTY(quint16      localPort   READ localPort  WRITE setLocalPort  NOTIFY localPortChanged)
    Q_PROPERTY(QStringList  hostList    READ hostList                       NOTIFY  hostListChanged)

    /*!
     * @brief Regular constructor
     *
     * @param[in] name Configuration (user friendly) name
     */
    UDPConfiguration(const QString& name);

    /*!
     * @brief Copy contructor
     *
     * When manipulating data, you create a copy of the configuration, edit it
     * and then transfer its content to the original (using copyFrom() below). Use this
     * contructor to create an editable copy.
     *
     * @param[in] source Original configuration
     */
    UDPConfiguration(UDPConfiguration* source);

    /*!
     * @brief Begin iteration through the list of target hosts
     *
     * @param[out] host Host name
     * @param[out] port Port number
     * @return Returns false if list is empty
     */
    bool firstHost      (QString& host, int& port);

    /*!
     * @brief Continues iteration through the list of target hosts
     *
     * @param[out] host Host name
     * @param[out] port Port number
     * @return Returns false if reached the end of the list (in which case, both host and port are unchanged)
     */
    bool nextHost       (QString& host, int& port);

    /*!
     * @brief Get the number of target hosts
     *
     * @return Number of hosts in list
     */
    int hostCount       () { return _hosts.count(); }

    /*!
     * @brief The UDP port we bind to
     *
     * @return Port number
     */
    quint16 localPort   () { return _localPort; }

    /*!
     * @brief Add a target host
     *
     * @param[in] host Host name in standard formatt, e.g. localhost:14551 or 192.168.1.1:14551
     */
    Q_INVOKABLE void addHost (const QString host);

    /*!
     * @brief Add a target host
     *
     * @param[in] host Host name, e.g. localhost or 192.168.1.1
     * @param[in] port Port number
     */
    void addHost        (const QString& host, int port);

    /*!
     * @brief Remove a target host from the list
     *
     * @param[in] host Host name, e.g. localhost or 192.168.1.1
     */
    Q_INVOKABLE void removeHost  (const QString host);

    /*!
     * @brief Set the UDP port we bind to
     *
     * @param[in] port Port number
     */
    void setLocalPort   (quint16 port);

    /*!
     * @brief QML Interface
     */
    QStringList hostList    () { return _hostList; }

    LinkType    type            () { return LinkConfiguration::TypeUdp; }
    void        copyFrom        (LinkConfiguration* source);
    void        loadSettings    (QSettings& settings, const QString& root);
    void        saveSettings    (QSettings& settings, const QString& root);
    void        updateSettings  ();
    QString     settingsURL     () { return "UdpSettings.qml"; }
signals:
    void localPortChanged   ();
    void hostListChanged    ();

private:
    void _updateHostList    ();

private:
    QMutex _confMutex;
    QMap<QString, int>::iterator _it;
    QMap<QString, int> _hosts;  ///< ("host", port)
    QStringList _hostList;      ///< Exposed to QML
pixhawk's avatar
pixhawk committed

class UDPLink : public LinkInterface
{
    Q_OBJECT
    friend class LinkManager;
pixhawk's avatar
pixhawk committed
public:
    bool isConnected() const;
    QString getName() const;
pixhawk's avatar
pixhawk committed

    // Extensive statistics for scientific purposes
    qint64 getConnectionSpeed() const;
    qint64 getCurrentInDataRate() const;
    qint64 getCurrentOutDataRate() const;
pixhawk's avatar
pixhawk committed

    void run();
    // These are left unimplemented in order to cause linker errors which indicate incorrect usage of
    // connect/disconnect on link directly. All connect/disconnect calls should be made through LinkManager.
    bool connect(void);
    bool disconnect(void);
pixhawk's avatar
pixhawk committed

    LinkConfiguration* getLinkConfiguration() { return _config; }

pixhawk's avatar
pixhawk committed
public slots:

    /*! @brief Add a new host to broadcast messages to */
    void addHost    (const QString& host);
    /*! @brief Remove a host from broadcasting messages to */
    void removeHost (const QString& host);
pixhawk's avatar
pixhawk committed

pixhawk's avatar
pixhawk committed
     * @brief Write a number of bytes to the interface.
     *
     * @param data Pointer to the data byte array
     * @param size The size of the bytes array
     **/
    void _writeBytes(const QByteArray data);
pixhawk's avatar
pixhawk committed

protected:

    QUdpSocket*         _socket;
    UDPConfiguration*   _config;
    bool                _connectState;
pixhawk's avatar
pixhawk committed

oberion's avatar
oberion committed
private:
    // Links are only created/destroyed by LinkManager so constructor/destructor is not public
    UDPLink(UDPConfiguration* config);
    ~UDPLink();
    // From LinkInterface
    virtual bool _connect(void);
Don Gagne's avatar
Don Gagne committed
    virtual void _disconnect(void);
    bool _hardwareConnect();
    void _restartConnection();
oberion's avatar
oberion committed

    void _registerZeroconf(uint16_t port, const std::string& regType);
    void _deregisterZeroconf();
Gus Grubba's avatar
Gus Grubba committed

#if defined(QGC_ZEROCONF_ENABLED)
    DNSServiceRef  _dnssServiceRef;
#endif

pixhawk's avatar
pixhawk committed
};

#endif // UDPLINK_H