首页 > 代码库 > 基于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 ®Info)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实现
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。