SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
rtpudptransmitter.cpp
Go to the documentation of this file.
1 /*
2 
3  This file is a part of JRTPLIB
4  Copyright (c) 1999-2017 Jori Liesenborgs
5 
6  Contact: jori.liesenborgs@gmail.com
7 
8  This library was developed at the Expertise Centre for Digital Media
9  (http://www.edm.uhasselt.be), a research center of the Hasselt University
10  (http://www.uhasselt.be). The library is based upon work done for
11  my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
12 
13  Permission is hereby granted, free of charge, to any person obtaining a
14  copy of this software and associated documentation files (the "Software"),
15  to deal in the Software without restriction, including without limitation
16  the rights to use, copy, modify, merge, publish, distribute, sublicense,
17  and/or sell copies of the Software, and to permit persons to whom the
18  Software is furnished to do so, subject to the following conditions:
19 
20  The above copyright notice and this permission notice shall be included
21  in all copies or substantial portions of the Software.
22 
23  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29  IN THE SOFTWARE.
30 
31  */
32 
33 #include "rtpudptransmitter.h"
34 #include "rtperrors.h"
35 #include "rtpaddress.h"
36 #include "rtpstructs.h"
37 #include "rtprawpacket.h"
38 
39 #include <QUdpSocket>
40 
41 namespace qrtplib
42 {
43 
45  m_rawPacketQueueLock(QMutex::Recursive)
46 {
47  m_created = false;
48  m_init = false;
49  m_rtcpsock = 0;
50  m_rtpsock = 0;
52  m_waitingfordata = false;
53  m_rtcpPort = 0;
54  m_rtpPort = 0;
56  m_maxpacksize = 0;
59 }
60 
62 {
63  Destroy();
64 }
65 
67 {
68  if (m_init) {
70  }
71 
72  m_init = true;
73  return 0;
74 }
75 
76 int RTPUDPTransmitter::Create(std::size_t maximumpacketsize, const RTPTransmissionParams *transparams)
77 {
78  const RTPUDPTransmissionParams *params, defaultparams;
79  qint64 size;
80 
81  if (maximumpacketsize > m_absoluteMaxPackSize) {
83  }
84 
85  if (!m_init) {
87  }
88 
89  if (m_created) {
91  }
92 
93  // Obtain transmission parameters
94 
95  if (transparams == 0) {
96  params = &defaultparams;
97  }
98  else
99  {
101  {
103  }
104  params = (const RTPUDPTransmissionParams *) transparams;
105  }
106 
107  // Determine the port numbers
108 
109  m_localIP = params->GetBindIP();
110 
111  if (params->GetAllowOddPortbase())
112  {
113  m_rtpPort = params->GetPortbase();
114  m_rtcpPort = params->GetForcedRTCPPort();
115  }
116  else
117  {
118  if (params->GetPortbase() % 2 == 0)
119  {
120  m_rtpPort = params->GetPortbase();
121  m_rtcpPort = m_rtpPort + 1;
122  }
123  else
124  {
126  }
127  }
128 
130  {
131  m_deletesocketswhendone = false;
132  }
133  else
134  {
136 
137  m_rtpsock = new QUdpSocket();
138 
139  // If we're multiplexing, we're just going to set the RTCP socket to equal the RTP socket
140  if (params->GetRTCPMultiplexing())
141  {
144  } else {
145  m_rtcpsock = new QUdpSocket();
146  }
147  }
148 
149  // set socket buffer sizes
150 
151  size = params->GetRTPReceiveBufferSize();
152  m_rtpsock->setReadBufferSize(size);
153 
154  if (m_rtpsock != m_rtcpsock)
155  {
156  size = params->GetRTCPReceiveBufferSize();
157  m_rtcpsock->setReadBufferSize(size);
158  }
159 
160  m_maxpacksize = maximumpacketsize;
163 
164  m_waitingfordata = false;
165  m_created = true;
166 
167  return 0;
168 }
169 
171 {
172  if (!m_rtpsock->bind(m_localIP, m_rtpPort)) {
174  }
175 
176  connect(m_rtpsock, SIGNAL(readyRead()), this, SLOT(readRTPPendingDatagrams()));
177 
178  if (m_rtpsock != m_rtcpsock)
179  {
180  if (!m_rtcpsock->bind(m_localIP, m_rtcpPort)) {
182  }
183 
184  connect(m_rtcpsock, SIGNAL(readyRead()), this, SLOT(readRTCPPendingDatagrams()));
185  }
186 
187  return 0;
188 }
189 
191 {
192  if (!m_init) {
193  return;
194  }
195 
196  if (!m_created)
197  {
198  return;
199  }
200 
202  {
203  if (m_rtpsock != m_rtcpsock) {
204  delete m_rtcpsock;
205  }
206 
207  delete m_rtpsock;
208  }
209 
210  m_created = false;
211 }
212 
214 {
215  if (!m_init) {
216  return 0;
217  }
218 
220 
221  return tinf;
222 }
223 
225 {
226  if (!m_init) {
227  return;
228  }
229 
230  delete inf;
231 }
232 
234 {
235  if (addr.getAddress() != m_localIP) {
236  return false;
237  }
238 
239  return (addr.getPort() == m_rtpPort) && (addr.getRtcpsendport() == m_rtcpPort);
240 }
241 
242 int RTPUDPTransmitter::SendRTPData(const void *data, std::size_t len)
243 {
244  if (!m_init) {
246  }
247 
248  if (!m_created) {
250  }
251 
252  if (len > m_maxpacksize)
253  {
255  }
256 
257  std::list<RTPAddress>::const_iterator it = m_destinations.begin();
258 
259  for (; it != m_destinations.end(); ++it)
260  {
261  m_rtpsock->writeDatagram((const char*) data, (qint64) len, it->getAddress(), it->getPort());
262  }
263 
264  return 0;
265 }
266 
267 int RTPUDPTransmitter::SendRTCPData(const void *data, std::size_t len)
268 {
269  if (!m_init) {
271  }
272 
273  if (!m_created) {
275  }
276 
277  if (len > m_maxpacksize) {
279  }
280 
281  std::list<RTPAddress>::const_iterator it = m_destinations.begin();
282 
283  for (; it != m_destinations.end(); ++it)
284  {
285  m_rtcpsock->writeDatagram((const char*) data, (qint64) len, it->getAddress(), it->getRtcpsendport());
286  }
287 
288  return 0;
289 }
290 
292 {
293  m_destinations.push_back(addr);
294  return 0;
295 }
296 
298 {
299  m_destinations.remove(addr);
300  return 0;
301 }
302 
304 {
305  m_destinations.clear();
306 }
307 
309 {
310  QNetworkInterface::InterfaceFlags flags = m_multicastInterface.flags();
311  QAbstractSocket::SocketState rtpSocketState = m_rtpsock->state();
312  QAbstractSocket::SocketState rtcpSocketState = m_rtcpsock->state();
313  return m_multicastInterface.isValid()
314  && (rtpSocketState & QAbstractSocket::BoundState)
315  && (rtcpSocketState & QAbstractSocket::BoundState)
316  && (flags & QNetworkInterface::CanMulticast)
317  && (flags & QNetworkInterface::IsRunning)
318  && !(flags & QNetworkInterface::IsLoopBack);
319 }
320 
322 {
323  if (!m_init) {
325  }
326 
327  if (!m_created) {
329  }
330 
331  if (!SupportsMulticasting()) {
333  }
334 
335  if (m_rtpsock->joinMulticastGroup(addr.getAddress(), m_multicastInterface))
336  {
337  if (m_rtpsock != m_rtcpsock)
338  {
339  if (!m_rtcpsock->joinMulticastGroup(addr.getAddress(), m_multicastInterface)) {
341  }
342  }
343  }
344  else
345  {
347  }
348 
349  return 0;
350 }
351 
353 {
354  if (!m_init) {
356  }
357 
358  if (!m_created) {
360  }
361 
362  if (!SupportsMulticasting()) {
364  }
365 
366  m_rtpsock->leaveMulticastGroup(addr.getAddress());
367 
368  if (m_rtpsock != m_rtcpsock)
369  {
370  m_rtcpsock->leaveMulticastGroup(addr.getAddress());
371  }
372 
373  return 0;
374 }
375 
377 {
378  if (!m_init) {
380  }
381 
382  if (!m_created) {
384  }
385 
386  if (m != m_receivemode) {
387  m_receivemode = m;
388  }
389 
390  return 0;
391 }
392 
394 {
395  m_ignoreList.push_back(addr);
396  return 0;
397 }
398 
400 {
401  m_ignoreList.remove(addr);
402  return 0;
403 }
404 
406 {
407  m_ignoreList.clear();
408 }
409 
411 {
412  m_acceptList.push_back(addr);
413  return 0;
414 }
415 
417 {
418  m_acceptList.remove(addr);
419  return 0;
420 }
421 
423 {
424  m_acceptList.clear();
425 }
426 
428 {
429  if (!m_init) {
431  }
432 
433  if (!m_created) {
435  }
436 
437  if (s > m_absoluteMaxPackSize) {
439  }
440 
441  m_maxpacksize = s;
442  return 0;
443 }
444 
446 {
447  QMutexLocker locker(&m_rawPacketQueueLock);
448 
449  if (m_rawPacketQueue.isEmpty()) {
450  return 0;
451  } else {
452  return m_rawPacketQueue.takeFirst();
453  }
454 }
455 
457 {
458  while (m_rtpsock->hasPendingDatagrams())
459  {
460  RTPTime curtime = RTPTime::CurrentTime();
461  QHostAddress remoteAddress;
462  quint16 remotePort;
463  qint64 pendingDataSize = m_rtpsock->pendingDatagramSize();
464  qint64 bytesRead = m_rtpsock->readDatagram(m_rtpBuffer, pendingDataSize, &remoteAddress, &remotePort);
465  qDebug("RTPUDPTransmitter::readRTPPendingDatagrams: %lld bytes read from %s:%d",
466  bytesRead,
467  qPrintable(remoteAddress.toString()),
468  remotePort);
469 
470  RTPAddress rtpAddress;
471  rtpAddress.setAddress(remoteAddress);
472  rtpAddress.setPort(remotePort);
473 
474  if (ShouldAcceptData(rtpAddress))
475  {
476  bool isrtp = true;
477 
478  if (m_rtpsock == m_rtcpsock) // check payload type when multiplexing
479  {
480  if ((std::size_t) bytesRead > sizeof(RTCPCommonHeader))
481  {
483  uint8_t packettype = rtcpheader->packettype;
484 
485  if (packettype >= 200 && packettype <= 204) {
486  isrtp = false;
487  }
488  }
489  }
490 
491  RTPRawPacket *pack = new RTPRawPacket((uint8_t *) m_rtpBuffer, bytesRead, rtpAddress, curtime, isrtp);
492 
493  m_rawPacketQueueLock.lock();
494  m_rawPacketQueue.append(pack);
495  m_rawPacketQueueLock.unlock();
496 
497  emit NewDataAvailable();
498  }
499  }
500 }
501 
503 {
504  while (m_rtcpsock->hasPendingDatagrams())
505  {
506  RTPTime curtime = RTPTime::CurrentTime();
507  QHostAddress remoteAddress;
508  quint16 remotePort;
509  qint64 pendingDataSize = m_rtcpsock->pendingDatagramSize();
510  qint64 bytesRead = m_rtcpsock->readDatagram(m_rtcpBuffer, pendingDataSize, &remoteAddress, &remotePort);
511  qDebug("RTPUDPTransmitter::readRTCPPendingDatagrams: %lld bytes read from %s:%d",
512  bytesRead,
513  qPrintable(remoteAddress.toString()),
514  remotePort);
515 
516  RTPAddress rtpAddress;
517  rtpAddress.setAddress(remoteAddress);
518  rtpAddress.setPort(remotePort);
519 
520  if (ShouldAcceptData(rtpAddress))
521  {
522  RTPRawPacket *pack = new RTPRawPacket((uint8_t *) m_rtcpBuffer, bytesRead, rtpAddress, curtime, false);
523 
524  m_rawPacketQueueLock.lock();
525  m_rawPacketQueue.append(pack);
526  m_rawPacketQueueLock.unlock();
527 
528  emit NewDataAvailable();
529  }
530  }
531 }
532 
534 {
536  {
537  return true;
538  }
540  {
541  std::list<RTPAddress>::iterator findIt = std::find(m_acceptList.begin(), m_acceptList.end(), rtpAddress);
542  return findIt != m_acceptList.end();
543  }
544  else // this is RTPTransmitter::IgnoreSome
545  {
546  std::list<RTPAddress>::iterator findIt = std::find(m_ignoreList.begin(), m_ignoreList.end(), rtpAddress);
547  return findIt == m_ignoreList.end();
548  }
549 }
550 
551 } // namespace
552 
553 
virtual bool ComesFromThisTransmitter(const RTPAddress &addr)
void setPort(uint16_t port)
Definition: rtpaddress.h:118
std::list< RTPAddress > m_destinations
#define ERR_RTP_UDPV4TRANS_ILLEGALPARAMETERS
Definition: rtperrors.h:135
std::list< RTPAddress > m_ignoreList
QQueue< RTPRawPacket * > m_rawPacketQueue
void setAddress(const QHostAddress &address)
Definition: rtpaddress.h:106
#define ERR_RTP_UDPV6TRANS_NOMULTICASTSUPPORT
Definition: rtperrors.h:162
#define ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP
Definition: rtperrors.h:133
virtual int AddDestination(const RTPAddress &addr)
bool GetUseExistingSockets(QUdpSocket **rtpsocket, QUdpSocket **rtcpsocket) const
virtual int SetMaximumPacketSize(std::size_t s)
virtual RTPTransmissionInfo * GetTransmissionInfo()
RTPTransmitter::ReceiveMode m_receivemode
virtual int SendRTPData(const void *data, std::size_t len)
virtual int DeleteFromAcceptList(const RTPAddress &addr)
virtual int Create(std::size_t maxpacksize, const RTPTransmissionParams *transparams)
QNetworkInterface m_multicastInterface
from parameters multicast interface
#define ERR_RTP_UDPV4TRANS_NOTINIT
Definition: rtperrors.h:142
char m_rtpBuffer[m_absoluteMaxPackSize]
uint16_t getPort() const
Definition: rtpaddress.h:112
RTPTransmitter::TransmissionProtocol GetTransmissionProtocol() const
bool ShouldAcceptData(const RTPAddress &address)
unsigned char uint8_t
Definition: rtptypes_win.h:42
const QHostAddress & getAddress() const
Definition: rtpaddress.h:100
QHostAddress m_localIP
from parameters bind IP
virtual int AddToAcceptList(const RTPAddress &addr)
virtual int DeleteDestination(const RTPAddress &addr)
#define ERR_RTP_UDPV4TRANS_PORTBASENOTEVEN
Definition: rtperrors.h:144
virtual int AddToIgnoreList(const RTPAddress &addr)
QNetworkInterface GetMulticastInterface() const
char m_rtcpBuffer[m_absoluteMaxPackSize]
virtual int LeaveMulticastGroup(const RTPAddress &addr)
virtual int SendRTCPData(const void *data, std::size_t len)
std::list< RTPAddress > m_acceptList
#define ERR_RTP_UDPV4TRANS_CANTBINDRTPSOCKET
Definition: rtperrors.h:126
static RTPTime CurrentTime()
#define ERR_RTP_UDPV4TRANS_ALREADYCREATED
Definition: rtperrors.h:122
static const std::size_t m_absoluteMaxPackSize
virtual void DeleteTransmissionInfo(RTPTransmissionInfo *inf)
uint16_t getRtcpsendport() const
Definition: rtpaddress.h:124
virtual RTPRawPacket * GetNextPacket()
#define ERR_RTP_UDPV4TRANS_CANTBINDRTCPSOCKET
Definition: rtperrors.h:125
#define ERR_RTP_UDPV4TRANS_ALREADYINIT
Definition: rtperrors.h:123
virtual int JoinMulticastGroup(const RTPAddress &addr)
#define ERR_RTP_UDPV4TRANS_NOTCREATED
Definition: rtperrors.h:141
virtual int DeleteFromIgnoreList(const RTPAddress &addr)
virtual int SetReceiveMode(RTPTransmitter::ReceiveMode m)
#define ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG
Definition: rtperrors.h:145