基于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:[email protected]:5060

121     CSipFromHeader from;

122     //地址编码@域名或IP地址:连接端口,例如sip:[email protected]:5060

123     CSipFromHeader proxy;

124     //地址编码@域名或IP地址:连接端口,例如sip:[email protected]: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 &regInfo)

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: [email protected]: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启动后,接受到报文效果

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

2.UAS发送401回复报文

3.UAS接受到带鉴权报文

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

4.UAS回复200OK

 

你可能感兴趣的:(OS)