在C中解析SIP数据包

时间:2011-02-23 15:40:01

标签: c parsing sip

我正在尝试解析SIP数据包并从中获取一些信息。更具体地说,数据包看起来像这样

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

现在,我需要从该数据包中提取以下内容:

  • “发件人:”之后的值(本例中为<sip:alice@open-ims.test>
  • “联系人:”之后的值(本例中为<sip:alice@192.168.1.64
  • “用户名”之后的值(在本例中为alice@open-ims.test

到目前为止,我的代码是

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);  
        }
    }

如果有效负载包含如上所述的数据包。

但是,当我运行程序时,会导致分段错误。奇怪的是,如果我在strtok中使用字符“&lt;&gt ;;:”并在strcmp中使用值“sip”,则消息将成功解析并保留保存的值。但我需要解析所有三个上限值。

sip图书馆会帮助我解决我的问题吗?

提前致谢

6 个答案:

答案 0 :(得分:4)

我认为这样的事情可以起作用

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); 

答案 1 :(得分:3)

回应Rup提供的评论,我也建议使用图书馆,因为已经为你完成了所有繁重的工作,你可以花更多的时间专注于你试图用解析的信息完成的事情。

GNU oSIP library可能是个好地方。

来自online documentation

   SIP parser:
   ==========
     

实施的初始功能   osip是一个SIP解析器。那没有   很多话要说:它有能力   解析和重新格式化SIP请求   和答案。

     

解析工具的详细信息   可用的如下:

     

1 SIP请求/回答
   2 SIP uri
   3个特定标题
   4通过
   5 CSeq
   6呼叫ID
   7 To,From,Route,Record-Route ...
   8认证相关标题
   9内容相关标题
   10接受相关标题
   11 ...
   12通用标题
   13 Attachement解析器(应该支持mime)
   14 SDP解析器

答案 2 :(得分:1)

阅读每一行并使用strstr()搜索每个子字符串('来源:','联系人:','用户名')。

如果您遇到包含某个关键字的行,请将其拆分为strtok()并相应地提取您需要的内容。

我不知道你是否需要一个完整的SIP lib来提取这三个东西,但是如果你将来可能需要解析更多的数据包,那可能不是一个坏主意。

答案 3 :(得分:1)

如果可能,请使用解析器。 SIP语法的语法非常复杂,以至于许多ABNF解析器无法处理RFC 3261 ABNF。如果你仍然在想自己编写它是一个好主意,你应该熟悉RFC 4475,SIP酷刑测试,因为你应该使用它们,如果这将与其他系统交互,并且因为它会告诉你为什么它如此很难做对。

答案 4 :(得分:0)

对于使用“&lt;&gt;;”的strtok,我希望您的数据包可以拆分为以下内容(删除换行符)

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 

这些都不匹配

 if (!strcmp(tch, "From: "))     

您需要修改解析器或搜索strtok返回的字符串“From:”。

答案 5 :(得分:0)

strtok每次都不必使用同一组分隔符。您可以在期望字段标签时使用冒号,并在期望右侧时将其关闭。