File: | src/mod/endpoints/mod_sofia/sofia_presence.c |
Warning: | line 562, column 30 Null pointer passed as an argument to a 'nonnull' parameter |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||
42 | struct state_helper { | |||
43 | switch_hash_t *hash; | |||
44 | sofia_profile_t *profile; | |||
45 | switch_memory_pool_t *pool; | |||
46 | int total; | |||
47 | }; | |||
48 | ||||
49 | ||||
50 | static int sofia_presence_mwi_callback(void *pArg, int argc, char **argv, char **columnNames); | |||
51 | static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char **columnNames); | |||
52 | static int sofia_presence_sub_reg_callback(void *pArg, int argc, char **argv, char **columnNames); | |||
53 | static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char **columnNames); | |||
54 | static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char **columnNames); | |||
55 | static int broadsoft_sla_gather_state_callback(void *pArg, int argc, char **argv, char **columnNames); | |||
56 | static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char **columnNames); | |||
57 | static 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); | |||
58 | static int sofia_dialog_probe_callback(void *pArg, int argc, char **argv, char **columnNames); | |||
59 | static int sofia_dialog_probe_notify_callback(void *pArg, int argc, char **argv, char **columnNames); | |||
60 | ||||
61 | struct pres_sql_cb { | |||
62 | sofia_profile_t *profile; | |||
63 | int ttl; | |||
64 | }; | |||
65 | ||||
66 | static int sofia_presence_send_sql(void *pArg, int argc, char **argv, char **columnNames); | |||
67 | ||||
68 | struct dialog_helper { | |||
69 | char state[128]; | |||
70 | char status[512]; | |||
71 | char rpid[512]; | |||
72 | char presence_id[1024]; | |||
73 | int hits; | |||
74 | }; | |||
75 | ||||
76 | struct resub_helper { | |||
77 | sofia_profile_t *profile; | |||
78 | switch_event_t *event; | |||
79 | int rowcount; | |||
80 | int noreg; | |||
81 | }; | |||
82 | ||||
83 | struct 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 | ||||
91 | struct 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 | ||||
101 | switch_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 | ||||
410 | void 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 | ||||
455 | char *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 | ||||
478 | struct mwi_helper { | |||
479 | sofia_profile_t *profile; | |||
480 | int total; | |||
481 | }; | |||
482 | ||||
483 | static 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))) { | |||
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 ))) { | |||
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) { | |||
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); | |||
519 | ||||
520 | ||||
521 | if ((pname = switch_event_get_header(event, "sofia-profile")switch_event_get_header_idx(event, "sofia-profile", -1))) { | |||
522 | profile = sofia_glue_find_profile(pname)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__ , 522, pname); | |||
523 | } | |||
524 | ||||
525 | if (!profile) { | |||
526 | if (!host || !(profile = sofia_glue_find_profile(host)sofia_glue_find_profile__("sofia_presence.c", (const char *)__func__ , 526, host))) { | |||
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) { | |||
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))) { | |||
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)) { | |||
| ||||
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 | ||||
634 | static 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 | ||||
680 | static 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 | ||||
827 | static 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 | ||||
948 | static 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 | ||||
1053 | static 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 | ||||
1098 | static 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 | ||||
1587 | static int EVENT_THREAD_RUNNING = 0; | |||
1588 | static int EVENT_THREAD_STARTED = 0; | |||
1589 | ||||
1590 | static 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 | ||||
1601 | void *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) { | |||
| ||||
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) { | |||
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) { | |||
1622 | int count = 0; | |||
1623 | ||||
1624 | if (switch_queue_pop(mod_sofia_globals.presence_queue, &pop) == SWITCH_STATUS_SUCCESS) { | |||
1625 | switch_event_t *event = (switch_event_t *) pop; | |||
1626 | ||||
1627 | if (!pop) { | |||
1628 | break; | |||
1629 | } | |||
1630 | ||||
1631 | if (mod_sofia_globals.presence_flush) { | |||
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) { | |||
1641 | case SWITCH_EVENT_MESSAGE_WAITING: | |||
1642 | actual_sofia_presence_mwi_event_handler(event); | |||
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 | ||||
1673 | void 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 | ||||
1699 | void 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 | ||||
1723 | static 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 | ||||
1767 | static 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 | ||||
1899 | char *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 | ||||
1935 | static 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) | |||
2115 | static 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 | ||||
2137 | uint32_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 | ||||
2165 | static 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 | ||||
2375 | static 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 | ||||
2465 | static 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 | ||||
2501 | static 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 | ||||
2600 | static 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 | ||||
3241 | static 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 | ||||
3297 | static 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 | ||||
3331 | static 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 | ||||
3381 | static 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 | ||||
3485 | static 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 | ||||
3644 | void 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(¶ms, SWITCH_EVENT_NOTIFY)switch_event_create_subclass_detailed("sofia_presence.c", (const char * )(const char *)__func__, 4002, ¶ms, 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(¶ms)switch_event_fire_detailed("sofia_presence.c", (const char * ) (const char *)__func__, 4010, ¶ms, ((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 | ||||
4441 | sofia_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 | ||||
4453 | void 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 | ||||
4520 | static 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 | ||||
4539 | uint32_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 | ||||
4552 | void 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 | ||||
4738 | void 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 | ||||
4745 | void 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 | ||||
5035 | void 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 | ||||
5064 | void 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 | */ |