core/AmRtpStream.h
a2a334f1
 /*
  * Copyright (C) 2002-2003 Fhg Fokus
  *
7dcb7e2a
  * This file is part of SEMS, a free SIP media server.
a2a334f1
  *
7dcb7e2a
  * SEMS is free software; you can redistribute it and/or modify
a2a334f1
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
7dcb7e2a
  * (at your option) any later version. This program is released under
  * the GPL with the additional exemption that compiling, linking,
  * and/or using OpenSSL is allowed.
a2a334f1
  *
7dcb7e2a
  * For a license to use the SEMS software under conditions
a2a334f1
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
7dcb7e2a
  * SEMS is distributed in the hope that it will be useful,
a2a334f1
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
df041a16
 /** @file AmRtpStream.h */
a2a334f1
 #ifndef _RtpStream_h_
 #define _RtpStream_h_
 
37abd537
 
a2a334f1
 #include "AmSdp.h"
37abd537
 #include "AmThread.h"
 #include "SampleArray.h"
 #include "AmRtpPacket.h"
cd175204
 #include "AmEvent.h"
a2a334f1
 
 #include <netinet/in.h>
 
 #include <string>
 #include <map>
218642de
 #include <queue>
c7a51805
 #include <memory>
a2a334f1
 using std::string;
 using std::auto_ptr;
184268f8
 using std::pair;
a2a334f1
 
 // return values of AmRtpStream::receive
 #define RTP_EMPTY        0 // no rtp packet available
 #define RTP_PARSE_ERROR -1 // error while parsing rtp packet
 #define RTP_TIMEOUT     -2 // last received packet is too old
 #define RTP_DTMF        -3 // dtmf packet has been received
 #define RTP_BUFFER_SIZE -4 // buffer overrun
 #define RTP_UNKNOWN_PL  -5 // unknown payload
 
 
 struct amci_payload_t;
 
 class AmAudio;
 class AmSession;
0df63e04
 struct SdpPayload;
407b3154
 typedef std::map<unsigned int, AmRtpPacket*, ts_less> ReceiveBuffer;
218642de
 typedef std::queue<AmRtpPacket*>  RtpEventQueue;
407b3154
 
 /**
  * This provides the memory for the receive buffer.
  */
 struct PacketMem {
 #define MAX_PACKETS 32
 
   AmRtpPacket packets[MAX_PACKETS];
   bool        used[MAX_PACKETS];
 
   PacketMem();
 
   inline AmRtpPacket* newPacket();
   inline void freePacket(AmRtpPacket* p);
36952ca7
   inline void clear();
407b3154
 };
 
89ba2485
 
a2a334f1
 /**
7c16a0f5
  * \brief RTP implementation
  *
a2a334f1
  * Rtp stream high level interface.
  */
 class AmRtpStream 
 {
 protected:
7c964b9b
   /**
      Remote payload (only different from 
      int_payload if using dynamic payloads)
   */
   int         payload;
   unsigned int   sequence;
 
   /**
      Payload of last received packet.
      Usefull to detect talk spurt, looking 
      for comfort noise packets.
   */
   int         last_payload;
 
   string             r_host;
   unsigned short     r_port;
e3f48aba
 
   /* local interface */
   int l_if;
 
a2a334f1
 #ifdef SUPPORT_IPV6
7c964b9b
   struct sockaddr_storage r_saddr;
   struct sockaddr_storage l_saddr;
a2a334f1
 #else
7c964b9b
   struct sockaddr_in r_saddr;
   struct sockaddr_in l_saddr;
a2a334f1
 #endif
7c964b9b
   unsigned short     l_port;
   int                l_sd;
a2a334f1
 
7c964b9b
   struct timeval last_recv_time;
a2a334f1
 
7c964b9b
   unsigned int   l_ssrc;
   unsigned int   r_ssrc;
   bool           r_ssrc_i;
a2a334f1
 
7c964b9b
   /** symmetric RTP */
   bool              passive;      // passive mode ?
a2a334f1
 
7c964b9b
   /** Payload type for telephone event */
   auto_ptr<const SdpPayload> telephone_event_pt;
a2a334f1
 
89ba2485
 
407b3154
   PacketMem       mem;
8132928a
   ReceiveBuffer   receive_buf;
218642de
   RtpEventQueue   rtp_ev_qu;
8132928a
   AmMutex         receive_mut;
89ba2485
 
1cb0bace
   /** if relay_stream is initialized, received RTP is relayed there */
   bool            relay_enabled;
   /** pointer to relay stream.
       NOTE: This may only be accessed in initialization
       or by the AmRtpReceiver thread while relaying!  */
   AmRtpStream*    relay_stream;
407b3154
 
7c964b9b
   /* get next packet in buffer */
407b3154
   int nextPacket(AmRtpPacket*& p);
027de947
   
7c964b9b
   AmSession*         session;
a2a334f1
 
184268f8
   int compile_and_send(const int payload, bool marker, 
 		       unsigned int ts, unsigned char* buffer, 
 		       unsigned int size);
 
 
   void sendDtmfPacket(unsigned int ts);
   //       event, duration
   std::queue<pair<int, unsigned int> > dtmf_send_queue;
   AmMutex dtmf_send_queue_mut;
   enum dtmf_sending_state_t {
     DTMF_SEND_NONE,      // not sending event
     DTMF_SEND_SENDING,   // sending event
     DTMF_SEND_ENDING     // sending end of event
   } dtmf_sending_state;
   pair<int, unsigned int> current_send_dtmf;
   unsigned int current_send_dtmf_ts;
   int send_dtmf_end_repeat;
a2a334f1
 
4bd9cd20
   /** handle symmetric RTP - if in passive mode, update raddr from rp */
   void handleSymmetricRtp(AmRtpPacket* rp);
 
1cb0bace
   void relay(AmRtpPacket* p);
 
a2a334f1
 public:
 
407b3154
   AmRtpPacket* newPacket();
   void freePacket(AmRtpPacket* p);
   
7c964b9b
   /** Mute */
   bool mute;
061dcad6
   /** mute && port == 0 */
4e6f4a91
   bool hold;
061dcad6
   /** marker flag */
7c964b9b
   bool begin_talk;
061dcad6
   /** do check rtp timeout */
   bool monitor_rtp_timeout;
 
a2a334f1
 
7c964b9b
   /** should we receive packets? if not -> drop */
   bool receiving;
866b8703
 
7c964b9b
   int send( unsigned int ts,
 	    unsigned char* buffer,
 	    unsigned int   size );
184268f8
   
6f44a030
   int send_raw( char* packet, unsigned int length );
89ba2485
 
7c964b9b
   int receive( unsigned char* buffer, unsigned int size,
3b527c23
 	       unsigned int& ts, int& payload);
7e9f3276
 
   /** ping the remote side, to open NATs and enable symmetric RTP */
   int ping();
 
7c964b9b
   /** Allocates resources for future use of RTP. */
e3f48aba
   AmRtpStream(AmSession* _s, int _if);
7c964b9b
   /** Stops the stream and frees all resources. */
   virtual ~AmRtpStream();
 
1cb0bace
   /** returns the socket descriptor for local socket (initialized or not) */
   int hasLocalSocket();
 
   /** initializes and gets the socket descriptor for local socket */
   int getLocalSocket();
 
7c964b9b
   /**
    * This function must be called before setLocalPort, because
    * setLocalPort will bind the socket and it will be not
    * possible to change the IP later
    */
   void setLocalIP(const string& ip);
a2a334f1
 	    
cf15e5cd
   /** Initializes a new random local port, and sets own attributes properly. */
   void setLocalPort();
 
7c964b9b
   /** 
    * Gets RTP port number. If no RTP port in assigned, assigns a new one.
    * @return local RTP port. 
    */
   int getLocalPort();
 
   /** 
    * Gets remote RTP port.
    * @return remote RTP port.
    */
   int getRPort();
555dd79d
     
7c964b9b
   /**
    * Gets remote host IP.
    * @return remote host IP.
    */
   string getRHost();
 
   /**
    * Set remote IP & port.
    */
   void setRAddr(const string& addr, unsigned short port);
 
   /** Symmetric RTP: passive mode ? */
   void setPassiveMode(bool p) { passive = p; }
   bool getPassiveMode() { return passive; }
 
6f44a030
   unsigned int get_ssrc() { return l_ssrc; }
 
7c964b9b
   /** 
    * Set remote telephone event 
    * payload type 
    */
   void setTelephoneEventPT(const SdpPayload *pt) {
     telephone_event_pt.reset(pt);
   }
 
   int getTelephoneEventRate();
 
184268f8
   /**
    * send a DTMF as RTP payload (RFC4733)
    * @param event event ID (e.g. key press), see rfc
    * @param duration_ms duration in milliseconds
    */
   void sendDtmf(int event, unsigned int duration_ms);
 
7c964b9b
   /**
    * Enables RTP stream.
    * @param sdp_payload payload from the SDP message.
    * @warning start() must have been called so that play and record work.
    * @warning It should be called only if the stream has been completly initialized,
    * @warning and only once per session. Use resume() then.
    */
3b527c23
   virtual void init(const vector<SdpPayload*>& sdp_payloads);
7c964b9b
 
   /**
    * Stops RTP stream.
    */
   void pause();
 
   /**
    * Resume a paused RTP stream.
    */
   void resume();
 
4e6f4a91
   /** set the RTP stream on hold (mute && port = 0) */
   void setOnHold(bool on_hold);
   
   /** get the RTP stream on hold  */
   bool getOnHold();
 
061dcad6
   /** setter for monitor_rtp_timeout */
   void setMonitorRTPTimeout(bool m) { monitor_rtp_timeout = m; }
   /** getter for monitor_rtp_timeout */
   bool getMonitorRTPTimeout() { return monitor_rtp_timeout; }
 
7c964b9b
   /**
    * Insert an RTP packet to the buffer.
    * Note: memory is owned by this instance.
    */
407b3154
   void bufferPacket(AmRtpPacket* p);
7c964b9b
 
027de947
   /*
    * clear RTP timeout at time recv_time 
    */
   void clearRTPTimeout(struct timeval* recv_time);
 
1cb0bace
   virtual unsigned int bytes2samples(unsigned int) const;
 
   /** set relay stream for  RTP relaying */
   void setRelayStream(AmRtpStream* stream);
 
   /** ensable RTP relaying through relay stream */
   void enableRtpRelay();
 
   /** disable RTP relaying through relay stream */
   void disableRtpRelay();
 
a2a334f1
 };
df041a16
 
 /** \brief event fired on RTP timeout */
cd175204
 class AmRtpTimeoutEvent
7c964b9b
   : public AmEvent
cd175204
 {
 	
 public:
7c964b9b
   AmRtpTimeoutEvent() 
     : AmEvent(0) { }
   ~AmRtpTimeoutEvent() { }
cd175204
 };
 
a2a334f1
 #endif
 
 // Local Variables:
 // mode:C++
 // End: