Documentation |
Documentation -> Development Manual 3.6 -> Parsing SIP MessagesThis page has been visited 187 times. Pages for other versions: devel 3.5 3.4 Older versions: 3.3 3.2 3.1
Table of Content (hide) The OpenSIPS SIP message parser is a lazy parser, which performs very well in terms of performance. The behavior is the following :
1. Generic Header ParserThe generic SIP header parser is exposed by parser/msg_parser.h. The function to be used is: /* Parameters : msg : the SIP message that needs to be parsed see parser/msg_parser.h for details on the struct sip_msg structure flags : bitmask of header types that need to be parsed next : specifies whether the parser should explicitly force the parsing of new headers from the provided bitmask, even though those header types were already previously found. Can be useful when trying to find a second occurrence of a header ( in the case that header can appear multiple times in a SIP message eg. Route ) Returns : 0 in case of error, -1 in case of error ( either header was not found or some other error occurred ). */ int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next);
if (parse_headers(req, HDR_CALLID_F|HDR_TO_F|HDR_FROM_F, 0) < 0 || !req->callid || !req->to || !req->from) { LM_ERR("bad request or missing CALLID/TO/FROM hdr\n"); return -1; } HDR_EOH_F can be used in order to parse all the headers in the current SIP message. The parse_headers() function will not duplicate SIP headers at all the hooks in the struct sip_msg structure will be populated with pointers that point directly in the SIP message buffer.
LM_INFO("The callid header name is %.*s and the callid header body is %.*s\n", req->callid->name.len, req->callid->name.s, req->callid->bodylen. req->callid->body.s); 2. Specific Header ParsingFor parsing a specific header type and extracting the header type relevant information, the parser/ directory contains all implementations for known headers.
The naming convention is that parser/parse_X.h will expose the parsing for the header named X.
int parse_to_header( struct sip_msg *msg) { struct to_body* to_b; if ( !msg->to && ( parse_headers(msg,HDR_TO_F,0)==-1 || !msg->to)) { LM_ERR("bad msg or missing To header\n"); goto error; } /* maybe the header is already parsed! */ if (msg->to->parsed) return 0; /* bad luck! :-( - we have to parse it */ /* first, get some memory */ to_b = pkg_malloc(sizeof(struct to_body)); if (to_b == 0) { LM_ERR("out of pkg_memory\n"); goto error; } /* now parse it!! */ memset(to_b, 0, sizeof(struct to_body)); parse_to(msg->to->body.s,msg->to->body.s+msg->to->body.len+1,to_b); if (to_b->error == PARSE_ERROR) { LM_ERR("bad to header\n"); pkg_free(to_b); goto error; } msg->to->parsed = to_b; return 0; error: return -1; }
Note that the void *parsed element in the hdr_field structure will contain the header specific parser structure, which will also be allocated into private memory and automatically freed when the SIP message processing has finished.
LM_INFO("The To header tag value is %.*s\n", get_to(msg)->tag_value.len, get_to(msg)->tag_value.s); 2.1 Parsing SIP URIsThe OpenSIPS parser also exposes the functionality of parsing individual SIP URI. /* Parameters : buf - the string which contains our SIP URI len - length of the SIP URI buffer uri - structure which will be populated by the function in case of success. See full struct sip_uri members in parser/msg_parser.h Returns : 0 in case of success, negative value in case of error parsing the URI */ int parse_uri(char *buf, int len, struct sip_uri* uri);
/* make sure TO header is parsed before this */ struct to_body *tb = get_to(msg); if (parse_uri(tb->uri.s, tb->uri.len , &tb->parsed_uri)<0) { LM_ERR("failed to parse To uri\n"); return -1; } LM_INFO(TO URI user is %.*s and TO URI domain is %.*s\n, tb->parsed_uri.user.len, tb->parsed_uri.user.s, tb->parsed_uri.domain.len, tb->parsed_uri.domain.s); 3. Parsing the SDP BodyOpenSIPS exposes functions for operating on the SIP message body.
/* Parameters : msg - the SIP message to fetch the body for body - output param, which will hold the body pointer inside the SIP message and the body length, or {NULL,0} in case of no body present Returns : 0 in case of success, or -1 in the case of parsing errors ( the function needs to internally parse all the headers in order to detect the body length ). */ int get_body(struct sip_msg *msg, str *body)
/* Parameters : _m - the SIP message to have it's SDP parsed Returns : 0 in case of success, negative in case of error */ int parse_sdp(struct sip_msg* _m);
|