The best example I found during registration is here . Here's the point, if, just in case, the connection dries one day:
The REGISTER request is used to update the user's current location to the REGISTRAR server. The application sends a REGISTER message informing the server of its current location, which, in turn, is stored in the location server. When the caller calls the user, the proxy server uses this information to find the location of the called person.
The registration request should be sent periodically by the client. The validity of the REGISTER request is determined by the Expires header.
Flow

Request example
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
Now let's see how to build the above query using the NIST SIP Stack.
The first step is to create a class that implements SIPListener. To do this, make sure your SIP stack initializes the 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 title
Address fromAddress = addressFactory.createAddress ("sip:" + username + '@' + server); FromHeader fromHeader = this.headerFactory.createFromHeader (fromAddress, String.valueOf (this.tag));
Create in title
ToHeader toHeader = this.headerFactory.createToHeader (fromAddress, null);
Create Max-Forward Header
MaxForwardsHeader maxForwardsHeader = this.headerFactory.createMaxForwardsHeader (70);
Create 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 a contact header used for all SIP messages. this.contactHeader = this.headerFactory.createContactHeader (contactAddress);
After creating all the headers, it's time to create the query on its own.
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's time to send the request.
inviteTid = sipProvider.getNewClientTransaction(request);
Once the request has been sent successfully, a response will be sent to the application using the processResponse callback in the SIPListener.
public void processResponse(ResponseEvent responseEvent) { int statusCode = responseEvent.getResponse().getStatusCode(); }
the 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 authentication help message here . Here's the point, if, just in case, the connection dries one day:
During a SIP request, if the server responds with 401 proxies, Authentication is required or 401 Unauthorized, this means that the client must repeat the same request again with an MD5 call.
The client must use the nonce value from the WWW-Authenticate response header.
WWW-Authenticate: digest realm = "sip.linphone.org", nonce = "JbAO1QAAAAA3aDI0AADMobiT7toAAAAA", opaque = "+ GNywA ==", algorithm = MD5, qop = "auth"
The client must use nonce to generate an MD5 call and make an original request with an authorization header.
Steps to Create a Challenge MD5
Create the first MD5 hash using username + ":" + realm + ":" + password
String a1 = username + ":" + realm + ":" + password; String ha1 = toHexString (mdigest.digest (a1.getBytes ()));
Create a 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 step 3b.
3a. Create the final MD5 line 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 line with ha1 + ":" + nonce + ":" + ha2
String finalStr = ha1 + ":" + nonce + ":" + ha2; String response = toHexString(mdigest.digest(finalStr.getBytes()));