rlmi_doc.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #include "rlmi_doc.h"
  2. #include "result_codes.h"
  3. #include <cds/dstring.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "../../mem/mem.h"
  8. #include "../../mem/shm_mem.h"
  9. #include "../../str.h"
  10. static void add_virtual_subscriptions_to_rlmi(dstring_t *doc, rl_subscription_t *s, const char *part_id)
  11. {
  12. int i, j, ncnt, cnt;
  13. virtual_subscription_t *vs;
  14. vs_display_name_t dn;
  15. char tmp[32];
  16. /* add all list elements */
  17. cnt = ptr_vector_size(&s->vs);
  18. for (i = 0; i < cnt; i++) {
  19. vs = ptr_vector_get(&s->vs, i);
  20. if (!vs) continue;
  21. dstr_append_zt(doc, "\t<resource uri=\"");
  22. dstr_append_str(doc, &vs->uri);
  23. dstr_append_zt(doc, "\">\r\n");
  24. /* add display names */
  25. ncnt = vector_size(&vs->display_names);
  26. for (j = 0; j < ncnt; j++) {
  27. if (vector_get(&vs->display_names, j, &dn) != 0) continue;
  28. if (dn.lang.len > 0) {
  29. dstr_append_zt(doc, "\t\t<name language=\"");
  30. dstr_append_str(doc, &dn.lang);
  31. dstr_append_zt(doc, "\">");
  32. }
  33. else dstr_append_zt(doc, "\t\t<name>");
  34. dstr_append_str(doc, &dn.name);
  35. dstr_append_zt(doc, "</name>\r\n");
  36. }
  37. sprintf(tmp, "vs%di%d", i, 1);
  38. dstr_append_zt(doc, "\t\t<instance id=\"");
  39. dstr_append_zt(doc, tmp);
  40. dstr_append_zt(doc, "\" state=\"");
  41. switch (vs->status) {
  42. case subscription_active:
  43. dstr_append_zt(doc, "active\"");
  44. break;
  45. case subscription_pending:
  46. dstr_append_zt(doc, "pending\"");
  47. break;
  48. case subscription_terminated_pending:
  49. case subscription_terminated:
  50. dstr_append_zt(doc, "terminated\" reason=\"closed\"");
  51. break;
  52. case subscription_terminated_pending_to:
  53. case subscription_terminated_to:
  54. dstr_append_zt(doc,
  55. "terminated\" reason=\"timeout\"");
  56. break;
  57. case subscription_uninitialized:
  58. dstr_append_zt(doc, "pending\"");
  59. /* this is an error ! */
  60. LOG(L_ERR, "generating RLMI for an unitialized virtual subscription!\n");
  61. break;
  62. }
  63. if (vs->state_document.len > 0) {
  64. sprintf(tmp, "%d", i);
  65. dstr_append_zt(doc, " cid=\"");
  66. dstr_append_zt(doc, part_id);
  67. dstr_append_zt(doc, tmp);
  68. dstr_append_zt(doc, "\"/>\r\n");
  69. }
  70. else dstr_append_zt(doc, "/>\r\n");
  71. dstr_append_zt(doc, "\t</resource>\r\n");
  72. }
  73. }
  74. static void add_virtual_subscriptions_documents(dstring_t *doc,
  75. rl_subscription_t *s, const char *boundary_str, const char *part_id)
  76. {
  77. int i, cnt;
  78. virtual_subscription_t *vs;
  79. char tmp[32];
  80. /* add all list elements */
  81. cnt = ptr_vector_size(&s->vs);
  82. for (i = 0; i < cnt; i++) {
  83. vs = ptr_vector_get(&s->vs, i);
  84. if (!vs) continue;
  85. if (vs->state_document.len < 1) {
  86. vs = vs->next;
  87. continue;
  88. }
  89. if (vs->content_type.len < 1) {
  90. LOG(L_ERR, "can't send resource status document for unknown type\n");
  91. vs = vs->next;
  92. continue;
  93. }
  94. dstr_append(doc, "--", 2);
  95. dstr_append_zt(doc, boundary_str);
  96. dstr_append(doc, "\r\n", 2);
  97. sprintf(tmp, "%d", i);
  98. dstr_append_zt(doc, "Content-Transfer-Encoding: binary\r\nContent-ID: ");
  99. dstr_append_zt(doc, part_id);
  100. dstr_append_zt(doc, tmp);
  101. dstr_append_zt(doc, "\r\nContent-Type: ");
  102. dstr_append_str(doc, &vs->content_type);
  103. dstr_append_zt(doc, "\r\n\r\n");
  104. dstr_append_str(doc, &vs->state_document);
  105. dstr_append(doc, "\r\n", 2);
  106. dstr_append(doc, "\r\n", 2);
  107. }
  108. }
  109. int create_rlmi_document(str *dst, str *content_type_dst, rl_subscription_t *s, int full_info)
  110. {
  111. dstring_t doc, cont;
  112. char tmp[32];
  113. char start_str[64];
  114. char boundary_str[64];
  115. char part_id[64];
  116. if ((!s) || (!dst) || (!content_type_dst)) return RES_INTERNAL_ERR;
  117. sprintf(start_str, "qwW%dpPdxX%d", rand(), rand());
  118. sprintf(boundary_str, "RewXdpxR%dxA%d", rand(), rand());
  119. sprintf(part_id, "id%di%dx", rand(), rand());
  120. /* --- build NOTIFY body --- */
  121. dstr_init(&doc, 256);
  122. dstr_append(&doc, "--", 2);
  123. dstr_append_zt(&doc, boundary_str);
  124. dstr_append(&doc, "\r\n", 2);
  125. dstr_append_zt(&doc,
  126. "Content-Transfer-Encoding: binary\r\n"
  127. "Content-ID: ");
  128. dstr_append_zt(&doc, start_str);
  129. dstr_append_zt(&doc, "\r\n");
  130. dstr_append_zt(&doc,
  131. "Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n");
  132. dstr_append(&doc, "\r\n", 2);
  133. /* -- RLMI document -- */
  134. dstr_append_zt(&doc,
  135. "<?xml version=\"1.0\"?>\r\n"
  136. "<list xmlns=\"urn:ietf:params:xml:ns:rlmi\" "
  137. "uri=\"");
  138. dstr_append_str(&doc, rls_get_uri(s));
  139. dstr_append_zt(&doc, "\" version=\"");
  140. sprintf(tmp, "%d", s->doc_version);
  141. dstr_append_zt(&doc, tmp);
  142. dstr_append_zt(&doc, "\" fullState=\"true\">\r\n");
  143. /* FIXME: as soon as will be finished partial notification document
  144. * if (full_info) dstr_append_zt(&doc, "\" fullState=\"true\">\r\n");
  145. else dstr_append_zt(&doc, "\" fullState=\"false\">\r\n");
  146. */
  147. /* add all virtual subscriptions to the RLMI document */
  148. add_virtual_subscriptions_to_rlmi(&doc, s, part_id);
  149. dstr_append_zt(&doc, "</list>\r\n\r\n");
  150. /* add all virtual subscriptions status documents */
  151. add_virtual_subscriptions_documents(&doc, s, boundary_str, part_id);
  152. dstr_append(&doc, "--", 2);
  153. dstr_append_zt(&doc, boundary_str);
  154. dstr_append(&doc, "--\r\n", 4);
  155. dstr_append(&doc, "\r\n", 2);
  156. /* --- build content type --- */
  157. dstr_init(&cont, 256);
  158. dstr_append_zt(&cont,
  159. "multipart/related;type=\"application/rlmi+xml\";"
  160. "start=\"");
  161. dstr_append_zt(&cont, start_str);
  162. dstr_append_zt(&cont, "\";boundary=\"");
  163. dstr_append_zt(&cont, boundary_str);
  164. dstr_append_zt(&cont, "\";");
  165. /* --- store output strings --- */
  166. dstr_get_str(&doc, dst);
  167. dstr_destroy(&doc);
  168. dstr_get_str(&cont, content_type_dst);
  169. dstr_destroy(&cont);
  170. /* increment version for next NOTIFY document */
  171. s->doc_version++;
  172. return RES_OK;
  173. }