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; }
char *xcap_uri_for_rls_resource(const str_t *xcap_root, const str_t *uri) { dstring_t s; int l; str_t c_uri; char *dst = NULL; if (!xcap_root) return NULL; dstr_init(&s, 2 * xcap_root->len + 32); dstr_append_str(&s, xcap_root); if (xcap_root->s[xcap_root->len - 1] != '/') dstr_append(&s, "/", 1); dstr_append_zt(&s, "rls-services/global/index/~~/rls-services/service[@uri=%22"); canonicalize_uri(uri, &c_uri); dstr_append_str(&s, &c_uri); if (c_uri.s) cds_free(c_uri.s); dstr_append_zt(&s, "%22]"); l = dstr_get_data_length(&s); if (l > 0) { dst = (char *)cds_malloc(l + 1); if (dst) { dstr_get_data(&s, dst); dst[l] = 0; } } dstr_destroy(&s); return dst; }
int create_lpidf_document(presentity_info_t *p, str_t *dst, str_t *dst_content_type) { dstring_t buf; int err; if (!dst) return -1; str_clear(dst); if (dst_content_type) str_clear(dst_content_type); if (!p) return -1; if (dst_content_type) { if (str_dup_zt(dst_content_type, "text/lpidf") < 0) { return -1; } } /* if (!p->first_tuple) return 0;*/ /* no tuples => nothing to say */ dstr_init(&buf, 2048); doc_add_presentity(&buf, p); err = dstr_get_str(&buf, dst); dstr_destroy(&buf); if (err != 0) { str_free_content(dst); if (dst_content_type) str_free_content(dst_content_type); } return err; }
char *xcap_uri_for_rls_services(const str_t *xcap_root) { dstring_t s; int l; char *dst = NULL; if (!xcap_root) return NULL; dstr_init(&s, 2 * xcap_root->len + 32); dstr_append_str(&s, xcap_root); if (xcap_root->s[xcap_root->len - 1] != '/') dstr_append(&s, "/", 1); dstr_append_zt(&s, "rls-services/global/index"); l = dstr_get_data_length(&s); if (l > 0) { dst = (char *)cds_malloc(l + 1); if (dst) { dstr_get_data(&s, dst); dst[l] = 0; } } dstr_destroy(&s); return dst; }
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; }
int xcap_query_impl(const char *uri, xcap_query_params_t *params, char **buf, int *bsize) { CURLcode res = -1; static CURL *handle = NULL; dstring_t data; char *auth = NULL; int i; long auth_methods; if (!uri) { ERR("BUG: no uri given\n"); return -1; } if (!buf) { ERR("BUG: no buf given\n"); return -1; } i = 0; if (params) { i += params->auth_user.len; i += params->auth_pass.len; } if (i > 0) { /* do authentication */ auth = (char *)cds_malloc_pkg(i + 2); if (!auth) return -1; sprintf(auth, "%.*s:%.*s", FMT_STR(params->auth_user), FMT_STR(params->auth_pass)); } auth_methods = CURLAUTH_BASIC | CURLAUTH_DIGEST; dstr_init(&data, 512); if (!handle) handle = curl_easy_init(); if (handle) { curl_easy_setopt(handle, CURLOPT_URL, uri); /* TRACE_LOG("uri: %s\n", uri ? uri : "<null>"); */ /* do not store data into a file - store them in memory */ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data_func); curl_easy_setopt(handle, CURLOPT_WRITEDATA, &data); /* be quiet */ #ifdef CURLOPT_MUTE curl_easy_setopt(handle, CURLOPT_MUTE, 1); #endif /* CURLOPT_MUTE */ /* non-2xx => error */ curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1); /* auth */ curl_easy_setopt(handle, CURLOPT_HTTPAUTH, auth_methods); /* TODO possibility of selection */ curl_easy_setopt(handle, CURLOPT_NETRC, CURL_NETRC_IGNORED); curl_easy_setopt(handle, CURLOPT_USERPWD, auth); /* SSL */ if (params) { if (params->enable_unverified_ssl_peer) { curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0); } } /* follow redirects (needed for apache mod_speling - case insesitive names) */ curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1); /* curl_easy_setopt(handle, CURLOPT_TCP_NODELAY, 1); curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, 10);*/ /* Accept headers */ res = curl_easy_perform(handle); /* curl_easy_cleanup(handle); */ /* FIXME: experimental */ } else ERROR_LOG("can't initialize curl handle\n"); if (res == 0) { *bsize = dstr_get_data_length(&data); if (*bsize) { *buf = (char*)cds_malloc(*bsize); if (!*buf) { ERROR_LOG("can't allocate %d bytes\n", *bsize); res = -1; *bsize = 0; } else dstr_get_data(&data, *buf); } } else DBG("curl error: %d\n", res); /* see curl/curl.h for possible values*/ dstr_destroy(&data); if (auth) cds_free_pkg(auth); return res; }
void destroy_sstream(sstream_t *ss) { if (ss->type == sstream_out) dstr_destroy(&ss->out); }