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;
while(xml) {
char *type = xtype ? xtype : iks_find_attrib(xml, "type");
iks *tag;
-
+
if (type) {
if (!strcasecmp(type, "initiate") || !strcasecmp(type, "accept")) {
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);
}
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");
}
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);
}
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));
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;
}
+
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);
}
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;
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");
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;
/*! \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 */
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;
*/
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
*/
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
*/
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
*/
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
/*.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,
/*.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,
/*.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,
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;
switch_rtp_flag_t flags;
if (tech_pvt->rtp_session) {
- return 0;
+ return 1;
}
if (!strncasecmp(tech_pvt->codec_name, "ilbc", 4)) {
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;
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);
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;
&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;
}
}
- return 0;
+ return 1;
}
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);
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;
}
}
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);
}
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;
}
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,
/*.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 = {
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);
}
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);
}
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;
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;
};
+/* 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) {
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)
{
}
#endif
+
/* Session Object */
/*********************************************************************************/
enum session_tinyid {
{"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}
db_methods
);
+ JS_InitClass(cx,
+ javascript_object,
+ NULL,
+ &event_class,
+ event_construct,
+ 3,
+ event_props,
+ event_methods,
+ event_props,
+ event_methods
+ );
+
return 1;
}
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)
{
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, ...)
{
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);
}
}
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);
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
}
*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
}