SIP Router Project


FS#170 - get_body_part2 (parse_body)

Attached to Project: sip-router
Opened by Luis Martin (lmartin) - Friday, 28 October 2011, 16:57 GMT
Last edited by Daniel-Constantin Mierla (miconda) - Tuesday, 26 February 2013, 15:40 GMT
Task Type Improvement
Category Core
Status Closed
Assigned To Daniel-Constantin Mierla (miconda)
Operating System All
Severity Low
Priority Normal
Reported Version Development
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 0
Private No


I made a new function for the “parser/parse_body.c” module : get_body_part2

char *get_body_part(struct sip_msg *msg, unsigned short type, unsigned short subtype, int *len)

get_body_part allows you to pick the first multipart part of the SIP message which matches TYPE/SUBTYPE. It will return a pointer to the multipart structure as well as its length. The code it is not easy-readable but this function is working great. The point is, what if I would like to search a multipart part within a SIP message that matches TYPE/SUBTYPE but also the Content-ID header or the Content-Length header?

New function:

char *get_body_part_strict(struct sip_msg *msg, unsigned short content_type, unsigned short content_subtype, char *content_id, char *content_length, int *len)

It returns the first multipart part of the SIP message which matches “TYPE/SUBTYPE” and/or the “Content-ID” and/or the “Content-Length”, and its length. If you want to be less restrictive, you can unflag the parameter by:
- setting 0/0 in case of the TYPE/SUBTYPE.
- setting NULL in case of the Content-ID and the Content-Length.

So setting Content-Length == NULL will make the function to skip the Content-Length from its filter and will give you back the first part which matches the TYPE/SUBTYPE and Content-ID, and its length.

Already tested and working fine.

See patch attached.

Luis Martin Gil

This task depends upon

Closed by  Daniel-Constantin Mierla (miconda)
Tuesday, 26 February 2013, 15:40 GMT
Reason for closing:  Implemented
Additional comments about closing:  Done by commit 9365c5c19cb0b9d4300fa5b0a220bf19738c808f
Comment by Iñaki Baz Castillo (ibc) - Saturday, 29 October 2011, 12:06 GMT

Hi, I’m not an expert in multipart bodies. What is the use case of matching by Content-ID? Could you please explain it with an example?

Thanks a lot.

Comment by Luis Martin (lmartin) - Monday, 31 October 2011, 02:14 GMT

There could scenarios where more than one multipart part with the same TYPE/SUBTYPE are conveyed within the SIP message. How to search for the correct one? In that cases the Content-ID should be provided and is gonna be the key in your multipart search.

Let’s say there is an incoming SIP INVITE with some xml information:
Session Initiation Protocol

  Request-Line: INVITE
      Method: INVITE
  Message Header
      Content-Type: multipart/mixed;boundary=unique-boundary-001
      Content-Length:  900
  Message Body
      MIME Multipart Media Encapsulation, Type: multipart/mixed, Boundary: "unique-boundary-001"
          [Type: multipart/mixed]
          First boundary: --unique-boundary-001\r\n
          Encapsulated multipart part:  (application/sdp)
              Content-Type: application/sdp\r\n
              Content-Length:   400\r\n\r\n
              Session Description Protocol
          Boundary: \r\n--unique-boundary-001\r\n
          Encapsulated multipart part:  (application/xml)
              Content-ID: content1\r\n
              Content-Type: application/xml\r\n
              Content-Length:  300\r\n\r\n
              eXtensible Markup Language
          Boundary: \r\n--unique-boundary-001\r\n
          Encapsulated multipart part:  (application/xml)
              Content-ID: content2\r\n
              Content-Type: application/xml\r\n
              Content-Length:  200\r\n\r\n
              eXtensible Markup Language
          Last boundary: \r\n--unique-boundary-001--\r\n

What if you want to get the second application/xml part of the multipart message?
get_body_part can’t retrieve that
get_body_part2 can retrieve that part with:
“get_body_part2(msg, APPLICATION, XML, “content2”, NULL, &len)” and also with:
“get_body_part2(msg, 0, 0, “content2”, NULL, &len)”

Hope it helps,

Comment by Iñaki Baz Castillo (ibc) - Thursday, 03 November 2011, 00:07 GMT

It makes sense :)

Comment by Luis Martin (lmartin) - Tuesday, 08 November 2011, 13:39 GMT

I made a mistake while renaming one variable before sending the patch to Kamailio. Here is the new patch which is the one that should be used.

Luis Martin

Comment by Daniel-Constantin Mierla (miconda) - Sunday, 24 February 2013, 18:16 GMT

There seems to be an issue in function:

+int part_multipart_headers_cmp (char *buffer,
+ char *end_buffer,
+ unsigned short content_type,
+ unsigned short content_subtype,
+ char *content_id,
+ char *content_length)
+ int error = 0;
+ char *error_msg = NULL;
+ char *cpy_c = NULL;
+ char *cpy_d = NULL;
+ char *value_ini = NULL;
+ char *value_fin = NULL;
+ unsigned int umime;
+ int found = 0;
+ int found_content_type = 0;
+ int found_content_id = 0;
+ int found_content_length = 0;
+ if 1) {
+ error = -1;
+ error_msg = “buffer and/or end_buffer are NULL”;
+ } else {
+ *cpy_c = buffer;
+ *cpy_d = end_buffer;

cpy_c and cpy_d are initialized to NULL, but then values are stored at that address (the last two lines above). Did you want to have:

+ cpy_c = buffer;
+ cpy_d = end_buffer;

1) buffer == NULL) || (end_buffer == NULL
Comment by Luis Martin (lmartin) - Monday, 25 February 2013, 17:40 GMT

It would be the same. I implemented that way because I think that improves the code readability. Changing it to the solution you’re pointing will be ok.

Comment by Daniel-Constantin Mierla (miconda) - Monday, 25 February 2013, 18:09 GMT

Maybe I miss something it the code, what i see is:

+ char *cpy_c = NULL;
+ char *cpy_d = NULL;
+ *cpy_c = buffer;
+ *cpy_d = end_buffer;

The compiler gives warnings, as well.

Unless I missed some logic, it actually results in:

*NULL = buffer;
*NULL = end_buffer;

So it tries to write a pointer at address 0×0.

Comment by Luis Martin (lmartin) - Tuesday, 26 February 2013, 14:38 GMT

You are not missing anything Daniel, I made a mistake and yesterday misunderstood what you were saying. Let me explain it to you:

First I sent the original patch (Friday, 28 October 2011, 16:57 GMT)
Then I realized I had an error because I renamed some variables to improve the readability. (Tuesday, 08 November 2011, 13:39 GMT)

Now you are letting me know this, and you are right, in the renaming I also missed that part of the code. I just checked that version I’m running and should be as your are pointing out:
+ cpy_c = buffer;
+ cpy_d = end_buffer;

I diff with the version that I’m running and that should work just fine.