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:
|