FreeCalypso > hg > sipout-test-utils
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 } |
