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