註冊請求被用來在 的註冊服務器更新用戶的當前位置。應用程序發送一條註冊消息 ,通知服務器其當前位置,該位置又存儲在位置服務器 中。當呼叫者呼叫用戶時,代理服務器使用此 信息來查找被呼叫者的位置。
註冊請求應該由客戶端定期發送。 REGISTER請求的有效性由Expires標頭決定。
流量
樣品申請
REGISTER sip:sip.linphone.org SIP/2.0
Call-ID: [email protected]
CSeq: 1 REGISTER
From: <sip:[email protected]>;tag=-1427592833
To: <sip:vks[email protected]>
Max-Forwards: 70
Via: SIP/2.0/TCP 223.1.1.128:5060;branch=z9hG4bK-323532-2a454f4ec2a4213f6d6928eba479521d
Contact: <sip:[email protected];transport=tcp>
Content-Length: 0
現在讓我們看看如何建立基於NIST SIP棧 上述要求。
第一步是創建一個實現SIPListener的類。使 確保您的SIP堆棧正在初始化NIST JAIN SIP堆棧。
創建Call-ID頭
CallIdHeader callIdHeader = this.sipProvider.getNewCallId();
創建Cseq頭
CSeqHeader cSeqHeader = this.headerFactory.createCSeqHeader(Cseq的, " REGISTER ");
創建From頭
地址FROMADDRESS = addressFactory。createAddress(「sip:」+ username +'@'+ server); FromHeader fromHeader = this.headerFactory.createFromHeader(fromAddress, String.valueOf(this.tag));
創建To頭
ToHeader toHeader = this.headerFactory.createToHeader(FROMADDRESS,NULL);
創建最大-Forwards頭
MaxForwardsHeader maxForwardsHeader = this.headerFactory.createMaxForwardsHeader(70);
創建一個Via頭部
ArrayList的viaHeaders =新的ArrayList(); ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip,this.port,「tcp」,null); viaHeaders.add(viaHeader);
創建聯繫報頭
this.contactAddress = this.addressFactory.createAddress( 「SIP:」 + this.username + '@' + this.ip + 「運輸= TCP」);
//創建用於所有SIP消息的聯繫人標題。 012.this.contactHeader = this.headerFactory.createContactHeader(contactAddress);
一旦創建了所有標題,就可以創建請求 本身。現在
request = this.messageFactory.createRequest("REGISTER sip:" + server + "SIP/2.0\r\n\r\n");
request.addHeader(callIdHeader);
request.addHeader(cSeqHeader);
request.addHeader(fromHeader);
request.addHeader(toHeader);
request.addHeader(maxForwardsHeader);
request.addHeader(viaHeader);
request.addHeader(contactHeader);
該請求對象與所有必要的頭 創建,是時候發送請求。
inviteTid = sipProvider.getNewClientTransaction(request); // send the request out.
inviteTid.sendRequest();
一旦請求被髮送成功的響應將被傳遞到 使用SIPListener的processResponse回調該應用程序。
public void processResponse(ResponseEvent responseEvent) {
int statusCode = responseEvent.getResponse().getStatusCode();
}
代碼
public void register(Response response) {
try {
cseq++;
ArrayList viaHeaders = new ArrayList();
ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip,
this.port, "tcp", null);
viaHeaders.add(viaHeader);
// The "Max-Forwards" header.
MaxForwardsHeader maxForwardsHeader = this.headerFactory
.createMaxForwardsHeader(70);
// The "Call-Id" header.
CallIdHeader callIdHeader = this.sipProvider.getNewCallId();
// The "CSeq" header.
CSeqHeader cSeqHeader = this.headerFactory.createCSeqHeader(cseq,
"REGISTER");
Address fromAddress = addressFactory.createAddress("sip:"
+ username + '@' + server);
FromHeader fromHeader = this.headerFactory.createFromHeader(
fromAddress, String.valueOf(this.tag));
// The "To" header.
ToHeader toHeader = this.headerFactory.createToHeader(fromAddress,
null);
// this.contactHeader = this.headerFactory
// .createContactHeader(contactAddress);
request = this.messageFactory.createRequest("REGISTER sip:"
+ server + " SIP/2.0\r\n\r\n");
request.addHeader(callIdHeader);
request.addHeader(cSeqHeader);
request.addHeader(fromHeader);
request.addHeader(toHeader);
request.addHeader(maxForwardsHeader);
request.addHeader(viaHeader);
request.addHeader(contactHeader);
if (response != null) {
retry = true;
AuthorizationHeader authHeader = Utils.makeAuthHeader(headerFactory, response,
request, username, password);
request.addHeader(authHeader);
}
inviteTid = sipProvider.getNewClientTransaction(request);
// send the request out.
inviteTid.sendRequest();
this.dialog = inviteTid.getDialog();
// Send the request statelessly through the SIP provider.
// this.sipProvider.sendRequest(request);
// Display the message in the text area.
logger.debug("Request sent:\n" + request.toString() + "\n\n");
} catch (Exception e) {
// If an error occurred, display the error.
e.printStackTrace();
logger.debug("Request sent failed: " + e.getMessage() + "\n");
}
}
在SIP請求,如果服務器401代理 需要認證或401未經授權的響應,則意味着客戶端 有重播再次提出與MD5挑戰相同的請求。
客戶端應該使用響應頭中的nonce值 WWW-Authenticate。
WWW-Authenticate:Digest realm =「sip.linphone。組織」, 現時= 「JbAO1QAAAAA3aDI0AADMobiT7toAAAAA」,不透明= 「+ GNywA ==」, 算法MD5 =,QOP = 「權威性」
客戶端應該使用隨機數生成MD5挑戰,並重新做 原始請求與授權頭
步驟來創建MD5挑戰
創建使用用戶名+第一MD5哈希值「:」 +境界+「:」 +密碼
String a1 = username +「:」+ realm +「:」+ password; String ha1 = toHexString(mdigest.digest(a1.getBytes()));
創建使用REQUEST_METHOD +第二MD5哈希「:」 + REQUEST_URI
字符串A2 = request_method.toUpperCase()+ 「:」 + REQUEST_URI; String ha2 = toHexString(mdigest.digest(a2.getBytes()));
如果響應頭中的qop是「auth」,那麼使用步驟3a計算最終的MD5散列值,否則如果未定義或爲空,請參閱步驟 3b。
3a。創建使用HA1 +最後的MD5字符串「:」 +現時+「:」 + nonceCount +「:」 + cNonce +「:」 + QOP +「:」 + HA2
String finalStr = ha1 + ":" + nonce + ":" + nonceCount + ":" + cNonce + ":" + qop + ":" + ha2;
String response = toHexString(mdigest.digest(finalStr.getBytes()));
3B。創建使用HA1 +最後的MD5字符串「:」 +隨機數+「:」 + HA2
String finalStr = ha1 + ":" + nonce + ":" + ha2;
String response = toHexString(mdigest.digest(finalStr.getBytes()));
當我嘗試從這篇文章使用的代碼我收到NPE 行: 'VIAHEADER VIAHEADER = this.headerFactory.createViaHeader(this.ip, this.port, 「TCP」,NULL);' – skywalker
@ johndaw16你的headerFactory是否爲null?你必須創建它。例如:SipFactory sipFactory = SipFactory.getInstance(); sipFactory.setPathName( 「gov.nist」); headerFactory = sipFactory.createHeaderFactory(); – 11101101b
'ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip,this.port,「tcp」,null)'最後一個參數應該是branchID字符串。試試這種方式。 – Bobzone