Bug Summary

File:src/mod/endpoints/mod_sofia/sofia_presence.c
Warning:line 562, column 30
Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sofia_presence.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fno-trapping-math -ffp-contract=fast -ffast-math -ffinite-math-only -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -resource-dir /usr/lib/llvm-7/lib/clang/7.0.1 -D HAVE_CONFIG_H -I . -I ../../../../src/include -I ../../../../libs/esl/src/include -I ../../../../libs/xmlrpc-c -I /drone/src/src/include -I /drone/src/src/include -I /drone/src/libs/libteletone/src -D SWITCH_API_VISIBILITY=1 -D CJSON_API_VISIBILITY=1 -D HAVE_VISIBILITY=1 -I /usr/include/uuid -I /drone/src/src/include -I /drone/src/src/include -I /drone/src/libs/libteletone/src -D SWITCH_API_VISIBILITY=1 -D CJSON_API_VISIBILITY=1 -D HAVE_VISIBILITY=1 -D HAVE_OPENSSL -I . -I /usr/include/sofia-sip-1.13 -D HAVE_STIRSHAKEN -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-result -Wno-misleading-indentation -std=c99 -fdebug-compilation-dir /drone/src/src/mod/endpoints/mod_sofia -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -o /drone/src/scan-build/2021-10-18-150934-401-1 -x c sofia_presence.c -faddrsig
1/*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Ken Rice <krice@freeswitch.org>
28 * Paul D. Tinsley <pdt at jackhammer.org>
29 * Bret McDanel <trixter AT 0xdecafbad.com>
30 * Raymond Chandler <intralanman@freeswitch.org>
31 * William King <william.king@quentustech.com>
32 * Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
33 * David Knell <david.knell@telng.com>
34 *
35 * sofia_presence.c -- SOFIA SIP Endpoint (presence code)
36 *
37 */
38#include "mod_sofia.h"
39#include "switch_stun.h"
40
41#define SUB_OVERLAP300 300
42struct state_helper {
43 switch_hash_t *hash;
44 sofia_profile_t *profile;
45 switch_memory_pool_t *pool;
46 int total;
47};
48
49
50static int sofia_presence_mwi_callback(void *pArg, int argc, char **argv, char **columnNames);
51static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char **columnNames);
52static int sofia_presence_sub_reg_callback(void *pArg, int argc, char **argv, char **columnNames);
53static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char **columnNames);
54static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char **columnNames);
55static int broadsoft_sla_gather_state_callback(void *pArg, int argc, char **argv, char **columnNames);
56static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char **columnNames);
57static int sync_sla(sofia_profile_t *profile, const char *to_user, const char *to_host, switch_bool_t clear, switch_bool_t unseize, const char *call_id);
58static int sofia_dialog_probe_callback(void *pArg, int argc, char **argv, char **columnNames);
59static int sofia_dialog_probe_notify_callback(void *pArg, int argc, char **argv, char **columnNames);
60
61struct pres_sql_cb {
62 sofia_profile_t *profile;
63 int ttl;
64};
65
66static int sofia_presence_send_sql(void *pArg, int argc, char **argv, char **columnNames);
67
68struct dialog_helper {
69 char state[128];
70 char status[512];
71 char rpid[512];
72 char presence_id[1024];
73 int hits;
74};
75
76struct resub_helper {
77 sofia_profile_t *profile;
78 switch_event_t *event;
79 int rowcount;
80 int noreg;
81};
82
83struct rfc4235_helper {
84 switch_hash_t *hash;
85 sofia_profile_t *profile;
86 switch_memory_pool_t *pool;
87 switch_event_t *event;
88 int rowcount;
89};
90
91struct presence_helper {
92 sofia_profile_t *profile;
93 switch_event_t *event;
94 switch_stream_handle_t stream;
95 char last_uuid[512];
96 int hup;
97 int calls_up;
98
99};
100
101switch_status_t sofia_presence_chat_send(switch_event_t *message_event)
102
103{
104 char *prof = NULL((void*)0), *user = NULL((void*)0), *host = NULL((void*)0);
105 sofia_profile_t *profile = NULL((void*)0);
106 char *ffrom = NULL((void*)0);
107 nua_handle_t *msg_nh;
108 char *contact = NULL((void*)0);
109 char *dup = NULL((void*)0);
110 switch_status_t status = SWITCH_STATUS_FALSE;
111 const char *ct = "text/html";
112 sofia_destination_t *dst = NULL((void*)0);
113 char *to_uri = NULL((void*)0);
114 switch_console_callback_match_t *list = NULL((void*)0);
115 switch_console_callback_match_node_t *m;
116 char *remote_ip = NULL((void*)0);
117 char *user_via = NULL((void*)0);
118 //char *contact_str = NULL;
119 char *dup_dest = NULL((void*)0);
120 char *p = NULL((void*)0);
121 char *remote_host = NULL((void*)0);
122 const char *proto;
123 const char *from;
124 const char *to;
125 //const char *subject;
126 const char *body;
127 const char *type;
128 const char *from_full;
129 char header[256] = "";
130 char *route_uri = NULL((void*)0);
131 const char *network_ip = NULL((void*)0), *network_port = NULL((void*)0), *from_proto;
132 char *extra_headers = NULL((void*)0);
133 char uuid_str[SWITCH_UUID_FORMATTED_LENGTH256 + 1];
134 int mstatus = 0, sanity = 0;
135 const char *blocking;
136 int is_blocking = 0;
137
138 proto = switch_event_get_header(message_event, "proto")switch_event_get_header_idx(message_event, "proto", -1);
139 from_proto = switch_event_get_header(message_event, "from_proto")switch_event_get_header_idx(message_event, "from_proto", -1);
140 from = switch_event_get_header(message_event, "from")switch_event_get_header_idx(message_event, "from", -1);
141 to = switch_event_get_header(message_event, "to")switch_event_get_header_idx(message_event, "to", -1);
142 //subject = switch_event_get_header(message_event, "subject");
143 body = switch_event_get_body(message_event);
144 type = switch_event_get_header(message_event, "type")switch_event_get_header_idx(message_event, "type", -1);
145 from_full = switch_event_get_header(message_event, "from_full")switch_event_get_header_idx(message_event, "from_full", -1);
146 blocking = switch_event_get_header(message_event, "blocking")switch_event_get_header_idx(message_event, "blocking", -1);
147 is_blocking = switch_true(blocking);
148
149 network_ip = switch_event_get_header(message_event, "to_sip_ip")switch_event_get_header_idx(message_event, "to_sip_ip", -1);
150 network_port = switch_event_get_header(message_event, "to_sip_port")switch_event_get_header_idx(message_event, "to_sip_port", -1);
151
152 extra_headers = sofia_glue_get_extra_headers_from_event(message_event, SOFIA_SIP_HEADER_PREFIX"sip_h_");
153
154 if (!to) {
155 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 155, ((void*)0)
, SWITCH_LOG_ERROR, "Missing To: header.\n");
156 goto end;
157 }
158
159 if (!from) {
160 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 160, ((void*)0)
, SWITCH_LOG_ERROR, "Missing From: header.\n");
161 goto end;
162 }
163
164 if (!zstr(type)_zstr(type)) {
165 ct = type;
166 }
167
168 dup = strdup(to);
169 switch_assert(dup)((dup) ? (void) (0) : __assert_fail ("dup", "sofia_presence.c"
, 169, __extension__ __PRETTY_FUNCTION__))
;
170 prof = dup;
171
172 /* Do we have a user of the form profile/user[@host]? */
173 if ((user = strchr(prof, '/'))) {
174 *user++ = '\0';
175 } else {
176 user = prof;
177 prof = NULL((void*)0);
178 }
179
180 if (!prof) {
181 prof = switch_event_get_header(message_event, "sip_profile")switch_event_get_header_idx(message_event, "sip_profile", -1);
182 }
183
184 if (!strncasecmp(user, "sip:", 4)) {
185 to_uri = user;
186 }
187
188 if ((host = strchr(user, '@'))) {
189 if (!to_uri) {
190 *host++ = '\0';
191 } else {
192 host++;
193 }
194 if (!prof) {
195 prof = host;
196 }
197 }
198
199 if (!prof || !(profile = sofia_glue_find_profile(prof)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 199, prof)
)) {
200 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 200, ((void*)0)
, SWITCH_LOG_ERROR,
201 "Chat proto [%s]\nfrom [%s]\nto [%s]\n%s\nInvalid Profile %s\n", proto, from, to,
202 body ? body : "[no body]", prof ? prof : "NULL");
203 goto end;
204 }
205
206 if (zstr(host)_zstr(host)) {
207 host = profile->domain_name;
208 if (zstr(host)_zstr(host)) {
209 host = prof;
210 }
211 }
212
213
214 if (to_uri) {
215 switch_console_push_match(&list, to_uri);
216 } else if (!(list = sofia_reg_find_reg_url_multi(profile, user, host))) {
217 sofia_profile_t *test;
218
219 if ((test = sofia_glue_find_profile(host)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 219, host)
)) {
220 sofia_glue_release_profile(test)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 220, test)
;
221 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 221, ((void*)0)
, SWITCH_LOG_WARNING, "Not sending to local box for %s@%s\n", user, host);
222 /* our box let's not send it */
223 } else {
224 char *tmp;
225 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 225, ((void*)0)
, SWITCH_LOG_DEBUG, "Can't find registered user %s@%s\n", user, host);
226 tmp = switch_mprintf("sip:%s@%s", user, host);
227 switch_console_push_match(&list, tmp);
228 free(tmp);
229 }
230
231 }
232
233 if (!strcasecmp(proto, SOFIA_CHAT_PROTO"sip")) {
234 from = from_full;
235 } else {
236 char *fp, *p = NULL((void*)0);
237
238
239 fp = strdup(from);
240 switch_assert(fp)((fp) ? (void) (0) : __assert_fail ("fp", "sofia_presence.c",
240, __extension__ __PRETTY_FUNCTION__))
;
241
242
243 if ((p = strchr(fp, '@'))) {
244 *p++ = '\0';
245 }
246
247 if (zstr(p)_zstr(p)) {
248 p = profile->domain_name;
249 if (zstr(p)_zstr(p)) {
250 p = host;
251 }
252 }
253
254 if (switch_stristr("global", proto)) {
255 if (!from_proto || !strcasecmp(from_proto, SOFIA_CHAT_PROTO"sip")) {
256 ffrom = switch_mprintf("\"%s\" <sip:%s@%s>", fp, fp, p);
257 } else {
258 ffrom = switch_mprintf("\"%s\" <sip:%s+%s@%s>", fp, from_proto, fp, p);
259 }
260
261 } else {
262 ffrom = switch_mprintf("\"%s\" <sip:%s+%s@%s>", fp, from_proto ? from_proto : proto, fp, p);
263 }
264
265 from = ffrom;
266 switch_safe_free(fp)if (fp) {free(fp);fp=((void*)0);};
267 }
268
269 if (!list) {
270 switch_event_t *event;
271
272 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 272, ((void*)0)
, SWITCH_LOG_ERROR,
273 "Chat proto [%s]\nfrom [%s]\nto [%s]\n%s\nNobody to send to: Profile %s\n", proto, from, to,
274 body ? body : "[no body]", prof);
275 // emit no recipient event
276 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_ERROR)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 276, &event, SWITCH_EVENT_CUSTOM
, "sofia::error")
== SWITCH_STATUS_SUCCESS) {
277 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Error-Type", "chat");
278 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Error-Reason", "no recipient");
279 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Chat-Send-To", to);
280 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Chat-Send-From", from);
281 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Chat-Send-Profile", prof);
282 switch_event_add_body(event, "%s", body);
283 switch_event_fire(&event)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 283, &event, ((void*)0))
;
284 }
285
286 goto end;
287 }
288
289 for (m = list->head; m; m = m->next) {
290
291 if (!(dst = sofia_glue_get_destination(m->val))) {
292 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 292, ((void*)0)
, SWITCH_LOG_CRIT, "Memory Error!\n");
293 break;
294 }
295
296 /* sofia_glue is running sofia_overcome_sip_uri_weakness we do not, not sure if it matters */
297
298 if (dst->route_uri) {
299 dup_dest = strdup(dst->route_uri);
300 } else {
301 dup_dest = strdup(dst->to);
302 }
303
304 switch_assert(dup_dest)((dup_dest) ? (void) (0) : __assert_fail ("dup_dest", "sofia_presence.c"
, 304, __extension__ __PRETTY_FUNCTION__))
;
305
306 remote_host = strdup(dup_dest);
307 if (!zstr(remote_host)_zstr(remote_host)) {
308 switch_split_user_domain(remote_host, NULL((void*)0), &remote_ip);
309 }
310
311 if (!zstr(remote_ip)_zstr(remote_ip) && sofia_glue_check_nat(profile, remote_ip)) {
312 char *ptr = NULL((void*)0);
313 if ((ptr = sofia_glue_find_parameter(dst->contact, "transport="))) {
314 sofia_transport_t transport = sofia_glue_str2transport( ptr + 10 );
315 user_via = sofia_glue_create_external_via(NULL((void*)0), profile, transport);
316 } else {
317 user_via = sofia_glue_create_external_via(NULL((void*)0), profile, SOFIA_TRANSPORT_UDP);
318 }
319 }
320
321 status = SWITCH_STATUS_SUCCESS;
322
323 if ((p = strstr(dup_dest, ";fs_"))) {
324 *p = '\0';
325 }
326
327 /* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */
328
329 //printf("DEBUG To: [%s] From: [%s] Contact: [%s] RURI [%s] ip [%s] port [%s]\n", to, from, contact, dst->route_uri, network_ip, network_port);
330
331 //DUMP_EVENT(message_event);
332
333 if (zstr(dst->route_uri)_zstr(dst->route_uri) && !zstr(user)_zstr(user) && !zstr(network_ip)_zstr(network_ip) && (zstr(host)_zstr(host) || strcmp(network_ip, host))) {
334 route_uri = switch_mprintf("sip:%s@%s:%s", user, network_ip, network_port);
335 }
336
337 msg_nh = nua_handle(profile->nua, NULL((void*)0),
338 TAG_END()(tag_type_t)0, (tag_value_t)0);
339
340 nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private);
341
342 switch_snprintf(header, sizeof(header), "X-FS-Sending-Message: %s", switch_core_get_uuid());
343
344 switch_uuid_str(uuid_str, sizeof(uuid_str));
345
346 if (is_blocking) {
347 switch_mutex_lock(profile->flag_mutex);
348 switch_core_hash_insert(profile->chat_hash, uuid_str, &mstatus)switch_core_hash_insert_destructor(profile->chat_hash, uuid_str
, &mstatus, ((void*)0))
;
349 switch_mutex_unlock(profile->flag_mutex);
350 }
351
352 nua_message(msg_nh,
353 TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri))!(dst->route_uri) ? tag_skip : ntatag_default_proxy, urltag_url_v
((dst->route_uri))
,
354 TAG_IF(route_uri, NUTAG_PROXY(route_uri))!(route_uri) ? tag_skip : ntatag_default_proxy, urltag_url_v(
(route_uri))
,
355 TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route))!(dst->route) ? tag_skip : siptag_route_str, tag_str_v(dst
->route)
,
356 SIPTAG_FROM_STR(from)siptag_from_str, tag_str_v(from),
357 TAG_IF(contact, NUTAG_URL(contact))!(contact) ? tag_skip : nutag_url, urltag_url_v(contact),
358 SIPTAG_TO_STR(dup_dest)siptag_to_str, tag_str_v(dup_dest),
359 SIPTAG_CALL_ID_STR(uuid_str)siptag_call_id_str, tag_str_v(uuid_str),
360 TAG_IF(user_via, SIPTAG_VIA_STR(user_via))!(user_via) ? tag_skip : siptag_via_str, tag_str_v(user_via),
361 SIPTAG_CONTENT_TYPE_STR(ct)siptag_content_type_str, tag_str_v(ct),
362 SIPTAG_PAYLOAD_STR(body)siptag_payload_str, tag_str_v(body),
363 SIPTAG_HEADER_STR(header)siptag_header_str, tag_str_v((header)),
364 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
365 TAG_END()(tag_type_t)0, (tag_value_t)0);
366
367
368 if (is_blocking) {
369 sanity = 200;
370
371 while(!mstatus && --sanity && !nua_handle_is_destroyed(msg_nh)) {
372 switch_yield(100000)switch_sleep(100000);;
373 }
374
375 if (!(mstatus > 199 && mstatus < 300)) {
376 status = SWITCH_STATUS_FALSE;
377 }
378
379 switch_event_add_header(message_event, SWITCH_STACK_BOTTOM, "Delivery-Result-Code", "%d", mstatus);
380
381 switch_mutex_lock(profile->flag_mutex);
382 switch_core_hash_delete(profile->chat_hash, uuid_str);
383 switch_mutex_unlock(profile->flag_mutex);
384 }
385
386 sofia_glue_free_destination(dst);
387 switch_safe_free(dup_dest)if (dup_dest) {free(dup_dest);dup_dest=((void*)0);};
388 switch_safe_free(user_via)if (user_via) {free(user_via);user_via=((void*)0);};
389 switch_safe_free(remote_host)if (remote_host) {free(remote_host);remote_host=((void*)0);};
390 }
391
392 end:
393
394 if (list) {
395 switch_console_free_matches(&list);
396 }
397
398 switch_safe_free(contact)if (contact) {free(contact);contact=((void*)0);};
399 switch_safe_free(route_uri)if (route_uri) {free(route_uri);route_uri=((void*)0);};
400 switch_safe_free(ffrom)if (ffrom) {free(ffrom);ffrom=((void*)0);};
401 switch_safe_free(dup)if (dup) {free(dup);dup=((void*)0);};
402
403 if (profile) {
404 switch_thread_rwlock_unlock(profile->rwlock);
405 }
406
407 return status;
408}
409
410void sofia_presence_cancel(void)
411{
412 char *sql;
413 sofia_profile_t *profile;
414 struct presence_helper helper = { 0 };
415 switch_console_callback_match_t *matches;
416 switch_bool_t r;
417
418 if (!mod_sofia_globals.profile_hash) {
419 return;
420 }
421
422 if (list_profiles_full(NULL((void*)0), NULL((void*)0), &matches, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
423 switch_console_callback_match_node_t *m;
424
425
426 for (m = matches->head; m; m = m->next) {
427 if ((profile = sofia_glue_find_profile(m->val)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 427, m->val)
)) {
428 if (profile->pres_type == PRES_TYPE_FULL) {
429 helper.profile = profile;
430 helper.event = NULL((void*)0);
431
432 sql = switch_mprintf("select proto,sip_user,sip_host,sub_to_user,sub_to_host,event,contact,call_id,full_from,"
433 "full_via,expires,user_agent,accept,profile_name,network_ip"
434 ",-1,'unavailable','unavailable' from sip_subscriptions where "
435 "event='presence' and hostname='%q' and profile_name='%q'",
436 mod_sofia_globals.hostname, profile->name);
437
438 r = sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_sub_callback, &helper);
439 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
440
441 if (r != SWITCH_TRUE) {
442 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 442, profile)
;
443 continue;
444 }
445 }
446 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 446, profile)
;
447 }
448 }
449
450 switch_console_free_matches(&matches);
451
452 }
453}
454
455char *sofia_presence_translate_rpid(char *in, char *ext)
456{
457 char *r = in;
458
459 if (in && (switch_stristr("null", in))) {
460 in = NULL((void*)0);
461 }
462
463 if (!in) {
464 in = ext;
465 }
466
467 if (!in) {
468 return NULL((void*)0);
469 }
470
471 if (!strcasecmp(in, "dnd") || !strcasecmp(in, "idle")) {
472 r = "busy";
473 }
474
475 return r;
476}
477
478struct mwi_helper {
479 sofia_profile_t *profile;
480 int total;
481};
482
483static void actual_sofia_presence_mwi_event_handler(switch_event_t *event)
484{
485 char *account, *dup_account, *yn, *host, *user;
486 char *sql;
487 sofia_profile_t *profile = NULL((void*)0);
488 switch_stream_handle_t stream = { 0 };
489 switch_event_header_t *hp;
490 struct mwi_helper h = { 0 };
491 const char *pname = NULL((void*)0);
492 const char *call_id;
493 const char *sub_call_id;
494 int for_everyone = 0;
495
496 switch_assert(event != NULL)((event != ((void*)0)) ? (void) (0) : __assert_fail ("event != ((void*)0)"
, "sofia_presence.c", 496, __extension__ __PRETTY_FUNCTION__)
)
;
497
498 if (!(account = switch_event_get_header(event, "mwi-message-account")switch_event_get_header_idx(event, "mwi-message-account", -1))) {
14
Assuming 'account' is not null
15
Taking false branch
499 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 499, ((void*)0)
, SWITCH_LOG_ERROR, "Missing required Header 'MWI-Message-Account'\n");
500 return;
501 }
502
503 if (!(yn = switch_event_get_header(event, "mwi-messages-waiting")switch_event_get_header_idx(event, "mwi-messages-waiting", -1
)
)) {
16
Assuming 'yn' is not null
17
Taking false branch
504 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 504, ((void*)0)
, SWITCH_LOG_ERROR, "Missing required Header 'MWI-Messages-Waiting'\n");
505 return;
506 }
507
508 call_id = switch_event_get_header(event, "call-id")switch_event_get_header_idx(event, "call-id", -1);
509 sub_call_id = switch_event_get_header(event, "sub-call-id")switch_event_get_header_idx(event, "sub-call-id", -1);
510
511 if (!call_id && !sub_call_id) {
18
Assuming 'call_id' is non-null
512 for_everyone = 1;
513 }
514
515
516 dup_account = strdup(account);
517 switch_assert(dup_account != NULL)((dup_account != ((void*)0)) ? (void) (0) : __assert_fail ("dup_account != ((void*)0)"
, "sofia_presence.c", 517, __extension__ __PRETTY_FUNCTION__)
)
;
518 switch_split_user_domain(dup_account, &user, &host);
19
Value assigned to 'host'
519
520
521 if ((pname = switch_event_get_header(event, "sofia-profile")switch_event_get_header_idx(event, "sofia-profile", -1))) {
20
Assuming 'pname' is null
21
Taking false branch
522 profile = sofia_glue_find_profile(pname)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 522, pname)
;
523 }
524
525 if (!profile) {
22
Taking true branch
526 if (!host || !(profile = sofia_glue_find_profile(host)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 526, host)
)) {
23
Assuming 'host' is null
527 char *sql;
528 char buf[512] = "";
529 switch_console_callback_match_t *matches;
530
531 sql = switch_mprintf("select profile_name from sip_registrations where hostname='%q' and (sip_host='%q' or mwi_host='%q')",
532 mod_sofia_globals.hostname, host, host);
533
534 if (list_profiles_full(NULL((void*)0), NULL((void*)0), &matches, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
24
Assuming the condition is false
25
Taking false branch
535 switch_console_callback_match_node_t *m;
536
537 for (m = matches->head; m; m = m->next) {
538 if ((profile = sofia_glue_find_profile(m->val)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 538, m->val)
)) {
539
540 sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
541 if (!zstr(buf)_zstr(buf)) {
542 break;
543 }
544 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 544, profile)
;
545 }
546 }
547
548 switch_console_free_matches(&matches);
549 }
550
551 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
552
553 if (!(profile = sofia_glue_find_profile(buf)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 553, buf)
)) {
26
Assuming 'profile' is not null
27
Taking false branch
554 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 554, ((void*)0)
, SWITCH_LOG_ERROR, "Cannot find profile %s\n", switch_str_nil(host)(host ? host : ""));
555 switch_safe_free(dup_account)if (dup_account) {free(dup_account);dup_account=((void*)0);};
556 return;
557 }
558 }
559 }
560
561
562 if (profile->domain_name && strcasecmp(profile->domain_name, host)) {
28
Assuming the condition is true
29
Null pointer passed as an argument to a 'nonnull' parameter
563 host = profile->domain_name;
564 }
565
566 h.profile = profile;
567 h.total = 0;
568
569 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "sofia_presence.c", 569, __extension__ __PRETTY_FUNCTION__)
); memset(stream.data, 0, 1024); stream.end = stream.data; stream
.data_size = 1024; stream.write_function = switch_console_stream_write
; stream.raw_write_function = switch_console_stream_raw_write
; stream.alloc_len = 1024; stream.alloc_chunk = 1024
;
570
571 for (hp = event->headers; hp; hp = hp->next) {
572 if (!strncasecmp(hp->name, "mwi-", 4)) {
573 char *tmp = NULL((void*)0);
574 char *value = hp->value;
575 if (!strcasecmp(hp->name, "mwi-message-account") && strncasecmp(hp->value, "sip:", 4)) {
576 tmp = switch_mprintf("sip:%s", hp->value);
577 value = tmp;
578 }
579 stream.write_function(&stream, "%s: %s\r\n", hp->name + 4, value);
580 switch_safe_free(tmp)if (tmp) {free(tmp);tmp=((void*)0);};
581 }
582 }
583
584 stream.write_function(&stream, "\r\n");
585
586 sql = NULL((void*)0);
587
588 if (for_everyone) {
589 sql = switch_mprintf("select proto,sip_user,sip_host,sub_to_user,sub_to_host,event,contact,call_id,full_from,"
590 "full_via,expires,user_agent,accept,profile_name,network_ip"
591 ",'%q',full_to,network_ip,network_port from sip_subscriptions "
592 "where hostname='%q' and event='message-summary' "
593 "and sub_to_user='%q' and (sub_to_host='%q' or presence_hosts like '%%%q%%')",
594 stream.data, mod_sofia_globals.hostname, user, host, host);
595 } else if (sub_call_id) {
596 sql = switch_mprintf("select proto,sip_user,sip_host,sub_to_user,sub_to_host,event,contact,call_id,full_from,"
597 "full_via,expires,user_agent,accept,profile_name,network_ip"
598 ",'%q',full_to,network_ip,network_port from sip_subscriptions where "
599 "hostname='%q' and event='message-summary' "
600 "and sub_to_user='%q' and (sub_to_host='%q' or presence_hosts like '%%%q%%') and call_id='%q'",
601 stream.data, mod_sofia_globals.hostname, user, host, host, sub_call_id);
602 }
603
604
605 if (sql) {
606 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_mwi_callback, &h);
607 free(sql);
608 sql = NULL((void*)0);
609
610 }
611
612 if (for_everyone) {
613 sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,network_ip,'%q',call_id "
614 "from sip_registrations where hostname='%q' and mwi_user='%q' and mwi_host='%q'",
615 stream.data, mod_sofia_globals.hostname, user, host);
616 } else if (call_id) {
617 sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,network_ip,'%q',call_id "
618 "from sip_registrations where hostname='%q' and call_id='%q'",
619 stream.data, mod_sofia_globals.hostname, call_id);
620 }
621
622 if (sql) {
623 switch_assert(sql != NULL)((sql != ((void*)0)) ? (void) (0) : __assert_fail ("sql != ((void*)0)"
, "sofia_presence.c", 623, __extension__ __PRETTY_FUNCTION__)
)
;
624 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_mwi_callback2, &h);
625 free(sql);
626 sql = NULL((void*)0);
627 }
628
629 switch_safe_free(stream.data)if (stream.data) {free(stream.data);stream.data=((void*)0);};
630 switch_safe_free(dup_account)if (dup_account) {free(dup_account);dup_account=((void*)0);};
631 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 631, profile)
;
632}
633
634static int sofia_presence_dialog_callback(void *pArg, int argc, char **argv, char **columnNames)
635{
636 struct dialog_helper *helper = (struct dialog_helper *) pArg;
637 switch_core_session_t *session = NULL((void*)0);
638 switch_channel_t *channel = NULL((void*)0);
639 int done = 0;
640
641 if (argc >= 4) {
642
643 if (argc == 5 && !zstr(argv[4])_zstr(argv[4])) {
644 if ((session = switch_core_session_locate(argv[4])switch_core_session_perform_locate(argv[4], "sofia_presence.c"
, (const char *)__func__, 644)
)) {
645 channel = switch_core_session_get_channel(session);
646
647 if (!switch_channel_test_flag(channel, CF_ANSWERED) &&
648 switch_true(switch_channel_get_variable_dup(channel, "presence_disable_early", SWITCH_FALSE, -1))) {
649 done++;
650 }
651
652 switch_core_session_rwunlock(session);
653 } else {
654 return 0;
655 }
656 }
657
658 if (done) {
659 return 0;
660 }
661
662 if (mod_sofia_globals.debug_presence > 0) {
663 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 663, ((void*)0)
, SWITCH_LOG_CRIT, "CHECK DIALOG state[%s] status[%s] rpid[%s] pres[%s] uuid[%s]\n",
664 argv[0], argv[1], argv[2], argv[3], argv[4]);
665 }
666
667 if (!helper->hits) {
668 switch_set_string(helper->state, argv[0])switch_copy_string(helper->state, argv[0], sizeof(helper->
state))
;
669 switch_set_string(helper->status, argv[1])switch_copy_string(helper->status, argv[1], sizeof(helper->
status))
;
670 switch_set_string(helper->rpid, argv[2])switch_copy_string(helper->rpid, argv[2], sizeof(helper->
rpid))
;
671 switch_set_string(helper->presence_id, argv[3])switch_copy_string(helper->presence_id, argv[3], sizeof(helper
->presence_id))
;
672 }
673 helper->hits++;
674 }
675
676 return 0;
677}
678
679
680static void do_normal_probe(switch_event_t *event)
681{
682 char *sql;
683 struct resub_helper h = { 0 };
684 char *to = switch_event_get_header(event, "to")switch_event_get_header_idx(event, "to", -1);
685 char *proto = switch_event_get_header(event, "proto")switch_event_get_header_idx(event, "proto", -1);
686 char *profile_name = switch_event_get_header(event, "sip_profile")switch_event_get_header_idx(event, "sip_profile", -1);
687 char *probe_user = NULL((void*)0), *probe_euser, *probe_host, *p;
688 struct dialog_helper dh = { { 0 } };
689 char *sub_call_id = switch_event_get_header(event, "sub-call-id")switch_event_get_header_idx(event, "sub-call-id", -1);
690 sofia_profile_t *profile;
691
692 //DUMP_EVENT(event);
693
694 if (!proto || strcasecmp(proto, SOFIA_CHAT_PROTO"sip") != 0) {
695 return;
696 }
697
698 if (!to || !(probe_user = strdup(to))) {
699 return;
700 }
701
702 if ((probe_host = strchr(probe_user, '@'))) {
703 *probe_host++ = '\0';
704 }
705 probe_euser = probe_user;
706 if ((p = strchr(probe_euser, '+')) && p != probe_euser) {
707 probe_euser = (p + 1);
708 }
709
710 if (probe_host &&
711 ((profile = sofia_glue_find_profile(probe_host)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 711, probe_host)
) || (profile_name && (profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 711, profile_name)
)))) {
712 sql = switch_mprintf("select state,status,rpid,presence_id,uuid from sip_dialogs "
713 "where hostname='%q' and profile_name='%q' and call_info_state != 'seized' and "
714 "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') order by rcd desc",
715 mod_sofia_globals.hostname, profile->name, probe_euser, probe_host, probe_euser, probe_host);
716
717
718 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_dialog_callback, &dh);
719
720 h.profile = profile;
721
722 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
723
724 sql = switch_mprintf("select sip_registrations.sip_user, "
725 "sip_registrations.sub_host, "
726 "sip_registrations.status, "
727 "sip_registrations.rpid, "
728 "'', "
729 "sip_dialogs.uuid, "
730 "sip_dialogs.state, "
731 "sip_dialogs.direction, "
732 "sip_dialogs.sip_to_user, "
733 "sip_dialogs.sip_to_host, "
734
735 "sip_presence.status,"
736 "sip_presence.rpid,"
737 "sip_dialogs.presence_id, "
738 "sip_presence.open_closed,"
739 "'%q','%q','%q' "
740 "from sip_registrations "
741
742 "left join sip_dialogs on "
743 "sip_dialogs.hostname = sip_registrations.hostname and sip_dialogs.profile_name = sip_registrations.profile_name and ("
744 "sip_dialogs.presence_id = sip_registrations.sip_user %q '@' %q sip_registrations.sub_host "
745 "or (sip_dialogs.sip_from_user = sip_registrations.sip_user "
746 "and sip_dialogs.sip_from_host = sip_registrations.sip_host)) "
747
748 "left join sip_presence on "
749 "sip_presence.hostname=sip_registrations.hostname and "
750 "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.orig_server_host=sip_presence.sip_host and "
751 "sip_registrations.profile_name=sip_presence.profile_name) "
752 "where sip_registrations.hostname='%q' and sip_registrations.profile_name='%q' and sip_dialogs.call_info_state != 'seized' "
753 "and sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and "
754 "(sip_registrations.orig_server_host='%q' or sip_registrations.sub_host='%q' "
755 "))",
756 dh.status, dh.rpid, switch_str_nil(sub_call_id)(sub_call_id ? sub_call_id : ""),
757 switch_sql_concat(), switch_sql_concat(),
758 mod_sofia_globals.hostname, profile->name, probe_euser, probe_host, probe_euser, probe_host, probe_host);
759
760
761
762 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "sofia_presence.c"
, 762, __extension__ __PRETTY_FUNCTION__))
;
763
764 if (mod_sofia_globals.debug_presence > 0) {
765 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 765, ((void*)0)
, SWITCH_LOG_INFO, "%s START_PRESENCE_PROBE_SQL\n", profile->name);
766 }
767
768 if (mod_sofia_globals.debug_presence > 1) {
769 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 769, ((void*)0)
, SWITCH_LOG_ERROR, "%s DUMP PRESENCE_PROBE_SQL:\n%s\n", profile->name, sql);
770 }
771
772 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_resub_callback, &h);
773 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
774
775 if (!h.rowcount) {
776 h.noreg++;
777
778 /* find ones with presence_id defined that are not registred */
779 sql = switch_mprintf("select sip_from_user, sip_from_host, 'Registered', '', '', "
780 "uuid, state, direction, "
781 "sip_to_user, sip_to_host,"
782 "'%q','%q',presence_id, '','','' "
783
784 "from sip_dialogs "
785
786 "where call_info_state != 'seized' and hostname='%q' and profile_name='%q' and (presence_id='%q@%q' or "
787 "(sip_from_user='%q' and (sip_from_host='%q' or sip_to_host='%q')))",
788 mod_sofia_globals.hostname, profile->name,
789 dh.status, dh.rpid, probe_euser, probe_host, probe_euser, probe_host, probe_host);
790
791 if (mod_sofia_globals.debug_presence > 0) {
792 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 792, ((void*)0)
, SWITCH_LOG_INFO, "%s START_PRESENCE_PROBE_SQL\n", profile->name);
793 }
794
795 if (mod_sofia_globals.debug_presence > 1) {
796 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 796, ((void*)0)
, SWITCH_LOG_ERROR, "%s DUMP PRESENCE_PROBE_SQL:\n%s\n", profile->name, sql);
797 }
798
799 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_resub_callback, &h);
800 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
801
802 if (mod_sofia_globals.debug_presence > 0) {
803 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 803, ((void*)0)
, SWITCH_LOG_INFO, "%s END_PRESENCE_PROBE_SQL\n\n", profile->name);
804 }
805 }
806
807 if (!h.rowcount) {
808 switch_event_t *sevent;
809 if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_IN)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 809, &sevent, SWITCH_EVENT_PRESENCE_IN
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
810 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
811 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name);
812 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
813 switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", probe_euser, probe_host);
814 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "status", "Unregistered");
815 switch_event_fire(&sevent)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 815, &sevent, ((void*)0))
;
816 }
817 }
818
819
820 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 820, profile)
;
821 }
822
823
824 switch_safe_free(probe_user)if (probe_user) {free(probe_user);probe_user=((void*)0);};
825}
826
827static void do_dialog_probe(switch_event_t *event)
828{
829 // Received SUBSCRIBE for "dialog" events.
830 // Return a complete list of dialogs for the monitored entity.
831 char *sql;
832 char *to = switch_event_get_header(event, "to")switch_event_get_header_idx(event, "to", -1);
833 char *probe_user = NULL((void*)0), *probe_euser, *probe_host, *p;
834
835 if (!to || !(probe_user = strdup(to))) {
836 return;
837 }
838
839 if ((probe_host = strchr(probe_user, '@'))) {
840 *probe_host++ = '\0';
841 }
842 probe_euser = probe_user;
843 if ((p = strchr(probe_euser, '+')) && p != probe_euser) {
844 probe_euser = (p + 1);
845 }
846
847 if (probe_host) {
848 char *sub_call_id = switch_event_get_header(event, "sub-call-id")switch_event_get_header_idx(event, "sub-call-id", -1);
849 char *profile_name = switch_event_get_header(event, "sip_profile")switch_event_get_header_idx(event, "sip_profile", -1);
850 sofia_profile_t *profile = sofia_glue_find_profile(probe_host)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 850, probe_host)
;
851 struct rfc4235_helper *h4235 = {0};
852 switch_memory_pool_t *pool;
853
854 if (!profile && profile_name) {
855 profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 855, profile_name)
;
856 }
857
858 if (!profile) {
859 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 859, ((void*)0)
, SWITCH_LOG_WARNING, "Cannot find profile for domain %s\n", probe_host);
860 goto end;
861 }
862
863 // We need all dialogs with presence_id matching the subscription entity,
864 // or from a registered set matching the subscription entity.
865 // We need the "proto" of the subscription in case it is for the special "conf" or "park".
866 sql = switch_mprintf(
867 "select sip_subscriptions.proto, '%q','%q',"
868 "sip_dialogs.uuid, sip_dialogs.call_id, sip_dialogs.state, sip_dialogs.direction, "
869 "sip_dialogs.sip_to_user, sip_dialogs.sip_to_host, "
870 "sip_dialogs.sip_from_user, sip_dialogs.sip_from_host, "
871 "sip_dialogs.contact, sip_dialogs.contact_user, sip_dialogs.contact_host, "
872 "sip_dialogs.sip_to_tag, sip_dialogs.sip_from_tag, sip_subscriptions.orig_proto "
873 "from sip_dialogs "
874 "left join sip_subscriptions on sip_subscriptions.hostname=sip_dialogs.hostname and "
875 "sip_subscriptions.profile_name=sip_dialogs.profile_name and "
876 "sip_subscriptions.call_id='%q' "
877 "left join sip_registrations on sip_registrations.hostname=sip_dialogs.hostname and "
878 "sip_registrations.profile_name=sip_dialogs.profile_name and "
879 "(sip_dialogs.sip_from_user = sip_registrations.sip_user and sip_dialogs.sip_from_host = '%q' and "
880 "(sip_dialogs.sip_from_host = sip_registrations.orig_server_host or "
881 "sip_dialogs.sip_from_host = sip_registrations.sip_host) ) "
882 "where sip_dialogs.hostname='%q' and sip_dialogs.profile_name='%q' and "
883 "sip_dialogs.call_info_state != 'seized' and sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and "
884 "(sip_registrations.orig_server_host='%q' or sip_registrations.sub_host='%q' "
885 "or sip_registrations.presence_hosts like '%%%q%%'))",
886 probe_euser, probe_host,
887 sub_call_id, probe_host,
888 mod_sofia_globals.hostname, profile->name,
889 probe_euser, probe_host,
890 probe_euser, probe_host, probe_host, probe_host);
891 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "sofia_presence.c"
, 891, __extension__ __PRETTY_FUNCTION__))
;
892
893 if (mod_sofia_globals.debug_presence > 0) {
894 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 894, ((void*)0)
,SWITCH_LOG_INFO, "%s START DIALOG_PROBE_SQL %s@%s\n", profile->name,probe_euser, probe_host);
895 }
896
897 if (mod_sofia_globals.debug_presence > 1) {
898 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 898, ((void*)0)
, SWITCH_LOG_DEBUG, "%s DUMP DIALOG_PROBE_SQL:\n%s\n", profile->name, sql);
899 }
900
901 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "sofia_presence.c"
, (const char *)__func__, 901)
;
902 h4235 = switch_core_alloc(pool, sizeof(*h4235))switch_core_perform_alloc(pool, sizeof(*h4235), "sofia_presence.c"
, (const char *)__func__, 902)
;
903 h4235->pool = pool;
904 h4235->profile = profile;
905 switch_core_hash_init(&h4235->hash)switch_core_hash_init_case(&h4235->hash, SWITCH_TRUE);
906 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_dialog_probe_callback, h4235);
907 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
908 if (mod_sofia_globals.debug_presence > 0) {
909 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 909, ((void*)0)
, SWITCH_LOG_INFO, "%s END DIALOG_PROBE_SQL\n\n", profile->name);
910 }
911
912
913 sql = switch_mprintf("update sip_subscriptions set version=version+1 where call_id='%q'", sub_call_id);
914
915 if (mod_sofia_globals.debug_presence > 1) {
916 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 916, ((void*)0)
, SWITCH_LOG_DEBUG, "%s DUMP DIALOG_PROBE set version sql:\n%s\n", profile->name, sql);
917 }
918 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
919 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
920
921
922 // The dialog_probe_callback has built up the dialogs to be included in the NOTIFY.
923 // Now send the "full" dialog event to the triggering subscription.
924 sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,version, "
925 "'full',full_to,full_from,contact,network_ip,network_port "
926 "from sip_subscriptions "
927 "where hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and call_id='%q'",
928 mod_sofia_globals.hostname, profile->name, probe_euser, probe_host, sub_call_id);
929
930 if (mod_sofia_globals.debug_presence > 1) {
931 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 931, ((void*)0)
, SWITCH_LOG_DEBUG, "%s DUMP DIALOG_PROBE subscription sql:\n%s\n", profile->name, sql);
932 }
933
934 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_dialog_probe_notify_callback, h4235);
935 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
936
937 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 937, profile)
;
938 switch_core_hash_destroy(&h4235->hash);
939 h4235 = NULL((void*)0);
940 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "sofia_presence.c"
, (const char *)__func__, 940)
;
941 }
942
943 end:
944
945 switch_safe_free(probe_user)if (probe_user) {free(probe_user);probe_user=((void*)0);};
946}
947
948static void send_conference_data(sofia_profile_t *profile, switch_event_t *event)
949{
950 char *sql;
951 struct pres_sql_cb cb = {profile, 0};
952 const char *call_id = switch_event_get_header(event, "call_id")switch_event_get_header_idx(event, "call_id", -1);
953 const char *from_user = switch_event_get_header(event, "conference-name")switch_event_get_header_idx(event, "conference-name", -1);
954 const char *from_host = switch_event_get_header(event, "conference-domain")switch_event_get_header_idx(event, "conference-domain", -1);
955 const char *event_str = switch_event_get_header(event, "conference-event")switch_event_get_header_idx(event, "conference-event", -1);
956 const char *notfound = switch_event_get_header(event, "notfound")switch_event_get_header_idx(event, "notfound", -1);
957 const char *body = switch_event_get_body(event);
958 const char *type = "application/conference-info+xml";
959 const char *final = switch_event_get_header(event, "final")switch_event_get_header_idx(event, "final", -1);
960
961 if (!event_str) {
962 event_str = "conference";
963 }
964
965 if (!strcasecmp(event_str, "refer")) {
966 type = "message/sipfrag";
967 }
968
969
970 if (!(from_user && from_host)) {
971 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 971, ((void*)0)
, SWITCH_LOG_ERROR, "Event information not given\n");
972 return;
973 }
974
975 if (switch_true(notfound)) {
976 sql = switch_mprintf("update sip_subscriptions set expires=%ld where "
977 "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q'",
978 (long)switch_epoch_time_now(NULL((void*)0)),
979 mod_sofia_globals.hostname, profile->name,
980 from_user, from_host, event_str);
981
982 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
983 }
984
985 if (call_id) {
986 if (switch_true(final)) {
987 sql = switch_mprintf("update sip_subscriptions set expires=%ld where "
988 "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q' "
989 "and call_id = '%q' ",
990 (long)0,
991 mod_sofia_globals.hostname, profile->name,
992 from_user, from_host, event_str, call_id);
993
994 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
995 }
996
997 sql = switch_mprintf("select full_to, full_from, contact %q ';_;isfocus', expires, call_id, event, network_ip, network_port, "
998 "'%q' as ct,'%q' as pt "
999 " from sip_subscriptions where "
1000 "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q' "
1001 "and call_id = '%q' ",
1002 switch_sql_concat(),
1003 type,
1004 switch_str_nil(body)(body ? body : ""),
1005 mod_sofia_globals.hostname, profile->name,
1006 from_user, from_host, event_str, call_id);
1007 } else {
1008 if (switch_true(final)) {
1009 sql = switch_mprintf("update sip_subscriptions set expires=%ld where "
1010 "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q'",
1011 (long)0,
1012 mod_sofia_globals.hostname, profile->name,
1013 from_user, from_host, event_str);
1014
1015 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1016 }
1017
1018 sql = switch_mprintf("select full_to, full_from, contact %q ';_;isfocus', expires, call_id, event, network_ip, network_port, "
1019 "'%q' as ct,'%q' as pt "
1020 " from sip_subscriptions where "
1021 "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q'",
1022 switch_sql_concat(),
1023 type,
1024 switch_str_nil(body)(body ? body : ""),
1025 mod_sofia_globals.hostname, profile->name,
1026 from_user, from_host, event_str);
1027 }
1028
1029 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_send_sql, &cb);
1030 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1031
1032 if (switch_true(final)) {
1033 if (call_id) {
1034 sql = switch_mprintf("delete from sip_subscriptions where "
1035 "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q' "
1036 "and call_id = '%q' ",
1037 mod_sofia_globals.hostname, profile->name,
1038 from_user, from_host, event_str, call_id);
1039
1040 } else {
1041 sql = switch_mprintf("delete from sip_subscriptions where "
1042 "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q'",
1043 mod_sofia_globals.hostname, profile->name,
1044 from_user, from_host, event_str);
1045 }
1046
1047 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1048 }
1049
1050
1051}
1052
1053static void conference_data_event_handler(switch_event_t *event)
1054{
1055 const char *pname;
1056 //const char *from_user = switch_event_get_header(event, "conference-name");
1057 //const char *from_host = switch_event_get_header(event, "conference-domain");
1058 const char *host = switch_event_get_header(event, "conference-domain")switch_event_get_header_idx(event, "conference-domain", -1);
1059 char *dup_domain = NULL((void*)0);
1060 sofia_profile_t *profile = NULL((void*)0);
1061
1062 if (zstr(host)_zstr(host)) {
1063 dup_domain = switch_core_get_domain(SWITCH_TRUE);
1064 host = dup_domain;
1065 }
1066
1067 if ((pname = switch_event_get_header(event, "sofia-profile")switch_event_get_header_idx(event, "sofia-profile", -1))) {
1068 profile = sofia_glue_find_profile(pname)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 1068, pname)
;
1069 }
1070
1071 if (host && !profile) {
1072 profile = sofia_glue_find_profile(host)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 1072, host)
;
1073 }
1074
1075 if (profile) {
1076 send_conference_data(profile, event);
1077 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 1077, profile)
;
1078 } else {
1079 switch_console_callback_match_t *matches;
1080
1081 if (list_profiles_full(NULL((void*)0), NULL((void*)0), &matches, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
1082 switch_console_callback_match_node_t *m;
1083
1084 for (m = matches->head; m; m = m->next) {
1085 if ((profile = sofia_glue_find_profile(m->val)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 1085, m->val)
)) {
1086 send_conference_data(profile, event);
1087 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 1087, profile)
;
1088 }
1089 }
1090
1091 switch_console_free_matches(&matches);
1092 }
1093 }
1094
1095 switch_safe_free(dup_domain)if (dup_domain) {free(dup_domain);dup_domain=((void*)0);};
1096}
1097
1098static switch_event_t *actual_sofia_presence_event_handler(switch_event_t *event)
1099{
1100 sofia_profile_t *profile = NULL((void*)0);
1101 char *from = switch_event_get_header(event, "from")switch_event_get_header_idx(event, "from", -1);
1102 char *proto = switch_event_get_header(event, "proto")switch_event_get_header_idx(event, "proto", -1);
1103 char *rpid = switch_event_get_header(event, "rpid")switch_event_get_header_idx(event, "rpid", -1);
1104 char *status = switch_event_get_header(event, "status")switch_event_get_header_idx(event, "status", -1);
1105 char *event_type = switch_event_get_header(event, "event_type")switch_event_get_header_idx(event, "event_type", -1);
1106 char *alt_event_type = switch_event_get_header(event, "alt_event_type")switch_event_get_header_idx(event, "alt_event_type", -1);
1107 //char *event_subtype = switch_event_get_header(event, "event_subtype");
1108 char *sql = NULL((void*)0);
1109 char *euser = NULL((void*)0), *user = NULL((void*)0), *host = NULL((void*)0);
1110 char *call_info = switch_event_get_header(event, "presence-call-info")switch_event_get_header_idx(event, "presence-call-info", -1);
1111 char *call_id = switch_event_get_header(event, "call-id")switch_event_get_header_idx(event, "call-id", -1);
1112 char *presence_source = switch_event_get_header(event, "presence-source")switch_event_get_header_idx(event, "presence-source", -1);
1113 char *call_info_state = switch_event_get_header(event, "presence-call-info-state")switch_event_get_header_idx(event, "presence-call-info-state"
, -1)
;
1114 const char *uuid = switch_event_get_header(event, "unique-id")switch_event_get_header_idx(event, "unique-id", -1);
1115 switch_console_callback_match_t *matches = NULL((void*)0);
1116 struct presence_helper helper = { 0 };
1117 int hup = 0;
1118 switch_event_t *s_event = NULL((void*)0);
1119
1120 if (!mod_sofia_globals.running) {
1121 goto done;
1122 }
1123
1124 if (zstr(proto)_zstr(proto) || !strcasecmp(proto, "any")) {
1125 proto = SOFIA_CHAT_PROTO"sip";
1126 }
1127
1128 //DUMP_EVENT(event);
1129
1130 if (rpid && !strcasecmp(rpid, "n/a")) {
1131 rpid = NULL((void*)0);
1132 }
1133
1134 if (status && !strcasecmp(status, "n/a")) {
1135 status = NULL((void*)0);
1136 }
1137
1138 if (!zstr(uuid)_zstr(uuid) && !switch_ivr_uuid_exists(uuid)) {
1139 status = "CS_HANGUP";
1140 }
1141
1142
1143 if ((status && switch_stristr("CS_HANGUP", status)) || (!zstr(uuid)_zstr(uuid) && !switch_ivr_uuid_exists(uuid))) {
1144 status = "Available";
1145 hup = 1;
1146 }
1147
1148 if (rpid) {
1149 rpid = sofia_presence_translate_rpid(rpid, status);
1150 }
1151
1152 if (event->event_id == SWITCH_EVENT_ROSTER) {
1153 if (list_profiles_full(NULL((void*)0), NULL((void*)0), &matches, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
1154 switch_console_callback_match_node_t *m;
1155
1156 for (m = matches->head; m; m = m->next) {
1157 if ((profile = sofia_glue_find_profile(m->val)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 1157, m->val)
)) {
1158 if (profile->pres_type != PRES_TYPE_FULL) {
1159
1160
1161 if (!mod_sofia_globals.profile_hash) {
1162 switch_console_free_matches(&matches);
1163 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 1163, profile)
;
1164 goto done;
1165 }
1166
1167 if (from) {
1168
1169 sql = switch_mprintf("update sip_subscriptions set version=version+1 where hostname='%q' and profile_name='%q' and "
1170 "sip_subscriptions.event='presence' and sip_subscriptions.full_from like '%%%q%%'",
1171 mod_sofia_globals.hostname, profile->name, from);
1172
1173 if (mod_sofia_globals.debug_presence > 1) {
1174 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1174, ((void*)0)
, SWITCH_LOG_ERROR, "PRES SQL %s\n", sql);
1175 }
1176
1177 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1178
1179
1180 sql = switch_mprintf("select sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host,"
1181 "sip_subscriptions.sub_to_user,sip_subscriptions.sub_to_host,sip_subscriptions.event,"
1182 "sip_subscriptions.contact,sip_subscriptions.call_id,sip_subscriptions.full_from,"
1183 "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent,"
1184 "sip_subscriptions.accept,sip_subscriptions.profile_name,sip_subscriptions.network_ip"
1185 ",1,'%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'','','','','sip',"
1186 " sip_subscriptions.full_to,sip_subscriptions.network_ip,sip_subscriptions.network_port "
1187 "from sip_subscriptions left join sip_presence on "
1188 "(sip_subscriptions.sub_to_user=sip_presence.sip_user and "
1189 "sip_subscriptions.sub_to_host=sip_presence.sip_host and "
1190 "sip_subscriptions.profile_name=sip_presence.profile_name and "
1191 "sip_presence.profile_name=sip_subscriptions.profile_name) "
1192 "where sip_subscriptions.hostname='%q' and sip_subscriptions.profile_name='%q' and "
1193 "sip_subscriptions.event='presence' and sip_subscriptions.full_from like '%%%q%%'",
1194 switch_str_nil(status)(status ? status : ""), switch_str_nil(rpid)(rpid ? rpid : ""), mod_sofia_globals.hostname, profile->name, from);
1195 } else {
1196
1197 sql = switch_mprintf("update sip_subscriptions set version=version+1 where hostname='%q' and profile_name='%q' and "
1198 "sip_subscriptions.event='presence'", mod_sofia_globals.hostname, profile->name);
1199
1200 if (mod_sofia_globals.debug_presence > 1) {
1201 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1201, ((void*)0)
, SWITCH_LOG_ERROR, "PRES SQL %s\n", sql);
1202 }
1203
1204 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1205
1206 sql = switch_mprintf("select sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host,"
1207 "sip_subscriptions.sub_to_user,sip_subscriptions.sub_to_host,sip_subscriptions.event,"
1208 "sip_subscriptions.contact,sip_subscriptions.call_id,sip_subscriptions.full_from,"
1209 "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent,"
1210 "sip_subscriptions.accept,sip_subscriptions.profile_name,sip_subscriptions.network_ip"
1211 ",1,'%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'','','','','sip',"
1212 "sip_subscriptions.full_to,sip_subscriptions.network_ip,sip_subscriptions.network_port "
1213 "from sip_subscriptions left join sip_presence on "
1214 "(sip_subscriptions.sub_to_user=sip_presence.sip_user and "
1215 "sip_subscriptions.sub_to_host=sip_presence.sip_host and "
1216 "sip_subscriptions.profile_name=sip_presence.profile_name and "
1217 "sip_subscriptions.hostname = sip_presence.hostname) "
1218 "where sip_subscriptions.hostname='%q' and sip_subscriptions.profile_name='%q' and "
1219 "sip_subscriptions.event='presence'", switch_str_nil(status)(status ? status : ""),
1220 switch_str_nil(rpid)(rpid ? rpid : ""), mod_sofia_globals.hostname, profile->name);
1221 }
1222
1223 switch_assert(sql != NULL)((sql != ((void*)0)) ? (void) (0) : __assert_fail ("sql != ((void*)0)"
, "sofia_presence.c", 1223, __extension__ __PRETTY_FUNCTION__
))
;
1224
1225
1226 if (mod_sofia_globals.debug_presence > 0) {
1227 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1227, ((void*)0)
, SWITCH_LOG_WARNING, "%s is passive, skipping\n", (char *) profile->name);
1228 }
1229 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 1229, profile)
;
1230 continue;
1231 }
1232 memset(&helper, 0, sizeof(helper));
1233 helper.profile = profile;
1234 helper.event = NULL((void*)0);
1235 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_sub_callback, &helper);
1236 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1237 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 1237, profile)
;
1238 }
1239 }
1240 switch_console_free_matches(&matches);
1241 }
1242
1243 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1244 goto done;
1245 }
1246
1247 if (zstr(event_type)_zstr(event_type)) {
1248 event_type = "presence";
1249 }
1250
1251 if (zstr(alt_event_type)_zstr(alt_event_type)) {
1252 if (!strcasecmp(event_type, "presence")) {
1253 alt_event_type = "dialog";
1254 } else {
1255 alt_event_type = "presence";
1256 }
1257 }
1258
1259 if (from && (user = strdup(from))) {
1260 if ((host = strchr(user, '@'))) {
1261 char *p;
1262 *host++ = '\0';
1263 if ((p = strchr(host, '/'))) {
1264 *p = '\0';
1265 }
1266 } else {
1267 switch_safe_free(user)if (user) {free(user);user=((void*)0);};
1268 goto done;
1269 }
1270 if ((euser = strchr(user, '+')) && euser != user) {
1271 euser++;
1272 } else {
1273 euser = user;
1274 }
1275 } else {
1276 goto done;
1277 }
1278
1279 switch (event->event_id) {
1280 case SWITCH_EVENT_PRESENCE_PROBE:
1281 {
1282 char *probe_type = switch_event_get_header(event, "probe-type")switch_event_get_header_idx(event, "probe-type", -1);
1283
1284 if (!probe_type || strcasecmp(probe_type, "dialog")) {
1285 /* NORMAL PROBE */
1286 do_normal_probe(event);
1287 } else {
1288 /* DIALOG PROBE */
1289 do_dialog_probe(event);
1290 }
1291 }
1292 goto done;
1293
1294 default:
1295 break;
1296 }
1297
1298 if (!mod_sofia_globals.profile_hash) {
1299 goto done;
1300 }
1301
1302 if (list_profiles_full(NULL((void*)0), NULL((void*)0), &matches, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
1303 switch_console_callback_match_node_t *m;
1304
1305 for (m = matches->head; m; m = m->next) {
1306 struct dialog_helper dh = { { 0 } };
1307
1308 if ((profile = sofia_glue_find_profile(m->val)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 1308, m->val)
)) {
1309 if (profile->pres_type != PRES_TYPE_FULL) {
1310 if (mod_sofia_globals.debug_presence > 0) {
1311 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1311, ((void*)0)
, SWITCH_LOG_WARNING, "%s is passive, skipping\n", (char *) profile->name);
1312 }
1313 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 1313, profile)
;
1314 continue;
1315 }
1316
1317
1318 if (mod_sofia_globals.debug_sla > 1) {
1319 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1319, ((void*)0)
, SWITCH_LOG_ERROR, "SLA EVENT:\n");
1320 DUMP_EVENT(event){char *event_str;switch_event_serialize(event, &event_str
, SWITCH_FALSE);switch_log_printf(SWITCH_CHANNEL_ID_LOG, "sofia_presence.c"
, (const char *)__func__, 1320, ((void*)0), SWITCH_LOG_CRIT, "DUMP\n%s\n"
, event_str);free(event_str);}
;
1321
1322 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1322, ((void*)0)
, SWITCH_LOG_ERROR, "CHECK CALL_INFO [%s]\n", switch_str_nil(call_info)(call_info ? call_info : ""));
1323 }
1324
1325 if (call_info) {
1326
1327 if (uuid) {
1328 sql = switch_mprintf("update sip_dialogs set call_info='%q',call_info_state='%q' where "
1329 "hostname='%q' and profile_name='%q' and uuid='%q'",
1330 call_info, call_info_state, mod_sofia_globals.hostname, profile->name, uuid);
1331 } else {
1332 sql = switch_mprintf("update sip_dialogs set call_info='%q', call_info_state='%q' where hostname='%q' and profile_name='%q' and "
1333 "((sip_dialogs.sip_from_user='%q' and sip_dialogs.sip_from_host='%q') or presence_id='%q@%q') and call_info='%q'",
1334
1335 call_info, call_info_state, mod_sofia_globals.hostname, profile->name, euser, host, euser, host, call_info);
1336
1337 }
1338
1339 if (mod_sofia_globals.debug_sla > 1) {
1340 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1340, ((void*)0)
, SWITCH_LOG_ERROR, "STATE SQL %s\n", sql);
1341 }
1342 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1343
1344
1345
1346 if (mod_sofia_globals.debug_sla > 1) {
1347 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1347, ((void*)0)
, SWITCH_LOG_ERROR, "PROCESS PRESENCE EVENT\n");
1348 }
1349
1350 sync_sla(profile, euser, host, SWITCH_TRUE, SWITCH_TRUE, call_id);
1351 }
1352
1353 if (!strcmp(proto, "dp")) {
1354 sql = switch_mprintf("update sip_presence set rpid='%q',status='%q' where hostname='%q' and profile_name='%q' and "
1355 "sip_user='%q' and sip_host='%q'",
1356 rpid, status, mod_sofia_globals.hostname, profile->name, euser, host);
1357 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1358 proto = SOFIA_CHAT_PROTO"sip";
1359 }
1360
1361 if (zstr(uuid)_zstr(uuid)) {
1362
1363 sql = switch_mprintf("select state,status,rpid,presence_id,uuid from sip_dialogs "
1364 "where call_info_state != 'seized' and hostname='%q' and profile_name='%q' and "
1365 "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') order by rcd desc",
1366 mod_sofia_globals.hostname, profile->name, euser, host, euser, host);
1367 } else {
1368 sql = switch_mprintf("select state,status,rpid,presence_id,uuid from sip_dialogs "
1369 "where uuid != '%q' and call_info_state != 'seized' and hostname='%q' and profile_name='%q' and "
1370 "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') order by rcd desc",
1371 uuid, mod_sofia_globals.hostname, profile->name, euser, host, euser, host);
1372 }
1373
1374 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_dialog_callback, &dh);
1375
1376 if (mod_sofia_globals.debug_presence > 0) {
1377 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1377, ((void*)0)
, SWITCH_LOG_CRIT, "CHECK SQL: %s@%s [%s]\nhits: %d\n", euser, host, sql, dh.hits);
1378 }
1379
1380 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1381
1382 if (hup && dh.hits > 0) {
1383 /* sigh, mangle this packet to simulate a call that is up instead of hungup */
1384 hup = 0;
1385 event->flags |= EF_UNIQ_HEADERS;
1386
1387 if (!strcasecmp(dh.state, "early")) {
1388 status = "CS_ROUTING";
1389 if (rpid) {
1390 rpid = sofia_presence_translate_rpid(rpid, status);
1391 }
1392
1393 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "early");
1394 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", status);
1395 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State", status);
1396 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-State", "EARLY");
1397 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "astate", "early");
1398 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "early");
1399 } else {
1400 status = "CS_EXECUTE";
1401 if (rpid) {
1402 rpid = sofia_presence_translate_rpid(rpid, status);
1403 }
1404
1405 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "answered");
1406 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", status);
1407 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State", status);
1408 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-State", "ACTIVE");
1409 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "astate", "confirmed");
1410 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "confirmed");
1411 }
1412 }
1413
1414
1415
1416 if (zstr(call_id)_zstr(call_id) && (dh.hits && presence_source && (!strcasecmp(presence_source, "register") || switch_stristr("register", status)))) {
1417 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 1417, profile)
;
1418 goto done;
1419 }
1420
1421 if (zstr(call_id)_zstr(call_id)) {
1422
1423 sql = switch_mprintf("update sip_subscriptions set version=version+1 where hostname='%q' and profile_name='%q' and "
1424 "sip_subscriptions.event != 'line-seize' "
1425 "and sip_subscriptions.proto='%q' and (event='%q' or event='%q') and sub_to_user='%q' and "
1426 "(sub_to_host='%q' or sub_to_host='%q' or sub_to_host='%q' or "
1427 "presence_hosts like '%%%q%%') and "
1428 "(sip_subscriptions.profile_name = '%q' or presence_hosts like '%%%q%%')",
1429 mod_sofia_globals.hostname, profile->name,
1430 proto, event_type, alt_event_type, euser, host, profile->sipip,
1431 profile->extsipip ? profile->extsipip : "N/A", host, profile->name, host);
1432
1433
1434 if (mod_sofia_globals.debug_presence > 1) {
1435 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1435, ((void*)0)
, SWITCH_LOG_ERROR, "PRES SQL %s\n", sql);
1436 }
1437
1438 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1439
1440
1441
1442 sql = switch_mprintf("select distinct sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host,"
1443 "sip_subscriptions.sub_to_user,sip_subscriptions.sub_to_host,sip_subscriptions.event,"
1444 "sip_subscriptions.contact,sip_subscriptions.call_id,sip_subscriptions.full_from,"
1445 "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent,"
1446 "sip_subscriptions.accept,sip_subscriptions.profile_name"
1447 ",'%q','%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'%q','%q',"
1448 "sip_subscriptions.version, '%q',sip_subscriptions.orig_proto,sip_subscriptions.full_to,"
1449 "sip_subscriptions.network_ip, sip_subscriptions.network_port "
1450 "from sip_subscriptions "
1451 "left join sip_presence on "
1452 "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and "
1453 "sip_subscriptions.profile_name=sip_presence.profile_name and sip_subscriptions.hostname=sip_presence.hostname) "
1454
1455 "where sip_subscriptions.hostname='%q' and sip_subscriptions.profile_name='%q' and "
1456 "sip_subscriptions.event != 'line-seize' and "
1457 "sip_subscriptions.proto='%q' and "
1458 "(event='%q' or event='%q') and sub_to_user='%q' "
1459 "and (sub_to_host='%q' or sub_to_host='%q' or sub_to_host='%q' or presence_hosts like '%%%q%%') ",
1460
1461
1462 switch_str_nil(status)(status ? status : ""), switch_str_nil(rpid)(rpid ? rpid : ""), host,
1463 dh.status,dh.rpid,dh.presence_id, mod_sofia_globals.hostname, profile->name, proto,
1464 event_type, alt_event_type, euser, host, profile->sipip,
1465 profile->extsipip ? profile->extsipip : "N/A", host);
1466 } else {
1467
1468 sql = switch_mprintf("update sip_subscriptions set version=version+1 where sip_subscriptions.event != 'line-seize' and "
1469 "sip_subscriptions.call_id='%q'", call_id);
1470
1471
1472
1473 if (mod_sofia_globals.debug_presence > 1) {
1474 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1474, ((void*)0)
, SWITCH_LOG_ERROR, "PRES SQL %s\n", sql);
1475 }
1476
1477 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1478
1479
1480 sql = switch_mprintf("select distinct sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host,"
1481 "sip_subscriptions.sub_to_user,sip_subscriptions.sub_to_host,sip_subscriptions.event,"
1482 "sip_subscriptions.contact,sip_subscriptions.call_id,sip_subscriptions.full_from,"
1483 "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent,"
1484 "sip_subscriptions.accept,sip_subscriptions.profile_name"
1485 ",'%q','%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'%q','%q',"
1486 "sip_subscriptions.version, '%q',sip_subscriptions.orig_proto,sip_subscriptions.full_to,"
1487 "sip_subscriptions.network_ip, sip_subscriptions.network_port "
1488 "from sip_subscriptions "
1489 "left join sip_presence on "
1490 "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and "
1491 "sip_subscriptions.profile_name=sip_presence.profile_name and sip_subscriptions.hostname=sip_presence.hostname) "
1492
1493 "where sip_subscriptions.hostname='%q' and sip_subscriptions.profile_name='%q' and "
1494 "sip_subscriptions.event != 'line-seize' and "
1495 "sip_subscriptions.call_id='%q'",
1496
1497 switch_str_nil(status)(status ? status : ""), switch_str_nil(rpid)(rpid ? rpid : ""), host,
1498 dh.status,dh.rpid,dh.presence_id, mod_sofia_globals.hostname, profile->name, call_id);
1499
1500 }
1501
1502 helper.hup = hup;
1503 helper.calls_up = dh.hits;
1504 helper.profile = profile;
1505 helper.event = event;
1506 SWITCH_STANDARD_STREAM(helper.stream)memset(&helper.stream, 0, sizeof(helper.stream)); helper.
stream.data = malloc(1024); ((helper.stream.data) ? (void) (0
) : __assert_fail ("helper.stream.data", "sofia_presence.c", 1506
, __extension__ __PRETTY_FUNCTION__)); memset(helper.stream.data
, 0, 1024); helper.stream.end = helper.stream.data; helper.stream
.data_size = 1024; helper.stream.write_function = switch_console_stream_write
; helper.stream.raw_write_function = switch_console_stream_raw_write
; helper.stream.alloc_len = 1024; helper.stream.alloc_chunk =
1024
;
1507 switch_assert(helper.stream.data)((helper.stream.data) ? (void) (0) : __assert_fail ("helper.stream.data"
, "sofia_presence.c", 1507, __extension__ __PRETTY_FUNCTION__
))
;
1508
1509 if (mod_sofia_globals.debug_presence > 0) {
1510 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1510, ((void*)0)
, SWITCH_LOG_INFO, "%s START_PRESENCE_SQL (%s)\n",
1511 event->event_id == SWITCH_EVENT_PRESENCE_IN ? "IN" : "OUT", profile->name);
1512 }
1513
1514 if (mod_sofia_globals.debug_presence) {
1515 char *buf;
1516 switch_event_serialize(event, &buf, SWITCH_FALSE);
1517 switch_assert(buf)((buf) ? (void) (0) : __assert_fail ("buf", "sofia_presence.c"
, 1517, __extension__ __PRETTY_FUNCTION__))
;
1518 if (mod_sofia_globals.debug_presence > 1) {
1519 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1519, ((void*)0)
, SWITCH_LOG_ERROR, "DUMP PRESENCE SQL:\n%s\nEVENT DUMP:\n%s\n", sql, buf);
1520 } else {
1521 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1521, ((void*)0)
, SWITCH_LOG_ERROR, "EVENT DUMP:\n%s\n", buf);
1522 }
1523 free(buf);
1524 }
1525
1526 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_sub_callback, &helper);
1527 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1528
1529 if (mod_sofia_globals.debug_presence > 0) {
1530 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1530, ((void*)0)
, SWITCH_LOG_INFO, "%s END_PRESENCE_SQL (%s)\n",
1531 event->event_id == SWITCH_EVENT_PRESENCE_IN ? "IN" : "OUT", profile->name);
1532 }
1533
1534#if 0
1535 if (hup && dh.hits < 1) {
1536 /* so many phones get confused when whe hangup we have to reprobe to get them all to reset to absolute states so the lights stay correct */
1537 if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 1537, &s_event, SWITCH_EVENT_PRESENCE_PROBE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
1538 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
1539 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name);
1540 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
1541 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", euser, host);
1542 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", euser, host);
1543 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence");
1544 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
1545 sofia_event_fire(profile, &s_event);
1546 }
1547 }
1548#endif
1549
1550 if (!zstr((char *) helper.stream.data)_zstr((char *) helper.stream.data)) {
1551 char *this_sql = (char *) helper.stream.data;
1552 char *next = NULL((void*)0);
1553 char *last = NULL((void*)0);
1554
1555 do {
1556 if ((next = strchr(this_sql, ';'))) {
1557 *next++ = '\0';
1558 while (*next == '\n' || *next == ' ' || *next == '\r') {
1559 *next++ = '\0';
1560 }
1561 }
1562
1563 if (!zstr(this_sql)_zstr(this_sql) && (!last || strcmp(last, this_sql))) {
1564 sofia_glue_execute_sql(profile, &this_sql, SWITCH_FALSE);
1565 last = this_sql;
1566 }
1567 this_sql = next;
1568 } while (this_sql);
1569 }
1570 switch_safe_free(helper.stream.data)if (helper.stream.data) {free(helper.stream.data);helper.stream
.data=((void*)0);}
;
1571 helper.stream.data = NULL((void*)0);
1572
1573 sofia_glue_release_profile(profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 1573, profile)
;
1574 }
1575 }
1576 switch_console_free_matches(&matches);
1577 }
1578
1579 done:
1580
1581 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1582 switch_safe_free(user)if (user) {free(user);user=((void*)0);};
1583
1584 return s_event;
1585}
1586
1587static int EVENT_THREAD_RUNNING = 0;
1588static int EVENT_THREAD_STARTED = 0;
1589
1590static void do_flush(void)
1591{
1592 void *pop = NULL((void*)0);
1593
1594 while (mod_sofia_globals.presence_queue && switch_queue_trypop(mod_sofia_globals.presence_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
1595 switch_event_t *event = (switch_event_t *) pop;
1596 switch_event_destroy(&event);
1597 }
1598
1599}
1600
1601void *SWITCH_THREAD_FUNC sofia_presence_event_thread_run(switch_thread_t *thread, void *obj)
1602{
1603 void *pop;
1604 int done = 0;
1605
1606 switch_mutex_lock(mod_sofia_globals.mutex);
1607 if (!EVENT_THREAD_RUNNING) {
1
Assuming 'EVENT_THREAD_RUNNING' is 0
2
Taking true branch
1608 EVENT_THREAD_RUNNING++;
1609 mod_sofia_globals.threads++;
1610 } else {
1611 done = 1;
1612 }
1613 switch_mutex_unlock(mod_sofia_globals.mutex);
1614
1615 if (done) {
3
Taking false branch
1616 return NULL((void*)0);
1617 }
1618
1619 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1619, ((void*)0)
, SWITCH_LOG_CONSOLE, "Event Thread Started\n");
1620
1621 while (mod_sofia_globals.running == 1) {
4
Assuming the condition is true
5
Loop condition is true. Entering loop body
1622 int count = 0;
1623
1624 if (switch_queue_pop(mod_sofia_globals.presence_queue, &pop) == SWITCH_STATUS_SUCCESS) {
6
Assuming the condition is true
7
Taking true branch
1625 switch_event_t *event = (switch_event_t *) pop;
1626
1627 if (!pop) {
8
Assuming 'pop' is non-null
9
Taking false branch
1628 break;
1629 }
1630
1631 if (mod_sofia_globals.presence_flush) {
10
Assuming the condition is false
11
Taking false branch
1632 switch_mutex_lock(mod_sofia_globals.mutex);
1633 if (mod_sofia_globals.presence_flush) {
1634 do_flush();
1635 mod_sofia_globals.presence_flush = 0;
1636 }
1637 switch_mutex_unlock(mod_sofia_globals.mutex);
1638 }
1639
1640 switch(event->event_id) {
12
Control jumps to 'case SWITCH_EVENT_MESSAGE_WAITING:' at line 1641
1641 case SWITCH_EVENT_MESSAGE_WAITING:
1642 actual_sofia_presence_mwi_event_handler(event);
13
Calling 'actual_sofia_presence_mwi_event_handler'
1643 break;
1644 case SWITCH_EVENT_CONFERENCE_DATA:
1645 conference_data_event_handler(event);
1646 break;
1647 default:
1648 do {
1649 switch_event_t *ievent = event;
1650 event = actual_sofia_presence_event_handler(ievent);
1651 switch_event_destroy(&ievent);
1652 } while (event);
1653 break;
1654 }
1655
1656 switch_event_destroy(&event);
1657 count++;
1658 }
1659 }
1660
1661 do_flush();
1662
1663 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1663, ((void*)0)
, SWITCH_LOG_CONSOLE, "Event Thread Ended\n");
1664
1665 switch_mutex_lock(mod_sofia_globals.mutex);
1666 mod_sofia_globals.threads--;
1667 EVENT_THREAD_RUNNING = EVENT_THREAD_STARTED = 0;
1668 switch_mutex_unlock(mod_sofia_globals.mutex);
1669
1670 return NULL((void*)0);
1671}
1672
1673void sofia_presence_event_thread_start(void)
1674{
1675 //switch_thread_t *thread;
1676 switch_threadattr_t *thd_attr = NULL((void*)0);
1677 int done = 0;
1678
1679 switch_mutex_lock(mod_sofia_globals.mutex);
1680 if (!EVENT_THREAD_STARTED) {
1681 EVENT_THREAD_STARTED++;
1682 } else {
1683 done = 1;
1684 }
1685 switch_mutex_unlock(mod_sofia_globals.mutex);
1686
1687 if (done) {
1688 return;
1689 }
1690
1691 switch_threadattr_create(&thd_attr, mod_sofia_globals.pool);
1692 //switch_threadattr_detach_set(thd_attr, 1);
1693 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE240 * 1024);
1694 switch_threadattr_priority_set(thd_attr, SWITCH_PRI_IMPORTANT);
1695 switch_thread_create(&mod_sofia_globals.presence_thread, thd_attr, sofia_presence_event_thread_run, NULL((void*)0), mod_sofia_globals.pool);
1696}
1697
1698
1699void sofia_presence_event_handler(switch_event_t *event)
1700{
1701 switch_event_t *cloned_event;
1702
1703 if (!EVENT_THREAD_STARTED) {
1704 sofia_presence_event_thread_start();
1705 switch_yield(500000)switch_sleep(500000);;
1706 }
1707
1708 switch_event_dup(&cloned_event, event);
1709 switch_assert(cloned_event)((cloned_event) ? (void) (0) : __assert_fail ("cloned_event",
"sofia_presence.c", 1709, __extension__ __PRETTY_FUNCTION__)
)
;
1710
1711 if (switch_queue_trypush(mod_sofia_globals.presence_queue, cloned_event) != SWITCH_STATUS_SUCCESS) {
1712 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1712, ((void*)0)
, SWITCH_LOG_ERROR, "Presence queue overloaded.... Flushing queue\n");
1713 switch_mutex_lock(mod_sofia_globals.mutex);
1714 mod_sofia_globals.presence_flush = 1;
1715 switch_mutex_unlock(mod_sofia_globals.mutex);
1716 switch_event_destroy(&cloned_event);
1717 }
1718
1719
1720}
1721
1722
1723static int sofia_presence_sub_reg_callback(void *pArg, int argc, char **argv, char **columnNames)
1724{
1725 sofia_profile_t *profile = (sofia_profile_t *) pArg;
1726 char *user = argv[3];
1727 char *host = argv[2];
1728 switch_event_t *event;
1729 char *event_name = argv[5];
1730 char *expires = argv[10];
1731
1732
1733
1734 if (!strcasecmp(event_name, "message-summary")) {
1735
1736 if (switch_event_create(&event, SWITCH_EVENT_MESSAGE_QUERY)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 1736, &event, SWITCH_EVENT_MESSAGE_QUERY
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
1737 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Message-Account", "sip:%s@%s", user, host);
1738 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name);
1739 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "VM-sub-call-id", argv[7]);
1740
1741 if (mod_sofia_globals.debug_presence > 0) {
1742 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1742, ((void*)0)
, SWITCH_LOG_ERROR, "Create MESSAGE QUERY EVENT...\n");
1743 DUMP_EVENT(event){char *event_str;switch_event_serialize(event, &event_str
, SWITCH_FALSE);switch_log_printf(SWITCH_CHANNEL_ID_LOG, "sofia_presence.c"
, (const char *)__func__, 1743, ((void*)0), SWITCH_LOG_CRIT, "DUMP\n%s\n"
, event_str);free(event_str);}
;
1744 }
1745
1746
1747 sofia_event_fire(profile, &event);
1748 }
1749 return 0;
1750 }
1751
1752 if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_PROBE)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 1752, &event, SWITCH_EVENT_PRESENCE_PROBE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
1753 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
1754 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
1755 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
1756 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", user, host);
1757 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
1758 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_subtype", "probe");
1759 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event_name);
1760 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "expires", expires);
1761 sofia_event_fire(profile, &event);
1762 }
1763
1764 return 0;
1765}
1766
1767static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char **columnNames)
1768{
1769 struct resub_helper *h = (struct resub_helper *) pArg;
1770 sofia_profile_t *profile = h->profile;
1771 char *user = argv[0];
1772 char *host = argv[1];
1773 char *status = argv[2];
1774 char *rpid = argv[3];
1775 char *proto = argv[4];
1776 char *call_id = NULL((void*)0);
1777 char *presence_id = NULL((void*)0);
1778 char *to_user = NULL((void*)0);
1779 char *uuid = NULL((void*)0);
1780 char *state = NULL((void*)0);
1781 char *direction = NULL((void*)0);
1782 switch_event_t *event;
1783 char to_buf[128] = "";
1784 switch_event_header_t *hp;
1785 char *free_me = NULL((void*)0);
1786 int do_event = 1, i;
1787
1788
1789 if (mod_sofia_globals.debug_presence > 1) {
1790 for (i = 0; i < argc; i++) {
1791 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1791, ((void*)0)
,SWITCH_LOG_WARNING, "sofia_presence_resub_callback: %d [%s]=[%s]\n", i, columnNames[i], argv[i]);
1792 }
1793 }
1794
1795 if (argc > 5) {
1796 uuid = argv[5];
1797 state = switch_str_nil(argv[6])(argv[6] ? argv[6] : "");
1798 direction = switch_str_nil(argv[7])(argv[7] ? argv[7] : "");
1799 if (argc > 8) {
1800 switch_set_string(to_buf, argv[8])switch_copy_string(to_buf, argv[8], sizeof(to_buf));
1801 switch_url_decode(to_buf);
1802 to_user = to_buf;
1803 }
1804 if (argc > 10 && !zstr(argv[10])_zstr(argv[10]) && !zstr(argv[11])_zstr(argv[11])) {
1805 status = argv[10];
1806 rpid = argv[11];
1807 }
1808
1809 if (argc > 12 && !zstr(argv[12])_zstr(argv[12]) && strchr(argv[12], '@')) {
1810 char *p;
1811
1812 presence_id = argv[12];
1813 free_me = strdup(presence_id);
1814 switch_assert(free_me)((free_me) ? (void) (0) : __assert_fail ("free_me", "sofia_presence.c"
, 1814, __extension__ __PRETTY_FUNCTION__))
;
1815 if ((p = strchr(free_me, '@'))) *p = '\0';
1816 user = free_me;
1817 }
1818
1819 if (argc > 16) {
1820 call_id = argv[16];
1821 }
1822
1823 }
1824
1825 if (!zstr(uuid)_zstr(uuid) && !switch_ivr_uuid_exists(uuid)) {
1826 if (mod_sofia_globals.debug_presence > 0) {
1827 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1827, ((void*)0)
, SWITCH_LOG_NOTICE, "%s SKIPPING NOT FOUND UUID %s\n", profile->name, uuid);
1828 }
1829 do_event = 0;
1830 }
1831
1832 if (zstr(proto)_zstr(proto)) {
1833 proto = NULL((void*)0);
1834 }
1835
1836 if (mod_sofia_globals.debug_presence > 0) {
1837 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1837, ((void*)0)
, SWITCH_LOG_NOTICE, "%s PRESENCE_PROBE %s@%s\n", profile->name, user, host);
1838 }
1839
1840 if (do_event && switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 1840, &event, SWITCH_EVENT_PRESENCE_IN
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
1841 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", proto ? proto : SOFIA_CHAT_PROTO"sip");
1842 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
1843 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
1844
1845 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", user, host);
1846
1847 if (h->noreg) {
1848 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Force-Direction", "inbound");
1849 }
1850
1851 if (!zstr(call_id)_zstr(call_id)) {
1852 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-id", call_id);
1853 }
1854
1855 //switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "resub", "true");
1856 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", status);
1857 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
1858 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
1859 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
1860 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", 0);
1861
1862 if (!zstr(to_user)_zstr(to_user)) {
1863 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to-user", to_user);
1864 }
1865
1866 if (zstr(state)_zstr(state)) {
1867 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
1868 //switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "resubscribe");
1869 } else {
1870 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
1871 if (uuid) {
1872 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", uuid);
1873 }
1874 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", state);
1875 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "astate", state);
1876 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-direction", direction);
1877 }
1878
1879 if (h->event) {
1880 for (hp = h->event->headers; hp; hp = hp->next) {
1881 if (!strncasecmp(hp->name, "fwd-", 4)) {
1882 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, hp->name + 4, hp->value);
1883 }
1884 }
1885 }
1886
1887 sofia_event_fire(profile, &event);
1888 }
1889
1890 switch_safe_free(free_me)if (free_me) {free(free_me);free_me=((void*)0);};
1891
1892
1893 h->rowcount++;
1894
1895
1896 return 0;
1897}
1898
1899char *get_display_name_from_contact(const char *in, char* dst)
1900{
1901 // name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
1902 // display-name = *(token LWS)/ quoted-string
1903 // return whatever comes before the left angle bracket, stripped of whitespace and quotes
1904 char *p;
1905 char *buf;
1906
1907 strcpy(dst, "");
1908 if (strchr(in, '<') && strchr(in, '>')) {
1909 buf = strdup(in);
1910 switch_assert(buf)((buf) ? (void) (0) : __assert_fail ("buf", "sofia_presence.c"
, 1910, __extension__ __PRETTY_FUNCTION__))
;
1911 p = strchr(buf, '<');
1912 *p = '\0';
1913 if (!zstr(buf)_zstr(buf)) {
1914 p = switch_strip_whitespace(buf);
1915 if (p) {
1916 if (*p == '"') {
1917 if (end_of(p+1)*(*p+1 == '\0' ? p+1 : p+1 + strlen(p+1) - 1) == '"') {
1918 char *q = strdup(p + 1);
1919 switch_assert(q)((q) ? (void) (0) : __assert_fail ("q", "sofia_presence.c", 1919
, __extension__ __PRETTY_FUNCTION__))
;
1920 end_of(q)*(*q == '\0' ? q : q + strlen(q) - 1) = '\0';
1921 strcpy(dst, q);
1922 switch_safe_free(q)if (q) {free(q);q=((void*)0);};
1923 }
1924 } else {
1925 strcpy(dst, p);
1926 }
1927 switch_safe_free(p)if (p) {free(p);p=((void*)0);};
1928 }
1929 }
1930 switch_safe_free(buf)if (buf) {free(buf);buf=((void*)0);};
1931 }
1932 return dst;
1933}
1934
1935static int sofia_dialog_probe_callback(void *pArg, int argc, char **argv, char **columnNames)
1936{
1937 struct rfc4235_helper *h = (struct rfc4235_helper *) pArg;
1938
1939 char *proto = argv[0];
1940 char *user = argv[1];
1941 char *host = argv[2];
1942 char *uuid = argv[3];
1943 char *call_id = argv[4];
1944 char *state = argv[5];
1945 char *direction = argv[6];
1946 char *to_user = argv[7];
1947 char *to_host = argv[8];
1948 char *from_user = argv[9];
1949 // char *from_host = argv[10];
1950 char *contact = switch_str_nil(argv[11])(argv[11] ? argv[11] : "");
1951 char *contact_user = switch_str_nil(argv[12])(argv[12] ? argv[12] : "");
1952 char *contact_host = switch_str_nil(argv[13])(argv[13] ? argv[13] : "");
1953 char *to_tag = switch_str_nil(argv[14])(argv[14] ? argv[14] : "");
1954 char *from_tag = switch_str_nil(argv[15])(argv[15] ? argv[15] : "");
1955 char *orig_proto = switch_str_nil(argv[16])(argv[16] ? argv[16] : "");
1956
1957 const char *event_status = "";
1958 char *data = NULL((void*)0), *tmp;
1959 char key[256] = "";
1960 char *local_user;
1961 char *local_host;
1962 char *remote_user;
1963 char *remote_host;
1964 char *remote_uri;
1965 char *local_user_param = NULL((void*)0);
1966 char remote_display_buf[512];
1967 char *buf_to_free = NULL((void*)0);
1968 int bInternal = 0;
1969 int i;
1970 int skip_proto = 0;
1971
1972 if (mod_sofia_globals.debug_presence > 1) {
1973 for (i = 0; i < argc; i++) {
1974 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1974, ((void*)0)
,SWITCH_LOG_WARNING, "sofia_dialog_probe_callback: %d [%s]=[%s]\n", i, columnNames[i], argv[i]);
1975 }
1976 }
1977
1978 if (zstr(to_user)_zstr(to_user) || zstr(contact_user)_zstr(contact_user)) {
1979 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1979, ((void*)0)
, SWITCH_LOG_WARNING, "sofia_dialog_probe_callback: not enough info to generate a dialog entry\n");
1980 return 0;
1981 }
1982
1983 // Usually we report the dialogs FROM the probed user. The exception is when the monitored endpoint is internal,
1984 // and its presence_id is set in the dialplan. Reverse the direction if this is not a registered entity.
1985 if (!strcmp(direction, "inbound") && strcmp(user, from_user) ) {
1986 // If inbound and the entity is not the caller (i.e. internal to FS), then the direction is reversed
1987 // because it is not going through the B2BUA
1988 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 1988, ((void*)0)
, SWITCH_LOG_DEBUG, "sofia_dialog_probe_callback: endpt is internal\n");
1989 direction = !strcasecmp(direction, "outbound") ? "inbound" : "outbound";
1990 bInternal = 1;
1991 }
1992
1993 if (!strcasecmp(direction, "outbound")) {
1994 direction = "recipient";
1995 }
1996 else {
1997 direction = "initiator";
1998 }
1999
2000 if (!zstr(orig_proto)_zstr(orig_proto) && !strcmp(orig_proto, SOFIA_CHAT_PROTO"sip")) {
2001 skip_proto = 1;
2002 }
2003
2004 local_host = to_host;
2005 if (proto && !strcasecmp(proto, "queue")) {
2006 local_user = to_user;
2007 local_user_param = switch_mprintf(";proto=%s", proto);
2008 event_status = "hold";
2009 if (skip_proto) {
2010 buf_to_free = switch_mprintf("sip:%s", to_user);
2011 } else {
2012 buf_to_free = switch_mprintf("sip:queue+%s", to_user);
2013 }
2014 remote_uri = buf_to_free;
2015 strcpy(remote_display_buf, "queue");
2016 remote_user = to_user;
2017 remote_host = local_host;
2018 }
2019 else if (proto && !strcasecmp(proto, "park")) {
2020 local_user = to_user;
2021 local_user_param = switch_mprintf(";proto=%s", proto);
2022 event_status = "hold";
2023 if (skip_proto) {
2024 buf_to_free = switch_mprintf("sip:%s", to_user);
2025 } else {
2026 buf_to_free = switch_mprintf("sip:park+%s", to_user);
2027 }
2028 remote_uri = buf_to_free;
2029 strcpy(remote_display_buf, "park");
2030 remote_user = to_user;
2031 remote_host = local_host;
2032 }
2033 else if (proto && !strcasecmp(proto, "pickup")) {
2034 local_user = to_user;
2035 local_user_param = switch_mprintf(";proto=%s", proto);
2036 event_status = "hold";
2037 if (skip_proto) {
2038 buf_to_free = switch_mprintf("sip:%s", to_user);
2039 } else {
2040 buf_to_free = switch_mprintf("sip:pickup+%s", to_user);
2041 }
2042 remote_uri = buf_to_free;
2043 strcpy(remote_display_buf, "pickup");
2044 remote_user = to_user;
2045 remote_host = local_host;
2046 }
2047 else if (proto && !strcasecmp(proto, "conf")) {
2048 local_user = to_user;
2049 local_user_param = switch_mprintf(";proto=%s", proto);
2050 if (skip_proto) {
2051 buf_to_free = switch_mprintf("sip:%s@%s", to_user, host);
2052 } else {
2053 buf_to_free = switch_mprintf("sip:conf+%s@%s", to_user, host);
2054 }
2055 remote_uri = buf_to_free;
2056 strcpy(remote_display_buf, "conference");
2057 remote_user = to_user;
2058 remote_host = local_host;
2059 }
2060 else if (bInternal) {
2061 local_user = to_user;
2062 get_display_name_from_contact(contact, remote_display_buf);
2063 buf_to_free = sofia_glue_strip_uri(contact);
2064 remote_uri = buf_to_free;
2065 remote_user = contact_user;
2066 remote_host = contact_host;
2067 } else {
2068 local_user = from_user;
2069 buf_to_free = switch_mprintf("**%s@%s", from_user, local_host);
2070 remote_uri = buf_to_free;
2071 strcpy(remote_display_buf, to_user);
2072 remote_user = to_user;
2073 remote_host = local_host;
2074 }
2075
2076 switch_snprintf(key, sizeof(key), "%s%s", user, host);
2077 data = switch_core_hash_find(h->hash, key);
2078 if (!data) {
2079 data = "";
2080 }
2081 tmp = switch_core_sprintf(h->pool, "%s"
2082 "<dialog id=\"%s\" call-id=\"%s\" local-tag=\"%s\" remote-tag=\"%s\" direction=\"%s\">\n"
2083 " <state>%s</state>\n"
2084 " <local>\n"
2085 " <identity display=\"%s\">sip:%s@%s%s</identity>\n"
2086 " <target uri=\"sip:%s@%s\">\n"
2087 " <param pname=\"+sip.rendering\" pvalue=\"%s\"/>\n"
2088 " </target>\n"
2089 " </local>\n"
2090 " <remote>\n"
2091 " <identity display=\"%s\">sip:%s@%s</identity>\n"
2092 " <target uri=\"%s\"/>\n"
2093 " </remote>\n"
2094 "</dialog>\n",
2095 data,
2096 uuid, call_id, to_tag, from_tag, direction,
2097 state,
2098 local_user, local_user, local_host, switch_str_nil(local_user_param)(local_user_param ? local_user_param : ""),
2099 local_user, local_host,
2100 !strcasecmp(event_status, "hold") ? "no" : "yes",
2101 remote_display_buf, remote_user, remote_host,
2102 remote_uri
2103 );
2104 switch_core_hash_insert(h->hash, key, tmp)switch_core_hash_insert_destructor(h->hash, key, tmp, ((void
*)0))
;
2105 switch_safe_free(local_user_param)if (local_user_param) {free(local_user_param);local_user_param
=((void*)0);}
;
2106 switch_safe_free(buf_to_free)if (buf_to_free) {free(buf_to_free);buf_to_free=((void*)0);};
2107
2108 h->rowcount++;
2109
2110 return 0;
2111}
2112
2113#define SOFIA_PRESENCE_COLLISION_DELTA50 50
2114#define SOFIA_PRESENCE_ROLLOVER_YEAR(86400 * 365 * 50) (86400 * 365 * SOFIA_PRESENCE_COLLISION_DELTA50)
2115static uint32_t check_presence_epoch(void)
2116{
2117 time_t now = switch_epoch_time_now(NULL((void*)0));
2118 uint32_t callsequence = (uint32_t)((now - mod_sofia_globals.presence_epoch) * SOFIA_PRESENCE_COLLISION_DELTA50);
2119
2120 if (!mod_sofia_globals.presence_year || callsequence >= SOFIA_PRESENCE_ROLLOVER_YEAR(86400 * 365 * 50)) {
2121 struct tm tm;
2122 switch_mutex_lock(mod_sofia_globals.mutex);
2123 tm = *(localtime(&now));
2124
2125 if (tm.tm_year != mod_sofia_globals.presence_year) {
2126 mod_sofia_globals.presence_epoch = (uint32_t)now - (tm.tm_yday * 86400) - (tm.tm_hour * 60 * 60) - (tm.tm_min * 60) - tm.tm_sec;
2127 mod_sofia_globals.presence_year = tm.tm_year;
2128 callsequence = (uint32_t)(((uint32_t)now - mod_sofia_globals.presence_epoch) * SOFIA_PRESENCE_COLLISION_DELTA50);
2129 }
2130
2131 switch_mutex_unlock(mod_sofia_globals.mutex);
2132 }
2133
2134 return callsequence;
2135}
2136
2137uint32_t sofia_presence_get_cseq(sofia_profile_t *profile)
2138{
2139 uint32_t callsequence;
2140 int diff = 0;
2141
2142 switch_mutex_lock(profile->ireg_mutex);
2143
2144 callsequence = check_presence_epoch();
2145
2146 if (profile->last_cseq) {
2147 diff = callsequence - profile->last_cseq;
2148 if (diff <= 0 && diff > -100000) {
2149 callsequence = ++profile->last_cseq;
2150 }
2151 }
2152
2153 profile->last_cseq = callsequence;
2154
2155 switch_mutex_unlock(profile->ireg_mutex);
2156
2157 return callsequence;
2158
2159}
2160
2161
2162#define send_presence_notify(_a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l)_send_presence_notify(_a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,"sofia_presence.c"
, (const char *)__func__, 2162)
\
2163_send_presence_notify(_a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,__FILE__"sofia_presence.c", __SWITCH_FUNC__(const char *)__func__, __LINE__2163)
2164
2165static void _send_presence_notify(sofia_profile_t *profile,
2166 const char *full_to,
2167 const char *full_from,
2168 const char *o_contact,
2169 const char *expires,
2170 const char *call_id,
2171 const char *event,
2172 const char *remote_ip,
2173 const char *remote_port,
2174 const char *ct,
2175 const char *pl,
2176 const char *call_info,
2177 const char *file, const char *func, int line
2178 )
2179{
2180 char sstr[128] = "";
2181 nua_handle_t *nh;
2182 int exptime = 0;
2183 char expires_str[10] = "";
2184 sip_cseq_t *cseq = NULL((void*)0);
2185 uint32_t callsequence;
2186 uint32_t now = (uint32_t) switch_epoch_time_now(NULL((void*)0));
2187
2188 sofia_destination_t *dst = NULL((void*)0);
2189 char *contact_str, *contact, *user_via = NULL((void*)0), *send_contact = NULL((void*)0);
2190 char *route_uri = NULL((void*)0), *o_contact_dup = NULL((void*)0), *tmp, *to_uri, *dcs = NULL((void*)0);
2191 const char *tp;
2192 char *cparams = NULL((void*)0);
2193 char *path = NULL((void*)0);
2194
2195 if (zstr(full_to)_zstr(full_to) || zstr(full_from)_zstr(full_from) || zstr(o_contact)_zstr(o_contact)) {
2196 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 2196, ((void*)0)
, SWITCH_LOG_WARNING, "MISSING DATA TO SEND NOTIFY.\n");
2197 return;
2198 }
2199
2200 if ((cparams = strstr(o_contact, ";_;"))) {
2201 cparams += 3;
2202 }
2203
2204 if (!switch_stristr("fs_nat=yes", o_contact)) {
2205 path = sofia_glue_get_path_from_contact((char *) o_contact);
2206 }
2207
2208 dst = sofia_glue_get_destination((char *) o_contact);
2209 switch_assert(dst)((dst) ? (void) (0) : __assert_fail ("dst", "sofia_presence.c"
, 2209, __extension__ __PRETTY_FUNCTION__))
;
2210
2211 if (!zstr(dst->contact)_zstr(dst->contact)) {
2212 contact = sofia_glue_get_url_from_contact(dst->contact, 1);
2213 } else {
2214 contact = strdup(o_contact);
2215 }
2216
2217 if (dst->route_uri) {
2218 route_uri = sofia_glue_strip_uri(dst->route_uri);
2219 tmp = (char *)route_uri;
2220 } else {
2221 tmp = (char *)o_contact;
2222 }
2223
2224 o_contact_dup = sofia_glue_get_url_from_contact(tmp, 1);
2225
2226 if ((tp = switch_stristr("transport=", o_contact_dup))) {
2227 tp += 10;
2228 }
2229
2230 if (zstr(tp)_zstr(tp)) {
2231 tp = "udp";
2232 }
2233
2234 if (!zstr(remote_ip)_zstr(remote_ip) && sofia_glue_check_nat(profile, remote_ip)) {
2235 sofia_transport_t transport = sofia_glue_str2transport(tp);
2236
2237 switch (transport) {
2238 case SOFIA_TRANSPORT_TCP:
2239 contact_str = profile->tcp_public_contact;
2240 break;
2241 case SOFIA_TRANSPORT_TCP_TLS:
2242 contact_str = sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0) ?
2243 profile->tls_public_contact : profile->tcp_public_contact;
2244 break;
2245 default:
2246 contact_str = profile->public_url;
2247 break;
2248 }
2249 user_via = sofia_glue_create_external_via(NULL((void*)0), profile, transport);
2250 } else {
2251 sofia_transport_t transport = sofia_glue_str2transport(tp);
2252 switch (transport) {
2253 case SOFIA_TRANSPORT_TCP:
2254 contact_str = profile->tcp_contact;
2255 break;
2256 case SOFIA_TRANSPORT_TCP_TLS:
2257 contact_str = sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0) ?
2258 profile->tls_contact : profile->tcp_contact;
2259 break;
2260 default:
2261 contact_str = profile->url;
2262 break;
2263 }
2264 }
2265
2266
2267 if ((to_uri = sofia_glue_get_url_from_contact((char *)full_to, 1))) {
2268 char *p;
2269
2270 if ((p = strstr(to_uri, "sip:"))) {
2271 char *q;
2272
2273 p += 4;
2274 if ((q = strchr(p, '@'))) {
2275 *q++ = '\0';
2276
2277 if ((dcs = switch_string_replace(contact_str, "mod_sofia", p))) {
2278 contact_str = dcs;
2279 }
2280
2281 }
2282 }
2283
2284 free(to_uri);
2285 }
2286
2287 if (expires) {
2288 long ltmp = atol(expires);
2289
2290 if (ltmp > 0) {
2291 exptime = (ltmp - now);
2292 } else {
2293 exptime = 0;
2294 }
2295 }
2296
2297 if (exptime <= 0) {
2298 switch_snprintf(sstr, sizeof(sstr), "terminated;reason=noresource");
2299 } else {
2300 switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", (unsigned) exptime);
2301 }
2302
2303 if (mod_sofia_globals.debug_presence > 1 || mod_sofia_globals.debug_sla > 1) {
2304 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 2304, ((void*)0)
, SWITCH_LOG_ERROR, "SEND PRES NOTIFY:\n"
2305 "file[%s]\nfunc[%s]\nline[%d]\n"
2306 "profile[%s]\nvia[%s]\nip[%s]\nport[%s]\nroute[%s]\ncontact[%s]\nto[%s]\nfrom[%s]\nurl[%s]\ncall_id[%s]\nexpires_str[%s]\n"
2307 "event[%s]\nct[%s]\npl[%s]\ncall_info[%s]\nexptime[%ld]\n",
2308 file, func, line,
2309 profile->name,
2310 switch_str_nil(user_via)(user_via ? user_via : ""),
2311 remote_ip,
2312 remote_port,
2313 route_uri,
2314 o_contact,
2315 full_to,
2316 full_from,
2317 contact,
2318 call_id,
2319 expires_str,
2320 event,
2321 switch_str_nil(ct)(ct ? ct : ""),
2322 switch_str_nil(pl)(pl ? pl : ""),
2323 switch_str_nil(call_info)(call_info ? call_info : ""),
2324 (long)exptime
2325 );
2326 }
2327
2328
2329 callsequence = sofia_presence_get_cseq(profile);
2330
2331 if (cparams) {
2332 send_contact = switch_mprintf("%s;%s", contact_str, cparams);
2333 contact_str = send_contact;
2334 }
2335
2336 nh = nua_handle(profile->nua, NULL((void*)0), NUTAG_URL(contact)nutag_url, urltag_url_v(contact), SIPTAG_CONTACT_STR(contact_str)siptag_contact_str, tag_str_v(contact_str), TAG_END()(tag_type_t)0, (tag_value_t)0);
2337 cseq = sip_cseq_create(nua_handle_get_home(nh), callsequence, SIP_METHOD_NOTIFYsip_method_notify, "NOTIFY");
2338 nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
2339
2340
2341 nua_notify(nh,
2342 NUTAG_NEWSUB(1)nutag_newsub, tag_bool_v(1),
2343 TAG_IF(route_uri, NUTAG_PROXY(route_uri))!(route_uri) ? tag_skip : ntatag_default_proxy, urltag_url_v(
(route_uri))
,
2344 TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route))!(dst->route) ? tag_skip : siptag_route_str, tag_str_v(dst
->route)
,
2345 TAG_IF(user_via, SIPTAG_VIA_STR(user_via))!(user_via) ? tag_skip : siptag_via_str, tag_str_v(user_via),
2346 TAG_IF(path, SIPTAG_RECORD_ROUTE_STR(path))!(path) ? tag_skip : siptag_record_route_str, tag_str_v(path),
2347
2348 SIPTAG_FROM_STR(full_to)siptag_from_str, tag_str_v(full_to),
2349 SIPTAG_TO_STR(full_from)siptag_to_str, tag_str_v(full_from),
2350
2351 SIPTAG_CALL_ID_STR(call_id)siptag_call_id_str, tag_str_v(call_id),
2352 TAG_IF(*expires_str, SIPTAG_EXPIRES_STR(expires_str))!(*expires_str) ? tag_skip : siptag_expires_str, tag_str_v(expires_str
)
,
2353 SIPTAG_SUBSCRIPTION_STATE_STR(sstr)siptag_subscription_state_str, tag_str_v(sstr),
2354 SIPTAG_EVENT_STR(event)siptag_event_str, tag_str_v(event),
2355 TAG_IF(!zstr(ct), SIPTAG_CONTENT_TYPE_STR(ct))!(!_zstr(ct)) ? tag_skip : siptag_content_type_str, tag_str_v
(ct)
,
2356 TAG_IF(!zstr(pl), SIPTAG_PAYLOAD_STR(pl))!(!_zstr(pl)) ? tag_skip : siptag_payload_str, tag_str_v(pl),
2357 TAG_IF(!zstr(call_info), SIPTAG_CALL_INFO_STR(call_info))!(!_zstr(call_info)) ? tag_skip : siptag_call_info_str, tag_str_v
(call_info)
,
2358 TAG_IF(!exptime, SIPTAG_EXPIRES_STR("0"))!(!exptime) ? tag_skip : siptag_expires_str, tag_str_v("0"),
2359 SIPTAG_CSEQ(cseq)siptag_cseq, siptag_cseq_v(cseq),
2360 TAG_END()(tag_type_t)0, (tag_value_t)0);
2361
2362
2363 switch_safe_free(route_uri)if (route_uri) {free(route_uri);route_uri=((void*)0);};
2364 switch_safe_free(dcs)if (dcs) {free(dcs);dcs=((void*)0);};
2365 switch_safe_free(contact)if (contact) {free(contact);contact=((void*)0);};
2366
2367 sofia_glue_free_destination(dst);
2368 switch_safe_free(user_via)if (user_via) {free(user_via);user_via=((void*)0);};
2369 switch_safe_free(o_contact_dup)if (o_contact_dup) {free(o_contact_dup);o_contact_dup=((void*
)0);}
;
2370 switch_safe_free(send_contact)if (send_contact) {free(send_contact);send_contact=((void*)0)
;}
;
2371 switch_safe_free(path)if (path) {free(path);path=((void*)0);};
2372}
2373
2374
2375static int sofia_dialog_probe_notify_callback(void *pArg, int argc, char **argv, char **columnNames)
2376{
2377 struct rfc4235_helper *sh = (struct rfc4235_helper *) pArg;
2378 char key[256] = "";
2379 char *data = NULL((void*)0);
2380 char *call_id = argv[0];
2381 char *expires = argv[1];
2382 char *user = argv[2];
2383 char *host = argv[3];
2384 char *event = argv[4];
2385 char *version = argv[5];
2386 char *notify_state = argv[6];
2387 char *full_to = argv[7];
2388 char *full_from = argv[8];
2389 char *contact = argv[9];
2390 char *remote_ip = argv[10];
2391 char *remote_port = argv[11];
2392
2393 switch_stream_handle_t stream = { 0 };
2394 char *to;
2395 const char *pl = NULL((void*)0);
2396 const char *ct = "application/dialog-info+xml";
2397
2398 if (mod_sofia_globals.debug_presence > 0) {
2399 int i;
2400 for(i = 0; i < argc; i++) {
2401 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 2401, ((void*)0)
, SWITCH_LOG_CRIT, "arg %d[%s] = [%s]\n", i, columnNames[i], argv[i]);
2402 }
2403 }
2404
2405
2406 if (mod_sofia_globals.debug_presence > 0) {
2407 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 2407, ((void*)0)
, SWITCH_LOG_NOTICE,
2408 "SEND DIALOG\nTo: \t%s@%s\nFrom: \t%s@%s\nCall-ID: \t%s\n",
2409 user, host, user, host, call_id);
2410 }
2411
2412 to = switch_mprintf("sip:%s@%s", user, host);
2413
2414 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "sofia_presence.c", 2414, __extension__ __PRETTY_FUNCTION__
)); memset(stream.data, 0, 1024); stream.end = stream.data; stream
.data_size = 1024; stream.write_function = switch_console_stream_write
; stream.raw_write_function = switch_console_stream_raw_write
; stream.alloc_len = 1024; stream.alloc_chunk = 1024
;
2415
2416 if (zstr(version)_zstr(version)) {
2417 version = "0";
2418 }
2419
2420 stream.write_function(&stream,
2421 "<?xml version=\"1.0\"?>\n"
2422 "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" "
2423 "version=\"%s\" state=\"%s\" entity=\"%s\">\n",
2424 version,
2425 notify_state, to);
2426
2427 switch_snprintf(key, sizeof(key), "%s%s", user, host);
2428
2429 data = switch_core_hash_find(sh->hash, key);
2430
2431 if (data) {
2432 stream.write_function(&stream, "%s\n", data);
2433 }
2434
2435 stream.write_function(&stream, "</dialog-info>\n");
2436 pl = stream.data;
2437 ct = "application/dialog-info+xml";
2438
2439 if (mod_sofia_globals.debug_presence > 0 && pl) {
2440 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 2440, ((void*)0)
, SWITCH_LOG_DEBUG, "send payload:\n%s\n", pl);
2441 }
2442
2443
2444 send_presence_notify(sh->profile,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2445 full_to,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2446 full_from,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2447 contact,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2448 expires,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2449 call_id,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2450 event,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2451 remote_ip,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2452 remote_port,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2453 ct,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2454 pl,_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2455 NULL_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
2456 )_send_presence_notify(sh->profile,full_to,full_from,contact
,expires,call_id,event,remote_ip,remote_port,ct,pl,((void*)0)
,"sofia_presence.c", (const char *)__func__, 2456)
;
2457
2458
2459 switch_safe_free(to)if (to) {free(to);to=((void*)0);};
2460 switch_safe_free(stream.data)if (stream.data) {free(stream.data);stream.data=((void*)0);};
2461
2462 return 0;
2463}
2464
2465static char *translate_rpid(char *in)
2466{
2467 char *r = in;
2468
2469 if (in && (strstr(in, "null") || strstr(in, "NULL"))) {
2470 in = NULL((void*)0);
2471 }
2472
2473 if (zstr(in)_zstr(in)) {
2474 return NULL((void*)0);
2475 }
2476
2477 if (!strcasecmp(in, "unknown")) {
2478 r = NULL((void*)0);
2479 goto end;
2480 }
2481
2482 if (!strcasecmp(in, "busy")) {
2483 r = in;
2484 goto end;
2485 }
2486
2487 if (!strcasecmp(in, "unavailable")) {
2488 r = "away";
2489 goto end;
2490 }
2491
2492 if (!strcasecmp(in, "idle")) {
2493 r = "busy";
2494 }
2495
2496 end:
2497 return r;
2498}
2499
2500
2501static char *gen_pidf(char *user_agent, char *id, char *url, char *open, char *rpid, char *prpid, char *status, const char **ct)
2502{
2503 char *ret = NULL((void*)0);
2504
2505 if (switch_stristr("polycom", user_agent)) {
2506 *ct = "application/xpidf+xml";
2507
2508 /* If unknown/none prpid is provided, just show the user as online. */
2509 if (!prpid || !strcasecmp(prpid, "unknown")) {
2510 prpid = "online";
2511 }
2512
2513 /* of course!, lets make a big deal over dashes. Now the stupidity is complete. */
2514 if (!strcmp(prpid, "on-the-phone")) {
2515 prpid = "onthephone";
2516 }
2517
2518 if (zstr(open)_zstr(open)) {
2519 open = "open";
2520 }
2521
2522 ret = switch_mprintf("<?xml version=\"1.0\"?>\n"
2523 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n"
2524 "<presence>\n"
2525 " <status>\n"
2526 " <note>%s</note>\n"
2527 " </status>\n"
2528 " <presentity uri=\"%s;method=SUBSCRIBE\" />\n"
2529 " <atom id=\"%s\">\n"
2530 " <address uri=\"%s;user=ip\" priority=\"0.800000\">\n"
2531 " <status status=\"%s\" />\n"
2532 " <msnsubstatus substatus=\"%s\" />\n"
2533 " </address>\n"
2534 " </atom>\n"
2535 "</presence>\n", status, id, id, url, open, prpid);
2536 } else {
2537 char *xml_rpid = NULL((void*)0);
2538
2539 *ct = "application/pidf+xml";
2540
2541 if (!strcasecmp(open, "closed")) {
2542 status = "Unregistered";
2543 prpid = NULL((void*)0);
2544 }
2545
2546 if (!strncasecmp(status, "Registered", 10)) {
2547 status = "Available";
2548 }
2549
2550 if (!strcasecmp(status, "Available")) {
2551 prpid = NULL((void*)0);
2552 }
2553
2554
2555 if (!strcasecmp(status, "Unregistered")) {
2556 prpid = NULL((void*)0);
2557 open = "closed";
2558 }
2559
2560 if (zstr(rpid)_zstr(rpid)) {
2561 prpid = NULL((void*)0);
2562 }
2563
2564
2565 if (zstr(status)_zstr(status) && !zstr(prpid)_zstr(prpid)) {
2566 status = "Available";
2567 prpid = NULL((void*)0);
2568 }
2569
2570 if (prpid) {
2571 xml_rpid = switch_mprintf(" <rpid:activities>\r\n"
2572 " <rpid:%s/>\n"
2573 " </rpid:activities>\n", prpid);
2574 }
2575
2576 ret = switch_mprintf("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> \n"
2577 "<presence xmlns='urn:ietf:params:xml:ns:pidf' \n"
2578 "xmlns:dm='urn:ietf:params:xml:ns:pidf:data-model' \n"
2579 "xmlns:rpid='urn:ietf:params:xml:ns:pidf:rpid' \n"
2580 "xmlns:c='urn:ietf:params:xml:ns:pidf:cipid' entity='%s'>\n"
2581 " <tuple id='t6a5ed77e'>\n"
2582 " <status>\r\n"
2583 " <basic>%s</basic>\n"
2584 " </status>\n"
2585 " </tuple>\n"
2586 " <dm:person id='p06360c4a'>\n"
2587 "%s"
2588 " <dm:note>%s</dm:note>\n"
2589 " </dm:person>\n"
2590 "</presence>", id, open, switch_str_nil(xml_rpid)(xml_rpid ? xml_rpid : ""), status);
2591
2592
2593 switch_safe_free(xml_rpid)if (xml_rpid) {free(xml_rpid);xml_rpid=((void*)0);};
2594 }
2595
2596
2597 return ret;
2598}
2599
2600static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char **columnNames)
2601{
2602 struct presence_helper *helper = (struct presence_helper *) pArg;
2603 char *pl = NULL((void*)0);
2604 char *clean_id = NULL((void*)0), *id = NULL((void*)0);
2605 char *proto = argv[0];
2606 char *user = argv[1];
2607 char *host = argv[2];
2608 char *sub_to_user = argv[3];
2609 char *event = argv[5];
2610 char *contact = argv[6];
2611 char *call_id = argv[7];
2612 char *full_from = argv[8];
2613 //char *full_via = argv[9];
2614 char *expires = argv[10];
2615 char *user_agent = argv[11];
2616 char *profile_name = argv[13];
2617 uint32_t in = 0;
2618 char *status = argv[14];
2619 char *rpid = argv[15];
2620 char *sub_to_host = argv[16];
2621 char *open_closed = NULL((void*)0);
2622 char *dialog_status = NULL((void*)0);
2623 char *dialog_rpid = NULL((void*)0);
2624 //char *default_dialog = "partial";
2625 char *default_dialog = "full";
2626 const char *ct = "no/idea";
2627
2628 char *to = NULL((void*)0);
2629 char *open;
2630 char *prpid;
2631
2632 int is_dialog = 0;
2633 sofia_profile_t *ext_profile = NULL((void*)0), *profile = helper->profile;
2634
2635 char status_line[256] = "";
2636 char *version = "0";
2637 char *presence_id = NULL((void*)0);
2638 char *free_me = NULL((void*)0);
2639 int holding = 0;
2640 char *orig_proto = NULL((void*)0);
2641 int skip_proto = 0;
2642 char *full_to = NULL((void*)0);
2643 char *ip = NULL((void*)0);
2644 char *port = 0;
2645 const char *call_state = NULL((void*)0);
2646 const char *astate = NULL((void*)0);
2647 const char *event_status = NULL((void*)0);
2648 const char *force_event_status = NULL((void*)0);
2649 char *contact_str, *contact_stripped;
2650
2651 if (mod_sofia_globals.debug_presence > 0) {
2652 int i;
2653 for(i = 0; i < argc; i++) {
2654 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 2654, ((void*)0)
, SWITCH_LOG_CRIT, "arg %d[%s] = [%s]\n", i, columnNames[i], argv[i]);
2655 }
2656 DUMP_EVENT(helper->event){char *event_str;switch_event_serialize(helper->event, &
event_str, SWITCH_FALSE);switch_log_printf(SWITCH_CHANNEL_ID_LOG
, "sofia_presence.c", (const char *)__func__, 2656, ((void*)0
), SWITCH_LOG_CRIT, "DUMP\n%s\n", event_str);free(event_str);
}
;
2657 }
2658
2659 if (argc > 18) {
2660 if (!zstr(argv[17])_zstr(argv[17])) {
2661 status = argv[17];
2662 }
2663 if (!zstr(argv[18])_zstr(argv[18])) {
2664 rpid = argv[18];
2665 }
2666 open_closed = argv[19];
2667 }
2668
2669 if (argc > 20) {
2670 dialog_status = argv[20];
2671 dialog_rpid = argv[21];
2672 version = argv[22];
2673 presence_id = argv[23];
2674 orig_proto = argv[24];
2675 full_to = argv[25];
2676 ip = argv[26];
2677 port = argv[27];
2678 }
2679
2680 if (!zstr(ip)_zstr(ip) && sofia_glue_check_nat(profile, ip)) {
2681 char *ptr;
2682 if ((ptr = sofia_glue_find_parameter(contact, "transport="))) {
2683 sofia_transport_t transport = sofia_glue_str2transport( ptr + 10 );
2684
2685 switch (transport) {
2686 case SOFIA_TRANSPORT_TCP:
2687 contact_str = profile->tcp_public_contact;
2688 break;
2689 case SOFIA_TRANSPORT_TCP_TLS:
2690 contact_str = sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0) ?
2691 profile->tls_public_contact : profile->tcp_public_contact;
2692 break;
2693 default:
2694 contact_str = profile->public_url;
2695 break;
2696 }
2697 } else {
2698 contact_str = profile->public_url;
2699 }
2700 } else {
2701 char *ptr;
2702 if ((ptr = sofia_glue_find_parameter(contact, "transport="))) {
2703 sofia_transport_t transport = sofia_glue_str2transport( ptr + 10 );
2704
2705 switch (transport) {
2706 case SOFIA_TRANSPORT_TCP:
2707 contact_str = profile->tcp_contact;
2708 break;
2709 case SOFIA_TRANSPORT_TCP_TLS:
2710 contact_str = sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0) ?
2711 profile->tls_contact : profile->tcp_contact;
2712 break;
2713 default:
2714 contact_str = profile->url;
2715 break;
2716 }
2717 } else {
2718 contact_str = profile->url;
2719 }
2720 }
2721
2722
2723 if (!zstr(presence_id)_zstr(presence_id) && strchr(presence_id, '@')) {
2724 char *p;
2725
2726 free_me = strdup(presence_id);
2727
2728 switch_assert(free_me)((free_me) ? (void) (0) : __assert_fail ("free_me", "sofia_presence.c"
, 2728, __extension__ __PRETTY_FUNCTION__))
;
2729
2730 if ((p = strchr(free_me, '@'))) {
2731 *p = '\0';
2732 }
2733
2734 user = free_me;
2735 }
2736
2737
2738 if (!zstr(orig_proto)_zstr(orig_proto) && !strcmp(orig_proto, SOFIA_CHAT_PROTO"sip")) {
2739 skip_proto = 1;
2740 }
2741
2742 in = helper->event && helper->event->event_id == SWITCH_EVENT_PRESENCE_IN;
2743
2744 if (zstr(rpid)_zstr(rpid)) {
2745 rpid = "unknown";
2746 }
2747
2748 if (zstr(status)_zstr(status)) {
2749 if (!strcasecmp(rpid, "busy")) {
2750 status = "Busy";
2751 } else if (!strcasecmp(rpid, "unavailable")) {
2752 status = "Idle";
2753 } else if (!strcasecmp(rpid, "away")) {
2754 status = "Idle";
2755 } else {
2756 status = "Available";
2757 }
2758 }
2759
2760 if (status && !strncasecmp(status, "hold", 4)) {
2761 holding = 1;
2762 }
2763
2764 if (profile_name && strcasecmp(profile_name, helper->profile->name)) {
2765 if ((ext_profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 2765, profile_name)
)) {
2766 profile = ext_profile;
2767 }
2768 }
2769
2770
2771 if (!strcasecmp(proto, SOFIA_CHAT_PROTO"sip") || skip_proto) {
2772 clean_id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host);
2773 } else {
2774 clean_id = switch_mprintf("sip:%s+%s@%s", proto, sub_to_user, sub_to_host);
2775 }
2776
2777
2778
2779 if (!rpid) {
2780 rpid = "unknown";
2781 }
2782
2783 // if (!strcasecmp(proto, SOFIA_CHAT_PROTO) || skip_proto) {
2784 // clean_id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host);
2785 //} else {
2786 // clean_id = switch_mprintf("sip:%s+%s@%s", proto, sub_to_user, sub_to_host);
2787 //}
2788
2789 if (mod_sofia_globals.debug_presence > 0) {
2790 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 2790, ((void*)0)
, SWITCH_LOG_NOTICE,
2791 "SEND PRESENCE\nTo: \t%s@%s\nFrom: \t%s@%s\nCall-ID: \t%s\nProfile:\t%s [%s]\n\n",
2792 user, host, sub_to_user, sub_to_host, call_id, profile_name, helper->profile->name);
2793 }
2794
2795 if (!strcasecmp(sub_to_host, host) && !skip_proto) {
2796 /* same host */
2797 id = switch_mprintf("sip:%s+%s@%s", proto, sub_to_user, sub_to_host);
2798 } else if (strcasecmp(proto, SOFIA_CHAT_PROTO"sip") && !skip_proto) {
2799 /*encapsulate */
2800 id = switch_mprintf("sip:%s+%s+%s@%s", proto, sub_to_user, sub_to_host, host);
2801 } else {
2802 id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host);
2803 }
2804
2805 to = switch_mprintf("sip:%s@%s", user, host);
2806
2807 is_dialog = !strcmp(event, "dialog");
2808
2809 if (helper->hup && helper->calls_up > 0) {
2810 call_state = "CS_EXECUTE";
2811 astate = "active";
2812 event_status = "Active";
2813 force_event_status = NULL((void*)0);
2814 } else {
2815 if (helper->event) {
2816 call_state = switch_event_get_header(helper->event, "channel-state")switch_event_get_header_idx(helper->event, "channel-state"
, -1)
;
2817 astate = switch_str_nil(switch_event_get_header(helper->event, "astate"))(switch_event_get_header_idx(helper->event, "astate", -1) ?
switch_event_get_header_idx(helper->event, "astate", -1) :
"")
;
2818 event_status = switch_str_nil(switch_event_get_header(helper->event, "status"))(switch_event_get_header_idx(helper->event, "status", -1) ?
switch_event_get_header_idx(helper->event, "status", -1) :
"")
;
2819 force_event_status = switch_str_nil(switch_event_get_header(helper->event, "force-status"))(switch_event_get_header_idx(helper->event, "force-status"
, -1) ? switch_event_get_header_idx(helper->event, "force-status"
, -1) : "")
;
2820 }
2821 }
2822
2823 if (helper->event) {
2824 switch_stream_handle_t stream = { 0 };
2825 const char *direction = switch_str_nil(switch_event_get_header(helper->event, "presence-call-direction"))(switch_event_get_header_idx(helper->event, "presence-call-direction"
, -1) ? switch_event_get_header_idx(helper->event, "presence-call-direction"
, -1) : "")
;
2826 //const char *force_direction = switch_str_nil(switch_event_get_header(helper->event, "force-direction"));
2827 const char *uuid = switch_str_nil(switch_event_get_header(helper->event, "unique-id"))(switch_event_get_header_idx(helper->event, "unique-id", -
1) ? switch_event_get_header_idx(helper->event, "unique-id"
, -1) : "")
;
2828 const char *resub = switch_str_nil(switch_event_get_header(helper->event, "resub"))(switch_event_get_header_idx(helper->event, "resub", -1) ?
switch_event_get_header_idx(helper->event, "resub", -1) :
"")
;
2829 const char *answer_state = switch_str_nil(switch_event_get_header(helper->event, "answer-state"))(switch_event_get_header_idx(helper->event, "answer-state"
, -1) ? switch_event_get_header_idx(helper->event, "answer-state"
, -1) : "")
;
2830 const char *dft_state;
2831 const char *from_id = NULL((void*)0), *from_name = NULL((void*)0);
2832 const char *to_user = switch_str_nil(switch_event_get_header(helper->event, "variable_sip_to_user"))(switch_event_get_header_idx(helper->event, "variable_sip_to_user"
, -1) ? switch_event_get_header_idx(helper->event, "variable_sip_to_user"
, -1) : "")
;
2833 const char *from_user = switch_str_nil(switch_event_get_header(helper->event, "variable_sip_from_user"))(switch_event_get_header_idx(helper->event, "variable_sip_from_user"
, -1) ? switch_event_get_header_idx(helper->event, "variable_sip_from_user"
, -1) : "")
;
2834 const char *disable_early = switch_str_nil(switch_event_get_header(helper->event, "variable_presence_disable_early"))(switch_event_get_header_idx(helper->event, "variable_presence_disable_early"
, -1) ? switch_event_get_header_idx(helper->event, "variable_presence_disable_early"
, -1) : "")
;
2835 const char *answer_epoch = switch_str_nil(switch_event_get_header(helper->event, "variable_answer_epoch"))(switch_event_get_header_idx(helper->event, "variable_answer_epoch"
, -1) ? switch_event_get_header_idx(helper->event, "variable_answer_epoch"
, -1) : "")
;
2836 int answered = 0;
2837 char *clean_to_user = NULL((void*)0);
2838 char *clean_from_user = NULL((void*)0);
2839 int force_status = 0;
2840 int term = 0;
2841
2842 if (answer_epoch) {
2843 answered = atoi(answer_epoch);
2844 }
2845
2846
2847 //if (user_agent && switch_stristr("snom", user_agent) && uuid) {
2848 // default_dialog = "full" ;
2849 //}
2850
2851 if (call_state && !strcasecmp(call_state, "cs_hangup")) {
2852 astate = "hangup";
2853 holding = 0;
2854 term = 1;
2855 } else {
2856
2857 if (event_status && !strncasecmp(event_status, "hold", 4)) {
2858 holding = 1;
2859 }
2860
2861 if (force_event_status && !event_status) {
2862 event_status = force_event_status;
2863 }
2864
2865 if (event_status && !strncasecmp(event_status, "hold", 4)) {
2866 holding = 1;
2867 }
2868 }
2869
2870 if (!strcasecmp(direction, "inbound")) {
2871 from_id = switch_str_nil(switch_event_get_header(helper->event, "Caller-Destination-Number"))(switch_event_get_header_idx(helper->event, "Caller-Destination-Number"
, -1) ? switch_event_get_header_idx(helper->event, "Caller-Destination-Number"
, -1) : "")
;
2872
2873 } else {
2874 from_id = switch_str_nil(switch_event_get_header(helper->event, "Caller-Caller-ID-Number"))(switch_event_get_header_idx(helper->event, "Caller-Caller-ID-Number"
, -1) ? switch_event_get_header_idx(helper->event, "Caller-Caller-ID-Number"
, -1) : "")
;
2875 from_name = switch_event_get_header(helper->event, "Caller-Caller-ID-Name")switch_event_get_header_idx(helper->event, "Caller-Caller-ID-Name"
, -1)
;
2876
2877 if (zstr(from_id)_zstr(from_id)) {
2878 from_id = switch_str_nil(switch_event_get_header(helper->event, "Other-Leg-Caller-ID-Number"))(switch_event_get_header_idx(helper->event, "Other-Leg-Caller-ID-Number"
, -1) ? switch_event_get_header_idx(helper->event, "Other-Leg-Caller-ID-Number"
, -1) : "")
;
2879 }
2880
2881 if (zstr(from_name)_zstr(from_name)) {
2882 from_name = switch_event_get_header(helper->event, "Other-Leg-Caller-ID-Name")switch_event_get_header_idx(helper->event, "Other-Leg-Caller-ID-Name"
, -1)
;
2883 }
2884
2885 }
2886
2887#if 0
2888 char *buf;
2889 switch_event_serialize(helper->event, &buf, SWITCH_FALSE);
2890 switch_assert(buf)((buf) ? (void) (0) : __assert_fail ("buf", "sofia_presence.c"
, 2890, __extension__ __PRETTY_FUNCTION__))
;
2891 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 2891, ((void*)0)
, SWITCH_LOG_INFO, "CHANNEL_DATA:\n%s\n", buf);
2892 free(buf);
2893#endif
2894
2895 if (is_dialog) {
2896 // Usually we report the dialogs FROM the probed user. The exception is when the monitored endpoint is internal,
2897 // and its presence_id is set in the dialplan. Reverse the direction if this is not a registered entity.
2898 const char *caller = switch_str_nil(switch_event_get_header(helper->event, "caller-username"))(switch_event_get_header_idx(helper->event, "caller-username"
, -1) ? switch_event_get_header_idx(helper->event, "caller-username"
, -1) : "")
;
2899 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "sofia_presence.c", 2899, __extension__ __PRETTY_FUNCTION__
)); memset(stream.data, 0, 1024); stream.end = stream.data; stream
.data_size = 1024; stream.write_function = switch_console_stream_write
; stream.raw_write_function = switch_console_stream_raw_write
; stream.alloc_len = 1024; stream.alloc_chunk = 1024
;
2900 if (!strcmp(direction, "inbound") && strcmp(sub_to_user, caller)) {
2901 // If inbound and the entity is not the caller (i.e. internal to FS), then the direction is reversed
2902 // because it is not going through the B2BUA
2903 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 2903, ((void*)0)
, SWITCH_LOG_DEBUG1, "sofia_presence_sub_callback: endpt is internal\n");
2904 direction = !strcasecmp(direction, "outbound") ? "inbound" : "outbound";
2905 }
2906
2907 }
2908
2909 if (!strcasecmp(direction, "outbound")) {
2910 direction = "recipient";
2911 dft_state = "early";
2912 } else {
2913 direction = "initiator";
2914 dft_state = "confirmed";
2915 }
2916
2917 if (is_dialog) {
2918 if (zstr(version)_zstr(version)) {
2919 version = "0";
2920 }
2921
2922 stream.write_function(&stream,
2923 "<?xml version=\"1.0\"?>\n"
2924 "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" "
2925 "version=\"%s\" state=\"%s\" entity=\"%s\">\n", version, default_dialog, clean_id);
2926
2927 }
2928
2929 if (!zstr(uuid)_zstr(uuid)) {
2930 if (!zstr(answer_state)_zstr(answer_state)) {
2931 astate = answer_state;
2932 }
2933
2934 if (zstr(astate)_zstr(astate)) {
2935 if (is_dialog) {
2936 astate = dft_state;
2937 } else {
2938 astate = "terminated";
2939 }
2940 }
2941
2942 if (!strcasecmp(astate, "answered")) {
2943 astate = "confirmed";
2944 }
2945
2946
2947 if (is_dialog) {
2948
2949 if (!strcasecmp(astate, "ringing")) {
2950 if (!strcasecmp(direction, "recipient")) {
2951 astate = "early";
2952 } else {
2953 astate = "confirmed";
2954 }
2955 }
2956
2957 if (holding) {
2958 if (profile->pres_held_type == PRES_HELD_CONFIRMED) {
2959 astate = "confirmed";
2960 } else if (profile->pres_held_type == PRES_HELD_TERMINATED) {
2961 astate = "terminated";
2962 } else {
2963 astate = "early";
2964 }
2965 }
2966
2967
2968 if (!strcasecmp(astate, "hangup")) {
2969 astate = "terminated";
2970 }
2971
2972 stream.write_function(&stream, "<dialog id=\"%s\" direction=\"%s\">\n", uuid, direction);
2973 stream.write_function(&stream, "<state>%s</state>\n", astate);
2974 } else {
2975 if (!strcasecmp(astate, "ringing")) {
2976 astate = "early";
2977 }
2978 }
2979
2980
2981 if ((sofia_test_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY)((profile)->pflags[PFLAG_PRESENCE_DISABLE_EARLY] ? 1 : 0) || switch_true(disable_early)) &&
2982 ((!zstr(astate)_zstr(astate) && (!strcasecmp(astate, "early") || !strcasecmp(astate, "ringing") || (!strcasecmp(astate, "terminated") && !answered))))) {
2983 switch_safe_free(stream.data)if (stream.data) {free(stream.data);stream.data=((void*)0);};
2984 goto end;
2985 }
2986
2987 if (!strcasecmp(astate, "early") || !strcasecmp(astate, "confirmed")) {
2988
2989 clean_to_user = switch_mprintf("%s", sub_to_user ? sub_to_user : to_user);
2990 clean_from_user = switch_mprintf("%s", from_id ? from_id : from_user);
2991
2992 if (is_dialog) {
2993 if (!zstr(clean_to_user)_zstr(clean_to_user) && !zstr(clean_from_user)_zstr(clean_from_user)) {
2994 stream.write_function(&stream, "<local>\n<identity display=\"%s\">sip:%s@%s</identity>\n", clean_to_user, clean_to_user, host);
2995 stream.write_function(&stream, "<target uri=\"sip:%s@%s\">\n", clean_to_user, host);
2996 stream.write_function(&stream, "<param pname=\"+sip.rendering\" pvalue=\"%s\"/>\n", holding ? "no" : "yes");
2997
2998 stream.write_function(&stream, "</target>\n</local>\n");
2999 if (switch_true(switch_event_get_header(helper->event, "Presence-Privacy")switch_event_get_header_idx(helper->event, "Presence-Privacy"
, -1)
)) {
3000 stream.write_function(&stream, "<remote>\n<identity display=\"Anonymous\">sip:anonymous@anonymous.invalid</identity>\n");
3001 } else {
3002 stream.write_function(&stream, "<remote>\n<identity display=\"%s\">sip:%s@%s</identity>\n",
3003 from_name ? from_name : clean_from_user, clean_from_user,
3004 host);
3005 }
3006 stream.write_function(&stream, "<target uri=\"sip:**%s@%s\"/>\n", clean_to_user, host);
3007 stream.write_function(&stream, "</remote>\n");
3008
3009 } else if (!strcasecmp(proto, "queue")) {
3010 stream.write_function(&stream, "<local>\n<identity display=\"queue\">sip:%s@%s;proto=queue</identity>\n",
3011 !zstr(clean_to_user)_zstr(clean_to_user) ? clean_to_user : "unknown", host);
3012 stream.write_function(&stream, "<target uri=\"sip:%s@%s;proto=fifo\">\n", !zstr(clean_to_user)_zstr(clean_to_user) ? clean_to_user : "unknown", host);
3013 stream.write_function(&stream, "<param pname=\"+sip.rendering\" pvalue=\"no\"/>\n</target>\n</local>\n");
3014 stream.write_function(&stream, "<remote>\n<identity display=\"queue\">sip:%s@%s</identity>\n", uuid, host);
3015 if (skip_proto) {
3016 stream.write_function(&stream, "<target uri=\"sip:%s@%s\"/>\n", uuid, host);
3017 } else {
3018 stream.write_function(&stream, "<target uri=\"sip:queue+%s@%s\"/>\n", uuid, host);
3019 }
3020
3021 stream.write_function(&stream, "</remote>\n");
3022 } else if (!strcasecmp(proto, "park")) {
3023 stream.write_function(&stream, "<local>\n<identity display=\"park\">sip:%s@%s;proto=park</identity>\n",
3024 !zstr(clean_to_user)_zstr(clean_to_user) ? clean_to_user : "unknown", host);
3025 stream.write_function(&stream, "<target uri=\"sip:%s@%s;proto=park\">\n", !zstr(clean_to_user)_zstr(clean_to_user) ? clean_to_user : "unknown", host);
3026 stream.write_function(&stream, "<param pname=\"+sip.rendering\" pvalue=\"no\"/>\n</target>\n</local>\n");
3027 stream.write_function(&stream, "<remote>\n<identity display=\"park\">sip:%s</identity>\n", uuid);
3028 if (skip_proto) {
3029 stream.write_function(&stream, "<target uri=\"sip:%s@%s\"/>\n", uuid, host);
3030 } else {
3031 stream.write_function(&stream, "<target uri=\"sip:park+%s@%s\"/>\n", uuid, host);
3032 }
3033 stream.write_function(&stream, "</remote>\n");
3034 } else if (!strcasecmp(proto, "pickup")) {
3035 stream.write_function(&stream, "<local>\n<identity display=\"pickup\">sip:%s@%s;proto=pickup</identity>\n",
3036 !zstr(clean_to_user)_zstr(clean_to_user) ? clean_to_user : "unknown", host);
3037 stream.write_function(&stream, "<target uri=\"sip:%s@%s;proto=pickup\">\n", !zstr(clean_to_user)_zstr(clean_to_user) ? clean_to_user : "unknown", host);
3038 stream.write_function(&stream, "<param pname=\"+sip.rendering\" pvalue=\"no\"/>\n</target>\n</local>\n");
3039 stream.write_function(&stream, "<remote>\n<identity display=\"pickup\">sip:%s@%s</identity>\n", uuid, host);
3040 if (skip_proto) {
3041 stream.write_function(&stream, "<target uri=\"sip:%s@%s\"/>\n", uuid, host);
3042 } else {
3043 stream.write_function(&stream, "<target uri=\"sip:pickup+%s@%s\"/>\n", uuid, host);
3044 }
3045 stream.write_function(&stream, "</remote>\n");
3046 } else if (!strcasecmp(proto, "conf")) {
3047 stream.write_function(&stream, "<local>\n<identity display=\"conference\">sip:%s@%s;proto=conference</identity>\n",
3048 !zstr(clean_to_user)_zstr(clean_to_user) ? clean_to_user : "unknown", host);
3049 stream.write_function(&stream, "<target uri=\"sip:%s@%s;proto=conference\">\n",
3050 !zstr(clean_to_user)_zstr(clean_to_user) ? clean_to_user : "unknown", host);
3051 stream.write_function(&stream, "<param pname=\"+sip.rendering\" pvalue=\"yes\"/>\n</target>\n</local>\n");
3052 stream.write_function(&stream, "<remote>\n<identity display=\"conference\">sip:%s@%s</identity>\n", uuid, host);
3053 if (skip_proto) {
3054 stream.write_function(&stream, "<target uri=\"sip:%s@%s\"/>\n", uuid, host);
3055 } else {
3056 stream.write_function(&stream, "<target uri=\"sip:conf+%s@%s\"/>\n", uuid, host);
3057 }
3058 stream.write_function(&stream, "</remote>\n");
3059 }
3060 }
3061
3062 switch_safe_free(clean_to_user)if (clean_to_user) {free(clean_to_user);clean_to_user=((void*
)0);}
;
3063 switch_safe_free(clean_from_user)if (clean_from_user) {free(clean_from_user);clean_from_user=(
(void*)0);}
;
3064 }
3065 if (is_dialog) {
3066 stream.write_function(&stream, "</dialog>\n");
3067 }
3068 }
3069
3070 if (is_dialog) {
3071 stream.write_function(&stream, "</dialog-info>\n");
3072 pl = stream.data;
3073 ct = "application/dialog-info+xml";
3074 }
3075
3076 if (!zstr(astate)_zstr(astate) && !zstr(uuid)_zstr(uuid) &&
3077 helper && helper->stream.data && strcmp(helper->last_uuid, uuid) && strcasecmp(astate, "terminated") && strchr(uuid, '-')) {
3078 helper->stream.write_function(&helper->stream, "update sip_dialogs set state='%q' where hostname='%q' and profile_name='%q' and uuid='%q';",
3079 astate, mod_sofia_globals.hostname, profile->name, uuid);
3080 switch_copy_string(helper->last_uuid, uuid, sizeof(helper->last_uuid));
3081 }
3082
3083 if (zstr(astate)_zstr(astate)) astate = "";
3084
3085 if (!is_dialog) {
3086 switch_set_string(status_line, status)switch_copy_string(status_line, status, sizeof(status_line));
3087
3088 if (in) {
3089 open = "open";
3090
3091 if (switch_false(resub)) {
3092 const char *direction = switch_event_get_header(helper->event, "Caller-Direction")switch_event_get_header_idx(helper->event, "Caller-Direction"
, -1)
;
3093 const char *op, *what = "Ring";
3094
3095 if (direction && !strcasecmp(direction, "outbound")) {
3096 op = switch_event_get_header(helper->event, "Other-Leg-Caller-ID-Number")switch_event_get_header_idx(helper->event, "Other-Leg-Caller-ID-Number"
, -1)
;
3097 } else {
3098 op = switch_event_get_header(helper->event, "Caller-Callee-ID-Number")switch_event_get_header_idx(helper->event, "Caller-Callee-ID-Number"
, -1)
;
3099 }
3100
3101 if (zstr(op)_zstr(op)) {
3102 op = switch_event_get_header(helper->event, "Caller-Destination-Number")switch_event_get_header_idx(helper->event, "Caller-Destination-Number"
, -1)
;
3103 }
3104
3105 if (direction) {
3106 what = strcasecmp(direction, "outbound") ? "Call" : "Ring";
3107 }
3108
3109 if (!strcmp(astate, "early")) {
3110 if (!zstr(op)_zstr(op)) {
3111 //switch_snprintf(status_line, sizeof(status_line), "%sing", what);
3112 //} else {
3113 if (sofia_test_pflag(profile, PFLAG_PRESENCE_PRIVACY)((profile)->pflags[PFLAG_PRESENCE_PRIVACY] ? 1 : 0)) {
3114 switch_snprintf(status_line, sizeof(status_line), "%s", what);
3115 } else {
3116 switch_snprintf(status_line, sizeof(status_line), "%s %s", what, op);
3117 }
3118 }
3119
3120 rpid = "on-the-phone";
3121 force_status = 1;
3122
3123 } else if (!strcmp(astate, "confirmed")) {
3124 if (!zstr(op)_zstr(op)) {
3125 if (sofia_test_pflag(profile, PFLAG_PRESENCE_PRIVACY)((profile)->pflags[PFLAG_PRESENCE_PRIVACY] ? 1 : 0)) {
3126 switch_snprintf(status_line, sizeof(status_line), "On The Phone");
3127 } else {
3128 switch_snprintf(status_line, sizeof(status_line), "Talk %s", op);
3129 }
3130 } else {
3131 switch_snprintf(status_line, sizeof(status_line), "On The Phone");
3132 }
3133
3134 rpid = "on-the-phone";
3135 force_status = 1;
3136 } else if (!strcmp(astate, "terminated") || !strcmp(astate, "hangup")) {
3137 //rpid = "online";
3138 //dialog_rpid = "";
3139 //force_event_status = "Available";
3140 term = 1;
3141 }
3142
3143 if (!term && !strcmp(status, "hold")) {
3144 rpid = "on-the-phone";
3145 if (!zstr(op)_zstr(op)) {
3146 if (sofia_test_pflag(profile, PFLAG_PRESENCE_PRIVACY)((profile)->pflags[PFLAG_PRESENCE_PRIVACY] ? 1 : 0)) {
3147 switch_snprintf(status_line, sizeof(status_line), "Hold");
3148 } else {
3149 switch_snprintf(status_line, sizeof(status_line), "Hold %s", op);
3150 }
3151 force_status = 1;
3152 }
3153 }
3154 }
3155 } else {
3156 open = "closed";
3157 }
3158
3159 if (!zstr(open_closed)_zstr(open_closed)) {
3160 open = open_closed;
3161 }
3162
3163 prpid = translate_rpid(rpid);
3164
3165 if (!zstr(dialog_status)_zstr(dialog_status) && !force_status) {
3166 status = dialog_status;
3167 switch_set_string(status_line, status)switch_copy_string(status_line, status, sizeof(status_line));
3168 }
3169
3170 if (!zstr(force_event_status)_zstr(force_event_status)) {
3171 switch_set_string(status_line, force_event_status)switch_copy_string(status_line, force_event_status, sizeof(status_line
))
;
3172 }
3173
3174 if (!zstr(dialog_rpid)_zstr(dialog_rpid)) {
3175 prpid = rpid = dialog_rpid;
3176 }
3177
3178 contact_stripped = sofia_glue_strip_uri(contact_str);
3179 pl = gen_pidf(user_agent, clean_id, contact_stripped, open, rpid, prpid, status_line, &ct);
3180 free(contact_stripped);
3181 }
3182
3183 } else {
3184 if (in) {
3185 open = "open";
3186 } else {
3187 open = "closed";
3188 }
3189
3190 if (!zstr(open_closed)_zstr(open_closed)) {
3191 open = open_closed;
3192 }
3193
3194 prpid = translate_rpid(rpid);
3195
3196 if (!zstr(dialog_status)_zstr(dialog_status)) {
3197 status = dialog_status;
3198 }
3199
3200 if (!zstr(dialog_rpid)_zstr(dialog_rpid)) {
3201 prpid = rpid = dialog_rpid;
3202 }
3203
3204 contact_stripped = sofia_glue_strip_uri(contact_str);
3205 pl = gen_pidf(user_agent, clean_id, contact_stripped, open, rpid, prpid, status, &ct);
3206 free(contact_stripped);
3207 }
3208
3209
3210 if (!is_dialog && helper->event && !switch_stristr("registered", status_line)){
3211 const char *uuid = switch_event_get_header_nil(helper->event, "unique-id")(switch_event_get_header_idx(helper->event, "unique-id", -
1) ? switch_event_get_header_idx(helper->event, "unique-id"
, -1) : "")
;
3212 const char *register_source = switch_event_get_header_nil(helper->event, "register-source")(switch_event_get_header_idx(helper->event, "register-source"
, -1) ? switch_event_get_header_idx(helper->event, "register-source"
, -1) : "")
;
3213
3214 if (!zstr(uuid)_zstr(uuid) && strchr(uuid, '-') && !zstr(status_line)_zstr(status_line) && !zstr(rpid)_zstr(rpid) && (zstr(register_source)_zstr(register_source) || strcasecmp(register_source, "register"))) {
3215 char *sql = switch_mprintf("update sip_dialogs set rpid='%q',status='%q' where hostname='%q' and profile_name='%q' and uuid='%q'",
3216 rpid, status_line,
3217 mod_sofia_globals.hostname, profile->name, uuid);
3218 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
3219 }
3220 }
3221
3222 send_presence_notify(profile, full_to, full_from, contact, expires, call_id, event, ip, port, ct, pl, NULL)_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,ip,port,ct,pl,((void*)0),"sofia_presence.c", (
const char *)__func__, 3222)
;
3223
3224
3225 end:
3226
3227 switch_safe_free(free_me)if (free_me) {free(free_me);free_me=((void*)0);};
3228
3229 if (ext_profile) {
3230 sofia_glue_release_profile(ext_profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 3230, ext_profile)
;
3231 }
3232
3233 switch_safe_free(id)if (id) {free(id);id=((void*)0);};
3234 switch_safe_free(clean_id)if (clean_id) {free(clean_id);clean_id=((void*)0);};
3235 switch_safe_free(pl)if (pl) {free(pl);pl=((void*)0);};
3236 switch_safe_free(to)if (to) {free(to);to=((void*)0);};
3237
3238 return 0;
3239}
3240
3241static int sofia_presence_mwi_callback(void *pArg, int argc, char **argv, char **columnNames)
3242{
3243 //char *sub_to_user = argv[3];
3244 //char *sub_to_host = argv[4];
3245 char *event = argv[5];
3246 char *contact = argv[6];
3247 char *call_id = argv[7];
3248 char *full_from = argv[8];
3249 char *expires = argv[10];
3250 char *profile_name = argv[13];
3251 char *body = argv[15];
3252 char *full_to = argv[16];
3253 char *remote_ip = argv[17];
3254 char *remote_port = argv[18];
3255
3256 struct mwi_helper *h = (struct mwi_helper *) pArg;
3257 sofia_profile_t *ext_profile = NULL((void*)0), *profile = h->profile;
3258
3259
3260 if (mod_sofia_globals.debug_presence > 0) {
3261 int i;
3262 for(i = 0; i < argc; i++) {
3263 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3263, ((void*)0)
, SWITCH_LOG_CRIT, "arg %d[%s] = [%s]\n", i, columnNames[i], argv[i]);
3264 }
3265 }
3266
3267 if (profile_name && strcasecmp(profile_name, h->profile->name)) {
3268 if ((ext_profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 3268, profile_name)
)) {
3269 profile = ext_profile;
3270 }
3271 }
3272
3273 send_presence_notify(profile,_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3274 full_to,_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3275 full_from,_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3276 contact,_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3277 expires,_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3278 call_id,_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3279 event,_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3280 remote_ip,_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3281 remote_port,_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3282 "application/simple-message-summary",_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3283 body,_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3284 NULL_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
3285 )_send_presence_notify(profile,full_to,full_from,contact,expires
,call_id,event,remote_ip,remote_port,"application/simple-message-summary"
,body,((void*)0),"sofia_presence.c", (const char *)__func__, 3285
)
;
3286
3287
3288 h->total++;
3289
3290 if (ext_profile) {
3291 sofia_glue_release_profile(ext_profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 3291, ext_profile)
;
3292 }
3293
3294 return 0;
3295}
3296
3297static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char **columnNames)
3298{
3299 const char *user = argv[0];
3300 const char *host = argv[1];
3301 const char *event = "message-summary";
3302 const char *contenttype = "application/simple-message-summary";
3303 const char *body = argv[5];
3304 const char *o_contact = argv[2];
3305 const char *network_ip = argv[4];
3306 const char *call_id = argv[6];
3307
3308 char *profile_name = argv[3];
3309 struct mwi_helper *h = (struct mwi_helper *) pArg;
3310 sofia_profile_t *ext_profile = NULL((void*)0), *profile = h->profile;
3311
3312 if (profile_name && strcasecmp(profile_name, h->profile->name)) {
3313 if ((ext_profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__
, 3313, profile_name)
)) {
3314 profile = ext_profile;
3315 }
3316 }
3317
3318 if (!sofia_test_pflag(profile, PFLAG_MWI_USE_REG_CALLID)((profile)->pflags[PFLAG_MWI_USE_REG_CALLID] ? 1 : 0)) {
3319 call_id = NULL((void*)0);
3320 }
3321
3322 sofia_glue_send_notify(profile, user, host, event, contenttype, body, o_contact, network_ip, call_id);
3323
3324 if (ext_profile) {
3325 sofia_glue_release_profile(ext_profile)sofia_glue_release_profile__("sofia_presence.c", (const char *
)__func__, 3325, ext_profile)
;
3326 }
3327
3328 return 0;
3329}
3330
3331static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char **columnNames)
3332{
3333 struct state_helper *sh = (struct state_helper *) pArg;
3334 char key[256] = "";
3335 char *data = NULL((void*)0), *tmp;
3336 char *call_id = argv[0];
3337 //char *expires = argv[1];
3338 char *user = argv[2];
3339 char *host = argv[3];
3340 char *event = argv[4];
3341 int i;
3342
3343
3344 if (mod_sofia_globals.debug_sla > 1) {
3345 for (i = 0; i < argc; i++) {
3346 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3346, ((void*)0)
, SWITCH_LOG_ERROR, "SLA3: %d [%s]=[%s]\n", i, columnNames[i], argv[i]);
3347 }
3348 }
3349
3350 switch_snprintf(key, sizeof(key), "%s%s", user, host);
3351 data = switch_core_hash_find(sh->hash, key);
3352
3353 if (data) {
3354 tmp = switch_core_sprintf(sh->pool, "%s,<sip:%s>;appearance-index=*;appearance-state=idle", data, host);
3355 } else {
3356 tmp = switch_core_sprintf(sh->pool, "<sip:%s>;appearance-index=*;appearance-state=idle", host);
3357 }
3358
3359
3360 if (!strcasecmp(event, "line-seize")) {
3361 char *hack;
3362
3363 if ((hack = (char *) switch_stristr("=seized", tmp))) {
3364 switch_snprintf(hack, 7, "=idle ");
3365 }
3366 }
3367
3368 if (mod_sofia_globals.debug_sla > 1) {
3369 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3369, ((void*)0)
, SWITCH_LOG_ERROR, "DB PRES NOTIFY: [%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n",
3370 argv[5], argv[6], argv[7], argv[8], call_id, event, argv[9], argv[10], tmp);
3371
3372 }
3373
3374 send_presence_notify(sh->profile, argv[5], argv[6], argv[7], argv[8], call_id, event, argv[9], argv[10], NULL, NULL, tmp)_send_presence_notify(sh->profile,argv[5],argv[6],argv[7],
argv[8],call_id,event,argv[9],argv[10],((void*)0),((void*)0),
tmp,"sofia_presence.c", (const char *)__func__, 3374)
;
3375
3376 sh->total++;
3377
3378 return 0;
3379}
3380
3381static int broadsoft_sla_gather_state_callback(void *pArg, int argc, char **argv, char **columnNames)
3382{
3383 struct state_helper *sh = (struct state_helper *) pArg;
3384 char key[256] = "";
3385 switch_core_session_t *session;
3386 const char *callee_name = NULL((void*)0), *callee_number = NULL((void*)0);
3387 char *data = NULL((void*)0), *tmp;
3388 char *user = argv[0];
3389 char *host = argv[1];
3390 char *info = argv[2];
3391 char *state = argv[3];
3392 char *uuid = argv[4];
3393 int i;
3394
3395 if (mod_sofia_globals.debug_sla > 1) {
3396 for (i = 0; i < argc; i++) {
3397 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3397, ((void*)0)
, SWITCH_LOG_ERROR, "SLA2: %d [%s]=[%s]\n", i, columnNames[i], argv[i]);
3398 }
3399 }
3400
3401 if (zstr(info)_zstr(info)) {
3402 return 0;
3403 }
3404
3405 if (zstr(state)_zstr(state)) {
3406 state = "idle";
3407 }
3408
3409 switch_snprintf(key, sizeof(key), "%s%s", user, host);
3410
3411 data = switch_core_hash_find(sh->hash, key);
3412
3413 if (strcasecmp(state, "idle") && uuid && (session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "sofia_presence.c", (
const char *)__func__, 3413)
)) {
3414 switch_channel_t *channel = switch_core_session_get_channel(session);
3415
3416 if (switch_channel_test_flag(channel, CF_ORIGINATOR) || switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR) ||
3417 switch_channel_inbound_display(channel)((switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND
&& !switch_channel_test_flag(channel, CF_BLEG)) || (
switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND
&& switch_channel_test_flag(channel, CF_DIALPLAN)))
|| switch_channel_test_flag(channel, CF_SLA_BARGING)) {
3418 if (!switch_channel_test_flag(channel, CF_ANSWERED)) state = "progressing";
3419 callee_name = switch_channel_get_variable(channel, "callee_id_name")switch_channel_get_variable_dup(channel, "callee_id_name", SWITCH_TRUE
, -1)
;
3420 callee_number = switch_channel_get_variable(channel, "callee_id_number")switch_channel_get_variable_dup(channel, "callee_id_number", SWITCH_TRUE
, -1)
;
3421
3422 if (zstr(callee_number)_zstr(callee_number)) {
3423 callee_number = switch_channel_get_variable(channel, "destination_number")switch_channel_get_variable_dup(channel, "destination_number"
, SWITCH_TRUE, -1)
;
3424 }
3425
3426 } else {
3427 callee_name = switch_channel_get_variable(channel, "caller_id_name")switch_channel_get_variable_dup(channel, "caller_id_name", SWITCH_TRUE
, -1)
;
3428 callee_number = switch_channel_get_variable(channel, "caller_id_number")switch_channel_get_variable_dup(channel, "caller_id_number", SWITCH_TRUE
, -1)
;
3429 }
3430
3431 if (zstr(callee_name)_zstr(callee_name) && !zstr(callee_number)_zstr(callee_number)) {
3432 callee_name = callee_number;
3433 }
3434
3435 if (!zstr(callee_number)_zstr(callee_number)) {
3436 callee_number = switch_sanitize_number(switch_core_session_strdup(session, callee_number)switch_core_perform_session_strdup(session, callee_number, "sofia_presence.c"
, (const char *)__func__, 3436)
);
3437 }
3438
3439 if (!zstr(callee_name)_zstr(callee_name)) {
3440 char *tmp = switch_core_session_strdup(session, callee_name)switch_core_perform_session_strdup(session, callee_name, "sofia_presence.c"
, (const char *)__func__, 3440)
;
3441 switch_url_decode(tmp);
3442 callee_name = switch_sanitize_number(tmp);
3443 }
3444
3445
3446 //if (switch_channel_get_state(channel) != CS_EXECUTE) {
3447 //callee_number = NULL;
3448 //}
3449
3450 switch_core_session_rwunlock(session);
3451 }
3452
3453 if (data && strstr(data, info)) {
3454 return 0;
3455 }
3456
3457
3458 if (!zstr(callee_number)_zstr(callee_number)) {
3459 if (zstr(callee_name)_zstr(callee_name)) {
3460 callee_name = "unknown";
3461 }
3462
3463 if (data) {
3464 tmp = switch_core_sprintf(sh->pool,
3465 "%s,<sip:%s>;%s;appearance-state=%s;appearance-uri=\"\\\"%s\\\" <sip:%s@%s>\"",
3466 data, host, info, state, callee_name, callee_number, host);
3467 } else {
3468 tmp = switch_core_sprintf(sh->pool,
3469 "<sip:%s>;%s;appearance-state=%s;appearance-uri=\"\\\"%s\\\" <sip:%s@%s>\"",
3470 host, info, state, callee_name, callee_number, host);
3471 }
3472 } else {
3473 if (data) {
3474 tmp = switch_core_sprintf(sh->pool, "%s,<sip:%s>;%s;appearance-state=%s", data, host, info, state);
3475 } else {
3476 tmp = switch_core_sprintf(sh->pool, "<sip:%s>;%s;appearance-state=%s", host, info, state);
3477 }
3478 }
3479
3480 switch_core_hash_insert(sh->hash, key, tmp)switch_core_hash_insert_destructor(sh->hash, key, tmp, ((void
*)0))
;
3481
3482 return 0;
3483}
3484
3485static int sync_sla(sofia_profile_t *profile, const char *to_user, const char *to_host, switch_bool_t clear, switch_bool_t unseize, const char *call_id)
3486{
3487 struct state_helper *sh;
3488 switch_memory_pool_t *pool;
3489 char *sql;
3490 int total = 0;
3491
3492
3493 if (clear) {
3494 struct pres_sql_cb cb = {profile, 0};
3495
3496
3497 if (call_id) {
3498
3499 sql = switch_mprintf("update sip_subscriptions set version=version+1,expires=%ld where "
3500 "call_id='%q' "
3501 "and event='line-seize'", (long) switch_epoch_time_now(NULL((void*)0)),
3502 call_id);
3503
3504 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
3505
3506 if (mod_sofia_globals.debug_sla > 1) {
3507 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3507, ((void*)0)
, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql);
3508 }
3509 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3510
3511 sql = switch_mprintf("select full_to, full_from, contact, -1, call_id, event, network_ip, network_port, "
3512 "NULL as ct, NULL as pt "
3513 " from sip_subscriptions where call_id='%q' "
3514
3515 "and event='line-seize'", call_id);
3516
3517 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_send_sql, &cb);
3518 if (mod_sofia_globals.debug_sla > 1) {
3519 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3519, ((void*)0)
, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql);
3520 }
3521 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3522 } else {
3523
3524 sql = switch_mprintf("update sip_subscriptions set version=version+1,expires=%ld where "
3525 "hostname='%q' and profile_name='%q' "
3526 "and sub_to_user='%q' and sub_to_host='%q' "
3527
3528 "and event='line-seize'", (long) switch_epoch_time_now(NULL((void*)0)),
3529 mod_sofia_globals.hostname, profile->name, to_user, to_host
3530 );
3531
3532 if (mod_sofia_globals.debug_sla > 1) {
3533 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3533, ((void*)0)
, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql);
3534 }
3535
3536 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
3537
3538
3539 sql = switch_mprintf("select full_to, full_from, contact, -1, call_id, event, network_ip, network_port, "
3540 "NULL as ct, NULL as pt "
3541 " from sip_subscriptions where "
3542 "hostname='%q' and profile_name='%q' "
3543 "and sub_to_user='%q' and sub_to_host='%q' "
3544 "and event='line-seized'",
3545 mod_sofia_globals.hostname, profile->name, to_user, to_host
3546 );
3547
3548 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_send_sql, &cb);
3549
3550 if (mod_sofia_globals.debug_sla > 1) {
3551 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3551, ((void*)0)
, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql);
3552 }
3553
3554 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3555 }
3556
3557
3558 sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and profile_name='%q' and "
3559 "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') "
3560 "and call_info_state='seized'", mod_sofia_globals.hostname, profile->name, to_user, to_host, to_user, to_host);
3561
3562
3563 if (mod_sofia_globals.debug_sla > 1) {
3564 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3564, ((void*)0)
, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql);
3565 }
3566 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
3567 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3568 }
3569
3570
3571 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "sofia_presence.c"
, (const char *)__func__, 3571)
;
3572 sh = switch_core_alloc(pool, sizeof(*sh))switch_core_perform_alloc(pool, sizeof(*sh), "sofia_presence.c"
, (const char *)__func__, 3572)
;
3573 sh->pool = pool;
3574 switch_core_hash_init(&sh->hash)switch_core_hash_init_case(&sh->hash, SWITCH_TRUE);
3575
3576 sql = switch_mprintf("select sip_from_user,sip_from_host,call_info,call_info_state,uuid from sip_dialogs "
3577 "where call_info_state is not null and call_info_state != '' and call_info_state != 'idle' and hostname='%q' and profile_name='%q' "
3578 "and ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') "
3579 "and profile_name='%q'",
3580 mod_sofia_globals.hostname, profile->name, to_user, to_host, to_user, to_host, profile->name);
3581
3582
3583 if (mod_sofia_globals.debug_sla > 1) {
3584 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3584, ((void*)0)
, SWITCH_LOG_ERROR, "PRES SQL %s\n", sql);
3585 }
3586 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, broadsoft_sla_gather_state_callback, sh);
3587 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3588
3589
3590 if (!zstr(call_id)_zstr(call_id)) {
3591
3592 if (unseize) {
3593 sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port "
3594 "from sip_subscriptions where call_id='%q' and hostname='%q' and profile_name='%q' "
3595 "and (event='call-info' or event='line-seize')",
3596 call_id, mod_sofia_globals.hostname, profile->name);
3597
3598 } else {
3599 sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port "
3600 "from sip_subscriptions where call_id='%q' and hostname='%q' and profile_name='%q' and event='call-info'",
3601 call_id, mod_sofia_globals.hostname, profile->name);
3602 }
3603
3604 } else {
3605
3606 if (unseize) {
3607 sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port "
3608 "from sip_subscriptions "
3609 "where hostname='%q' and profile_name='%q' "
3610 "and sub_to_user='%q' and sub_to_host='%q' "
3611 "and (event='call-info' or event='line-seize') and (profile_name='%q' or presence_hosts like '%%%q%%')",
3612 mod_sofia_globals.hostname, profile->name, to_user, to_host, profile->name, to_host);
3613 } else {
3614 sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port "
3615 "from sip_subscriptions "
3616 "where hostname='%q' and profile_name='%q' "
3617 "and sub_to_user='%q' and sub_to_host='%q' " "and (event='call-info') and "
3618 "(profile_name='%q' or presence_hosts like '%%%q%%')",
3619 mod_sofia_globals.hostname, profile->name, to_user, to_host, profile->name, to_host);
3620 }
3621 }
3622
3623 if (mod_sofia_globals.debug_sla > 1) {
3624 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3624, ((void*)0)
, SWITCH_LOG_ERROR, "PRES SQL %s\n", sql);
3625 }
3626
3627 sh->profile = profile;
3628 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, broadsoft_sla_notify_callback, sh);
3629 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3630 total = sh->total;
3631 switch_core_hash_destroy(&sh->hash);
3632
3633 sh = NULL((void*)0);
3634 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "sofia_presence.c"
, (const char *)__func__, 3634)
;
3635
3636
3637
3638
3639
3640 return total;
3641
3642}
3643
3644void sofia_presence_handle_sip_i_subscribe(int status,
3645 char const *phrase,
3646 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
3647 sofia_dispatch_event_t *de,
3648 tagi_t tags[])
3649{
3650
3651 long exp_delta = 0;
3652 char exp_delta_str[30] = "";
3653 uint32_t sub_max_deviation_var = 0;
3654 sip_to_t const *to;
3655 const char *from_user = NULL((void*)0), *from_host = NULL((void*)0);
3656 const char *to_user = NULL((void*)0), *to_host = NULL((void*)0);
3657 char *my_to_user = NULL((void*)0);
3658 char *sql, *event = NULL((void*)0);
3659 char *proto = "sip";
3660 char *orig_proto = "";
3661 char *alt_proto = NULL((void*)0);
3662 char *d_user = NULL((void*)0);
3663 char *contact_str = "";
3664 const char *call_id = NULL((void*)0);
3665 char *to_str = NULL((void*)0);
3666 char *full_from = NULL((void*)0);
3667 char *full_to = NULL((void*)0);
3668 char *full_via = NULL((void*)0);
3669 char *full_agent = NULL((void*)0);
3670 char *sstr;
3671 switch_event_t *sevent;
3672 int sub_state = nua_substate_pending;
3673 int sent_reply = 0;
3674 sip_contact_t const *contact;
3675 const char *ipv6;
3676 const char *contact_user = NULL((void*)0);
3677 const char *contact_host = NULL((void*)0);
3678 const char *contact_port = NULL((void*)0);
3679 sofia_nat_parse_t np = { { 0 } };
3680 int found_proto = 0;
3681 const char *use_to_tag;
3682 char to_tag[13] = "";
3683 char buf[1025] = "";
3684 char *orig_to_user = NULL((void*)0);
3685 char *p;
3686 uint32_t callsequence;
3687 sip_cseq_t * cseq;
3688
3689 if (!sip) {
3690 return;
3691 }
3692
3693 to = sip->sip_to;
3694 contact = sip->sip_contact;
3695
3696 np.fs_path = 1;
3697 if (!(contact_str = sofia_glue_gen_contact_str(profile, sip, nh, de, &np))) {
3698 nua_respond(nh, 481, "INVALID SUBSCRIPTION", TAG_END()(tag_type_t)0, (tag_value_t)0);
3699 return;
3700 }
3701
3702 if (sip->sip_to && sip->sip_to->a_tag) {
3703 use_to_tag = sip->sip_to->a_tag;
3704 } else {
3705 switch_stun_random_string(to_tag, 12, NULL((void*)0));
3706 use_to_tag = to_tag;
3707 }
3708
3709 if (sip->sip_contact) {
3710 contact_host = sip->sip_contact->m_url->url_host;
3711 contact_port = sip->sip_contact->m_url->url_port;
3712 contact_user = sip->sip_contact->m_url->url_user;
3713 }
3714
3715 full_agent = sip_header_as_string(nua_handle_get_home(nh), (void *) sip->sip_user_agent);
3716
3717 //tl_gets(tags, NUTAG_SUBSTATE_REF(sub_state), TAG_END());
3718
3719 //sip->sip_subscription_state->ss_substate
3720
3721 if (sip->sip_subscription_state && sip->sip_subscription_state->ss_substate) {
3722 if (switch_stristr("terminated", sip->sip_subscription_state->ss_substate)) {
3723 sub_state = nua_substate_terminated;
3724 } else if (switch_stristr("active", sip->sip_subscription_state->ss_substate)) {
3725 sub_state = nua_substate_active;
3726 }
3727 }
3728
3729 event = sip_header_as_string(nua_handle_get_home(nh), (void *) sip->sip_event);
3730
3731 if (to) {
3732 to_str = switch_mprintf("sip:%s@%s", to->a_url->url_user, to->a_url->url_host);
3733 to_user = to->a_url->url_user;
3734 to_host = to->a_url->url_host;
3735 }
3736
3737 if (profile->sub_domain) {
3738 to_host = profile->sub_domain;
3739 }
3740
3741 if (sip->sip_from) {
3742 from_user = sip->sip_from->a_url->url_user;
3743 from_host = sip->sip_from->a_url->url_host;
3744 } else {
3745 from_user = "n/a";
3746 from_host = "n/a";
3747 }
3748
3749 if ((exp_delta = sip->sip_expires ? sip->sip_expires->ex_delta : 3600)) {
3750 if ((profile->force_subscription_expires > 0) && (profile->force_subscription_expires < (uint32_t)exp_delta)) {
3751 exp_delta = profile->force_subscription_expires;
3752 }
3753 }
3754
3755 if ((sub_max_deviation_var = profile->sip_subscription_max_deviation)) {
3756 int sub_deviation;
3757 srand( (unsigned) ( (unsigned)(intptr_t)switch_thread_self() + switch_micro_time_now() ) );
3758 /* random negative number between 0 and negative sub_max_deviation_var: */
3759 sub_deviation = ( rand() % sub_max_deviation_var ) - sub_max_deviation_var;
3760 if ( (exp_delta + sub_deviation) > 45 ) {
3761 exp_delta += sub_deviation;
3762 }
3763 }
3764
3765 if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) {
3766 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3766, ((void*)0)
, SWITCH_LOG_ERROR, "DELTA %ld\n", exp_delta);
3767 }
3768
3769 if (!exp_delta) {
3770 sub_state = nua_substate_terminated;
3771 }
3772
3773 switch_snprintf(exp_delta_str, sizeof(exp_delta_str), "%ld", exp_delta);
3774
3775 if (!strcmp("as-feature-event", event)) {
3776 sip_authorization_t const *authorization = NULL((void*)0);
3777 auth_res_t auth_res = AUTH_FORBIDDEN;
3778 char key[128] = "";
3779 switch_event_t *v_event = NULL((void*)0);
3780
3781
3782 if (sip->sip_authorization) {
3783 authorization = sip->sip_authorization;
3784 } else if (sip->sip_proxy_authorization) {
3785 authorization = sip->sip_proxy_authorization;
3786 }
3787
3788 if (authorization) {
3789 char network_ip[80];
3790 int network_port;
3791 sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
3792 auth_res = sofia_reg_parse_auth(profile, authorization, sip, de,
3793 (char *) sip->sip_request->rq_method_name, key, sizeof(key), network_ip, network_port, &v_event, 0,
3794 REG_REGISTER, to_user, NULL((void*)0), NULL((void*)0), NULL((void*)0));
3795 if (v_event) switch_event_destroy(&v_event);
3796 } else if (sofia_reg_handle_register(nua, profile, nh, sip, de, REG_REGISTER, key, sizeof(key), &v_event, NULL, NULL, NULL)sofia_reg_handle_register_token(nua, profile, nh, sip, de, REG_REGISTER
, key, sizeof(key), &v_event, ((void*)0), ((void*)0), ((void
*)0), ((void*)0))
) {
3797 if (v_event) switch_event_destroy(&v_event);
3798 goto end;
3799 }
3800
3801 if ((auth_res != AUTH_OK && auth_res != AUTH_RENEWED)) {
3802 nua_respond(nh, SIP_401_UNAUTHORIZED401, sip_401_Unauthorized, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
3803 goto end;
3804 }
3805 } else if (sofia_test_pflag(profile, PFLAG_AUTH_SUBSCRIPTIONS)((profile)->pflags[PFLAG_AUTH_SUBSCRIPTIONS] ? 1 : 0)) {
3806 sip_authorization_t const *authorization = NULL((void*)0);
3807 auth_res_t auth_res = AUTH_FORBIDDEN;
3808 char keybuf[128] = "";
3809 char *key;
3810 size_t keylen;
3811 switch_event_t *v_event = NULL((void*)0);
3812
3813 key = keybuf;
3814 keylen = sizeof(keybuf);
3815
3816 if (sip->sip_authorization) {
3817 authorization = sip->sip_authorization;
3818 } else if (sip->sip_proxy_authorization) {
3819 authorization = sip->sip_proxy_authorization;
3820 }
3821
3822 if (authorization) {
3823 char network_ip[80];
3824 int network_port;
3825 sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
3826 auth_res = sofia_reg_parse_auth(profile, authorization, sip, de,
3827 (char *) sip->sip_request->rq_method_name, key, keylen, network_ip, network_port, NULL((void*)0), 0,
3828 REG_INVITE, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0));
3829 } else if ( sofia_reg_handle_register(nua, profile, nh, sip, de, REG_INVITE, key, (uint32_t)keylen, &v_event, NULL, NULL, NULL)sofia_reg_handle_register_token(nua, profile, nh, sip, de, REG_INVITE
, key, (uint32_t)keylen, &v_event, ((void*)0), ((void*)0)
, ((void*)0), ((void*)0))
) {
3830 if (v_event) {
3831 switch_event_destroy(&v_event);
3832 }
3833
3834 goto end;
3835 }
3836
3837 if ((auth_res != AUTH_OK && auth_res != AUTH_RENEWED)) {
3838 nua_respond(nh, SIP_401_UNAUTHORIZED401, sip_401_Unauthorized, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
3839 goto end;
3840 }
3841 }
3842
3843 orig_to_user = su_strdup(nua_handle_home(nh)((su_home_t *)(nh)), to_user);
3844
3845 if (to_user && (p = strchr(to_user, '+')) && p != to_user) {
3846 char *h;
3847 if ((proto = (d_user = strdup(to_user)))) {
3848 if ((my_to_user = strchr(d_user, '+'))) {
3849 *my_to_user++ = '\0';
3850 to_user = my_to_user;
3851 if ((h = strchr(to_user, '+')) || (h = strchr(to_user, '@'))) {
3852 *h++ = '\0';
3853 to_host = h;
3854 }
3855 }
3856 }
3857
3858 if (!(proto && to_host)) {
3859 nua_respond(nh, SIP_404_NOT_FOUND404, sip_404_Not_found, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
3860 goto end;
3861 }
3862
3863 found_proto++;
3864 }
3865
3866 call_id = sip->sip_call_id->i_id;
3867 full_from = sip_header_as_string(nua_handle_get_home(nh), (void *) sip->sip_from);
3868 full_to = sip_header_as_string(nua_handle_get_home(nh), (void *) sip->sip_to);
3869 full_via = sip_header_as_string(nua_handle_get_home(nh), (void *) sip->sip_via);
3870
3871
3872 if (sip->sip_expires && sip->sip_expires->ex_delta > 31536000) {
3873 sip->sip_expires->ex_delta = 31536000;
3874 }
3875
3876 if (sofia_test_pflag(profile, PFLAG_PRESENCE_MAP)((profile)->pflags[PFLAG_PRESENCE_MAP] ? 1 : 0) && !found_proto && (alt_proto = switch_ivr_check_presence_mapping(to_user, to_host))) {
3877 orig_proto = proto;
3878 proto = alt_proto;
3879 }
3880
3881 if ((sub_state != nua_substate_terminated)) {
3882 sql = switch_mprintf("select contact from sip_subscriptions where call_id='%q' and profile_name='%q' and hostname='%q'",
3883 call_id, profile->name, mod_sofia_globals.hostname);
3884 sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
3885
3886
3887 if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) {
3888 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3888, ((void*)0)
, SWITCH_LOG_ERROR,
3889 "check subs sql: %s [%s]\n", sql, buf);
3890 }
3891
3892 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3893
3894 if (!zstr(buf)_zstr(buf)) {
3895 sub_state = nua_substate_active;
3896 }
3897 }
3898
3899 if (sub_state == nua_substate_active) {
3900 char *contact = contact_str;
3901
3902 sstr = switch_mprintf("active;expires=%ld", exp_delta);
3903
3904 if (strstr(buf, "fs_path=") && !strstr(contact_str, "fs_path=")) {
3905 char *e = strchr(buf,';');
3906 size_t l = e ? e-buf : strlen(buf);
3907 if (!strncmp(contact_str,buf,l)) {
3908 contact = buf;
3909 }
3910 }
3911
3912 sql = switch_mprintf("update sip_subscriptions "
3913 "set expires=%ld, "
3914 "network_ip='%q',network_port='%d',sip_user='%q',sip_host='%q',full_via='%q',full_to='%q',full_from='%q',contact='%q' "
3915 "where call_id='%q' and profile_name='%q' and hostname='%q'",
3916 (long) switch_epoch_time_now(NULL((void*)0)) + exp_delta,
3917 np.network_ip, np.network_port, from_user, from_host, full_via, full_to, full_from, contact,
3918
3919 call_id, profile->name, mod_sofia_globals.hostname);
3920
3921 if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) {
3922 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3922, ((void*)0)
, SWITCH_LOG_ERROR,
3923 "re-subscribe event %s, sql: %s\n", event, sql);
3924 }
3925
3926 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
3927 } else {
3928
3929 if (sub_state == nua_substate_terminated) {
3930 sql = switch_mprintf("delete from sip_subscriptions where call_id='%q' and profile_name='%q' and hostname='%q'",
3931 call_id, profile->name, mod_sofia_globals.hostname);
3932
3933 if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) {
3934 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3934, ((void*)0)
, SWITCH_LOG_ERROR,
3935 "sub del sql: %s\n", sql);
3936 }
3937
3938 switch_assert(sql != NULL)((sql != ((void*)0)) ? (void) (0) : __assert_fail ("sql != ((void*)0)"
, "sofia_presence.c", 3938, __extension__ __PRETTY_FUNCTION__
))
;
3939 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
3940 sstr = switch_mprintf("terminated;reason=noresource");
3941
3942 } else {
3943 sip_accept_t *ap = sip->sip_accept;
3944 char accept_header[256] = "";
3945
3946 sub_state = nua_substate_active;
3947
3948 while (ap) {
3949 switch_snprintf(accept_header + strlen(accept_header), sizeof(accept_header) - strlen(accept_header),
3950 "%s%s ", ap->ac_type, ap->ac_next ? "," : "");
3951 ap = ap->ac_next;
3952 }
3953
3954 sql = switch_mprintf("insert into sip_subscriptions "
3955 "(proto,sip_user,sip_host,sub_to_user,sub_to_host,presence_hosts,event,contact,call_id,full_from,"
3956 "full_via,expires,user_agent,accept,profile_name,hostname,network_port,network_ip,version,orig_proto, full_to) "
3957 "values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%d','%q',-1,'%q','%q;tag=%q')",
3958 proto, from_user, from_host, to_user, to_host, profile->presence_hosts ? profile->presence_hosts : "",
3959 event, contact_str, call_id, full_from, full_via,
3960 (long) switch_epoch_time_now(NULL((void*)0)) + exp_delta,
3961 full_agent, accept_header, profile->name, mod_sofia_globals.hostname,
3962 np.network_port, np.network_ip, orig_proto, full_to, use_to_tag);
3963
3964 switch_assert(sql != NULL)((sql != ((void*)0)) ? (void) (0) : __assert_fail ("sql != ((void*)0)"
, "sofia_presence.c", 3964, __extension__ __PRETTY_FUNCTION__
))
;
3965
3966
3967 if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) {
3968 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 3968, ((void*)0)
, SWITCH_LOG_NOTICE, "%s SUBSCRIBE %s@%s %s@%s\n%s\n",
3969 profile->name, from_user, from_host, to_user, to_host, sql);
3970 }
3971
3972
3973 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
3974 sstr = switch_mprintf("active;expires=%ld", exp_delta);
3975 }
3976
3977 }
3978
3979 if ( sip->sip_event && sip->sip_event->o_type && !strcasecmp(sip->sip_event->o_type, "ua-profile") && contact_host ) {
3980 char *uri = NULL((void*)0);
3981 char *ct = "application/url";
3982 char *extra_headers = NULL((void*)0);
3983
3984 if ( contact_port ) {
3985 uri = switch_mprintf("sip:%s:%s", contact_host, contact_port);
3986 } else {
3987 uri = switch_mprintf("sip:%s", contact_host);
3988 }
3989
3990 if ( uri ) {
3991 switch_event_t *params = NULL((void*)0);
3992 /* Grandstream REALLY uses a header called Message Body */
3993 extra_headers = switch_mprintf("MessageBody: %s\r\n", profile->pnp_prov_url);
3994 if (sofia_test_pflag(profile, PFLAG_SUBSCRIBE_RESPOND_200_OK)((profile)->pflags[PFLAG_SUBSCRIBE_RESPOND_200_OK] ? 1 : 0
)
) {
3995 nua_respond(nh, SIP_200_OK200, sip_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
3996 } else {
3997 nua_respond(nh, SIP_202_ACCEPTED202, sip_202_Accepted, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
3998 }
3999
4000 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4000, ((void*)0)
, SWITCH_LOG_DEBUG, "sending pnp NOTIFY for %s to provision to %s\n", uri, profile->pnp_prov_url);
4001
4002 switch_event_create(&params, SWITCH_EVENT_NOTIFY)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 4002, &params, SWITCH_EVENT_NOTIFY
, ((void*)0))
;
4003 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "profile", profile->name);
4004 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "event-string", sip->sip_event->o_type);
4005 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "to-uri", uri);
4006 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "from-uri", uri);
4007 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "extra-headers", extra_headers);
4008 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "content-type", ct);
4009 switch_event_add_body(params, "%s", profile->pnp_prov_url);
4010 switch_event_fire(&params)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 4010, &params, ((void*)0))
;
4011
4012 switch_safe_free(uri)if (uri) {free(uri);uri=((void*)0);};
4013 switch_safe_free(extra_headers)if (extra_headers) {free(extra_headers);extra_headers=((void*
)0);}
;
4014
4015 goto end;
4016 }
4017 }
4018
4019 if (status < 200) {
4020 char *sticky = NULL((void*)0);
4021 char *contactstr, *cs = NULL((void*)0);
4022 char *p = NULL((void*)0), *new_contactstr = NULL((void*)0);
4023 sofia_transport_t transport;
4024
4025 if (np.is_nat) {
4026 char params[128] = "";
4027 if (contact->m_url->url_params) {
4028 switch_snprintf(params, sizeof(params), ";%s", contact->m_url->url_params);
4029 }
4030 ipv6 = strchr(np.network_ip, ':');
4031 sticky = switch_mprintf("sip:%s@%s%s%s:%d%s", contact_user, ipv6 ? "[" : "", np.network_ip, ipv6 ? "]" : "", np.network_port, params);
4032 }
4033
4034 if (np.is_auto_nat) {
4035 contactstr = profile->public_url;
4036 } else {
4037 contactstr = profile->url;
4038 }
4039
4040 if (sip->sip_via) {
4041 transport = sofia_glue_via2transport(sip->sip_via);
4042 } else {
4043 transport = sofia_glue_url2transport(contact->m_url);
4044 }
4045
4046 if (transport == SOFIA_TRANSPORT_TCP) {
4047 if (np.is_auto_nat) {
4048 cs = profile->tcp_public_contact;
4049 } else {
4050 cs = profile->tcp_contact;
4051 }
4052 } else if (transport == SOFIA_TRANSPORT_TCP_TLS) {
4053 if (np.is_auto_nat) {
4054 cs = sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0) ? profile->tls_public_contact : profile->tcp_public_contact;
4055 } else {
4056 cs = sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0) ? profile->tls_contact : profile->tcp_contact;
4057 }
4058 }
4059
4060 if (cs) {
4061 contactstr = cs;
4062 }
4063
4064
4065 if (nh) {
4066 /* nua_dialog_usage_set_refresh_range(nh->nh_ds->ds_usage, exp_delta + SUB_OVERLAP, exp_delta + SUB_OVERLAP); */
4067 nua_handle_dialog_usage_set_refresh_range(nh, exp_delta, exp_delta);
4068 }
4069
4070 if (contactstr && (p = strchr(contactstr, '@'))) {
4071 if (strrchr(p, '>')) {
4072 new_contactstr = switch_mprintf("<sip:%s%s", orig_to_user, p);
4073 } else {
4074 new_contactstr = switch_mprintf("<sip:%s%s>", orig_to_user, p);
4075 }
4076 }
4077
4078 if (nh) {
4079 sip_to_tag(nua_handle_get_home(nh), sip->sip_to, use_to_tag);
4080 }
4081
4082 if (mod_sofia_globals.debug_presence > 0) {
4083 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4083, ((void*)0)
, SWITCH_LOG_DEBUG, "Responding to SUBSCRIBE with 202 Accepted\n");
4084 }
4085 if (sofia_test_pflag(profile, PFLAG_SUBSCRIBE_RESPOND_200_OK)((profile)->pflags[PFLAG_SUBSCRIBE_RESPOND_200_OK] ? 1 : 0
)
) {
4086 nua_respond(nh, SIP_200_OK200, sip_200_OK,
4087 SIPTAG_TO(sip->sip_to)siptag_to, siptag_to_v(sip->sip_to),
4088 TAG_IF(new_contactstr, SIPTAG_CONTACT_STR(new_contactstr))!(new_contactstr) ? tag_skip : siptag_contact_str, tag_str_v(
new_contactstr)
,
4089 NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg),
4090 SIPTAG_SUBSCRIPTION_STATE_STR(sstr)siptag_subscription_state_str, tag_str_v(sstr), SIPTAG_EXPIRES_STR(exp_delta_str)siptag_expires_str, tag_str_v(exp_delta_str), TAG_IF(sticky, NUTAG_PROXY(sticky))!(sticky) ? tag_skip : ntatag_default_proxy, urltag_url_v((sticky
))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
4091 } else {
4092 nua_respond(nh, SIP_202_ACCEPTED202, sip_202_Accepted,
4093 SIPTAG_TO(sip->sip_to)siptag_to, siptag_to_v(sip->sip_to),
4094 TAG_IF(new_contactstr, SIPTAG_CONTACT_STR(new_contactstr))!(new_contactstr) ? tag_skip : siptag_contact_str, tag_str_v(
new_contactstr)
,
4095 NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg),
4096 SIPTAG_SUBSCRIPTION_STATE_STR(sstr)siptag_subscription_state_str, tag_str_v(sstr), SIPTAG_EXPIRES_STR(exp_delta_str)siptag_expires_str, tag_str_v(exp_delta_str), TAG_IF(sticky, NUTAG_PROXY(sticky))!(sticky) ? tag_skip : ntatag_default_proxy, urltag_url_v((sticky
))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
4097 }
4098
4099 switch_safe_free(new_contactstr)if (new_contactstr) {free(new_contactstr);new_contactstr=((void
*)0);}
;
4100 switch_safe_free(sticky)if (sticky) {free(sticky);sticky=((void*)0);};
4101
4102 if (sub_state == nua_substate_terminated) {
4103 if (mod_sofia_globals.debug_presence > 0) {
4104 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4104, ((void*)0)
, SWITCH_LOG_DEBUG, "Sending NOTIFY with Expires [0] and State [%s]\n", sstr);
4105 }
4106
4107 if (zstr(full_agent)_zstr(full_agent) || (*full_agent != 'z' && *full_agent != 'Z')) {
4108 /* supress endless loop bug with zoiper */
4109 callsequence = sofia_presence_get_cseq(profile);
4110 cseq = sip_cseq_create(nua_handle_get_home(nh), callsequence, SIP_METHOD_NOTIFYsip_method_notify, "NOTIFY");
4111 nua_notify(nh,
4112 SIPTAG_EXPIRES_STR("0")siptag_expires_str, tag_str_v("0"),
4113 SIPTAG_SUBSCRIPTION_STATE_STR(sstr)siptag_subscription_state_str, tag_str_v(sstr),
4114 SIPTAG_CSEQ(cseq)siptag_cseq, siptag_cseq_v(cseq),
4115 TAG_END()(tag_type_t)0, (tag_value_t)0);
4116 }
4117
4118
4119 }
4120 }
4121
4122 if (sub_state == nua_substate_terminated) {
4123 char *full_call_info = NULL((void*)0);
4124 char *p = NULL((void*)0);
4125
4126 if (sip->sip_call_info) {
4127 full_call_info = sip_header_as_string(nua_handle_get_home(nh), (void *) sip->sip_call_info);
4128 if ((p = strchr(full_call_info, ';'))) {
4129 p++;
4130 }
4131
4132#if 0
4133 nua_notify(nh,
4134 SIPTAG_EXPIRES_STR("0")siptag_expires_str, tag_str_v("0"),
4135 SIPTAG_SUBSCRIPTION_STATE_STR(sstr)siptag_subscription_state_str, tag_str_v(sstr), TAG_IF(full_call_info, SIPTAG_CALL_INFO_STR(full_call_info))!(full_call_info) ? tag_skip : siptag_call_info_str, tag_str_v
(full_call_info)
, TAG_END()(tag_type_t)0, (tag_value_t)0);
4136#endif
4137
4138 if (!strcasecmp(event, "line-seize")) {
4139 if (mod_sofia_globals.debug_sla > 1) {
4140 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4140, ((void*)0)
, SWITCH_LOG_ERROR, "CANCEL LINE SEIZE\n");
4141 }
4142
4143 sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and profile_name='%q' and "
4144 "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') "
4145 "and call_info_state='seized'",
4146 mod_sofia_globals.hostname, profile->name, to_user, to_host, to_user, to_host);
4147
4148
4149 if (mod_sofia_globals.debug_sla > 1) {
4150 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4150, ((void*)0)
, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql);
4151 }
4152 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
4153
4154 sync_sla(profile, to_user, to_host, SWITCH_FALSE, SWITCH_FALSE, NULL((void*)0));
4155 }
4156
4157 su_free(nua_handle_get_home(nh), full_call_info);
4158
4159 }
4160
4161 } else {
4162 if (!strcasecmp(event, "line-seize")) {
4163 char *full_call_info = NULL((void*)0);
4164 char *p;
4165 switch_time_t now;
4166
4167 if (sip->sip_call_info) {
4168 full_call_info = sip_header_as_string(nua_handle_get_home(nh), (void *) sip->sip_call_info);
4169 if ((p = strchr(full_call_info, ';'))) {
4170 p++;
4171 }
4172 callsequence = sofia_presence_get_cseq(profile);
4173 cseq = sip_cseq_create(nua_handle_get_home(nh), callsequence, SIP_METHOD_NOTIFYsip_method_notify, "NOTIFY");
4174 nua_notify(nh,
4175 SIPTAG_FROM(sip->sip_to)siptag_from, siptag_from_v(sip->sip_to),
4176 SIPTAG_TO(sip->sip_from)siptag_to, siptag_to_v(sip->sip_from),
4177 SIPTAG_EXPIRES_STR(exp_delta_str)siptag_expires_str, tag_str_v(exp_delta_str),
4178 SIPTAG_CSEQ(cseq)siptag_cseq, siptag_cseq_v(cseq),
4179 SIPTAG_SUBSCRIPTION_STATE_STR(sstr)siptag_subscription_state_str, tag_str_v(sstr),
4180 SIPTAG_EVENT_STR("line-seize")siptag_event_str, tag_str_v("line-seize"), TAG_IF(full_call_info, SIPTAG_CALL_INFO_STR(full_call_info))!(full_call_info) ? tag_skip : siptag_call_info_str, tag_str_v
(full_call_info)
, TAG_END()(tag_type_t)0, (tag_value_t)0);
4181
4182
4183
4184
4185 sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and profile_name='%q' and "
4186 "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') "
4187 "and call_info_state='seized' and profile_name='%q'",
4188 mod_sofia_globals.hostname, profile->name, to_user, to_host, to_user, to_host, profile->name);
4189
4190
4191 if (mod_sofia_globals.debug_sla > 1) {
4192 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4192, ((void*)0)
, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql);
4193 }
4194 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
4195
4196 now = switch_epoch_time_now(NULL((void*)0));
4197 sql = switch_mprintf("insert into sip_dialogs (sip_from_user,sip_from_host,call_info,call_info_state,hostname,expires,rcd,profile_name) "
4198 "values ('%q','%q','%q','seized','%q',%"TIME_T_FMT"ld"",%ld,'%q')",
4199 to_user, to_host, switch_str_nil(p)(p ? p : ""), mod_sofia_globals.hostname,
4200 switch_epoch_time_now(NULL((void*)0)) + exp_delta, (long)now, profile->name);
4201
4202 if (mod_sofia_globals.debug_sla > 1) {
4203 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4203, ((void*)0)
, SWITCH_LOG_ERROR, "SEIZE SQL %s\n", sql);
4204 }
4205 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
4206 sync_sla(profile, to_user, to_host, SWITCH_FALSE, SWITCH_FALSE, NULL((void*)0));
4207
4208 su_free(nua_handle_get_home(nh), full_call_info);
4209 }
4210 } else if (!strcasecmp(event, "call-info")) {
4211 sync_sla(profile, to_user, to_host, SWITCH_FALSE, SWITCH_FALSE, call_id);
4212 }
4213 }
4214
4215 sent_reply++;
4216
4217 switch_safe_free(sstr)if (sstr) {free(sstr);sstr=((void*)0);};
4218
4219 if (!strcasecmp(event, "as-feature-event")) {
4220 switch_event_t *event;
4221 char sip_cseq[40] = "";
4222
4223 switch_snprintf(sip_cseq, sizeof(sip_cseq), "%d", sip->sip_cseq->cs_seq);
4224 switch_event_create(&event, SWITCH_EVENT_PHONE_FEATURE_SUBSCRIBE)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 4224, &event, SWITCH_EVENT_PHONE_FEATURE_SUBSCRIBE
, ((void*)0))
;
4225 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user", from_user);
4226 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "host", from_host);
4227 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "contact", contact_str);
4228 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-id", call_id);
4229 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
4230 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "cseq", sip_cseq);
4231 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "profile_name", profile->name);
4232 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hostname", mod_sofia_globals.hostname);
4233
4234 if (sip->sip_payload) {
4235 switch_xml_t xml = NULL((void*)0);
4236 char *pd_dup = NULL((void*)0);
4237
4238 pd_dup = strdup(sip->sip_payload->pl_data);
4239
4240 switch_assert(pd_dup)((pd_dup) ? (void) (0) : __assert_fail ("pd_dup", "sofia_presence.c"
, 4240, __extension__ __PRETTY_FUNCTION__))
;
4241
4242 if ((xml = switch_xml_parse_str(pd_dup, strlen(pd_dup)))) {
4243 switch_xml_t device = NULL((void*)0);
4244
4245 if ((device = switch_xml_child(xml, "device"))) {
4246 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "device", device->txt);
4247 }
4248
4249 if (xml->name && !strcmp(xml->name, "SetDoNotDisturb")) {
4250 switch_xml_t action = NULL((void*)0);
4251
4252 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Feature-Action", "SetDoNotDisturb");
4253 if ((action = switch_xml_child(xml, "doNotDisturbOn"))) {
4254 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Feature-Enabled", action->txt);
4255 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action-Name", action->name);
4256 }
4257 }
4258
4259 if (xml->name && !strcmp(xml->name, "SetForwarding")) {
4260 switch_xml_t cfwd_type, cfwd_enable, cfwd_target;
4261
4262 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Feature-Action", "SetCallForward");
4263 if ((cfwd_type = switch_xml_child(xml, "forwardingType"))
4264 && (cfwd_enable = switch_xml_child(xml, "activateForward"))
4265 && (cfwd_target = switch_xml_child(xml, "forwardDN"))) {
4266
4267 if (!strcmp(cfwd_type->txt, "forwardImmediate")) {
4268 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Feature-Enabled", cfwd_enable->txt);
4269 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action-Name", "forward_immediate");
4270 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action-Value", cfwd_target->txt);
4271 } else if (!strcmp(cfwd_type->txt, "forwardBusy")) {
4272 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Feature-Enabled", cfwd_enable->txt);
4273 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action-Name", "forward_busy");
4274 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action-Value", cfwd_target->txt);
4275 } else if (!strcmp(cfwd_type->txt, "forwardNoAns")) {
4276 switch_xml_t rc;
4277
4278 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Feature-Enabled", cfwd_enable->txt);
4279 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action-Name", "forward_no_answer");
4280 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action-Value", cfwd_target->txt);
4281 if ((rc = switch_xml_child(xml, "ringCount"))) {
4282 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ringCount", rc->txt);
4283 }
4284 }
4285 }
4286 }
4287
4288 switch_xml_free(xml);
4289 }
4290
4291 switch_safe_free(pd_dup)if (pd_dup) {free(pd_dup);pd_dup=((void*)0);};
4292 }
4293 switch_event_fire(&event)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 4293, &event, ((void*)0))
;
4294 } else if (!strcasecmp(event, "message-summary")) {
4295 if ((sql = switch_mprintf("select proto,sip_user,'%q',sub_to_user,sub_to_host,event,contact,call_id,full_from,"
4296 "full_via,expires,user_agent,accept,profile_name,network_ip"
4297 " from sip_subscriptions where hostname='%q' and profile_name='%q' and "
4298 "event='message-summary' and sub_to_user='%q' "
4299 "and (sip_host='%q' or presence_hosts like '%%%q%%') and call_id='%q'",
4300 to_host, mod_sofia_globals.hostname, profile->name,
4301 to_user, to_host, to_host, call_id))) {
4302
4303 if (mod_sofia_globals.debug_presence > 0) {
4304 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4304, ((void*)0)
, SWITCH_LOG_ERROR,
4305 "SUBSCRIBE MWI SQL: %s\n", sql);
4306 }
4307
4308
4309 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_sub_reg_callback, profile);
4310
4311 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
4312 }
4313 } else if (!strcasecmp(event, "conference")) {
4314 switch_event_t *event;
4315 switch_event_create(&event, SWITCH_EVENT_CONFERENCE_DATA_QUERY)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 4315, &event, SWITCH_EVENT_CONFERENCE_DATA_QUERY
, ((void*)0))
;
4316 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Name", to_user);
4317 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Domain", to_host);
4318 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Query-From", from_user);
4319 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Query-From-Domain", from_host);
4320 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-Id", call_id);
4321 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sofia-Profile", profile->name);
4322 switch_event_fire(&event)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 4322, &event, ((void*)0))
;
4323 }
4324
4325 end:
4326
4327 if (strcasecmp(event, "call-info") && strcasecmp(event, "line-seize")) {
4328
4329 if (to_user && (strstr(to_user, "ext+") || strstr(to_user, "user+"))) {
4330 char protocol[80];
4331 char *p;
4332
4333 switch_copy_string(protocol, to_user, sizeof(protocol));
4334 if ((p = strchr(protocol, '+'))) {
4335 *p = '\0';
4336 }
4337
4338 if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_IN)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 4338, &sevent, SWITCH_EVENT_PRESENCE_IN
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
4339 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", protocol);
4340 if (!zstr(orig_proto)_zstr(orig_proto)) {
4341 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "orig_proto", orig_proto);
4342 }
4343 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name);
4344 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
4345 switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, to_host);
4346 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "rpid", "active");
4347 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "status", "Click To Call");
4348 switch_event_fire(&sevent)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 4348, &sevent, ((void*)0))
;
4349 }
4350
4351 } else if (to_user && (strcasecmp(proto, SOFIA_CHAT_PROTO"sip") != 0)) {
4352 if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 4352, &sevent, SWITCH_EVENT_PRESENCE_PROBE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
4353 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", proto);
4354 if (!zstr(orig_proto)_zstr(orig_proto)) {
4355 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "orig_proto", orig_proto);
4356 }
4357 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name);
4358 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
4359 switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
4360 switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s%s%s@%s", proto, "+", to_user, to_host);
4361 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event);
4362 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
4363 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "event_type", "presence");
4364 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
4365 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
4366 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sub-call-id", call_id);
4367 switch_event_fire(&sevent)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 4367, &sevent, ((void*)0))
;
4368
4369 }
4370 } else {
4371
4372 if (!strcasecmp(event, "dialog")) {
4373 if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 4373, &sevent, SWITCH_EVENT_PRESENCE_PROBE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
4374 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "probe-type", "dialog");
4375 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
4376 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name);
4377 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
4378 switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
4379 switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, to_host);
4380 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event);
4381 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
4382 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "event_type", "presence");
4383 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
4384 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
4385 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sub-call-id", call_id);
4386 switch_event_fire(&sevent)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 4386, &sevent, ((void*)0))
;
4387 }
4388 } else if (!strcasecmp(event, "presence")) {
4389 if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 4389, &sevent, SWITCH_EVENT_PRESENCE_PROBE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
4390 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
4391 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name);
4392 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
4393 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "presence-source", "subscribe");
4394 switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
4395 switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, to_host);
4396 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
4397 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
4398 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "rpid", "unknown");
4399 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "status", "Registered");
4400 switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sub-call-id", call_id);
4401 switch_event_fire(&sevent)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 4401, &sevent, ((void*)0))
;
4402 }
4403 }
4404 }
4405 }
4406
4407 if (event) {
4408 su_free(nua_handle_get_home(nh), event);
4409 }
4410
4411 if (full_from) {
4412 su_free(nua_handle_get_home(nh), full_from);
4413 }
4414 if (full_to) {
4415 su_free(nua_handle_get_home(nh), full_to);
4416 }
4417
4418 if (full_via) {
4419 su_free(nua_handle_get_home(nh), full_via);
4420 }
4421 if (full_agent) {
4422 su_free(nua_handle_get_home(nh), full_agent);
4423 }
4424
4425 switch_safe_free(d_user)if (d_user) {free(d_user);d_user=((void*)0);};
4426 switch_safe_free(to_str)if (to_str) {free(to_str);to_str=((void*)0);};
4427 switch_safe_free(contact_str)if (contact_str) {free(contact_str);contact_str=((void*)0);};
4428 switch_safe_free(alt_proto)if (alt_proto) {free(alt_proto);alt_proto=((void*)0);};
4429
4430 if (!sent_reply) {
4431 nua_respond(nh, 481, "INVALID SUBSCRIPTION", TAG_END()(tag_type_t)0, (tag_value_t)0);
4432 }
4433
4434 if (!sofia_private || !sofia_private->is_call) {
4435 nua_handle_destroy(nh);
4436 }
4437
4438}
4439
4440
4441sofia_gateway_subscription_t *sofia_find_gateway_subscription(sofia_gateway_t *gateway_ptr, const char *event)
4442{
4443 sofia_gateway_subscription_t *gw_sub_ptr;
4444 for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
4445 if (!strcasecmp(gw_sub_ptr->event, event)) {
4446 /* this is the gateway subscription we are interested in */
4447 return gw_sub_ptr;
4448 }
4449 }
4450 return NULL((void*)0);
4451}
4452
4453void sofia_presence_handle_sip_r_subscribe(int status,
4454 char const *phrase,
4455 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
4456 sofia_dispatch_event_t *de,
4457 tagi_t tags[])
4458{
4459 sip_event_t const *o = NULL((void*)0);
4460 sofia_gateway_subscription_t *gw_sub_ptr;
4461 sofia_gateway_t *gateway = NULL((void*)0);
4462
4463 if (!sip) {
4464 return;
4465 }
4466
4467 tl_gets(tags, SIPTAG_EVENT_REF(o)siptag_event_ref, siptag_event_vr(&(o)), TAG_END()(tag_type_t)0, (tag_value_t)0);
4468 /* o->o_type: message-summary (for example) */
4469 if (!o) {
4470 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4470, ((void*)0)
, SWITCH_LOG_ERROR, "Event information not given\n");
4471 return;
4472 }
4473
4474 if (!sofia_private || zstr(sofia_private->gateway_name)_zstr(sofia_private->gateway_name)) {
4475 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4475, ((void*)0)
, SWITCH_LOG_ERROR, "Gateway information missing\n");
4476 return;
4477 }
4478
4479
4480 if (!(gateway = sofia_reg_find_gateway(sofia_private->gateway_name)sofia_reg_find_gateway__("sofia_presence.c", (const char *)__func__
, 4480, sofia_private->gateway_name)
)) {
4481 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4481, ((void*)0)
, SWITCH_LOG_ERROR, "Gateway information missing\n");
4482 return;
4483 }
4484
4485
4486 /* Find the subscription if one exists */
4487 if (!(gw_sub_ptr = sofia_find_gateway_subscription(gateway, o->o_type))) {
4488 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4488, ((void*)0)
, SWITCH_LOG_WARNING, "Could not find gateway subscription. Gateway: %s. Subscription Event: %s\n",
4489 gateway->name, o->o_type);
4490 goto end;
4491 }
4492
4493 /* Update the subscription status for the subscription */
4494 switch (status) {
4495 case 200:
4496 case 202:
4497 /* TODO: in the spec it is possible for the other side to change the original expiry time,
4498 * this needs to be researched (eg, what sip header this information will be in) and implemented.
4499 * Although, since it seems the sofia stack is pretty much handling the subscription expiration
4500 * anyway, then maybe its not even worth bothering.
4501 */
4502 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4502, ((void*)0)
, SWITCH_LOG_DEBUG, "got 200 OK response, updated state to SUB_STATE_SUBSCRIBE.\n");
4503 gw_sub_ptr->state = SUB_STATE_SUBSCRIBE;
4504 break;
4505 case 100:
4506 break;
4507 default:
4508 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4508, ((void*)0)
, SWITCH_LOG_WARNING, "status (%d) != 200, updated state to SUB_STATE_FAILED.\n", status);
4509 gw_sub_ptr->state = SUB_STATE_FAILED;
4510
4511 break;
4512 }
4513
4514 end:
4515 sofia_reg_release_gateway(gateway)sofia_reg_release_gateway__("sofia_presence.c", (const char *
)__func__, 4515, gateway);
;
4516
4517}
4518
4519
4520static int sofia_presence_send_sql(void *pArg, int argc, char **argv, char **columnNames)
4521{
4522 struct pres_sql_cb *cb = (struct pres_sql_cb *) pArg;
4523
4524
4525 if (mod_sofia_globals.debug_presence > 0) {
4526 int i;
4527 for(i = 0; i < argc; i++) {
4528 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4528, ((void*)0)
, SWITCH_LOG_CRIT, "arg %d[%s] = [%s]\n", i, columnNames[i], argv[i]);
4529 }
4530 }
4531
4532 send_presence_notify(cb->profile, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], NULL)_send_presence_notify(cb->profile,argv[0],argv[1],argv[2],
argv[3],argv[4],argv[5],argv[6],argv[7],argv[8],argv[9],((void
*)0),"sofia_presence.c", (const char *)__func__, 4532)
;
4533 cb->ttl++;
4534
4535 return 0;
4536}
4537
4538
4539uint32_t sofia_presence_contact_count(sofia_profile_t *profile, const char *contact_str)
4540{
4541 char buf[32] = "";
4542 char *sql;
4543
4544 sql = switch_mprintf("select count(*) from sip_subscriptions where hostname='%q' and profile_name='%q' and contact='%q'",
4545 mod_sofia_globals.hostname, profile->name, contact_str);
4546
4547 sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
4548 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
4549 return atoi(buf);
4550}
4551
4552void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
4553 sofia_dispatch_event_t *de,
4554 tagi_t tags[])
4555{
4556
4557 sip_from_t const *from;
4558 char *from_user = NULL((void*)0);
4559 char *from_host = NULL((void*)0);
4560 char *rpid = "";
4561 sip_payload_t *payload;
4562 char *event_type = NULL((void*)0);
4563 char etag[9] = "";
4564 char expstr[30] = "";
4565 long exp = 0, exp_delta = 3600;
4566 char *pd_dup = NULL((void*)0);
4567 int count = 1, sub_count = 1;
4568 char *contact_str;
4569 sofia_nat_parse_t np = { { 0 } };
4570
4571 if (!sip) {
4572 return;
4573 }
4574
4575 from = sip->sip_from;
4576 payload = sip->sip_payload;
4577
4578 np.fs_path = 1;
4579 contact_str = sofia_glue_gen_contact_str(profile, sip, nh, de, &np);
4580
4581 if (from) {
4582 from_user = (char *) from->a_url->url_user;
4583 from_host = (char *) from->a_url->url_host;
4584 }
4585
4586 exp_delta = (sip->sip_expires ? sip->sip_expires->ex_delta : 3600);
4587 if ((profile->force_publish_expires > 0) && (profile->force_publish_expires < (uint32_t)exp_delta)) {
4588 exp_delta = profile->force_publish_expires;
4589 }
4590
4591 if (exp_delta < 0) {
4592 exp = exp_delta;
4593 } else {
4594 exp = (long) switch_epoch_time_now(NULL((void*)0)) + exp_delta;
4595 }
4596
4597 if (payload) {
4598 switch_xml_t xml, note, person, tuple, status, basic, act;
4599 switch_event_t *event;
4600 char *sql;
4601 char *full_agent = NULL((void*)0);
4602 char network_ip[80];
4603 int network_port = 0;
4604
4605 sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
4606
4607 pd_dup = strdup(payload->pl_data);
4608
4609 switch_assert(pd_dup)((pd_dup) ? (void) (0) : __assert_fail ("pd_dup", "sofia_presence.c"
, 4609, __extension__ __PRETTY_FUNCTION__))
;
4610
4611 if ((xml = switch_xml_parse_str(pd_dup, strlen(pd_dup)))) {
4612 char *open_closed = "", *note_txt = "";
4613
4614 if (sip->sip_user_agent) {
4615 full_agent = sip_header_as_string(nua_handle_get_home(nh), (void *) sip->sip_user_agent);
4616 }
4617
4618 if ((tuple = switch_xml_child(xml, "tuple")) && (status = switch_xml_child(tuple, "status"))
4619 && (basic = switch_xml_child(status, "basic"))) {
4620 open_closed = basic->txt;
4621
4622 if ((note = switch_xml_child(tuple, "note"))) {
4623 rpid = note_txt = note->txt;
4624 } else if ((note = switch_xml_child(tuple, "dm:note"))) {
4625 rpid = note_txt = note->txt;
4626 }
4627 }
4628
4629 if ((person = switch_xml_child(xml, "dm:person"))) {
4630 if ((note = switch_xml_child(person, "dm:note"))) {
4631 note_txt = note->txt;
4632 } else if ((note = switch_xml_child(person, "rpid:note"))) {
4633 note_txt = note->txt;
4634 }
4635 if ((act = switch_xml_child(person, "rpid:activities")) && act->child && act->child->name) {
4636 if ((rpid = strchr(act->child->name, ':'))) {
4637 rpid++;
4638 } else {
4639 rpid = act->child->name;
4640 }
4641 }
4642 if (zstr(note_txt)_zstr(note_txt)) note_txt = "Available";
4643 }
4644
4645 if (!strcasecmp(open_closed, "closed")) {
4646 rpid = note_txt = "Unregistered";
4647 if (sofia_test_pflag(profile, PFLAG_MULTIREG)((profile)->pflags[PFLAG_MULTIREG] ? 1 : 0)) {
4648 count = sofia_reg_reg_count(profile, from_user, from_host);
4649
4650 if (count != 1) {
4651 /* Don't broadcast offline when there is more than one client or one signing off makes them all appear to sign off on some clients */
4652 count = 0;
4653 } else {
4654 sub_count = sofia_presence_contact_count(profile, contact_str);
4655 }
4656 }
4657 }
4658
4659 event_type = sip_header_as_string(nua_handle_get_home(nh), (void *) sip->sip_event);
4660
4661 if (count) {
4662 if ((sql = switch_mprintf("delete from sip_presence where sip_user='%q' and sip_host='%q' "
4663 " and profile_name='%q' and hostname='%q'",
4664 from_user, from_host, profile->name, mod_sofia_globals.hostname))) {
4665 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
4666 }
4667
4668 if (sub_count > 0 && (sql = switch_mprintf("insert into sip_presence (sip_user, sip_host, status, rpid, expires, user_agent,"
4669 " profile_name, hostname, open_closed, network_ip, network_port) "
4670 "values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%q','%d')",
4671 from_user, from_host, note_txt, rpid, exp, full_agent, profile->name,
4672 mod_sofia_globals.hostname, open_closed, network_ip, network_port))) {
4673
4674 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
4675 }
4676
4677 } else if (contact_str) {
4678 struct pres_sql_cb cb = {profile, 0};
4679
4680 sql = switch_mprintf("select full_to, full_from, contact, expires, call_id, event, network_ip, network_port, "
4681 "'application/pidf+xml' as ct,'%q' as pt "
4682 " from sip_subscriptions where "
4683 "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q'"
4684 "and contact = '%q' ",
4685
4686 switch_str_nil(payload->pl_data)(payload->pl_data ? payload->pl_data : ""),
4687 mod_sofia_globals.hostname, profile->name,
4688 from_user, from_host, event_type, contact_str);
4689
4690 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_send_sql, &cb);
4691 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
4692 }
4693
4694 if (sub_count > 0) {
4695 if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 4695, &event, SWITCH_EVENT_PRESENCE_IN
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
4696 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
4697 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
4698 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
4699 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
4700 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent", full_agent);
4701 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
4702 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", note_txt);
4703 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", event_type);
4704 switch_event_fire(&event)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 4704, &event, ((void*)0))
;
4705 }
4706 }
4707
4708 if (event_type) {
4709 su_free(nua_handle_get_home(nh), event_type);
4710 }
4711
4712 if (full_agent) {
4713 su_free(nua_handle_get_home(nh), full_agent);
4714 }
4715
4716 switch_xml_free(xml);
4717 }
4718 } else {
4719 char *sql = switch_mprintf("update sip_presence set expires=%ld where sip_user='%q' and sip_host='%q' and profile_name='%q' and hostname='%q'",
4720 exp, from_user, from_host, profile->name, mod_sofia_globals.hostname);
4721 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
4722 }
4723
4724 switch_safe_free(pd_dup)if (pd_dup) {free(pd_dup);pd_dup=((void*)0);};
4725
4726 switch_snprintf(expstr, sizeof(expstr), "%d", exp_delta);
4727 switch_stun_random_string(etag, 8, NULL((void*)0));
4728
4729 if (sub_count > 0) {
4730 nua_respond(nh, SIP_200_OK200, sip_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), SIPTAG_ETAG_STR(etag)siptag_etag_str, tag_str_v(etag), SIPTAG_EXPIRES_STR(expstr)siptag_expires_str, tag_str_v(expstr), TAG_END()(tag_type_t)0, (tag_value_t)0);
4731 } else {
4732 nua_respond(nh, SIP_404_NOT_FOUND404, sip_404_Not_found, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
4733 }
4734
4735 switch_safe_free(contact_str)if (contact_str) {free(contact_str);contact_str=((void*)0);};
4736}
4737
4738void sofia_presence_set_hash_key(char *hash_key, int32_t len, sip_t const *sip)
4739{
4740 url_t *to = sip->sip_to->a_url;
4741 url_t *from = sip->sip_from->a_url;
4742 switch_snprintf(hash_key, len, "%s%s%s", from->url_user, from->url_host, to->url_user);
4743}
4744
4745void sofia_presence_handle_sip_i_message(int status,
4746 char const *phrase,
4747 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh,
4748 switch_core_session_t *session,
4749 sofia_private_t *sofia_private, sip_t const *sip,
4750 sofia_dispatch_event_t *de,
4751 tagi_t tags[])
4752{
4753
4754 if (sip) {
4755 sip_from_t const *from = sip->sip_from;
4756 const char *from_user = NULL((void*)0);
4757 const char *from_host = NULL((void*)0);
4758 sip_to_t const *to = sip->sip_to;
4759 const char *to_user = NULL((void*)0);
4760 const char *to_host = NULL((void*)0);
4761 sip_payload_t *payload = sip->sip_payload;
4762 char *msg = NULL((void*)0);
4763 const char *us;
4764 char network_ip[80];
4765 int network_port = 0;
4766 switch_channel_t *channel = NULL((void*)0);
4767
4768
4769 if (!sofia_test_pflag(profile, PFLAG_ENABLE_CHAT)((profile)->pflags[PFLAG_ENABLE_CHAT] ? 1 : 0)) {
4770 goto end;
4771 }
4772
4773
4774 if (session) {
4775 channel = switch_core_session_get_channel(session);
4776 }
4777
4778 if (sofia_test_pflag(profile, PFLAG_AUTH_MESSAGES)((profile)->pflags[PFLAG_AUTH_MESSAGES] ? 1 : 0)) {
4779 sip_authorization_t const *authorization = NULL((void*)0);
4780 auth_res_t auth_res = AUTH_FORBIDDEN;
4781 char keybuf[128] = "";
4782 char *key;
4783 size_t keylen;
4784 switch_event_t *v_event = NULL((void*)0);
4785
4786 key = keybuf;
4787 keylen = sizeof(keybuf);
4788
4789 if (sip->sip_authorization) {
4790 authorization = sip->sip_authorization;
4791 } else if (sip->sip_proxy_authorization) {
4792 authorization = sip->sip_proxy_authorization;
4793 }
4794
4795 if (authorization) {
4796 char network_ip[80];
4797 int network_port;
4798 sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
4799 auth_res = sofia_reg_parse_auth(profile, authorization, sip, de,
4800 (char *) sip->sip_request->rq_method_name, key, keylen, network_ip, network_port, NULL((void*)0), 0,
4801 REG_INVITE, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0));
4802 } else if ( sofia_reg_handle_register(nua, profile, nh, sip, de, REG_INVITE, key, (uint32_t)keylen, &v_event, NULL, NULL, NULL)sofia_reg_handle_register_token(nua, profile, nh, sip, de, REG_INVITE
, key, (uint32_t)keylen, &v_event, ((void*)0), ((void*)0)
, ((void*)0), ((void*)0))
) {
4803 if (v_event) {
4804 switch_event_destroy(&v_event);
4805 }
4806
4807 goto end;
4808 }
4809
4810 if ((auth_res != AUTH_OK && auth_res != AUTH_RENEWED)) {
4811 nua_respond(nh, SIP_401_UNAUTHORIZED401, sip_401_Unauthorized, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
4812 goto end;
4813 }
4814
4815 if (channel) {
4816 switch_channel_set_variable(channel, "sip_authorized", "true")switch_channel_set_variable_var_check(channel, "sip_authorized"
, "true", SWITCH_TRUE)
;
4817 }
4818 }
4819
4820 if ((us = sofia_glue_get_unknown_header(sip, "X-FS-Sending-Message")) && !strcmp(us, switch_core_get_uuid())) {
4821 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 4821, ((void*)0)
, SWITCH_LOG_WARNING, "Not sending message to ourselves!\n");
4822 nua_respond(nh, SIP_503_SERVICE_UNAVAILABLE503, sip_503_Service_unavailable, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
4823 return;
4824 }
4825
4826 if (sip->sip_content_type && sip->sip_content_type->c_subtype) {
4827 if (strstr(sip->sip_content_type->c_subtype, "composing")) {
4828 goto end;
4829 }
4830 }
4831
4832
4833 sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
4834
4835
4836 if (from) {
4837 from_user = from->a_url->url_user;
4838 from_host = from->a_url->url_host;
4839 }
4840
4841 if (to) {
4842 to_user = to->a_url->url_user;
4843 to_host = to->a_url->url_host;
4844 }
4845
4846 if (!to_user) {
4847 goto end;
4848 }
4849
4850 if (payload) {
4851 msg = payload->pl_data;
4852 }
4853
4854 if (nh) {
4855 char hash_key[512];
4856 private_object_t *tech_pvt;
4857 switch_event_t *event, *event_dup;
4858 char *to_addr;
4859 char *from_addr;
4860 char *p;
4861 char *full_from;
4862 char proto[512] = SOFIA_CHAT_PROTO"sip";
4863 sip_unknown_t *un;
4864 int first_history_info = 1;
4865
4866 full_from = sip_header_as_string(nua_handle_get_home(nh), (void *) sip->sip_from);
4867
4868 if ((p = strchr(to_user, '+')) && p != to_user) {
4869 switch_copy_string(proto, to_user, sizeof(proto));
4870 p = strchr(proto, '+');
4871 *p++ = '\0';
4872
4873 if ((to_addr = strdup(p))) {
4874 if ((p = strchr(to_addr, '+'))) {
4875 *p = '@';
4876 }
4877 }
4878 } else {
4879 to_addr = switch_mprintf("%s@%s", to_user, to_host);
4880 }
4881
4882 from_addr = switch_mprintf("%s@%s", from_user, from_host);
4883
4884 if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT)((profile)->pflags[PFLAG_IN_DIALOG_CHAT] ? 1 : 0)) {
4885 sofia_presence_set_hash_key(hash_key, sizeof(hash_key), sip);
4886 }
4887
4888 if (switch_event_create(&event, SWITCH_EVENT_MESSAGE)switch_event_create_subclass_detailed("sofia_presence.c", (const
char * )(const char *)__func__, 4888, &event, SWITCH_EVENT_MESSAGE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
4889 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
4890 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO"sip");
4891
4892 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_proto", proto);
4893
4894 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", from_addr);
4895 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", from_user);
4896 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_host", from_host);
4897 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_user", to_user);
4898 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_host", to_host);
4899 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_sip_ip", network_ip);
4900 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from_sip_port", "%d", network_port);
4901 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to_addr);
4902 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE");
4903 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "context", profile->context);
4904
4905 if (sip->sip_content_type && sip->sip_content_type->c_subtype) {
4906 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", sip->sip_content_type->c_type);
4907 } else {
4908 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "text/plain");
4909 }
4910
4911 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_full", full_from);
4912 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
4913
4914
4915 if (sip->sip_call_info) {
4916 sip_call_info_t *call_info = sip->sip_call_info;
4917 char *ci = sip_header_as_string(nua_handle_home(nh)((su_home_t *)(nh)), (void *) call_info);
4918 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_call_info", ci);
4919 }
4920
4921 /* Loop thru unknown Headers Here so we can do something with them */
4922 for (un = sip->sip_unknown; un; un = un->un_next) {
4923 if (!strncasecmp(un->un_name, "Diversion", 9)) {
4924 /* Basic Diversion Support for Diversion Indication in SIP */
4925 /* draft-levy-sip-diversion-08 */
4926 if (!zstr(un->un_value)_zstr(un->un_value)) {
4927 char *tmp_name;
4928 if ((tmp_name = switch_mprintf("%s%s", SOFIA_SIP_HEADER_PREFIX"sip_h_", un->un_name))) {
4929 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, tmp_name, un->un_value);
4930 free(tmp_name);
4931 }
4932 }
4933 } else if (!strncasecmp(un->un_name, "History-Info", 12)) {
4934 if (first_history_info) {
4935 /* If the header exists first time, make sure to remove old info and re-set the variable */
4936 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_history_info", un->un_value);
4937 first_history_info = 0;
4938 } else {
4939 /* Append the History-Info into one long string */
4940 const char *history_var = switch_event_get_header(event, "sip_history_info")switch_event_get_header_idx(event, "sip_history_info", -1);
4941 if (!zstr(history_var)_zstr(history_var)) {
4942 char *tmp_str;
4943 if ((tmp_str = switch_mprintf("%s, %s", history_var, un->un_value))) {
4944 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_history_info", tmp_str);
4945 free(tmp_str);
4946 } else {
4947 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_history_info", un->un_value);
4948 }
4949 } else {
4950 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_history_info", un->un_value);
4951 }
4952 }
4953 } else if (!strcasecmp(un->un_name, "Geolocation")) {
4954 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_geolocation", un->un_value);
4955 } else if (!strcasecmp(un->un_name, "Geolocation-Error")) {
4956 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_geolocation_error", un->un_value);
4957 } else if (!strncasecmp(un->un_name, "X-", 2) || !strncasecmp(un->un_name, "P-", 2) || !strcasecmp(un->un_name, "User-to-User")) {
4958 if (!zstr(un->un_value)_zstr(un->un_value)) {
4959 char new_name[512] = "";
4960 int reps = 0;
4961 for (;;) {
4962 char postfix[25] = "";
4963 if (reps > 0) {
4964 switch_snprintf(postfix, sizeof(postfix), "-%d", reps);
4965 }
4966 reps++;
4967 switch_snprintf(new_name, sizeof(new_name), "%s%s%s", SOFIA_SIP_HEADER_PREFIX"sip_h_", un->un_name, postfix);
4968
4969 if (switch_event_get_header(event, new_name)switch_event_get_header_idx(event, new_name, -1)) {
4970 continue;
4971 }
4972
4973 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, new_name, un->un_value);
4974 break;
4975 }
4976 }
4977 }
4978 }
4979
4980 if (msg) {
4981 switch_event_add_body(event, "%s", msg);
4982 }
4983
4984 if (channel) {
4985 switch_channel_event_set_data(channel, event);
4986 }
4987
4988
4989 if (sofia_test_pflag(profile, PFLAG_FIRE_MESSAGE_EVENTS)((profile)->pflags[PFLAG_FIRE_MESSAGE_EVENTS] ? 1 : 0)) {
4990 if (switch_event_dup(&event_dup, event) == SWITCH_STATUS_SUCCESS) {
4991 event_dup->event_id = SWITCH_EVENT_RECV_MESSAGE;
4992 event_dup->flags |= EF_UNIQ_HEADERS;
4993 switch_event_add_header_string(event_dup, SWITCH_STACK_BOTTOM, "Event-Name", switch_event_name(event_dup->event_id));
4994 switch_event_fire(&event_dup)switch_event_fire_detailed("sofia_presence.c", (const char * )
(const char *)__func__, 4994, &event_dup, ((void*)0))
;
4995 }
4996 }
4997
4998 if (session) {
4999 if (switch_event_dup(&event_dup, event) == SWITCH_STATUS_SUCCESS) {
5000 switch_core_session_queue_event(session, &event_dup);
5001 }
5002 }
5003
5004
5005 } else {
5006 abort();
5007 }
5008
5009 if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT)((profile)->pflags[PFLAG_IN_DIALOG_CHAT] ? 1 : 0) && (tech_pvt = (private_object_t *) switch_core_hash_find_locked(profile->chat_hash, hash_key, profile->flag_mutex))) {
5010 switch_core_session_queue_event(tech_pvt->session, &event);
5011 } else {
5012 switch_core_chat_send(proto, event);
5013 switch_event_destroy(&event);
5014 }
5015
5016 switch_safe_free(to_addr)if (to_addr) {free(to_addr);to_addr=((void*)0);};
5017 switch_safe_free(from_addr)if (from_addr) {free(from_addr);from_addr=((void*)0);};
5018
5019 if (full_from) {
5020 su_free(nua_handle_get_home(nh), full_from);
5021 }
5022 }
5023 }
5024
5025 end:
5026
5027 if (sofia_test_pflag(profile, PFLAG_MESSAGES_RESPOND_200_OK)((profile)->pflags[PFLAG_MESSAGES_RESPOND_200_OK] ? 1 : 0)) {
5028 nua_respond(nh, SIP_200_OK200, sip_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
5029 } else {
5030 nua_respond(nh, SIP_202_ACCEPTED202, sip_202_Accepted, NUTAG_WITH_THIS_MSG(de->data->e_msg)nutag_with, tag_ptr_v(de->data->e_msg), TAG_END()(tag_type_t)0, (tag_value_t)0);
5031 }
5032
5033}
5034
5035void sofia_presence_set_chat_hash(private_object_t *tech_pvt, sip_t const *sip)
5036{
5037 char hash_key[256] = "";
5038 char buf[512];
5039 su_home_t *home = NULL((void*)0);
5040
5041 if (!tech_pvt || tech_pvt->hash_key || !sip || !sip->sip_from || !sip->sip_from->a_url->url_user || !sip->sip_from->a_url->url_host) {
5042 return;
5043 }
5044
5045 if (sofia_reg_find_reg_url(tech_pvt->profile, sip->sip_from->a_url->url_user, sip->sip_from->a_url->url_host, buf, sizeof(buf))) {
5046 home = su_home_new(sizeof(*home));
5047 switch_assert(home != NULL)((home != ((void*)0)) ? (void) (0) : __assert_fail ("home != ((void*)0)"
, "sofia_presence.c", 5047, __extension__ __PRETTY_FUNCTION__
))
;
5048 tech_pvt->chat_from = sip_header_as_string(home, (const sip_header_t *) sip->sip_to);
5049 tech_pvt->chat_to = switch_core_session_strdup(tech_pvt->session, buf)switch_core_perform_session_strdup(tech_pvt->session, buf,
"sofia_presence.c", (const char *)__func__, 5049)
;
5050 sofia_presence_set_hash_key(hash_key, sizeof(hash_key), sip);
5051 su_home_unref(home);
5052 home = NULL((void*)0);
5053 } else {
5054 return;
5055 }
5056
5057 switch_mutex_lock(tech_pvt->profile->flag_mutex);
5058 tech_pvt->hash_key = switch_core_session_strdup(tech_pvt->session, hash_key)switch_core_perform_session_strdup(tech_pvt->session, hash_key
, "sofia_presence.c", (const char *)__func__, 5058)
;
5059 switch_core_hash_insert(tech_pvt->profile->chat_hash, tech_pvt->hash_key, tech_pvt)switch_core_hash_insert_destructor(tech_pvt->profile->chat_hash
, tech_pvt->hash_key, tech_pvt, ((void*)0))
;
5060 switch_mutex_unlock(tech_pvt->profile->flag_mutex);
5061}
5062
5063
5064void sofia_presence_check_subscriptions(sofia_profile_t *profile, time_t now)
5065{
5066 char *sql;
5067
5068 if (now) {
5069 struct pres_sql_cb cb = {profile, 0};
5070
5071 if (profile->pres_type != PRES_TYPE_FULL) {
5072 if (mod_sofia_globals.debug_presence > 0) {
5073 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 5073, ((void*)0)
, SWITCH_LOG_WARNING, "check_subs: %s is passive, skipping\n", (char *) profile->name);
5074 }
5075 return;
5076 }
5077
5078 sql = switch_mprintf("update sip_subscriptions set version=version+1 where "
5079 "((expires > 0 and expires <= %ld)) and profile_name='%q' and hostname='%q'",
5080 (long) now, profile->name, mod_sofia_globals.hostname);
5081
5082 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
5083 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
5084
5085 sql = switch_mprintf("select full_to, full_from, contact, -1, call_id, event, network_ip, network_port, "
5086 "NULL as ct, NULL as pt "
5087 " from sip_subscriptions where ((expires > 0 and expires <= %ld)) and profile_name='%q' and hostname='%q'",
5088 (long) now, profile->name, mod_sofia_globals.hostname);
5089
5090 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_presence_send_sql, &cb);
5091 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
5092
5093 if (cb.ttl) {
5094 sql = switch_mprintf("delete from sip_subscriptions where ((expires > 0 and expires <= %ld)) "
5095 "and profile_name='%q' and hostname='%q'",
5096 (long) now, profile->name, mod_sofia_globals.hostname);
5097
5098 if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) {
5099 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "sofia_presence.c", (const char *)__func__
, 5099, ((void*)0)
, SWITCH_LOG_ERROR,
5100 "sub del sql: %s\n", sql);
5101 }
5102
5103 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
5104 }
5105 }
5106
5107
5108
5109}
5110
5111
5112/* For Emacs:
5113 * Local Variables:
5114 * mode:c
5115 * indent-tabs-mode:t
5116 * tab-width:4
5117 * c-basic-offset:4
5118 * End:
5119 * For VIM:
5120 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
5121 */