基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(一)

时间:2024-03-29 15:07:21

原创文章,引用请保证原文完整性,尊重作者劳动,原文地址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

 /*
===============================================================
GBT28181 SIP组件libGBT28181SipComponent.so注册实现
作者:程序人生
博客地址:http://blog.csdn.net/hiwubihe
QQ:1269122125
注:请尊重原作者劳动成果,仅供学习使用,请勿盗用,违者必究!
================================================================
*/ #include <iostream>
#include <string>
#include <sstream>
#include <osipparser2/osip_message.h>
#include <osipparser2/osip_parser.h>
#include <osipparser2/osip_port.h> #include <eXosip2/eXosip.h>
#include <eXosip2/eX_setup.h>
#include <eXosip2/eX_register.h>
#include <eXosip2/eX_options.h>
#include <eXosip2/eX_message.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h> using namespace std; #define LISTEN_ADDR ("192.168.50.57")
#define UASPORT (5060) //该系数是由UAS维护的,UAS在接收到UAC的未鉴权报文后,给UAC回复401,在该报文中必须要带相关认证系数和认证方法
//UAS赋值的认证随机数
#define NONCE "9bd055"
//UAS默认加密算法
#define ALGORITHTHM "MD5" //SIP From头部
class CSipFromHeader
{
public:
CSipFromHeader()
{
}
~CSipFromHeader()
{
}
void SetHeader(string addrCod, string addrI, string addrPor)
{
addrCode = addrCod;
addrIp = addrI;
addrPort = addrPor;
}
string GetFormatHeader()
{
std::stringstream stream;
stream << "<sip: " << addrCode << "@" << addrIp << ":" << addrPort
<< ">";
return stream.str();
}
//主机名称
string GetRealName()
{
std::stringstream stream;
stream << addrIp;
return stream.str();
}
private:
string addrCode;
string addrIp;
string addrPort;
}; //SIP Contract头部
class CContractHeader: public CSipFromHeader
{
public:
CContractHeader()
{
}
~CContractHeader()
{
}
void SetContractHeader(string addrCod, string addrI, string addrPor,
int expire)
{
SetHeader(addrCod, addrI, addrPor);
expires = expire;
}
string GetContractFormatHeader(bool bExpires)
{
if (!bExpires)
{
return GetFormatHeader();
}
else
{
string sTmp = GetFormatHeader();
std::stringstream stream;
stream << ";" << "expires=" << expires;
sTmp += stream.str();
return sTmp;
} }
private:
int expires;
}; struct SipContextInfo
{
//Sip层返回的请求的标志 响应时返回即可
int sipRequestId;
//维护一次注册
string callId;
//消息所属的功能方法名字符串
string method;
//地址编码@域名或IP地址:连接端口,例如sip:1111@127.0.0.1:5060
CSipFromHeader from;
//地址编码@域名或IP地址:连接端口,例如sip:1111@127.0.0.1:5060
CSipFromHeader proxy;
//地址编码@域名或IP地址:连接端口,例如sip:1111@127.0.0.1:5060
CContractHeader contact;
//消息内容,一般为DDCP消息体XML文档,或者具体协议帧要求的其他字符串文本
string content;
//响应状态信息
string status;
//超时,时间单位为秒
int expires;
}; struct SipAuthInfo
{
//平台主机名
string digestRealm;
//平台提供的随机数
string nonce;
//用户名
string userName;
//密码
string response;
//“sip:平台地址”,不需要uac赋值
string uri;
//加密算法MD5
string algorithm;
}; struct sipRegisterInfo
{
SipContextInfo baseInfo;
SipAuthInfo authInfo;
bool isAuthNull;
}; void parserRegisterInfo(osip_message_t*request, int iReqId,
sipRegisterInfo &regInfo)
{
std::stringstream stream;
regInfo.baseInfo.method = request->sip_method;
regInfo.baseInfo.from.SetHeader(request->from->url->username,
request->from->url->host, request->from->url->port);
regInfo.baseInfo.proxy.SetHeader(request->to->url->username,
request->to->url->host, request->to->url->port);
//获取expires
osip_header_t* header = NULL;
{
osip_message_header_get_byname(request, "expires",
, &header);
if (NULL != header && NULL != header->hvalue)
{
regInfo.baseInfo.expires = atoi(header->hvalue);
}
}
//contact字段
osip_contact_t* contact = NULL;
osip_message_get_contact(request, , &contact);
if (NULL != contact)
{
regInfo.baseInfo.contact.SetContractHeader(contact->url->username,
contact->url->host, contact->url->port,
regInfo.baseInfo.expires);
}
//注册返回 由发送方维护的请求ID 接收方接收后原样返回即可
regInfo.baseInfo.sipRequestId = iReqId;
//CALL_ID
{
stream.str("");
stream << request->call_id->number;
regInfo.baseInfo.callId = stream.str();
}
//解析content消息
osip_body_t * body = NULL;
osip_message_get_body(request, , &body);
if (body != NULL)
{
stream.str("");
stream << body->body;
regInfo.baseInfo.content = stream.str();
}
//鉴权信息
osip_authorization_t* authentication = NULL;
{
osip_message_get_authorization(request, , &authentication);
if (NULL == authentication)
{
regInfo.isAuthNull = true;
}
else
{
regInfo.isAuthNull = false;
stream.str("");
stream << authentication->username;
regInfo.authInfo.userName = stream.str();
stream.str("");
stream << authentication->algorithm;
regInfo.authInfo.algorithm = stream.str();
stream.str("");
stream << authentication->realm;
regInfo.authInfo.digestRealm = stream.str();
stream.str("");
stream << authentication->nonce;
regInfo.authInfo.nonce = stream.str();
stream.str("");
stream << authentication->response;
regInfo.authInfo.response = stream.str();
stream.str("");
stream << authentication->uri;
regInfo.authInfo.uri = stream.str();
}
}
authentication = NULL;
} //打印接收到的响应报文
void printRegisterPkt( sipRegisterInfo&info)
{
cout<<"接收到报文:"<<endl;
cout<<"=============================================="
"=================="<<endl;
cout << "method:" << info.baseInfo.method << endl;
cout << "from: " << info.baseInfo.from.GetFormatHeader() << endl;
cout << "to:" << info.baseInfo.proxy.GetFormatHeader() << endl;
cout << "contact:" << info.baseInfo.contact.GetContractFormatHeader(false)
<< endl; //注册返回 由发送方维护的请求ID 接收方接收后原样返回即可
cout << "sipRequestId:" << info.baseInfo.sipRequestId << endl;
//CALL_ID
cout << "CallId:" << info.baseInfo.callId << endl;
//解析content消息
cout << "body:" << info.baseInfo.content << endl;
//获取expires
cout << "expires:" << info.baseInfo.expires << endl;
//鉴权信息
if (info.isAuthNull)
{
cout << "当前报文未提供鉴权信息!!!" << endl;
}
else
{
cout << "当前报文鉴权信息如下:" << endl;
cout << "username:" << info.authInfo.userName << endl;
cout << "algorithm:" << info.authInfo.algorithm << endl;
cout << "Realm:" << info.authInfo.digestRealm << endl;
cout << "nonce:" << info.authInfo.nonce << endl;
cout << "response:" << info.authInfo.response << endl;
cout << "uri:" << info.authInfo.uri << endl;
}
cout<<"=================================================="
"=============="<<endl;
return;
}
void sendRegisterAnswer( sipRegisterInfo&info)
{
osip_message_t* answer = NULL;
int iStatus;
if (info.isAuthNull)
{
iStatus = ;
}
else
{
iStatus = ;
}eXosip_lock();
{
int result = ::eXosip_message_build_answer(info.baseInfo.sipRequestId,
iStatus, &answer);
if (iStatus == )
{
//由SIP库生成认证方法和认证参数发送客户端
std::stringstream stream;
string nonce=NONCE;
string algorithm=ALGORITHTHM;
stream << "Digest realm=\"" << info.baseInfo.from.GetRealName()
<< "\",nonce=\"" << nonce
<< "\",algorithm=" << algorithm; osip_message_set_header(answer, "WWW-Authenticate",
stream.str().c_str());
cout<<"======================================================="
"========="<<endl;
cout<<"发送401报文"<<endl;
cout<<"========================================================"
"========"<<endl;
}
else if (iStatus == )
{
osip_message_set_header(answer, "Contact",
info.baseInfo.contact.GetContractFormatHeader(true).c_str());
cout<<"========================================================="
"======="<<endl;
cout<<"发送200报文"<<endl;
cout<<"=========================================================="
"======"<<endl;
//string_t b = "<sip: 100110000101000000@192.168.31.18:5061>;expires=600";
//osip_message_set_header(answer, "Contact", b.c_str());
}
else
{
//Do nothing
} if (OSIP_SUCCESS != result)
{
::eXosip_message_send_answer(info.baseInfo.sipRequestId, , NULL);
}
else
{
//发送消息体
::eXosip_message_send_answer(info.baseInfo.sipRequestId, iStatus,
answer);
}
if ( == info.baseInfo.expires)
{
eXosip_register_remove(info.baseInfo.sipRequestId);
}
}eXosip_unlock();
}
void OnRegister(eXosip_event_t *osipEvent)
{
sipRegisterInfo regInfo;
parserRegisterInfo(osipEvent->request, osipEvent->tid, regInfo);
//打印报文
printRegisterPkt(regInfo);
//发送应答报文
sendRegisterAnswer(regInfo); } int main()
{ int result = OSIP_SUCCESS;
// init exosip.
if (OSIP_SUCCESS != (result = eXosip_init()))
{
printf("eXosip_init failure.\n");
return ;
}
cout << "eXosip_init success." << endl;
//
// if (null_ptr != this->receiveSipMessageCallback || null_ptr
// != this->sendSipMessageCallback)
// {
// if (OSIP_SUCCESS != (result = ::eXosip_set_cbsip_message(
// &Sip::MessageCallback)))
// {
// return;
// }
// }
eXosip_set_user_agent(NULL); if (OSIP_SUCCESS != eXosip_listen_addr(IPPROTO_UDP, NULL, UASPORT, AF_INET,
))
{
printf("eXosip_listen_addr failure.\n");
return ;
} if (OSIP_SUCCESS != eXosip_set_option(
EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,
LISTEN_ADDR))
{
return -;
}
//开启循环消息,实际应用中可以开启多线程同时接收信号
eXosip_event_t* osipEventPtr = NULL; while (true)
{
// Wait the osip event.
osipEventPtr = ::eXosip_event_wait(, );// 0的单位是秒,500是毫秒
// If get nothing osip event,then continue the loop.
if (NULL == osipEventPtr)
{
continue;
}
// 事件处理 switch (osipEventPtr->type)
{ //需要继续验证REGISTER是什么类型
case EXOSIP_REGISTRATION_NEW:
OnRegister(osipEventPtr);
break;
case EXOSIP_MESSAGE_NEW:
{
if (!strncmp(osipEventPtr->request->sip_method, "REGISTER",
strlen("REGISTER")))
{
OnRegister(osipEventPtr);
}
else if (!strncmp(osipEventPtr->request->sip_method, "MESSAGE",
strlen("MESSAGE")))
{
//
}
}
break;
default:
cout
<< "The sip event type that not be precessed.the event "
"type is : "
<< osipEventPtr->type;
break;
}
//ProcessSipEvent(this->osipEventPtrParam);
eXosip_event_free(osipEventPtr);
osipEventPtr = NULL;
} return ;
}

二.UAC源代码

 参看下一篇 基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(二)

三.测试效果

1.UAS启动后,接受到报文效果

基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(一)

2.UAS发送401回复报文

基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(一)

3.UAS接受到带鉴权报文

基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(一)

4.UAS回复200OK

基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(一)