首页 > 代码库 > 基于GBT28181:SIP协议组件开发-----------第五篇SIP注册流程eXosip2实现(二)
基于GBT28181:SIP协议组件开发-----------第五篇SIP注册流程eXosip2实现(二)
原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3966794.html。
上章节讲解了讲解一个用eXosip2库实现的Demo 程序。Demo讲的是注册的过程,因为篇幅比较长,再分一节写。本节是上一节的继续,主要实现UAC用eXosip2库实现的Demo 程序。本节讲的比较全面,处理实现注册问题还添加了注销和刷新注册的过程。刷新相当于心跳的功能。注意这个函数eXosip_default_action()实现在sip中401和407错误类型的eXosip2库的自动处理。网上有的人问注册报文发送后,只收到401返回码。这是对SIP注册不了解造成的。至于这个过程在前面注册理论部分已经讲解。我也尝试不用eXosip_default_action()这个函数,我自己发送鉴权信息,可惜没成功,不知道什么原因,有时返回200OK,有时不返回,所以还是用了eXosip_default_action()这个函数,让401的响应报文由eXosip2库去发送。
一.UAC代码main.cpp
1 /* 2 =============================================================== 3 GBT28181 基于eXosip2,osip库实现注册UAC功能 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 //本地监听IP 30 #define LISTEN_ADDR ("192.168.50.57") 31 //本地监听端口 32 #define UACPORT ("5061") 33 #define UACPORTINT (5061) 34 //本UAC地址编码 35 #define UACCODE ("100110000201000000") 36 //本地UAC密码 37 #define UACPWD ("12345") 38 //远程UAS IP 39 #define UAS_ADDR ("192.168.50.57") 40 //远程UAS 端口 41 #define UAS_PORT ("5060") 42 //超时 43 #define EXPIS 300 44 45 //当前服务状态 1 已经注册 0 未注册 46 static int iCurrentStatus; 47 //注册成功HANDLE 48 static int iHandle = -1; 49 50 //SIP From/To 头部 51 class CSipFromToHeader 52 { 53 public: 54 CSipFromToHeader() 55 { 56 } 57 ~CSipFromToHeader() 58 { 59 } 60 void SetHeader(string addrCod, string addrI, string addrPor) 61 { 62 addrCode = addrCod; 63 addrIp = addrI; 64 addrPort = addrPor; 65 } 66 string GetFormatHeader() 67 { 68 std::stringstream stream; 69 stream << "sip: " << addrCode << "@" << addrIp << ":" << addrPort; 70 return stream.str(); 71 } 72 //主机名称 73 string GetCode() 74 { 75 std::stringstream stream; 76 stream << addrCode; 77 return stream.str(); 78 } 79 //主机地址 80 string GetAddr() 81 { 82 std::stringstream stream; 83 stream << addrIp; 84 return stream.str(); 85 } 86 //端口 87 string GetPort() 88 { 89 std::stringstream stream; 90 stream << addrPort; 91 return stream.str(); 92 } 93 94 private: 95 string addrCode; 96 string addrIp; 97 string addrPort; 98 }; 99 100 //SIP Contract头部101 class CContractHeader: public CSipFromToHeader102 {103 public:104 CContractHeader()105 {106 }107 ~CContractHeader()108 {109 }110 void SetContractHeader(string addrCod, string addrI, string addrPor)111 {112 SetHeader(addrCod, addrI, addrPor);113 }114 string GetContractFormatHeader()115 {116 117 std::stringstream stream;118 stream << "<sip:" << GetCode() << "@" << GetAddr() << ":" << GetPort()119 << ">";120 return stream.str();121 }122 };123 124 //发送注册信息125 int SendRegister(int& registerId, CSipFromToHeader &from, CSipFromToHeader &to,126 CContractHeader &contact, const string& userName, const string& pwd,127 const int expires, int iType)128 {129 cout << "=============================================" << endl;130 if (iType == 0)131 {132 cout << "注册请求信息:" << endl;133 }134 else if (iType == 1)135 {136 cout << "刷新注册信息:" << endl;137 }138 else139 {140 cout << "注销信息:" << endl;141 }142 cout << "registerId " << registerId << endl;143 cout << "from " << from.GetFormatHeader() << endl;144 cout << "to " << to.GetFormatHeader() << endl;145 cout << "contact" << contact.GetContractFormatHeader() << endl;146 cout << "userName" << userName << endl;147 cout << "pwd" << pwd << endl;148 cout << "expires" << expires << endl;149 cout << "=============================================" << endl;150 //服务器注册151 static osip_message_t *regMsg = 0;152 int ret;153 154 ::eXosip_add_authentication_info(userName.c_str(), userName.c_str(),155 pwd.c_str(), "MD5", NULL);156 eXosip_lock();157 //发送注册信息 401响应由eXosip2库自动发送158 if (0 == registerId)159 {160 // 注册消息的初始化161 registerId = ::eXosip_register_build_initial_register(162 from.GetFormatHeader().c_str(), to.GetFormatHeader().c_str(),163 contact.GetContractFormatHeader().c_str(), expires, ®Msg);164 if (registerId <= 0)165 {166 return -1;167 }168 }169 else170 {171 // 构建注册消息172 ret = ::eXosip_register_build_register(registerId, expires, ®Msg);173 if (ret != OSIP_SUCCESS)174 {175 return ret;176 }177 //添加注销原因178 if (expires == 0)179 {180 osip_contact_t *contact = NULL;181 char tmp[128];182 183 osip_message_get_contact(regMsg, 0, &contact);184 {185 sprintf(tmp, "<sip:%s@%s:%s>;expires=0",186 contact->url->username, contact->url->host,187 contact->url->port);188 }189 //osip_contact_free(contact);190 //reset contact header191 osip_list_remove(®Msg->contacts, 0);192 osip_message_set_contact(regMsg, tmp);193 osip_message_set_header(regMsg, "Logout-Reason", "logout");194 }195 }196 // 发送注册消息197 ret = ::eXosip_register_send_register(registerId, regMsg);198 if (ret != OSIP_SUCCESS)199 {200 registerId = 0;201 }eXosip_unlock();202 203 return ret;204 }205 206 //注册207 void Register()208 {209 if (iCurrentStatus == 1)210 {211 cout << "当前已经注册" << endl;212 return;213 }214 CSipFromToHeader stFrom;215 stFrom.SetHeader(UACCODE, UAS_ADDR, UAS_PORT);216 CSipFromToHeader stTo;217 stTo.SetHeader(UACCODE, UAS_ADDR, UAS_PORT);218 CContractHeader stContract;219 stContract.SetContractHeader(UACCODE, LISTEN_ADDR, UACPORT);220 //发送注册信息221 int registerId = 0;222 if (0 > SendRegister(registerId, stFrom, stTo, stContract, UACCODE, UACPWD,223 3000, 0))224 {225 cout << "发送注册失败" << endl;226 return;227 }228 iCurrentStatus = 1;229 iHandle = registerId;230 }231 //刷新注册232 void RefreshRegister()233 {234 if (iCurrentStatus == 0)235 {236 cout << "当前未注册,不允许刷新" << endl;237 return;238 }239 CSipFromToHeader stFrom;240 stFrom.SetHeader(UACCODE, UAS_ADDR, UAS_PORT);241 CSipFromToHeader stTo;242 stTo.SetHeader(UACCODE, UAS_ADDR, UAS_PORT);243 CContractHeader stContract;244 stContract.SetContractHeader(UACCODE, LISTEN_ADDR, UACPORT);245 //发送注册信息246 if (0 > SendRegister(iHandle, stFrom, stTo, stContract, UACCODE, UACPWD,247 3000, 1))248 {249 cout << "发送刷新注册失败" << endl;250 return;251 }252 }253 //注销254 void UnRegister()255 {256 if (iCurrentStatus == 0)257 {258 cout << "当前未注册,不允许注销" << endl;259 return;260 }261 CSipFromToHeader stFrom;262 stFrom.SetHeader(UACCODE, UAS_ADDR, UAS_PORT);263 CSipFromToHeader stTo;264 stTo.SetHeader(UACCODE, UAS_ADDR, UAS_PORT);265 CContractHeader stContract;266 stContract.SetContractHeader(UACCODE, LISTEN_ADDR, UACPORT);267 //发送注册信息268269 if (0 > SendRegister( iHandle, stFrom, stTo, stContract, UACCODE, UACPWD,270 0, 2))271 {272 cout << "发送注销失败" << endl;273 return;274 }275 iCurrentStatus = 0;276 iHandle = -1;277 }278 static void help()279 {280 const char281 *b =282 "-------------------------------------------------------------------------------\n"283 "SIP Library test process - uac v 1.0 (June 13, 2014)\n\n"284 "SIP UAC端 注册,刷新注册,注销实现\n\n"285 "Author: 程序人生\n\n"286 "博客地址:http://blog.csdn.net/hiwubihe QQ:1269122125\n\n"287 "-------------------------------------------------------------------------------\n"288 "\n"289 " 0:Register\n"290 " 1:RefreshRegister\n"291 " 2:UnRegister\n"292 " 3:clear scream\n"293 " 4:exit\n"294 "-------------------------------------------------------------------------------\n"295 "\n";296 fprintf(stderr, b, strlen(b));297 cout << "please select method :";298 }299 //服务处理线程300 void *serverHandle(void *pUser)301 {302 sleep(3);303 help();304 char ch = getchar();305 getchar();306 while (1)307 {308 switch (ch)309 {310 case ‘0‘:311 //注册312 Register();313 break;314 case ‘1‘:315 //刷新注册316 RefreshRegister();317 break;318 case ‘2‘:319 //注销320 UnRegister();321 break;322 case ‘3‘:323 if (system("clear") < 0)324 {325 cout << "clear scream error" << endl;326 exit(1);327 }328 break;329 case ‘4‘:330 cout << "exit sipserver......" << endl;331 getchar();332 exit(0);333 default:334 cout << "select error" << endl;335 break;336 }337 cout << "press any key to continue......" << endl;338 getchar();339 help();340 ch = getchar();341 getchar();342 }343 return NULL;344 }345 346 //事件处理线程347 void *eventHandle(void *pUser)348 {349 eXosip_event_t* osipEventPtr = (eXosip_event_t*) pUser;350 switch (osipEventPtr->type)351 {352 //需要继续验证REGISTER是什么类型353 case EXOSIP_REGISTRATION_SUCCESS:354 case EXOSIP_REGISTRATION_FAILURE:355 {356 cout<<"收到状态码:"<<osipEventPtr->response->status_code<<"报文"<<endl;357 if(osipEventPtr->response->status_code == 401)358 {359 cout<<"发送鉴权报文"<<endl;360 }361 else if(osipEventPtr->response->status_code == 200)362 {363 cout<<"接收成功"<<endl;364 }365 else366 {}367 }368 break;369 default:370 cout << "The sip event type that not be precessed.the event "371 "type is : " << osipEventPtr->type << endl;372 break;373 }374 eXosip_event_free(osipEventPtr);375 return NULL;376 }377 378 int main()379 {380 iCurrentStatus = 0;381 //库处理结果382 int result = OSIP_SUCCESS;383 //初始化库384 if (OSIP_SUCCESS != (result = eXosip_init()))385 {386 printf("eXosip_init failure.\n");387 return 1;388 }389 cout << "eXosip_init success." << endl;390 eXosip_set_user_agent(NULL);391 //监听392 if (OSIP_SUCCESS != eXosip_listen_addr(IPPROTO_UDP, NULL, UACPORTINT,393 AF_INET, 0))394 {395 printf("eXosip_listen_addr failure.\n");396 return 1;397 }398 //设置监听网卡399 if (OSIP_SUCCESS != eXosip_set_option(400 EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,401 LISTEN_ADDR))402 {403 return -1;404 }405 //开启服务线程406 pthread_t pthser;407 if (0 != pthread_create(&pthser, NULL, serverHandle, NULL))408 {409 printf("创建主服务失败\n");410 return -1;411 }412 //事件用于等待413 eXosip_event_t* osipEventPtr = NULL;414 //开启事件循环415 while (true)416 {417 //等待事件 0的单位是秒,500是毫秒418 osipEventPtr = ::eXosip_event_wait(0, 200);419 //处理eXosip库默认处理420 {421 usleep(500 * 1000);422 eXosip_lock();423 //一般处理401/407采用库默认处理424 eXosip_default_action(osipEventPtr);425 eXosip_unlock();426 }427 //事件空继续等待428 if (NULL == osipEventPtr)429 {430 continue;431 }432 //开启线程处理事件并在事件处理完毕将事件指针释放433 pthread_t pth;434 if (0 != pthread_create(&pth, NULL, eventHandle, (void*) osipEventPtr))435 {436 printf("创建线程处理事件失败\n");437 continue;438 }439 osipEventPtr = NULL;440 }441 }
二.测试效果
1.启动后
2.输入0 注册后,可以看到第一次收到了401报文,库自动发送鉴权信息,然后收到了200OK报文。
3.然后输入1,刷新后,可以看到收到200OK报文
4.输入2,注销后。收到200OK报文。并且可以看到expires为0了。
至此eXosip2库实现注册,全部功能完成。
欢迎技术交流沟通,转载请注明出处并保持作品的完整性。 作者:程序人生 qq1269122125
基于GBT28181:SIP协议组件开发-----------第五篇SIP注册流程eXosip2实现(二)