首页 > 代码库 > 基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现

基于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 SipContextInfo113 {114     //Sip层返回的请求的标志 响应时返回即可115     int sipRequestId;116     //维护一次注册117     string callId;118     //消息所属的功能方法名字符串119     string method;120     //地址编码@域名或IP地址:连接端口,例如sip:1111@127.0.0.1:5060121     CSipFromHeader from;122     //地址编码@域名或IP地址:连接端口,例如sip:1111@127.0.0.1:5060123     CSipFromHeader proxy;124     //地址编码@域名或IP地址:连接端口,例如sip:1111@127.0.0.1:5060125     CContractHeader contact;126     //消息内容,一般为DDCP消息体XML文档,或者具体协议帧要求的其他字符串文本127     string content;128     //响应状态信息129     string status;130     //超时,时间单位为秒131     int expires;132 };133 134 struct SipAuthInfo135 {136     //平台主机名137     string digestRealm;138     //平台提供的随机数139     string nonce;140     //用户名141     string userName;142     //密码143     string response;144     //“sip:平台地址”,不需要uac赋值145     string uri;146     //加密算法MD5147     string algorithm;148 };149 150 struct sipRegisterInfo151 {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     //获取expires167     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_ID188     {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         else211         {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_ID251     cout << "CallId:" << info.baseInfo.callId << endl;252     //解析content消息253     cout << "body:" << info.baseInfo.content << endl;254     //获取expires255     cout << "expires:" << info.baseInfo.expires << endl;256     //鉴权信息257     if (info.isAuthNull)258     {259         cout << "当前报文未提供鉴权信息!!!" << endl;260     }261     else262     {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     else284     {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=\"" << nonce298                     << "\",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         else321         {322             //Do nothing323         }324 325         if (OSIP_SUCCESS != result)326         {327             ::eXosip_message_send_answer(info.baseInfo.sipRequestId, 400, NULL);328         }329         else330         {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.\n");360         return 1;361     }362     cout << "eXosip_init success." << endl;363     //364     //        if (null_ptr != this->receiveSipMessageCallback || null_ptr365     //                != 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.\n");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             cout425                     << "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源代码

三.测试效果

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

2.UAS发送401回复报文

3.UAS接受到带鉴权报文

4.UAS回复200OK

 

基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现