static inline int create_headers(struct watcher* _w, str *dst, str *content_type) { dstring_t buf; time_t t; int err = 0; dstr_init(&buf, 256); str_clear(dst); /* required by RFC 3261 */ dstr_append_zt(&buf, "Max-Forwards: 70\r\n"); /* Event header */ dstr_append_zt(&buf, "Event: "); dstr_append_zt(&buf, event_package2str(_w->event_package)); dstr_append_zt(&buf, "\r\n"); /* Content-Type header */ /* content types can have dynamical parameters (multipart/related) * => don't generate them "staticaly"; use values created in the * time of document creation */ if (!is_str_empty(content_type)) { /* documents without body doesn't need it */ dstr_append_zt(&buf, "Content-Type: "); dstr_append_str(&buf, content_type); dstr_append_zt(&buf, "\r\n"); } /* Contact header */ if (is_str_empty(&_w->server_contact)) { LOG(L_WARN, "add_contact_hf(): Can't add empty contact to NOTIFY.\n"); } else { dstr_append_zt(&buf, "Contact: "); dstr_append_str(&buf, &_w->server_contact); dstr_append_zt(&buf, "\r\n"); } /* Subscription-State header */ if (_w->expires) t = _w->expires - time(0); else t = 0; if (add_subs_state_hf(&buf, _w->status, t) < 0) { LOG(L_ERR, "create_headers(): Error while adding Subscription-State\n"); dstr_destroy(&buf); return -3; } err = dstr_get_str(&buf, dst); dstr_destroy(&buf); return err; }
static int prepare_winfo_notify(struct retr_buf **dst, struct presentity* _p, struct watcher* _w, pa_notify_cb_param_t *cbd) { str doc = STR_NULL; str content_type = STR_NULL; str headers = STR_NULL; int res = 0; str body = STR_STATIC_INIT(""); uac_req_t uac_r; switch (_w->preferred_mimetype) { case DOC_WINFO: create_winfo_document(_p, _w, &doc, &content_type); DEBUG("winfo document created\n"); break; /* other formats ? */ default: ERR("unknow doctype\n"); return -1; } if (create_headers(_w, &headers, &content_type) < 0) { ERR("Error while adding headers\n"); str_free_content(&doc); str_free_content(&content_type); return -7; } if (!is_str_empty(&doc)) body = doc; /* res = tmb.t_request_within(¬ify, &headers, &body, _w->dialog, 0, 0); */ set_uac_req(&uac_r, ¬ify, &headers, &body, _w->dialog, TMCB_LOCAL_COMPLETED, pa_notify_cb, cbd ); res = tmb.prepare_request_within(&uac_r, dst); if (res < 0) { ERR("Can't send watcherinfo notification (%d)\n", res); } else { _w->document_index++; /* increment index for next document */ } str_free_content(&doc); str_free_content(&headers); str_free_content(&content_type); return res; }
int send_winfo_notify_offline(struct presentity* _p, struct watcher* _w, offline_winfo_t *info, transaction_cb completion_cb, void* cbp) { str doc = STR_NULL; str content_type = STR_NULL; str headers = STR_NULL; str body = STR_STATIC_INIT(""); uac_req_t uac_r; switch (_w->preferred_mimetype) { case DOC_WINFO: create_winfo_document_offline(_p, _w, info, &doc, &content_type); break; /* other formats ? */ default: ERR("send_winfo_notify: unknow doctype\n"); return -1; } if (create_headers(_w, &headers, &content_type) < 0) { ERR("send_winfo_notify(): Error while adding headers\n"); str_free_content(&doc); str_free_content(&content_type); return -7; } if (!is_str_empty(&doc)) body = doc; set_uac_req(&uac_r, ¬ify, &headers, &body, _w->dialog, TMCB_LOCAL_COMPLETED, completion_cb, cbp ); tmb.t_request_within(&uac_r); str_free_content(&doc); str_free_content(&headers); str_free_content(&content_type); _w->document_index++; /* increment index for next document */ if (use_db) db_update_watcher(_p, _w); /* dialog and index have changed */ return 0; }
static inline int add_cont_type_hf(dstring_t *buf, str *content_type) { /* content types can have dynamical parameters (multipart/related) * => don't generate them "staticaly"; use values created in the * time of document creation */ if (is_str_empty(content_type)) return 0; /* documents without body doesn't need it */ dstr_append_zt(buf, "Content-Type: "); dstr_append_str(buf, content_type); dstr_append_zt(buf, "\r\n"); return 0; }
int preset_dialog_route(dlg_t* dialog, str *route) { rr_t *old_r, *r = NULL; int res; /* check parameters */ if ((!dialog) || (is_str_empty(route))) { ERR("bad parameters\n"); return -1; } if (dialog->state != DLG_NEW) { ERR("Dialog is not in DLG_NEW state\n"); return -1; } if (parse_rr_body(route->s, route->len, &r) < 0) { ERR("can't parse given route\n"); return -1; } if (!r) { ERR("empty route\n"); return -1; } old_r = dialog->route_set; dialog->route_set = NULL; res = shm_duplicate_rr(&dialog->route_set, r); if (r) free_rr(&r); if (res < 0) { /* return old routeset to its place */ dialog->route_set = old_r; ERR("can't duplicate route\n"); return -1; } /* free old route */ if (old_r) shm_free_rr(&old_r); res = tmb.calculate_hooks(dialog); if (res < 0) { ERR("Error while calculating hooks\n"); return -2; } return 0; }
static int rls_generate_notify_ext(rl_subscription_t *s, int full_info) { /* !!! the main mutex must be locked here !!! */ int res; str doc; dstring_t dstr; str headers, content_type; static str method = STR_STATIC_INIT(METHOD_NOTIFY); dlg_t *dlg; int exp_time = 0; char expiration[32]; str body = STR_STATIC_INIT(""); int removed = 0; dlg = s->u.external.dialog; if (!dlg) return -1; DEBUG("generating external notify\n"); str_clear(&doc); str_clear(&content_type); if (sm_subscription_pending(&s->u.external) != 0) { /* create the document only for non-pending subscriptions */ if (create_rlmi_document(&doc, &content_type, s, full_info) != 0) { return -1; } } exp_time = sm_subscription_expires_in(rls_manager, &s->u.external); sprintf(expiration, ";expires=%d\r\n", exp_time); dstr_init(&dstr, 256); dstr_append_zt(&dstr, "Subscription-State: "); switch (s->u.external.status) { case subscription_active: dstr_append_zt(&dstr, "active"); dstr_append_zt(&dstr, expiration); break; case subscription_pending: dstr_append_zt(&dstr, "pending"); dstr_append_zt(&dstr, expiration); break; case subscription_terminated_pending: case subscription_terminated: dstr_append_zt(&dstr, "terminated\r\n"); break; case subscription_terminated_pending_to: case subscription_terminated_to: dstr_append_zt(&dstr, "terminated;reason=timeout\r\n"); break; case subscription_uninitialized: dstr_append_zt(&dstr, "pending\r\n"); /* this is an error ! */ LOG(L_ERR, "sending NOTIFY for an unitialized subscription!\n"); break; } dstr_append_str(&dstr, &s->u.external.contact); /* required by RFC 3261 */ dstr_append_zt(&dstr, "Max-Forwards: 70\r\n"); dstr_append_zt(&dstr, "Event: "); dstr_append_str(&dstr, rls_get_package(s)); dstr_append_zt(&dstr, "\r\n"); dstr_append_zt(&dstr, "Require: eventlist\r\nContent-Type: "); dstr_append_str(&dstr, &content_type); dstr_append_zt(&dstr, "\r\n"); res = dstr_get_str(&dstr, &headers); dstr_destroy(&dstr); if (res >= 0) { /* DEBUG("sending NOTIFY message to %.*s (subscription %p)\n", dlg->rem_uri.len, ZSW(dlg->rem_uri.s), s); */ if (!is_str_empty(&doc)) body = doc; if (sm_subscription_terminated(&s->u.external) == 0) { /* doesn't matter if delivered or not, it will be freed otherwise !!! */ res = tmb.t_request_within(&method, &headers, &body, dlg, 0, 0); if (res >= 0) clear_change_flags(s); } else { rls_notify_cb_param_t *cbd = create_notify_cb_param(s); if (!cbd) { ERR("Can't create notify cb data! Freeing RL subscription.\n"); rls_remove(s); /* ?????? */ removed = 1; res = -13; } else { /* the subscritpion will be destroyed if NOTIFY delivery problems */ /* rls_unlock(); the callback locks this mutex ! */ /* !!!! FIXME: callbacks can't be safely used (may be called or not, * may free memory automaticaly or not) !!! */ res = tmb.t_request_within(&method, &headers, &body, dlg, rls_notify_cb, cbd); /* res = tmb.t_request_within(&method, &headers, &body, dlg, rls_notify_cb, s); */ /* rls_lock(); the callback locks this mutex ! */ if (res < 0) { /* does this mean, that the callback was not called ??? */ ERR("t_request_within FAILED: %d! Freeing RL subscription.\n", res); rls_remove(s); /* ?????? */ removed = 1; } else clear_change_flags(s); } } } if (doc.s) cds_free(doc.s); if (content_type.s) cds_free(content_type.s); if (headers.s) cds_free(headers.s); if ((!removed) && use_db) rls_db_update(s); if (res < 0) DEBUG("external notify NOT generated\n"); else DEBUG("external notify generated\n"); return res; }
static int prepare_presence_notify(struct retr_buf **dst, struct presentity* _p, struct watcher* _w, pa_notify_cb_param_t *cbd) { /* Send a notify, saved Contact will be put in * Request-URI, To will be put in from and new tag * will be generated, callid will be callid, * from will be put in to including tag */ str doc = STR_NULL; str content_type = STR_NULL; str headers = STR_NULL; str body = STR_STATIC_INIT(""); int res = 0; uac_req_t uac_r; switch(_w->preferred_mimetype) { case DOC_XPIDF: res = create_xpidf_document(&_p->data, &doc, &content_type); break; case DOC_LPIDF: res = create_lpidf_document(&_p->data, &doc, &content_type); break; case DOC_CPIM_PIDF: res = create_cpim_pidf_document(&_p->data, &doc, &content_type); break; case DOC_MSRTC_PIDF: case DOC_PIDF: default: res = create_pidf_document(&_p->data, &doc, &content_type); } if (res != 0) { LOG(L_ERR, "can't create presence document (%d)\n", _w->preferred_mimetype); return -2; } if (create_headers(_w, &headers, &content_type) < 0) { LOG(L_ERR, "send_presence_notify(): Error while adding headers\n"); str_free_content(&doc); str_free_content(&content_type); return -7; } if (!is_str_empty(&doc)) body = doc; /* res = tmb.t_request_within(¬ify, &headers, &body, _w->dialog, pa_notify_cb, cbd);*/ set_uac_req(&uac_r, ¬ify, &headers, &body, _w->dialog, TMCB_LOCAL_COMPLETED, pa_notify_cb, cbd ); res = tmb.prepare_request_within(&uac_r, dst); if (res < 0) { ERR("Can't send NOTIFY (%d) in dlg %.*s, %.*s, %.*s\n", res, FMT_STR(_w->dialog->id.call_id), FMT_STR(_w->dialog->id.rem_tag), FMT_STR(_w->dialog->id.loc_tag)); } str_free_content(&doc); str_free_content(&headers); str_free_content(&content_type); return res; }