由于已经成功搭建好基于eXosip的UAC的开发环境,并且也与SPVMN测试系统交互成功,所以现在开始针对注册、查询等业务进行详细的研究。
今天先研究下设备注册的流程,模拟一个IPC向SPVMN系统注册,记录下交互的消息,详细研究了下:
转载请注明出处:http://blog.csdn.net/longlong530
一.环境搭建:
环境准备:http://blog.csdn.net/longlong530/article/details/9176989
UAC(模拟IPC):
IP:192.168.10.117
Port:5061
UAS(模拟SIP服务器):
IP:192.168.10.177
Port:5060
二.业务时序图:
三.消息详解:
第一步:UAC --> UAS
UAC向UAS注册,下面是具体注册消息:
REGISTER sip:192.168.10.177:5060 SIP/2.0 Via: SIP/2.0/UDP 192.168.10.117:5061;rport=5061;branch=z9hG4bK2509000523;received=192.168.10.117 From: <sip:[email protected]>;tag=2577708869 To: <sip:[email protected]> Call-ID: 939764460 CSeq: 1 REGISTER Contact: <sip:[email protected]:5061;line=6513f93347c330b> Max-Forwards: 70 User-Agent: eXosip/3.6.0 Expires: 3600 Authorization: Capability, algorithm="H:MD5" Content-Length: 0
字段说明:
请求起始行:表示UAC向IP地址为192.168.10.177的服务器发起注册,SIP版本号为2.0
From字段:指明该REGISTER请求消息由UAS(IP地址:192.168.10.177)控制的UAC发起的。
To字段:指明REGISTER请求接收方的地址。此时REGISTER请求的接收方为IP地址为192.168.10.177的UAS。(这个值和To头域的值相同,除非这个请求是第三方发起的注册请求。)第二步,UAS-->UAC
UAS返回401 Unauthorized(无权限)响应,表明要求对UAC进行用户认证,并且通过WWW-Authenticate字段携带UAS支持的认证方式,产生本次认证的nonce
SIP/2.0 401 Unauthorized To: <sip:[email protected]>;tag=66081813_53173353_54026835-98f6-4d1e-b562-0d969636b944 Via: SIP/2.0/UDP 192.168.10.117:5061;rport=5061;branch=z9hG4bK2509000523;received=192.168.10.117 CSeq: 1 REGISTER Call-ID: 939764460 From: <sip:[email protected]>;tag=2577708869 WWW-Authenticate: Digest realm="3402000000",nonce="324cab6e557268e0" Content-Length: 0
第三步,UAC-->UAS
UAC重新向UAS发起注册请求,携带WWW-Authorization字段
REGISTER sip:192.168.10.177:5060 SIP/2.0 Via: SIP/2.0/UDP 192.168.10.117:5061;rport=5061;branch=z9hG4bK3163110852;received=192.168.10.117 From: <sip:[email protected]>;tag=2577708869 To: <sip:[email protected]> Call-ID: 939764460 CSeq: 2 REGISTER Contact: <sip:[email protected]:5061;line=6513f93347c330b> Authorization: Digest username="34020000001320000001",realm="3402000000",nonce="324cab6e557268e0",uri="sip:192.168.10.177:5060",response="7f536c8ce38593239f9130e37a72276e",algorithm=MD5 Max-Forwards: 70 User-Agent: eXosip/3.6.0 Expires: 3600 Content-Length: 0
UAS收到UAC的注册请求,首先检查NONCE的正确性,如果和在401 Unauthorized响应中产生的NONCE相同,则通过。否则,直接返回失败。然后,UAS会根据NONCE、用户名、密码(服务器端可以根据本地用户信息获取用户的密码)、URI等采用和终端相同的算法生成
RESPONSE,并且对此RESPONSE和请求消息中的RESPONSE进行比较,如果二者一致则用户认证成功,否则认证失败。此时,UAS返回200 OK响应消息,表明终端认证成功。
SIP/2.0 200 OK To: <sip:[email protected]>;tag=31428812_53173353_376bd3d9-cb9d-4b4f-a950-da26d575cff5 Via: SIP/2.0/UDP 192.168.10.117:5061;rport=5061;branch=z9hG4bK3163110852;received=192.168.10.117 CSeq: 2 REGISTER Call-ID: 939764460 From: <sip:[email protected]>;tag=2577708869 Contact: <sip:[email protected]:5061;line=6513f93347c330b> Expires: 3600 Date: 2013-06-26T16:08:37.164 Content-Length: 0
附代码:
int eXosip_register(int expires)/*expires/注册消息过期时间,单位为秒*/ { int ret = 0; eXosip_event_t *je = NULL; osip_message_t *reg = NULL; char from[100];/*sip:主叫用户名@被叫IP地址*/ char proxy[100];/*sip:被叫IP地址:被叫IP端口*/ memset(from, 0, 100); memset(proxy, 0, 100); sprintf(from, "sip:%s@%s", device_info.ipc_id, device_info.server_ip); sprintf(proxy, "sip:%s:%s", device_info.server_ip, device_info.server_port); /*发送不带认证信息的注册请求*/ retry: eXosip_lock(); g_register_id = eXosip_register_build_initial_register(from, proxy, NULL, expires, ®); osip_message_set_authorization(reg, "Capability algorithm=\"H:MD5\""); if(0 > g_register_id) { eXosip_unlock(); printf("eXosip_register_build_initial_register error!\r\n"); return -1; } printf("eXosip_register_build_initial_register success!\r\n"); ret = eXosip_register_send_register(g_register_id, reg); eXosip_unlock(); if(0 != ret) { printf("eXosip_register_send_register no authorization error!\r\n"); return -1; } printf("eXosip_register_send_register no authorization success!\r\n"); printf("g_register_id=%d\r\n", g_register_id); for(;;) { je = eXosip_event_wait(0, 50);/*侦听消息的到来*/ if(NULL == je)/*没有接收到消息*/ { continue; } if(EXOSIP_REGISTRATION_FAILURE == je->type)/*注册失败*/ { printf("<EXOSIP_REGISTRATION_FAILURE>\r\n"); printf("je->rid=%d\r\n", je->rid); /*收到服务器返回的注册失败/401未认证状态*/ if((NULL != je->response)&&(401 == je->response->status_code)) { reg = NULL; /*发送携带认证信息的注册请求*/ eXosip_lock(); eXosip_clear_authentication_info();/*清除认证信息*/ eXosip_add_authentication_info(device_info.ipc_id, device_info.ipc_id, device_info.ipc_pwd, "MD5", NULL);/*添加主叫用户的认证信息*/ eXosip_register_build_register(je->rid, expires, ®); ret = eXosip_register_send_register(je->rid, reg); eXosip_unlock(); if(0 != ret) { printf("eXosip_register_send_register authorization error!\r\n"); return -1; } printf("eXosip_register_send_register authorization success!\r\n"); } else/*真正的注册失败*/ { printf("EXOSIP_REGISTRATION_FAILURE error!\r\n"); goto retry;/*重新注册*/ } } else if(EXOSIP_REGISTRATION_SUCCESS == je->type) { /*收到服务器返回的注册成功*/ printf("<EXOSIP_REGISTRATION_SUCCESS>\r\n"); g_register_id = je->rid;/*保存注册成功的注册ID*/ printf("g_register_id=%d\r\n", g_register_id); break; } } return 0; }