1. 程式人生 > >基於GBT28181:SIP協議元件開發-----------第三篇SIP註冊流程分析實現

基於GBT28181:SIP協議元件開發-----------第三篇SIP註冊流程分析實現

原創文章,引用請保證原文完整性,尊重作者勞動,原文地址http://www.cnblogs.com/qq1269122125/p/3941172.html,qq:1269122125。

上兩章節簡要的講解了SIP元件開發介面和開發環境的搭建。在本節將實現Linux 32平臺的UAS和UAC,當然該UAS和UAC只實現了註冊功能,並且是基於自主開發SIP元件libGBT28181SipComponent.so的,沒有這個元件是執行不了的。其他功能在後續章節中講解。

首先簡單講解一下GBT28181關於註冊描述

一. GBT28181註冊的流程如下圖

         

          電力系統註冊稍微複雜點,但原來基本相同。多了個重新整理註冊的過程。

             

二.GBT28181關於註冊的解釋如下


三.SIP協議簡介

一個合法的SIP請求必須至少包含如下頭域:TO,FROM,Cseq,Call-ID,Max-Forwards, Via;這些欄位在所有SIP請求中必須包含。這6個欄位是SIP訊息的基本組成部分,他們提供了用於路由用的核心資訊,包含了訊息的地址,響應的路由,訊息傳遞次數,詳細的順序,事務的唯一標誌。 

這些頭域欄位是必須包含在請求行之後的,請求行包含了請求的方法,Request-URI,SIP的版本號碼。請求行例子:REGISTER sip:192.168.10.177:5060 SIP/2.0

四.GBT28181註冊流程如下

 1.UAC--->UAS 傳送請求登入,傳送未鑑權資訊

 

 From 欄位,由UAS管理的UAC地址編碼@UAS IP:UAS埠號。在實際過程中,UAS管理很多的UAC每個UAC都會儲存一個地址編碼(可以理解為使用者名稱)和密碼等UAC的資訊,當UAC登入時,用於驗證UAC身份的合法性。

 To欄位,From相同

 Contact欄位是通訊資訊欄位,儲存是本地UAC地址編碼@本地IP:UAC埠號

 Call-ID地段,對應用層是必須要的,一次成功登入完成後要儲存這個Call_id值,因為這個ID是標誌這次註冊的唯一標誌。在後續的登出登入及重新整理登入都必須要這個ID.。

 Cseq值保證了REGISTER請求的正確順序

 Expires欄位:表示該登記生存期為3600s。

 Content-Length欄位:表明此請求訊息訊息體的長度為空,即此訊息不帶會話描述

2.UAS--->UAC  exosip庫在傳送註冊請求時,第一次傳送未鑑權資訊,UAS收到後回覆401,並攜帶認證體制(如MD4)和認證引數(如nonce值)。


3.UAC--->UAS  UAC在收到401資訊後,根據UAS傳送的401資訊中的認證體制和認證引數,結合使用者名稱和密碼,生成response值。傳送鑑權訊息。

 

4.UAS--->UAC UAS收到鑑權資訊後,根據自己自身的管理體制,找到UAC使用者在伺服器中的密碼,根據UAC傳送的認證體制和認證引數,結合使用者名稱和密碼,生成response值,在把response和UAC傳送的response比較,相等則認證通過傳送 200 ok。不等傳送404驗證失敗。


五.原始碼

這裡註冊功能雖然簡單,但是為了後續其他功能的新增,這裡還是根據功能劃分了幾個模組。後續新增功能,只是在這個框架中新增。

UAS_test部分程式碼:

1.主要功能檔案method.h

 1 /*
 2 ===============================================================
 3     GBT28181 SIP元件libGBT28181SipComponent.so註冊實現
 4     作者:程式人生
 5     部落格地址:http://blog.csdn.net/hiwubihe
 6     QQ:1269122125
 7     注:請尊重原作者勞動成果,僅供學習使用,請勿盜用,違者必究!
 8 ================================================================
 9 */
10 
11 #ifndef METHOD_H_
12 #define METHOD_H_
13 #include <iostream>
14 #include <cstdlib>
15 #include <stdio.h>
16 #include "callback.h"
17 #include "IGBT28181Comm.h"
18 #include "sipserver.h"
19 
20 
21 using namespace GBT28181::Vsp;
22 using namespace std;
23 
24 //啟動UAS角色的伺服器
25 int server_start(void*addr);
26 //停止UAS角色伺服器
27 void server_stop();
28 
29 
30 #endif /* METHOD_H_ */

2.method.cpp 實現檔案中,開啟服務包括啟動服務和設定回撥函式。

 1 /*
 2 ===============================================================
 3     GBT28181 SIP元件libGBT28181SipComponent.so註冊實現
 4     作者:程式人生
 5     部落格地址:http://blog.csdn.net/hiwubihe
 6     QQ:1269122125
 7     注:請尊重原作者勞動成果,僅供學習使用,請勿盜用,違者必究!
 8 ================================================================
 9 */
10 
11 #include "method.h"
12 #include <semaphore.h>
13 
14 static IGBT28181Comm* g_SIPComm = NULL;
15 
16 //啟動SIP服務
17 int server_start(void*addr)
18 {
19     COMM_PAIR *addr_entry = (COMM_PAIR *) addr;
20     if (g_SIPComm != NULL)
21     {
22         delete g_SIPComm;
23     }
24     if (!(g_SIPComm = new IGBT28181Comm(true)))
25     {
26         return -1;
27     }
28     //回撥函式
29     g_SIPComm->SetResponseCallback(&server_callback, (void_t*) g_SIPComm);
30     g_SIPComm->StartSip(addr_entry->local_addr, addr_entry->local_port);
31     return 0;
32 }
33 
34 //停止SIP服務
35 void server_stop()
36 {
37 
38     if (g_SIPComm != NULL)
39     {
40         g_SIPComm->StopSip();
41         sleep(2);
42         delete g_SIPComm;
43     }
44     g_SIPComm = NULL;
45 }

3.回撥函式callback.h

 1 /*
 2 ===============================================================
 3     GBT28181 SIP元件libGBT28181SipComponent.so註冊實現
 4     作者:程式人生
 5     部落格地址:http://blog.csdn.net/hiwubihe
 6     QQ:1269122125
 7     注:請尊重原作者勞動成果,僅供學習使用,請勿盜用,違者必究!
 8 ================================================================
 9 */
10 
11 #ifndef CALLBACK_H_
12 #define CALLBACK_H_
13 #include <stdio.h>
14 #include <string.h>
15 #include <iostream>
16 #include <stdlib.h>
17 #include "sipserver.h"
18 #include "IGBT28181Comm.h"
19 #include "method.h"
20 
21 using namespace GBT28181::Vsp;
22 using namespace std;
23 
24 //回撥函式
25 void_t server_callback(const SipRequestInfo& info, void_t* user);
26 
27 
28 #endif /* LIBINTERFACE_H_ */

4.callback.cpp 實現檔案

  1 /*
  2 ===============================================================
  3     GBT28181 SIP元件libGBT28181SipComponent.so註冊實現
  4     作者:程式人生
  5     部落格地址:http://blog.csdn.net/hiwubihe
  6     QQ:1269122125
  7     注:請尊重原作者勞動成果,僅供學習使用,請勿盜用,違者必究!
  8 ================================================================
  9 */
 10 
 11 #include "callback.h"
 12 #include "algorithm.h"
 13 
 14 
 15 //客戶端主動請求,伺服器端回撥
 16 const char * client_request_method[] =
 17 {
 18         "GBT28181.Vsp.Sip.SipMethod.Register",
 19         "GBT28181.Vsp.Sip.SipMethod.Notify",
 20         "GBT28181.Vsp.Sip.SipMethod.Subscribenotify"
 21 };
 22 
 23 //列印SIP訊息
 24 static void SIP_PKG_Print(const SipRequestInfo& infomation)
 25 {
 26     SipRegisterContextInfo* info = (SipRegisterContextInfo*) &infomation;
 27     cout << "\n"
 28             << "**************************************************"
 29             << "**************************"
 30             << endl;
 31     cout << "packet receive " << endl;
 32     cout << "status :" << info->status << endl;
 33     cout << "sipRequestId :" << info->sipRequestId << endl;
 34     cout << "requestId :" << info->requestId << endl;
 35     cout << "method :" << info->method << endl;
 36     cout << "from :" << info->from << endl;
 37     cout << "proxy :" << info->proxy << endl;
 38     cout << "contact :" << info->contact << endl;
 39     cout << "handle :" << info->handle << endl;
 40     cout << "sipIp :" << info->sipIp << endl;
 41     cout << "sipPort :" << info->sipPort << endl;
 42     cout << "subscribeEvent :" << info->subscribeEvent << endl;
 43     cout << "expires :" << info->expires << endl;
 44     cout << "content :" << info->content << endl;
 45     cout<<"Call ID:"<<info->callid<<endl;
 46     if (!info->registerInfo.userName.empty())
 47     {
 48         cout<<"********************************************"<<endl;
 49         cout<<"authendication infomation as follows:"<<endl;
 50         cout<<"username:"<<info->registerInfo.userName<<endl;
 51         cout<<"algorithm:"<<info->registerInfo.algorithm<<endl;
 52         cout<<"Realm:"<<info->registerInfo.digestRealm<<endl;
 53         cout<<"nonce:"<<info->registerInfo.nonce<<endl;
 54         cout<<"response:"<<info->registerInfo.response<<endl;
 55         cout<<"uri:"<<info->registerInfo.uri<<endl;
 56 
 57     }
 58     cout
 59             << "**************************************************"
 60             << "**************************"
 61             << endl;
 62 }
 63 
 64 static void_t register_response(const GBT28181::Vsp::SipRequestInfo& info,
 65         void_t* user)
 66 {
 67     cout << "receive register request packet from client" << endl;
 68     SIP_PKG_Print(info);
 69     char temp[16];
 70     SipRegisterContextInfo* regInfo = (SipRegisterContextInfo*) &info;
 71     SipRegisterContextInfo repinfo;
 72     repinfo.sipRequestId = info.sipRequestId;
 73     repinfo.from = info.proxy;
 74     repinfo.proxy = info.from;
 75     repinfo.method = info.method;
 76     //repinfo.expires = 300;
 77     repinfo.registerInfo.nonce = "9bd055";
 78     sscanf(info.contact.c_str(), "%*[^@]@%[^:]", temp);
 79     repinfo.registerInfo.digestRealm = temp;
 80     sscanf(info.proxy.c_str(), "%*[^@]@%[^:]", temp);
 81     repinfo.sipIp = temp;
 82     sscanf(info.proxy.c_str(), "%*[^:]:%s", temp);
 83     repinfo.sipPort = atoi(temp);
 84     repinfo.registerInfo.userName = regInfo->registerInfo.userName;
 85     repinfo.content="sfsdfsdf";
 86     GBT28181::Vsp::IGBT28181Comm* p_this = (GBT28181::Vsp::IGBT28181Comm*) user;
 87 
 88     if (repinfo.registerInfo.userName.empty())
 89     {
 90         cout<<"this register packet is unauthendicatin"<<endl;
 91         cout<<"send 401"<<endl;
 92         repinfo.status = "401";
 93         p_this->Downcast(repinfo);
 94     }
 95     else
 96     {
 97         cout<<"this register packet is authendicatin"<<endl;
 98         //驗證
 99         HASHHEX HA1;
100         HASHHEX Response;
101         DigestCalcHA1(regInfo->registerInfo.algorithm.c_str(),
102                 regInfo->registerInfo.userName.c_str(),
103                 regInfo->registerInfo.digestRealm.c_str(), UAC_PASSWD,
104                 regInfo->registerInfo.nonce.c_str(), NULL, HA1);
105         DigestCalcResponse(HA1, regInfo->registerInfo.nonce.c_str(),
106                 NULL, NULL, NULL, 0, "REGISTER",
107                 regInfo->registerInfo.uri.c_str(),
108                 NULL, Response);
109         if (!strcmp(Response, regInfo->registerInfo.response.c_str()))
110         {
111             cout<<"認證成功傳送 200 OK!!!"<<endl;
112             repinfo.expires = 5;
113             repinfo.status = "200";
114         }
115         else
116         {
117             cout<<"認證失敗傳送 404 OK!!!"<<endl;
118             repinfo.expires = 5;
119             repinfo.status = "404";
120         }
121 
122         p_this->Downcast(repinfo);
123 
124     }
125 }
126 
127 //
128 void_t server_callback(const SipRequestInfo& info, void_t* user)
129 {
130     //註冊報文的情況,呼叫註冊回撥
131     if (strncmp(info.method.c_str(), client_request_method[0], strlen(
132             client_request_method[0])) == 0)
133     {
134         register_response(info, user);
135     }
136     //其他情況報文
137     else
138     {
139         cout << "server receive wrong packer" << endl;
140         SIP_PKG_Print(info);
141         exit(1);
142     }
143 }

5.sip認證 algorithm.h

 1 /*
 2 ===============================================================
 3     GBT28181 SIP元件libGBT28181SipComponent.so註冊實現
 4     作者:程式人生
 5     部落格地址:http://blog.csdn.net/hiwubihe
 6     QQ:1269122125
 7     注:請尊重原作者勞動成果,僅供學習使用,請勿盜用,違者必究!
 8 ================================================================
 9 */
10 #ifndef B_REGISTER__ALGORITHM_H_
11 #define B_REGISTER__ALGORITHM_H_
12 
13 #include <stdio.h>
14 #include "osip_md5.h"
15 
16 #define HASHLEN 16
17 typedef char HASH[HASHLEN];
18 
19 #define HASHHEXLEN 32
20 typedef char HASHHEX[HASHHEXLEN + 1];
21 
22 
23 void DigestCalcHA1(const char *pszAlg, const char *pszUserName,
24         const char *pszRealm, const char *pszPassword,
25         const char *pszNonce, const char *pszCNonce,
26         HASHHEX SessionKey);
27 
28 void DigestCalcResponse(HASHHEX HA1, const char *pszNonce,
29         const char *pszNonceCount, const char *pszCNonce,
30         const char *pszQop, int Aka, const char *pszMethod,
31         const char *pszDigestUri, HASHHEX HEntity, HASHHEX Response);
32 
33 #endif /* B_REGISTER__ALGORITHM_H_ */

5.sip認證 algorithm.cpp,這部分參考程式碼可以在exosip2原始碼中找到。

  1 /*
  2 ===============================================================
  3     GBT28181 SIP元件libGBT28181SipComponent.so註冊實現
  4     作者:程式人生
  5     部落格地址:http://blog.csdn.net/hiwubihe
  6     QQ:1269122125
  7     注:請尊重原作者勞動成果,僅供學習使用,請勿盜用,違者必究!
  8 ================================================================
  9 */
 10 
 11 #include "algorithm.h"
 12 #include "string.h"
 13 
 14 static void CvtHex(HASH Bin, HASHHEX Hex)
 15 {
 16     unsigned short i;
 17     unsigned char j;
 18 
 19     for (i = 0; i < HASHLEN; i++)
 20     {
 21         j = (Bin[i] >> 4) & 0xf;
 22         if (j <= 9)
 23             Hex[i * 2] = (j + '0');
 24         else
 25             Hex[i * 2] = (j + 'a' - 10);

            
           

相關推薦

基於GBT28181SIP協議元件開發-----------SIP註冊流程分析實現

原創文章,引用請保證原文完整性,尊重作者勞動,原文地址http://www.cnblogs.com/qq1269122125/p/3941172.html,qq:1269122125。 上兩章節簡要的講解了SIP元件開發介面和開發環境的搭建。在本節將實現Linux 3

基於GBT28181SIP協議元件開發-----------第一環境搭建

SIP協議在安防視訊系統的國標中,有重要應用。從本文開始,講解並開發一套SIP協議元件。現在一般在開發這類系統時,採用的exosip2和osip2庫,這是個開源的SIP協議棧庫。實際遵從國標開發時並不能滿足實際的需要。所以本文依照GBT28181開發的一套SIP元件。該元件支援代理伺服器UAS和代理客戶

基於springboot+mybatis的微信公眾號開發-訊息的接收與回覆

1、在寫處理訊息的方法前,我們得把相關的model類寫好。 在model包下建立message(req與resp),具體建立如圖所示: BaseMessage類 /** * 訊息基類(普通使用者 -> 公眾帳號) * */ public

Android外掛化開發 [載入外掛資源]

引言 本文講解宿主如何從外掛apk中獲取到資源,為啥要從外掛中獲取資源呢?這種需求可能來自於顯示外掛的名字啊,圖示之類的。比如宿主的一個按鍵上顯示“掃一掃”或者"搖一搖"之類的,這個字串是外掛提供的。 Demo建立 引入外掛的AssetManager private sta

微信小程式開發 資料繫結,點選事件,陣列迴圈

前面介紹了註冊以及專案結構,現在開始開發吧。 1。資料繫結,如果學過vue.js的小夥伴應該很快會上手。小程式的資料繫結也是{{}},下面看例子吧 首先清空index.wxml的程式碼 <view> <text>{{name}}</tex

開發中的問題及解決方式

.text cat 彈窗 ret 如何 配置 中項 新的 顯示 1.texarea 如何保存空格、換行? 答:var content1= $("#content").val(); var content =content1.replace(/\n|\r\n/g,"&

Modbus庫開發筆記之九利用協議開發Modbus TCP Server應用

數根 網絡 received ant getc multiple 利用 這不 tar 前面我們已經完成了Modbus協議棧的開發,但這不是我們的目的。我們開發它的目的當然是要使用它來解決我們的實際問題。接下來我們就使用剛開發的Modbus協議棧開發一個Modbus TCP

python開發python基本數據類型(列表,元組,字典)

python開發 .com mage es2017 列表 基本 images 數據類型 切片 ##########列表:list########## 1.索引: 結果:eirc 2.切片 python開發(第三篇):python基本數據類型(列表,元組,字典)

Python開發基本數據類型

name 分享圖片 alex 賦值運算 gpo 基本 刪除 索引 常用功能 1、算數運算: 2、比較運算: 3、賦值運算: 4、邏輯運算: 5、成員運算: ---------------------------------------------------

基於深度學習的人臉特徵點檢測 - 資料集整理

https://yinguobing.com/facial-landmark-localization-by-deep-learning-data-collate/ 在上一篇博文中,我們已經下載到了包括300-W、LFPW、HELEN、AFW、IBUG和300-VW在內的6個數據集,初步估算有2

5章資料庫-Flask Web 開發(2版)

關係型資料庫 NoSQL 資料庫 Python 資料庫框架 使用 Flask-SQLAlchemy 管理資料庫 模型定義 關係 資料庫操作 建立表 插入資料 修改資料 刪除資料 查詢資料 在檢視函式中使用資料庫 (將

Spark視訊王家林3課在IDE下開發一個Scala程式純傻瓜式徹底透徹解析

內容:     1.控制結構     2.Scala的基礎語法 /**   * FileName: HelloScala   * Author:   hadoop   * Email:    [email protected]   * Date:     18-

【vue大師晉級之路第二集深入瞭解元件3章——自定義事件

事件名 不同於元件和 prop,事件名不存在任何自動化的大小寫轉換。而是觸發的事件名需要完全匹配監聽這個事件所用的名稱。舉個例子,如果觸發一個 camelCase 名字的事件: this.$emit('myEvent') 則監聽這個名字的 kebab-case

【vue大師晉級之路第二集深入瞭解元件4章——插槽

插槽內容 Vue 實現了一套內容分發的 API,這套 API 基於當前的 Web Components 規範草案,將 < slot> 元素作為承載分發內容的出口。 它允許你像這樣合成元件: <navigation-link url="/prof

【vue大師晉級之路第二集深入瞭解元件5章——動態元件 & 非同步元件

在動態元件上使用 keep-alive 我們之前曾經在一個多標籤的介面中使用 is 特性來切換不同的元件: <component v-bind:is="currentTabComponent"></component> 當在這些元件之間

Python開發Python基本數據類型

line .com post 數據類型 fun 其他 否則 對象 移除 運算符 1、算數運算: 2、比較運算: 3、賦值運算: 4、邏輯運算: 5、成員運算: 基本數據類型 1、數字 int(整型)   在32位機器上,整數的位數為32位,取值範圍

微信公眾平臺開發實戰Java版之請求訊息,響應訊息以及事件訊息類的封裝

微信伺服器和第三方伺服器之間究竟是通過什麼方式進行對話的? 下面,我們先看下圖: 其實我們可以簡單的理解: (1)首先,使用者向微信伺服器傳送訊息; (2)微信伺服器接收到使用者的訊息處理之後,通過開發者配置的URL和Token 來找到第三方伺服器,並以XML形式向第三方伺服器傳送訊息

Tigase開發筆記4Tigase Component元件開發

使用的Tigase Server版本 7.0.2 最新版,網上的資料很多,但都不能清楚明白的說明,自己整理了一下,其實很簡單,希望幫助走繞了路的朋友。 元件開發的快速引導 開發一個元件(Component)需要做如下幾件事兒 1. 定義一個元件 2. 配置這個元件 3

基於OSGi的JSF Web元件開發問題求解

最近一直在研究OSGi Web組建開發,跑了一些小程式中間出現了不少問題,其中很多是由於對OSGi理解不夠深入,當然還有些問題,目前也沒有解決的辦法,因此貼出來想讓大夥幫幫忙。具體情況如下:1.拿純Java程式碼編寫的JSP頁面進行測試,結果一切正常,說明JspServlet

Revit二次開發模型線的建立與偏移

對於模型線ModelCurve的偏移,研究了好幾天,終於搞定。先稍微談下自己中間遇到的情況。 1.首先,API中並沒有提供直接的方法對ModelCurve進行偏移; 2.考慮到模型線的建立,需要用到引數Curve,因此想到了對先Curve進行偏移,API提供了相應的方法: