首页 > 代码库 > 基于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, &regMsg);164         if (registerId <= 0)165         {166             return -1;167         }168     }169     else170     {171         // 构建注册消息172         ret = ::eXosip_register_build_register(registerId, expires, &regMsg);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(&regMsg->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实现(二)