#include "rlmi_doc.h" #include "result_codes.h" #include <cds/dstring.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "../../mem/mem.h" #include "../../mem/shm_mem.h" #include "../../str.h" static void add_virtual_subscriptions_to_rlmi(dstring_t *doc, rl_subscription_t *s, const char *part_id) { int i, j, ncnt, cnt; virtual_subscription_t *vs; vs_display_name_t dn; char tmp[32]; /* add all list elements */ cnt = ptr_vector_size(&s->vs); for (i = 0; i < cnt; i++) { vs = ptr_vector_get(&s->vs, i); if (!vs) continue; dstr_append_zt(doc, "\t<resource uri=\""); dstr_append_str(doc, &vs->uri); dstr_append_zt(doc, "\">\r\n"); /* add display names */ ncnt = vector_size(&vs->display_names); for (j = 0; j < ncnt; j++) { if (vector_get(&vs->display_names, j, &dn) != 0) continue; if (dn.lang.len > 0) { dstr_append_zt(doc, "\t\t<name language=\""); dstr_append_str(doc, &dn.lang); dstr_append_zt(doc, "\">"); } else dstr_append_zt(doc, "\t\t<name>"); dstr_append_str(doc, &dn.name); dstr_append_zt(doc, "</name>\r\n"); } sprintf(tmp, "vs%di%d", i, 1); dstr_append_zt(doc, "\t\t<instance id=\""); dstr_append_zt(doc, tmp); dstr_append_zt(doc, "\" state=\""); switch (vs->status) { case subscription_active: dstr_append_zt(doc, "active\""); break; case subscription_pending: dstr_append_zt(doc, "pending\""); break; case subscription_terminated_pending: case subscription_terminated: dstr_append_zt(doc, "terminated\" reason=\"closed\""); break; case subscription_terminated_pending_to: case subscription_terminated_to: dstr_append_zt(doc, "terminated\" reason=\"timeout\""); break; case subscription_uninitialized: dstr_append_zt(doc, "pending\""); /* this is an error ! */ LOG(L_ERR, "generating RLMI for an unitialized virtual subscription!\n"); break; } if (vs->state_document.len > 0) { sprintf(tmp, "%d", i); dstr_append_zt(doc, " cid=\""); dstr_append_zt(doc, part_id); dstr_append_zt(doc, tmp); dstr_append_zt(doc, "\"/>\r\n"); } else dstr_append_zt(doc, "/>\r\n"); dstr_append_zt(doc, "\t</resource>\r\n"); } } static void add_virtual_subscriptions_documents(dstring_t *doc, rl_subscription_t *s, const char *boundary_str, const char *part_id) { int i, cnt; virtual_subscription_t *vs; char tmp[32]; /* add all list elements */ cnt = ptr_vector_size(&s->vs); for (i = 0; i < cnt; i++) { vs = ptr_vector_get(&s->vs, i); if (!vs) continue; if (vs->state_document.len < 1) { vs = vs->next; continue; } if (vs->content_type.len < 1) { LOG(L_ERR, "can't send resource status document for unknown type\n"); vs = vs->next; continue; } dstr_append(doc, "--", 2); dstr_append_zt(doc, boundary_str); dstr_append(doc, "\r\n", 2); sprintf(tmp, "%d", i); dstr_append_zt(doc, "Content-Transfer-Encoding: binary\r\nContent-ID: "); dstr_append_zt(doc, part_id); dstr_append_zt(doc, tmp); dstr_append_zt(doc, "\r\nContent-Type: "); dstr_append_str(doc, &vs->content_type); dstr_append_zt(doc, "\r\n\r\n"); dstr_append_str(doc, &vs->state_document); dstr_append(doc, "\r\n", 2); dstr_append(doc, "\r\n", 2); } } int create_rlmi_document(str *dst, str *content_type_dst, rl_subscription_t *s, int full_info) { dstring_t doc, cont; char tmp[32]; char start_str[64]; char boundary_str[64]; char part_id[64]; if ((!s) || (!dst) || (!content_type_dst)) return RES_INTERNAL_ERR; sprintf(start_str, "qwW%dpPdxX%d", rand(), rand()); sprintf(boundary_str, "RewXdpxR%dxA%d", rand(), rand()); sprintf(part_id, "id%di%dx", rand(), rand()); /* --- build NOTIFY body --- */ dstr_init(&doc, 256); dstr_append(&doc, "--", 2); dstr_append_zt(&doc, boundary_str); dstr_append(&doc, "\r\n", 2); dstr_append_zt(&doc, "Content-Transfer-Encoding: binary\r\n" "Content-ID: "); dstr_append_zt(&doc, start_str); dstr_append_zt(&doc, "\r\n"); dstr_append_zt(&doc, "Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n"); dstr_append(&doc, "\r\n", 2); /* -- RLMI document -- */ dstr_append_zt(&doc, "<?xml version=\"1.0\"?>\r\n" "<list xmlns=\"urn:ietf:params:xml:ns:rlmi\" " "uri=\""); dstr_append_str(&doc, rls_get_uri(s)); dstr_append_zt(&doc, "\" version=\""); sprintf(tmp, "%d", s->doc_version); dstr_append_zt(&doc, tmp); dstr_append_zt(&doc, "\" fullState=\"true\">\r\n"); /* FIXME: as soon as will be finished partial notification document * if (full_info) dstr_append_zt(&doc, "\" fullState=\"true\">\r\n"); else dstr_append_zt(&doc, "\" fullState=\"false\">\r\n"); */ /* add all virtual subscriptions to the RLMI document */ add_virtual_subscriptions_to_rlmi(&doc, s, part_id); dstr_append_zt(&doc, "</list>\r\n\r\n"); /* add all virtual subscriptions status documents */ add_virtual_subscriptions_documents(&doc, s, boundary_str, part_id); dstr_append(&doc, "--", 2); dstr_append_zt(&doc, boundary_str); dstr_append(&doc, "--\r\n", 4); dstr_append(&doc, "\r\n", 2); /* --- build content type --- */ dstr_init(&cont, 256); dstr_append_zt(&cont, "multipart/related;type=\"application/rlmi+xml\";" "start=\""); dstr_append_zt(&cont, start_str); dstr_append_zt(&cont, "\";boundary=\""); dstr_append_zt(&cont, boundary_str); dstr_append_zt(&cont, "\";"); /* --- store output strings --- */ dstr_get_str(&doc, dst); dstr_destroy(&doc); dstr_get_str(&cont, content_type_dst); dstr_destroy(&cont); /* increment version for next NOTIFY document */ s->doc_version++; return RES_OK; }