zoukankan      html  css  js  c++  java
  • 基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(一)

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3945294.html。

    上章节讲解了利用自主开发的组件SIP组件libGBT28181SipComponent.so实现Linux 32平台的UAS和UAC,因为该组件采用很多新的技术,所以采用该组件效率无疑是很高的。但是对于想学习SIP协议,或者想了解eXosip2开发流程的程序员,是不能从根本上了解学习的。因为所有的功能都封装在libGBT28181SipComponent.so中。本讲将讲解一个用eXosip2库实现的Demo 程序。该Demo中包括UAS和UAC的实现。当然Demo实现比较粗糙,主要目的就是讲解eXosip2库的用法。该Demo讲的也是注册的过程,注册的流程在上一节已经有了详细的讲解,再次不赘述。源代码不多,直接上代码。

    一.源代码UAS main.cpp

      1 /*
      2  ===============================================================
      3  GBT28181 SIP组件libGBT28181SipComponent.so注册实现
      4  作者:程序人生
      5  博客地址:http://blog.csdn.net/hiwubihe
      6  QQ:1269122125
      7  注:请尊重原作者劳动成果,仅供学习使用,请勿盗用,违者必究!
      8  ================================================================
      9  */
     10 
     11 #include <iostream>
     12 #include <string>
     13 #include <sstream>
     14 #include <osipparser2/osip_message.h>
     15 #include <osipparser2/osip_parser.h>
     16 #include <osipparser2/osip_port.h>
     17 
     18 #include <eXosip2/eXosip.h>
     19 #include <eXosip2/eX_setup.h>
     20 #include <eXosip2/eX_register.h>
     21 #include <eXosip2/eX_options.h>
     22 #include <eXosip2/eX_message.h>
     23 #include <arpa/inet.h>
     24 #include <sys/types.h>
     25 #include <sys/socket.h>
     26 
     27 using namespace std;
     28 
     29 #define LISTEN_ADDR ("192.168.50.57")
     30 #define UASPORT (5060)
     31 
     32 
     33 //该系数是由UAS维护的,UAS在接收到UAC的未鉴权报文后,给UAC回复401,在该报文中必须要带相关认证系数和认证方法
     34 //UAS赋值的认证随机数
     35 #define NONCE "9bd055"
     36 //UAS默认加密算法
     37 #define ALGORITHTHM "MD5"
     38 
     39 
     40 //SIP From头部
     41 class CSipFromHeader
     42 {
     43 public:
     44     CSipFromHeader()
     45     {
     46     }
     47     ~CSipFromHeader()
     48     {
     49     }
     50     void SetHeader(string addrCod, string addrI, string addrPor)
     51     {
     52         addrCode = addrCod;
     53         addrIp = addrI;
     54         addrPort = addrPor;
     55     }
     56     string GetFormatHeader()
     57     {
     58         std::stringstream stream;
     59         stream << "<sip: " << addrCode << "@" << addrIp << ":" << addrPort
     60                 << ">";
     61         return stream.str();
     62     }
     63     //主机名称
     64     string GetRealName()
     65     {
     66         std::stringstream stream;
     67         stream << addrIp;
     68         return stream.str();
     69     }
     70 private:
     71     string addrCode;
     72     string addrIp;
     73     string addrPort;
     74 };
     75 
     76 //SIP Contract头部
     77 class CContractHeader: public CSipFromHeader
     78 {
     79 public:
     80     CContractHeader()
     81     {
     82     }
     83     ~CContractHeader()
     84     {
     85     }
     86     void SetContractHeader(string addrCod, string addrI, string addrPor,
     87             int expire)
     88     {
     89         SetHeader(addrCod, addrI, addrPor);
     90         expires = expire;
     91     }
     92     string GetContractFormatHeader(bool bExpires)
     93     {
     94         if (!bExpires)
     95         {
     96             return GetFormatHeader();
     97         }
     98         else
     99         {
    100             string sTmp = GetFormatHeader();
    101             std::stringstream stream;
    102             stream << ";" << "expires=" << expires;
    103             sTmp += stream.str();
    104             return sTmp;
    105         }
    106 
    107     }
    108 private:
    109     int expires;
    110 };
    111 
    112 struct SipContextInfo
    113 {
    114     //Sip层返回的请求的标志 响应时返回即可
    115     int sipRequestId;
    116     //维护一次注册
    117     string callId;
    118     //消息所属的功能方法名字符串
    119     string method;
    120     //地址编码@域名或IP地址:连接端口,例如sip:1111@127.0.0.1:5060
    121     CSipFromHeader from;
    122     //地址编码@域名或IP地址:连接端口,例如sip:1111@127.0.0.1:5060
    123     CSipFromHeader proxy;
    124     //地址编码@域名或IP地址:连接端口,例如sip:1111@127.0.0.1:5060
    125     CContractHeader contact;
    126     //消息内容,一般为DDCP消息体XML文档,或者具体协议帧要求的其他字符串文本
    127     string content;
    128     //响应状态信息
    129     string status;
    130     //超时,时间单位为秒
    131     int expires;
    132 };
    133 
    134 struct SipAuthInfo
    135 {
    136     //平台主机名
    137     string digestRealm;
    138     //平台提供的随机数
    139     string nonce;
    140     //用户名
    141     string userName;
    142     //密码
    143     string response;
    144     //“sip:平台地址”,不需要uac赋值
    145     string uri;
    146     //加密算法MD5
    147     string algorithm;
    148 };
    149 
    150 struct sipRegisterInfo
    151 {
    152     SipContextInfo baseInfo;
    153     SipAuthInfo authInfo;
    154     bool isAuthNull;
    155 };
    156 
    157 void parserRegisterInfo(osip_message_t*request, int iReqId,
    158         sipRegisterInfo &regInfo)
    159 {
    160     std::stringstream stream;
    161     regInfo.baseInfo.method = request->sip_method;
    162     regInfo.baseInfo.from.SetHeader(request->from->url->username,
    163             request->from->url->host, request->from->url->port);
    164     regInfo.baseInfo.proxy.SetHeader(request->to->url->username,
    165             request->to->url->host, request->to->url->port);
    166     //获取expires
    167     osip_header_t* header = NULL;
    168     {
    169         osip_message_header_get_byname(request, "expires", 
    170                 0, &header);
    171         if (NULL != header && NULL != header->hvalue)
    172         {
    173             regInfo.baseInfo.expires = atoi(header->hvalue);
    174         }
    175     }
    176     //contact字段
    177     osip_contact_t* contact = NULL;
    178     osip_message_get_contact(request, 0, &contact);
    179     if (NULL != contact)
    180     {
    181         regInfo.baseInfo.contact.SetContractHeader(contact->url->username,
    182                 contact->url->host, contact->url->port,
    183                 regInfo.baseInfo.expires);
    184     }
    185     //注册返回 由发送方维护的请求ID 接收方接收后原样返回即可
    186     regInfo.baseInfo.sipRequestId = iReqId;
    187     //CALL_ID
    188     {
    189         stream.str("");
    190         stream << request->call_id->number;
    191         regInfo.baseInfo.callId = stream.str();
    192     }
    193     //解析content消息
    194     osip_body_t * body = NULL;
    195     osip_message_get_body(request, 0, &body);
    196     if (body != NULL)
    197     {
    198         stream.str("");
    199         stream << body->body;
    200         regInfo.baseInfo.content = stream.str();
    201     }
    202     //鉴权信息
    203     osip_authorization_t* authentication = NULL;
    204     {
    205         osip_message_get_authorization(request, 0, &authentication);
    206         if (NULL == authentication)
    207         {
    208             regInfo.isAuthNull = true;
    209         }
    210         else
    211         {
    212             regInfo.isAuthNull = false;
    213             stream.str("");
    214             stream << authentication->username;
    215             regInfo.authInfo.userName = stream.str();
    216             stream.str("");
    217             stream << authentication->algorithm;
    218             regInfo.authInfo.algorithm = stream.str();
    219             stream.str("");
    220             stream << authentication->realm;
    221             regInfo.authInfo.digestRealm = stream.str();
    222             stream.str("");
    223             stream << authentication->nonce;
    224             regInfo.authInfo.nonce = stream.str();
    225             stream.str("");
    226             stream << authentication->response;
    227             regInfo.authInfo.response = stream.str();
    228             stream.str("");
    229             stream << authentication->uri;
    230             regInfo.authInfo.uri = stream.str();
    231         }
    232     }
    233     authentication = NULL;
    234 }
    235 
    236 //打印接收到的响应报文
    237 void printRegisterPkt( sipRegisterInfo&info)
    238 {
    239     cout<<"接收到报文:"<<endl;
    240     cout<<"=============================================="
    241             "=================="<<endl;
    242     cout << "method:" << info.baseInfo.method << endl;
    243     cout << "from:    " << info.baseInfo.from.GetFormatHeader() << endl;
    244     cout << "to:" << info.baseInfo.proxy.GetFormatHeader() << endl;
    245     cout << "contact:" << info.baseInfo.contact.GetContractFormatHeader(false)
    246             << endl;
    247 
    248     //注册返回 由发送方维护的请求ID 接收方接收后原样返回即可
    249     cout << "sipRequestId:" << info.baseInfo.sipRequestId << endl;
    250     //CALL_ID
    251     cout << "CallId:" << info.baseInfo.callId << endl;
    252     //解析content消息
    253     cout << "body:" << info.baseInfo.content << endl;
    254     //获取expires
    255     cout << "expires:" << info.baseInfo.expires << endl;
    256     //鉴权信息
    257     if (info.isAuthNull)
    258     {
    259         cout << "当前报文未提供鉴权信息!!!" << endl;
    260     }
    261     else
    262     {
    263         cout << "当前报文鉴权信息如下:" << endl;
    264         cout << "username:" << info.authInfo.userName << endl;
    265         cout << "algorithm:" << info.authInfo.algorithm << endl;
    266         cout << "Realm:" << info.authInfo.digestRealm << endl;
    267         cout << "nonce:" << info.authInfo.nonce << endl;
    268         cout << "response:" << info.authInfo.response << endl;
    269         cout << "uri:" << info.authInfo.uri << endl;
    270     }
    271      cout<<"=================================================="
    272              "=============="<<endl;
    273     return;
    274 }
    275 void sendRegisterAnswer( sipRegisterInfo&info)
    276 {
    277     osip_message_t* answer = NULL;
    278     int iStatus;
    279     if (info.isAuthNull)
    280     {
    281         iStatus = 401;
    282     }
    283     else
    284     {
    285         iStatus = 200;
    286     }eXosip_lock();
    287     {
    288         int result = ::eXosip_message_build_answer(info.baseInfo.sipRequestId,
    289                 iStatus, &answer);
    290         if (iStatus == 401)
    291         {
    292             //由SIP库生成认证方法和认证参数发送客户端
    293             std::stringstream stream;
    294             string nonce=NONCE;
    295             string algorithm=ALGORITHTHM;
    296             stream << "Digest realm="" << info.baseInfo.from.GetRealName() 
    297                     << "",nonce="" << nonce
    298                     << "",algorithm=" << algorithm;
    299 
    300             osip_message_set_header(answer, "WWW-Authenticate",
    301                     stream.str().c_str());
    302              cout<<"======================================================="
    303                      "========="<<endl;
    304              cout<<"发送401报文"<<endl;
    305              cout<<"========================================================"
    306                      "========"<<endl;
    307         }
    308         else if (iStatus == 200)
    309         {
    310             osip_message_set_header(answer, "Contact",
    311                     info.baseInfo.contact.GetContractFormatHeader(true).c_str());
    312              cout<<"========================================================="
    313                      "======="<<endl;
    314              cout<<"发送200报文"<<endl;
    315              cout<<"=========================================================="
    316                      "======"<<endl;
    317             //string_t b = "<sip: 100110000101000000@192.168.31.18:5061>;expires=600";
    318             //osip_message_set_header(answer, "Contact", b.c_str());
    319         }
    320         else
    321         {
    322             //Do nothing
    323         }
    324 
    325         if (OSIP_SUCCESS != result)
    326         {
    327             ::eXosip_message_send_answer(info.baseInfo.sipRequestId, 400, NULL);
    328         }
    329         else
    330         {
    331             //发送消息体
    332             ::eXosip_message_send_answer(info.baseInfo.sipRequestId, iStatus,
    333                     answer);
    334         }
    335         if (0 == info.baseInfo.expires)
    336         {
    337             eXosip_register_remove(info.baseInfo.sipRequestId);
    338         }
    339     }eXosip_unlock();
    340 }
    341 void OnRegister(eXosip_event_t *osipEvent)
    342 {
    343     sipRegisterInfo regInfo;
    344     parserRegisterInfo(osipEvent->request, osipEvent->tid, regInfo);
    345     //打印报文
    346     printRegisterPkt(regInfo);
    347     //发送应答报文
    348     sendRegisterAnswer(regInfo);
    349 
    350 }
    351 
    352 int main()
    353 {
    354 
    355     int result = OSIP_SUCCESS;
    356     // init exosip.
    357     if (OSIP_SUCCESS != (result = eXosip_init()))
    358     {
    359         printf("eXosip_init failure.
    ");
    360         return 1;
    361     }
    362     cout << "eXosip_init success." << endl;
    363     //
    364     //        if (null_ptr != this->receiveSipMessageCallback || null_ptr
    365     //                != this->sendSipMessageCallback)
    366     //        {
    367     //            if (OSIP_SUCCESS != (result = ::eXosip_set_cbsip_message(
    368     //                    &Sip::MessageCallback)))
    369     //            {
    370     //                return;
    371     //            }
    372     //        }
    373     eXosip_set_user_agent(NULL);
    374 
    375     if (OSIP_SUCCESS != eXosip_listen_addr(IPPROTO_UDP, NULL, UASPORT, AF_INET,
    376             0))
    377     {
    378         printf("eXosip_listen_addr failure.
    ");
    379         return 1;
    380     }
    381 
    382     if (OSIP_SUCCESS != eXosip_set_option(
    383     EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,
    384             LISTEN_ADDR))
    385     {
    386         return -1;
    387     }
    388     //开启循环消息,实际应用中可以开启多线程同时接收信号
    389     eXosip_event_t* osipEventPtr = NULL;
    390 
    391     while (true)
    392     {
    393         // Wait the osip event.
    394         osipEventPtr = ::eXosip_event_wait(0, 200);// 0的单位是秒,500是毫秒
    395         // If get nothing osip event,then continue the loop.
    396         if (NULL == osipEventPtr)
    397         {
    398             continue;
    399         }
    400         // 事件处理
    401 
    402         switch (osipEventPtr->type)
    403         {
    404 
    405         //需要继续验证REGISTER是什么类型
    406         case EXOSIP_REGISTRATION_NEW:
    407             OnRegister(osipEventPtr);
    408             break;
    409         case EXOSIP_MESSAGE_NEW:
    410         {
    411             if (!strncmp(osipEventPtr->request->sip_method, "REGISTER", 
    412                     strlen("REGISTER")))
    413             {
    414                 OnRegister(osipEventPtr);
    415             }
    416             else if (!strncmp(osipEventPtr->request->sip_method, "MESSAGE",
    417                     strlen("MESSAGE")))
    418             {
    419                 //
    420             }
    421         }
    422             break;
    423         default:
    424             cout
    425                     << "The sip event type that not be precessed.the event "
    426                             "type is : "
    427                     << osipEventPtr->type;
    428             break;
    429         }
    430         //ProcessSipEvent(this->osipEventPtrParam);
    431         eXosip_event_free(osipEventPtr);
    432         osipEventPtr = NULL;
    433     }
    434 
    435     return 0;
    436 }

    二.UAC源代码

     参看下一篇 基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(二)

    三.测试效果

    1.UAS启动后,接受到报文效果

    2.UAS发送401回复报文

    3.UAS接受到带鉴权报文

    4.UAS回复200OK

    欢迎技术交流沟通,转载请注明出处并保持作品的完整性。 作者:程序人生 qq1269122125
  • 相关阅读:
    JBoss中配置虚拟目录以及设置浏览器地址输入框支持中文的方法
    实现表格鼠标经过变色,点击变色并选中项目
    JBoss4.0与金山词霸有端口冲突
    Hibernate查询方式比较
    数字证书使用Javascript在浏览器中自动安装的解决方案
    JBoss设置URI编码,使浏览器URL支持中文
    VC++中list的使用方式
    使用JBoss管理数据库连接的方法(JDNI方式)
    CefSharp中实现Chrome中jS导出Excel
    WP7备注(27)(DependencyProperty|RoutedPropertyChangedEventHandler)
  • 原文地址:https://www.cnblogs.com/qq1269122125/p/3945294.html
Copyright © 2011-2022 走看看