基於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);相關推薦
基於GBT28181:SIP協議元件開發-----------第三篇SIP註冊流程分析實現
原創文章,引用請保證原文完整性,尊重作者勞動,原文地址http://www.cnblogs.com/qq1269122125/p/3941172.html,qq:1269122125。 上兩章節簡要的講解了SIP元件開發介面和開發環境的搭建。在本節將實現Linux 3
基於GBT28181:SIP協議元件開發-----------第一篇環境搭建
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開發筆記4:Tigase 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提供了相應的方法: