The best example I have found on registration is found here.
Here is the gist of if just in case the link dries-up one day:
REGISTER request is used to update the current location of a user on
the REGISTRAR server. The application sends a REGISTER message
informing the server its current location which in turn is stored in
location server. When a caller calls a user the proxy server uses this
information to find the location of the callee.
Register request should be sent by the client periodically. The
validity of the REGISTER request is determined by the Expires header.
Flow
Sample Request
REGISTER sip:sip.linphone.org SIP/2.0
Call-ID: [email protected]
CSeq: 1 REGISTER
From: <sip:[email protected]>;tag=-1427592833
To: <sip:[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
Now lets see how to construct the above request using the NIST SIP
Stack.
First step is to create a class that implements the SIPListener. Make
sure your SIP Stack is Initializing NIST JAIN SIP Stack.
Create Call-ID header
CallIdHeader callIdHeader = this.sipProvider.getNewCallId();
Create CSeq header
CSeqHeader cSeqHeader = this.headerFactory.createCSeqHeader(cseq,
"REGISTER");
Create From header
Address fromAddress = addressFactory.createAddress("sip:" + username + '@' + server);
FromHeader fromHeader = this.headerFactory.createFromHeader(fromAddress,
String.valueOf(this.tag));
Create To Header
ToHeader toHeader = this.headerFactory.createToHeader(fromAddress, null);
Create Max-Forwards header
MaxForwardsHeader maxForwardsHeader = this.headerFactory.createMaxForwardsHeader(70);
Create a Via header
ArrayList viaHeaders = new ArrayList();
ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip, this.port, "tcp", null);
viaHeaders.add(viaHeader);
Create contact header
this.contactAddress = this.addressFactory.createAddress("sip:" + this.username + '@' + this.ip + "transport=tcp");
// Create the contact header used for all SIP messages.
this.contactHeader = this.headerFactory.createContactHeader(contactAddress);
Once all the headers are created it is time to create the request
itself.
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);
Now that the request object is created with all the necessary headers
it is time to send the request.
inviteTid = sipProvider.getNewClientTransaction(request); // send the request out.
inviteTid.sendRequest();
Once the request is sent successfully the response will be passed to
the application using the processResponse callback in SIPListener.
public void processResponse(ResponseEvent responseEvent) {
int statusCode = responseEvent.getResponse().getStatusCode();
}
Code
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");
}
}
You can also view the reference post on authentication here.
Here is the gist of if just in case the link dries-up one day:
During a SIP request if the server responds with 401 Proxy
Authentication Required or 401 Unauthorized then it means the client
has to replay the same request again with MD5 challenge.
The client should use nonce value from the response header
WWW-Authenticate.
WWW-Authenticate: Digest realm="sip.linphone.org",
nonce="JbAO1QAAAAA3aDI0AADMobiT7toAAAAA", opaque="+GNywA==",
algorithm=MD5, qop="auth"
The client should use nonce to generate the MD5 challenge and make the
original request again with the Authorization header.
Steps to create the MD5 Challenge
Create first MD5 hash using username + “:” + realm + “:” + password
String a1 = username + ":" + realm + ":" + password;
String ha1 = toHexString(mdigest.digest(a1.getBytes()));
Create second MD5 hash using request_method + “:” + request_uri
String a2 = request_method.toUpperCase() + ":" + request_uri;
String ha2 = toHexString(mdigest.digest(a2.getBytes()));
If qop in the response header is “auth” then the final MD5 hash is calculated using step 3a else if it is undefined or empty refer step
3b.
3a. Create the final MD5 string using ha1 + “:” + nonce + “:” + nonceCount + “:” + cNonce + “:” + qop + “:” + ha2
String finalStr = ha1 + ":" + nonce + ":" + nonceCount + ":" + cNonce + ":" + qop + ":" + ha2;
String response = toHexString(mdigest.digest(finalStr.getBytes()));
3b. Create the final MD5 string using ha1 + “:” + nonce + “:” + ha2
String finalStr = ha1 + ":" + nonce + ":" + ha2;
String response = toHexString(mdigest.digest(finalStr.getBytes()));
ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip, this.port, "tcp", null);
– Gush