Add support for ICE/STUN/TURN in res_rtp_asterisk and chan_sip.
[asterisk/asterisk.git] / res / pjproject / pjsip / src / test / multipart_test.c
1 /* $Id$ */
2 /* 
3  * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
18  */
19 #include "test.h"
20 #include <pjsip.h>
21 #include <pjlib.h>
22
23 #define THIS_FILE       ""
24
25 /*
26  * multipart tests
27  */
28 typedef pj_status_t (*verify_ptr)(pj_pool_t*,pjsip_msg_body*);
29
30 static pj_status_t verify1(pj_pool_t *pool, pjsip_msg_body *body);
31
32 static struct test_t
33 {
34     char *ctype;
35     char *csubtype;
36     char *boundary;
37     const char *msg;
38     verify_ptr  verify;
39 } p_tests[] =
40 {
41         {
42                 /* Content-type */
43                 "multipart", "mixed", "12345",
44
45                 /* Body: */
46                 "This is the prolog, which should be ignored.\r\n"
47                 "--12345\r\n"
48                 "Content-Type: my/text\r\n"
49                 "\r\n"
50                 "Header and body\r\n"
51                 "--12345 \t\r\n"
52                 "Content-Type: hello/world\r\n"
53                 "Content-Length: 0\r\n"
54                 "\r\n"
55                 "--12345\r\n"
56                 "\r\n"
57                 "Body only\r\n"
58                 "--12345\r\n"
59                 "Content-Type: multipart/mixed;boundary=6789\r\n"
60                 "\r\n"
61                 "Prolog of the subbody, should be ignored\r\n"
62                 "--6789\r\n"
63                 "\r\n"
64                 "Subbody\r\n"
65                 "--6789--\r\n"
66                 "Epilogue of the subbody, should be ignored\r\n"
67                 "--12345--\r\n"
68                 "This is epilogue, which should be ignored too",
69
70                 &verify1
71         }
72 };
73
74 static void init_media_type(pjsip_media_type *mt,
75                             char *type, char *subtype, char *boundary)
76 {
77     static pjsip_param prm;
78
79     pjsip_media_type_init(mt, NULL, NULL);
80     if (type) mt->type = pj_str(type);
81     if (subtype) mt->subtype = pj_str(subtype);
82     if (boundary) {
83         pj_list_init(&prm);
84         prm.name = pj_str("boundary");
85         prm.value = pj_str(boundary);
86         pj_list_push_back(&mt->param, &prm);
87     }
88 }
89
90 static int verify_part(pjsip_multipart_part *part,
91                        char *h_content_type,
92                        char *h_content_subtype,
93                        char *boundary,
94                        int h_content_length,
95                        const char *body)
96 {
97     pjsip_ctype_hdr *ctype_hdr = NULL;
98     pjsip_clen_hdr *clen_hdr = NULL;
99     pjsip_hdr *hdr;
100     pj_str_t the_body;
101
102     hdr = part->hdr.next;
103     while (hdr != &part->hdr) {
104         if (hdr->type == PJSIP_H_CONTENT_TYPE)
105             ctype_hdr = (pjsip_ctype_hdr*)hdr;
106         else if (hdr->type == PJSIP_H_CONTENT_LENGTH)
107             clen_hdr = (pjsip_clen_hdr*)hdr;
108         hdr = hdr->next;
109     }
110
111     if (h_content_type) {
112         pjsip_media_type mt;
113
114         if (ctype_hdr == NULL)
115             return -10;
116
117         init_media_type(&mt, h_content_type, h_content_subtype, boundary);
118
119         if (pjsip_media_type_cmp(&ctype_hdr->media, &mt, 2) != 0)
120             return -20;
121
122     } else {
123         if (ctype_hdr)
124             return -30;
125     }
126
127     if (h_content_length >= 0) {
128         if (clen_hdr == NULL)
129             return -50;
130         if (clen_hdr->len != h_content_length)
131             return -60;
132     } else {
133         if (clen_hdr)
134             return -70;
135     }
136
137     the_body.ptr = (char*)part->body->data;
138     the_body.slen = part->body->len;
139
140     if (pj_strcmp2(&the_body, body) != 0)
141         return -90;
142
143     return 0;
144 }
145
146 static pj_status_t verify1(pj_pool_t *pool, pjsip_msg_body *body)
147 {
148     pjsip_media_type mt;
149     pjsip_multipart_part *part;
150     int rc;
151
152     PJ_UNUSED_ARG(pool);
153
154     /* Check content-type: "multipart/mixed;boundary=12345" */
155     init_media_type(&mt, "multipart", "mixed", "12345");
156     if (pjsip_media_type_cmp(&body->content_type, &mt, 2) != 0)
157         return -200;
158
159     /* First part:
160                 "Content-Type: my/text\r\n"
161                 "\r\n"
162                 "Header and body\r\n"
163      */
164     part = pjsip_multipart_get_first_part(body);
165     if (!part)
166         return -210;
167     if (verify_part(part, "my", "text", NULL, -1, "Header and body"))
168         return -220;
169
170     /* Next part:
171                 "Content-Type: hello/world\r\n"
172                 "Content-Length: 0\r\n"
173                 "\r\n"
174      */
175     part = pjsip_multipart_get_next_part(body, part);
176     if (!part)
177         return -230;
178     if ((rc=verify_part(part, "hello", "world", NULL, 0, ""))!=0) {
179         PJ_LOG(3,(THIS_FILE, "   err: verify_part rc=%d", rc));
180         return -240;
181     }
182
183     /* Next part:
184                 "\r\n"
185                 "Body only\r\n"
186      */
187     part = pjsip_multipart_get_next_part(body, part);
188     if (!part)
189         return -260;
190     if (verify_part(part, NULL, NULL, NULL, -1, "Body only"))
191         return -270;
192
193     /* Next part:
194                 "Content-Type: multipart/mixed;boundary=6789\r\n"
195                 "\r\n"
196                 "Prolog of the subbody, should be ignored\r\n"
197                 "--6789\r\n"
198                 "\r\n"
199                 "Subbody\r\n"
200                 "--6789--\r\n"
201                 "Epilogue of the subbody, should be ignored\r\n"
202
203      */
204     part = pjsip_multipart_get_next_part(body, part);
205     if (!part)
206         return -280;
207     if ((rc=verify_part(part, "multipart", "mixed", "6789", -1,
208                 "Prolog of the subbody, should be ignored\r\n"
209                 "--6789\r\n"
210                 "\r\n"
211                 "Subbody\r\n"
212                 "--6789--\r\n"
213                 "Epilogue of the subbody, should be ignored"))!=0) {
214         PJ_LOG(3,(THIS_FILE, "   err: verify_part rc=%d", rc));
215         return -290;
216     }
217
218     return 0;
219 }
220
221 static int parse_test(void)
222 {
223     unsigned i;
224
225     for (i=0; i<PJ_ARRAY_SIZE(p_tests); ++i) {
226         pj_pool_t *pool;
227         pjsip_media_type ctype;
228         pjsip_msg_body *body;
229         pj_str_t str;
230         int rc;
231
232         pool = pjsip_endpt_create_pool(endpt, NULL, 512, 512);
233
234         init_media_type(&ctype, p_tests[i].ctype, p_tests[i].csubtype,
235                         p_tests[i].boundary);
236
237         pj_strdup2_with_null(pool, &str, p_tests[i].msg);
238         body = pjsip_multipart_parse(pool, str.ptr, str.slen, &ctype, 0);
239         if (!body)
240             return -100;
241
242         if (p_tests[i].verify) {
243             rc = p_tests[i].verify(pool, body);
244         } else {
245             rc = 0;
246         }
247
248         pj_pool_release(pool);
249         if (rc)
250             return rc;
251     }
252
253     return 0;
254 }
255
256 int multipart_test(void)
257 {
258     int rc;
259
260     rc = parse_test();
261     if (rc)
262         return rc;
263
264     return rc;
265 }
266