| 1 | = IP Address change handling in 2.7 = |
| 2 | |
| 3 | [[PageOutline(2-3,,inline)]] |
| 4 | |
| 5 | This article describes some issues and their corresponding solutions related to access point disconnection, reconnection, IP address change, and how to handle these events in your PJSIP applications, specifically |
| 6 | on 2.7. This is an update to the previous [wiki:IPAddressChange doc] and will focus on the new API {{{pjsua_handle_ip_change()}}}. |
| 7 | |
| 8 | [[BR]] |
| 9 | |
| 10 | == Problem description == |
| 11 | |
| 12 | IP address change and/or access point disconnection and reconnection are scenarios that need to be handled in mobile applications. Few issues or scenarios related to this for example are: |
| 13 | - user moves outside the range of a Wi-Fi access point (AP) and lost the connection |
| 14 | - user moves outside the range of one AP and reconnect to another |
| 15 | - the handset may get new IP address if user reconnects to different AP |
| 16 | |
| 17 | == IP address change handling using {{{pjsua_handle_ip_change()}}} == |
| 18 | Since 2.7, pjsua API introduce a new API ({{{pjsua_handle_ip_change()}}}) to handle IP address change. This way, application only needs to detect for IP address change event, and let the library |
| 19 | handle the IP address change based on the configuration. |
| 20 | |
| 21 | == API ({{{pjsua_handle_ip_change()}}}) flow == |
| 22 | When invoked, the stack will: |
| 23 | 1. Restart the SIP transport listener [[BR]] |
| 24 | This will restart TCP/TLS listener no matter whether they are enabled or not when the transport were created. If you don't have any use of the listener, you can disable this. |
| 25 | However, if you do need this, then on some platform (e.g: on IOS), some delay is needed when restarting the the listener. [[BR]] |
| 26 | ref: {{{pjsua_ip_change_param.restart_listener}}} and {{{pjsua_ip_change_param.restart_lis_delay}}}. |
| 27 | 2. Shutdown the SIP transport used by account registration [[BR]] |
| 28 | On some platform (e.g: iOS), it is necessary to shutdown the transport used by registration, since presumably the socket is already in a bad state. [[BR]] |
| 29 | ref: {{{pjsua_acc_config.ip_change_cfg.shutdown_tp}}}. |
| 30 | 3. Update contact URI by sending re-Registration [[BR]] |
| 31 | The server needs to be updated of the new Contact URI when the IP address changed. Set it to PJ_TRUE to allow the stack update contact URI to the server. [[BR]] |
| 32 | ref: {{{pjsua_acc_config.allow_contact_rewrite}}} and {{{pjsua_acc_config.contact_rewrite_method}}}. |
| 33 | 4. Hangup active calls or continue the call by sending re-INVITE [[BR]] |
| 34 | You can either hangup or maintain the ongoing/active calls. If you intend to maintain the active calls, updating dialog's contact URI is required. This can be done by specifying {{{PJSUA_CALL_UPDATE_CONTACT }}} to the reinvite flags. Note that, hanging up calls might be inevitable on some cases, please see [wiki:IPv6#NetworkchangetoadifferentIPaddresstype.IPv4toIPv6orIPv6toIPv4 below] [[BR]] |
| 35 | ref: {{{pjsua_acc_config.ip_change_cfg.hangup_calls}}} and {{{pjsua_acc_config.ip_change_cfg.reinvite_flags}}}. |
| 36 | |
| 37 | == Notes and limitations == |
| 38 | To monitor the progress of IP change handling, application can use on_ip_change_progress() callback. The callback will notify application of these events: |
| 39 | restart SIP transport listener |
| 40 | shutdown SIP transport |
| 41 | update contact (re-registration process) |
| 42 | hangup calls |
| 43 | re-INVITE calls |
| 44 | Related to maintaining a call during IP change, there are some scenarios that are currently not implemented by IP change mechanism, so application needs to handle manually: |
| 45 | If IP change occurs during SDP negotiation (and it is not completed yet, so there cannot be another SDP offer), updating such call needs to be done in two steps: |
| 46 | First, updating Contact header, so remote endpoint can send its SDP answer to our new contact address, i.e: use UPDATE without SDP offer ({{{PJSUA_CALL_NO_SDP_OFFER}}} flag). |
| 47 | |
| 48 | Note that, not every endpoint supports UPDATE. Contact is used by remote to resolve target before sending new requests. If proxy is used, then you can probably skip this. |
| 49 | Update local media transport after SDP answer is received, by sending UPDATE/re-INVITE with {{{PJSUA_CALL_REINIT_MEDIA}}} flag. |
| 50 | If IP change occurs before a call is established, there are two possible cases: |
| 51 | Dialog is not yet created, since response with To tag is not received yet. The call needs to be cleared and reported to application via {{{on_call_state().}}} |
| 52 | Dialog is created, (1xx response with To tag is received). |
| 53 | - SDP nego is done, then update Contact and SDP is needed using re-INVITE or UPDATE. |
| 54 | - SDP nego is not done, see point 2 above. |
| 55 | |
| 56 | |
| 57 | |
| 58 | == IP change scenarios == |
| 59 | |
| 60 | === Network change to the same IP address type. (IPv4 to IPv4) or (IPv6 to IPv6) === |
| 61 | |
| 62 | Update contact process (re-Registration) and call handling (hang-up or continue the call) should be handled by the API ({{{pjsua_handle_ip_change()}}}) without any special treatment from the application. |
| 63 | |
| 64 | === Network change to a different IP address type. (IPv4 to IPv6) or (IPv6 to IPv4) === |
| 65 | |
| 66 | As you already know, IPv6 needs specific account configuration as described [wiki:IPv6 here]. |
| 67 | On the case of IP address type change, then additional steps are required from application. |
| 68 | |
| 69 | a) Once application detects a network with IP address type change, a new transport might need to be created. |
| 70 | |
| 71 | b) Once the transport is available, app can change the account configuration needed for IPv6/IPv4 and call {{{pjsua_handle_ip_change()}}}. |
| 72 | |
| 73 | Notes: to maintain ongoing calls, update to RTP/RTCP address and update dialog’s Contact is needed using re-INVITE. However sending re-INVITE might fail when route set is still using IPv4 (e.g: Record-route returned contains IPv4). |
| 74 | In this case, forcefully disconnect the call is recommended. |
| 75 | |
| 76 | {{{ |
| 77 | static void ip_change_to_ip6() |
| 78 | { |
| 79 | ... |
| 80 | //create new ipv6 transport, if it's not yet available. e.g: UDP6 |
| 81 | status = pjsua_transport_create(PJSIP_TRANSPORT_UDP6, |
| 82 | &udp_cfg, |
| 83 | &transport_id); |
| 84 | ... |
| 85 | // modify specific IPv6 account configuration |
| 86 | pjsua_acc_get_config(acc_id, app_config.pool, &acc_cfg); |
| 87 | acc_cfg.ipv6_media_use = PJ_TRUE; |
| 88 | pjsua_acc_set_transport(acc_id, transport_id); |
| 89 | acc_cfg.ip_change_cfg.hangup_calls = PJ_TRUE; |
| 90 | pjsua_acc_modify(acc_id, &acc_cfg); |
| 91 | |
| 92 | ... |
| 93 | // handle ip change |
| 94 | pjsua_ip_change_param_default(¶m); |
| 95 | pjsua_handle_ip_change(param); |
| 96 | } |
| 97 | |
| 98 | }}} |
| 99 | |
| 100 | == IP address change detection == |
| 101 | === iOS === |
| 102 | Have a look at [https://developer.apple.com/library/content/samplecode/Reachability/Introduction/Intro.html Reachability API] |
| 103 | |
| 104 | === Android === |
| 105 | Have a look at [https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html ConnectivityManager] |
| 106 | |
| 107 | |
| 108 | |