FreeCalypso > hg > themwi-system-sw
view libsip/primary_parse.c @ 152:7176dc850d7a
sip-in hold/retr error handling: simply send BYE
Because we know that the SIP state is CONNECTED at the time of any
such error event, we can call initiate_bye() instead of disconnect_sip(),
and thereby get rid of struct gsm_mncc_cause which will never be used
in this scenario anyway.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 11 Oct 2022 16:11:21 -0800 |
parents | f1cf80c7e243 |
children |
line wrap: on
line source
/* * 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); }