1 /*
2  * Copyright (C) 2002-2003 Fhg Fokus
3  *
4  * This file is part of SEMS, a free SIP media server.
5  *
6  * SEMS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version. This program is released under
10  * the GPL with the additional exemption that compiling, linking,
11  * and/or using OpenSSL is allowed.
12  *
13  * For a license to use the SEMS software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * SEMS is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 /** @file AmRtpStream.h */
28 #ifndef _RtpStream_h_
29 #define _RtpStream_h_
30 
31 
32 #include "AmSdp.h"
33 #include "AmThread.h"
34 #include "SampleArray.h"
35 #include "AmRtpPacket.h"
36 #include "AmEvent.h"
37 #include "AmDtmfSender.h"
38 
39 #include <netinet/in.h>
40 
41 #include <string>
42 #include <map>
43 #include <queue>
44 #include <memory>
45 using std::string;
46 using std::unique_ptr;
47 using std::pair;
48 
49 // return values of AmRtpStream::receive
50 #define RTP_EMPTY        0 // no rtp packet available
51 #define RTP_ERROR       -1 // generic error
52 #define RTP_PARSE_ERROR -2 // error while parsing rtp packet
53 #define RTP_TIMEOUT     -3 // last received packet is too old
54 #define RTP_DTMF        -4 // dtmf packet has been received
55 #define RTP_BUFFER_SIZE -5 // buffer overrun
56 #define RTP_UNKNOWN_PL  -6 // unknown payload
57 
58 
59 /**
60  * Forward declarations
61  */
62 class  AmAudio;
63 class  AmSession;
64 struct SdpPayload;
65 struct amci_payload_t;
66 class msg_logger;
67 
68 /**
clear()69  * This provides the memory for the receive buffer.
70  */
71 struct PacketMem {
72 #define MAX_PACKETS_BITS 5
73 #define MAX_PACKETS (1<<MAX_PACKETS_BITS)
74 #define MAX_PACKETS_MASK (MAX_PACKETS-1)
75 
76   AmRtpPacket packets[MAX_PACKETS];
77   bool        used[MAX_PACKETS];
78 
79   PacketMem();
80 
81   inline AmRtpPacket* newPacket();
82   inline void freePacket(AmRtpPacket* p);
83   inline void clear();
84 
85 private:
86   unsigned int cur_idx;
87   unsigned int n_used;
88 };
89 
90 /** \brief event fired on RTP timeout */
91 class AmRtpTimeoutEvent
92   : public AmEvent
93 {
94 
95 public:
96   AmRtpTimeoutEvent()
97     : AmEvent(0) { }
98   ~AmRtpTimeoutEvent() { }
setLocalIP(const string & ip)99 };
100 
101 /** helper class for assigning boolean floag to a payload ID
102  * it is used to check if the payload should be relayed or not */
103 class PayloadMask
104 {
105   private:
106     unsigned char bits[16];
hasLocalSocket()107 
108   public:
109     // clear flag for all payloads
110     void clear();
getLocalSocket()111 
112     // set given flag (TODO: once it shows to be working, change / and % to >> and &)
113     void set(unsigned char payload_id) { if (payload_id < 128) bits[payload_id / 8] |= 1 << (payload_id % 8); }
114 
115     // set all flags to 'true'
116     void set_all();
117 
118     // invert all flags
119     void invert();
120 
121     // get given flag
122     bool get(unsigned char payload_id) { if (payload_id > 127) { ERROR("BUG: payload_id out of range\n"); return false; } return (bits[payload_id / 8] & (1 << (payload_id % 8))); }
123 
124     PayloadMask() { clear(); }
125     PayloadMask(bool _set_all) { if (_set_all) set_all(); else clear(); }
126     PayloadMask(const PayloadMask &src);
127 };
128 
129 /**
130  * \brief represents one admissible payload type
131  *
132  *
133  */
134 struct Payload {
135   unsigned char pt;
136   string        name;
137   unsigned int  clock_rate;
138   unsigned int  advertised_clock_rate; // differs for G722
139   int           codec_id;
140   string        format_parameters;
141 };
142 
143 /**
144  * \brief RTP implementation
145  *
setLocalPort(unsigned short p)146  * Rtp stream high level interface.
147  */
148 class AmRtpStream
149   : public AmObject
150 {
151 protected:
152 
153   // payload collection
154   typedef std::vector<Payload> PayloadCollection;
155 
156   // list of locally supported payloads
157   PayloadCollection payloads;
158 
159   // current payload (index into @payloads)
160   int payload;
161 
162   struct PayloadMapping {
163     // remote payload type
164     int8_t remote_pt;
165 
166     // index in payloads vector
167     uint8_t index;
168   };
169 
170   typedef std::map<unsigned int, AmRtpPacket*, ts_less> ReceiveBuffer;
171   typedef std::queue<AmRtpPacket*>                      RtpEventQueue;
172   typedef std::map<unsigned char, PayloadMapping>       PayloadMappingTable;
173 
174   // mapping from local payload type to PayloadMapping
175   PayloadMappingTable pl_map;
176 
177   /** SDP media slot number (n-th media line) */
178   int sdp_media_index;
179 
180   /** RTP sequence number */
181   unsigned int sequence;
182 
183   /**
184      Payload of last received packet.
185      Usefull to detect talk spurt, looking
186      for comfort noise packets.
187   */
188   int         last_payload;
189 
190   /** Remote host information */
191   string             r_host;
192   unsigned short     r_port;
193   unsigned short     r_rtcp_port;
194 
195   /**
196    * Local interface used for this stream
197    * (index into @AmConfig::Ifs)
198    */
199   int l_if;
200 
201   /**
202    * Local and remote host addresses
203    */
204   struct sockaddr_storage r_saddr;
205   struct sockaddr_storage l_saddr;
206   struct sockaddr_storage l_rtcp_saddr;
207 
208   /** Local port */
209   unsigned short     l_port;
210 
211   /** Local socket */
212   int                l_sd;
213 
214   /** Local RTCP port */
215   unsigned int l_rtcp_port;
216 
217   /** Local RTCP socket */
218   int          l_rtcp_sd;
219 
220   /** Timestamp of the last received RTP packet */
221   struct timeval last_recv_time;
222 
223   /** Local and remote SSRC information */
224   unsigned int   l_ssrc;
225   unsigned int   r_ssrc;
226   bool           r_ssrc_i;
227 
228   /** symmetric RTP & RTCP */
229   bool           passive;
230   bool           passive_rtcp;
231 
232   /** mute && port == 0 */
233   bool           hold;
234 
235   bool           remotehold;
236 
237   /** marker flag */
238   bool           begin_talk;
239 
240   /** do check rtp timeout */
241   bool           monitor_rtp_timeout;
242 
243   /** Payload type for telephone event */
244   unique_ptr<const SdpPayload> remote_telephone_event_pt;
245   unique_ptr<const SdpPayload> local_telephone_event_pt;
246 
247   /** DTMF sender */
248   AmDtmfSender   dtmf_sender;
249 
250   /**
251    * Receive buffer, queue and mutex
252    */
253   PacketMem       mem;
254   ReceiveBuffer   receive_buf;
255   RtpEventQueue   rtp_ev_qu;
256   AmMutex         receive_mut;
257 
258   /** should we receive packets? if not -> drop */
259   bool receiving;
260 
261   /** if relay_stream is initialized, received RTP is relayed there */
262   bool            relay_enabled;
263   /** if true, packets are note parsed or checked */
264   bool            relay_raw;
265   /** pointer to relay stream.
266       NOTE: This may only be accessed in initialization
267       or by the AmRtpReceiver thread while relaying!  */
268   AmRtpStream*    relay_stream;
269   /** control transparency for RTP seqno in RTP relay mode */
270   bool            relay_transparent_seqno;
271   /** control transparency for RTP ssrc in RTP relay mode */
272   bool            relay_transparent_ssrc;
273   /** filter RTP DTMF (2833 / 4733) in relaying */
274   bool            relay_filter_dtmf;
275 
276   /** remote IP for RTP MUX - empty if disabled */
277   string          rtp_mux_remote_ip;
278   /** remote port for RTP MUX - 0 if disabled*/
279   unsigned int    rtp_mux_remote_port;
280 
281   /** Session owning this stream */
282   AmSession*         session;
283 
284   msg_logger *logger;
285 
286   /** Payload provider */
287   AmPayloadProvider* payload_provider;
288 
289   /** insert packet in DTMF queue if correct payload */
290   void recvDtmfPacket(AmRtpPacket* p);
291 
292   /** Insert an RTP packet to the buffer queue */
293   void bufferPacket(AmRtpPacket* p);
294   /* Get next packet from the buffer queue */
295   int nextPacket(AmRtpPacket*& p);
296 
297   /** Try to reuse oldest buffered packet for newly coming packet */
298   AmRtpPacket *reuseBufferedPacket();
299 
300   /** handle symmetric RTP/RTCP - if in passive mode, update raddr from rp */
301   void handleSymmetricRtp(struct sockaddr_storage* recv_addr, bool rtcp);
302 
303   void relay(AmRtpPacket* p);
304 
305   /** Sets generic parameters on SDP media */
306   void getSdp(SdpMedia& m);
307 
308   /** Clear RTP timeout at time recv_time */
309   void clearRTPTimeout(struct timeval* recv_time);
310 
311   PayloadMask relay_payloads;
312   bool offer_answer_used;
313 
314   /** set to true if any data received */
315   bool active;
316 
317   /**
318    * Select a compatible default payload
319    * @return -1 if none available.
320    */
321   int getDefaultPT();
322 
323 public:
324 
325   /**
326    * Set whether RTP stream will receive RTP packets internally (received packets will be dropped or not).
327    */
328   void setReceiving(bool r);
329 
330   /**
331    * Stops RTP stream receiving RTP packets internally (received packets will be dropped).
332    */
333   void pause();
334 
335   /**
336    * Resume a paused RTP stream internally (received packets will be processed).
337    */
338   void resume();
339 
340   /** Mute */
341   bool mute;
342 
343   /** should we receive RFC-2833-style DTMF even when receiving is disabled? */
344   bool force_receive_dtmf;
345 
346   /** Allocates resources for future use of RTP. */
347   AmRtpStream(AmSession* _s, int _if);
348 
349   /** Stops the stream and frees all resources. */
350   virtual ~AmRtpStream();
351 
352   int send( unsigned int ts,
353 	    unsigned char* buffer,
354 	    unsigned int   size );
355 
356   int send_raw( char* packet, unsigned int length );
357 
358   int compile_and_send( const int payload, bool marker,
359 		        unsigned int ts, unsigned char* buffer,
360 		        unsigned int size );
361 
362   int receive( unsigned char* buffer, unsigned int size,
363 	       unsigned int& ts, int& payload );
364 
365   virtual void recvPacket(int fd, unsigned char* pkt = NULL, size_t len = 0);
366 
367   void recvRtcpPacket();
368 
369   /** ping the remote side, to open NATs and enable symmetric RTP */
370   int ping();
371 
372   /** returns the socket descriptor for local socket (initialized or not) */
373   int hasLocalSocket();
374 
375   /** initializes and gets the socket descriptor for local socket */
376   int getLocalSocket();
377 
378   /**
379    * This function must be called before setLocalPort, because
380    * setLocalPort will bind the socket and it will be not
381    * possible to change the IP later
382    */
383   void setLocalIP(const string& ip);
384 
385   /**
386    * Initializes with a new random local port if 'p' is 0,
387    * else binds the given port, and sets own attributes properly.
388    */
389   void setLocalPort(unsigned short p = 0);
390 
391   /**
392    * Gets RTP port number. If no RTP port in assigned, assigns a new one.
393    * @return local RTP port.
394    */
395   int getLocalPort();
396 
397   /**
398    * Gets RTCP port number. If no RTP/RTCP port in assigned, assigns a new one.
399    * @return local RTCP port.
400    */
401   int getLocalRtcpPort();
402 
403   /**
404    * Gets remote RTP port.
405    * @return remote RTP port.
406    */
407   int getRPort();
408 
409   /**
410    * Gets remote host IP.
411    * @return remote host IP.
412    */
413   string getRHost();
414 
415   /**
416    * Set remote IP & port.
417    */
418   void setRAddr(const string& addr, unsigned short port,
419 		unsigned short rtcp_port = 0);
420 
421   /** Symmetric RTP & RTCP: passive mode ? */
422   void setPassiveMode(bool p);
423   bool getPassiveMode() { return passive || passive_rtcp; }
424 
425   unsigned int get_ssrc() { return l_ssrc; }
426 
427   int getLocalTelephoneEventPT();
428   int getLocalTelephoneEventRate();
429 
430   void setPayloadProvider(AmPayloadProvider* pl_prov);
431 
432   int getSdpMediaIndex() { return sdp_media_index; }
433   void forceSdpMediaIndex(int idx) { sdp_media_index = idx; offer_answer_used = false; }
434   int getPayloadType() { return payload; }
435   int getLastPayload() { return last_payload; }
436   string getPayloadName(int payload_type);
437 
438   /**
439    * send a DTMF as RTP payload (RFC4733)
440    * @param event event ID (e.g. key press), see rfc
441    * @param duration_ms duration in milliseconds
442    */
443   void sendDtmf(int event, unsigned int duration_ms);
444 
445   /**
446    * Generate an SDP offer based on the stream capabilities.
447    * @param index index of the SDP media within the SDP.
448    * @param offer the local offer to be filled/completed.
449    */
450   virtual void getSdpOffer(unsigned int index, SdpMedia& offer);
451 
452   /**
453    * Generate an answer for the given SDP media based on the stream capabilities.
454    * @param index index of the SDP media within the SDP.
455    * @param offer the remote offer.
456    * @param answer the local answer to be filled/completed.
457    */
458   virtual void getSdpAnswer(unsigned int index, const SdpMedia& offer, SdpMedia& answer);
459 
460   /**
461    * Enables RTP stream.
462    * @param local the SDP message generated by the local UA.
463    * @param remote the SDP message generated by the remote UA.
464    * @warning It is necessary to call getSdpOffer/getSdpAnswer prior to init(...)
465    * @warning so that the internal SDP media line index is set properly.
466    */
467   virtual int init(const AmSdp& local, const AmSdp& remote, bool force_passive_mode = false);
468 
469   /** set the RTP stream on hold */
470   void setOnHold(bool on_hold);
471 
472   /** get whether RTP stream is on hold  */
473   bool getOnHold();
474 
475   /** request the remote end to set the RTP stream on hold */
476   void setRemoteHold(bool remote_hold);
477 
478   /** get whether the remote end is requested to set the RTP stream is on hold  */
479   bool getRemoteHold();
480 
481   /** setter for monitor_rtp_timeout */
482   void setMonitorRTPTimeout(bool m) { monitor_rtp_timeout = m; }
483   /** getter for monitor_rtp_timeout */
484   bool getMonitorRTPTimeout() { return monitor_rtp_timeout; }
485 
486   /*
487    * clear RTP timeout to current time
488    */
489   void clearRTPTimeout();
490 
491   /** set relay stream for  RTP relaying */
492   void setRelayStream(AmRtpStream* stream);
493 
494   /** set relay payloads for  RTP relaying */
495   void setRelayPayloads(const PayloadMask &_relay_payloads);
496 
497   /** ensable RTP relaying through relay stream */
498   void enableRtpRelay();
499 
500   /** disable RTP relaying through relay stream */
501   void disableRtpRelay();
502 
503   /** enable raw UDP relaying through relay stream */
504   void enableRawRelay();
505 
506   /** disable raw UDP relaying through relay stream */
507   void disableRawRelay();
508 
509   /** enable or disable transparent RTP seqno for relay */
510   void setRtpRelayTransparentSeqno(bool transparent);
511 
512   /** enable or disable transparent SSRC seqno for relay */
513   void setRtpRelayTransparentSSRC(bool transparent);
514 
515   /** enable or disable filtering of RTP DTMF for relay */
516   void setRtpRelayFilterRtpDtmf(bool filter);
517 
518   /** set RTP Mux remote IP / port ("" and 0 to disable) */
519   void setRtpMuxRemote(const string& remote_ip, unsigned int remote_port);
520 
521   /** remove from RTP receiver */
522   void stopReceiving();
523 
524   /** (re-)insert into RTP receiver */
525   void resumeReceiving();
526 
527   /** Quick hack to assign existing stream to another session. The stream should
528    * not be reinitialised implicitly (it might be used for media traffic
529    * already). */
530   void changeSession(AmSession *_s) { session = _s; }
531 
532   /** set destination for logging all received/sent RTP and RTCP packets */
533   void setLogger(msg_logger *_logger);
534 
535   void debug();
536 };
537 
538 #endif
539 
540 // Local Variables:
541 // mode:C++
542 // End:
543 
544