Parse SIP packet in C
I am trying to parse a SIP packet and get some information out of it. To be more specific, the packet looks like this
REGISTER sip:open-ims.test SIP/2.0
Via: SIP/2.0/UDP 192.168.1.64:5060;rport;branch=z9hG4bK1489975971
From: <sip:alice@open-ims.test>;tag=1627897650
To: <sip:alice@open-ims.test>
Call-ID: 1097412971
CSeq: 1 REGISTER
Contact: <sip:alice@192.168.1.64:5060;line=5fc3b39f127158d>;+sip.instance="<urn:uuid:46f525fe-3f60-11e0-bec1-d965d1488cfa>"
Authorization: Digest username="alice@open-ims.test", realm="open-ims.test", nonce=" ", uri="sip:open-ims.test", response=" "
Max-Forwards: 70
User-Agent: UCT IMS Client
Expires: 600000
Supported: path
Supported: gruu
Content-Length: 0
Now, from that packet I need to extract the following :
- The value after "From: " ( in this case
<sip:alice@open-ims.test>
) - The value after "Contact: " ( in this case
<sip:alice@192.168.1.64
) - The value after "username" ( in this case
alice@open-ims.test
)
My code so far is this
char * tch;
char * saved;
tch = strtok (payload,"<>;");
while (tch != NULL)
{
int savenext = 0;
if (!strcmp(tch, "From: "))
{
savenext = 1;
}
tch = strtok (NULL, "<开发者_开发问答>;");
if (savenext == 1)
{
saved = tch;
}
}
printf ("### SIP Contact: %s ###\n", saved);
}
}
Where payload contains the packet as described above.
However, when I run my program, it will result in a segmentation fault. The weird thing is that if I use in strtok the characters "<>;: " and in strcmp the value "sip" the message will parse successfully and it will keep the saved value. But I need to parse all three of the upper values.
Would a sip library help me more with my problem ?
Thanks in advance
I think something like this could work
char * tch;
char * saved;
tch = strtok (payload,"<>;\n\"");
while (tch != NULL)
{
int savenext = 0;
if (strncmp(tch, "From",4)==0)
{
tch = strtok (NULL, "<>;\n\"");
saved = tch;
printf (" SIP From: %s \n", saved);
}
else if (strncmp(tch, "Contact",7)==0)
{
tch = strtok (NULL, "<>;\n\"");
saved = tch;
printf (" SIP Cont: %s \n", saved);
}
if (strncmp(tch, "Authorization",13)==0)
{
tch = strtok (NULL, "<>;\n\"");
saved = tch;
printf (" SIP User: %s \n", saved);
Echoing the comment provided by Rup, I too would recommend using a library as all the heavy lifting has been done for you and you can spend more time focusing on what you are attempting to accomplish with the parsed information.
The GNU oSIP library may be a good place to start.
From the online documentation:
SIP parser: ==========
The initial feature implemented in osip is a SIP parser. There is not much to say about it: it is capable of parsing and reformating SIP requests and answers.
The details of the parsing tools available are listed below:
1 SIP request/answer
2 SIP uri
3 specific headers
4 Via
5 CSeq
6 Call-ID
7 To, From, Route, Record-Route...
8 Authentication related headers
9 Content related headers
10 Accept related headers
11 ...
12 Generic header
13 Attachement parser (should support mime)
14 SDP parser
Use a parser if you possibly can. SIP syntax has a grammar so complex that many ABNF parsers can't handle the RFC 3261 ABNF. If you're still thinking writing it yourself is a good idea, you should get familiar with RFC 4475, the SIP torture tests because you should use them if this is going to interact with other systems, and because it will show you why it's so hard to get right.
Read each line and search for each of your substrings ('From:', 'Contact:', 'username') using strstr()
.
When you encounter a line that contains one of your keywords, split it with strtok()
and extract the piece you need accordingly.
I don't know if you need a full-blown SIP lib for extracting these three things, but if you might need to parse more of the packet in the future, it might not be a bad idea.
For strtok use with "<>;", I'd expect your packet to be split into something like the following (newlines removed)
REGISTER sip:open-ims.test SIP/2.0Via: SIP/2.0/UDP 192.168.1.64:5060
rport
branch=z9hG4bK1489975971From:
sip:alice@open-ims.test
None of these will match
if (!strcmp(tch, "From: "))
You'd either need to modify your parser or search through the string returned by strtok for "From: ".
strtok
doesn't have to use the same set of delimiters every time. You can use a colon when you are expecting a field label and leave it off when you are expecting the right hand side.
精彩评论