我在注册中找到的最佳示例在这里。如果万一有一天链接干涸,以下是要点:
REGISTER 请求用于更新用户在 REGISTRAR 服务器上的当前位置。应用程序发送 REGISTER 消息通知服务器其当前位置,该位置又存储在位置服务器中。当呼叫者呼叫用户时,代理服务器使用此信息来查找被呼叫者的位置。
注册请求应由客户端定期发送。REGISTER 请求的有效性由 Expires 标头确定。
流动
样品请求
REGISTER sip:sip.linphone.org SIP/2.0
Call-ID: 0a0f14355fa76ae6435b98bfe085baf9@223.1.1.128
CSeq: 1 REGISTER
From: <sip:vkslabs@sip.linphone.org>;tag=-1427592833
To: <sip:vkslabs@sip.linphone.org>
Max-Forwards: 70
Via: SIP/2.0/TCP 223.1.1.128:5060;branch=z9hG4bK-323532-2a454f4ec2a4213f6d6928eba479521d
Contact: <sip:vkslabs@223.1.1.128;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");
创建自标头
地址 fromAddress = addressFactory.createAddress("sip:" + username + '@' + server); FromHeader fromHeader = this.headerFactory.createFromHeader(fromAddress, String.valueOf(this.tag));
创建到标题
ToHeader toHeader = this.headerFactory.createToHeader(fromAddress, null);
创建 Max-Forwards 标头
MaxForwardsHeader maxForwardsHeader = this.headerFactory.createMaxForwardsHeader(70);
创建 Via 标头
ArrayList viaHeaders = new 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 + "transport=tcp");
// 创建用于所有 SIP 消息的联系人标头。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 Proxy Authentication Required 或 401 Unauthorized 响应,则意味着客户端必须使用 MD5 质询再次重放相同的请求。
客户端应该使用来自响应头 WWW-Authenticate 的 nonce 值。
WWW-Authenticate: Digest realm="sip.linphone.org", nonce="JbAO1QAAAAA3aDI0AADMobiT7toAAAAA", opaque="+GNywA==", algorithm=MD5, qop="auth"
客户端应使用 nonce 生成 MD5 质询,并使用 Authorization 标头再次发出原始请求。
创建 MD5 挑战的步骤
使用用户名 + “:” + 领域 + “:” + 密码创建第一个 MD5 哈希
字符串 a1 = 用户名 + ":" + 领域 + ":" + 密码;字符串 ha1 = toHexString(mdigest.digest(a1.getBytes()));
使用 request_method + “:” + request_uri 创建第二个 MD5 哈希
字符串 a2 = request_method.toUpperCase() + ":" + request_uri; 字符串 ha2 = toHexString(mdigest.digest(a2.getBytes()));
如果响应标头中的 qop 是“auth”,则使用步骤 3a 计算最终的 MD5 哈希,否则如果它未定义或为空,请参阅步骤 3b。
3a。使用 ha1 + “:” + nonce + “:” + nonceCount + “:” + cNonce + “:” + qop + “:” + ha2 创建最终的 MD5 字符串
String finalStr = ha1 + ":" + nonce + ":" + nonceCount + ":" + cNonce + ":" + qop + ":" + ha2;
String response = toHexString(mdigest.digest(finalStr.getBytes()));
3b。使用 ha1 + “:” + nonce + “:” + ha2 创建最终的 MD5 字符串
String finalStr = ha1 + ":" + nonce + ":" + ha2;
String response = toHexString(mdigest.digest(finalStr.getBytes()));