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,162 +15,203 @@ static int WSOCKON = 0;
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _FORMATBUG
}
#endif
class JRTP4C: public RTPSession {
// add virtuals later
public:
JRTP4C(): RTPSession() {}
};
struct jrtp4c;
struct jrtp4c {
JRTP4C *session;
RTPUDPv4TransmissionParams *transparams;
uint32_t ssrc;
int payload;
};
class JRTP4C: public RTPSession {
// add virtuals later
public:
JRTP4C(): RTPSession() { }
void OnInvalidRawPacketType(RTPRawPacket *rawpacket, jrtp_socket_t socket);
struct jrtp4c *myjrtp4c;
};
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;
uint32_t destip = ntohl(inet_addr(tx_ip));
uint32_t srcip;
RTPIPv4Address addr(destip, tx_port);
RTPSessionParams sessparams;
int status;
struct jrtp4c {
JRTP4C *session;
RTPUDPv4TransmissionParams *transparams;
uint32_t ssrc;
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 = NULL;
uint32_t destip = ntohl(inet_addr(tx_ip));
uint32_t srcip;
RTPIPv4Address addr(destip, tx_port);
RTPSessionParams sessparams;
int status;
#ifdef WIN32
if (!WSOCKON) {
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
WSOCKON = 1;
}
if (!WSOCKON) {
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
WSOCKON = 1;
}
#endif // WIN32
sessparams.SetOwnTimestampUnit(1.0/sps);
//sessparams.SetAcceptOwnPackets(true);
sessparams.SetOwnTimestampUnit(1.0/sps);
//sessparams.SetAcceptOwnPackets(true);
if (!(jrtp4c = new struct jrtp4c)) {
*err = "Memory Error!\n";
memset(jrtp4c, 0, sizeof(*jrtp4c));
return NULL;
}
if (!(jrtp4c->transparams = new RTPUDPv4TransmissionParams)) {
delete jrtp4c;
*err = "Memory Error!\n";
return NULL;
}
if (rx_ip) {
srcip = ntohl(inet_addr(rx_ip));
jrtp4c->transparams->SetBindIP(srcip);
}
jrtp4c->transparams->SetPortbase(rx_port);
if (!(jrtp4c->session = new JRTP4C)) {
*err = "Memory Error!\n";
delete jrtp4c->transparams;
delete jrtp4c;
return NULL;
}
if ((status = jrtp4c->session->Create(sessparams, jrtp4c->transparams)) < 0) {
*err = RTPGetErrorString(status).c_str();
delete jrtp4c->transparams;
delete jrtp4c;
return NULL;
}
if ((status = jrtp4c->session->AddDestination(addr)) < 0) {
*err = RTPGetErrorString(status).c_str();
jrtp4c_destroy(&jrtp4c);
return NULL;
}
jrtp4c->session->SetDefaultPayloadType(payload);
jrtp4c->payload = payload;
return jrtp4c;
if (!(jrtp4c = new struct jrtp4c)) {
*err = "Memory Error!\n";
return NULL;
}
void jrtp4c_destroy(struct jrtp4c **jrtp4c)
{
(*jrtp4c)->session->BYEDestroy(RTPTime(10,0),0,0);
delete (*jrtp4c)->session;
delete (*jrtp4c)->transparams;
delete (*jrtp4c);
*jrtp4c = NULL;
memset(jrtp4c, 0, sizeof(*jrtp4c));
if (!(jrtp4c->transparams = new RTPUDPv4TransmissionParams)) {
delete jrtp4c;
*err = "Memory Error!\n";
return NULL;
}
void jrtp4c_killread(struct jrtp4c *jrtp4c)
{
jrtp4c->session->AbortWait();
if (rx_ip) {
srcip = ntohl(inet_addr(rx_ip));
jrtp4c->transparams->SetBindIP(srcip);
}
int jrtp4c_read(struct jrtp4c *jrtp4c, void *data, int datalen, int *payload_type)
{
RTPPacket *pack;
int slen = 0;
bool hasdata = 0;
jrtp4c->transparams->SetPortbase(rx_port);
*payload_type = 0;
if (!(jrtp4c->session = new JRTP4C)) {
*err = "Memory Error!\n";
delete jrtp4c->transparams;
delete jrtp4c;
return NULL;
}
jrtp4c->session->BeginDataAccess();
if ((status = jrtp4c->session->Create(sessparams, jrtp4c->transparams)) < 0) {
*err = RTPGetErrorString(status).c_str();
delete jrtp4c->transparams;
delete jrtp4c;
return NULL;
}
jrtp4c->session->WaitForIncomingData(RTPTime(.5), &hasdata);
if ((status = jrtp4c->session->AddDestination(addr)) < 0) {
*err = RTPGetErrorString(status).c_str();
jrtp4c_destroy(&jrtp4c);
return NULL;
}
if (!jrtp4c->session->GotoFirstSourceWithData()) {
jrtp4c->session->EndDataAccess();
return 0;
}
jrtp4c->session->SetDefaultPayloadType(payload);
jrtp4c->payload = payload;
jrtp4c->session->myjrtp4c = jrtp4c;
return jrtp4c;
}
if ((pack = jrtp4c->session->GetNextPacket())) {
slen = pack->GetPayloadLength();
void jrtp4c_destroy(struct jrtp4c **jrtp4c)
{
(*jrtp4c)->session->BYEDestroy(RTPTime(10,0),0,0);
delete (*jrtp4c)->session;
delete (*jrtp4c)->transparams;
delete (*jrtp4c);
*jrtp4c = NULL;
}
if (slen > datalen) {
slen = datalen;
}
*payload_type = pack->GetPayloadType();
void jrtp4c_set_invald_handler(struct jrtp4c *jrtp4c, invalid_handler on_invalid)
{
jrtp4c->on_invalid = on_invalid;
}
memcpy(data, pack->GetPayloadData(), slen);
jrtp_socket_t jrtp4c_get_rtp_socket(struct jrtp4c *jrtp4c)
{
delete pack;
}
return jrtp4c->session->GetRTPSocket();
}
void jrtp4c_killread(struct jrtp4c *jrtp4c)
{
jrtp4c->session->AbortWait();
}
int jrtp4c_read(struct jrtp4c *jrtp4c, void *data, int datalen, int *payload_type)
{
RTPPacket *pack;
int slen = 0;
bool hasdata = 0;
*payload_type = 0;
jrtp4c->session->BeginDataAccess();
jrtp4c->session->WaitForIncomingData(RTPTime(.5), &hasdata);
if (!jrtp4c->session->GotoFirstSourceWithData()) {
jrtp4c->session->EndDataAccess();
return slen;
}
int jrtp4c_write(struct jrtp4c *jrtp4c, void *data, int datalen, uint32_t ts)
{
return jrtp4c->session->SendPacket(data, datalen, jrtp4c->payload, false, ts);
}
int jrtp4c_write_payload(struct jrtp4c *jrtp4c, void *data, int datalen, int payload, uint32_t ts, uint32_t mseq)
{
return jrtp4c->session->SendPacket(data, datalen, payload, false, ts, mseq);
}
uint32_t jrtp4c_start(struct jrtp4c *jrtp4c)
{
//jrtp4c->session->BeginDataAccess();
return 0;
}
uint32_t jrtp4c_get_ssrc(struct jrtp4c *jrtp4c)
{
return jrtp4c->ssrc;
if ((pack = jrtp4c->session->GetNextPacket())) {
slen = pack->GetPayloadLength();
if (slen > datalen) {
slen = datalen;
}
*payload_type = pack->GetPayloadType();
memcpy(data, pack->GetPayloadData(), slen);
delete pack;
}
jrtp4c->session->EndDataAccess();
return slen;
}
int jrtp4c_write(struct jrtp4c *jrtp4c, void *data, int datalen, uint32_t ts)
{
return jrtp4c->session->SendPacket(data, datalen, jrtp4c->payload, false, ts);
}
int jrtp4c_write_payload(struct jrtp4c *jrtp4c, void *data, int datalen, int payload, uint32_t ts, uint32_t mseq)
{
return jrtp4c->session->SendPacket(data, datalen, payload, false, ts, mseq);
}
uint32_t jrtp4c_start(struct jrtp4c *jrtp4c)
{
//jrtp4c->session->BeginDataAccess();
return 0;
}
uint32_t jrtp4c_get_ssrc(struct jrtp4c *jrtp4c)
{
return jrtp4c->ssrc;
}
#ifdef __cplusplus
}

View File

@ -9,6 +9,7 @@
#ifdef __cplusplus
#include <rtpsession.h>
#include <rtppacket.h>
#include <rtprawpacket.h>
#include <rtpudpv4transmitter.h>
#include <rtpipv4address.h>
#include <rtpsessionparams.h>
@ -28,33 +29,48 @@
extern "C" {
#endif
#ifdef _FORMABUG
}
#endif
typedef enum {
SR,
RR,
SDES,
BYE,
APP,
UNK
} jrtp4c_packet_t;
typedef enum {
SR,
RR,
SDES,
BYE,
APP,
UNK
} jrtp4c_packet_t;
#ifndef uint32_t
#ifdef WIN32
typedef unsigned int uint32_t;
typedef unsigned int uint32_t;
#else
#include <stdint.h>
#endif
#endif
#ifdef WIN32
typedef SOCKET jrtp_sock_t;
#else
typedef int jrtp_socket_t;
#endif
struct jrtp4c;
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);
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_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_get_ssrc(struct jrtp4c *jrtp4c);
void jrtp4c_killread(struct jrtp4c *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);
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_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);
uint32_t jrtp4c_start(struct jrtp4c *jrtp4c);
uint32_t jrtp4c_get_ssrc(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
}
#endif

View File

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

View File

@ -47,4 +47,3 @@
//#define RTP_SUPPORT_IPV6MULTICAST
#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_NOTNETBUFFER, "Received buffer is not a GstNetBuffer"},
{ 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 }
};

View File

@ -197,6 +197,6 @@ std::string RTPGetErrorString(int errcode);
#define ERR_RTP_GSTV4TRANS_SRCADDRNOTSET -157
#define ERR_RTP_GSTV4TRANS_NOTNETBUFFER -158
#define ERR_RTP_GSTV4TRANS_WAITNOTIMPLEMENTED -159
#define ERR_RTP_INVALID_PACKET_VERISON -160
#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
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();
rtpheader = (RTPHeader *)packetbytes;
// 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;
// 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;
}
#if ! (defined(WIN32) || defined(_WIN32_WCE))
int RTPSession::GetRTPSocket(void)
#else
SOCKET RTPSession::GetRTPSocket(void)
#endif // WIN32
{
return rtptrans->GetRTPSocket();
}
int RTPSession::ProcessPolledData()
{
RTPRawPacket *rawpack;
@ -1039,15 +1048,23 @@ int RTPSession::ProcessPolledData()
// since our sources instance also uses the scheduler (analysis of incoming packets)
// we'll lock it
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
SOURCES_UNLOCK
delete rawpack;
return status;
}
SCHED_UNLOCK
if (sources.DetectedOwnCollision()) // collision handling!
{
bool created;

View File

@ -143,6 +143,11 @@ public:
int SetLocalPhone(const void *s,size_t len);
int SetLocalTool(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
void DumpSources();
@ -168,8 +173,15 @@ protected:
const RTPAddress *senderaddress) { }
virtual void OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime,
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 OnBYEPacket(RTPSourceData *srcdat) { }
#ifdef RTP_SUPPORT_THREAD
virtual void OnPollThreadError(int errcode) { }
virtual void OnPollThreadStep() { }

View File

@ -61,6 +61,9 @@ public:
virtual int Create(size_t maxpacksize,const RTPTransmissionParams *transparams) = 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
virtual RTPTransmissionInfo *GetTransmissionInfo() = 0;
@ -108,6 +111,7 @@ public:
virtual bool NewDataAvailable() = 0;
virtual RTPRawPacket *GetNextPacket() = 0;
#ifdef RTPDEBUG
virtual void Dump() = 0;
#endif // RTPDEBUG

View File

@ -673,6 +673,17 @@ int RTPUDPv4Transmitter::AbortWait()
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)
{
if (!init)

View File

@ -71,29 +71,16 @@ private:
class RTPUDPv4TransmissionInfo : public RTPTransmissionInfo
{
public:
#if ! (defined(WIN32) || defined(_WIN32_WCE))
RTPUDPv4TransmissionInfo(std::list<u_int32_t> iplist,int rtpsock,int 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; }
RTPUDPv4TransmissionInfo(std::list<u_int32_t> iplist,jrtp_socket_t rtpsock,jrtp_socket_t rtcpsock) : RTPTransmissionInfo(RTPTransmitter::IPv4UDPProto)
{ localIPlist = iplist; rtpsocket = rtpsock; rtcpsocket = rtcpsock; }
~RTPUDPv4TransmissionInfo() { }
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:
std::list<u_int32_t> localIPlist;
#if ! (defined(WIN32) || defined(_WIN32_WCE))
int rtpsocket,rtcpsocket;
#else
SOCKET rtpsocket,rtcpsocket;
#endif // WIN32
jrtp_socket_t rtpsocket,rtcpsocket;
};
#ifdef RTP_SUPPORT_INLINETEMPLATEPARAM
@ -112,6 +99,8 @@ public:
RTPUDPv4Transmitter();
~RTPUDPv4Transmitter();
jrtp_socket_t RTPUDPv4Transmitter::GetRTPSocket();
jrtp_socket_t RTPUDPv4Transmitter::GetRTCPSocket();
int Init(bool treadsafe);
int Create(size_t maxpacksize,const RTPTransmissionParams *transparams);
void Destroy();
@ -173,11 +162,7 @@ private:
bool init;
bool created;
bool waitingfordata;
#if (defined(WIN32) || defined(_WIN32_WCE))
SOCKET rtpsock,rtcpsock;
#else // not using winsock
int rtpsock,rtcpsock;
#endif // WIN32
jrtp_socket_t rtpsock,rtcpsock;
u_int32_t bindIP;
std::list<u_int32_t> localIPs;
u_int16_t portbase;
@ -208,11 +193,7 @@ private:
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)
#if (defined(WIN32) || defined(_WIN32_WCE))
SOCKET abortdesc[2];
#else
int abortdesc[2];
#endif // WIN32
jrtp_socket_t abortdesc[2];
int CreateAbortDescriptors();
void DestroyAbortDescriptors();
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) {
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 {
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);
iks_insert_attrib(msg, "subject", "Event");
iks_send(globals.session.parser, msg);
iks_delete(msg);
break;
}
}

View File

@ -491,6 +491,7 @@ static JSBool session_speak(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
char *voice_name = NULL;
char *text = NULL;
char *dtmf_callback = NULL;
char *timer_name = NULL;
switch_codec *codec;
void *bp = NULL;
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) {
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,
tts_name,
voice_name && strlen(voice_name) ? voice_name : NULL,
NULL,
timer_name,
codec->implementation->samples_per_second,
dtmf_func,
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(peer_channel, &audio_bridge_peer_state_handlers);
switch_core_session_thread_launch(peer_session);
time(&start);
for (;;) {
int state = switch_channel_get_state(peer_channel);
if (state > CS_RING) {
break;
}
if (!switch_channel_ready(caller_channel)) {
break;
}
if ((time(NULL) - start) > timelimit) {
break;
}
switch_yield(1000);
}
switch_channel_pre_answer(caller_channel);
time(&start);
while (switch_channel_ready(caller_channel) &&
switch_channel_ready(peer_channel) &&
!switch_channel_test_flag(peer_channel, CF_ANSWERED) &&
!switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) &&
((time(NULL) - start) < timelimit)) {
/* 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_core_session_read_frame(session, &read_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) {