41 | 41 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,56 @@ |
1 |
+/* |
|
2 |
+ * $Id$ |
|
3 |
+ */ |
|
4 |
+ |
|
5 |
+#include "hf.h" |
|
6 |
+#include "parse_via.h" |
|
7 |
+#include "parse_to.h" |
|
8 |
+#include "parse_cseq.h" |
|
9 |
+#include "../dprint.h" |
|
10 |
+#include "../mem/mem.h" |
|
11 |
+#include "parse_def.h" |
|
12 |
+ |
|
13 |
+ |
|
14 |
+/* |
|
15 |
+ * Frees a hdr_field structure, |
|
16 |
+ * WARNING: it frees only parsed (and not name.s, body.s) |
|
17 |
+ */ |
|
18 |
+void clean_hdr_field(struct hdr_field* hf) |
|
19 |
+{ |
|
20 |
+ if (hf->parsed){ |
|
21 |
+ switch(hf->type){ |
|
22 |
+ case HDR_VIA: |
|
23 |
+ free_via_list(hf->parsed); |
|
24 |
+ break; |
|
25 |
+ |
|
26 |
+ case HDR_TO: |
|
27 |
+ free_to(hf->parsed); |
|
28 |
+ break; |
|
29 |
+ |
|
30 |
+ case HDR_CSEQ: |
|
31 |
+ free_cseq(hf->parsed); |
|
32 |
+ break; |
|
33 |
+ |
|
34 |
+ default: |
|
35 |
+ LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n", |
|
36 |
+ hf->type); |
|
37 |
+ break; |
|
38 |
+ } |
|
39 |
+ } |
|
40 |
+} |
|
41 |
+ |
|
42 |
+ |
|
43 |
+/* |
|
44 |
+ * Frees a hdr_field list, |
|
45 |
+ * WARNING: frees only ->parsed and ->next*/ |
|
46 |
+void free_hdr_field_lst(struct hdr_field* hf) |
|
47 |
+{ |
|
48 |
+ struct hdr_field* foo; |
|
49 |
+ |
|
50 |
+ while(hf) { |
|
51 |
+ foo=hf; |
|
52 |
+ hf=hf->next; |
|
53 |
+ clean_hdr_field(foo); |
|
54 |
+ pkg_free(foo); |
|
55 |
+ } |
|
56 |
+} |
0 | 57 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,54 @@ |
1 |
+/* |
|
2 |
+ * $Id$ |
|
3 |
+ */ |
|
4 |
+ |
|
5 |
+#ifndef HF_H |
|
6 |
+#define HF_H |
|
7 |
+ |
|
8 |
+#include "../str.h" |
|
9 |
+ |
|
10 |
+ |
|
11 |
+/* Header types and flags */ |
|
12 |
+#define HDR_EOH -1 /* End of header found */ |
|
13 |
+#define HDR_ERROR 0 /* Error while parsing */ |
|
14 |
+#define HDR_VIA 1 /* Via header field */ |
|
15 |
+#define HDR_VIA1 1 /* First Via header field */ |
|
16 |
+#define HDR_VIA2 2 /* only used as flag*/ |
|
17 |
+#define HDR_TO 4 /* To header field */ |
|
18 |
+#define HDR_FROM 8 /* From header field */ |
|
19 |
+#define HDR_CSEQ 16 /* CSeq header field */ |
|
20 |
+#define HDR_CALLID 32 /* Call-Id header field */ |
|
21 |
+#define HDR_CONTACT 64 /* Contact header field */ |
|
22 |
+#define HDR_MAXFORWARDS 128 /* MaxForwards header field */ |
|
23 |
+#define HDR_ROUTE 256 /* Route header field */ |
|
24 |
+#define HDR_RECORDROUTE 512 /* Record-Route header field */ |
|
25 |
+#define HDR_CONTENTTYPE 1024 /* Content-Type header field */ |
|
26 |
+#define HDR_CONTENTLENGTH 2048 /* Content-Length header field */ |
|
27 |
+#define HDR_OTHER 65536 /* Unknown header type */ |
|
28 |
+ |
|
29 |
+ |
|
30 |
+/* |
|
31 |
+ * Format: name':' body |
|
32 |
+ */ |
|
33 |
+struct hdr_field { |
|
34 |
+ int type; /* Header field type */ |
|
35 |
+ str name; /* Header field name */ |
|
36 |
+ str body; /* Header field body */ |
|
37 |
+ void* parsed; /* Parsed data structures */ |
|
38 |
+ struct hdr_field* next; /* Next header field in the list */ |
|
39 |
+}; |
|
40 |
+ |
|
41 |
+ |
|
42 |
+/* frees a hdr_field structure, |
|
43 |
+ * WARNING: it frees only parsed (and not name.s, body.s) |
|
44 |
+ */ |
|
45 |
+void clean_hdr_field(struct hdr_field* hf); |
|
46 |
+ |
|
47 |
+ |
|
48 |
+/* frees a hdr_field list, |
|
49 |
+ * WARNING: frees only ->parsed and ->next |
|
50 |
+ */ |
|
51 |
+void free_hdr_field_lst(struct hdr_field* hf); |
|
52 |
+ |
|
53 |
+ |
|
54 |
+#endif |
... | ... |
@@ -17,185 +17,20 @@ |
17 | 17 |
#include "../mem/mem.h" |
18 | 18 |
#include "../error.h" |
19 | 19 |
#include "../globals.h" |
20 |
+#include "parse_hname.h" |
|
21 |
+#include "parse_hname2.h" |
|
22 |
+ |
|
20 | 23 |
|
21 | 24 |
#ifdef DEBUG_DMALLOC |
22 | 25 |
#include <mem/dmalloc.h> |
23 | 26 |
#endif |
24 | 27 |
|
25 | 28 |
|
26 |
- |
|
27 |
- |
|
28 |
- |
|
29 |
-/* parses the first line, returns pointer to next line & fills fl; |
|
30 |
- also modifies buffer (to avoid extra copy ops) */ |
|
31 |
-char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
|
32 |
-{ |
|
33 |
- |
|
34 |
- char *tmp; |
|
35 |
- char* second; |
|
36 |
- char* third; |
|
37 |
- char* nl; |
|
38 |
- int offset; |
|
39 |
- /* int l; */ |
|
40 |
- char* end; |
|
41 |
- char s1,s2,s3; |
|
42 |
- char *prn; |
|
43 |
- unsigned int t; |
|
44 |
- |
|
45 |
- /* grammar: |
|
46 |
- request = method SP uri SP version CRLF |
|
47 |
- response = version SP status SP reason CRLF |
|
48 |
- (version = "SIP/2.0") |
|
49 |
- */ |
|
50 |
- |
|
51 |
- |
|
52 |
- end=buffer+len; |
|
53 |
- /* see if it's a reply (status) */ |
|
54 |
- |
|
55 |
- /* jku -- parse well-known methods */ |
|
56 |
- |
|
57 |
- /* drop messages which are so short they are for sure useless; |
|
58 |
- utilize knowledge of minimum size in parsing the first |
|
59 |
- token |
|
60 |
- */ |
|
61 |
- if (len <=16 ) { |
|
62 |
- LOG(L_INFO, "ERROR: parse_first_line: message too short: %d\n", len); |
|
63 |
- goto error1; |
|
64 |
- } |
|
65 |
- |
|
66 |
- tmp=buffer; |
|
67 |
- /* is it perhaps a reply, ie does it start with "SIP...." ? */ |
|
68 |
- if ( (*tmp=='S' || *tmp=='s') && |
|
69 |
- strncasecmp( tmp+1, SIP_VERSION+1, SIP_VERSION_LEN-1)==0 && |
|
70 |
- (*(tmp+SIP_VERSION_LEN)==' ')) { |
|
71 |
- fl->type=SIP_REPLY; |
|
72 |
- fl->u.reply.version.len=SIP_VERSION_LEN; |
|
73 |
- tmp=buffer+SIP_VERSION_LEN; |
|
74 |
- } else IFISMETHOD( INVITE, 'I' ) |
|
75 |
- else IFISMETHOD( CANCEL, 'C') |
|
76 |
- else IFISMETHOD( ACK, 'A' ) |
|
77 |
- else IFISMETHOD( BYE, 'B' ) |
|
78 |
- /* if you want to add another method XXX, include METHOD_XXX in |
|
79 |
- H-file (this is the value which you will take later in |
|
80 |
- processing and define XXX_LEN as length of method name; |
|
81 |
- then just call IFISMETHOD( XXX, 'X' ) ... 'X' is the first |
|
82 |
- latter; everything must be capitals |
|
83 |
- */ |
|
84 |
- else { |
|
85 |
- /* neither reply, nor any of known method requests, |
|
86 |
- let's believe it is an unknown method request |
|
87 |
- */ |
|
88 |
- tmp=eat_token_end(buffer,buffer+len); |
|
89 |
- if ((tmp==buffer)||(tmp>=end)){ |
|
90 |
- LOG(L_INFO, "ERROR:parse_first_line: empty or bad first line\n"); |
|
91 |
- goto error1; |
|
92 |
- } |
|
93 |
- if (*tmp!=' ') { |
|
94 |
- LOG(L_INFO, "ERROR:parse_first_line: method not followed by SP\n"); |
|
95 |
- goto error1; |
|
96 |
- } |
|
97 |
- fl->type=SIP_REQUEST; |
|
98 |
- fl->u.request.method_value=METHOD_OTHER; |
|
99 |
- fl->u.request.method.len=tmp-buffer; |
|
100 |
- } |
|
101 |
- |
|
102 |
- |
|
103 |
- /* identifying type of message over now; |
|
104 |
- tmp points at space after; go ahead */ |
|
105 |
- |
|
106 |
- fl->u.request.method.s=buffer; /* store ptr to first token */ |
|
107 |
- (*tmp)=0; /* mark the 1st token end */ |
|
108 |
- second=tmp+1; /* jump to second token */ |
|
109 |
- offset=second-buffer; |
|
110 |
- |
|
111 |
-/* EoJku */ |
|
112 |
- |
|
113 |
- /* next element */ |
|
114 |
- tmp=eat_token_end(second, second+len-offset); |
|
115 |
- if (tmp>=end){ |
|
116 |
- goto error; |
|
117 |
- } |
|
118 |
- offset+=tmp-second; |
|
119 |
- third=eat_space_end(tmp, tmp+len-offset); |
|
120 |
- offset+=third-tmp; |
|
121 |
- if ((third==tmp)||(tmp>=end)){ |
|
122 |
- goto error; |
|
123 |
- } |
|
124 |
- *tmp=0; /* mark the end of the token */ |
|
125 |
- fl->u.request.uri.s=second; |
|
126 |
- fl->u.request.uri.len=tmp-second; |
|
127 |
- |
|
128 |
- /* jku: parse status code */ |
|
129 |
- if (fl->type==SIP_REPLY) { |
|
130 |
- if (fl->u.request.uri.len!=3) { |
|
131 |
- LOG(L_INFO, "ERROR:parse_first_line: len(status code)!=3: %s\n", |
|
132 |
- second ); |
|
133 |
- goto error; |
|
134 |
- } |
|
135 |
- s1=*second; s2=*(second+1);s3=*(second+2); |
|
136 |
- if (s1>='0' && s1<='9' && |
|
137 |
- s2>='0' && s2<='9' && |
|
138 |
- s3>='0' && s3<='9' ) { |
|
139 |
- fl->u.reply.statuscode=(s1-'0')*100+10*(s2-'0')+(s3-'0'); |
|
140 |
- } else { |
|
141 |
- LOG(L_INFO, "ERROR:parse_first_line: status_code non-numerical: %s\n", |
|
142 |
- second ); |
|
143 |
- goto error; |
|
144 |
- } |
|
145 |
- } |
|
146 |
- /* EoJku */ |
|
147 |
- |
|
148 |
- /* last part: for a request it must be the version, for a reply |
|
149 |
- * it can contain almost anything, including spaces, so we don't care |
|
150 |
- * about it*/ |
|
151 |
- if (fl->type==SIP_REQUEST){ |
|
152 |
- tmp=eat_token_end(third,third+len-offset); |
|
153 |
- offset+=tmp-third; |
|
154 |
- if ((tmp==third)||(tmp>=end)){ |
|
155 |
- goto error; |
|
156 |
- } |
|
157 |
- if (! is_empty_end(tmp, tmp+len-offset)){ |
|
158 |
- goto error; |
|
159 |
- } |
|
160 |
- }else{ |
|
161 |
- tmp=eat_token2_end(third,third+len-offset,'\r'); /* find end of line |
|
162 |
- ('\n' or '\r') */ |
|
163 |
- if (tmp>=end){ /* no crlf in packet => invalid */ |
|
164 |
- goto error; |
|
165 |
- } |
|
166 |
- offset+=tmp-third; |
|
167 |
- } |
|
168 |
- nl=eat_line(tmp,len-offset); |
|
169 |
- if (nl>=end){ /* no crlf in packet or only 1 line > invalid */ |
|
170 |
- goto error; |
|
171 |
- } |
|
172 |
- *tmp=0; |
|
173 |
- fl->u.request.version.s=third; |
|
174 |
- fl->u.request.version.len=tmp-third; |
|
175 |
- |
|
176 |
- return nl; |
|
177 |
- |
|
178 |
-error: |
|
179 |
- LOG(L_INFO, "ERROR:parse_first_line: bad %s first line\n", |
|
180 |
- (fl->type==SIP_REPLY)?"reply(status)":"request"); |
|
181 |
- |
|
182 |
- LOG(L_INFO, "ERROR: at line 0 char %d: \n", offset ); |
|
183 |
- prn=pkg_malloc( offset ); |
|
184 |
- if (prn) { |
|
185 |
- for (t=0; t<offset; t++) |
|
186 |
- if (*(buffer+t)) *(prn+t)=*(buffer+t); |
|
187 |
- else *(prn+t)='�'; |
|
188 |
- LOG(L_INFO, "ERROR: parsed so far: %.*s\n", offset, prn ); |
|
189 |
- pkg_free( prn ); |
|
190 |
- }; |
|
191 |
-error1: |
|
192 |
- fl->type=SIP_INVALID; |
|
193 |
- LOG(L_INFO, "ERROR:parse_first_line: bad message\n"); |
|
194 |
- /* skip line */ |
|
195 |
- nl=eat_line(buffer,len); |
|
196 |
- return nl; |
|
197 |
-} |
|
198 |
- |
|
29 |
+#ifdef NEW_HNAME |
|
30 |
+# define parse_hname(_b,_e,_h) parse_hname2((_b),(_e),(_h)) |
|
31 |
+#else |
|
32 |
+# define parse_hname(_b,_e,_h) parse_hname1((_b),(_e),(_h)) |
|
33 |
+#endif |
|
199 | 34 |
|
200 | 35 |
|
201 | 36 |
/* returns pointer to next header line, and fill hdr_f ; |
... | ... |
@@ -326,267 +161,6 @@ error: |
326 | 161 |
|
327 | 162 |
|
328 | 163 |
|
329 |
-char* parse_hostport(char* buf, str* host, short int* port) |
|
330 |
-{ |
|
331 |
- char *tmp; |
|
332 |
- int err; |
|
333 |
- |
|
334 |
- host->s=buf; |
|
335 |
- for(tmp=buf;(*tmp)&&(*tmp!=':');tmp++); |
|
336 |
- host->len=tmp-buf; |
|
337 |
- if (*tmp==0){ |
|
338 |
- *port=0; |
|
339 |
- }else{ |
|
340 |
- *tmp=0; |
|
341 |
- *port=str2s((unsigned char*)(tmp+1), strlen(tmp+1), &err); |
|
342 |
- if (err ){ |
|
343 |
- LOG(L_INFO, |
|
344 |
- "ERROR: hostport: trailing chars in port number: %s\n", |
|
345 |
- tmp+1); |
|
346 |
- /* report error? */ |
|
347 |
- } |
|
348 |
- } |
|
349 |
- return host->s; |
|
350 |
-} |
|
351 |
- |
|
352 |
- |
|
353 |
- |
|
354 |
-/*BUGGY*/ |
|
355 |
-char * parse_cseq(char *buf, char* end, struct cseq_body* cb) |
|
356 |
-{ |
|
357 |
- char *t, *m, *m_end; |
|
358 |
- char c; |
|
359 |
- |
|
360 |
- cb->error=PARSE_ERROR; |
|
361 |
- t=eat_space_end(buf, end); |
|
362 |
- if (t>=end) goto error; |
|
363 |
- |
|
364 |
- cb->number.s=t; |
|
365 |
- t=eat_token_end(t, end); |
|
366 |
- if (t>=end) goto error; |
|
367 |
- m=eat_space_end(t, end); |
|
368 |
- m_end=eat_token_end(m, end); |
|
369 |
- *t=0; /*null terminate it*/ |
|
370 |
- cb->number.len=t-cb->number.s; |
|
371 |
- |
|
372 |
- if (m_end>=end) goto error; |
|
373 |
- if (m_end==m){ |
|
374 |
- /* null method*/ |
|
375 |
- LOG(L_ERR, "ERROR:parse_cseq: no method found\n"); |
|
376 |
- goto error; |
|
377 |
- } |
|
378 |
- cb->method.s=m; |
|
379 |
- t=m_end; |
|
380 |
- c=*t; |
|
381 |
- *t=0; /*null terminate it*/ |
|
382 |
- cb->method.len=t-cb->method.s; |
|
383 |
- t++; |
|
384 |
- /*check if the header ends here*/ |
|
385 |
- if (c=='\n') goto check_continue; |
|
386 |
- do{ |
|
387 |
- for (;(t<end)&&((*t==' ')||(*t=='\t')||(*t=='\r'));t++); |
|
388 |
- if (t>=end) goto error; |
|
389 |
- if (*t!='\n'){ |
|
390 |
- LOG(L_ERR, "ERROR:parse_cseq: unexpected char <%c> at end of" |
|
391 |
- " cseq\n", *t); |
|
392 |
- goto error; |
|
393 |
- } |
|
394 |
- t++; |
|
395 |
-check_continue: |
|
396 |
- ; |
|
397 |
- }while( (t<end) && ((*t==' ')||(*t=='\t')) ); |
|
398 |
- |
|
399 |
- cb->error=PARSE_OK; |
|
400 |
- return t; |
|
401 |
-error: |
|
402 |
- LOG(L_ERR, "ERROR: parse_cseq: bad cseq\n"); |
|
403 |
- return t; |
|
404 |
-} |
|
405 |
- |
|
406 |
- |
|
407 |
- |
|
408 |
-/* buf= pointer to begining of uri (sip:x@foo.bar:5060;a=b?h=i) |
|
409 |
- len= len of uri |
|
410 |
-returns: fills uri & returns <0 on error or 0 if ok */ |
|
411 |
-int parse_uri(char *buf, int len, struct sip_uri* uri) |
|
412 |
-{ |
|
413 |
- char* next, *end; |
|
414 |
- char *user, *passwd, *host, *port, *params, *headers, *ipv6; |
|
415 |
- int host_len, port_len, params_len, headers_len; |
|
416 |
- int ret; |
|
417 |
- |
|
418 |
- |
|
419 |
- ret=0; |
|
420 |
- host_len=0; |
|
421 |
- end=buf+len; |
|
422 |
- memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure */ |
|
423 |
- /* look for "sip:"*/; |
|
424 |
- next=q_memchr(buf, ':', len); |
|
425 |
- if ((next==0)||(strncmp(buf,"sip",next-buf)!=0)){ |
|
426 |
- LOG(L_DBG, "ERROR: parse_uri: bad sip uri\n"); |
|
427 |
- ser_error=ret=E_BAD_URI; |
|
428 |
- goto error; |
|
429 |
- } |
|
430 |
- buf=next+1; /* next char after ':' */ |
|
431 |
- if (buf>end){ |
|
432 |
- LOG(L_DBG, "ERROR: parse_uri: uri too short\n"); |
|
433 |
- ser_error=ret=E_BAD_URI; |
|
434 |
- goto error; |
|
435 |
- } |
|
436 |
- /*look for '@' */ |
|
437 |
- next=q_memchr(buf,'@', end-buf); |
|
438 |
- if (next==0){ |
|
439 |
- /* no '@' found, => no userinfo */ |
|
440 |
- uri->user.s=0; |
|
441 |
- uri->passwd.s=0; |
|
442 |
- host=buf; |
|
443 |
- }else{ |
|
444 |
- /* found it */ |
|
445 |
- user=buf; |
|
446 |
- /* try to find passwd */ |
|
447 |
- passwd=q_memchr(user,':', next-user); |
|
448 |
- if (passwd==0){ |
|
449 |
- /* no ':' found => no password */ |
|
450 |
- uri->passwd.s=0; |
|
451 |
- uri->user.s=(char*)pkg_malloc(next-user+1); |
|
452 |
- if (uri->user.s==0){ |
|
453 |
- LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n"); |
|
454 |
- ser_error=ret=E_OUT_OF_MEM; |
|
455 |
- goto error; |
|
456 |
- } |
|
457 |
- memcpy(uri->user.s, user, next-user); |
|
458 |
- uri->user.len=next-user; |
|
459 |
- uri->user.s[next-user]=0; /* null terminate it, |
|
460 |
- usefull for easy printing*/ |
|
461 |
- }else{ |
|
462 |
- uri->user.s=(char*)pkg_malloc(passwd-user+1); |
|
463 |
- if (uri->user.s==0){ |
|
464 |
- LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n"); |
|
465 |
- ser_error=ret=E_OUT_OF_MEM; |
|
466 |
- goto error; |
|
467 |
- } |
|
468 |
- memcpy(uri->user.s, user, passwd-user); |
|
469 |
- uri->user.len=passwd-user; |
|
470 |
- uri->user.s[passwd-user]=0; |
|
471 |
- passwd++; /*skip ':' */ |
|
472 |
- uri->passwd.s=(char*)pkg_malloc(next-passwd+1); |
|
473 |
- if (uri->passwd.s==0){ |
|
474 |
- LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n"); |
|
475 |
- ser_error=ret=E_OUT_OF_MEM; |
|
476 |
- goto error; |
|
477 |
- } |
|
478 |
- memcpy(uri->passwd.s, passwd, next-passwd); |
|
479 |
- uri->passwd.len=next-passwd; |
|
480 |
- uri->passwd.s[next-passwd]=0; |
|
481 |
- } |
|
482 |
- host=next+1; /* skip '@' */ |
|
483 |
- } |
|
484 |
- /* try to find the rest */ |
|
485 |
- if(host>=end){ |
|
486 |
- LOG(L_DBG, "ERROR: parse_uri: missing hostport\n"); |
|
487 |
- ser_error=ret=E_UNSPEC; |
|
488 |
- goto error; |
|
489 |
- } |
|
490 |
- next=host; |
|
491 |
- ipv6=q_memchr(host, '[', end-host); |
|
492 |
- if (ipv6){ |
|
493 |
- host=ipv6+1; /* skip '[' in "[3ffe::abbcd]" */ |
|
494 |
- if (host>=end){ |
|
495 |
- LOG(L_DBG, "ERROR: parse_uri: bad ipv6 uri\n"); |
|
496 |
- ret=E_UNSPEC; |
|
497 |
- goto error; |
|
498 |
- } |
|
499 |
- ipv6=q_memchr(host, ']', end-host); |
|
500 |
- if ((ipv6==0)||(ipv6==host)){ |
|
501 |
- LOG(L_DBG, "ERROR: parse_uri: bad ipv6 uri - null address" |
|
502 |
- " or missing ']'\n"); |
|
503 |
- ret=E_UNSPEC; |
|
504 |
- goto error; |
|
505 |
- } |
|
506 |
- host_len=ipv6-host; |
|
507 |
- next=ipv6; |
|
508 |
- } |
|
509 |
- |
|
510 |
- |
|
511 |
- headers=q_memchr(next,'?',end-next); |
|
512 |
- params=q_memchr(next,';',end-next); |
|
513 |
- port=q_memchr(next,':',end-next); |
|
514 |
- if (host_len==0){ /* host not ipv6 addr */ |
|
515 |
- host_len=(port)?port-host:(params)?params-host:(headers)?headers-host: |
|
516 |
- end-host; |
|
517 |
- } |
|
518 |
- /* get host */ |
|
519 |
- uri->host.s=pkg_malloc(host_len+1); |
|
520 |
- if (uri->host.s==0){ |
|
521 |
- LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
|
522 |
- ret=E_OUT_OF_MEM; |
|
523 |
- goto error; |
|
524 |
- } |
|
525 |
- memcpy(uri->host.s, host, host_len); |
|
526 |
- uri->host.len=host_len; |
|
527 |
- uri->host.s[host_len]=0; |
|
528 |
- /* get port*/ |
|
529 |
- if ((port)&&(port+1<end)){ |
|
530 |
- port++; |
|
531 |
- if ( ((params) &&(params<port))||((headers) &&(headers<port)) ){ |
|
532 |
- /* error -> invalid uri we found ';' or '?' before ':' */ |
|
533 |
- LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n"); |
|
534 |
- ser_error=ret=E_BAD_URI; |
|
535 |
- goto error; |
|
536 |
- } |
|
537 |
- port_len=(params)?params-port:(headers)?headers-port:end-port; |
|
538 |
- uri->port.s=pkg_malloc(port_len+1); |
|
539 |
- if (uri->port.s==0){ |
|
540 |
- LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
|
541 |
- ser_error=ret=E_OUT_OF_MEM; |
|
542 |
- goto error; |
|
543 |
- } |
|
544 |
- memcpy(uri->port.s, port, port_len); |
|
545 |
- uri->port.len=port_len; |
|
546 |
- uri->port.s[port_len]=0; |
|
547 |
- }else uri->port.s=0; |
|
548 |
- /* get params */ |
|
549 |
- if ((params)&&(params+1<end)){ |
|
550 |
- params++; |
|
551 |
- if ((headers) && (headers<params)){ |
|
552 |
- /* error -> invalid uri we found '?' or '?' before ';' */ |
|
553 |
- LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n"); |
|
554 |
- ser_error=ret=E_BAD_URI; |
|
555 |
- goto error; |
|
556 |
- } |
|
557 |
- params_len=(headers)?headers-params:end-params; |
|
558 |
- uri->params.s=pkg_malloc(params_len+1); |
|
559 |
- if (uri->params.s==0){ |
|
560 |
- LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
|
561 |
- ser_error=ret=E_OUT_OF_MEM; |
|
562 |
- goto error; |
|
563 |
- } |
|
564 |
- memcpy(uri->params.s, params, params_len); |
|
565 |
- uri->params.len=params_len; |
|
566 |
- uri->params.s[params_len]=0; |
|
567 |
- }else uri->params.s=0; |
|
568 |
- /*get headers */ |
|
569 |
- if ((headers)&&(headers+1<end)){ |
|
570 |
- headers++; |
|
571 |
- headers_len=end-headers; |
|
572 |
- uri->headers.s=pkg_malloc(headers_len+1); |
|
573 |
- if(uri->headers.s==0){ |
|
574 |
- LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
|
575 |
- ser_error=ret=E_OUT_OF_MEM; |
|
576 |
- goto error; |
|
577 |
- } |
|
578 |
- memcpy(uri->headers.s, headers, headers_len); |
|
579 |
- uri->headers.len=headers_len; |
|
580 |
- uri->headers.s[headers_len]=0; |
|
581 |
- }else uri->headers.s=0; |
|
582 |
- |
|
583 |
- return ret; |
|
584 |
-error: |
|
585 |
- free_uri(uri); |
|
586 |
- return ret; |
|
587 |
-} |
|
588 |
- |
|
589 |
- |
|
590 | 164 |
/* parse the headers and adds them to msg->headers and msg->to, from etc. |
591 | 165 |
* It stops when all the headers requested in flags were parsed, on error |
592 | 166 |
* (bad header) or end of headers */ |
... | ... |
@@ -811,18 +385,6 @@ error: |
811 | 385 |
|
812 | 386 |
|
813 | 387 |
|
814 |
-void free_uri(struct sip_uri* u) |
|
815 |
-{ |
|
816 |
- if (u){ |
|
817 |
- if (u->user.s) pkg_free(u->user.s); |
|
818 |
- if (u->passwd.s) pkg_free(u->passwd.s); |
|
819 |
- if (u->host.s) pkg_free(u->host.s); |
|
820 |
- if (u->port.s) pkg_free(u->port.s); |
|
821 |
- if (u->params.s) pkg_free(u->params.s); |
|
822 |
- if (u->headers.s) pkg_free(u->headers.s); |
|
823 |
- } |
|
824 |
-} |
|
825 |
- |
|
826 | 388 |
void free_reply_lump( struct lump_rpl *lump) |
827 | 389 |
{ |
828 | 390 |
struct lump_rpl *foo, *bar; |
... | ... |
@@ -834,80 +396,6 @@ void free_reply_lump( struct lump_rpl *lump) |
834 | 396 |
} |
835 | 397 |
} |
836 | 398 |
|
837 |
-void free_via_param_list(struct via_param* vp) |
|
838 |
-{ |
|
839 |
- struct via_param* foo; |
|
840 |
- while(vp){ |
|
841 |
- foo=vp; |
|
842 |
- vp=vp->next; |
|
843 |
- pkg_free(foo); |
|
844 |
- } |
|
845 |
-} |
|
846 |
- |
|
847 |
- |
|
848 |
- |
|
849 |
-void free_via_list(struct via_body* vb) |
|
850 |
-{ |
|
851 |
- struct via_body* foo; |
|
852 |
- while(vb){ |
|
853 |
- foo=vb; |
|
854 |
- vb=vb->next; |
|
855 |
- if (foo->param_lst) free_via_param_list(foo->param_lst); |
|
856 |
- pkg_free(foo); |
|
857 |
- } |
|
858 |
-} |
|
859 |
- |
|
860 |
-void free_to(struct to_body* tb) |
|
861 |
-{ |
|
862 |
- struct to_param *tp=tb->param_lst; |
|
863 |
- struct to_param *foo; |
|
864 |
- while (tp){ |
|
865 |
- foo = tp->next; |
|
866 |
- pkg_free(tp); |
|
867 |
- tp=foo; |
|
868 |
- } |
|
869 |
- pkg_free(tb); |
|
870 |
-} |
|
871 |
- |
|
872 |
-/* frees a hdr_field structure, |
|
873 |
- * WARNING: it frees only parsed (and not name.s, body.s)*/ |
|
874 |
-void clean_hdr_field(struct hdr_field* hf) |
|
875 |
-{ |
|
876 |
- if (hf->parsed){ |
|
877 |
- switch(hf->type){ |
|
878 |
- case HDR_VIA: |
|
879 |
- free_via_list(hf->parsed); |
|
880 |
- break; |
|
881 |
- case HDR_TO: |
|
882 |
- free_to(hf->parsed); |
|
883 |
- break; |
|
884 |
- case HDR_CSEQ: |
|
885 |
- pkg_free(hf->parsed); |
|
886 |
- break; |
|
887 |
- default: |
|
888 |
- LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n", |
|
889 |
- hf->type); |
|
890 |
- } |
|
891 |
- } |
|
892 |
-} |
|
893 |
- |
|
894 |
- |
|
895 |
- |
|
896 |
-/* frees a hdr_field list, |
|
897 |
- * WARNING: frees only ->parsed and ->next*/ |
|
898 |
-void free_hdr_field_lst(struct hdr_field* hf) |
|
899 |
-{ |
|
900 |
- struct hdr_field* foo; |
|
901 |
- |
|
902 |
- while(hf){ |
|
903 |
- foo=hf; |
|
904 |
- hf=hf->next; |
|
905 |
- clean_hdr_field(foo); |
|
906 |
- pkg_free(foo); |
|
907 |
- } |
|
908 |
-} |
|
909 |
- |
|
910 |
- |
|
911 | 399 |
|
912 | 400 |
/*only the content*/ |
913 | 401 |
void free_sip_msg(struct sip_msg* msg) |
... | ... |
@@ -9,71 +9,23 @@ |
9 | 9 |
#include "../data_lump.h" |
10 | 10 |
#include "../flags.h" |
11 | 11 |
#include "../ip_addr.h" |
12 |
+#include "parse_def.h" |
|
13 |
+#include "parse_cseq.h" |
|
14 |
+#include "parse_to.h" |
|
15 |
+#include "parse_via.h" |
|
16 |
+#include "parse_uri.h" |
|
17 |
+#include "parse_fline.h" |
|
18 |
+#include "hf.h" |
|
12 | 19 |
|
13 |
-#define SIP_REQUEST 1 |
|
14 |
-#define SIP_REPLY 2 |
|
15 |
-#define SIP_INVALID 0 |
|
16 | 20 |
|
17 |
- |
|
18 |
- |
|
19 |
-/*header types and flags*/ |
|
20 |
-#define HDR_EOH -1 |
|
21 |
-#define HDR_ERROR 0 |
|
22 |
-#define HDR_VIA 1 |
|
23 |
-#define HDR_VIA1 1 |
|
24 |
-#define HDR_VIA2 2 /*only used as flag*/ |
|
25 |
-#define HDR_TO 4 |
|
26 |
-#define HDR_FROM 8 |
|
27 |
-#define HDR_CSEQ 16 |
|
28 |
-#define HDR_CALLID 32 |
|
29 |
-#define HDR_CONTACT 64 |
|
30 |
-#define HDR_MAXFORWARDS 128 |
|
31 |
-#define HDR_ROUTE 256 |
|
32 |
-#define HDR_RECORDROUTE 512 |
|
33 |
-#define HDR_CONTENTTYPE 1024 |
|
34 |
-#define HDR_CONTENTLENGTH 2048 |
|
35 |
-#define HDR_OTHER 65536 /*unknown header type*/ |
|
36 |
- |
|
37 |
- |
|
38 |
-/* maximum length of values appended to Via-branch parameter */ |
|
21 |
+/* Maximum length of values appended to Via-branch parameter */ |
|
39 | 22 |
#ifdef USE_SYNONIM |
40 | 23 |
#define MAX_BRANCH_PARAM_LEN 22 |
41 | 24 |
#else |
42 | 25 |
#define MAX_BRANCH_PARAM_LEN 48 |
43 | 26 |
#endif |
44 |
-/* via param types |
|
45 |
- * WARNING: keep in sync w/ FIN_*, GEN_PARAM and PARAM_ERROR from via_parse.c*/ |
|
46 |
-enum{ |
|
47 |
- PARAM_HIDDEN=230, PARAM_TTL, PARAM_BRANCH, PARAM_MADDR, PARAM_RECEIVED, |
|
48 |
- GEN_PARAM, |
|
49 |
- PARAM_ERROR |
|
50 |
-}; |
|
51 |
- |
|
52 |
-enum{ |
|
53 |
- TAG_PARAM=400, GENERAL_PARAM |
|
54 |
-}; |
|
55 |
- |
|
56 |
-/* casting macro for accessing CSEQ body */ |
|
57 |
-#define get_cseq( p_msg) ((struct cseq_body*)(p_msg)->cseq->parsed) |
|
58 |
-#define get_to( p_msg) ((struct to_body*)(p_msg)->to->parsed) |
|
59 |
- |
|
60 |
-#ifdef NEW_HNAME |
|
61 |
-# define parse_hname(_b,_e,_h) parse_hname2((_b),(_e),(_h)) |
|
62 |
- void init_htable(void); |
|
63 |
-#else |
|
64 |
-# define parse_hname(_b,_e,_h) parse_hname1((_b),(_e),(_h)) |
|
65 |
-#endif |
|
66 | 27 |
|
67 | 28 |
|
68 |
-#define INVITE_LEN 6 |
|
69 |
-#define ACK_LEN 3 |
|
70 |
-#define CANCEL_LEN 6 |
|
71 |
-#define BYE_LEN 3 |
|
72 |
- |
|
73 |
-#define CANCEL "CANCEL" |
|
74 |
-#define ACK "ACK" |
|
75 |
-#define INVITE "INVITE" |
|
76 |
- |
|
77 | 29 |
/* convenience short-cut macros */ |
78 | 30 |
#define REQ_LINE(_msg) ((_msg)->first_line.u.request) |
79 | 31 |
#define REQ_METHOD first_line.u.request.method_value |
... | ... |
@@ -93,109 +45,18 @@ if ( (*tmp==(firstchar) || *tmp==((firstchar) | 32)) && \ |
93 | 45 |
} |
94 | 46 |
|
95 | 47 |
|
96 |
-#define VIA_PARSE_OK 1 |
|
97 |
-#define VIA_PARSE_ERROR -1 |
|
98 |
-#define PARSE_ERROR -1 |
|
99 |
-#define PARSE_OK 1 |
|
100 |
- |
|
101 |
-#define SIP_VERSION "SIP/2.0" |
|
102 |
-#define SIP_VERSION_LEN 7 |
|
103 |
- |
|
104 |
- |
|
105 |
-struct msg_start{ |
|
106 |
- int type; |
|
107 |
- union { |
|
108 |
- struct { |
|
109 |
- str method; |
|
110 |
- str uri; |
|
111 |
- str version; |
|
112 |
- int method_value; |
|
113 |
- }request; |
|
114 |
- struct { |
|
115 |
- str version; |
|
116 |
- str status; |
|
117 |
- str reason; |
|
118 |
- unsigned int /* statusclass,*/ statuscode; |
|
119 |
- }reply; |
|
120 |
- }u; |
|
121 |
-}; |
|
122 |
- |
|
123 |
-struct hdr_field{ /* format: name':' body */ |
|
124 |
- int type; |
|
125 |
- str name; |
|
126 |
- str body; |
|
127 |
- void* parsed; |
|
128 |
- struct hdr_field* next; |
|
129 |
-}; |
|
130 |
- |
|
131 |
- |
|
132 |
- |
|
133 |
-struct via_param{ |
|
134 |
- int type; |
|
135 |
- str name; |
|
136 |
- str value; |
|
137 |
- int size; /* total size*/ |
|
138 |
- struct via_param* next; |
|
139 |
-}; |
|
140 |
- |
|
141 |
-struct via_body{ /* format: name/version/transport host:port;params comment */ |
|
142 |
- int error; |
|
143 |
- str hdr; /* contains "Via" or "v" */ |
|
144 |
- str name; |
|
145 |
- str version; |
|
146 |
- str transport; |
|
147 |
- str host; |
|
148 |
- int port; |
|
149 |
- str port_str; |
|
150 |
- str params; |
|
151 |
- str comment; |
|
152 |
- int bsize; /* body size, not including hdr */ |
|
153 |
- struct via_param* param_lst; /* list of parameters*/ |
|
154 |
- struct via_param* last_param; /*last via parameter, internal use*/ |
|
155 |
- /* shortcuts to "important" params*/ |
|
156 |
- struct via_param* branch; |
|
157 |
- |
|
158 |
- struct via_body* next; /* pointer to next via body string if |
|
159 |
- compact via or null */ |
|
160 |
-}; |
|
161 |
- |
|
162 |
- |
|
163 |
- |
|
164 |
-struct to_param{ |
|
165 |
- int type; |
|
166 |
- str name; |
|
167 |
- str value; |
|
168 |
- struct to_param* next; |
|
169 |
-}; |
|
170 |
- |
|
171 |
-struct to_body{ |
|
172 |
- int error; |
|
173 |
- str body; |
|
174 |
- str uri; |
|
175 |
- str tag_value; |
|
176 |
- struct to_param *param_lst; |
|
177 |
- struct to_param *last_param; |
|
178 |
-}; |
|
179 |
- |
|
180 |
- |
|
181 |
-struct cseq_body{ |
|
182 |
- int error; |
|
183 |
- str number; |
|
184 |
- str method; |
|
185 |
-}; |
|
48 |
+struct sip_msg { |
|
49 |
+ unsigned int id; /* message id, unique/process*/ |
|
50 |
+ struct msg_start first_line; /* Message first line */ |
|
51 |
+ struct via_body* via1; /* The first via */ |
|
52 |
+ struct via_body* via2; /* The second via */ |
|
53 |
+ struct hdr_field* headers; /* All the parsed headers*/ |
|
54 |
+ struct hdr_field* last_header; /* Pointer to the last parsed header*/ |
|
55 |
+ int parsed_flag; /* Already parsed header field types */ |
|
186 | 56 |
|
57 |
+ /* Via, To, CSeq, Call-Id, From, end of header*/ |
|
58 |
+ /* first occurance of it; subsequent occurances saved in 'headers' */ |
|
187 | 59 |
|
188 |
- |
|
189 |
-struct sip_msg{ |
|
190 |
- unsigned int id; /* message id, unique/process*/ |
|
191 |
- struct msg_start first_line; |
|
192 |
- struct via_body* via1; |
|
193 |
- struct via_body* via2; |
|
194 |
- struct hdr_field* headers; /* all the parsed headers*/ |
|
195 |
- struct hdr_field* last_header; /* pointer to the last parsed header*/ |
|
196 |
- int parsed_flag; |
|
197 |
- /* via, to, cseq, call-id, from, end of header*/ |
|
198 |
- /* first occurance of it; subsequent occurances saved in 'headers' */ |
|
199 | 60 |
struct hdr_field* h_via1; |
200 | 61 |
struct hdr_field* h_via2; |
201 | 62 |
struct hdr_field* callid; |
... | ... |
@@ -208,72 +69,47 @@ struct sip_msg{ |
208 | 69 |
struct hdr_field* record_route; |
209 | 70 |
struct hdr_field* content_type; |
210 | 71 |
struct hdr_field* content_length; |
211 |
- char* eoh; /* pointer to the end of header (if found) or null */ |
|
212 |
- char* unparsed; /* here we stopped parsing*/ |
|
72 |
+ |
|
73 |
+ char* eoh; /* pointer to the end of header (if found) or null */ |
|
74 |
+ char* unparsed; /* here we stopped parsing*/ |
|
213 | 75 |
|
214 | 76 |
struct ip_addr src_ip; |
215 | 77 |
struct ip_addr dst_ip; |
216 |
- char* orig; /* original message copy */ |
|
217 |
- char* buf; /* scratch pad, holds a modfied message, |
|
218 |
- via, etc. point into it */ |
|
78 |
+ |
|
79 |
+ char* orig; /* original message copy */ |
|
80 |
+ char* buf; /* scratch pad, holds a modfied message, |
|
81 |
+ * via, etc. point into it |
|
82 |
+ */ |
|
219 | 83 |
unsigned int len; /* message len (orig) */ |
220 | 84 |
|
221 |
- /* modifications */ |
|
85 |
+ /* modifications */ |
|
86 |
+ |
|
222 | 87 |
str new_uri; /* changed first line uri*/ |
223 |
- |
|
224 |
- struct lump* add_rm; /* used for all the forwarded messages */ |
|
225 |
- struct lump* repl_add_rm; /* only for localy generated replies !!!*/ |
|
88 |
+ |
|
89 |
+ struct lump* add_rm; /* used for all the forwarded messages */ |
|
90 |
+ struct lump* repl_add_rm; /* only for localy generated replies !!!*/ |
|
226 | 91 |
struct lump_rpl *reply_lump; |
227 |
- |
|
228 |
- /* str add_to_branch; */ /* whatever whoever want to append to branch comes here */ |
|
92 |
+ |
|
93 |
+ /* str add_to_branch */ |
|
94 |
+ /* whatever whoever want to append to branch comes here */ |
|
229 | 95 |
char add_to_branch_s[MAX_BRANCH_PARAM_LEN]; |
230 | 96 |
int add_to_branch_len; |
231 |
- |
|
232 |
- /* index to TM hash table; stored in core to avoid unnecessary calcs */ |
|
97 |
+ |
|
98 |
+ /* index to TM hash table; stored in core to avoid unnecessary calcs */ |
|
233 | 99 |
unsigned int hash_index; |
234 |
- |
|
235 |
- /* allows to set various flags on the message; may be used for |
|
236 |
- simple inter-module communication or remembering processing state |
|
237 |
- reached */ |
|
238 |
- flag_t flags; |
|
239 |
- |
|
240 | 100 |
|
101 |
+ /* allows to set various flags on the message; may be used for |
|
102 |
+ * simple inter-module communication or remembering processing state |
|
103 |
+ * reached |
|
104 |
+ */ |
|
105 |
+ flag_t flags; |
|
241 | 106 |
}; |
242 | 107 |
|
243 | 108 |
|
244 |
-struct sip_uri{ |
|
245 |
- str user; |
|
246 |
- str passwd; |
|
247 |
- str host; |
|
248 |
- str port; |
|
249 |
- str params; |
|
250 |
- str headers; |
|
251 |
-}; |
|
252 |
- |
|
253 |
- |
|
254 |
-char* parse_fline(char* buffer, char* end, struct msg_start* fl); |
|
255 |
-char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl); |
|
256 |
-char* parse_hostport(char* buf, str* host, short int* port); |
|
257 |
- |
|
258 | 109 |
int parse_msg(char* buf, unsigned int len, struct sip_msg* msg); |
259 |
-int parse_uri(char *buf, int len, struct sip_uri* uri); |
|
260 |
-int parse_headers(struct sip_msg* msg, int flags); |
|
261 |
- |
|
262 |
-void free_uri(struct sip_uri* u); |
|
263 | 110 |
|
111 |
+int parse_headers(struct sip_msg* msg, int flags); |
|
264 | 112 |
|
265 |
-/* char* parse_hname(char* buf, char* end, struct hdr_field* hdr); */ |
|
266 |
-char* parse_hname1(char* buf, char* end, struct hdr_field* hdr); |
|
267 |
-char* parse_hname2(char* buf, char* end, struct hdr_field* hdr); |
|
268 |
- |
|
269 |
-char* parse_via(char* buffer, char* end, struct via_body *vb); |
|
270 |
-char* parse_to(char* buffer, char* end, struct to_body *to_b); |
|
271 |
-char* parse_cseq(char* buffer, char* end, struct cseq_body *cb); |
|
272 |
- |
|
273 |
-void free_via_param_list(struct via_param *vp); |
|
274 |
-void free_via_list(struct via_body *vb); |
|
275 |
-void clean_hdr_field(struct hdr_field* hf); |
|
276 |
-void free_hdr_field_lst(struct hdr_field* hf); |
|
277 | 113 |
void free_sip_msg(struct sip_msg* msg); |
278 | 114 |
|
279 | 115 |
/* make sure all HFs needed for transaction identification have been |
280 | 116 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,71 @@ |
1 |
+/* |
|
2 |
+ * $Id |
|
3 |
+ */ |
|
4 |
+ |
|
5 |
+#include "parse_cseq.h" |
|
6 |
+#include "parser_f.h" /* eat_space_end and so on */ |
|
7 |
+#include "../dprint.h" |
|
8 |
+#include "parse_def.h" |
|
9 |
+#include "../mem/mem.h" |
|
10 |
+ |
|
11 |
+/* |
|
12 |
+ * Parse CSeq header field |
|
13 |
+ */ |
|
14 |
+ |
|
15 |
+/*BUGGY*/ |
|
16 |
+char* parse_cseq(char *buf, char* end, struct cseq_body* cb) |
|
17 |
+{ |
|
18 |
+ char *t, *m, *m_end; |
|
19 |
+ char c; |
|
20 |
+ |
|
21 |
+ cb->error=PARSE_ERROR; |
|
22 |
+ t=eat_space_end(buf, end); |
|
23 |
+ if (t>=end) goto error; |
|
24 |
+ |
|
25 |
+ cb->number.s=t; |
|
26 |
+ t=eat_token_end(t, end); |
|
27 |
+ if (t>=end) goto error; |
|
28 |
+ m=eat_space_end(t, end); |
|
29 |
+ m_end=eat_token_end(m, end); |
|
30 |
+ *t=0; /*null terminate it*/ |
|
31 |
+ cb->number.len=t-cb->number.s; |
|
32 |
+ |
|
33 |
+ if (m_end>=end) goto error; |
|
34 |
+ if (m_end==m){ |
|
35 |
+ /* null method*/ |
|
36 |
+ LOG(L_ERR, "ERROR:parse_cseq: no method found\n"); |
|
37 |
+ goto error; |
|
38 |
+ } |
|
39 |
+ cb->method.s=m; |
|
40 |
+ t=m_end; |
|
41 |
+ c=*t; |
|
42 |
+ *t=0; /*null terminate it*/ |
|
43 |
+ cb->method.len=t-cb->method.s; |
|
44 |
+ t++; |
|
45 |
+ /*check if the header ends here*/ |
|
46 |
+ if (c=='\n') goto check_continue; |
|
47 |
+ do{ |
|
48 |
+ for (;(t<end)&&((*t==' ')||(*t=='\t')||(*t=='\r'));t++); |
|
49 |
+ if (t>=end) goto error; |
|
50 |
+ if (*t!='\n'){ |
|
51 |
+ LOG(L_ERR, "ERROR:parse_cseq: unexpected char <%c> at end of" |
|
52 |
+ " cseq\n", *t); |
|
53 |
+ goto error; |
|
54 |
+ } |
|
55 |
+ t++; |
|
56 |
+check_continue: |
|
57 |
+ ; |
|
58 |
+ }while( (t<end) && ((*t==' ')||(*t=='\t')) ); |
|
59 |
+ |
|
60 |
+ cb->error=PARSE_OK; |
|
61 |
+ return t; |
|
62 |
+error: |
|
63 |
+ LOG(L_ERR, "ERROR: parse_cseq: bad cseq\n"); |
|
64 |
+ return t; |
|
65 |
+} |
|
66 |
+ |
|
67 |
+ |
|
68 |
+void free_cseq(struct cseq_body* cb) |
|
69 |
+{ |
|
70 |
+ pkg_free(cb); |
|
71 |
+} |
0 | 72 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,34 @@ |
1 |
+/* |
|
2 |
+ * $Id$ |
|
3 |
+ */ |
|
4 |
+ |
|
5 |
+#ifndef PARSE_CSEQ |
|
6 |
+#define PARSE_CSEQ |
|
7 |
+ |
|
8 |
+#include "../str.h" |
|
9 |
+ |
|
10 |
+ |
|
11 |
+struct cseq_body{ |
|
12 |
+ int error; /* Error code */ |
|
13 |
+ str number; /* CSeq number */ |
|
14 |
+ str method; /* Associated method */ |
|
15 |
+}; |
|
16 |
+ |
|
17 |
+ |
|
18 |
+/* casting macro for accessing CSEQ body */ |
|
19 |
+#define get_cseq(p_msg) ((struct cseq_body*)(p_msg)->cseq->parsed) |
|
20 |
+ |
|
21 |
+ |
|
22 |
+/* |
|
23 |
+ * Parse CSeq header field |
|
24 |
+ */ |
|
25 |
+char* parse_cseq(char *buf, char* end, struct cseq_body* cb); |
|
26 |
+ |
|
27 |
+ |
|
28 |
+/* |
|
29 |
+ * Free all associated memory |
|
30 |
+ */ |
|
31 |
+void free_cseq(struct cseq_body* cb); |
|
32 |
+ |
|
33 |
+ |
|
34 |
+#endif |
... | ... |
@@ -9,6 +9,8 @@ |
9 | 9 |
|
10 | 10 |
#include "../dprint.h" |
11 | 11 |
#include "msg_parser.h" |
12 |
+#include "parser_f.h" |
|
13 |
+#include "../mem/mem.h" |
|
12 | 14 |
|
13 | 15 |
|
14 | 16 |
/* grammar: |
... | ... |
@@ -19,17 +21,17 @@ |
19 | 21 |
|
20 | 22 |
/*known methods: INVITE, ACK, CANCEL, BYE*/ |
21 | 23 |
|
22 |
-enum{ START, |
|
23 |
- INVITE1, INVITE2, INVITE3, INVITE4, INVITE5, |
|
24 |
- ACK1, ACK2, |
|
25 |
- CANCEL1, CANCEL2, CANCEL3, CANCEL4, CANCEL5, |
|
26 |
- BYE1, BYE2, |
|
27 |
- SIP1, SIP2, SIP3, SIP4, SIP5, SIP6, |
|
28 |
- FIN_INVITE=100, FIN_ACK, FIN_CANCEL, FIN_BYE, FIN_SIP, |
|
29 |
- P_METHOD=200, L_URI, P_URI, L_VER, |
|
30 |
- VER1, VER2, VER3, VER4, VER5, VER6, FIN_VER, |
|
31 |
- L_STATUS, P_STATUS, L_REASON, P_REASON, |
|
32 |
- L_LF, F_CR, F_LF |
|
24 |
+enum { START, |
|
25 |
+ INVITE1, INVITE2, INVITE3, INVITE4, INVITE5, |
|
26 |
+ ACK1, ACK2, |
|
27 |
+ CANCEL1, CANCEL2, CANCEL3, CANCEL4, CANCEL5, |
|
28 |
+ BYE1, BYE2, |
|
29 |
+ SIP1, SIP2, SIP3, SIP4, SIP5, SIP6, |
|
30 |
+ FIN_INVITE = 100, FIN_ACK, FIN_CANCEL, FIN_BYE, FIN_SIP, |
|
31 |
+ P_METHOD = 200, L_URI, P_URI, L_VER, |
|
32 |
+ VER1, VER2, VER3, VER4, VER5, VER6, FIN_VER, |
|
33 |
+ L_STATUS, P_STATUS, L_REASON, P_REASON, |
|
34 |
+ L_LF, F_CR, F_LF |
|
33 | 35 |
}; |
34 | 36 |
|
35 | 37 |
|
... | ... |
@@ -1108,3 +1110,175 @@ error: |
1108 | 1110 |
fl->type=SIP_INVALID; |
1109 | 1111 |
return tmp; |
1110 | 1112 |
} |
1113 |
+ |
|
1114 |
+ |
|
1115 |
+ |
|
1116 |
+/* parses the first line, returns pointer to next line & fills fl; |
|
1117 |
+ also modifies buffer (to avoid extra copy ops) */ |
|
1118 |
+char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
|
1119 |
+{ |
|
1120 |
+ |
|
1121 |
+ char *tmp; |
|
1122 |
+ char* second; |
|
1123 |
+ char* third; |
|
1124 |
+ char* nl; |
|
1125 |
+ int offset; |
|
1126 |
+ /* int l; */ |
|
1127 |
+ char* end; |
|
1128 |
+ char s1,s2,s3; |
|
1129 |
+ char *prn; |
|
1130 |
+ unsigned int t; |
|
1131 |
+ |
|
1132 |
+ /* grammar: |
|
1133 |
+ request = method SP uri SP version CRLF |
|
1134 |
+ response = version SP status SP reason CRLF |
|
1135 |
+ (version = "SIP/2.0") |
|
1136 |
+ */ |
|
1137 |
+ |
|
1138 |
+ |
|
1139 |
+ end=buffer+len; |
|
1140 |
+ /* see if it's a reply (status) */ |
|
1141 |
+ |
|
1142 |
+ /* jku -- parse well-known methods */ |
|
1143 |
+ |
|
1144 |
+ /* drop messages which are so short they are for sure useless; |
|
1145 |
+ utilize knowledge of minimum size in parsing the first |
|
1146 |
+ token |
|
1147 |
+ */ |
|
1148 |
+ if (len <=16 ) { |
|
1149 |
+ LOG(L_INFO, "ERROR: parse_first_line: message too short: %d\n", len); |
|
1150 |
+ goto error1; |
|
1151 |
+ } |
|
1152 |
+ |
|
1153 |
+ tmp=buffer; |
|
1154 |
+ /* is it perhaps a reply, ie does it start with "SIP...." ? */ |
|
1155 |
+ if ( (*tmp=='S' || *tmp=='s') && |
|
1156 |
+ strncasecmp( tmp+1, SIP_VERSION+1, SIP_VERSION_LEN-1)==0 && |
|
1157 |
+ (*(tmp+SIP_VERSION_LEN)==' ')) { |
|
1158 |
+ fl->type=SIP_REPLY; |
|
1159 |
+ fl->u.reply.version.len=SIP_VERSION_LEN; |
|
1160 |
+ tmp=buffer+SIP_VERSION_LEN; |
|
1161 |
+ } else IFISMETHOD( INVITE, 'I' ) |
|
1162 |
+ else IFISMETHOD( CANCEL, 'C') |
|
1163 |
+ else IFISMETHOD( ACK, 'A' ) |
|
1164 |
+ else IFISMETHOD( BYE, 'B' ) |
|
1165 |
+ /* if you want to add another method XXX, include METHOD_XXX in |
|
1166 |
+ H-file (this is the value which you will take later in |
|
1167 |
+ processing and define XXX_LEN as length of method name; |
|
1168 |
+ then just call IFISMETHOD( XXX, 'X' ) ... 'X' is the first |
|
1169 |
+ latter; everything must be capitals |
|
1170 |
+ */ |
|
1171 |
+ else { |
|
1172 |
+ /* neither reply, nor any of known method requests, |
|
1173 |
+ let's believe it is an unknown method request |
|
1174 |
+ */ |
|
1175 |
+ tmp=eat_token_end(buffer,buffer+len); |
|
1176 |
+ if ((tmp==buffer)||(tmp>=end)){ |
|
1177 |
+ LOG(L_INFO, "ERROR:parse_first_line: empty or bad first line\n"); |
|
1178 |
+ goto error1; |
|
1179 |
+ } |
|
1180 |
+ if (*tmp!=' ') { |
|
1181 |
+ LOG(L_INFO, "ERROR:parse_first_line: method not followed by SP\n"); |
|
1182 |
+ goto error1; |
|
1183 |
+ } |
|
1184 |
+ fl->type=SIP_REQUEST; |
|
1185 |
+ fl->u.request.method_value=METHOD_OTHER; |
|
1186 |
+ fl->u.request.method.len=tmp-buffer; |
|
1187 |
+ } |
|
1188 |
+ |
|
1189 |
+ |
|
1190 |
+ /* identifying type of message over now; |
|
1191 |
+ tmp points at space after; go ahead */ |
|
1192 |
+ |
|
1193 |
+ fl->u.request.method.s=buffer; /* store ptr to first token */ |
|
1194 |
+ (*tmp)=0; /* mark the 1st token end */ |
|
1195 |
+ second=tmp+1; /* jump to second token */ |
|
1196 |
+ offset=second-buffer; |
|
1197 |
+ |
|
1198 |
+/* EoJku */ |
|
1199 |
+ |
|
1200 |
+ /* next element */ |
|
1201 |
+ tmp=eat_token_end(second, second+len-offset); |
|
1202 |
+ if (tmp>=end){ |
|
1203 |
+ goto error; |
|
1204 |
+ } |
|
1205 |
+ offset+=tmp-second; |
|
1206 |
+ third=eat_space_end(tmp, tmp+len-offset); |
|
1207 |
+ offset+=third-tmp; |
|
1208 |
+ if ((third==tmp)||(tmp>=end)){ |
|
1209 |
+ goto error; |
|
1210 |
+ } |
|
1211 |
+ *tmp=0; /* mark the end of the token */ |
|
1212 |
+ fl->u.request.uri.s=second; |
|
1213 |
+ fl->u.request.uri.len=tmp-second; |
|
1214 |
+ |
|
1215 |
+ /* jku: parse status code */ |
|
1216 |
+ if (fl->type==SIP_REPLY) { |
|
1217 |
+ if (fl->u.request.uri.len!=3) { |
|
1218 |
+ LOG(L_INFO, "ERROR:parse_first_line: len(status code)!=3: %s\n", |
|
1219 |
+ second ); |
|
1220 |
+ goto error; |
|
1221 |
+ } |
|
1222 |
+ s1=*second; s2=*(second+1);s3=*(second+2); |
|
1223 |
+ if (s1>='0' && s1<='9' && |
|
1224 |
+ s2>='0' && s2<='9' && |
|
1225 |
+ s3>='0' && s3<='9' ) { |
|
1226 |
+ fl->u.reply.statuscode=(s1-'0')*100+10*(s2-'0')+(s3-'0'); |
|
1227 |
+ } else { |
|
1228 |
+ LOG(L_INFO, "ERROR:parse_first_line: status_code non-numerical: %s\n", |
|
1229 |
+ second ); |
|
1230 |
+ goto error; |
|
1231 |
+ } |
|
1232 |
+ } |
|
1233 |
+ /* EoJku */ |
|
1234 |
+ |
|
1235 |
+ /* last part: for a request it must be the version, for a reply |
|
1236 |
+ * it can contain almost anything, including spaces, so we don't care |
|
1237 |
+ * about it*/ |
|
1238 |
+ if (fl->type==SIP_REQUEST){ |
|
1239 |
+ tmp=eat_token_end(third,third+len-offset); |
|
1240 |
+ offset+=tmp-third; |
|
1241 |
+ if ((tmp==third)||(tmp>=end)){ |
|
1242 |
+ goto error; |
|
1243 |
+ } |
|
1244 |
+ if (! is_empty_end(tmp, tmp+len-offset)){ |
|
1245 |
+ goto error; |
|
1246 |
+ } |
|
1247 |
+ }else{ |
|
1248 |
+ tmp=eat_token2_end(third,third+len-offset,'\r'); /* find end of line |
|
1249 |
+ ('\n' or '\r') */ |
|
1250 |
+ if (tmp>=end){ /* no crlf in packet => invalid */ |
|
1251 |
+ goto error; |
|
1252 |
+ } |
|
1253 |
+ offset+=tmp-third; |
|
1254 |
+ } |
|
1255 |
+ nl=eat_line(tmp,len-offset); |
|
1256 |
+ if (nl>=end){ /* no crlf in packet or only 1 line > invalid */ |
|
1257 |
+ goto error; |
|
1258 |
+ } |
|
1259 |
+ *tmp=0; |
|
1260 |
+ fl->u.request.version.s=third; |
|
1261 |
+ fl->u.request.version.len=tmp-third; |
|
1262 |
+ |
|
1263 |
+ return nl; |
|
1264 |
+ |
|
1265 |
+error: |
|
1266 |
+ LOG(L_INFO, "ERROR:parse_first_line: bad %s first line\n", |
|
1267 |
+ (fl->type==SIP_REPLY)?"reply(status)":"request"); |
|
1268 |
+ |
|
1269 |
+ LOG(L_INFO, "ERROR: at line 0 char %d: \n", offset ); |
|
1270 |
+ prn=pkg_malloc( offset ); |
|
1271 |
+ if (prn) { |
|
1272 |
+ for (t=0; t<offset; t++) |
|
1273 |
+ if (*(buffer+t)) *(prn+t)=*(buffer+t); |
|
1274 |
+ else *(prn+t)='�'; |
|
1275 |
+ LOG(L_INFO, "ERROR: parsed so far: %.*s\n", offset, prn ); |
|
1276 |
+ pkg_free( prn ); |
|
1277 |
+ }; |
|
1278 |
+error1: |
|
1279 |
+ fl->type=SIP_INVALID; |
|
1280 |
+ LOG(L_INFO, "ERROR:parse_first_line: bad message\n"); |
|
1281 |
+ /* skip line */ |
|
1282 |
+ nl=eat_line(buffer,len); |
|
1283 |
+ return nl; |
|
1284 |
+} |
1111 | 1285 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,56 @@ |
1 |
+/* |
|
2 |
+ * $Id$ |
|
3 |
+ */ |
|
4 |
+ |
|
5 |
+#ifndef PARSE_FLINE |
|
6 |
+#define PARSE_FLINE |
|
7 |
+ |
|
8 |
+#include "../str.h" |
|
9 |
+ |
|
10 |
+/* Message is a request */ |
|
11 |
+#define SIP_REQUEST 1 |
|
12 |
+ |
|
13 |
+/* Message is a reply */ |
|
14 |
+#define SIP_REPLY 2 |
|
15 |
+ |
|
16 |
+/* Invalid message */ |
|
17 |
+#define SIP_INVALID 0 |
|
18 |
+ |
|
19 |
+ |
|
20 |
+#define SIP_VERSION "SIP/2.0" |
|
21 |
+#define SIP_VERSION_LEN 7 |
|
22 |
+ |
|
23 |
+#define CANCEL "CANCEL" |
|
24 |
+#define ACK "ACK" |
|
25 |
+#define INVITE "INVITE" |
|
26 |
+ |
|
27 |
+#define INVITE_LEN 6 |
|
28 |
+#define CANCEL_LEN 6 |
|
29 |
+#define ACK_LEN 3 |
|
30 |
+#define BYE_LEN 3 |
|
31 |
+ |
|
32 |
+struct msg_start { |
|
33 |
+ int type; /* Type of the Message - Request/Response */ |
|
34 |
+ union { |
|
35 |
+ struct { |
|
36 |
+ str method; /* Method string */ |
|
37 |
+ str uri; /* Request URI */ |
|
38 |
+ str version; /* SIP version */ |
|
39 |
+ int method_value; |
|
40 |
+ } request; |
|
41 |
+ struct { |
|
42 |
+ str version; /* SIP version */ |
|
43 |
+ str status; /* Reply status */ |
|
44 |
+ str reason; /* Reply reason phrase */ |
|
45 |
+ unsigned int /* statusclass,*/ statuscode; |
|
46 |
+ } reply; |
|
47 |
+ }u; |
|
48 |
+}; |
|
49 |
+ |
|
50 |
+ |
|
51 |
+char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl); |
|
52 |
+ |
|
53 |
+char* parse_fline(char* buffer, char* end, struct msg_start* fl); |
|
54 |
+ |
|
55 |
+ |
|
56 |
+#endif |
... | ... |
@@ -14,6 +14,7 @@ |
14 | 14 |
#include "msg_parser.h" |
15 | 15 |
#include "../strs.h" |
16 | 16 |
#include "../dprint.h" |
17 |
+#include "../ut.h" /* q_memchr */ |
|
17 | 18 |
|
18 | 19 |
/* |
19 | 20 |
* Size of hash table, this is magic value |
... | ... |
@@ -66,26 +67,11 @@ static struct ht_entry *hash_table; |
66 | 67 |
/* |
67 | 68 |
* Declarations |
68 | 69 |
*/ |
69 |
-static inline char* q_memchr (char* p, int c, unsigned int size); |
|
70 | 70 |
static inline char* skip_ws (char* p, unsigned int size); |
71 | 71 |
void init_htable (void); |
72 | 72 |
static void set_entry (unsigned int key, unsigned int val); |
73 | 73 |
static inline int unify (int key); |
74 | 74 |
|
75 |
-/* |
|
76 |
- * Fast replacement of standard memchr function |
|
77 |
- */ |
|
78 |
-static inline char* q_memchr(char* p, int c, unsigned int size) |
|
79 |
-{ |
|
80 |
- char* end; |
|
81 |
- |
|
82 |
- end=p+size; |
|
83 |
- for(;p<end;p++){ |
|
84 |
- if (*p==(unsigned char)c) return p; |
|
85 |
- } |
|
86 |
- return 0; |
|
87 |