-->

Issue with dialing REGISTERED (but offline) users

2019-08-20 03:51发布

问题:

i'm facing the following scenario: we have to local (REGISTERED) users (iOS apps pjSIP) which initiating local calls between each other. the problem arise when one of the users (let's say user B) is closing the application few minutes after he successfully REGISTERS. now, when user A tries to call user B we see that the INVITE is sent but we got no reply (e.g 180 ringing) from User B.

Note: when we are sending an invite to User B he get's Push notification to his device what cases him to open the app (and to Re-REGISTER)

our targets are: 1. determinate if user B (e.g the callee) is reachable before we are sending an INVITE in cases User B App is closed and his extension is still REGISTERED 2. be able to send invite to user B right after he REGISTER

we tried to solve this issue from many directions: 1.Qualify - tried to decrease the qualify time of the registersion period so user B will be UNAVAILABLE as soon as possible (and we will check the device state before we will dial) but it may cause to massive OPTIONS on our network, and it's not going to solve target #2 2.AMI Service - it can catch events like: User A Dials user B , User B is Ringing (180 Ringing) and save those statuses to ASTDB . all this logic will be prefomed before we will launch the dial. this solution is clumsy and to cmplicated and it requires to watch yet another service

after some research i'v got to the conclusion that the most suitable solution will be to store the time of the last OPTIONS reply of each extension(requires a patch in chan_sip.c) . re-trigger sip options qualify request to user B before User A Dials . if the original value (e.g before we re-triggered the OPTIONS) is equal the value after we trigged the OPTIONS it means that User B has not replied OPTIONS.

i'm attaching the changes i'v preformed to complete this task. i would like to know if solution for the issue is suitable and valid and of course if there is a better way to preform it.

These is the change in chan_sip (using asterisk 11.7) i'v prefomed changes only on the following lines: 23492 to 23500

  23485 /*! \brief Handle qualification responses (OPTIONS) */
  23486 static void handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_request *req)
  23487 {
  23488   struct sip_peer *peer = /* sip_ref_peer( */ p->relatedpeer /* , "bump refcount on p, as it is being used in this function(handle_response_peerpoke)")*/ ; /* hope this is already refcounted! */
  23489   int statechanged, is_reachable, was_reachable;
  23490   int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps);
  23491
  23492   time_t result = time(NULL);
  23493   result = (int)result;

This is how should implement dialplan with the patch:

Dial(SIP/${dest},10,Rgb(check_extension,s,1));

I'm sending the call to context before inviting ( with the "b" option)
context check_extension {
  s => {
    Set(IS_REACHABLE=0);
    Verbose(KOLA/LastQualify/${DEST}); // Display User B initial quliafy
    Set(INITIAL_QUALIFY=${DB(KOLA/LastQualify/${DEST})}); // Store it
    for(loop=0;${loop}<60;dialLoop=${loop}+1) { // Loop untill the qualify will be changes
      System(/usr/sbin/asterisk -rx "sip qualify peer ${DEST}");
      Wait(2); // we need to wait a while for a response
      Set(LAST_QUALIFY=${DB(KOLA/LastQualify/${DEST})}); // set the new qualify
      if (${LAST_QUALIFY} > ${INITIAL_QUALIFY}) { // if the new qualify is newer, User B is reachable
        Set(IS_REACHABLE=1);
        break;
      }
    }

    if (${IS_REACHABLE} = 0) {
      Verbose(Peer is not reachable);
      Hangup();
    }
  }
}

回答1:

Best option for that is not use asterisk.

Use kamailio or opensips project, it can handle thousands of options packets.

Also you HAVE rewrite your app so when it closed it UNREGISTER, as that described in sip RFC.

To summarize: you are using buggy application, and triing do on asterisk thing it not designed to(large amount of users with options). So correct answer - use correct tools for this task.



标签: voip asterisk