blob: 7216823a143e11d47744bd331e54a26ebf330448 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 2001-2005 Federico Montesino Pouzols <fedemp@altern.org>
Alexandre Lisionddd731e2014-01-31 11:50:08 -05002//
Emeric Vigier2f625822012-08-06 11:09:52 -04003// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation; either version 2 of the License, or
6// (at your option) any later version.
Alexandre Lisionddd731e2014-01-31 11:50:08 -05007//
Emeric Vigier2f625822012-08-06 11:09:52 -04008// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
Alexandre Lisionddd731e2014-01-31 11:50:08 -050012//
Emeric Vigier2f625822012-08-06 11:09:52 -040013// You should have received a copy of the GNU General Public License
Alexandre Lisionddd731e2014-01-31 11:50:08 -050014// along with this program; if not, write to the Free Software
Emeric Vigier2f625822012-08-06 11:09:52 -040015// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Alexandre Lisionddd731e2014-01-31 11:50:08 -050016//
Emeric Vigier2f625822012-08-06 11:09:52 -040017// As a special exception, you may use this file as part of a free software
18// library without restriction. Specifically, if other files instantiate
19// templates or use macros or inline functions from this file, or you compile
20// this file and link it with other files to produce an executable, this
21// file does not by itself cause the resulting executable to be covered by
Alexandre Lisionddd731e2014-01-31 11:50:08 -050022// the GNU General Public License. This exception does not however
Emeric Vigier2f625822012-08-06 11:09:52 -040023// invalidate any other reasons why the executable file might be covered by
Alexandre Lisionddd731e2014-01-31 11:50:08 -050024// the GNU General Public License.
Emeric Vigier2f625822012-08-06 11:09:52 -040025//
26// This exception applies only to the code released under the name GNU
27// ccRTP. If you copy code from other releases into a copy of GNU
28// ccRTP, as the General Public License permits, the exception does
29// not apply to the code that you add in this way. To avoid misleading
30// anyone as to the status of such modified files, you must delete
31// this exception notice from them.
32//
33// If you write modifications of your own for GNU ccRTP, it is your choice
34// whether to permit this exception to apply to your modifications.
35// If you do not wish that, delete this exception notice.
36//
37
Alexandre Lisionddd731e2014-01-31 11:50:08 -050038#ifndef CCRTP_CHANNEL_H_
Emeric Vigier2f625822012-08-06 11:09:52 -040039#define CCRTP_CHANNEL_H_
40
41#include <ccrtp/base.h>
Alexandre Lisionddd731e2014-01-31 11:50:08 -050042#include <commoncpp/socket.h>
Emeric Vigier2f625822012-08-06 11:09:52 -040043
Alexandre Lisionddd731e2014-01-31 11:50:08 -050044#ifndef _MSWINDOWS_
Emeric Vigier2f625822012-08-06 11:09:52 -040045#include <sys/ioctl.h>
Alexandre Lisionddd731e2014-01-31 11:50:08 -050046inline size_t ccioctl(int so, int request, size_t& len)
47 { return ioctl(so,request,&len); }
Emeric Vigier2f625822012-08-06 11:09:52 -040048#else
49inline size_t ccioctl(SOCKET so, int request, size_t& len )
Alexandre Lisionddd731e2014-01-31 11:50:08 -050050{
51 unsigned long l;
52 size_t result = 0;
53 ::ioctlsocket(so,request,&l);
54 len = l;
55 return result;
Emeric Vigier2f625822012-08-06 11:09:52 -040056}
57#endif
58
Alexandre Lisionddd731e2014-01-31 11:50:08 -050059NAMESPACE_COMMONCPP
Emeric Vigier2f625822012-08-06 11:09:52 -040060
61/**
62 * @file channel.h
63 *
64 * Definition of socket classes for different underlying transport
65 * and/or network protocols that can be used to instantiate the
66 * TRTPSessionBase template.
67 **/
68
69/**
70 * @defgroup sockets Underlying transport protocol socket classes.
71 * @{
72 **/
73
74/**
75 * @class RTPBaseUDPIPv4Socket
76 * @short A UDP/IPv4 socket class targetted at RTP stacks.
77 *
78 * This class provides a flat interface that includes all the services
79 * required by an RTP stack.
80 *
81 * It can be used in two ways:
82 *
83 * To instantiate the DualSocket template, which will be used to
84 * instantiate an RTP stack template (such as TRTPSessionBase).
85 *
86 * To directly instantiate an RTP stack template (such as
87 * TRTPSessionBase).
88 *
89 * This class offers an example of the interface that other classes
90 * should provide in order to specialize the ccRTP stack for different
91 * underlying protocols.
92 *
93 * @author Federico Montesino Pouzols <fedemp@altern.org>
94 **/
95class RTPBaseUDPIPv4Socket : private UDPSocket
96{
97public:
Alexandre Lisionddd731e2014-01-31 11:50:08 -050098 /**
99 * Constructor for receiver.
100 **/
101 RTPBaseUDPIPv4Socket(const InetAddress& ia, tpport_t port) :
102 UDPSocket(ia,port)
103 { }
Emeric Vigier2f625822012-08-06 11:09:52 -0400104
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500105 inline ~RTPBaseUDPIPv4Socket()
106 { endSocket(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400107
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500108 inline bool
109 isPendingRecv(microtimeout_t timeout)
110 { return UDPSocket::isPending(UDPSocket::pendingInput, timeout); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400111
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500112 inline InetHostAddress
113 getSender(tpport_t& port) const
114 { return UDPSocket::getSender(&port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400115
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500116 inline size_t
117 recv(unsigned char* buffer, size_t len)
118 { return UDPSocket::receive(buffer, len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400119
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500120 /**
121 * Get size of next datagram waiting to be read.
122 **/
123 inline size_t
124 getNextPacketSize() const
125 { size_t len; ccioctl(UDPSocket::so,FIONREAD,len); return len; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400126
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500127 Socket::Error
128 setMulticast(bool enable)
129 { return UDPSocket::setMulticast(enable); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400130
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500131 inline Socket::Error
132 join(const InetMcastAddress& ia, uint32 iface)
133 { return UDPSocket::join(ia,iface); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400134
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500135 inline Socket::Error
136 drop(const InetMcastAddress& ia)
137 { return UDPSocket::drop(ia); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400138
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500139 inline Socket::Error
140 setTimeToLive(unsigned char ttl)
141 { return UDPSocket::setTimeToLive(ttl); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400142
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500143 /**
144 * Constructor for transmitter.
145 **/
146 RTPBaseUDPIPv4Socket() :
147 UDPSocket()
148 { }
Emeric Vigier2f625822012-08-06 11:09:52 -0400149
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500150 inline void
151 setPeer(const InetAddress &ia, tpport_t port)
152 {UDPSocket::setPeer((InetHostAddress&)ia, port);}
153
154 inline size_t
155 send(const unsigned char* const buffer, size_t len)
156 { return UDPSocket::send(buffer, len); }
157
158 inline SOCKET getRecvSocket() const
159 { return UDPSocket::so; }
160
161 // common
162 inline void
163 endSocket()
164 { UDPSocket::endSocket(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400165};
166
167/**
168 * @class DualUDPIPv4Socket
169 * @short A socket class based on two UDP/IPv4 sockets.
170 *
171 * Defines a communication channel for RTP data and/or RTCP streams.
172 * Sockets used to instantiate this template must define a framing
173 * mechanism (UDP does not need any addition, TCP does).
174 *
175 * This class implements a socket as a pair of UDP/IPv4 sockets,
176 * alllowing both transmission and reception of packets in unicast as
177 * well as multicast mode. The implementation of this class relies on
178 * the Common C++ UDPSocket class but provides the interface needed by
179 * a ccRTP stack.
180 *
181 * Normally, RTP stacks will use two objects of this class, one for
182 * RTP data packets transmission/reception and other for RTCP
183 * (control) transmission/reception.
184 *
185 * @author Federico Montesino Pouzols <fedemp@altern.org>
186 **/
187template<class BaseSocket>
188class DualRTPChannel
189{
190public:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500191 DualRTPChannel(const InetAddress& ia, tpport_t port)
192 {
193 recvSocket = new BaseSocket(ia,port);
194 sendSocket = new BaseSocket;
195 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400196
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500197 inline ~DualRTPChannel()
198 { delete sendSocket; delete recvSocket; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400199
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500200 inline bool
201 isPendingRecv(microtimeout_t timeout) const
202 { return recvSocket->isPendingRecv(timeout); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400203
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500204 inline InetHostAddress
205 getSender(tpport_t& port) const
206 { return recvSocket->getSender(port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400207
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500208 inline size_t
209 recv(unsigned char* buffer, size_t len)
210 { return recvSocket->recv(buffer, len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400211
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500212 inline size_t
213 getNextPacketSize() const
214 { return recvSocket->getNextPacketSize(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400215
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500216 inline Socket::Error
217 setMulticast(bool enable)
218 { Socket::Error error = recvSocket->setMulticast(enable);
219 if (error) return error;
220 return sendSocket->setMulticast(enable); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400221
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500222 inline Socket::Error
223 join(const InetMcastAddress& ia, uint32 iface)
224 { return recvSocket->join(ia,iface); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400225
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500226 inline Socket::Error
227 drop(const InetMcastAddress& ia)
228 { return recvSocket->drop(ia); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400229
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500230 inline Socket::Error
231 setTimeToLive(unsigned char ttl)
232 { return sendSocket->setTimeToLive(ttl); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400233
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500234 inline void
235 setPeer(const InetAddress& host, tpport_t port)
236 { sendSocket->setPeer(host,port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400237
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500238 inline size_t
239 send(const unsigned char* const buffer, size_t len)
240 { return sendSocket->send(buffer, len); }
241
242 inline SOCKET getRecvSocket() const
243 { return recvSocket->getRecvSocket(); }
244
245 // common.
246 inline void
247 endSocket()
248 { sendSocket->endSocket(); recvSocket->endSocket(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400249
250private:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500251 BaseSocket* sendSocket;
252 BaseSocket* recvSocket;
Emeric Vigier2f625822012-08-06 11:09:52 -0400253};
254
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500255#ifdef CCXX_IPV6
Emeric Vigier2f625822012-08-06 11:09:52 -0400256
257/**
258 * @class RTPBaseUDPIPv4Socket
259 * @short A UDP/IPv6 socket class targetted at RTP stacks.
260 *
261 * This class provides a flat interface that includes all the services
262 * required by an RTP stack.
263 *
264 * It can be used in two ways:
265 *
266 * To instantiate the DualSocket template, which will be used to
267 * instantiate an RTP stack template (such as TRTPSessionBaseIPV6).
268 *
269 * To directly instantiate an RTP stack template (such as
270 * TRTPSessionBaseIPV6).
271 *
272 * This class offers an example of the interface that other classes
273 * should provide in order to specialize the ccRTP stack for different
274 * underlying protocols.
275 *
276 * @author David Sugar <dyfet@gnutelephony.org>
277 **/
278class RTPBaseUDPIPv6Socket : private UDPSocket
279{
280public:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500281 /**
282 * Constructor for receiver.
283 **/
284 RTPBaseUDPIPv6Socket(const IPV6Address& ia, tpport_t port) :
285 UDPSocket(ia,port)
286 { }
Emeric Vigier2f625822012-08-06 11:09:52 -0400287
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500288 inline ~RTPBaseUDPIPv6Socket()
289 { endSocket(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400290
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500291 inline bool
292 isPendingRecv(microtimeout_t timeout)
293 { return UDPSocket::isPending(UDPSocket::pendingInput, timeout); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400294
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500295 inline IPV6Host
296 getSender(tpport_t& port) const
297 { return UDPSocket::getIPV6Sender(&port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400298
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500299 inline size_t
300 recv(unsigned char* buffer, size_t len)
301 { return UDPSocket::receive(buffer, len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400302
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500303 /**
304 * Get size of next datagram waiting to be read.
305 **/
306 inline size_t
307 getNextPacketSize() const
308 { size_t len; ccioctl(UDPSocket::so,FIONREAD,len); return len; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400309
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500310 Socket::Error
311 setMulticast(bool enable)
312 { return UDPSocket::setMulticast(enable); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400313
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500314 inline Socket::Error
315 join(const IPV6Multicast& ia, uint32 iface)
316 { return Socket::join(ia); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400317
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500318 inline Socket::Error
319 drop(const IPV6Multicast& ia)
320 { return UDPSocket::drop(ia); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400321
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500322 inline Socket::Error
323 setTimeToLive(unsigned char ttl)
324 { return UDPSocket::setTimeToLive(ttl); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400325
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500326 /**
327 * Constructor for transmitter.
328 **/
329 RTPBaseUDPIPv6Socket() :
330 UDPSocket()
331 { }
Emeric Vigier2f625822012-08-06 11:09:52 -0400332
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500333 inline void
334 setPeer(const IPV6Host &ia, tpport_t port)
335 {UDPSocket::setPeer(ia, port);}
336
337 inline size_t
338 send(const unsigned char* const buffer, size_t len)
339 { return UDPSocket::send(buffer, len); }
340
341 inline SOCKET getRecvSocket() const
342 { return UDPSocket::so; }
343
344 // common
345 inline void
346 endSocket()
347 { UDPSocket::endSocket(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400348};
349
350/**
351 * @class DualUDPIPv6Socket
352 * @short A socket class based on two UDP/IPv6 sockets.
353 *
354 * Defines a communication channel for RTP data and/or RTCP streams.
355 * Sockets used to instantiate this template must define a framing
356 * mechanism (UDP does not need any addition, TCP does).
357 *
358 * This class implements a socket as a pair of UDP/IPv6 sockets,
359 * alllowing both transmission and reception of packets in unicast as
360 * well as multicast mode. The implementation of this class relies on
361 * the Common C++ UDPSocket class but provides the interface needed by
362 * a ccRTP stack.
363 *
364 * Normally, RTP stacks will use two objects of this class, one for
365 * RTP data packets transmission/reception and other for RTCP
366 * (control) transmission/reception.
367 *
368 * @author David Sugar <dyfet@gnutelephony.org>
369 **/
370template<class BaseSocket>
371class DualRTPChannelIPV6
372{
373public:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500374 DualRTPChannelIPV6(const IPV6Host& ia, tpport_t port)
375 {
376 recvSocket = new BaseSocket(ia,port);
377 sendSocket = new BaseSocket;
378 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400379
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500380 inline ~DualRTPChannelIPV6()
381 { delete sendSocket; delete recvSocket; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400382
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500383 inline bool
384 isPendingRecv(microtimeout_t timeout) const
385 { return recvSocket->isPendingRecv(timeout); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400386
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500387 inline IPV6Host
388 getSender(tpport_t& port) const
389 { return recvSocket->getIPV6Sender(port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400390
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500391 inline size_t
392 recv(unsigned char* buffer, size_t len)
393 { return recvSocket->recv(buffer, len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400394
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500395 inline size_t
396 getNextPacketSize() const
397 { return recvSocket->getNextPacketSize(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400398
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500399 inline Socket::Error
400 setMulticast(bool enable)
401 { Socket::Error error = recvSocket->setMulticast(enable);
402 if (error) return error;
403 return sendSocket->setMulticast(enable); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400404
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500405 inline Socket::Error
406 join(const IPV6Multicast& ia, uint32 iface)
407 { return recvSocket->join(ia,iface); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400408
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500409 inline Socket::Error
410 drop(const IPV6Multicast& ia)
411 { return recvSocket->drop(ia); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400412
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500413 inline Socket::Error
414 setTimeToLive(unsigned char ttl)
415 { return sendSocket->setTimeToLive(ttl); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400416
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500417 inline void
418 setPeer(const IPV6Host& host, tpport_t port)
419 { sendSocket->setPeer(host,port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400420
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500421 inline size_t
422 send(const unsigned char* const buffer, size_t len)
423 { return sendSocket->send(buffer, len); }
424
425 inline SOCKET getRecvSocket() const
426 { return recvSocket->getRecvSocket(); }
427
428 // common.
429 inline void
430 endSocket()
431 { sendSocket->endSocket(); recvSocket->endSocket(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400432
433private:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500434 BaseSocket* sendSocket;
435 BaseSocket* recvSocket;
Emeric Vigier2f625822012-08-06 11:09:52 -0400436};
437
438
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500439typedef DualRTPChannelIPV6<RTPBaseUDPIPv6Socket> DualRTPUDPIPv6Channel;
440typedef RTPBaseUDPIPv6Socket SingleRTPChannelIPV6;
Emeric Vigier2f625822012-08-06 11:09:52 -0400441typedef SingleRTPChannelIPV6 SymmetricRTPChannelIPV6;
442
443#endif
444
445typedef DualRTPChannel<RTPBaseUDPIPv4Socket> DualRTPUDPIPv4Channel;
446
447/**
448 * May be used in applications where using the same socket for both
449 * sending and receiving is not a limitation.
450 **/
451typedef RTPBaseUDPIPv4Socket SingleRTPChannel;
452
453/**
454 * Actually, RTP with a single channel can be called 'Symmetric RTP'
455 **/
456typedef SingleRTPChannel SymmetricRTPChannel;
457
458/** @}*/ // sockets
459
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500460END_NAMESPACE
Emeric Vigier2f625822012-08-06 11:09:52 -0400461
462#endif //CCRTP_CHANNEL_H_
463
464/** EMACS **
465 * Local variables:
466 * mode: c++
467 * c-basic-offset: 8
468 * End:
469 */