Upgrade Dingaling to meet new googletalk spec upgrade your client if you have issues.

codecs need more work...

Expose events into javascript so you can create and fire events and 
and pick up chat events with chat-enabled clients like googletalk
EXAMPLE:

session.answer();

e = new Event("custom", "JS::Custom");
e.addHeader("subject", "cool");
e.addBody("hello this is a test");
e.fire;

while(session.ready()) {
    session.execute("sleep", "1000");
    event = session.getEvent();
    if (event) {
      str = event.serialize(); // or ("xml")
      console_log("debug", "Dump Event:\n" + str + "\n");


        e = new Event("custom", "JS::Chat");
        e.addHeader("works", "yes");
        e.addBody("you said: " + event.getBody());
        session.sendEvent(e);
      event.destroy();
    }
}





git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2323 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2006-08-18 01:28:50 +00:00
parent 099a771ddf
commit 47192db741
10 changed files with 520 additions and 38 deletions

View File

@ -190,6 +190,11 @@ char *ldl_session_get_id(ldl_session_t *session)
return session->id;
}
void ldl_session_send_msg(ldl_session_t *session, char *subject, char *body)
{
ldl_handle_send_msg(session->handle, session->them, subject, body);
}
ldl_status ldl_session_destroy(ldl_session_t **session_p)
{
ldl_session_t *session = *session_p;
@ -277,7 +282,7 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
while(xml) {
char *type = xtype ? xtype : iks_find_attrib(xml, "type");
iks *tag;
if (type) {
if (!strcasecmp(type, "initiate") || !strcasecmp(type, "accept")) {
@ -298,7 +303,7 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
if (!strcasecmp(iks_name(itag), "payload-type") && session->payload_len < LDL_MAX_PAYLOADS) {
char *name = iks_find_attrib(itag, "name");
char *id = iks_find_attrib(itag, "id");
char *rate = iks_find_attrib(itag, "rate");
char *rate = iks_find_attrib(itag, "clockrate");
if (name && id) {
session->payloads[session->payload_len].name = apr_pstrdup(session->pool, name);
session->payloads[session->payload_len].id = atoi(id);
@ -317,10 +322,15 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
}
tag = iks_next_tag(tag);
}
} else if (!strcasecmp(type, "candidates")) {
} else if (!strcasecmp(type, "transport-info")) {
char *tid = iks_find_attrib(xml, "id");
signal = LDL_SIGNAL_CANDIDATES;
tag = iks_child (xml);
if (tag && !strcasecmp(iks_name(tag), "transport")) {
tag = iks_child(tag);
}
while(tag) {
if (!strcasecmp(iks_name(tag), "info_element")) {
char *name = iks_find_attrib(tag, "name");
@ -354,6 +364,11 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
}
session->candidates[index].pref = pref;
if (tid) {
session->candidates[index].tid = apr_pstrdup(session->pool, tid);
}
if ((key = iks_find_attrib(tag, "name"))) {
session->candidates[index].name = apr_pstrdup(session->pool, key);
}
@ -427,8 +442,8 @@ static int on_presence(void *user_data, ikspak *pak)
struct ldl_buffer *buffer;
size_t x;
iks *msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, from, "Ding A Ling....");
apr_queue_push(handle->queue, msg);
//iks *msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, from, "Ding A Ling....");
//apr_queue_push(handle->queue, msg);
apr_cpystrn(id, from, sizeof(id));
@ -1087,6 +1102,31 @@ void *ldl_session_get_private(ldl_session_t *session)
return session->private_data;
}
void ldl_session_accept_candidate(ldl_session_t *session, ldl_candidate_t *candidate)
{
iks *iq, *sess, *tp;
unsigned int myid;
char idbuf[80];
myid = next_id();
snprintf(idbuf, sizeof(idbuf), "%u", myid);
iq = iks_new("iq");
iks_insert_attrib(iq, "type", "set");
iks_insert_attrib(iq, "id", idbuf);
iks_insert_attrib(iq, "from", session->handle->login);
iks_insert_attrib(iq, "to", session->them);
sess = iks_insert (iq, "session");
iks_insert_attrib(sess, "xmlns", "http://www.google.com/session");
iks_insert_attrib(sess, "type", "transport-accept");
iks_insert_attrib(sess, "id", candidate->tid);
iks_insert_attrib(sess, "xmlns", "http://www.google.com/session");
iks_insert_attrib(sess, "initiator", session->initiator ? session->initiator : session->them);
tp = iks_insert (sess, "transport");
iks_insert_attrib(tp, "xmlns", "http://www.google.com/transport/p2p");
apr_queue_push(session->handle->queue, iq);
}
void *ldl_handle_get_private(ldl_handle_t *handle)
{
return handle->private_info;
@ -1128,18 +1168,27 @@ unsigned int ldl_session_terminate(ldl_session_t *session)
}
unsigned int ldl_session_candidates(ldl_session_t *session,
ldl_candidate_t *candidates,
unsigned int clen)
ldl_candidate_t *candidates,
unsigned int clen)
{
iks *iq, *sess, *tag;
unsigned int x, id;
new_session_iq(session, &iq, &sess, &id, "candidates");
for (x = 0; x < clen; x++) {
char buf[512];
tag = iks_insert(sess, "candidate");
iq = NULL;
sess = NULL;
id = 0;
new_session_iq(session, &iq, &sess, &id, "transport-info");
tag = iks_insert(sess, "transport");
iks_insert_attrib(tag, "xmlns", "http://www.google.com/transport/p2p");
tag = iks_insert(tag, "candidate");
if (candidates[x].name) {
iks_insert_attrib(tag, "name", candidates[x].name);
}
@ -1169,13 +1218,13 @@ unsigned int ldl_session_candidates(ldl_session_t *session,
iks_insert_attrib(tag, "network", "0");
iks_insert_attrib(tag, "generation", "0");
schedule_packet(session->handle, id, iq, LDL_RETRY);
}
schedule_packet(session->handle, id, iq, LDL_RETRY);
return id;
}
char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *buf, unsigned int len)
{
iks *pres, *msg;
@ -1232,13 +1281,14 @@ unsigned int ldl_session_describe(ldl_session_t *session,
unsigned int plen,
ldl_description_t description)
{
iks *iq, *sess, *tag, *payload;
iks *iq, *sess, *tag, *payload, *tp;
unsigned int x, id;
new_session_iq(session, &iq, &sess, &id, description == LDL_DESCRIPTION_ACCEPT ? "accept" : "initiate");
tag = iks_insert(sess, "description");
iks_insert_attrib(tag, "xmlns", "http://www.google.com/session/phone");
iks_insert_attrib(tag, "xml:lang", "en");
for (x = 0; x < plen; x++) {
char idbuf[80];
payload = iks_insert(tag, "payload-type");
@ -1249,10 +1299,19 @@ unsigned int ldl_session_describe(ldl_session_t *session,
iks_insert_attrib(payload, "name", payloads[x].name);
if (payloads[x].rate) {
sprintf(idbuf, "%d", payloads[x].rate);
iks_insert_attrib(payload, "rate", idbuf);
iks_insert_attrib(payload, "clockrate", idbuf);
}
if (payloads[x].bps) {
sprintf(idbuf, "%d", payloads[x].bps);
iks_insert_attrib(payload, "bitrate", idbuf);
}
}
if (description == LDL_DESCRIPTION_INITIATE) {
tp = iks_insert (sess, "transport");
iks_insert_attrib(tp, "xmlns", "http://www.google.com/transport/p2p");
}
schedule_packet(session->handle, id, iq, LDL_RETRY);
return id;

View File

@ -53,6 +53,8 @@ extern "C" {
/*! \brief A structure to store a jingle candidate */
struct ldl_candidate {
/*! the transport id of the candidate */
char *tid;
/*! the name of the candidate */
char *name;
/*! the type of the candidate */
@ -80,6 +82,8 @@ struct ldl_payload {
unsigned int id;
/*! the transfer rate of the payload type */
unsigned int rate;
/*! the bits per second of the payload type */
unsigned int bps;
};
typedef struct ldl_payload ldl_payload_t;
@ -286,6 +290,13 @@ void ldl_session_set_private(ldl_session_t *session, void *private_data);
*/
void *ldl_session_get_private(ldl_session_t *session);
/*!
\brief Accept a candidate
\param session the session to accept on
\param candidate the candidate to accept
*/
void ldl_session_accept_candidate(ldl_session_t *session, ldl_candidate_t *candidate);
/*!
\brief Set a custom logger
\param logger the logger function
@ -316,6 +327,14 @@ unsigned int ldl_session_terminate(ldl_session_t *session);
*/
void *ldl_handle_get_private(ldl_handle_t *handle);
/*!
\brief Send a message to a session
\param session the session handle
\param to the message recipiant
\param subject optional subject
\param body body of the message
*/
void ldl_session_send_msg(ldl_session_t *session, char *subject, char *body);
/*!
\brief Send a message

View File

@ -443,6 +443,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_receive_message(switch_core_
*/
SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(switch_core_session_t *session, switch_event_t **event);
/*!
\brief Indicate the number of waiting events on a session
\param session the session to check
\return the number of events
*/
SWITCH_DECLARE(int32_t) switch_core_session_event_count(switch_core_session_t *session);
/*!
\brief DE-Queue an event on a given session
\param session the session to de-queue the message on

View File

@ -155,6 +155,13 @@ SWITCH_DECLARE(switch_status_t) switch_event_set_priority(switch_event_t *event,
*/
SWITCH_DECLARE(char *) switch_event_get_header(switch_event_t *event, char *header_name);
/*!
\brief Retrieve the body value from an event
\param event the event to read the body from
\return the value of the body or NULL
*/
SWITCH_DECLARE(char *) switch_event_get_body(switch_event_t *event);
/*!
\brief Add a header to an event
\param event the event to add the header to

View File

@ -271,7 +271,7 @@ static const switch_codec_implementation_t speex_32k_implementation = {
/*.ianacode */ 102,
/*.iananame */ "speex",
/*.samples_per_second */ 32000,
/*.bits_per_second */ 512000,
/*.bits_per_second */ 256000,
/*.nanoseconds_per_frame */ 20000,
/*.samples_per_frame */ 640,
/*.bytes_per_frame */ 1280,
@ -289,8 +289,8 @@ static const switch_codec_implementation_t speex_16k_implementation = {
/*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 100,
/*.iananame */ "speex",
/*.samples_per_second */ 16000,
/*.bits_per_second */ 256000,
/*.samples_per_second */ 22000,
/*.bits_per_second */ 128000,
/*.nanoseconds_per_frame */ 20000,
/*.samples_per_frame */ 320,
/*.bytes_per_frame */ 640,
@ -310,11 +310,11 @@ static const switch_codec_implementation_t speex_8k_implementation = {
/*.ianacode */ 97,
/*.iananame */ "speex",
/*.samples_per_second */ 8000,
/*.bits_per_second */ 128000,
/*.bits_per_second */ 11000,
/*.nanoseconds_per_frame */ 20000,
/*.samples_per_frame */ 160,
/*.bytes_per_frame */ 320,
/*.encoded_bytes_per_frame */ 0,
/*.encoded_bytes_per_frame */ 28,
/*.number_of_channels */ 1,
/*.pref_frames_per_packet */ 1,
/*.max_frames_per_packet */ 1,

View File

@ -134,6 +134,7 @@ struct private_object {
uint32_t last_read;
char *codec_name;
switch_payload_t codec_num;
switch_payload_t r_codec_num;
switch_time_t next_desc;
switch_time_t next_cand;
char *stun_ip;
@ -244,7 +245,7 @@ static int activate_rtp(struct private_object *tech_pvt)
switch_rtp_flag_t flags;
if (tech_pvt->rtp_session) {
return 0;
return 1;
}
if (!strncasecmp(tech_pvt->codec_name, "ilbc", 4)) {
@ -260,7 +261,7 @@ static int activate_rtp(struct private_object *tech_pvt)
NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Can't load codec?\n");
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return -1;
return 0;
}
tech_pvt->read_frame.rate = tech_pvt->read_codec.implementation->samples_per_second;
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
@ -276,7 +277,7 @@ static int activate_rtp(struct private_object *tech_pvt)
NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Can't load codec?\n");
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return -1;
return 0;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set Write Codec to %s\n", tech_pvt->codec_name);
@ -287,6 +288,7 @@ static int activate_rtp(struct private_object *tech_pvt)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SETUP RTP %s:%d -> %s:%d\n", tech_pvt->profile->ip, tech_pvt->local_port, tech_pvt->remote_ip, tech_pvt->remote_port);
flags = SWITCH_RTP_FLAG_GOOGLEHACK | SWITCH_RTP_FLAG_AUTOADJ;
//flags = SWITCH_RTP_FLAG_AUTOADJ;
if (switch_test_flag(tech_pvt->profile, TFLAG_TIMER)) {
flags |= SWITCH_RTP_FLAG_USE_TIMER;
@ -304,7 +306,7 @@ static int activate_rtp(struct private_object *tech_pvt)
&err, switch_core_session_get_pool(tech_pvt->session)))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RTP ERROR %s\n", err);
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return -1;
return 0;
} else {
uint8_t vad_in = switch_test_flag(tech_pvt, TFLAG_VAD_IN) ? 1 : 0;
uint8_t vad_out = switch_test_flag(tech_pvt, TFLAG_VAD_OUT) ? 1 : 0;
@ -316,7 +318,7 @@ static int activate_rtp(struct private_object *tech_pvt)
}
}
return 0;
return 1;
}
@ -444,18 +446,23 @@ static int do_describe(struct private_object *tech_pvt, int force)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Don't have my codec yet here's one\n");
tech_pvt->codec_name = lame(tech_pvt->codecs[0]->iananame);
tech_pvt->codec_num = tech_pvt->codecs[0]->ianacode;
tech_pvt->r_codec_num = tech_pvt->codecs[0]->ianacode;
tech_pvt->codec_index = 0;
payloads[0].name = lame(tech_pvt->codecs[0]->iananame);
payloads[0].id = tech_pvt->codecs[0]->ianacode;
payloads[0].rate = tech_pvt->codecs[0]->samples_per_second;
payloads[0].bps = tech_pvt->codecs[0]->bits_per_second;
} else {
payloads[0].name = lame(tech_pvt->codecs[tech_pvt->codec_index]->iananame);
payloads[0].id = tech_pvt->codecs[tech_pvt->codec_index]->ianacode;
payloads[0].rate = tech_pvt->codecs[0]->samples_per_second;
payloads[0].bps = tech_pvt->codecs[0]->bits_per_second;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send Describe [%s]\n", payloads[0].name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send Describe [%s@%d]\n", payloads[0].name, payloads[0].rate);
tech_pvt->desc_id = ldl_session_describe(tech_pvt->dlsession, payloads, 1,
switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ? LDL_DESCRIPTION_INITIATE : LDL_DESCRIPTION_ACCEPT);
switch_set_flag_locked(tech_pvt, TFLAG_CODEC_READY);
@ -499,7 +506,7 @@ static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread_t *thread, vo
elapsed = (unsigned int)((now - started) / 1000);
if (switch_channel_get_state(channel) >= CS_HANGUP || switch_test_flag(tech_pvt, TFLAG_BYE)) {
return NULL;
goto out;
}
@ -528,10 +535,12 @@ static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread_t *thread, vo
}
if (switch_channel_get_state(channel) >= CS_HANGUP || switch_test_flag(tech_pvt, TFLAG_BYE)) {
return NULL;
goto out;
}
activate_rtp(tech_pvt);
if (!activate_rtp(tech_pvt)) {
goto out;
}
if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
do_candidates(tech_pvt, 0);
@ -542,6 +551,13 @@ static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread_t *thread, vo
}
switch_channel_set_state(channel, CS_INIT);
return NULL;
out:
if (!switch_core_session_runing(tech_pvt->session)) {
channel_on_hangup(tech_pvt->session);
switch_core_session_destroy(&tech_pvt->session);
}
return NULL;
}
@ -920,6 +936,33 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
{
switch_channel_t *channel;
struct private_object *tech_pvt;
char *subject, *body;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
if (!(body = switch_event_get_body(event))) {
body = "";
}
if (!(subject = switch_event_get_header(event, "subject"))) {
subject = "None";
}
ldl_session_send_msg(tech_pvt->dlsession, subject, body);
return SWITCH_STATUS_SUCCESS;
}
static const switch_state_handler_table_t channel_event_handlers = {
/*.on_init */ channel_on_init,
/*.on_ring */ channel_on_ring,
@ -938,7 +981,8 @@ static const switch_io_routines_t channel_io_routines = {
/*.waitfor_read */ channel_waitfor_read,
/*.waitfor_write */ channel_waitfor_write,
/*.send_dtmf */ channel_send_dtmf,
/*.receive_message*/ channel_receive_message
/*.receive_message*/ channel_receive_message,
/*.receive_event*/ channel_receive_event
};
static const switch_endpoint_interface_t channel_endpoint_interface = {
@ -1531,7 +1575,9 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
if (*msg == '+') {
switch_channel_queue_dtmf(channel, msg + 1);
switch_set_flag_locked(tech_pvt, TFLAG_DTMF);
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_BREAK);
if (tech_pvt->rtp_session) {
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_BREAK);
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "SESSION MSG [%s]\n", msg);
}
@ -1594,11 +1640,12 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
match = (payloads[x].id == tech_pvt->codecs[y]->ianacode) ? 1 : 0;
}
if (match) {
if (match && payloads[x].rate == tech_pvt->codecs[y]->samples_per_second) {
tech_pvt->codec_index = y;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Choosing Payload index %u %s %u\n", y, payloads[x].name, payloads[x].id);
tech_pvt->codec_name = tech_pvt->codecs[y]->iananame;
tech_pvt->codec_num = tech_pvt->codecs[y]->ianacode;
tech_pvt->r_codec_num = payloads[x].id;
if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
do_describe(tech_pvt, 0);
}
@ -1663,7 +1710,9 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Acceptable Candidate %s:%d\n", candidates[x].address, candidates[x].port);
if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
ldl_session_accept_candidate(dlsession, &candidates[x]);
}
if (!(exten = ldl_session_get_value(dlsession, "dnis"))) {
exten = profile->exten;
@ -1719,10 +1768,13 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
ldl_session_set_ip(dlsession, tech_pvt->remote_ip);
tech_pvt->remote_port = candidates[x].port;
tech_pvt->remote_user = switch_core_session_strdup(session, candidates[x].username);
if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
do_candidates(tech_pvt, 0);
}
switch_set_flag_locked(tech_pvt, TFLAG_TRANSPORT);
return LDL_STATUS_SUCCESS;

View File

@ -149,6 +149,262 @@ struct db_obj {
};
/* Event Object */
/*********************************************************************************/
static JSBool event_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
if (argc > 0) {
switch_event_t *event;
switch_event_types_t etype;
char *ename = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
if (switch_name_event(ename, &etype) != SWITCH_STATUS_SUCCESS) {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
if (etype == SWITCH_EVENT_CUSTOM) {
char *subclass_name;
if (argc < 1) {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
subclass_name = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
if (switch_event_create_subclass(&event, etype, subclass_name) != SWITCH_STATUS_SUCCESS) {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
} else {
if (!switch_event_create(&event, etype) != SWITCH_STATUS_SUCCESS) {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
}
JS_SetPrivate(cx, obj, event);
return JS_TRUE;
}
return JS_FALSE;
}
static void event_destroy(JSContext *cx, JSObject *obj)
{
switch_event_t *event = JS_GetPrivate(cx, obj);
if (event) {
switch_event_destroy(&event);
}
}
static JSBool event_add_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
switch_event_t *event = JS_GetPrivate(cx, obj);
if (!event) {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
if (argc > 1) {
char *hname = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
char *hval = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, hname, hval);
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
return JS_TRUE;
}
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
static JSBool event_get_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
switch_event_t *event = JS_GetPrivate(cx, obj);
if (!event) {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
if (argc > 0) {
char *hname = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
char *val = switch_event_get_header(event, hname);
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, val));
return JS_TRUE;
}
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
static JSBool event_add_body(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
switch_event_t *event = JS_GetPrivate(cx, obj);
if (!event) {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
if (argc > 0) {
char *body = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
switch_event_add_body(event, body);
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
return JS_TRUE;
}
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
static JSBool event_get_body(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
switch_event_t *event = JS_GetPrivate(cx, obj);
if (!event) {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_event_get_body(event)));
return JS_TRUE;
}
static JSBool event_serialize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
switch_event_t *event = JS_GetPrivate(cx, obj);
char buf[1024];
uint8_t isxml = 0;
if (!event) {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
if (argc > 0) {
char *arg = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
if (!strcasecmp(arg, "xml")) {
isxml++;
}
}
if (isxml) {
switch_xml_t xml;
char *xmlstr;
if ((xml = switch_event_xmlize(event, NULL))) {
xmlstr = switch_xml_toxml(xml);
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, xmlstr));
switch_xml_free(xml);
free(xmlstr);
} else {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
}
} else {
switch_event_serialize(event, buf, sizeof(buf), NULL);
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, buf));
}
return JS_TRUE;
}
static JSBool event_fire(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
switch_event_t *event = JS_GetPrivate(cx, obj);
if (event) {
switch_event_fire(&event);
JS_SetPrivate(cx, obj, NULL);
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
return JS_TRUE;
}
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
static JSBool event_destroy_(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
switch_event_t *event = JS_GetPrivate(cx, obj);
if (event) {
switch_event_destroy(&event);
JS_SetPrivate(cx, obj, NULL);
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
return JS_TRUE;
}
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
enum event_tinyid {
EVENT_READY
};
static JSFunctionSpec event_methods[] = {
{"addHeader", event_add_header, 1},
{"getHeader", event_get_header, 1},
{"addBody", event_add_body, 1},
{"getBody", event_get_body, 1},
{"serialize", event_serialize, 0},
{"fire", event_fire, 0},
{"destroy", event_destroy_, 0},
{0}
};
static JSPropertySpec event_props[] = {
{"ready", EVENT_READY, JSPROP_READONLY|JSPROP_PERMANENT},
{0}
};
static JSBool event_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
JSBool res = JS_TRUE;
switch_event_t *event = JS_GetPrivate(cx, obj);
char *name;
int param = 0;
if (!event) {
*vp = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
name = JS_GetStringBytes(JS_ValueToString(cx, id));
/* numbers are our props anything else is a method */
if (name[0] >= 48 && name[0] <= 57) {
param = atoi(name);
} else {
return JS_TRUE;
}
switch(param) {
case EVENT_READY:
*vp = BOOLEAN_TO_JSVAL( JS_TRUE );
break;
}
return res;
}
JSClass event_class = {
"Event", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, event_getProperty, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, event_destroy, NULL, NULL, NULL,
event_construct
};
static void js_error(JSContext *cx, const char *message, JSErrorReport *report)
{
if (message) {
@ -681,6 +937,52 @@ static JSBool session_execute(JSContext *cx, JSObject *obj, uintN argc, jsval *a
return JS_TRUE;
}
static JSBool session_get_event(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
struct js_session *jss = JS_GetPrivate(cx, obj);
switch_event_t *event;
if (switch_core_session_dequeue_event(jss->session, &event) == SWITCH_STATUS_SUCCESS) {
JSObject *Event;
if ((Event = JS_DefineObject(cx, obj, "Event", &event_class, NULL, 0))) {
if ((JS_SetPrivate(cx, Event, event) &&
JS_DefineProperties(cx, Event, event_props) &&
JS_DefineFunctions(cx, Event, event_methods))) {
*rval = OBJECT_TO_JSVAL ( Event );
return JS_TRUE;
}
}
}
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
static JSBool session_send_event(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
struct js_session *jss = JS_GetPrivate(cx, obj);
switch_event_t *event;
JSObject *Event;
if (argc > 0) {
if (JS_ValueToObject(cx, argv[0], &Event)) {
if ((event = JS_GetPrivate(cx, Event))) {
if (switch_core_session_receive_event(jss->session, &event) != SWITCH_STATUS_SUCCESS) {
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
return JS_TRUE;
}
JS_SetPrivate(cx, Event, NULL);
}
}
}
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
return JS_TRUE;
}
static JSBool session_hangup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
@ -845,6 +1147,7 @@ static JSBool js_fetchurl_file(JSContext *cx, JSObject *obj, uintN argc, jsval *
}
#endif
/* Session Object */
/*********************************************************************************/
enum session_tinyid {
@ -860,6 +1163,8 @@ static JSFunctionSpec session_methods[] = {
{"answer", session_answer, 0},
{"ready", session_ready, 0},
{"waitForAnswer", session_wait_for_answer, 0},
{"getEvent", session_get_event, 0},
{"sendEvent", session_send_event, 0},
{"hangup", session_hangup, 0},
{"execute", session_execute, 0},
{0}
@ -2126,6 +2431,18 @@ static int env_init(JSContext *cx, JSObject *javascript_object)
db_methods
);
JS_InitClass(cx,
javascript_object,
NULL,
&event_class,
event_construct,
3,
event_props,
event_methods,
event_props,
event_methods
);
return 1;
}

View File

@ -1174,6 +1174,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(switch_core_sess
return status;
}
SWITCH_DECLARE(int32_t) switch_core_session_event_count(switch_core_session_t *session)
{
if (session->event_queue) {
return (int32_t) switch_queue_size(session->event_queue);
}
return -1;
}
SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_event(switch_core_session_t *session, switch_event_t **event)
{

View File

@ -393,6 +393,15 @@ SWITCH_DECLARE(char *) switch_event_get_header(switch_event_t *event, char *head
return NULL;
}
SWITCH_DECLARE(char *) switch_event_get_body(switch_event_t *event)
{
if (event) {
return event->body;
}
return NULL;
}
SWITCH_DECLARE(switch_status_t) switch_event_add_header(switch_event_t *event, switch_stack_t stack, char *header_name,
char *fmt, ...)
{
@ -623,7 +632,7 @@ SWITCH_DECLARE(switch_xml_t) switch_event_xmlize(switch_event_t *event, char *fm
switch_xml_t xbody = NULL;
add_xml_header(xml, "Content-Length", blena, off++);
if ((xbody = switch_xml_add_child_d(xml, "body", 0))) {
if ((xbody = switch_xml_add_child_d(xml, "body", off++))) {
switch_xml_set_txt_d(xbody, body);
}
}

View File

@ -1012,7 +1012,7 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len,
char *txt = (xml->parent) ? xml->parent->txt : "";
switch_size_t off = 0;
uint32_t lcount = 0;
// parent character content up to this tag
*s = switch_xml_ampencode(txt + start, xml->off - start, s, len, max, 0);
@ -1045,11 +1045,13 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len,
switch_xml_ampencode(attr[i][j + 1], 0, s, len, max, 1);
*len += sprintf(*s + *len, "\"");
}
*len += sprintf(*s + *len, xml->child ? ">\n" : "/>\n");
*len += sprintf(*s + *len, (xml->child || xml->txt) ? ">" : "/>\n");
if (xml->child) {
(*count)++;
*s = switch_xml_toxml_r(xml->child, s, len, max, 0, attr, count);
} else {
*s = switch_xml_ampencode(xml->txt, 0, s, len, max, 0); //data
}
@ -1058,10 +1060,10 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len,
*s = realloc(*s, *max += SWITCH_XML_BUFSIZE);
if (xml->child) {
for (lcount = 0; lcount < *count; lcount++) {
*len += sprintf(*s + *len, "%s", XML_INDENT); // indent
}
if (xml->child || xml->txt) {
//for (lcount = 0; lcount < *count; lcount++) {
//*len += sprintf(*s + *len, "%s", XML_INDENT); // indent
//}
*len += sprintf(*s + (*len), "</%s>\n", xml->name); // close tag
}