DataProtocol.h 6.4 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
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  over the Internet

  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
  SoundWIRE group at CCRMA, Stanford University.
  
  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:
  
  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.
  
  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 DataProtocol.h
jcaceres's avatar
jcaceres committed
34
35
36
37
 * \author Juan-Pablo Caceres
 * \date June 2008
 */

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

jcaceres's avatar
jcaceres committed
41
42
43
//#include <sys/socket.h> //basic socket definitions
#include <netinet/in.h> //sockaddr_in{} and other Internet defns
#include <arpa/inet.h> //inet(3) functions
44
#include <netdb.h>
jcaceres's avatar
jcaceres committed
45
#include <tr1/memory> //for shared_ptr
46
47

#include <QThread>
48
#include <QHostAddress>
49

jcaceres's avatar
More    
jcaceres committed
50
#include "RingBuffer.h"
51
class PacketHeader; // forward declaration
jcaceres's avatar
jcaceres committed
52
class JackAudioInterface; //forward declaration
jcaceres's avatar
jcaceres committed
53

jcaceres's avatar
jcaceres committed
54
55

/** \brief Base class that defines the transmission protocol.
56
57
58
59
60
61
62
63
64
65
66
 * 
 * This base class defines most of the common method to setup and connect
 * sockets using the individual protocols (UDP, TCP, SCTP, etc).
 *
 * The class has to be constructed using one of two modes (runModeT):\n
 * - SENDER
 * - RECEIVER
 *
 * This has to be specified as a constructor argument. When using, create two instances
 * of the class, one to receive and one to send packets. Each instance will run on a
 * separate thread.
jcaceres's avatar
jcaceres committed
67
 *
jcaceres's avatar
jcaceres committed
68
69
70
 * Redundancy and forward error correction should be implemented on each
 * Transport protocol, cause they depend on the protocol itself
 *
jcaceres's avatar
jcaceres committed
71
 * \todo This Class should contain definition of jacktrip header and basic funcionality to obtain
jcaceres's avatar
jcaceres committed
72
73
74
 * local machine IPs and maybe functions to manipulate IPs.
 * Redundancy and forward error correction should be implemented on each
 * Transport protocol, cause they depend on the protocol itself
jcaceres's avatar
jcaceres committed
75
 *
jcaceres's avatar
jcaceres committed
76
 * \todo The transport protocol itself has to be implemented subclassing this class, i.e.,
jcaceres's avatar
jcaceres committed
77
78
79
80
81
82
83
84
 * using a TCP or UDP protocol.
 *
 * Even if the underlined transmission protocol is stream oriented (as in TCP),
 * we send packets that are the size of the audio processing buffer.
 * Use AudioInterface::getBufferSize to obtain this value.
 *
 * Each transmission (i.e., inputs and outputs) run on its own thread.
 */
85
class DataProtocol : public QThread
jcaceres's avatar
jcaceres committed
86
87
{
public:
jcaceres's avatar
jcaceres committed
88

jcaceres's avatar
jcaceres committed
89
  //----------ENUMS------------------------------------------
jcaceres's avatar
More    
jcaceres committed
90
91
92
93
94
95
  /// \brief Enum to define packet header types
  enum packetHeaderTypeT {
    DEFAULT, ///< Default application header
    JAMLINK ///< Header to use with Jamlinks
  };

jcaceres's avatar
jcaceres committed
96
97
98
99
100
  /// \brief Enum to define class modes, SENDER or RECEIVER
  enum runModeT {
    SENDER, ///< Set class as a Sender (send packets)
    RECEIVER ///< Set class as a Receiver (receives packets)
  };
jcaceres's avatar
jcaceres committed
101
  //---------------------------------------------------------
jcaceres's avatar
More    
jcaceres committed
102

jcaceres's avatar
more    
jcaceres committed
103

104
  /** \brief The class constructor 
jcaceres's avatar
more    
jcaceres committed
105
106
   * \param runmode Sets the run mode, use either DataProtocol::SENDER or
   * DataProtocol::RECEIVER
107
   */
108
109
  DataProtocol(const runModeT runmode,
	       const packetHeaderTypeT headertype = DEFAULT);
110
  
jcaceres's avatar
jcaceres committed
111
  /// \brief The class destructor
112
113
  virtual ~DataProtocol();
  
jcaceres's avatar
jcaceres committed
114
115
116
  /** \brief Set the pointer to the RingBuffer that'll be use to read 
   * or write
   */
jcaceres's avatar
jcaceres committed
117
118
  void setRingBuffer(std::tr1::shared_ptr<RingBuffer> RingBuffer)
  { mRingBuffer = RingBuffer; };
119
120
121

  /** \brief Implements the thread loop
   *
jcaceres's avatar
more    
jcaceres committed
122
123
   * Depending on the runmode, with will run a DataProtocol::SENDER thread or
   * DataProtocol::RECEIVER thread
124
   */
jcaceres's avatar
jcaceres committed
125
  virtual void run() = 0;
jcaceres's avatar
jcaceres committed
126

jcaceres's avatar
jcaceres committed
127
  /// \brief Stops the execution of the Thread
jcaceres's avatar
jcaceres committed
128
  void stop() { mStopped = true; };
jcaceres's avatar
More    
jcaceres committed
129

jcaceres's avatar
jcaceres committed
130
131
132
  /** \brief Sets the size of the audio part of the packets
   * \param size_bytes Size in bytes
   */
jcaceres's avatar
jcaceres committed
133
  void setAudioPacketSize(const size_t size_bytes){ mAudioPacketSize = size_bytes; };
jcaceres's avatar
jcaceres committed
134
135
136
137

  /** \brief Get the size of the audio part of the packets
   * \return size_bytes Size in bytes
   */
jcaceres's avatar
jcaceres committed
138
  size_t getAudioPacketSize() { return(mAudioPacketSize); };
jcaceres's avatar
jcaceres committed
139

jcaceres's avatar
more    
jcaceres committed
140
141
142
143
  /** \brief Set the peer address
   * \param peerHostOrIP IPv4 number or host name
   * \todo implement here instead of in the subclass UDP
   */
144
  virtual void setPeerAddress(char* peerHostOrIP) = 0;
jcaceres's avatar
jcaceres committed
145

146
147
  void fillHeaderCommonFromJack(const JackAudioInterface& jackaudio);

148
149
150
  virtual void getPeerAddressFromFirstPacket(QHostAddress& peerHostAddress,
					     uint16_t& port) = 0;

jcaceres's avatar
jcaceres committed
151
152
protected:

jcaceres's avatar
jcaceres committed
153
154
155
156
157
  /** \brief Get the Run Mode of the object
   * \return SENDER or RECEIVER
   */
  runModeT getRunMode() const { return mRunMode; };

jcaceres's avatar
More    
jcaceres committed
158
  /// Smart Pointer to RingBuffer to read (for SENDER) or write (for RECEIVER)
jcaceres's avatar
jcaceres committed
159
160
  std::tr1::shared_ptr<RingBuffer> mRingBuffer;

jcaceres's avatar
More    
jcaceres committed
161
162
163
164
165
166
167
  /// Boolean stop the execution of the thread
  volatile bool mStopped;
  /// Boolean to indicate if the RECEIVER is waiting to obtain peer address
  volatile bool mHasPeerAddress;
  /// Boolean that indicates if a packet was received
  volatile bool mHasPacketsToReceive;

168

169
private:
jcaceres's avatar
jcaceres committed
170
171
172
173

  int mLocalPort; ///< Local Port number to Bind
  int mPeerPort; ///< Peer Port number to Bind
  const runModeT mRunMode; ///< Run mode, either SENDER or RECEIVER
174
  
jcaceres's avatar
jcaceres committed
175
176
  struct sockaddr_in mLocalIPv4Addr; ///< Local IPv4 Address struct
  struct sockaddr_in mPeerIPv4Addr; ///< Peer IPv4 Address struct
177
  
jcaceres's avatar
jcaceres committed
178
  /// Number of clients running to check for ports already used
jcaceres's avatar
More    
jcaceres committed
179
  /// \note Unimplemented, try to find another way to check for used ports
jcaceres's avatar
jcaceres committed
180
  static int sClientsRunning;
181
  
jcaceres's avatar
jcaceres committed
182
  size_t mAudioPacketSize; ///< Packet audio part size
jcaceres's avatar
jcaceres committed
183
184
185

  /// \todo check a better way to access the header from the subclasses
protected:
jcaceres's avatar
jcaceres committed
186
  PacketHeader* mHeader; ///< Packet Header
jcaceres's avatar
jcaceres committed
187
188
189
};

#endif