UdpDataProtocol.h 7.81 KB
Newer Older
jcaceres's avatar
jcaceres committed
1
2
//*****************************************************************
/*
jcaceres's avatar
jcaceres committed
3
  JackTrip: A System for High-Quality Audio Network Performance
jcaceres's avatar
jcaceres committed
4
5
6
7
  over the Internet

  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
  SoundWIRE group at CCRMA, Stanford University.
8

jcaceres's avatar
jcaceres committed
9
10
11
12
13
14
15
16
  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:
17

jcaceres's avatar
jcaceres committed
18
19
  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.
20

jcaceres's avatar
jcaceres committed
21
22
23
24
25
26
27
28
29
30
31
32
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*/
//*****************************************************************

/**
jcaceres's avatar
jcaceres committed
33
 * \file UdpDataProtocol.h
jcaceres's avatar
jcaceres committed
34
35
36
37
 * \author Juan-Pablo Caceres
 * \date June 2008
 */

jcaceres's avatar
jcaceres committed
38
#ifndef __UDPDATAPROTOCOL_H__
39
40
#define __UDPDATAPROTOCOL_H__

41
42
#include <stdexcept>

43
44
45
#include <QThread>
#include <QUdpSocket>
#include <QHostAddress>
46
#include <QMutex>
jcaceres's avatar
jcaceres committed
47

jcaceres's avatar
jcaceres committed
48
#include "DataProtocol.h"
jcacerec's avatar
jcacerec committed
49
#include "jacktrip_types.h"
50
#include "jacktrip_globals.h"
51

52
/** \brief UDP implementation of DataProtocol class
53
54
55
56
57
58
 *
 * The class has a <tt>bind port</tt> and a <tt>peer port</tt>. The meaning of these
 * depends on the runModeT. If it's a SENDER, <tt>bind port</tt> is the source port and
 * <tt>peer port</tt> is the destination port for each UDP packet. If it's a RECEIVER,
 * the <tt>bind port</tt> destination port (for incoming packets) and the <tt>peer port</tt>
 * is the source port.
59
60
61
62
63
64
 *
 * The SENDER and RECEIVER socket can share the same port/address pair (for compatibility
 * with the JamLink boxes). This is achieved setting
 * the resusable property in the socket for address and port. You have to
 * externaly check if the port is already binded if you want to avoid re-binding to the
 * same port.
65
 */
66
class UdpDataProtocol : public DataProtocol
jcaceres's avatar
jcaceres committed
67
{
68
69
    Q_OBJECT;

jcaceres's avatar
jcaceres committed
70
public:
71
72

    /** \brief The class constructor
73
   * \param jacktrip Pointer to the JackTrip class that connects all classes (mediator)
74
   * \param runmode Sets the run mode, use either SENDER or RECEIVER
jcacerec's avatar
jcacerec committed
75
76
77
   * \param bind_port Port number to bind for this socket (this is the receive or send port depending on the runmode)
   * \param peer_port Peer port number (this is the receive or send port depending on the runmode)
   * \param udp_redundancy_factor Number of redundant packets
78
   */
79
80
81
82
83
    UdpDataProtocol(JackTrip* jacktrip, const runModeT runmode,
                    int bind_port, int peer_port,
                    unsigned int udp_redundancy_factor = 1);

    /** \brief The class destructor
84
   */
85
    virtual ~UdpDataProtocol();
jcaceres's avatar
more    
jcaceres committed
86

87
    /** \brief Set the Peer address to connect to
88
89
   * \param peerHostOrIP IPv4 number or host name
   */
90
    void setPeerAddress(const char* peerHostOrIP);
91

Aaron Wyatt's avatar
Aaron Wyatt committed
92
#if defined (__WIN_32__)
93
    void setSocket(SOCKET &socket);
Aaron Wyatt's avatar
Aaron Wyatt committed
94
#else
95
    void setSocket(int &socket);
Aaron Wyatt's avatar
Aaron Wyatt committed
96
#endif
Aaron Wyatt's avatar
Aaron Wyatt committed
97

98
    /** \brief Receives a packet. It blocks until a packet is received
jcaceres's avatar
more    
jcaceres committed
99
100
101
102
103
104
105
   *
   * This function makes sure we recieve a complete packet
   * of size n
   * \param buf Buffer to store the recieved packet
   * \param n size of packet to receive
   * \return number of bytes read, -1 on error
   */
106
    //virtual int receivePacket(char* buf, const size_t n);
Aaron Wyatt's avatar
Aaron Wyatt committed
107
    virtual int receivePacket(QUdpSocket& UdpSocket, char* buf, const size_t n);
108
109

    /** \brief Sends a packet
jcaceres's avatar
more    
jcaceres committed
110
111
112
   *
   * This function meakes sure we send a complete packet
   * of size n
113
   * \param buf Buffer to send
jcaceres's avatar
more    
jcaceres committed
114
115
116
   * \param n size of packet to receive
   * \return number of bytes read, -1 on error
   */
Aaron Wyatt's avatar
Aaron Wyatt committed
117
    virtual int sendPacket(const char* buf, const size_t n);
118
119

    /** \brief Obtains the peer address from the first UDP packet received. This address
120
121
122
123
   * is used by the SERVER mode to connect back to the client.
   * \param peerHostAddress QHostAddress to store the peer address
   * \param port Receiving port
   */
Aaron Wyatt's avatar
Aaron Wyatt committed
124
    virtual void getPeerAddressFromFirstPacket(QUdpSocket& UdpSocket,
125
126
                                               QHostAddress& peerHostAddress,
                                               uint16_t& port);
127

128
    /** \brief Sets the bind port number
129
    */
130
131
    void setBindPort(int port)
    { mBindPort = port; }
132

133
    /** \brief Sets the peer port number
134
    */
135
    void setPeerPort(int port)
Aaron Wyatt's avatar
Aaron Wyatt committed
136
    { mPeerPort = port; mPeerAddr.sin_port = htons(mPeerPort); mPeerAddr6.sin6_port = htons(mPeerPort); }
jcacerec's avatar
jcacerec committed
137

138
    /** \brief Implements the Thread Loop. To start the thread, call start()
139
   * ( DO NOT CALL run() )
140
141
   *
   * This function creats and binds all the socket and start the connection loop thread.
142
   */
143
    virtual void run();
144

145
    virtual bool getStats(PktStat* stat);
jcaceres's avatar
jcaceres committed
146

147
private slots:
148
    void printUdpWaitedTooLong(int wait_msec);
149
150


151
signals:
152

153
154
    /// \brief Signals when waiting every 10 milliseconds, with the total wait on wait_msec
    /// \param wait_msec Total wait in milliseconds
155
    void signalWaitingTooLong(int wait_msec);
156

157

158
    //private:
jcacerec's avatar
jcacerec committed
159
protected:
jcaceres's avatar
jcaceres committed
160

161
    /** \brief Binds the UDP socket to the available address and specified port
jcaceres's avatar
jcaceres committed
162
   */
Aaron Wyatt's avatar
Aaron Wyatt committed
163
#if defined (__WIN_32__)
164
    SOCKET bindSocket();
Aaron Wyatt's avatar
Aaron Wyatt committed
165
#else
166
    int bindSocket();
Aaron Wyatt's avatar
Aaron Wyatt committed
167
#endif
168
169

    /** \brief This function blocks until data is available for reading in the
170
171
172
173
174
175
176
177
   * QUdpSocket. The function will timeout after timeout_msec microseconds.
   *
   * This function is intended to replace QAbstractSocket::waitForReadyRead which has
   * some problems with multithreading.
   *
   * \return returns true if there is data available for reading;
   * otherwise it returns false (if an error occurred or the operation timed out)
   */
Aaron Wyatt's avatar
Aaron Wyatt committed
178
    void waitForReady(QUdpSocket& UdpSocket, int timeout_msec);
jcaceres's avatar
jcaceres committed
179

180
    /** \brief Redundancy algorythm at the receiving end
181
    */
Aaron Wyatt's avatar
Aaron Wyatt committed
182
    virtual void receivePacketRedundancy(QUdpSocket& UdpSocket,
183
184
185
186
187
188
189
190
                                         int8_t* full_redundant_packet,
                                         int full_redundant_packet_size,
                                         int full_packet_size,
                                         uint16_t& current_seq_num,
                                         uint16_t& last_seq_num,
                                         uint16_t& newer_seq_num);

    /** \brief Redundancy algorythm at the sender's end
191
    */
Aaron Wyatt's avatar
Aaron Wyatt committed
192
    virtual void sendPacketRedundancy(int8_t* full_redundant_packet,
193
194
                                      int full_redundant_packet_size,
                                      int full_packet_size);
195

196
197
198

private:

199
200
201
    int mBindPort; ///< Local Port number to Bind
    int mPeerPort; ///< Peer Port number
    const runModeT mRunMode; ///< Run mode, either SENDER or RECEIVER
Aaron Wyatt's avatar
Aaron Wyatt committed
202
    bool mIPv6; /// Use IPv6
203

204
    QHostAddress mPeerAddress; ///< The Peer Address
Aaron Wyatt's avatar
Aaron Wyatt committed
205
206
    struct sockaddr_in mPeerAddr;
    struct sockaddr_in6 mPeerAddr6;
Aaron Wyatt's avatar
Aaron Wyatt committed
207
208
209
210
211
#if defined (__WIN_32__)
    SOCKET mSocket;
#else
    int mSocket;
#endif
212

213
214
    int8_t* mAudioPacket; ///< Buffer to store Audio Packets
    int8_t* mFullPacket; ///< Buffer to store Full Packet (audio+header)
jcacerec's avatar
jcacerec committed
215

216
217
    unsigned int mUdpRedundancyFactor; ///< Factor of redundancy
    static QMutex sUdpMutex; ///< Mutex to make thread safe the binding process
218
219
220
221
222
223

    std::atomic<uint32_t>  mTotCount;
    std::atomic<uint32_t>  mLostCount;
    std::atomic<uint32_t>  mOutOfOrderCount;
    std::atomic<uint32_t>  mRevivedCount;
    uint32_t  mStatCount;
jcaceres's avatar
jcaceres committed
224
225
};

226
#endif // __UDPDATAPROTOCOL_H__