comparison libsip/primary_parse.c @ 0:35c0d9f03c0a

beginning with sipout-test-voice, a copy of sip-manual-out from themwi-system-sw
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 03 Mar 2024 23:20:19 -0800
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:35c0d9f03c0a
1 /*
2 * In this module we are going to implement the first stage of
3 * parsing for incoming SIP UDP packets, using struct sip_pkt_rx
4 * defined in parse.h.
5 */
6
7 #include <ctype.h>
8 #include <string.h>
9 #include <strings.h>
10 #include <stdlib.h>
11 #include "parse.h"
12
13 static
14 find_crlf(ptr, msg_end, endp, nextp)
15 char *ptr, *msg_end, **endp, **nextp;
16 {
17 for (;;) {
18 if (ptr >= msg_end)
19 return(0);
20 switch (*ptr) {
21 case '\0':
22 return(0);
23 case '\n':
24 *endp = ptr;
25 *nextp = ptr + 1;
26 return(1);
27 case '\r':
28 *endp = ptr;
29 ptr++;
30 if (ptr >= msg_end)
31 return(0);
32 if (*ptr != '\n')
33 return(0);
34 *nextp = ptr + 1;
35 return(1);
36 }
37 ptr++;
38 }
39 }
40
41 static
42 try_status_line(msg)
43 struct sip_pkt_rx *msg;
44 {
45 if (strncasecmp(msg->pkt_buffer, "SIP/2.0 ", 8))
46 return(0);
47 if (!isdigit(msg->pkt_buffer[8]))
48 return(0);
49 if (!isdigit(msg->pkt_buffer[9]))
50 return(0);
51 if (!isdigit(msg->pkt_buffer[10]))
52 return(0);
53 if (msg->pkt_buffer[11] != ' ')
54 return(0);
55 msg->status_code = atoi(msg->pkt_buffer + 8);
56 msg->status_str = msg->pkt_buffer + 8;
57 return(1);
58 }
59
60 static
61 try_request_line(msg)
62 struct sip_pkt_rx *msg;
63 {
64 char *cp;
65
66 cp = msg->pkt_buffer;
67 if (!isupper(*cp))
68 return(0);
69 while (isalnum(*cp))
70 cp++;
71 if (*cp != ' ')
72 return(0);
73 msg->req_method = msg->pkt_buffer;
74 *cp++ = '\0';
75 msg->req_uri = cp;
76 while (*cp && !isspace(*cp))
77 cp++;
78 if (*cp != ' ')
79 return(0);
80 *cp++ = '\0';
81 if (strcasecmp(cp, "SIP/2.0"))
82 return(0);
83 else
84 return(1);
85 }
86
87 static void
88 trim_trailing_spaces(sp)
89 char *sp;
90 {
91 char *ep;
92
93 ep = index(sp, '\0');
94 while (ep > sp && isspace(ep[-1]))
95 ep--;
96 *ep = '\0';
97 }
98
99 parse_incoming_sip_msg(msg)
100 struct sip_pkt_rx *msg;
101 {
102 char *msg_end = msg->pkt_buffer + msg->pkt_length;
103 char *cp, *endp, *nextp, *sp;
104 unsigned hdr_cnt;
105 int rc;
106
107 /* begin by isolating the Request-Line or Status-Line */
108 rc = find_crlf(msg->pkt_buffer, msg_end, &endp, &nextp);
109 if (!rc)
110 return(-1);
111 *endp = '\0';
112 if (try_status_line(msg))
113 msg->parse_msgtype = SIP_MSG_TYPE_RESP;
114 else if (try_request_line(msg))
115 msg->parse_msgtype = SIP_MSG_TYPE_REQ;
116 else
117 return(-1);
118 /* now preparse header fields */
119 cp = nextp;
120 for (hdr_cnt = 0; ; ) {
121 rc = find_crlf(cp, msg_end, &endp, &nextp);
122 if (!rc)
123 return(-1);
124 if (endp == cp) /* final CRLF? */
125 break;
126 if (!isalpha(*cp))
127 return(-1);
128 if (hdr_cnt >= MAX_HEADER_FIELDS)
129 return(-2);
130 msg->hdr_fields[hdr_cnt].field_name = cp;
131 while (cp < endp && (isalnum(*cp) || *cp == '-'))
132 cp++;
133 if (cp >= endp)
134 return(-1);
135 if (*cp == ':')
136 *cp++ = '\0';
137 else if (isspace(*cp)) {
138 *cp++ = '\0';
139 while (cp < endp && isspace(*cp))
140 cp++;
141 if (cp >= endp)
142 return(-1);
143 if (*cp++ != ':')
144 return(-1);
145 } else
146 return(-1);
147 sp = cp;
148 cp = nextp;
149 while (cp < msg_end && (*cp == ' ' || *cp == '\t')) {
150 rc = find_crlf(cp, msg_end, &endp, &nextp);
151 if (!rc)
152 return(-1);
153 cp = nextp;
154 }
155 *endp = '\0';
156 while (isspace(*sp))
157 sp++;
158 trim_trailing_spaces(sp);
159 msg->hdr_fields[hdr_cnt++].field_value = sp;
160 }
161 msg->num_hdr_fields = hdr_cnt;
162 msg->msg_body = nextp;
163 msg->msg_body_len = msg_end - nextp;
164 return(0);
165 }