diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 18c3d092ee..37c79fdd06 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -371,7 +371,7 @@ struct switch_chat_interface { /*! the name of the interface */ const char *interface_name; /*! function to open the directory interface */ - switch_status_t (*chat_send)(char *from, char *to, char *subject, char *body, char *hint); + switch_status_t (*chat_send)(char *proto, char *from, char *to, char *subject, char *body, char *hint); const struct switch_chat_interface *next; }; diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 9ccb5031c5..4b03ee2421 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -44,6 +44,7 @@ static switch_api_interface_t conf_api_interface; #define CONF_DBLOCK_SIZE CONF_BUFFER_SIZE #define CONF_DBUFFER_SIZE CONF_BUFFER_SIZE #define CONF_DBUFFER_MAX 0 +#define CONF_CHAT_PROTO "conf" typedef enum { FILE_STOP_CURRENT, @@ -128,6 +129,7 @@ struct conference_obj { char *pin_sound; char *bad_pin_sound; char *profile_name; + char *domain; uint32_t flags; switch_call_cause_t bridge_hangup_cause; switch_mutex_t *flag_mutex; @@ -217,6 +219,7 @@ static switch_status_t conference_member_say(conference_obj_t *conference, confe static uint32_t conference_member_stop_file(conference_member_t *member, file_stop_t stop); static conference_obj_t *conference_new(char *name, switch_xml_t profile, switch_memory_pool_t *pool); static void switch_change_sln_volume(int16_t *data, uint32_t samples, int32_t vol); +static switch_status_t chat_send(char *proto, char *from, char *to, char *subject, char *body, char *hint); /* Return a Distinct ID # */ static uint32_t next_member_id(void) @@ -358,6 +361,16 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe conference->members = member; conference->count++; + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", conference->name, conference->domain); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Active (%d caller%s)", conference->count, conference->count == 1 ? "" : "s"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_fire(&event); + } + + if (conference->enter_sound) { conference_play_file(conference, conference->enter_sound, CONF_DEFAULT_LEADIN); } @@ -411,9 +424,19 @@ static void conference_del_member(conference_obj_t *conference, conference_membe } last = imember; } + conference->count--; member->conference = NULL; + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", conference->name, conference->domain); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Active (%d caller%s)", conference->count, conference->count == 1 ? "" : "s"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_fire(&event); + } + if ((conference->min && switch_test_flag(conference, CFLAG_ENFORCE_MIN) && conference->count < conference->min) || (switch_test_flag(conference, CFLAG_DYNAMIC) && conference->count == 0) ) { switch_set_flag(conference, CFLAG_DESTRUCT); @@ -456,6 +479,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v uint32_t bytes = samples * 2; uint8_t ready = 0; switch_timer_t timer = {0}; + switch_event_t *event; if (switch_core_timer_init(&timer, conference->timer_name, conference->interval, samples, conference->pool) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "setup timer success interval: %u samples: %u\n", conference->interval, samples); @@ -676,6 +700,16 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v } } + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", conference->name, conference->domain); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Inactive"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "idle"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + + switch_event_fire(&event); + } globals.threads--; return NULL; } @@ -729,8 +763,19 @@ static void conference_loop(conference_member_t *member) switch_event_t *event; if (switch_core_session_dequeue_event(member->session, &event) == SWITCH_STATUS_SUCCESS) { + char *p; + char *from = switch_event_get_header(event, "from"); + char *to = switch_event_get_header(event, "to"); + char *proto = switch_event_get_header(event, "proto"); + char *subject = switch_event_get_header(event, "subject"); + char *body = switch_event_get_body(event); + if ((p = strchr(to, '+'))) { + to = ++p; + } + chat_send(proto, from, to, subject, body, ""); switch_event_destroy(&event); } + #if 1 if (switch_channel_test_flag(channel, CF_OUTBOUND)) { // test to see if outbound channel has answered @@ -1312,6 +1357,26 @@ static void conference_list(conference_obj_t *conference, switch_stream_handle_t switch_mutex_unlock(conference->member_mutex); } + +static void conference_list_pretty(conference_obj_t *conference, switch_stream_handle_t *stream) +{ + conference_member_t *member = NULL; + + switch_mutex_lock(conference->member_mutex); + + for (member = conference->members; member; member = member->next) { + switch_channel_t *channel = switch_core_session_get_channel(member->session); + switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel); + + stream->write_function(stream, "Caller %s <%s>\n", + profile->caller_id_name, + profile->caller_id_number + ); + + } + switch_mutex_unlock(conference->member_mutex); +} + /* API Interface Function */ static switch_status_t conf_function(char *buf, switch_core_session_t *session, switch_stream_handle_t *stream) { @@ -2669,6 +2734,50 @@ static switch_api_interface_t conf_api_interface = { /*.next */ }; +static switch_status_t chat_send(char *proto, char *from, char *to, char *subject, char *body, char *hint) +{ + char name[512] = "", *p; + switch_chat_interface_t *ci; + conference_obj_t *conference = NULL; + switch_stream_handle_t stream = {0}; + + if (!(ci = switch_loadable_module_get_chat_interface(proto))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invaid Chat Interface [%s]!\n", proto); + } + + if ((p = strchr(to, '@'))) { + switch_copy_string(name, to, ++p-to); + } else { + switch_copy_string(name, to, sizeof(name)); + } + + if (!(conference = (conference_obj_t *) switch_core_hash_find(globals.conference_hash, name))) { + ci->chat_send(CONF_CHAT_PROTO, to, from, "", "Sorry, We're Closed", ""); + return SWITCH_STATUS_FALSE; + } + + SWITCH_STANDARD_STREAM(stream); + + if (strstr(body, "list")) { + conference_list_pretty(conference, &stream); + } else { + stream.write_function(&stream, "The only command we have is so far is 'list' Get coding or go press PayPal!!\n"); + } + + ci->chat_send(CONF_CHAT_PROTO, to, from, "", stream.data, ""); + switch_safe_free(stream.data); + + + return SWITCH_STATUS_SUCCESS; +} + + +static const switch_chat_interface_t conference_chat_interface = { + /*.name */ CONF_CHAT_PROTO, + /*.chat_send */ chat_send, + +}; + static switch_loadable_module_interface_t conference_module_interface = { /*.module_name */ modname, /*.endpoint_interface */ NULL, @@ -2679,7 +2788,8 @@ static switch_loadable_module_interface_t conference_module_interface = { /*.api_interface */ &conf_api_interface, /*.file_interface */ NULL, /*.speech_interface */ NULL, - /*.directory_interface */ NULL + /*.directory_interface */ NULL, + /*.chat_interface */ &conference_chat_interface }; /* create a new conferene with a specific profile */ @@ -2690,6 +2800,7 @@ static conference_obj_t *conference_new(char *name, switch_xml_t profile, switch char *rate_name = NULL; char *interval_name = NULL; char *timer_name = NULL; + char *domain = NULL; char *tts_engine = NULL; char *tts_voice = NULL; char *enter_sound = NULL; @@ -2734,6 +2845,8 @@ static conference_obj_t *conference_new(char *name, switch_xml_t profile, switch if (!strcasecmp(var, "rate")) { rate_name = val; + } else if (!strcasecmp(var, "domain")) { + domain = val; } else if (!strcasecmp(var, "interval")) { interval_name= val; } else if (!strcasecmp(var, "timer-name")) { @@ -2886,6 +2999,11 @@ static conference_obj_t *conference_new(char *name, switch_xml_t profile, switch } conference->name = switch_core_strdup(conference->pool, name); + if (domain) { + conference->domain = switch_core_strdup(conference->pool, domain); + } else { + conference->domain = "cluecon.com"; + } conference->rate = rate; conference->interval = interval; @@ -2899,11 +3017,13 @@ static conference_obj_t *conference_new(char *name, switch_xml_t profile, switch return conference; } + /* Called by FreeSWITCH when the module loads */ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename) { switch_status_t status = SWITCH_STATUS_SUCCESS; - + switch_xml_t cfg, xml, param, ads; + memset(&globals, 0, sizeof(globals)); /* Connect my internal structure to the blank pointer passed to me */ @@ -2920,6 +3040,29 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_mod return SWITCH_STATUS_TERM; } + if ((xml = switch_xml_open_cfg(global_cf_name, &cfg, NULL))) { + if ((ads = switch_xml_child(cfg, "advertise"))) { + switch_event_t *event; + + for (param = switch_xml_child(ads, "room"); param; param = param->next) { + char *status = (char *) switch_xml_attr_soft(param, "status"); + char *name = (char *) switch_xml_attr_soft(param, "name"); + + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", status ? status : "Inactive"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "idle"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + + switch_event_fire(&event); + } + } + } + } + + /* Setup a hash to store conferences by name */ switch_core_hash_init(&globals.conference_hash, globals.conference_pool); switch_mutex_init(&globals.conference_mutex, SWITCH_MUTEX_NESTED, globals.conference_pool); diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index a6023391fc..f5b4140343 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -38,7 +38,7 @@ #define DL_EVENT_LOGIN_SUCCESS "dingaling::login_success" #define DL_EVENT_LOGIN_FAILURE "dingaling::login_failure" #define DL_EVENT_CONNECTED "dingaling::connected" -#define MDL_CHAT_NAME "jingle" +#define MDL_CHAT_PROTO "jingle" static const char modname[] = "mod_dingaling"; @@ -212,6 +212,10 @@ static char *translate_rpid(char *in, char *ext) r = "dnd"; } + if (!strcasecmp(in, "idle")) { + r = "away"; + } + if (ext && !strcasecmp(ext, "idle")) { r = "away"; } else if (ext && !strcasecmp(ext, "away")) { @@ -230,16 +234,19 @@ static int sub_callback(void *pArg, int argc, char **argv, char **columnNames) char *type = argv[2]; char *rpid = argv[3]; char *status = argv[4]; - + //char *proto = argv[5]; + if (switch_strlen_zero(type)) { type = NULL; } else if (!strcasecmp(type, "unavailable")) { status = NULL; } rpid = translate_rpid(rpid, status); - + + ldl_handle_send_presence(profile->handle, sub_to, sub_from, "probe", rpid, status); ldl_handle_send_presence(profile->handle, sub_to, sub_from, type, rpid, status); + return 0; } @@ -270,14 +277,23 @@ static void pres_event_handler(switch_event_t *event) struct mdl_profile *profile = NULL; switch_hash_index_t *hi; void *val; + char *proto = switch_event_get_header(event, "proto"); char *from = switch_event_get_header(event, "from"); char *status= switch_event_get_header(event, "status"); char *rpid = switch_event_get_header(event, "rpid"); char *type = switch_event_get_header(event, "event_subtype"); char *sql; switch_core_db_t *db; - char *p; + if (!proto) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Missing 'proto' header\n"); + return; + } + + if (!from) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Missing 'from' header\n"); + return; + } if (status && !strcasecmp(status, "n/a")) { status = NULL; @@ -297,12 +313,22 @@ static void pres_event_handler(switch_event_t *event) } - if ((p = strchr(from, '/'))) { - *p = '\0'; + if (!type) { + type = ""; + } + if (!rpid) { + rpid = ""; + } + if (!status) { + status = "Away"; } - sql = switch_mprintf("select sub_from, sub_to,'%q','%q','%q' from subscriptions where sub_to='%q'", - type ? type : "", rpid, status ? status : "unavailable", from); + + sql = switch_mprintf("select sub_from, sub_to,'%q','%q','%q','%q' from subscriptions where sub_to like '%%%q'", + type, rpid, status, proto, from); + + + for (hi = switch_hash_first(apr_hash_pool_get(globals.profile_hash), globals.profile_hash); hi; hi = switch_hash_next(hi)) { char *errmsg; switch_hash_this(hi, NULL, NULL, &val); @@ -330,11 +356,13 @@ static void pres_event_handler(switch_event_t *event) switch_safe_free(sql); } -static switch_status_t chat_send(char *from, char *to, char *subject, char *body, char *hint) +static switch_status_t chat_send(char *proto, char *from, char *to, char *subject, char *body, char *hint) { - char *user, *host, *f_user, *f_host = NULL; + char *user, *host, *f_user = NULL, *ffrom = NULL, *f_host = NULL; struct mdl_profile *profile = NULL; + assert(proto != NULL); + if (from && (f_user = strdup(from))) { if ((f_host = strchr(f_user, '@'))) { *f_host++ = '\0'; @@ -347,14 +375,25 @@ static switch_status_t chat_send(char *from, char *to, char *subject, char *body } if (f_host && (profile = switch_core_hash_find(globals.profile_hash, f_host))) { + + if (!strcmp(proto, MDL_CHAT_PROTO)) { + from = hint; + } else { + char *p; + ffrom = switch_mprintf("%s+%s", proto, from); + from = ffrom; + if ((p = strchr(from, '/'))) { + *p = '\0'; + } + } ldl_handle_send_msg(profile->handle, from, to, NULL, body); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile %s\n", f_host ? f_host : "NULL"); return SWITCH_STATUS_FALSE; } - switch_safe_free(f_host); - free(user); + switch_safe_free(user); + switch_safe_free(f_user); } return SWITCH_STATUS_SUCCESS; @@ -548,12 +587,8 @@ static void *SWITCH_THREAD_FUNC handle_thread_run(switch_thread_t *thread, void { ldl_handle_t *handle = obj; struct mdl_profile *profile = NULL; - switch_event_t *event; - if (switch_event_create(&event, SWITCH_EVENT_ROSTER) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_NAME); - switch_event_fire(&event); - } + profile = ldl_handle_get_private(handle); globals.handles++; @@ -1342,7 +1377,7 @@ static switch_api_interface_t login_api_interface = { }; static const switch_chat_interface_t channel_chat_interface = { - /*.name */ MDL_CHAT_NAME, + /*.name */ MDL_CHAT_PROTO, /*.chat_send */ chat_send, }; @@ -1936,7 +1971,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi break; case LDL_SIGNAL_ROSTER: if (switch_event_create(&event, SWITCH_EVENT_ROSTER) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_NAME); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", from); switch_event_fire(&event); } @@ -1949,7 +1984,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi } if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_NAME); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->login); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", from); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", msg); @@ -1967,7 +2002,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi } if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_NAME); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->login); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", from); switch_event_fire(&event); @@ -1975,8 +2010,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi break; case LDL_SIGNAL_MSG: { switch_chat_interface_t *ci; - char *proto = MDL_CHAT_NAME; - char *pproto = NULL; + char *proto = MDL_CHAT_PROTO; + char *pproto = NULL, *ffrom = NULL; if (profile->auto_reply) { ldl_handle_send_msg(handle, (profile->user_flags & LDL_FLAG_COMPONENT) ? to : profile->login, from, "", profile->auto_reply); @@ -1990,13 +2025,23 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi proto = pproto; } + if (strchr(from, '/') && (ffrom = strdup(from))) { + char *p; + if ((p = strchr(ffrom, '/'))) { + *p = '\0'; + } + from = ffrom; + + } + if ((ci = switch_loadable_module_get_chat_interface(proto))) { - ci->chat_send(from, to, subject, msg, ""); + ci->chat_send(MDL_CHAT_PROTO, from, to, subject, msg, ""); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invaid Chat Interface [%s]!\n", proto); } switch_safe_free(pproto); + switch_safe_free(ffrom); } break; case LDL_SIGNAL_LOGIN_SUCCESS: @@ -2093,14 +2138,23 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi 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); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SESSION MSG [%s]\n", msg); } if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_NAME); + char *p, *freeme = NULL; + + if (strchr(from, '/')) { + freeme = strdup(from); + p = strchr(freeme, '/'); + *p = '\0'; + from = freeme; + } + + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->login); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", from); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s", to); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s", to); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "subject", "%s", subject); if (msg) { switch_event_add_body(event, msg); @@ -2110,6 +2164,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi switch_event_fire(&event); } + switch_safe_free(freeme); } break; case LDL_SIGNAL_TRANSPORT_ACCEPT: diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index ffce1fe941..0d79b2fcf1 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -63,7 +63,7 @@ typedef struct private_object private_object_t; #define MULTICAST_EVENT "multicast::event" #define SOFIA_REPLACES_HEADER "_sofia_replaces_" #define SOFIA_USER_AGENT "FreeSWITCH(mod_sofia)" -#define SOFIA_CHAT_NAME "sip" +#define SOFIA_CHAT_PROTO "sip" #include #include @@ -349,6 +349,8 @@ static uint8_t negotiate_sdp(switch_core_session_t *session, sdp_session_t *sdp) static char *get_auth_data(char *dbname, char *nonce, char *npassword, size_t len, switch_mutex_t *mutex); +static void establish_presence(sofia_profile_t *profile); + static void sip_i_state(int status, char const *phrase, nua_t *nua, @@ -397,7 +399,7 @@ static void launch_profile_thread(sofia_profile_t *profile); static switch_status_t config_sofia(int reload); -static switch_status_t chat_send(char *from, char *to, char *subject, char *body, char *hint); +static switch_status_t chat_send(char *proto, char *from, char *to, char *subject, char *body, char *hint); /* BODY OF THE MODULE */ /*************************************************************************************************************************************************************/ @@ -837,53 +839,6 @@ static switch_status_t tech_choose_port(private_object_t *tech_pvt) return SWITCH_STATUS_SUCCESS; } -char *encode_name(char *s) -{ - char *ss, *sret; - uint32_t len; - char *at, *resource; - char *user; - - if (!s) { - return NULL; - } - - if (!strchr(s, '/')) { - return NULL; - } - - if (!(ss = strdup(s))) { - return NULL; - } - - user = ss; - - resource = strchr(user, '/'); - at = strchr(user, '@'); - - if (resource) { - *resource++ = '\0'; - } - - len = (uint32_t)strlen(user) + 25; - - if (at) { - *at++ = '\0'; - } - - if (!(sret = (char *) malloc(len))) { - return NULL; - } - - memset(sret, 0, len); - snprintf(sret, len, "jingle+%s+%s", user, at); - - free(ss); - - - return sret; -} - static void do_invite(switch_core_session_t *session) { char rpid[1024] = { 0 }; @@ -892,7 +847,7 @@ static void do_invite(switch_core_session_t *session) private_object_t *tech_pvt; switch_channel_t *channel = NULL; switch_caller_profile_t *caller_profile; - char *cid_name, *cid_num_p = NULL, *cid_num; + char *cid_name, *cid_num; char *e_dest = NULL; channel = switch_core_session_get_channel(session); @@ -906,10 +861,6 @@ static void do_invite(switch_core_session_t *session) cid_name = (char *) caller_profile->caller_id_name; cid_num = (char *) caller_profile->caller_id_number; - if ((cid_num_p = encode_name(cid_num))) { - cid_num = cid_num_p; - } - if ((tech_pvt->from_str = switch_mprintf("\"%s\" ", cid_name, cid_num, @@ -985,8 +936,6 @@ static void do_invite(switch_core_session_t *session) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); } - switch_safe_free(cid_num_p); - } @@ -1861,7 +1810,7 @@ static const switch_endpoint_interface_t sofia_endpoint_interface = { }; static const switch_chat_interface_t sofia_chat_interface = { - /*.name */ SOFIA_CHAT_NAME, + /*.name */ SOFIA_CHAT_PROTO, /*.chat_send */ chat_send, }; @@ -2192,6 +2141,11 @@ static void sip_i_message(int status, to_host = (char *) to->a_url->url_host; } + + if (!to_user) { + return; + } + if (payload) { msg = payload->pl_data; } @@ -2209,7 +2163,7 @@ static void sip_i_message(int status, char *from_addr; char *p; char *full_from; - char proto[512] = SOFIA_CHAT_NAME; + char proto[512] = SOFIA_CHAT_PROTO; full_from = sip_header_as_string(profile->home, (void *)sip->sip_from); @@ -2219,21 +2173,23 @@ static void sip_i_message(int status, *p++ = '\0'; if ((to_addr = strdup(p))) { - p = strchr(to_addr, '+'); - *p = '@'; + if((p = strchr(to_addr, '+'))) { + *p = '@'; + } } } else { to_addr = switch_mprintf("%s@%s", to_user, to_host); } - from_addr = switch_mprintf("%s+%s@%s", SOFIA_CHAT_NAME, from_user, from_host); + from_addr = switch_mprintf("%s@%s", from_user, from_host); + set_hash_key(hash_key, sizeof(hash_key), sip); if ((tech_pvt = (private_object_t *) switch_core_hash_find(profile->chat_hash, hash_key))) { channel = switch_core_session_get_channel(tech_pvt->session); if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", tech_pvt->hash_key); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s", to_addr); @@ -2250,7 +2206,7 @@ static void sip_i_message(int status, switch_chat_interface_t *ci; if ((ci = switch_loadable_module_get_chat_interface(proto))) { - ci->chat_send(from_addr, to_addr, "", msg, full_from); + ci->chat_send(SOFIA_CHAT_PROTO, from_addr, to_addr, "", msg, full_from); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invaid Chat Interface [%s]!\n", proto); } @@ -2594,7 +2550,7 @@ static char *get_auth_data(char *dbname, char *nonce, char *npassword, size_t le sql = switch_mprintf("select passwd from sip_authentication where nonce='%q'", nonce); - if(switch_core_db_prepare(db, sql, -1, &stmt, 0)) { + if (switch_core_db_prepare(db, sql, -1, &stmt, 0)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Statement Error!\n"); goto fail; } else { @@ -2858,7 +2814,7 @@ static uint8_t handle_register(nua_t *nua, switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", rpid); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_NAME, from_user, from_host); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Registered"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); @@ -2873,7 +2829,7 @@ static uint8_t handle_register(nua_t *nua, if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_NAME, from_user, from_host); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_PROTO, from_user, from_host); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "unavailable"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", rpid); @@ -2903,18 +2859,18 @@ static uint8_t handle_register(nua_t *nua, static int sub_reg_callback(void *pArg, int argc, char **argv, char **columnNames) { sofia_profile_t *profile = (sofia_profile_t *) pArg; - char *from = argv[0]; - char *status = argv[1]; + //char *proto = argv[0]; + char *user = argv[1]; + char *host = argv[2]; switch_event_t *event; - + char *status = NULL; if (switch_strlen_zero(status)) { status = "Available"; } - if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", from); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", user, host); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", status); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_subtype", "probe"); @@ -2924,6 +2880,28 @@ static int sub_reg_callback(void *pArg, int argc, char **argv, char **columnName return 0; } +static int resub_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + sofia_profile_t *profile = (sofia_profile_t *) pArg; + char *user = argv[0]; + char *host = argv[1]; + char *status = argv[2]; + char *rpid = argv[3]; + switch_event_t *event; + + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", user, host); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", status); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", rpid); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_fire(&event); + } + + return 0; +} + static int sub_callback(void *pArg, int argc, char **argv, char **columnNames) { sofia_profile_t *profile = (sofia_profile_t *) pArg; @@ -2958,7 +2936,7 @@ static int sub_callback(void *pArg, int argc, char **argv, char **columnNames) open = "closed"; } - if (strcasecmp(proto, "sip")) { + if (strcasecmp(proto, SOFIA_CHAT_PROTO)) { /*encapsulate*/ id = switch_mprintf("sip:%s+%s+%s@%s", proto, sub_to_user, sub_to_host, host); } else { @@ -2985,7 +2963,6 @@ static int sub_callback(void *pArg, int argc, char **argv, char **columnNames) nh = nua_handle(profile->nua, NULL, TAG_END()); - nua_notify(nh, NUTAG_URL(contact), SIPTAG_TO_STR(full_from), @@ -3069,11 +3046,13 @@ static void sip_i_subscribe(int status, } if (strchr(to_user, '+')) { + char *h; if ((proto = (d_user = strdup(to_user)))) { if ((to_user = strchr(d_user, '+'))) { *to_user++ = '\0'; - if ((to_host = strchr(to_user, '+'))) { - *to_host++ = '\0'; + if ((h = strchr(to_user, '+')) || (h = strchr(to_user, '@'))) { + *h++ = '\0'; + to_host = h; } } } @@ -3113,7 +3092,7 @@ static void sip_i_subscribe(int status, full_from, full_via, exp - ))) { + ))) { execute_sql(profile->dbname, sql, profile->ireg_mutex); switch_safe_free(sql); } @@ -3133,7 +3112,7 @@ static void sip_i_subscribe(int status, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname); goto end; } - if ((sql = switch_mprintf("select 'sip+%q@%q',status,rpid from sip_registrations where user='%q' and host='%q'", + if ((sql = switch_mprintf("select * from sip_subscriptions where user='%q' and host='%q'", to_user, to_host, to_user, to_host))) { switch_mutex_lock(profile->ireg_mutex); switch_core_db_exec(db, sql, sub_reg_callback, profile, &errmsg); @@ -3501,10 +3480,10 @@ static void sip_i_publish(nua_t *nua, if (in) { if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", rpid); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_NAME, from_user, from_host); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", note_txt); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "%s", event_type); @@ -3512,10 +3491,10 @@ static void sip_i_publish(nua_t *nua, } } else { if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", rpid); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_NAME, from_user, from_host); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "%s", event_type); switch_event_fire(&event); @@ -3681,7 +3660,7 @@ static void sip_i_invite(nua_t *nua, if (!strncasecmp(argv[x], "privacy=", 8)) { char *arg = argv[x] + 9; - if(!strcasecmp(arg, "no")) { + if (!strcasecmp(arg, "no")) { switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME); switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NUMBER); } else if (!strcasecmp(arg, "yes")) { @@ -4162,10 +4141,7 @@ static void *SWITCH_THREAD_FUNC profile_thread_run(switch_thread_t *thread, void switch_mutex_unlock(globals.hash_mutex); if (profile->pflags & PFLAG_PRESENCE) { - if (switch_event_create(&s_event, SWITCH_EVENT_ROSTER) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_NAME); - switch_event_fire(&s_event); - } + establish_presence(profile); } while(globals.running == 1) { @@ -4542,13 +4518,14 @@ static void event_handler(switch_event_t *event) } -static switch_status_t chat_send(char *from, char *to, char *subject, char *body, char *hint) +static switch_status_t chat_send(char *proto, char *from, char *to, char *subject, char *body, char *hint) { char buf[256]; char *user, *host; sofia_profile_t *profile; - char *from_p = NULL, *from_pp = NULL, *from_ppp = NULL; - + char *ffrom = NULL; + nua_handle_t *msg_nh; + if (to && (user = strdup(to))) { if ((host = strchr(user, '@'))) { *host++ = '\0'; @@ -4559,48 +4536,47 @@ static switch_status_t chat_send(char *from, char *to, char *subject, char *body return SWITCH_STATUS_FALSE; } - if (find_reg_url(profile, user, host, buf, sizeof(buf))) { - nua_handle_t *msg_nh; - - if ((from_p = encode_name(from))) { - char *p, *q = NULL; - - from_ppp = strdup(from_p); - if ((p = strchr(from_ppp, '+'))) { - *p++ = '\0'; - if ((q = strchr(p, '+'))) { - *q = '@'; - } - } - if (!p) { - p = from; - } - from_pp = switch_mprintf("\"%s\" ", p, from_p, host); - from = from_pp; - } else { - from = hint; - } - - - msg_nh = nua_handle(profile->nua, NULL, - SIPTAG_FROM_STR(from), - NUTAG_URL(buf), - SIPTAG_TO_STR(buf), - SIPTAG_CONTACT_STR(profile->url), - TAG_END()); - - nua_message(msg_nh, - SIPTAG_CONTENT_TYPE_STR("text/html"), - SIPTAG_PAYLOAD_STR(body), - TAG_END()); - - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid chat dest"); + if (!find_reg_url(profile, user, host, buf, sizeof(buf))) { + return SWITCH_STATUS_FALSE; } - switch_safe_free(from_p); - switch_safe_free(from_pp); - switch_safe_free(from_ppp); + if (!strcmp(proto, SOFIA_CHAT_PROTO)) { + from = hint; + } else { + char *fp, *p, *fu = NULL; + + if (!(fp = strdup(from))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + return SWITCH_STATUS_FALSE; + } + + if ((p = strchr(fp, '@'))) { + *p = '\0'; + fu = strdup(fp); + *p = '+'; + } + + ffrom = switch_mprintf("\"%s\"", fu, proto, fp, profile->name); + from = ffrom; + switch_safe_free(fu); + switch_safe_free(fp); + } + + + msg_nh = nua_handle(profile->nua, NULL, + SIPTAG_FROM_STR(from), + NUTAG_URL(buf), + SIPTAG_TO_STR(buf), + SIPTAG_CONTACT_STR(profile->url), + TAG_END()); + + nua_message(msg_nh, + SIPTAG_CONTENT_TYPE_STR("text/html"), + SIPTAG_PAYLOAD_STR(body), + TAG_END()); + + + switch_safe_free(ffrom); free(user); } @@ -4637,6 +4613,28 @@ static void cancel_presence(void) } +static void establish_presence(sofia_profile_t *profile) +{ + char *sql, *errmsg = NULL; + switch_core_db_t *db; + + if (!(db = switch_core_db_open_file(profile->dbname))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname); + return; + } + + if ((sql = switch_mprintf("select user,host,'Registered','unavailable' from sip_registrations"))) { + switch_mutex_lock(profile->ireg_mutex); + switch_core_db_exec(db, sql, resub_callback, profile, &errmsg); + switch_mutex_unlock(profile->ireg_mutex); + switch_safe_free(sql); + } + + switch_core_db_close(db); + +} + + static char *translate_rpid(char *in, char *ext) { @@ -4671,15 +4669,17 @@ static void pres_event_handler(switch_event_t *event) switch_hash_index_t *hi; void *val; char *from = switch_event_get_header(event, "from"); + char *proto = switch_event_get_header(event, "proto"); char *rpid = switch_event_get_header(event, "rpid"); char *status= switch_event_get_header(event, "status"); char *event_type = switch_event_get_header(event, "event_type"); - char *sql = NULL, *sql2 = NULL; + //char *event_subtype = switch_event_get_header(event, "event_subtype"); + char *sql = NULL; char *euser = NULL, *user = NULL, *host = NULL; char *errmsg; - char *resource; switch_core_db_t *db; + if (rpid && !strcasecmp(rpid, "n/a")) { rpid = NULL; } @@ -4690,7 +4690,7 @@ static void pres_event_handler(switch_event_t *event) if (rpid) { rpid = translate_rpid(rpid, status); - } + } if (!status) { status = "Available"; @@ -4706,12 +4706,16 @@ static void pres_event_handler(switch_event_t *event) } } + if (!rpid) { + rpid = "unknown"; + } + if (event->event_id == SWITCH_EVENT_ROSTER) { if (from) { - sql = switch_mprintf("select 1,'%q',%q',* from sip_subscriptions where event='presence' and full_from like '%%%q%%'", status, rpid, from); + sql = switch_mprintf("select 1,'%q','%q',* from sip_subscriptions where event='presence' and full_from like '%%%q%%'", status, rpid, from); } else { - sql = switch_mprintf("select 1,'%q',%q',* from sip_subscriptions where event='presence'", status, rpid); + sql = switch_mprintf("select 1,'%q','%q',* from sip_subscriptions where event='presence'", status, rpid); } for (hi = switch_hash_first(apr_hash_pool_get(globals.profile_hash), globals.profile_hash); hi; hi = switch_hash_next(hi)) { @@ -4744,37 +4748,29 @@ static void pres_event_handler(switch_event_t *event) if ((user = strdup(from))) { if ((host = strchr(user, '@'))) { *host++ = '\0'; - } - if ((resource = strchr(host, '/'))) { - *resource++ = '\0'; + } else { + switch_safe_free(user); + return; } if ((euser = strchr(user, '+'))) { euser++; } else { euser = user; } + } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); return; } - - if (!host) { - switch_safe_free(user); - return; - } - - - switch(event->event_id) { case SWITCH_EVENT_PRESENCE_IN: - sql = switch_mprintf("select 1,'%q','%q',* from sip_subscriptions where event='%q' and sub_to_user='%q' and sub_to_host='%q'", - status , rpid, event_type, euser, host); + sql = switch_mprintf("select 1,'%q','%q',* from sip_subscriptions where proto='%q' and event='%q' and sub_to_user='%q' and sub_to_host='%q'", + status , rpid, proto, event_type, euser, host); break; case SWITCH_EVENT_PRESENCE_OUT: - sql = switch_mprintf("select 0,'%q','%q',* from sip_subscriptions where event='%q' and sub_to_user='%q' and sub_to_host='%q'", - status, rpid, event_type, euser, host); + sql = switch_mprintf("select 0,'%q','%q',* from sip_subscriptions where proto='%q' and event='%q' and sub_to_user='%q' and sub_to_host='%q'", + status, rpid, proto, event_type, euser, host); break; default: break; @@ -4796,13 +4792,6 @@ static void pres_event_handler(switch_event_t *event) switch_core_db_exec(db, sql, sub_callback, profile, &errmsg); switch_mutex_unlock(profile->ireg_mutex); - - if ((sql2 = switch_mprintf("select 'sip+%q@%q',status,rpid from sip_registrations where user='%q' and host='%q'", euser, host, user, host))) { - switch_mutex_lock(profile->ireg_mutex); - switch_core_db_exec(db, sql2, sub_reg_callback, profile, &errmsg); - switch_mutex_unlock(profile->ireg_mutex); - switch_safe_free(sql2); - } switch_core_db_close(db); } }