extra.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * extra.c Handling of extra attributes (adapted from acc module)
  3. *
  4. * Copyright (C) 2004-2006 Voice Sistem SRL
  5. * Copyright (C) 2008 Juha Heinanen <[email protected]>
  6. *
  7. * This file is part of Kamailio, a free SIP server.
  8. *
  9. * Kamailio is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version
  13. *
  14. * Kamailio is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. */
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include "../../mem/mem.h"
  27. #include "../../ut.h"
  28. #include "extra.h"
  29. #define EQUAL '='
  30. #define SEPARATOR ';'
  31. /* here we copy the strings returned by int2str (which uses a static buffer) */
  32. static char int_buf[INT2STR_MAX_LEN*MAX_EXTRA];
  33. static char *static_detector = 0;
  34. /* Initialize extra engine */
  35. void init_extra_engine(void)
  36. {
  37. int i;
  38. /* ugly trick to get the address of the static buffer */
  39. static_detector = int2str( (unsigned long)3, &i) + i;
  40. }
  41. /*
  42. * Parse extra module parameter value to extra_attr list, where each
  43. * element contains name of attribute and pseudo variable specification.
  44. */
  45. struct extra_attr *parse_extra_str(char *extra_str)
  46. {
  47. struct extra_attr *head;
  48. struct extra_attr *tail;
  49. struct extra_attr *extra;
  50. char *foo;
  51. char *s;
  52. int n;
  53. str stmp;
  54. n = 0;
  55. head = 0;
  56. extra = 0;
  57. tail = 0;
  58. s = extra_str;
  59. if (s==0) {
  60. LM_ERR("null string received\n");
  61. goto error;
  62. }
  63. while (*s) {
  64. /* skip white spaces */
  65. while (*s && isspace((int)*s)) s++;
  66. if (*s == 0) goto parse_error;
  67. if (n == MAX_EXTRA) {
  68. LM_ERR("too many extras -> please increase the internal buffer\n");
  69. goto error;
  70. }
  71. extra = (struct extra_attr*)pkg_malloc(sizeof(struct extra_attr));
  72. if (extra == 0) {
  73. LM_ERR("no more pkg memory\n");
  74. goto error;
  75. }
  76. memset( extra, 0, sizeof(struct extra_attr));
  77. /* link the new extra at the end */
  78. if (tail == 0) {
  79. head = extra;
  80. } else {
  81. tail->next = extra;
  82. }
  83. tail = extra;
  84. n++;
  85. /* get name */
  86. foo = s;
  87. while (*s && !isspace((int)*s) && EQUAL != *s) s++;
  88. if (*s == 0) goto parse_error;
  89. if (*s==EQUAL) {
  90. extra->name.len = (s++) - foo;
  91. } else {
  92. extra->name.len = (s++) - foo;
  93. /* skip spaces */
  94. while (*s && isspace((int)*s)) s++;
  95. if (*s != EQUAL) goto parse_error;
  96. s++;
  97. }
  98. extra->name.s = foo;
  99. /* skip spaces */
  100. while (*s && isspace((int)*s)) s++;
  101. /* get value type */
  102. stmp.s = s; stmp.len = strlen(s);
  103. if ((foo = pv_parse_spec(&stmp, &extra->spec)) == 0 )
  104. goto parse_error;
  105. s = foo;
  106. /* skip spaces */
  107. while (*s && isspace((int)*s)) s++;
  108. if (*s && ((*(s++) != SEPARATOR) || (*s == 0)))
  109. goto parse_error;
  110. }
  111. /* go throught all extras and make the names null terminated */
  112. for( extra = head; extra; extra = extra->next)
  113. extra->name.s[extra->name.len] = 0;
  114. return head;
  115. parse_error:
  116. LM_ERR("parse failed in <%s> around position %d\n",
  117. extra_str, (int)(long)(s-extra_str));
  118. error:
  119. LM_ERR("error\n");
  120. destroy_extras(head);
  121. return 0;
  122. }
  123. /*
  124. * Fill attr array name component with names of extra attributes
  125. * starting from offset. Return number of attributes added.
  126. */
  127. int extra2attrs(struct extra_attr *extra, struct attr *attrs, int offset)
  128. {
  129. int i;
  130. for (i = 0; extra; i++, extra = extra->next) {
  131. attrs[offset+i].n = extra->name.s;
  132. }
  133. return i;
  134. }
  135. /*
  136. * Get pseudo variable values of extra attributes to val_arr.
  137. * Return number of values or -1 in case of error.
  138. */
  139. int extra2strar( struct extra_attr *extra, struct sip_msg *rq, str *val_arr)
  140. {
  141. pv_value_t value;
  142. int n;
  143. int r;
  144. n = 0;
  145. r = 0;
  146. while (extra) {
  147. /* get the value */
  148. if (pv_get_spec_value(rq, &extra->spec, &value) != 0) {
  149. LM_ERR("failed to get value of extra attribute'%.*s'\n",
  150. extra->name.len,extra->name.s);
  151. }
  152. /* check for overflow */
  153. if (n == MAX_EXTRA) {
  154. LM_WARN("array too short -> ommiting extras for accounting\n");
  155. return -1;
  156. }
  157. if(value.flags&PV_VAL_NULL) {
  158. /* convert <null> to empty to have consistency */
  159. val_arr[n].s = 0;
  160. val_arr[n].len = 0;
  161. } else if (value.flags&PV_VAL_INT) {
  162. /* len = -1 denotes int type */
  163. val_arr[n].s = (char *)(long)value.ri;
  164. val_arr[n].len = -1;
  165. } else {
  166. /* set the value into the acc buffer */
  167. if (value.rs.s+value.rs.len == static_detector) {
  168. val_arr[n].s = int_buf + r*INT2STR_MAX_LEN;
  169. val_arr[n].len = value.rs.len;
  170. memcpy(val_arr[n].s, value.rs.s, value.rs.len);
  171. r++;
  172. } else {
  173. val_arr[n] = value.rs;
  174. }
  175. }
  176. n++;
  177. extra = extra->next;
  178. }
  179. return n;
  180. }
  181. /* Free memory allocated for extra attributes */
  182. void destroy_extras(struct extra_attr *extra)
  183. {
  184. struct extra_attr *foo;
  185. while (extra) {
  186. foo = extra;
  187. extra = extra->next;
  188. pkg_free(foo);
  189. }
  190. }