原创文章,引用请保证原文完整性,尊重作者劳动,原文地址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.\n");
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.\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             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

基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(一)相关推荐

  1. 基于GBT28181:SIP协议组件开发-----------第三篇SIP注册流程分析实现

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3941172.html,qq:1269122125. 上两章节简要的 ...

  2. 基于GBT28181:SIP协议组件开发-----------第五篇SIP注册流程eXosip2实现(二)

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3966794.html. 上章节讲解了讲解一个用eXosip2库实现 ...

  3. ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl

    第四章 组合控件开发CompositeControl 大家好,今天我们来实现一个自定义的控件,之前我们已经知道了,要开发自定义的控件一般继承三个基 类:Control,WebControl,还有一个就 ...

  4. Agv、Rgv 车辆控制调度系统开发第四篇

    Agv.Rgv 车辆控制调度系统开发第四篇 车辆调度模拟器 前言 一.车辆模拟器是什么? 二.如何做模拟器 1.动作仿真模拟器 2.完全仿真模拟器 总结 下期预告 系列文章链接 其他文章 新篇章 前言 ...

  5. 基于Mozilla Thunderbird的扩展开发(四)---修改Thunderbird源代码实现自动保存附件...

    <?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace ...

  6. SIP协议简介(一)之SIP基本的概述

    本篇文章主要是对RFC3261翻译进行的,也包含着自己的一些理解.希望能给需要的人带来一些帮助 补充说明:RFC即Request For Comments(RFC),是一系列以编号排定的文件.文件收集 ...

  7. python基于什么语言-一种基于Python语言的EDA开发平台及其使用方法与流程

    本发明涉及EDA开发的技术领域,尤其是指一种基于Python语言的EDA开发平台及其使用方法. 背景技术: 目前,主流的EDA设计语言Verilog HDL能实现完整的芯片硬件逻辑电路开发,但是其代码 ...

  8. python语言的编程模式_一种基于Python语言的EDA开发平台及其使用方法与流程

    本发明涉及EDA开发的技术领域,尤其是指一种基于Python语言的EDA开发平台及其使用方法. 背景技术: 目前,主流的EDA设计语言Verilog HDL能实现完整的芯片硬件逻辑电路开发,但是其代码 ...

  9. uniapp中使用ucharts组件开发App中的折线图流程

    uniapp中使用ucharts组件开发流程 官方ucharts地址 我是在uniapp使用echarts后发现在安卓手机app上不显示,所以使用ucharts来代替echarts 组件地址 在这里导 ...

最新文章

  1. svg animation应用之-描边效果
  2. QMouseEvent
  3. excel vba 调用webbrowser_Python杀死Excel?我只会用Python来增强Excel!
  4. maven 之 setting.xm 的配置详解、说明
  5. Cause: java.lang.IllegalArgumentException: No enum constant org.apache.ibatis.type.JdbcType.Date
  6. 【WCF】WCF服务库和WCF服务应用程序的区别
  7. bc显示小数点前的0
  8. python逐行读取txt文件-在python 3.4上逐行读取文本文件
  9. android framework 触摸屏事件传递
  10. 《转载》python爬虫实践之模拟登录
  11. WPF-21:WPF实现仿安卓的图案密码键盘(改进)
  12. project安装包_Microsoft project 2019软件功能介绍(附安装包)
  13. Android Builder模式
  14. python热身教程_[转载]技术教程-MayaPython教程二之Python
  15. 宝塔nginx自编译云锁web防护教程
  16. RK3399:HDMI输出固定频率与热插拔
  17. 吴恩达《机器学习》第四章:多元线性回归
  18. Python爬虫:js加密实例-有道翻译
  19. linux火车游戏,火车路路通安卓版下载-火车路路通手机版下载v1.0-Linux公社
  20. ZZNUOJ_C语言1123:最佳校友(附完整源码)

热门文章

  1. 【Matlab指纹识别】指纹识别匹配门禁系统【含GUI源码 587期】
  2. python基于django的同学校友录网站
  3. 《巴菲特的护城河》书中的精髓:如何识别有投资价值的公司,让你投资的钱不再打水漂?
  4. R-CNN简述(目标检测篇)
  5. 使用CNN,RNN和HAN 进行文本分类
  6. 电子学习电子设计竞赛必会元件清单!!!
  7. python 设置精度_在python中以全微秒精度设置文件的mtime
  8. 财务分析和决策学习笔记
  9. UNIX网络编程unp.h配置
  10. 字符编码--第3章 字符的存储--ASCII(1967年)