test_sip_msg.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * This file is part of the Sofia-SIP package
  3. *
  4. * Copyright (C) 2005 Nokia Corporation.
  5. *
  6. * Contact: Pekka Pessi <pekka.pessi@nokia.com>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * as published by the Free Software Foundation; either version 2.1 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21. * 02110-1301 USA
  22. *
  23. */
  24. /**@SIP_PARSER
  25. *
  26. * @file test_sip_msg.c Simple SIP message parser/printer tester.
  27. *
  28. * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
  29. *
  30. * @date Created: Fri Feb 18 10:25:08 2000 ppessi
  31. */
  32. #include "config.h"
  33. /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */
  34. #define MSG_PUB_T struct sip_s
  35. #define MSG_HDR_T union sip_header_u
  36. #include "sofia-sip/sip_parser.h"
  37. #include "sofia-sip/msg_mclass.h"
  38. #include "sofia-sip/msg_mclass_hash.h"
  39. #include <sofia-sip/sip_header.h>
  40. #include <sofia-sip/sip_util.h>
  41. #include <sofia-sip/msg_addr.h>
  42. #include <stddef.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <stdio.h>
  46. #include <assert.h>
  47. int diff(const char *olds, const char *news, int *linep, int *pos)
  48. {
  49. const char *o, *n;
  50. *linep = 0;
  51. for (o = olds, n = news; *o && *n && *o == *n ; o++, n++) {
  52. if (*o == '\n') ++*linep;
  53. }
  54. *pos = o - olds;
  55. return *o != *n;
  56. }
  57. int test_msg_class(msg_mclass_t const *mc)
  58. {
  59. int i, j, N;
  60. N = mc->mc_hash_size;
  61. /* Check parser table sanity */
  62. for (i = 0; i < N; i++) {
  63. /* Verify each header entry */
  64. msg_hclass_t *hc = mc->mc_hash[i].hr_class;
  65. if (hc == NULL)
  66. continue;
  67. /* Short form */
  68. if (hc->hc_short[0])
  69. assert(mc->mc_short[hc->hc_short[0] - 'a'].hr_class == hc);
  70. /* Long form */
  71. for (j = MC_HASH(hc->hc_name, N); j != i; j = (j + 1) % N)
  72. assert(mc->mc_hash[j].hr_class);
  73. }
  74. return 0;
  75. }
  76. char * url_print(url_t *url, char buf[1024])
  77. {
  78. url_e(buf, 1024, url);
  79. return buf;
  80. }
  81. void print_contact(FILE *f, sip_contact_t *m)
  82. {
  83. char const * const *p;
  84. char buf[1024];
  85. const char *sep = "\tContact: ";
  86. for (;m; m = m->m_next) {
  87. int quoted_url = 0;
  88. fputs(sep, f); sep = ", ";
  89. if (m->m_display) {
  90. quoted_url = 1;
  91. fprintf(f, "\"%s\" <", m->m_display);
  92. }
  93. url_print(m->m_url, buf);
  94. if (!quoted_url && strpbrk(buf, ",;?")) {
  95. fputs("<", f);
  96. }
  97. fputs(buf, f);
  98. if (quoted_url) fputs(">", f);
  99. if (m->m_params)
  100. for (p = m->m_params; *p; p++)
  101. fprintf(f, " ;%s", *p);
  102. if (m->m_comment)
  103. fprintf(f, " (%s)", m->m_comment);
  104. }
  105. fputs("\n", f);
  106. }
  107. void print_via(FILE *f, sip_via_t *v)
  108. {
  109. char const * const *p;
  110. char const * sep = "\tVia: ";
  111. for (;v; v = v->v_next) {
  112. fputs(sep, f); sep = ", ";
  113. fprintf(f, "%s %s", v->v_protocol, v->v_host);
  114. if (v->v_port)
  115. fprintf(f, ":%s", v->v_port);
  116. if (v->v_params)
  117. for (p = v->v_params; *p; p++)
  118. fprintf(f, " ;%s", *p);
  119. if (v->v_comment)
  120. fprintf(f, " (%s)", v->v_comment);
  121. }
  122. fputs("\n", f);
  123. }
  124. int main(int argc, char *argv[])
  125. {
  126. char urlbuf[1024];
  127. size_t n;
  128. int m, tcp;
  129. sip_t *sip;
  130. int exitcode = 0;
  131. msg_mclass_t const *sip_mclass = sip_default_mclass();
  132. msg_t *msg = msg_create(sip_mclass, MSG_FLG_EXTRACT_COPY);
  133. msg_iovec_t iovec[1];
  134. tcp = argv[1] && strcmp(argv[1], "-t") == 0;
  135. test_msg_class(sip_mclass);
  136. for (n = 0, m = 0;;) {
  137. if (msg_recv_iovec(msg, iovec, 1, 1, 0) < 0) {
  138. perror("msg_recv_iovec");
  139. exit(1);
  140. }
  141. assert(iovec->mv_len >= 1);
  142. n = read(0, iovec->mv_base, 1);
  143. if (n < 0) {
  144. perror("test_sip_msg read");
  145. exit(1);
  146. }
  147. msg_recv_commit(msg, n, n == 0);
  148. if (tcp)
  149. m = msg_extract(msg);
  150. if (n == 0 || m < 0)
  151. break;
  152. }
  153. if (!tcp)
  154. m = msg_extract(msg);
  155. sip = msg_object(msg);
  156. if (sip)
  157. fprintf(stdout, "sip flags = %x\n", sip->sip_flags);
  158. if (m < 0) {
  159. fprintf(stderr, "test_sip_msg: parsing error ("MOD_ZD")\n", n);
  160. exit(1);
  161. }
  162. if (sip->sip_flags & MSG_FLG_TRUNC) {
  163. fprintf(stderr, "test_sip_msg: message truncated\n");
  164. exit(1);
  165. }
  166. if (msg_next(msg)) {
  167. fprintf(stderr, "test_sip_msg: stuff after message\n");
  168. exit(1);
  169. }
  170. #if 0
  171. fprintf(stderr, "test_sip_msg: %d headers (%d short ones), %d unknown\n",
  172. msg->mh_n_headers, msg->mh_n_short, msg->mh_n_unknown);
  173. if (msg->mh_payload) {
  174. fprintf(stderr, "\twith payload of %d bytes\n",
  175. msg->mh_payload->pl_len);
  176. }
  177. #endif
  178. if (MSG_HAS_ERROR(sip->sip_flags) || sip->sip_error) {
  179. fprintf(stderr, "test_sip_msg: parsing error\n");
  180. exit(1);
  181. }
  182. else if (sip_sanity_check(sip) < 0) {
  183. fprintf(stderr, "test_sip_msg: message failed sanity check\n");
  184. exit(1);
  185. }
  186. if (sip->sip_request) {
  187. fprintf(stdout, "\trequest %s (%d) %s %s\n",
  188. sip->sip_request->rq_method_name,
  189. sip->sip_request->rq_method,
  190. url_print(sip->sip_request->rq_url, urlbuf),
  191. sip->sip_request->rq_version);
  192. if (sip->sip_request->rq_url->url_type == url_unknown) {
  193. exitcode = 1;
  194. fprintf(stderr, "test_sip_msg: invalid request URI\n");
  195. }
  196. }
  197. if (sip->sip_status)
  198. fprintf(stdout, "\tstatus %s %03d %s\n",
  199. sip->sip_status->st_version,
  200. sip->sip_status->st_status,
  201. sip->sip_status->st_phrase);
  202. if (sip->sip_cseq)
  203. fprintf(stdout, "\tCSeq: %u %s (%d)\n",
  204. sip->sip_cseq->cs_seq,
  205. sip->sip_cseq->cs_method_name,
  206. sip->sip_cseq->cs_method);
  207. if (sip->sip_call_id)
  208. fprintf(stdout, "\tCall-ID: %s (%x)\n",
  209. sip->sip_call_id->i_id,
  210. sip->sip_call_id->i_hash);
  211. if (sip->sip_from)
  212. fprintf(stdout, "\tFrom: %s@%s%s%s\n",
  213. sip->sip_from->a_user ? sip->sip_from->a_user : "[nobody]",
  214. sip->sip_from->a_host ? sip->sip_from->a_host : "[nowhere]",
  215. sip->sip_from->a_tag ? " ;tag=" : "",
  216. sip->sip_from->a_tag ? sip->sip_from->a_tag : "");
  217. if (sip->sip_to)
  218. fprintf(stdout, "\tTo: %s@%s%s%s\n",
  219. sip->sip_to->a_user ? sip->sip_to->a_user : "[nobody]",
  220. sip->sip_to->a_host ? sip->sip_to->a_host : "[nowhere]",
  221. sip->sip_to->a_tag ? " ;tag=" : "",
  222. sip->sip_to->a_tag ? sip->sip_to->a_tag : "");
  223. if (sip->sip_contact)
  224. print_contact(stdout, sip->sip_contact);
  225. if (sip->sip_via)
  226. print_via(stdout, sip->sip_via);
  227. if (sip->sip_content_length) {
  228. fprintf(stdout, "\tcontent length %u\n",
  229. sip->sip_content_length->l_length);
  230. }
  231. if (msg_next(msg)) {
  232. fprintf(stderr, "test_sip_msg: extra stuff after valid message\n");
  233. exit(1);
  234. }
  235. return exitcode;
  236. }