blob: 3d9bbbccf4e0a89967fcb0c5cf73e4e1302015e6 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 2001,2002,2004,2005 Federico Montesino Pouzols <fedemp@altern.org>.
2//
3// 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.
7//
8// 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.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program; if not, write to the Free Software
15// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16//
17// 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
22// the GNU General Public License. This exception does not however
23// invalidate any other reasons why the executable file might be covered by
24// the GNU General Public License.
25//
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
38/**
39 * @file oqueue.h
40 *
41 * @short Generic RTP output queues.
42 **/
43
44#ifndef CCXX_RTP_OQUEUE_H_
45#define CCXX_RTP_OQUEUE_H_
46
47#include <ccrtp/queuebase.h>
48#include <ccrtp/CryptoContext.h>
49#include <list>
50
51#ifdef CCXX_NAMESPACES
52namespace ost {
53#endif
54
55/**
56 * @defgroup oqueue Generic RTP output queues.
57 * @{
58 **/
59
60/**
61 * @class DestinationListHandler
62 *
63 * This class handles a list of destination addresses. Stores network
64 * addresses as InetAddress objects.
65 *
66 * @author Federico Montesino Pouzols <fedemp@altern.org>
67 **/
68class __EXPORT DestinationListHandler
69{
70protected:
71 struct TransportAddress;
72 std::list<TransportAddress*> destList;
73
74public:
75 DestinationListHandler();
76
77 ~DestinationListHandler();
78
79 /**
80 * Get whether there is only a destination in the list.
81 **/
82 inline bool isSingleDestination() const
83 { return (1 == destList.size()); }
84
85 inline TransportAddress* getFirstDestination() const
86 { return destList.front(); }
87
88 inline void lockDestinationList() const
89 { destinationLock.readLock(); }
90
91 inline void unlockDestinationList() const
92 { destinationLock.unlock(); }
93
94protected:
95 inline void writeLockDestinationList() const
96 { destinationLock.writeLock(); }
97
98 /**
99 * Locks the object before modifying it.
100 **/
101 bool
102 addDestinationToList(const InetAddress& ia, tpport_t data,
103 tpport_t control);
104
105 /**
106 * Locks the object before modifying it.
107 **/
108 bool removeDestinationFromList(const InetAddress& ia,
109 tpport_t dataPort,
110 tpport_t controlPort);
111
112 struct TransportAddress
113 {
114 TransportAddress(InetAddress na, tpport_t dtp, tpport_t ctp) :
115 networkAddress(na), dataTransportPort(dtp),
116 controlTransportPort(ctp)
117 { }
118
119 inline const InetAddress& getNetworkAddress() const
120 { return networkAddress; }
121
122 inline tpport_t getDataTransportPort() const
123 { return dataTransportPort; }
124
125 inline tpport_t getControlTransportPort() const
126 { return controlTransportPort; }
127
128 InetAddress networkAddress;
129 tpport_t dataTransportPort, controlTransportPort;
130 };
131
132private:
133 mutable ThreadLock destinationLock;
134};
135
136#ifdef CCXX_IPV6
137/**
138 * @class DestinationListHandler
139 *
140 * This class handles a list of destination addresses. Stores network
141 * addresses as InetAddress objects.
142 *
143 * @author Federico Montesino Pouzols <fedemp@altern.org>
144 **/
145class __EXPORT DestinationListHandlerIPV6
146{
147protected:
148 struct TransportAddressIPV6;
149 std::list<TransportAddressIPV6*> destListIPV6;
150
151public:
152 DestinationListHandlerIPV6();
153
154 ~DestinationListHandlerIPV6();
155
156 /**
157 * Get whether there is only a destination in the list.
158 **/
159 inline bool isSingleDestinationIPV6() const
160 { return (1 == destListIPV6.size()); }
161
162 inline TransportAddressIPV6* getFirstDestinationIPV6() const
163 { return destListIPV6.front(); }
164
165 inline void lockDestinationListIPV6() const
166 { destinationLock.readLock(); }
167
168 inline void unlockDestinationListIPV6() const
169 { destinationLock.unlock(); }
170
171protected:
172 inline void writeLockDestinationListIPV6() const
173 { destinationLock.writeLock(); }
174
175 /**
176 * Locks the object before modifying it.
177 **/
178 bool
179 addDestinationToListIPV6(const IPV6Address& ia, tpport_t data,
180 tpport_t control);
181
182 /**
183 * Locks the object before modifying it.
184 **/
185 bool removeDestinationFromListIPV6(const IPV6Address& ia,
186 tpport_t dataPort,
187 tpport_t controlPort);
188
189 struct TransportAddressIPV6
190 {
191 TransportAddressIPV6(IPV6Address na, tpport_t dtp, tpport_t ctp) :
192 networkAddress(na), dataTransportPort(dtp),
193 controlTransportPort(ctp)
194 { }
195
196 inline const IPV6Address& getNetworkAddress() const
197 { return networkAddress; }
198
199 inline tpport_t getDataTransportPort() const
200 { return dataTransportPort; }
201
202 inline tpport_t getControlTransportPort() const
203 { return controlTransportPort; }
204
205 IPV6Address networkAddress;
206 tpport_t dataTransportPort, controlTransportPort;
207 };
208
209private:
210 mutable ThreadLock destinationLock;
211};
212
213#endif
214
215/**
216 * @class OutgoingDataQueue
217 *
218 * A generic outgoing RTP data queue supporting multiple destinations.
219 *
220 * @author Federico Montesino Pouzols <fedemp@altern.org>
221 **/
222class __EXPORT OutgoingDataQueue:
223 public OutgoingDataQueueBase,
224#ifdef CCXX_IPV6
225 protected DestinationListHandlerIPV6,
226#endif
227 protected DestinationListHandler
228{
229public:
230#ifdef CCXX_IPV6
231 bool
232 addDestination(const IPV6Address& ia,
233 tpport_t dataPort = DefaultRTPDataPort,
234 tpport_t controlPort = 0);
235
236 bool
237 forgetDestination(const IPV6Address& ia,
238 tpport_t dataPort = DefaultRTPDataPort,
239 tpport_t controlPort = 0);
240
241#endif
242
243 bool
244 addDestination(const InetHostAddress& ia,
245 tpport_t dataPort = DefaultRTPDataPort,
246 tpport_t controlPort = 0);
247
248 bool
249 addDestination(const InetMcastAddress& ia,
250 tpport_t dataPort = DefaultRTPDataPort,
251 tpport_t controlPort = 0);
252
253 bool
254 forgetDestination(const InetHostAddress& ia,
255 tpport_t dataPort = DefaultRTPDataPort,
256 tpport_t controlPort = 0);
257
258 bool
259 forgetDestination(const InetMcastAddress& ia,
260 tpport_t dataPort = DefaultRTPDataPort,
261 tpport_t controlPort = 0);
262
263 /**
264 * Add csrc as the CSRC identifier of a new contributor. This
265 * method adds the CSRC identifier to a list of contributors
266 * that will be inserted in every packet enqueued from now on.
267 **/
268 void
269 addContributor(uint32 csrc);
270
271 /**
272 * Remove CSRC from the list of contributors.
273 **/
274 bool
275 removeContributor(uint32 csrc);
276
277 /**
278 * Determine if outgoing packets are waiting to send.
279 *
280 * @return true if there are packets waiting to be send.
281 */
282 bool
283 isSending() const;
284
285
286 /**
287 * This is used to create a data packet in the send queue.
288 * Sometimes a "NULL" or empty packet will be used instead, and
289 * these are known as "silent" packets. "Silent" packets are
290 * used simply to "push" the scheduler along more accurately
291 * by giving the appearence that a next packet is waiting to
292 * be sent and to provide a valid timestamp for that packet.
293 *
294 * @param stamp Timestamp for expected send time of packet.
295 * @param data Value or NULL if special "silent" packet.
296 * @param len May be 0 to indicate a default by payload type.
297 **/
298 void
299 putData(uint32 stamp, const unsigned char* data = NULL, size_t len = 0);
300
301 /**
302 * This is used to create a data packet and send it immediately.
303 * Sometimes a "NULL" or empty packet will be used instead, and
304 * these are known as "silent" packets. "Silent" packets are
305 * used simply to "push" the scheduler along more accurately
306 * by giving the appearence that a next packet is waiting to
307 * be sent and to provide a valid timestamp for that packet.
308 *
309 * @param stamp Timestamp immediate send time of packet.
310 * @param data Value or NULL if special "silent" packet.
311 * @param len May be 0 to indicate a default by payload type.
312 **/
313 void
314 sendImmediate(uint32 stamp, const unsigned char* data = NULL, size_t len = 0);
315
316
317 /**
318 * Set padding. All outgoing packets will be transparently
319 * padded to a multiple of paddinglen.
320 *
321 * @param paddinglen pad packets to a length multiple of paddinglen.
322 **/
323 void setPadding(uint8 paddinglen)
324 { sendInfo.paddinglen = paddinglen; }
325
326 /**
327 * Set marker bit for the packet in which the next data
328 * provided will be send. When transmitting audio, should be
329 * set for the first packet of a talk spurt. When transmitting
330 * video, should be set for the last packet for a video frame.
331 *
332 * @param mark Marker bit value for next packet.
333 **/
334 void setMark(bool mark)
335 { sendInfo.marked = mark; }
336
337 /**
338 * Get wheter the mark bit will be set in the next packet.
339 **/
340 inline bool getMark() const
341 { return sendInfo.marked; }
342
343 /**
344 * Set partial data for an already queued packet. This is often
345 * used for multichannel data.
346 *
347 * @param timestamp Timestamp of packet.
348 * @param data Buffer to copy from.
349 * @param offset Offset to copy from.
350 * @param max Maximum data size.
351 * @return Number of packet data bytes set.
352 **/
353 size_t
354 setPartial(uint32 timestamp, unsigned char* data, size_t offset, size_t max);
355
356 inline microtimeout_t
357 getDefaultSchedulingTimeout() const
358 { return defaultSchedulingTimeout; }
359
360 /**
361 * Set the default scheduling timeout to use when no data
362 * packets are waiting to be sent.
363 *
364 * @param to timeout in milliseconds.
365 **/
366 inline void
367 setSchedulingTimeout(microtimeout_t to)
368 { schedulingTimeout = to; }
369
370 inline microtimeout_t
371 getDefaultExpireTimeout() const
372 { return defaultExpireTimeout; }
373
374 /**
375 * Set the "expired" timer for expiring packets pending in
376 * the send queue which have gone unsent and are already
377 * "too late" to be sent now.
378 *
379 * @param to timeout to expire unsent packets in milliseconds.
380 **/
381 inline void
382 setExpireTimeout(microtimeout_t to)
383 { expireTimeout = to; }
384
385 inline microtimeout_t getExpireTimeout() const
386 { return expireTimeout; }
387
388 /**
389 * Get the total number of packets sent so far
390 *
391 * @return total number of packets sent
392 */
393 inline uint32
394 getSendPacketCount() const
395 { return sendInfo.packetCount; }
396
397 /**
398 * Get the total number of octets (payload only) sent so far.
399 *
400 * @return total number of payload octets sent in RTP packets.
401 **/
402 inline uint32
403 getSendOctetCount() const
404 { return sendInfo.octetCount; }
405
406 /**
407 * Get the sequence number of the next outgoing packet.
408 *
409 * @return the 16 bit sequence number.
410 **/
411 inline uint16
412 getSequenceNumber() const
413 { return sendInfo.sendSeq; }
414
415 /**
416 * Set ouput queue CryptoContext.
417 *
418 * The endQueue method (provided by RTPQueue) deletes all
419 * registered CryptoContexts.
420 *
421 * @param cc Pointer to initialized CryptoContext.
422 */
423 void
424 setOutQueueCryptoContext(CryptoContext* cc);
425
426 /**
427 * Remove output queue CryptoContext.
428 *
429 * The endQueue method (provided by RTPQueue) also deletes all
430 * registered CryptoContexts.
431 *
432 * @param cc Pointer to initialized CryptoContext to remove.
433 */
434 void
435 removeOutQueueCryptoContext(CryptoContext* cc);
436
437 /**
438 * Get an output queue CryptoContext identified by SSRC
439 *
440 * @param ssrc Request CryptoContext for this incoming SSRC
441 * @return Pointer to CryptoContext of the SSRC of NULL if no context
442 * available for this SSRC.
443 */
444 CryptoContext*
445 getOutQueueCryptoContext(uint32 ssrc);
446
447
448protected:
449 OutgoingDataQueue();
450
451 virtual ~OutgoingDataQueue()
452 { }
453
454 struct OutgoingRTPPktLink
455 {
456 OutgoingRTPPktLink(OutgoingRTPPkt* pkt,
457 OutgoingRTPPktLink* p,
458 OutgoingRTPPktLink* n) :
459 packet(pkt), prev(p), next(n) { }
460
461 ~OutgoingRTPPktLink() { delete packet; }
462
463 inline OutgoingRTPPkt* getPacket() { return packet; }
464
465 inline void setPacket(OutgoingRTPPkt* pkt) { packet = pkt; }
466
467 inline OutgoingRTPPktLink* getPrev() { return prev; }
468
469 inline void setPrev(OutgoingRTPPktLink* p) { prev = p; }
470
471 inline OutgoingRTPPktLink* getNext() { return next; }
472
473 inline void setNext(OutgoingRTPPktLink* n) { next = n; }
474
475 // the packet this link refers to.
476 OutgoingRTPPkt* packet;
477 // global outgoing packets queue.
478 OutgoingRTPPktLink * prev, * next;
479 };
480
481 /**
482 * This is used to write the RTP data packet to one or more
483 * destinations. It is used by both sendImmediate and by
484 * dispatchDataPacket.
485 *
486 * @param RTP packet to send.
487 */
488 void
489 dispatchImmediate(OutgoingRTPPkt *packet);
490
491 /**
492 * This computes the timeout period for scheduling transmission
493 * of the next packet at the "head" of the send buffer. If no
494 * packets are waiting, a default timeout is used. This actually
495 * forms the "isPending()" timeout of the rtp receiver in the
496 * service thread.
497 *
498 * @return timeout until next packet is scheduled to send.
499 **/
500 microtimeout_t
501 getSchedulingTimeout();
502
503 /**
504 * This function is used by the service thread to process
505 * the next outgoing packet pending in the sending queue.
506 *
507 * @return number of bytes sent. 0 if silent, <0 if error.
508 **/
509 size_t
510 dispatchDataPacket();
511
512 /**
513 * For thoses cases in which the application requires a method
514 * to set the sequence number for the outgoing stream (such as
515 * for implementing the RTSP PLAY command).
516 *
517 * @param seqNum next sequence number to be used for outgoing packets.
518 *
519 **/
520 inline void
521 setNextSeqNum(uint32 seqNum)
522 { sendInfo.sendSeq = seqNum; }
523
524 inline uint32
525 getCurrentSeqNum(void)
526 { return sendInfo.sendSeq; }
527
528 /**
529 */
530 inline void
531 setInitialTimestamp(uint32 ts)
532 { initialTimestamp = ts; }
533
534 /**
535 */
536 inline uint32
537 getInitialTimestamp()
538 { return initialTimestamp; }
539
540 void purgeOutgoingQueue();
541
542 virtual void
543 setControlPeer(const InetAddress &host, tpport_t port) {}
544
545#ifdef CCXX_IPV6
546 virtual void
547 setControlPeerIPV6(const IPV6Address &host, tpport_t port) {}
548#endif
549
550 // The crypto contexts for outgoing SRTP sessions.
551 mutable Mutex cryptoMutex;
552 std::list<CryptoContext *> cryptoContexts;
553
554private:
555 /**
556 * A hook to filter packets being sent that have been expired.
557 *
558 * @param - expired packet from the send queue.
559 **/
560 inline virtual void onExpireSend(OutgoingRTPPkt&)
561 { }
562
563 virtual void
564 setDataPeer(const InetAddress &host, tpport_t port) {}
565
566#ifdef CCXX_IPV6
567 virtual void
568 setDataPeerIPV6(const IPV6Address &host, tpport_t port) {}
569#endif
570
571 /**
572 * This function performs the physical I/O for writing a
573 * packet to the destination. It is a virtual that is
574 * overriden in the derived class.
575 *
576 * @param buffer Pointer to data to write.
577 * @param len Length of data to write.
578 * @return number of bytes sent.
579 **/
580 virtual size_t
581 sendData(const unsigned char* const buffer, size_t len) {return 0;}
582
583#ifdef CCXX_IPV6
584 virtual size_t
585 sendDataIPV6(const unsigned char* const buffer, size_t len) {return 0;}
586#endif
587
588 static const microtimeout_t defaultSchedulingTimeout;
589 static const microtimeout_t defaultExpireTimeout;
590 mutable ThreadLock sendLock;
591 // outgoing data packets queue
592 OutgoingRTPPktLink* sendFirst, * sendLast;
593 uint32 initialTimestamp;
594 // transmission scheduling timeout for the service thread
595 microtimeout_t schedulingTimeout;
596 // how old a packet can reach in the sending queue before deletetion
597 microtimeout_t expireTimeout;
598
599
600 struct {
601 // number of packets sent from the beginning
602 uint32 packetCount;
603 // number of payload octets sent from the beginning
604 uint32 octetCount;
605 // the sequence number of the next packet to sent
606 uint16 sendSeq;
607 // contributing sources
608 uint32 sendSources[16];
609 // how many CSRCs to send.
610 uint16 sendCC;
611 // pad packets to a paddinglen multiple
612 uint8 paddinglen;
613 // This flags tells whether to set the bit M in the
614 // RTP fixed header of the packet in which the next
615 // provided data will be sent.
616 bool marked;
617 // whether there was not loss.
618 bool complete;
619 // ramdonly generated offset for the timestamp of sent packets
620 uint32 initialTimestamp;
621 // elapsed time accumulated through successive overflows of
622 // the local timestamp field
623 timeval overflowTime;
624 } sendInfo;
625};
626
627/** @}*/ // oqueue
628
629#ifdef CCXX_NAMESPACES
630}
631#endif
632
633#endif //CCXX_RTP_OQUEUE_H_
634
635/** EMACS **
636 * Local variables:
637 * mode: c++
638 * c-basic-offset: 8
639 * End:
640 */