FS-2731 significantly reworked version of Emmanuel's patch to allow subscribing and notifying for the as-feature-event events. we still need a module to handle the FS events for this automatically... coming soon to a repository near you

This commit is contained in:
Raymond Chandler 2013-08-23 15:54:49 -04:00
parent a524fadf17
commit 863e6cfa3f
8 changed files with 734 additions and 414 deletions

View File

@ -98,6 +98,8 @@ static const char *EVENT_NAMES[] = {
"MESSAGE", "MESSAGE",
"PRESENCE_IN", "PRESENCE_IN",
"NOTIFY_IN", "NOTIFY_IN",
"PHONE_FEATURE",
"PHONE_FEATURE_SUBSCRIBE",
"PRESENCE_OUT", "PRESENCE_OUT",
"PRESENCE_PROBE", "PRESENCE_PROBE",
"MESSAGE_WAITING", "MESSAGE_WAITING",

View File

@ -1681,6 +1681,8 @@ typedef uint32_t switch_io_flag_t;
SWITCH_EVENT_RE_SCHEDULE - Something scheduled has been rescheduled SWITCH_EVENT_RE_SCHEDULE - Something scheduled has been rescheduled
SWITCH_EVENT_RELOADXML - XML registry has been reloaded SWITCH_EVENT_RELOADXML - XML registry has been reloaded
SWITCH_EVENT_NOTIFY - Notification SWITCH_EVENT_NOTIFY - Notification
SWITCH_EVENT_PHONE_FEATURE - Notification (DND/CFWD/etc)
SWITCH_EVENT_PHONE_FEATURE_SUBSCRIBE - Phone feature subscription
SWITCH_EVENT_SEND_MESSAGE - Message SWITCH_EVENT_SEND_MESSAGE - Message
SWITCH_EVENT_RECV_MESSAGE - Message SWITCH_EVENT_RECV_MESSAGE - Message
SWITCH_EVENT_NAT - NAT Management (new/del/status) SWITCH_EVENT_NAT - NAT Management (new/del/status)
@ -1748,6 +1750,8 @@ typedef enum {
SWITCH_EVENT_RE_SCHEDULE, SWITCH_EVENT_RE_SCHEDULE,
SWITCH_EVENT_RELOADXML, SWITCH_EVENT_RELOADXML,
SWITCH_EVENT_NOTIFY, SWITCH_EVENT_NOTIFY,
SWITCH_EVENT_PHONE_FEATURE,
SWITCH_EVENT_PHONE_FEATURE_SUBSCRIBE,
SWITCH_EVENT_SEND_MESSAGE, SWITCH_EVENT_SEND_MESSAGE,
SWITCH_EVENT_RECV_MESSAGE, SWITCH_EVENT_RECV_MESSAGE,
SWITCH_EVENT_REQUEST_PARAMS, SWITCH_EVENT_REQUEST_PARAMS,

View File

@ -4582,6 +4582,70 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
return cause; return cause;
} }
static int notify_csta_callback(void *pArg, int argc, char **argv, char **columnNames)
{
nua_handle_t *nh;
sofia_profile_t *ext_profile = NULL, *profile = (sofia_profile_t *) pArg;
int i = 0;
char *user = argv[i++];
char *host = argv[i++];
char *contact_in = argv[i++];
char *profile_name = argv[i++];
char *call_id = argv[i++];
char *full_from = argv[i++];
char *full_to = argv[i++];
int expires = atoi(argv[i++]);
char *body = argv[i++];
char *ct = argv[i++];
char *id = NULL;
char *contact;
sofia_destination_t *dst = NULL;
char *route_uri = NULL;
time_t epoch_now = switch_epoch_time_now(NULL);
time_t expires_in = (expires - epoch_now);
char *extra_headers = switch_mprintf("Subscription-State: active, %d\r\n", expires_in);
if (profile_name && strcasecmp(profile_name, profile->name)) {
if ((ext_profile = sofia_glue_find_profile(profile_name))) {
profile = ext_profile;
}
}
id = switch_mprintf("sip:%s@%s", user, host);
switch_assert(id);
contact = sofia_glue_get_url_from_contact(contact_in, 1);
dst = sofia_glue_get_destination((char *) contact);
if (dst->route_uri) {
route_uri = sofia_glue_strip_uri(dst->route_uri);
}
//nh = nua_handle(profile->nua, NULL, NUTAG_URL(dst->contact), SIPTAG_FROM_STR(id), SIPTAG_TO_STR(id), SIPTAG_CONTACT_STR(profile->url), TAG_END());
nh = nua_handle(profile->nua, NULL, NUTAG_URL(dst->contact), SIPTAG_FROM_STR(full_from), SIPTAG_TO_STR(full_to), SIPTAG_CONTACT_STR(profile->url), TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
nua_notify(nh, NUTAG_NEWSUB(1),
TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)),
SIPTAG_EVENT_STR("as-feature-event"), SIPTAG_CONTENT_TYPE_STR(ct), TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)), TAG_END());
switch_safe_free(route_uri);
sofia_glue_free_destination(dst);
free(id);
free(contact);
if (ext_profile) {
sofia_glue_release_profile(ext_profile);
}
return 0;
}
static int notify_callback(void *pArg, int argc, char **argv, char **columnNames) static int notify_callback(void *pArg, int argc, char **argv, char **columnNames)
{ {
@ -4655,22 +4719,69 @@ static void general_event_handler(switch_event_t *event)
const char *to_uri = switch_event_get_header(event, "to-uri"); const char *to_uri = switch_event_get_header(event, "to-uri");
const char *from_uri = switch_event_get_header(event, "from-uri"); const char *from_uri = switch_event_get_header(event, "from-uri");
const char *extra_headers = switch_event_get_header(event, "extra-headers"); const char *extra_headers = switch_event_get_header(event, "extra-headers");
const char *contact_uri = switch_event_get_header(event, "contact-uri");
const char *no_sub_state = switch_event_get_header(event, "no-sub-state");
sofia_profile_t *profile; sofia_profile_t *profile;
if (contact_uri) {
if (!es) {
es = "message-summary";
}
if (to_uri || from_uri) { if (!ct) {
ct = "application/simple-message-summary";
}
if (!to_uri) { if (!profile_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To-URI header\n"); profile_name = "default";
}
if (!(profile = sofia_glue_find_profile(profile_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find profile %s\n", profile_name);
return; return;
} }
if (!from_uri) { if (to_uri && from_uri) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing From-URI header\n"); sofia_destination_t *dst = NULL;
return; nua_handle_t *nh;
char *route_uri = NULL;
char *sip_sub_st = NULL;
dst = sofia_glue_get_destination((char *) contact_uri);
if (dst->route_uri) {
route_uri = sofia_glue_strip_uri(dst->route_uri);
}
nh = nua_handle(profile->nua,
NULL,
NUTAG_URL(dst->contact),
SIPTAG_FROM_STR(from_uri),
SIPTAG_TO_STR(to_uri),
SIPTAG_CONTACT_STR(profile->url),
TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
if (!switch_true(no_sub_state)) {
sip_sub_st = "terminated;reason=noresource";
}
nua_notify(nh,
NUTAG_NEWSUB(1), TAG_IF(sip_sub_st, SIPTAG_SUBSCRIPTION_STATE_STR(sip_sub_st)),
TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)),
SIPTAG_EVENT_STR(es), TAG_IF(ct, SIPTAG_CONTENT_TYPE_STR(ct)), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_END());
switch_safe_free(route_uri);
sofia_glue_free_destination(dst);
sofia_glue_release_profile(profile);
} }
return;
} else if (to_uri || from_uri) {
if (!es) { if (!es) {
es = "message-summary"; es = "message-summary";
} }
@ -4770,6 +4881,96 @@ static void general_event_handler(switch_event_t *event)
} }
break; break;
case SWITCH_EVENT_PHONE_FEATURE:
{
const char *profile_name = switch_event_get_header(event, "profile");
const char *user = switch_event_get_header(event, "user");
const char *host = switch_event_get_header(event, "host");
const char *call_id = switch_event_get_header(event, "call-id");
const char *csta_event = switch_event_get_header(event, "csta-event");
char *ct = "application/x-as-feature-event+xml";
sofia_profile_t *profile;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Phone Feature NOTIFY\n");
if (profile_name && user && host && (profile = sofia_glue_find_profile(profile_name))) {
char *sql;
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "we have all required vars\n");
if (csta_event) {
if (!strcmp(csta_event, "init")) {
char *boundary_string = "UniqueFreeSWITCHBoundary";
switch_stream_handle_t dnd_stream = { 0 };
char *header_name = NULL;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending multipart with DND and CFWD\n");
if ((header_name = switch_event_get_header(event, "forward_immediate"))) {
switch_stream_handle_t fwdi_stream = { 0 };
SWITCH_STANDARD_STREAM(fwdi_stream);
write_csta_xml_chunk(event, fwdi_stream, "ForwardingEvent", "forwardImmediate");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)fwdi_stream.data, (int)strlen(fwdi_stream.data));
stream.write_function(&stream, "--%s\nContent-Type: application/x-as-feature-event+xml\nContent-Length:%d\nContent-ID:<%s@%s>\n\n%s", boundary_string, strlen(fwdi_stream.data), user, host, fwdi_stream.data);
switch_safe_free(fwdi_stream.data);
}
if ((header_name = switch_event_get_header(event, "forward_busy"))) {
switch_stream_handle_t fwdb_stream = { 0 };
SWITCH_STANDARD_STREAM(fwdb_stream);
write_csta_xml_chunk(event, fwdb_stream, "ForwardingEvent", "forwardBusy");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)fwdb_stream.data, (int)strlen(fwdb_stream.data));
stream.write_function(&stream, "--%s\nContent-Type: application/x-as-feature-event+xml\nContent-Length:%d\nContent-ID:<%s@%s>\n\n%s", boundary_string, strlen(fwdb_stream.data), user, host, fwdb_stream.data);
switch_safe_free(fwdb_stream.data);
}
if ((header_name = switch_event_get_header(event, "forward_no_answer"))) {
switch_stream_handle_t fwdna_stream = { 0 };
SWITCH_STANDARD_STREAM(fwdna_stream);
write_csta_xml_chunk(event, fwdna_stream, "ForwardingEvent", "forwardNoAns");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)fwdna_stream.data, (int)strlen(fwdna_stream.data));
stream.write_function(&stream, "--%s\nContent-Type: application/x-as-feature-event+xml\nContent-Length:%d\nContent-ID:<%s@%s>\n\n%s", boundary_string, strlen(fwdna_stream.data), user, host, fwdna_stream.data);
switch_safe_free(fwdna_stream.data);
}
SWITCH_STANDARD_STREAM(dnd_stream);
write_csta_xml_chunk(event, dnd_stream, "DoNotDisturbEvent", NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)dnd_stream.data, (int)strlen(dnd_stream.data));
stream.write_function(&stream, "--%s\nContent-Type:application/x-as-feature-event+xml\nContent-Length:%d\nContent-ID:<%s@%s>\n\n%s", boundary_string, strlen(dnd_stream.data), user, host, dnd_stream.data);
switch_safe_free(dnd_stream.data);
stream.write_function(&stream, "--%s--\n", boundary_string);
ct = switch_mprintf("multipart/mixed; boundary=\"%s\"", boundary_string);
} else {
// this will need some work to handle the different types of forwarding events
write_csta_xml_chunk(event, stream, csta_event, NULL);
}
}
if (call_id) {
sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,call_id,full_from,full_to,expires,'%q', '%q' "
"from sip_subscriptions where event='as-feature-event' and call_id='%q'", stream.data, ct, call_id);
} else {
sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,call_id,full_from,full_to,expires,'%q', '%q' "
"from sip_subscriptions where event='as-feature-event' and sip_user='%s' and sip_host='%q'", stream.data, ct, switch_str_nil(user), switch_str_nil(host)
);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query: %s\n", sql);
switch_safe_free(stream.data);
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_callback(profile, NULL, sql, notify_csta_callback, profile);
switch_mutex_unlock(profile->ireg_mutex);
sofia_glue_release_profile(profile);
free(sql);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "missing something\n");
}
}
break;
case SWITCH_EVENT_SEND_MESSAGE: case SWITCH_EVENT_SEND_MESSAGE:
{ {
const char *profile_name = switch_event_get_header(event, "profile"); const char *profile_name = switch_event_get_header(event, "profile");
@ -5024,6 +5225,57 @@ static void general_event_handler(switch_event_t *event)
} }
} }
void write_csta_xml_chunk(switch_event_t *event, switch_stream_handle_t stream, const char *csta_event, char *fwdtype)
{
const char *device = switch_event_get_header(event, "device");
if (csta_event) {
stream.write_function(&stream, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<%s xmlns=\"http://www.ecma-international.org/standards/ecma-323/csta/ed3\">\n", csta_event);
}
if (device) {
stream.write_function(&stream, " <device>%s</device>\n", device);
}
if (!strcmp(csta_event, "DoNotDisturbEvent")) {
const char *dndstatus = switch_event_get_header(event, "doNotDisturbOn");
if (dndstatus) {
stream.write_function(&stream, " <doNotDisturbOn>%s</doNotDisturbOn>\n", dndstatus);
}
} else if(!strcmp(csta_event, "ForwardingEvent")) {
const char *fwdstatus = switch_event_get_header(event, "forwardStatus");
const char *fwdto = NULL;
const char *ringcount = NULL;
if (strcmp("forwardImmediate", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_immediate");
} else if (strcmp("forwardBusy", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_busy");
} else if (strcmp("fowardNoAns", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_no_answer");
ringcount = switch_event_get_header(event, "ringCount");
}
if (fwdtype) {
stream.write_function(&stream, " <forwardingType>%s</forwardingType>\n", fwdtype);
}
if (fwdstatus) {
stream.write_function(&stream, " <forwardStatus>%s</forwardStatus>\n", fwdstatus);
}
if (fwdto) {
stream.write_function(&stream, " <forwardTo>%s</forwardTo>\n", fwdto);
}
if (ringcount) {
stream.write_function(&stream, " <ringCount>%s</ringCount>\n", ringcount);
}
}
if (csta_event) {
stream.write_function(&stream, "</%s>\n", csta_event);
}
}
switch_status_t list_profiles_full(const char *line, const char *cursor, switch_console_callback_match_t **matches, switch_bool_t show_aliases) switch_status_t list_profiles_full(const char *line, const char *cursor, switch_console_callback_match_t **matches, switch_bool_t show_aliases)
{ {
sofia_profile_t *profile = NULL; sofia_profile_t *profile = NULL;
@ -5287,6 +5539,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
if (switch_event_bind(modname, SWITCH_EVENT_PHONE_FEATURE, SWITCH_EVENT_SUBCLASS_ANY, general_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_SEND_MESSAGE, SWITCH_EVENT_SUBCLASS_ANY, general_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { if (switch_event_bind(modname, SWITCH_EVENT_SEND_MESSAGE, SWITCH_EVENT_SUBCLASS_ANY, general_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;

View File

@ -1,4 +1,4 @@
/* /*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org> * Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
* *
@ -22,14 +22,14 @@
* the Initial Developer. All Rights Reserved. * the Initial Developer. All Rights Reserved.
* *
* Contributor(s): * Contributor(s):
* *
* Anthony Minessale II <anthm@freeswitch.org> * Anthony Minessale II <anthm@freeswitch.org>
* Ken Rice <krice@freeswitch.org> * Ken Rice <krice@freeswitch.org>
* Paul D. Tinsley <pdt at jackhammer.org> * Paul D. Tinsley <pdt at jackhammer.org>
* Bret McDanel <trixter AT 0xdecafbad.com> * Bret McDanel <trixter AT 0xdecafbad.com>
* Marcel Barbulescu <marcelbarbulescu@gmail.com> * Marcel Barbulescu <marcelbarbulescu@gmail.com>
* Raymond Chandler <intralanman@gmail.com> * Raymond Chandler <intralanman@gmail.com>
* Emmanuel Schmidbauer <e.schmidbauer@gmail.com> * Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
* *
* *
* mod_sofia.h -- SOFIA SIP Endpoint * mod_sofia.h -- SOFIA SIP Endpoint
@ -149,9 +149,9 @@ typedef enum {
typedef struct sofia_dispatch_event_s { typedef struct sofia_dispatch_event_s {
nua_saved_event_t event[1]; nua_saved_event_t event[1];
nua_handle_t *nh; nua_handle_t *nh;
nua_event_data_t const *data; nua_event_data_t const *data;
su_time_t when; su_time_t when;
sip_t *sip; sip_t *sip;
nua_t *nua; nua_t *nua;
sofia_profile_t *profile; sofia_profile_t *profile;
@ -353,7 +353,7 @@ struct mod_sofia_globals {
int reg_deny_binding_fetch_and_no_lookup; /* backwards compatibility */ int reg_deny_binding_fetch_and_no_lookup; /* backwards compatibility */
int auto_nat; int auto_nat;
int tracelevel; int tracelevel;
char *capture_server; char *capture_server;
int rewrite_multicasted_fs_path; int rewrite_multicasted_fs_path;
int presence_flush; int presence_flush;
switch_thread_t *presence_thread; switch_thread_t *presence_thread;
@ -511,10 +511,10 @@ typedef enum {
} sofia_media_options_t; } sofia_media_options_t;
typedef enum { typedef enum {
PAID_DEFAULT = 0, PAID_DEFAULT = 0,
PAID_USER, PAID_USER,
PAID_USER_DOMAIN, PAID_USER_DOMAIN,
PAID_VERBATIM PAID_VERBATIM
} sofia_paid_type_t; } sofia_paid_type_t;
#define MAX_RTPIP 50 #define MAX_RTPIP 50
@ -619,7 +619,7 @@ struct sofia_profile {
char *pre_trans_execute; char *pre_trans_execute;
char *post_trans_execute; char *post_trans_execute;
char *inner_pre_trans_execute; char *inner_pre_trans_execute;
char *inner_post_trans_execute; char *inner_post_trans_execute;
switch_sql_queue_manager_t *qm; switch_sql_queue_manager_t *qm;
char *acl[SOFIA_MAX_ACL]; char *acl[SOFIA_MAX_ACL];
char *acl_pass_context[SOFIA_MAX_ACL]; char *acl_pass_context[SOFIA_MAX_ACL];
@ -678,7 +678,7 @@ struct sofia_profile {
sofia_paid_type_t paid_type; sofia_paid_type_t paid_type;
uint32_t rtp_digit_delay; uint32_t rtp_digit_delay;
switch_queue_t *event_queue; switch_queue_t *event_queue;
switch_thread_t *thread; switch_thread_t *thread;
switch_core_media_vflag_t vflags; switch_core_media_vflag_t vflags;
char *ws_ip; char *ws_ip;
switch_port_t ws_port; switch_port_t ws_port;
@ -851,7 +851,7 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
sofia_dispatch_event_t *de, tagi_t tags[]); sofia_dispatch_event_t *de, tagi_t tags[]);
void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, sofia_dispatch_event_t *de, tagi_t tags[]); void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, sofia_dispatch_event_t *de, tagi_t tags[]);
void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t **sofia_private, sip_t const *sip, void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t **sofia_private, sip_t const *sip,
sofia_dispatch_event_t *de, sofia_dispatch_event_t *de,
@ -868,9 +868,9 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
void launch_sofia_profile_thread(sofia_profile_t *profile); void launch_sofia_profile_thread(sofia_profile_t *profile);
switch_status_t sofia_presence_chat_send(switch_event_t *message_event); switch_status_t sofia_presence_chat_send(switch_event_t *message_event);
/* /*
* \brief Sets the "ep_codec_string" channel variable, parsing r_sdp and taing codec_string in consideration * \brief Sets the "ep_codec_string" channel variable, parsing r_sdp and taing codec_string in consideration
* \param channel Current channel * \param channel Current channel
* \param codec_string The profile's codec string or NULL if inexistant * \param codec_string The profile's codec string or NULL if inexistant
* \param sdp The parsed SDP content * \param sdp The parsed SDP content
@ -935,7 +935,7 @@ switch_call_cause_t sofia_glue_sip_cause_to_freeswitch(int status);
void sofia_glue_do_xfer_invite(switch_core_session_t *session); void sofia_glue_do_xfer_invite(switch_core_session_t *session);
uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip, uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
sofia_dispatch_event_t *de, sofia_dispatch_event_t *de,
sofia_regtype_t regtype, char *key, sofia_regtype_t regtype, char *key,
uint32_t keylen, switch_event_t **v_event, const char *is_nat, sofia_private_t **sofia_private_p, switch_xml_t *user_xml); uint32_t keylen, switch_event_t **v_event, const char *is_nat, sofia_private_t **sofia_private_p, switch_xml_t *user_xml);
extern switch_endpoint_interface_t *sofia_endpoint_interface; extern switch_endpoint_interface_t *sofia_endpoint_interface;
void sofia_presence_set_chat_hash(private_object_t *tech_pvt, sip_t const *sip); void sofia_presence_set_chat_hash(private_object_t *tech_pvt, sip_t const *sip);
@ -1044,7 +1044,7 @@ void sofia_glue_restart_all_profiles(void);
const char *sofia_state_string(int state); const char *sofia_state_string(int state);
void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout); void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout);
/* /*
* Logging control functions * Logging control functions
*/ */
@ -1117,6 +1117,7 @@ switch_status_t sofia_glue_ext_address_lookup(sofia_profile_t *profile, char **i
void sofia_reg_check_socket(sofia_profile_t *profile, const char *call_id, const char *network_addr, const char *network_ip); void sofia_reg_check_socket(sofia_profile_t *profile, const char *call_id, const char *network_addr, const char *network_ip);
void sofia_reg_close_handles(sofia_profile_t *profile); void sofia_reg_close_handles(sofia_profile_t *profile);
void write_csta_xml_chunk(switch_event_t *event, switch_stream_handle_t stream, const char *csta_event, char *fwd_type);
/* For Emacs: /* For Emacs:
* Local Variables: * Local Variables:
* mode:c * mode:c

File diff suppressed because it is too large Load Diff

View File

@ -3658,6 +3658,39 @@ void sofia_presence_handle_sip_i_subscribe(int status,
switch_snprintf(exp_delta_str, sizeof(exp_delta_str), "%ld", exp_delta); switch_snprintf(exp_delta_str, sizeof(exp_delta_str), "%ld", exp_delta);
if (!strcmp("as-feature-event", event)) {
sip_authorization_t const *authorization = NULL;
auth_res_t auth_res = AUTH_FORBIDDEN;
char key[128] = "";
switch_event_t *v_event = NULL;
if (sip->sip_authorization) {
authorization = sip->sip_authorization;
} else if (sip->sip_proxy_authorization) {
authorization = sip->sip_proxy_authorization;
}
if (authorization) {
char network_ip[80];
sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), NULL);
auth_res = sofia_reg_parse_auth(profile, authorization, sip, de,
(char *) sip->sip_request->rq_method_name, key, sizeof(key), network_ip, &v_event, 0,
REG_REGISTER, to_user, NULL, NULL, NULL);
} else if ( sofia_reg_handle_register(nua, profile, nh, sip, de, REG_REGISTER, key, sizeof(key), &v_event, NULL, NULL, NULL)) {
if (v_event) {
switch_event_destroy(&v_event);
}
goto end;
}
if ((auth_res != AUTH_OK && auth_res != AUTH_RENEWED)) {
nua_respond(nh, SIP_401_UNAUTHORIZED, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
goto end;
}
}
if (to_user && strchr(to_user, '+')) { if (to_user && strchr(to_user, '+')) {
char *h; char *h;
if ((proto = (d_user = strdup(to_user)))) { if ((proto = (d_user = strdup(to_user)))) {
@ -3991,7 +4024,24 @@ void sofia_presence_handle_sip_i_subscribe(int status,
switch_safe_free(sstr); switch_safe_free(sstr);
if (!strcasecmp(event, "message-summary")) { if (!strcasecmp(event, "as-feature-event")) {
switch_event_t *event;
char sip_cseq[40] = "";
switch_snprintf(sip_cseq, sizeof(sip_cseq), "%d", sip->sip_cseq->cs_seq);
switch_event_create(&event, SWITCH_EVENT_PHONE_FEATURE_SUBSCRIBE);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user", from_user);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "host", from_host);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "contact", contact_str);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-id", call_id);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "cseq", sip_cseq);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "profile_name", profile->name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hostname", mod_sofia_globals.hostname);
if (sip->sip_payload) {
switch_event_add_body(event, "%s", sip->sip_payload->pl_data);
}
switch_event_fire(&event);
} else if (!strcasecmp(event, "message-summary")) {
if ((sql = switch_mprintf("select proto,sip_user,'%q',sub_to_user,sub_to_host,event,contact,call_id,full_from," if ((sql = switch_mprintf("select proto,sip_user,'%q',sub_to_user,sub_to_host,event,contact,call_id,full_from,"
"full_via,expires,user_agent,accept,profile_name,network_ip" "full_via,expires,user_agent,accept,profile_name,network_ip"
" from sip_subscriptions where hostname='%q' and profile_name='%q' and " " from sip_subscriptions where hostname='%q' and profile_name='%q' and "

View File

@ -1240,10 +1240,12 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
to_host = to->a_url->url_host; to_host = to->a_url->url_host;
} }
if (!to_user) if (!to_user) {
to_user = from_user; to_user = from_user;
if (!to_host) }
if (!to_host) {
to_host = from_host; to_host = from_host;
}
if (!to_user || !to_host) { if (!to_user || !to_host) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can not do authorization without a complete header in REGISTER request from %s:%d\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can not do authorization without a complete header in REGISTER request from %s:%d\n",

View File

@ -1,4 +1,4 @@
/* /*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org> * Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
* *
@ -22,11 +22,12 @@
* the Initial Developer. All Rights Reserved. * the Initial Developer. All Rights Reserved.
* *
* Contributor(s): * Contributor(s):
* *
* Anthony Minessale II <anthm@freeswitch.org> * Anthony Minessale II <anthm@freeswitch.org>
* Michael Jerris <mike@jerris.com> * Michael Jerris <mike@jerris.com>
* Paul D. Tinsley <pdt at jackhammer.org> * Paul D. Tinsley <pdt at jackhammer.org>
* William King <william.king@quentustech.com> * William King <william.king@quentustech.com>
* Raymond Chandler <intralanman@freeswitch.org>
* *
* switch_event.c -- Event System * switch_event.c -- Event System
* *
@ -153,6 +154,8 @@ static char *EVENT_NAMES[] = {
"MESSAGE", "MESSAGE",
"PRESENCE_IN", "PRESENCE_IN",
"NOTIFY_IN", "NOTIFY_IN",
"PHONE_FEATURE",
"PHONE_FEATURE_SUBSCRIBE",
"PRESENCE_OUT", "PRESENCE_OUT",
"PRESENCE_PROBE", "PRESENCE_PROBE",
"MESSAGE_WAITING", "MESSAGE_WAITING",
@ -263,7 +266,7 @@ static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *th
EVENT_DISPATCH_QUEUE_RUNNING[my_id] = 1; EVENT_DISPATCH_QUEUE_RUNNING[my_id] = 1;
switch_mutex_unlock(EVENT_QUEUE_MUTEX); switch_mutex_unlock(EVENT_QUEUE_MUTEX);
for (;;) { for (;;) {
void *pop = NULL; void *pop = NULL;
@ -308,11 +311,11 @@ static switch_status_t switch_event_queue_dispatch_event(switch_event_t **eventp
if (!SYSTEM_RUNNING) { if (!SYSTEM_RUNNING) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
while (event) { while (event) {
int launch = 0; int launch = 0;
switch_mutex_lock(EVENT_QUEUE_MUTEX); switch_mutex_lock(EVENT_QUEUE_MUTEX);
if (!PENDING && switch_queue_size(EVENT_DISPATCH_QUEUE) > (unsigned int)(DISPATCH_QUEUE_LEN * DISPATCH_THREAD_COUNT)) { if (!PENDING && switch_queue_size(EVENT_DISPATCH_QUEUE) > (unsigned int)(DISPATCH_QUEUE_LEN * DISPATCH_THREAD_COUNT)) {
if (SOFT_MAX_DISPATCH + 1 > MAX_DISPATCH) { if (SOFT_MAX_DISPATCH + 1 > MAX_DISPATCH) {
@ -322,7 +325,7 @@ static switch_status_t switch_event_queue_dispatch_event(switch_event_t **eventp
} }
switch_mutex_unlock(EVENT_QUEUE_MUTEX); switch_mutex_unlock(EVENT_QUEUE_MUTEX);
if (launch) { if (launch) {
if (SOFT_MAX_DISPATCH + 1 < MAX_DISPATCH) { if (SOFT_MAX_DISPATCH + 1 < MAX_DISPATCH) {
switch_event_launch_dispatch_threads(SOFT_MAX_DISPATCH + 1); switch_event_launch_dispatch_threads(SOFT_MAX_DISPATCH + 1);
@ -336,9 +339,9 @@ static switch_status_t switch_event_queue_dispatch_event(switch_event_t **eventp
*eventp = NULL; *eventp = NULL;
switch_queue_push(EVENT_DISPATCH_QUEUE, event); switch_queue_push(EVENT_DISPATCH_QUEUE, event);
event = NULL; event = NULL;
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -579,12 +582,12 @@ SWITCH_DECLARE(switch_status_t) switch_event_init(switch_memory_pool_t *pool)
{ {
//switch_threadattr_t *thd_attr; //switch_threadattr_t *thd_attr;
/* /*
This statement doesn't do anything commenting it out for now. This statement doesn't do anything commenting it out for now.
switch_assert(switch_arraylen(EVENT_NAMES) == SWITCH_EVENT_ALL + 1); switch_assert(switch_arraylen(EVENT_NAMES) == SWITCH_EVENT_ALL + 1);
*/ */
/* don't need any more dispatch threads than we have CPU's*/ /* don't need any more dispatch threads than we have CPU's*/
MAX_DISPATCH = (switch_core_cpu_count() / 2) + 1; MAX_DISPATCH = (switch_core_cpu_count() / 2) + 1;
if (MAX_DISPATCH < 2) { if (MAX_DISPATCH < 2) {
@ -751,7 +754,7 @@ SWITCH_DECLARE(char *) switch_event_get_header_idx(switch_event_t *event, const
} }
} }
return hp->value; return hp->value;
} else if (!strcmp(header_name, "_body")) { } else if (!strcmp(header_name, "_body")) {
return event->body; return event->body;
} }
@ -802,7 +805,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_del_header_val(switch_event_t *even
} }
FREE(hp->value); FREE(hp->value);
memset(hp, 0, sizeof(*hp)); memset(hp, 0, sizeof(*hp));
#ifdef SWITCH_EVENT_RECYCLE #ifdef SWITCH_EVENT_RECYCLE
if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, hp) != SWITCH_STATUS_SUCCESS) { if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, hp) != SWITCH_STATUS_SUCCESS) {
@ -834,7 +837,7 @@ static switch_event_header_t *new_header(const char *header_name)
switch_assert(header); switch_assert(header);
#ifdef SWITCH_EVENT_RECYCLE #ifdef SWITCH_EVENT_RECYCLE
} }
#endif #endif
memset(header, 0, sizeof(*header)); memset(header, 0, sizeof(*header));
header->name = DUP(header_name); header->name = DUP(header_name);
@ -870,15 +873,15 @@ SWITCH_DECLARE(int) switch_event_add_array(switch_event_t *event, const char *va
} }
data = strdup(val + 7); data = strdup(val + 7);
len = (sizeof(char *) * max) + 1; len = (sizeof(char *) * max) + 1;
switch_assert(len); switch_assert(len);
array = malloc(len); array = malloc(len);
memset(array, 0, len); memset(array, 0, len);
switch_separate_string_string(data, "|:", array, max); switch_separate_string_string(data, "|:", array, max);
for(i = 0; i < max; i++) { for(i = 0; i < max; i++) {
switch_event_add_header_string(event, SWITCH_STACK_PUSH, var, array[i]); switch_event_add_header_string(event, SWITCH_STACK_PUSH, var, array[i]);
} }
@ -914,20 +917,20 @@ static switch_status_t switch_event_base_add_header(switch_event_t *event, switc
} }
if (index_ptr || (stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) { if (index_ptr || (stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) {
if (!(header = switch_event_get_header_ptr(event, header_name)) && index_ptr) { if (!(header = switch_event_get_header_ptr(event, header_name)) && index_ptr) {
header = new_header(header_name); header = new_header(header_name);
if (switch_test_flag(event, EF_UNIQ_HEADERS)) { if (switch_test_flag(event, EF_UNIQ_HEADERS)) {
switch_event_del_header(event, header_name); switch_event_del_header(event, header_name);
} }
fly++; fly++;
} }
if (header || (header = switch_event_get_header_ptr(event, header_name))) { if (header || (header = switch_event_get_header_ptr(event, header_name))) {
if (index_ptr) { if (index_ptr) {
if (index > -1 && index <= 4000) { if (index > -1 && index <= 4000) {
if (index < header->idx) { if (index < header->idx) {
@ -936,7 +939,7 @@ static switch_status_t switch_event_base_add_header(switch_event_t *event, switc
} else { } else {
int i; int i;
char **m; char **m;
m = realloc(header->array, sizeof(char *) * (index + 1)); m = realloc(header->array, sizeof(char *) * (index + 1));
switch_assert(m); switch_assert(m);
header->array = m; header->array = m;
@ -986,7 +989,7 @@ static switch_status_t switch_event_base_add_header(switch_event_t *event, switc
header = new_header(header_name); header = new_header(header_name);
} }
if ((stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) { if ((stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) {
char **m = NULL; char **m = NULL;
switch_size_t len = 0; switch_size_t len = 0;
@ -1004,7 +1007,7 @@ static switch_status_t switch_event_base_add_header(switch_event_t *event, switc
} }
i = header->idx + 1; i = header->idx + 1;
m = realloc(header->array, sizeof(char *) * i); m = realloc(header->array, sizeof(char *) * i);
switch_assert(m); switch_assert(m);
if ((stack & SWITCH_STACK_PUSH)) { if ((stack & SWITCH_STACK_PUSH)) {
@ -1016,7 +1019,7 @@ static switch_status_t switch_event_base_add_header(switch_event_t *event, switc
m[0] = data; m[0] = data;
} }
header->idx++; header->idx++;
header->array = m; header->array = m;
redraw: redraw:
@ -1118,7 +1121,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_set_body(switch_event_t *event, con
if (body) { if (body) {
event->body = DUP(body); event->body = DUP(body);
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -1170,7 +1173,7 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event)
FREE(this->name); FREE(this->name);
FREE(this->value); FREE(this->value);
#ifdef SWITCH_EVENT_RECYCLE #ifdef SWITCH_EVENT_RECYCLE
if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, this) != SWITCH_STATUS_SUCCESS) { if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, this) != SWITCH_STATUS_SUCCESS) {
@ -1200,13 +1203,13 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event)
SWITCH_DECLARE(void) switch_event_merge(switch_event_t *event, switch_event_t *tomerge) SWITCH_DECLARE(void) switch_event_merge(switch_event_t *event, switch_event_t *tomerge)
{ {
switch_event_header_t *hp; switch_event_header_t *hp;
switch_assert(tomerge && event); switch_assert(tomerge && event);
for (hp = tomerge->headers; hp; hp = hp->next) { for (hp = tomerge->headers; hp; hp = hp->next) {
if (hp->idx) { if (hp->idx) {
int i; int i;
for(i = 0; i < hp->idx; i++) { for(i = 0; i < hp->idx; i++) {
switch_event_add_header_string(event, SWITCH_STACK_PUSH, hp->name, hp->array[i]); switch_event_add_header_string(event, SWITCH_STACK_PUSH, hp->name, hp->array[i]);
} }
@ -1232,7 +1235,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_dup(switch_event_t **event, switch_
if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")) { if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")) {
continue; continue;
} }
if (hp->idx) { if (hp->idx) {
int i; int i;
for (i = 0; i < hp->idx; i++) { for (i = 0; i < hp->idx; i++) {
@ -1270,11 +1273,11 @@ SWITCH_DECLARE(switch_status_t) switch_event_dup_reply(switch_event_t **event, s
for (hp = todup->headers; hp; hp = hp->next) { for (hp = todup->headers; hp; hp = hp->next) {
char *name = hp->name, *value = hp->value; char *name = hp->name, *value = hp->value;
if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")) { if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")) {
continue; continue;
} }
if (!strncasecmp(hp->name, "from_", 5)) { if (!strncasecmp(hp->name, "from_", 5)) {
p = hp->name + 5; p = hp->name + 5;
switch_snprintf(hname, sizeof(hname), "to_%s", p); switch_snprintf(hname, sizeof(hname), "to_%s", p);
@ -1288,7 +1291,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_dup_reply(switch_event_t **event, s
} else if (!strcasecmp(name, "from")) { } else if (!strcasecmp(name, "from")) {
name = "to"; name = "to";
} }
if (hp->idx) { if (hp->idx) {
int i; int i;
for (i = 0; i < hp->idx; i++) { for (i = 0; i < hp->idx; i++) {
@ -1379,13 +1382,13 @@ SWITCH_DECLARE(switch_status_t) switch_event_binary_serialize(switch_event_t *ev
tn = tpl_map(SWITCH_SERIALIZED_EVENT_MAP, &e, &sh); tn = tpl_map(SWITCH_SERIALIZED_EVENT_MAP, &e, &sh);
tpl_pack(tn, 0); tpl_pack(tn, 0);
for (eh = event->headers; eh; eh = eh->next) { for (eh = event->headers; eh; eh = eh->next) {
if (eh->idx) continue; // no arrays yet if (eh->idx) continue; // no arrays yet
sh.name = eh->name; sh.name = eh->name;
sh.value = eh->value; sh.value = eh->value;
tpl_pack(tn, 1); tpl_pack(tn, 1);
} }
@ -1427,7 +1430,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize(switch_event_t *event, ch
/* /*
* grab enough memory to store 3x the string (url encode takes one char and turns it into %XX) * grab enough memory to store 3x the string (url encode takes one char and turns it into %XX)
* so we could end up with a string that is 3 times the originals length, unlikely but rather * so we could end up with a string that is 3 times the originals length, unlikely but rather
* be safe than destroy the string, also add one for the null. And try to be smart about using * be safe than destroy the string, also add one for the null. And try to be smart about using
* the memory, allocate and only reallocate if we need more. This avoids an alloc, free CPU * the memory, allocate and only reallocate if we need more. This avoids an alloc, free CPU
* destroying loop. * destroying loop.
*/ */
@ -1522,11 +1525,11 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_array_pair(switch_event_t **
char *name, *val; char *name, *val;
switch_event_create(event, SWITCH_EVENT_CLONE); switch_event_create(event, SWITCH_EVENT_CLONE);
for (r = 0; r < len; r++) { for (r = 0; r < len; r++) {
val = switch_str_nil(vals[r]); val = switch_str_nil(vals[r]);
name = names[r]; name = names[r];
if (zstr(name)) { if (zstr(name)) {
name = "Unknown"; name = "Unknown";
} }
@ -1535,7 +1538,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_array_pair(switch_event_t **
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
SWITCH_DECLARE(switch_status_t) switch_event_create_brackets(char *data, char a, char b, char c, switch_event_t **event, char **new_data, switch_bool_t dup) SWITCH_DECLARE(switch_status_t) switch_event_create_brackets(char *data, char a, char b, char c, switch_event_t **event, char **new_data, switch_bool_t dup)
@ -1555,17 +1558,17 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_brackets(char *data, char a,
} }
end = switch_find_end_paren(vdata, a, b); end = switch_find_end_paren(vdata, a, b);
check_a = end; check_a = end;
while (check_a && (check_b = switch_strchr_strict(check_a, a, " "))) { while (check_a && (check_b = switch_strchr_strict(check_a, a, " "))) {
if ((check_b = switch_find_end_paren(check_b, a, b))) { if ((check_b = switch_find_end_paren(check_b, a, b))) {
check_a = check_b; check_a = check_b;
} }
} }
if (check_a) end = check_a; if (check_a) end = check_a;
if (end) { if (end) {
next = end; next = end;
vdata++; vdata++;
@ -1576,12 +1579,12 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_brackets(char *data, char a,
} }
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
if (!e) { if (!e) {
switch_event_create_plain(&e, SWITCH_EVENT_CHANNEL_DATA); switch_event_create_plain(&e, SWITCH_EVENT_CHANNEL_DATA);
} }
for (;;) { for (;;) {
if (next) { if (next) {
char *pnext; char *pnext;
@ -1595,7 +1598,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_brackets(char *data, char a,
vnext = switch_find_end_paren(next, a, b); vnext = switch_find_end_paren(next, a, b);
next = NULL; next = NULL;
} }
if (vdata) { if (vdata) {
if (*vdata == '^' && *(vdata + 1) == '^') { if (*vdata == '^' && *(vdata + 1) == '^') {
@ -1603,7 +1606,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_brackets(char *data, char a,
c = *vdata++; c = *vdata++;
} }
} }
if ((var_count = switch_separate_string(vdata, c, var_array, (sizeof(var_array) / sizeof(var_array[0]))))) { if ((var_count = switch_separate_string(vdata, c, var_array, (sizeof(var_array) / sizeof(var_array[0]))))) {
int x = 0; int x = 0;
for (x = 0; x < var_count; x++) { for (x = 0; x < var_count; x++) {
@ -1635,7 +1638,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_brackets(char *data, char a,
} else { } else {
*new_data = end; *new_data = end;
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -1687,7 +1690,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_json(switch_event_t **event,
} }
} }
} }
cJSON_Delete(cj); cJSON_Delete(cj);
*event = new_event; *event = new_event;
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -1699,7 +1702,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize_json(switch_event_t *even
cJSON *cj; cJSON *cj;
*str = NULL; *str = NULL;
cj = cJSON_CreateObject(); cj = cJSON_CreateObject();
for (hp = event->headers; hp; hp = hp->next) { for (hp = event->headers; hp; hp = hp->next) {
@ -1710,9 +1713,9 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize_json(switch_event_t *even
for(i = 0; i < hp->idx; i++) { for(i = 0; i < hp->idx; i++) {
cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i])); cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i]));
} }
cJSON_AddItemToObject(cj, hp->name, a); cJSON_AddItemToObject(cj, hp->name, a);
} else { } else {
cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value)); cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
} }
@ -1730,7 +1733,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize_json(switch_event_t *even
*str = cJSON_Print(cj); *str = cJSON_Print(cj);
cJSON_Delete(cj); cJSON_Delete(cj);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -1901,7 +1904,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_bind_removable(const char *id, swit
if (node) { if (node) {
*node = NULL; *node = NULL;
} }
if (subclass_name) { if (subclass_name) {
if (!(subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name))) { if (!(subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name))) {
switch_event_reserve_subclass_detailed(id, subclass_name); switch_event_reserve_subclass_detailed(id, subclass_name);
@ -2066,9 +2069,9 @@ char *dp;\
olen += (len + l + block);\ olen += (len + l + block);\
cpos = c - data;\ cpos = c - data;\
if ((dp = realloc(data, olen))) {\ if ((dp = realloc(data, olen))) {\
data = dp;\ data = dp;\
c = data + cpos;\ c = data + cpos;\
memset(c, 0, olen - cpos);\ memset(c, 0, olen - cpos);\
}} \ }} \
SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur) SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur)
@ -2223,7 +2226,7 @@ SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event,
int ooffset = 0; int ooffset = 0;
char *ptr; char *ptr;
int idx = -1; int idx = -1;
if ((expanded = switch_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) { if ((expanded = switch_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) {
expanded = NULL; expanded = NULL;
} else { } else {
@ -2266,7 +2269,7 @@ SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event,
switch_assert(cloned_sub_val); switch_assert(cloned_sub_val);
sub_val = cloned_sub_val; sub_val = cloned_sub_val;
} }
if (offset >= 0) { if (offset >= 0) {
sub_val += offset; sub_val += offset;
} else if ((size_t) abs(offset) <= strlen(sub_val)) { } else if ((size_t) abs(offset) <= strlen(sub_val)) {
@ -2278,7 +2281,7 @@ SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event,
*ptr = '\0'; *ptr = '\0';
} }
} }
switch_safe_free(expanded); switch_safe_free(expanded);
} else { } else {
@ -2477,7 +2480,7 @@ SWITCH_DECLARE(int) switch_event_check_permission_list(switch_event_t *list, con
r = default_allow; r = default_allow;
} }
return r; return r;
} }
SWITCH_DECLARE(void) switch_event_add_presence_data_cols(switch_channel_t *channel, switch_event_t *event, const char *prefix) SWITCH_DECLARE(void) switch_event_add_presence_data_cols(switch_channel_t *channel, switch_event_t *event, const char *prefix)
@ -2485,7 +2488,7 @@ SWITCH_DECLARE(void) switch_event_add_presence_data_cols(switch_channel_t *chann
const char *data; const char *data;
if (!prefix) prefix = ""; if (!prefix) prefix = "";
if ((data = switch_channel_get_variable(channel, "presence_data_cols"))) { if ((data = switch_channel_get_variable(channel, "presence_data_cols"))) {
char *cols[128] = { 0 }; char *cols[128] = { 0 };
char header_name[128] = ""; char header_name[128] = "";
@ -2493,17 +2496,17 @@ SWITCH_DECLARE(void) switch_event_add_presence_data_cols(switch_channel_t *chann
char *data_copy = NULL; char *data_copy = NULL;
data_copy = strdup(data); data_copy = strdup(data);
col_count = switch_split(data_copy, ':', cols); col_count = switch_split(data_copy, ':', cols);
for (i = 0; i < col_count; i++) { for (i = 0; i < col_count; i++) {
const char *val = NULL; const char *val = NULL;
switch_snprintf(header_name, sizeof(header_name), "%s%s", prefix, cols[i]); switch_snprintf(header_name, sizeof(header_name), "%s%s", prefix, cols[i]);
val = switch_channel_get_variable(channel, cols[i]); val = switch_channel_get_variable(channel, cols[i]);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header_name, val); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header_name, val);
} }
switch_safe_free(data_copy); switch_safe_free(data_copy);
} }