FreeCalypso > hg > sipout-test-utils
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libsip/primary_parse.c Sun Mar 03 23:20:19 2024 -0800 @@ -0,0 +1,165 @@ +/* + * In this module we are going to implement the first stage of + * parsing for incoming SIP UDP packets, using struct sip_pkt_rx + * defined in parse.h. + */ + +#include <ctype.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include "parse.h" + +static +find_crlf(ptr, msg_end, endp, nextp) + char *ptr, *msg_end, **endp, **nextp; +{ + for (;;) { + if (ptr >= msg_end) + return(0); + switch (*ptr) { + case '\0': + return(0); + case '\n': + *endp = ptr; + *nextp = ptr + 1; + return(1); + case '\r': + *endp = ptr; + ptr++; + if (ptr >= msg_end) + return(0); + if (*ptr != '\n') + return(0); + *nextp = ptr + 1; + return(1); + } + ptr++; + } +} + +static +try_status_line(msg) + struct sip_pkt_rx *msg; +{ + if (strncasecmp(msg->pkt_buffer, "SIP/2.0 ", 8)) + return(0); + if (!isdigit(msg->pkt_buffer[8])) + return(0); + if (!isdigit(msg->pkt_buffer[9])) + return(0); + if (!isdigit(msg->pkt_buffer[10])) + return(0); + if (msg->pkt_buffer[11] != ' ') + return(0); + msg->status_code = atoi(msg->pkt_buffer + 8); + msg->status_str = msg->pkt_buffer + 8; + return(1); +} + +static +try_request_line(msg) + struct sip_pkt_rx *msg; +{ + char *cp; + + cp = msg->pkt_buffer; + if (!isupper(*cp)) + return(0); + while (isalnum(*cp)) + cp++; + if (*cp != ' ') + return(0); + msg->req_method = msg->pkt_buffer; + *cp++ = '\0'; + msg->req_uri = cp; + while (*cp && !isspace(*cp)) + cp++; + if (*cp != ' ') + return(0); + *cp++ = '\0'; + if (strcasecmp(cp, "SIP/2.0")) + return(0); + else + return(1); +} + +static void +trim_trailing_spaces(sp) + char *sp; +{ + char *ep; + + ep = index(sp, '\0'); + while (ep > sp && isspace(ep[-1])) + ep--; + *ep = '\0'; +} + +parse_incoming_sip_msg(msg) + struct sip_pkt_rx *msg; +{ + char *msg_end = msg->pkt_buffer + msg->pkt_length; + char *cp, *endp, *nextp, *sp; + unsigned hdr_cnt; + int rc; + + /* begin by isolating the Request-Line or Status-Line */ + rc = find_crlf(msg->pkt_buffer, msg_end, &endp, &nextp); + if (!rc) + return(-1); + *endp = '\0'; + if (try_status_line(msg)) + msg->parse_msgtype = SIP_MSG_TYPE_RESP; + else if (try_request_line(msg)) + msg->parse_msgtype = SIP_MSG_TYPE_REQ; + else + return(-1); + /* now preparse header fields */ + cp = nextp; + for (hdr_cnt = 0; ; ) { + rc = find_crlf(cp, msg_end, &endp, &nextp); + if (!rc) + return(-1); + if (endp == cp) /* final CRLF? */ + break; + if (!isalpha(*cp)) + return(-1); + if (hdr_cnt >= MAX_HEADER_FIELDS) + return(-2); + msg->hdr_fields[hdr_cnt].field_name = cp; + while (cp < endp && (isalnum(*cp) || *cp == '-')) + cp++; + if (cp >= endp) + return(-1); + if (*cp == ':') + *cp++ = '\0'; + else if (isspace(*cp)) { + *cp++ = '\0'; + while (cp < endp && isspace(*cp)) + cp++; + if (cp >= endp) + return(-1); + if (*cp++ != ':') + return(-1); + } else + return(-1); + sp = cp; + cp = nextp; + while (cp < msg_end && (*cp == ' ' || *cp == '\t')) { + rc = find_crlf(cp, msg_end, &endp, &nextp); + if (!rc) + return(-1); + cp = nextp; + } + *endp = '\0'; + while (isspace(*sp)) + sp++; + trim_trailing_spaces(sp); + msg->hdr_fields[hdr_cnt++].field_value = sp; + } + msg->num_hdr_fields = hdr_cnt; + msg->msg_body = nextp; + msg->msg_body_len = msg_end - nextp; + return(0); +}