基于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 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 ®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 //获取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
欢迎技术交流沟通,转载请注明出处并保持作品的完整性。
作者:程序人生 qq1269122125