tweaks and fixes

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@859 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2006-03-15 22:11:13 +00:00
parent c5e3144711
commit 539ff39995
16 changed files with 289 additions and 189 deletions

View File

@ -15,11 +15,18 @@ static int WSOCKON = 0;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#ifdef _FORMATBUG
}
#endif
struct jrtp4c;
class JRTP4C: public RTPSession { class JRTP4C: public RTPSession {
// add virtuals later // add virtuals later
public: public:
JRTP4C(): RTPSession() { } JRTP4C(): RTPSession() { }
void OnInvalidRawPacketType(RTPRawPacket *rawpacket, jrtp_socket_t socket);
struct jrtp4c *myjrtp4c;
}; };
struct jrtp4c { struct jrtp4c {
@ -27,8 +34,33 @@ extern "C" {
RTPUDPv4TransmissionParams *transparams; RTPUDPv4TransmissionParams *transparams;
uint32_t ssrc; uint32_t ssrc;
int payload; int payload;
invalid_handler on_invalid;
void *private_data;
}; };
void JRTP4C::OnInvalidRawPacketType(RTPRawPacket *rawpacket, jrtp_socket_t socket)
{
void * data = rawpacket->GetData();
unsigned int len = rawpacket->GetDataLength();
const RTPAddress *addr = rawpacket->GetSenderAddress();
const RTPIPv4Address *Sender = (const RTPIPv4Address *)addr;
if (myjrtp4c->on_invalid) {
myjrtp4c->on_invalid(myjrtp4c, socket, data, len, ntohl(Sender->GetIP()), ntohs(Sender->GetPort()));
}
}
void jrtp4c_set_private(struct jrtp4c *jrtp4c, void *private_data)
{
jrtp4c->private_data = private_data;
}
void *jrtp4c_get_private(struct jrtp4c *jrtp4c)
{
return jrtp4c->private_data;
}
struct jrtp4c *jrtp4c_new(char *rx_ip, int rx_port, char *tx_ip, int tx_port, int payload, int sps, const char **err) struct jrtp4c *jrtp4c_new(char *rx_ip, int rx_port, char *tx_ip, int tx_port, int payload, int sps, const char **err)
{ {
struct jrtp4c *jrtp4c = NULL; struct jrtp4c *jrtp4c = NULL;
@ -51,10 +83,11 @@ extern "C" {
if (!(jrtp4c = new struct jrtp4c)) { if (!(jrtp4c = new struct jrtp4c)) {
*err = "Memory Error!\n"; *err = "Memory Error!\n";
memset(jrtp4c, 0, sizeof(*jrtp4c));
return NULL; return NULL;
} }
memset(jrtp4c, 0, sizeof(*jrtp4c));
if (!(jrtp4c->transparams = new RTPUDPv4TransmissionParams)) { if (!(jrtp4c->transparams = new RTPUDPv4TransmissionParams)) {
delete jrtp4c; delete jrtp4c;
*err = "Memory Error!\n"; *err = "Memory Error!\n";
@ -69,9 +102,6 @@ extern "C" {
jrtp4c->transparams->SetPortbase(rx_port); jrtp4c->transparams->SetPortbase(rx_port);
if (!(jrtp4c->session = new JRTP4C)) { if (!(jrtp4c->session = new JRTP4C)) {
*err = "Memory Error!\n"; *err = "Memory Error!\n";
delete jrtp4c->transparams; delete jrtp4c->transparams;
@ -86,7 +116,6 @@ extern "C" {
return NULL; return NULL;
} }
if ((status = jrtp4c->session->AddDestination(addr)) < 0) { if ((status = jrtp4c->session->AddDestination(addr)) < 0) {
*err = RTPGetErrorString(status).c_str(); *err = RTPGetErrorString(status).c_str();
jrtp4c_destroy(&jrtp4c); jrtp4c_destroy(&jrtp4c);
@ -95,6 +124,7 @@ extern "C" {
jrtp4c->session->SetDefaultPayloadType(payload); jrtp4c->session->SetDefaultPayloadType(payload);
jrtp4c->payload = payload; jrtp4c->payload = payload;
jrtp4c->session->myjrtp4c = jrtp4c;
return jrtp4c; return jrtp4c;
} }
@ -108,6 +138,17 @@ extern "C" {
} }
void jrtp4c_set_invald_handler(struct jrtp4c *jrtp4c, invalid_handler on_invalid)
{
jrtp4c->on_invalid = on_invalid;
}
jrtp_socket_t jrtp4c_get_rtp_socket(struct jrtp4c *jrtp4c)
{
return jrtp4c->session->GetRTPSocket();
}
void jrtp4c_killread(struct jrtp4c *jrtp4c) void jrtp4c_killread(struct jrtp4c *jrtp4c)
{ {
jrtp4c->session->AbortWait(); jrtp4c->session->AbortWait();

View File

@ -9,6 +9,7 @@
#ifdef __cplusplus #ifdef __cplusplus
#include <rtpsession.h> #include <rtpsession.h>
#include <rtppacket.h> #include <rtppacket.h>
#include <rtprawpacket.h>
#include <rtpudpv4transmitter.h> #include <rtpudpv4transmitter.h>
#include <rtpipv4address.h> #include <rtpipv4address.h>
#include <rtpsessionparams.h> #include <rtpsessionparams.h>
@ -28,6 +29,9 @@
extern "C" { extern "C" {
#endif #endif
#ifdef _FORMABUG
}
#endif
typedef enum { typedef enum {
SR, SR,
@ -45,16 +49,28 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#endif #endif
#endif #endif
#ifdef WIN32
typedef SOCKET jrtp_sock_t;
#else
typedef int jrtp_socket_t;
#endif
struct jrtp4c; struct jrtp4c;
typedef void (*invalid_handler)(struct jrtp4c *jrtp4c, jrtp_socket_t sock, void *data, unsigned int datalen, uint32_t fromip, uint16_t fromport);
struct jrtp4c *jrtp4c_new(char *rx_ip, int rx_port, char *tx_ip, int tx_port, int payload, int sps, const char **err); struct jrtp4c *jrtp4c_new(char *rx_ip, int rx_port, char *tx_ip, int tx_port, int payload, int sps, const char **err);
void jrtp4c_destroy(struct jrtp4c **jrtp4c); void jrtp4c_destroy(struct jrtp4c **jrtp4c);
jrtp_socket_t jrtp4c_get_rtp_socket(struct jrtp4c *jrtp4c);
void jrtp4c_set_invald_handler(struct jrtp4c *jrtp4c, invalid_handler on_invalid);
int jrtp4c_read(struct jrtp4c *jrtp4c, void *data, int datalen, int *payload_type); int jrtp4c_read(struct jrtp4c *jrtp4c, void *data, int datalen, int *payload_type);
int jrtp4c_write(struct jrtp4c *jrtp4c, void *data, int datalen, uint32_t ts); int jrtp4c_write(struct jrtp4c *jrtp4c, void *data, int datalen, uint32_t ts);
int jrtp4c_write_payload(struct jrtp4c *jrtp4c, void *data, int datalen, int payload, uint32_t ts, uint32_t mseq); int jrtp4c_write_payload(struct jrtp4c *jrtp4c, void *data, int datalen, int payload, uint32_t ts, uint32_t mseq);
uint32_t jrtp4c_start(struct jrtp4c *jrtp4c); uint32_t jrtp4c_start(struct jrtp4c *jrtp4c);
uint32_t jrtp4c_get_ssrc(struct jrtp4c *jrtp4c); uint32_t jrtp4c_get_ssrc(struct jrtp4c *jrtp4c);
void jrtp4c_killread(struct jrtp4c *jrtp4c); void jrtp4c_killread(struct jrtp4c *jrtp4c);
void jrtp4c_set_private(struct jrtp4c *jrtp4c, void *private_data);
void *jrtp4c_get_private(struct jrtp4c *jrtp4c);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -35,8 +35,10 @@
#define RTPCONFIG_H #define RTPCONFIG_H
#if (defined(WIN32) || defined(_WIN32_WCE)) #if (defined(WIN32) || defined(_WIN32_WCE))
typedef SOCKET jrtp_socket_t;
#include "rtpconfig_win.h" #include "rtpconfig_win.h"
#else #else
typedef int jrtp_socket_t;
#include "rtpconfig_unix.h" #include "rtpconfig_unix.h"
#endif // WIN32 #endif // WIN32

View File

@ -47,4 +47,3 @@
//#define RTP_SUPPORT_IPV6MULTICAST //#define RTP_SUPPORT_IPV6MULTICAST
#endif // RTPCONFIG_WIN_H #endif // RTPCONFIG_WIN_H

View File

@ -201,6 +201,7 @@ static RTPErrorInfo ErrorDescriptions[]=
{ ERR_RTP_GSTV4TRANS_SRCADDRNOTSET, "Got packet but src address information was not set, returning"}, { ERR_RTP_GSTV4TRANS_SRCADDRNOTSET, "Got packet but src address information was not set, returning"},
{ ERR_RTP_GSTV4TRANS_NOTNETBUFFER, "Received buffer is not a GstNetBuffer"}, { ERR_RTP_GSTV4TRANS_NOTNETBUFFER, "Received buffer is not a GstNetBuffer"},
{ ERR_RTP_GSTV4TRANS_WAITNOTIMPLEMENTED, "The WaitForIncomingData is not implemented in the Gst transmitter"}, { ERR_RTP_GSTV4TRANS_WAITNOTIMPLEMENTED, "The WaitForIncomingData is not implemented in the Gst transmitter"},
{ ERR_RTP_INVALID_PACKET_VERISON, "The packet is not the correct version of RTP"},
{ 0,0 } { 0,0 }
}; };

View File

@ -197,6 +197,6 @@ std::string RTPGetErrorString(int errcode);
#define ERR_RTP_GSTV4TRANS_SRCADDRNOTSET -157 #define ERR_RTP_GSTV4TRANS_SRCADDRNOTSET -157
#define ERR_RTP_GSTV4TRANS_NOTNETBUFFER -158 #define ERR_RTP_GSTV4TRANS_NOTNETBUFFER -158
#define ERR_RTP_GSTV4TRANS_WAITNOTIMPLEMENTED -159 #define ERR_RTP_GSTV4TRANS_WAITNOTIMPLEMENTED -159
#define ERR_RTP_INVALID_PACKET_VERISON -160
#endif // RTPERRORS_H #endif // RTPERRORS_H

View File

@ -113,16 +113,17 @@ int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack)
if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it
return ERR_RTP_PACKET_INVALIDPACKET; return ERR_RTP_PACKET_INVALIDPACKET;
// The length should be at least the size of the RTP header
packetlen = rawpack.GetDataLength();
if (packetlen < sizeof(RTPHeader))
return ERR_RTP_PACKET_INVALIDPACKET;
packetbytes = (u_int8_t *)rawpack.GetData(); packetbytes = (u_int8_t *)rawpack.GetData();
rtpheader = (RTPHeader *)packetbytes; rtpheader = (RTPHeader *)packetbytes;
// The version number should be correct // The version number should be correct
if (rtpheader->version != RTP_VERSION) if (rtpheader->version != RTP_VERSION) {
return ERR_RTP_INVALID_PACKET_VERISON;
}
// The length should be at least the size of the RTP header
packetlen = rawpack.GetDataLength();
if (packetlen < sizeof(RTPHeader))
return ERR_RTP_PACKET_INVALIDPACKET; return ERR_RTP_PACKET_INVALIDPACKET;
// We'll check if this is possibly a RTCP packet. For this to be possible // We'll check if this is possibly a RTCP packet. For this to be possible

View File

@ -1026,6 +1026,15 @@ int RTPSession::SetLocalNote(const void *s,size_t len)
return status; return status;
} }
#if ! (defined(WIN32) || defined(_WIN32_WCE))
int RTPSession::GetRTPSocket(void)
#else
SOCKET RTPSession::GetRTPSocket(void)
#endif // WIN32
{
return rtptrans->GetRTPSocket();
}
int RTPSession::ProcessPolledData() int RTPSession::ProcessPolledData()
{ {
RTPRawPacket *rawpack; RTPRawPacket *rawpack;
@ -1039,7 +1048,15 @@ int RTPSession::ProcessPolledData()
// since our sources instance also uses the scheduler (analysis of incoming packets) // since our sources instance also uses the scheduler (analysis of incoming packets)
// we'll lock it // we'll lock it
SCHED_LOCK SCHED_LOCK
if ((status = sources.ProcessRawPacket(rawpack,rtptrans,acceptownpackets)) < 0)
status = sources.ProcessRawPacket(rawpack,rtptrans,acceptownpackets);
if (status == ERR_RTP_INVALID_PACKET_VERISON) {
OnInvalidRawPacketType(rawpack, rtptrans->GetRTPSocket());
status = 0;
}
if (status < 0)
{ {
SCHED_UNLOCK SCHED_UNLOCK
SOURCES_UNLOCK SOURCES_UNLOCK

View File

@ -143,6 +143,11 @@ public:
int SetLocalPhone(const void *s,size_t len); int SetLocalPhone(const void *s,size_t len);
int SetLocalTool(const void *s,size_t len); int SetLocalTool(const void *s,size_t len);
int SetLocalNote(const void *s,size_t len); int SetLocalNote(const void *s,size_t len);
#if ! (defined(WIN32) || defined(_WIN32_WCE))
int GetRTPSocket(void);
#else
SOCKET GetRTPSocket(void);
#endif // WIN32
#ifdef RTPDEBUG #ifdef RTPDEBUG
void DumpSources(); void DumpSources();
@ -168,8 +173,15 @@ protected:
const RTPAddress *senderaddress) { } const RTPAddress *senderaddress) { }
virtual void OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime, virtual void OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress) { } const RTPAddress *senderaddress) { }
#if (defined(WIN32) || defined(_WIN32_WCE))
virtual void OnInvalidRawPacketType(RTPRawPacket *rawpacket, SOCKET socket) { }
#else
virtual void OnInvalidRawPacketType(RTPRawPacket *rawpacket, int socket) { }
#endif
virtual void OnNoteTimeout(RTPSourceData *srcdat) { } virtual void OnNoteTimeout(RTPSourceData *srcdat) { }
virtual void OnBYEPacket(RTPSourceData *srcdat) { } virtual void OnBYEPacket(RTPSourceData *srcdat) { }
#ifdef RTP_SUPPORT_THREAD #ifdef RTP_SUPPORT_THREAD
virtual void OnPollThreadError(int errcode) { } virtual void OnPollThreadError(int errcode) { }
virtual void OnPollThreadStep() { } virtual void OnPollThreadStep() { }

View File

@ -61,6 +61,9 @@ public:
virtual int Create(size_t maxpacksize,const RTPTransmissionParams *transparams) = 0; virtual int Create(size_t maxpacksize,const RTPTransmissionParams *transparams) = 0;
virtual void Destroy() = 0; virtual void Destroy() = 0;
virtual jrtp_socket_t GetRTPSocket() {}
virtual jrtp_socket_t GetRTCPSocket() {}
// The user MUST delete the returned instance when it is no longer needed // The user MUST delete the returned instance when it is no longer needed
virtual RTPTransmissionInfo *GetTransmissionInfo() = 0; virtual RTPTransmissionInfo *GetTransmissionInfo() = 0;
@ -108,6 +111,7 @@ public:
virtual bool NewDataAvailable() = 0; virtual bool NewDataAvailable() = 0;
virtual RTPRawPacket *GetNextPacket() = 0; virtual RTPRawPacket *GetNextPacket() = 0;
#ifdef RTPDEBUG #ifdef RTPDEBUG
virtual void Dump() = 0; virtual void Dump() = 0;
#endif // RTPDEBUG #endif // RTPDEBUG

View File

@ -673,6 +673,17 @@ int RTPUDPv4Transmitter::AbortWait()
return 0; return 0;
} }
jrtp_socket_t RTPUDPv4Transmitter::GetRTPSocket()
{
return rtpsock;
}
jrtp_socket_t RTPUDPv4Transmitter::GetRTCPSocket()
{
return rtcpsock;
}
int RTPUDPv4Transmitter::SendRTPData(const void *data,size_t len) int RTPUDPv4Transmitter::SendRTPData(const void *data,size_t len)
{ {
if (!init) if (!init)

View File

@ -71,29 +71,16 @@ private:
class RTPUDPv4TransmissionInfo : public RTPTransmissionInfo class RTPUDPv4TransmissionInfo : public RTPTransmissionInfo
{ {
public: public:
#if ! (defined(WIN32) || defined(_WIN32_WCE))
RTPUDPv4TransmissionInfo(std::list<u_int32_t> iplist,int rtpsock,int rtcpsock) : RTPTransmissionInfo(RTPTransmitter::IPv4UDPProto) RTPUDPv4TransmissionInfo(std::list<u_int32_t> iplist,jrtp_socket_t rtpsock,jrtp_socket_t rtcpsock) : RTPTransmissionInfo(RTPTransmitter::IPv4UDPProto)
#else
RTPUDPv4TransmissionInfo(std::list<u_int32_t> iplist,SOCKET rtpsock,SOCKET rtcpsock) : RTPTransmissionInfo(RTPTransmitter::IPv4UDPProto)
#endif // WIN32
{ localIPlist = iplist; rtpsocket = rtpsock; rtcpsocket = rtcpsock; } { localIPlist = iplist; rtpsocket = rtpsock; rtcpsocket = rtcpsock; }
~RTPUDPv4TransmissionInfo() { } ~RTPUDPv4TransmissionInfo() { }
std::list<u_int32_t> GetLocalIPList() const { return localIPlist; } std::list<u_int32_t> GetLocalIPList() const { return localIPlist; }
#if ! (defined(WIN32) || defined(_WIN32_WCE))
int GetRTPSocket() const { return rtpsocket; }
int GetRTCPSocket() const { return rtcpsocket; }
#else
SOCKET GetRTPSocket() const { return rtpsocket; }
SOCKET GetRTCPSocket() const { return rtcpsocket; }
#endif // WIN32
private: private:
std::list<u_int32_t> localIPlist; std::list<u_int32_t> localIPlist;
#if ! (defined(WIN32) || defined(_WIN32_WCE)) jrtp_socket_t rtpsocket,rtcpsocket;
int rtpsocket,rtcpsocket;
#else
SOCKET rtpsocket,rtcpsocket;
#endif // WIN32
}; };
#ifdef RTP_SUPPORT_INLINETEMPLATEPARAM #ifdef RTP_SUPPORT_INLINETEMPLATEPARAM
@ -112,6 +99,8 @@ public:
RTPUDPv4Transmitter(); RTPUDPv4Transmitter();
~RTPUDPv4Transmitter(); ~RTPUDPv4Transmitter();
jrtp_socket_t RTPUDPv4Transmitter::GetRTPSocket();
jrtp_socket_t RTPUDPv4Transmitter::GetRTCPSocket();
int Init(bool treadsafe); int Init(bool treadsafe);
int Create(size_t maxpacksize,const RTPTransmissionParams *transparams); int Create(size_t maxpacksize,const RTPTransmissionParams *transparams);
void Destroy(); void Destroy();
@ -173,11 +162,7 @@ private:
bool init; bool init;
bool created; bool created;
bool waitingfordata; bool waitingfordata;
#if (defined(WIN32) || defined(_WIN32_WCE)) jrtp_socket_t rtpsock,rtcpsock;
SOCKET rtpsock,rtcpsock;
#else // not using winsock
int rtpsock,rtcpsock;
#endif // WIN32
u_int32_t bindIP; u_int32_t bindIP;
std::list<u_int32_t> localIPs; std::list<u_int32_t> localIPs;
u_int16_t portbase; u_int16_t portbase;
@ -208,11 +193,7 @@ private:
RTPKeyHashTable<const u_int32_t,PortInfo*,RTPUDPv4Trans_GetHashIndex_u_int32_t,RTPUDPV4TRANS_HASHSIZE> acceptignoreinfo; RTPKeyHashTable<const u_int32_t,PortInfo*,RTPUDPv4Trans_GetHashIndex_u_int32_t,RTPUDPV4TRANS_HASHSIZE> acceptignoreinfo;
// notification descriptors for AbortWait (0 is for reading, 1 for writing) // notification descriptors for AbortWait (0 is for reading, 1 for writing)
#if (defined(WIN32) || defined(_WIN32_WCE)) jrtp_socket_t abortdesc[2];
SOCKET abortdesc[2];
#else
int abortdesc[2];
#endif // WIN32
int CreateAbortDescriptors(); int CreateAbortDescriptors();
void DestroyAbortDescriptors(); void DestroyAbortDescriptors();
void AbortWaitInternal(); void AbortWaitInternal();

View File

@ -1037,7 +1037,7 @@ static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type,
} }
if ((fd = sangoma_create_socket_intr(spri->span, event->restart.channel)) < 0) { if ((fd = sangoma_create_socket_intr(spri->span, event->restart.channel)) < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open fd!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open fd [%s]!\n", strerror(errno));
} else { } else {
close(fd); close(fd);
} }

View File

@ -83,7 +83,7 @@ static void event_handler(switch_event *event)
msg = iks_make_msg(IKS_TYPE_NONE, globals.target_jid, buf); msg = iks_make_msg(IKS_TYPE_NONE, globals.target_jid, buf);
iks_insert_attrib(msg, "subject", "Event"); iks_insert_attrib(msg, "subject", "Event");
iks_send(globals.session.parser, msg); iks_send(globals.session.parser, msg);
iks_delete(msg);
break; break;
} }
} }

View File

@ -491,6 +491,7 @@ static JSBool session_speak(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
char *voice_name = NULL; char *voice_name = NULL;
char *text = NULL; char *text = NULL;
char *dtmf_callback = NULL; char *dtmf_callback = NULL;
char *timer_name = NULL;
switch_codec *codec; switch_codec *codec;
void *bp = NULL; void *bp = NULL;
int len = 0; int len = 0;
@ -524,6 +525,10 @@ static JSBool session_speak(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
} }
} }
if (argc > 4) {
timer_name = JS_GetStringBytes(JS_ValueToString(cx, argv[4]));
}
if (!tts_name && text) { if (!tts_name && text) {
return JS_FALSE; return JS_FALSE;
} }
@ -532,7 +537,7 @@ static JSBool session_speak(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
switch_ivr_speak_text(jss->session, switch_ivr_speak_text(jss->session,
tts_name, tts_name,
voice_name && strlen(voice_name) ? voice_name : NULL, voice_name && strlen(voice_name) ? voice_name : NULL,
NULL, timer_name,
codec->implementation->samples_per_second, codec->implementation->samples_per_second,
dtmf_func, dtmf_func,
text, text,

View File

@ -893,25 +893,35 @@ SWITCH_DECLARE(switch_status) switch_ivr_multi_threaded_bridge(switch_core_sessi
switch_channel_add_state_handler(caller_channel, &audio_bridge_caller_state_handlers); switch_channel_add_state_handler(caller_channel, &audio_bridge_caller_state_handlers);
switch_channel_add_state_handler(peer_channel, &audio_bridge_peer_state_handlers); switch_channel_add_state_handler(peer_channel, &audio_bridge_peer_state_handlers);
switch_core_session_thread_launch(peer_session); switch_core_session_thread_launch(peer_session);
time(&start);
for (;;) { for (;;) {
int state = switch_channel_get_state(peer_channel); int state = switch_channel_get_state(peer_channel);
if (state > CS_RING) { if (state > CS_RING) {
break; break;
} }
if (!switch_channel_ready(caller_channel)) {
break;
}
if ((time(NULL) - start) > timelimit) {
break;
}
switch_yield(1000); switch_yield(1000);
} }
switch_channel_pre_answer(caller_channel); switch_channel_pre_answer(caller_channel);
time(&start);
while (switch_channel_ready(caller_channel) && while (switch_channel_ready(caller_channel) &&
switch_channel_ready(peer_channel) && switch_channel_ready(peer_channel) &&
!switch_channel_test_flag(peer_channel, CF_ANSWERED) && !switch_channel_test_flag(peer_channel, CF_ANSWERED) &&
!switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) &&
((time(NULL) - start) < timelimit)) { ((time(NULL) - start) < timelimit)) {
/* read from the channel while we wait if the audio is up on it */ /* read from the channel while we wait if the audio is up on it */
if (switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) { if (switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) {
if (switch_core_session_read_frame(session, &read_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) { if (switch_core_session_read_frame(session, &read_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) {