views:

336

answers:

3

I currently have a SIP registration working proprly with Jain-SIP.

I get the challenge, use MD5 on the nonce etc and send my reply.

I then get the 200 OK message.

So thats all fine.

However I want to reregister automatically every X seconds depending on the expires time.

To do this I have tried to use a timer to re run the code every X seconds.

However it leads to a couple of problems:

The SipProvider is already attached and wont run a second time. Or I get an error saying the request has already been sent.

So I was wondering if anyone has any advice on how best to reregister with the server every X seconds? As in the reccomended steps to take?


Source code public void register()throws Exception{

    // all this into a create request method
    String fromName = "xxxxxxxx";
    String fromSipAddress = "sip.network.com";

    String toSipAddress = "sip.network.com";
    String toUser = "xxxxxxxx";

    SipURI fromAddress = addressFactory.createSipURI(fromName,
            fromSipAddress);

    Address fromNameAddress = addressFactory.createAddress(fromAddress);
    FromHeader fromHeader = headerFactory.createFromHeader(
            fromNameAddress, null);

    SipURI toAddress = addressFactory
            .createSipURI(toUser, toSipAddress);
    Address toNameAddress = addressFactory.createAddress(toAddress);
    ToHeader toHeader = headerFactory.createToHeader(toNameAddress,
            null);

    URI requestURI = addressFactory.createURI(
            "sip:" + "sip.network.com");

    List<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
    String ipAddress = lp.getIPAddress();
    ViaHeader viaHeader = headerFactory.createViaHeader(ipAddress,
            lp.getPort(),
            lp.getTransport(), null);

    viaHeaders.add(viaHeader);

    CallIdHeader callIdHeader = sipProvider.getNewCallId();

    CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L,
            Request.REGISTER);

    MaxForwardsHeader maxForwards = headerFactory
            .createMaxForwardsHeader(70);

    Request request = messageFactory.createRequest(requestURI,
            Request.REGISTER, callIdHeader, cSeqHeader, fromHeader,
            toHeader, viaHeaders, maxForwards);

    SipURI contactUrl = addressFactory.createSipURI(fromName, fromSipAddress);
    contactUrl.setPort(8002);
    contactUrl.setLrParam();

    SipURI contactURI = addressFactory.createSipURI(fromName, "sip.network.com");
    contactURI.setPort(sipProvider.getListeningPoint(lp.getTransport())
            .getPort());

    Address contactAddress = addressFactory.createAddress(contactURI);

    contactHeader = headerFactory.createContactHeader(contactAddress);
    request.addHeader(contactHeader);
    Header extensionHeader = headerFactory.createHeader("Expires",
        "120");
    request.addHeader(extensionHeader);

    inviteTid = sipProvider.getNewClientTransaction(request);
    inviteTid.sendRequest();
    Log.d("AFTERSENDREQUEST", "SipProvider = : " + sipProvider.toString());

    Log.d("INVITETID", "inviteTid = " + inviteTid.getState());

    dialog = inviteTid.getDialog();

}
public void processResponse(ResponseEvent responseEvent) {
    Message message = Message.obtain();
    message.obj = "received response "+responseEvent.getResponse();
    handler.sendMessage(message);   
    Response response = (Response) responseEvent.getResponse();
    ClientTransaction tid = responseEvent.getClientTransaction();
    CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);

    if (response.getStatusCode() == Response.UNAUTHORIZED){
    try {
        createAuthReply(authHeader, callid);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

UPDATE:

So I've figured that if I keep creating new methods the same as the register() Method and keep the same Call Id and hard code the setting of the port number I can send a few messages like this (Not in a loop).

So I must have to change something in my register code to make sure that it is a NEW request being sent every time or something like that?

Does anyone have any ideas?

+1  A: 

You need not require to initialize service provider everytime you want to send a new Register request. Here are the steps that I suggest you should follow.

  • Initialize service provider
  • Send out first registration request.
  • Once you receive 200 OK - retrieve expires field and start a timer based on that expires value.
  • Once timer is fired send a new Register request - Do not initialize service provider again. (You can check for sipProvider pointer again for NON NULL).
calvinscorner
I have tried doing that but when I try to reregister I get this error java.lang.NullPointerExceptiongov.nist.javax.sip.SipProviderImpl.getNewCallId(SipProviderImpl.java:230)
Donal Rafferty
Are you having correct reference of sipProvider to initiate sipProvider.getNewClientTransaction(request); ?Where are you loosing this reference ?
calvinscorner
I have added more of the code above, so I have the init() to set up the SipProvider, then the register is created and sent and I get 401 UnAuth challenge, I reply with the response and get 200 OK. I then try to reregister again but when I try again the getNewCAllId() throws a null pointer exception
Donal Rafferty
Somehow I'm not able to post comment to your answer, any idea whey?Anyway Glad, that It worked. I did not notice super.finish() in the posted code. More importantly,I'm not at all familiar with Android/Java. It seems you're very much involved with Android? Any good suggestion on where to start with ? I'm involved with Linux based embeded apps development.
calvinscorner
+1  A: 

Okay, I spent quite some time in analyzing this stuff. And really I'm out-of-clue on what are we doing wrong? Everything looks fine to me. Init / Send Register / Start a Timer and on Timer expiry - Again send a register request. It also seems that sipProvider is a global object. Can you just for the sake of debugging purpose perform following two things

Fist, Invoke getNewCallId just after you send first Register request, to see everything is fine.

callIdHeader = sipProvider.getNewCallId();

Or may be try to shift

inviteTid = sipProvider.getNewClientTransaction(request);

ahead of the getNewCallId in new Re-register requst, to veify sipProvider object is available.

What I'm saying is nothing but elementary style of debugging.

calvinscorner
Ooops - Just noticed I added another answer instead of comment.Sorries
calvinscorner
I figured it out, I was trying to get a new call ID when trying to re-register but it turns out in the SIP spec that the call ID should always be the same when sending register messages to the server. I have another problem now - inviteTid = sipProvider.getNewClientTransaction(request); is throwing a null pointer exception!! :(
Donal Rafferty
No, Call-id need not necessarily be the same. It can differ also. Thats the reason server challenges and verifies the Client's identity.And I'm also of the opinion that getNewcallId() method should not fail. All its job is to generate new Call Id.There is nothing wrong in generating new call id.As suspected, any reference to sipProvider object is failing. Earlier it was failing in getNewCallId and now getNewClientTransaction. Is there any way to monitor what is happening to this object once first request is sent out?
calvinscorner
Yeh I have logged the state of the SipProvider all throughout the running of the application and it never gets set to null, even just before the getNewCallId() method is called the object is still there and then the null pointer is thrown when the getNewCallId() method is run. I have added the entire source code which is very messy but you might be able to pick something out of it
Donal Rafferty
Hey @Donal I'm now extremely occupied with some other work and may not be able to respond you for a while. But keep posting if you have any updates.
calvinscorner
No worries, I have tried putting in my register() method several times and if I call the different register() methods, so call register() then register2() then register3() it works this way. but not if I simply put register() in a timer looping. So there must be something I have to terminate and restart or something each time I run the method? More info in my Question
Donal Rafferty
+1  A: 

//Face Palm!!!!!

Error was the SipProvider gets attached to the Activity (Android) and I had super.finish() in the code which killed the activity at the wrong time so the registering still tried but the activity was gone so the sip provider lost its context.

Thanks for your time calvinscorner, really appreciate it

Donal Rafferty