Changeset 5649


Ignore:
Timestamp:
Sep 15, 2017 5:32:08 AM (7 years ago)
Author:
riza
Message:

Re #2041: Implement API to handle IP address change.

Location:
pjproject/trunk
Files:
2 added
22 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip-apps/src/pjsua/ios/ipjsua.xcodeproj/project.pbxproj

    r5609 r5649  
    4040                3AF253001EFBD15E00213893 /* libyuv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF252FF1EFBD15E00213893 /* libyuv.a */; }; 
    4141                3AF253021EFBD36E00213893 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF253011EFBD36E00213893 /* VideoToolbox.framework */; }; 
     42                7485A6AF1F09AAE500122F1A /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 7485A6AE1F09AAE500122F1A /* Reachability.m */; }; 
     43                7485A6B11F09B2D500122F1A /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7485A6B01F09B2D500122F1A /* SystemConfiguration.framework */; }; 
    4244                E5E991E61B67A45500017E67 /* libg7221codec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E991D41B67A45500017E67 /* libg7221codec.a */; }; 
    4345                E5E991E71B67A45500017E67 /* libgsmcodec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E991D51B67A45500017E67 /* libgsmcodec.a */; }; 
     
    98100                3AF252FF1EFBD15E00213893 /* libyuv.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libyuv.a; sourceTree = "<group>"; }; 
    99101                3AF253011EFBD36E00213893 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; }; 
     102                741C73BA1F0E64AF00887FB6 /* libopenh264.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libopenh264.a; path = "../../../../../../../../../../openh264-1.6.0/lib_armv7/lib/libopenh264.a"; sourceTree = "<group>"; }; 
     103                7485A6AD1F09AAE500122F1A /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = "<group>"; }; 
     104                7485A6AE1F09AAE500122F1A /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = "<group>"; }; 
     105                7485A6B01F09B2D500122F1A /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 
    100106                E5E991D41B67A45500017E67 /* libg7221codec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libg7221codec.a; sourceTree = "<group>"; }; 
    101107                E5E991D51B67A45500017E67 /* libgsmcodec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgsmcodec.a; sourceTree = "<group>"; }; 
     
    123129                        buildActionMask = 2147483647; 
    124130                        files = ( 
     131                                7485A6B11F09B2D500122F1A /* SystemConfiguration.framework in Frameworks */, 
    125132                                3AF253021EFBD36E00213893 /* VideoToolbox.framework in Frameworks */, 
    126133                                3AB0EC581DA76B39008A0F62 /* libc++.tbd in Frameworks */, 
     
    197204                        isa = PBXGroup; 
    198205                        children = ( 
     206                                741C73BA1F0E64AF00887FB6 /* libopenh264.a */, 
     207                                7485A6B01F09B2D500122F1A /* SystemConfiguration.framework */, 
    199208                                3AF253011EFBD36E00213893 /* VideoToolbox.framework */, 
    200209                                3AB0EC571DA76B39008A0F62 /* libc++.tbd */, 
     
    224233                                3AF0582016F050780046B835 /* ipjsuaViewController.h */, 
    225234                                3AF0582116F050780046B835 /* ipjsuaViewController.m */, 
     235                                7485A6AD1F09AAE500122F1A /* Reachability.h */, 
     236                                7485A6AE1F09AAE500122F1A /* Reachability.m */, 
    226237                                3AF0582316F050780046B835 /* ipjsuaViewController_iPhone.xib */, 
    227238                                3AF0582616F050780046B835 /* ipjsuaViewController_iPad.xib */, 
     
    354365                                3ADCCD2F172E40120007BE8E /* pjsua_app_config.c in Sources */, 
    355366                                3ADCCD30172E40120007BE8E /* pjsua_app_legacy.c in Sources */, 
     367                                7485A6AF1F09AAE500122F1A /* Reachability.m in Sources */, 
    356368                                3ADCCD31172E40120007BE8E /* pjsua_app.c in Sources */, 
    357369                        ); 
  • pjproject/trunk/pjsip-apps/src/pjsua/ios/ipjsua/ipjsuaAppDelegate.m

    r5628 r5649  
    2828 
    2929#import "ipjsuaViewController.h" 
     30#import "Reachability.h" 
    3031 
    3132@implementation ipjsuaAppDelegate 
     
    4041static char           **restartArgv; 
    4142static int              restartArgc; 
     43Reachability            *internetReach; 
     44 
     45- (void) updateWithReachability: (Reachability *)curReach 
     46{ 
     47    NetworkStatus netStatus = [curReach currentReachabilityStatus]; 
     48    BOOL connectionRequired = [curReach connectionRequired]; 
     49    switch (netStatus) { 
     50        case NotReachable: 
     51            PJ_LOG(3,("", "Access Not Available..")); 
     52            connectionRequired= NO; 
     53            break; 
     54        case ReachableViaWiFi: 
     55            PJ_LOG(3,("", "Reachable WiFi..")); 
     56            break; 
     57        case ReachableViaWWAN: 
     58            PJ_LOG(3,("", "Reachable WWAN..")); 
     59        break; 
     60    } 
     61    if (connectionRequired) { 
     62        PJ_LOG(3,("", "Connection Required")); 
     63    } 
     64} 
     65 
     66/* Called by Reachability whenever status changes. */ 
     67- (void)reachabilityChanged: (NSNotification *)note 
     68{ 
     69    Reachability* curReach = [note object]; 
     70    NSParameterAssert([curReach isKindOfClass: [Reachability class]]); 
     71    PJ_LOG(3,("", "reachability changed..")); 
     72    [self updateWithReachability: curReach]; 
     73     
     74    if ([curReach currentReachabilityStatus] != NotReachable && 
     75        ![curReach connectionRequired]) 
     76    { 
     77        pjsua_ip_change_param param; 
     78        pjsua_ip_change_param_default(&param); 
     79        pjsua_handle_ip_change(&param); 
     80    } 
     81} 
     82 
    4283 
    4384void displayLog(const char *msg, int len) 
     
    155196    self.window.rootViewController = self.viewController; 
    156197    [self.window makeKeyAndVisible]; 
     198     
     199    /* Observe the kNetworkReachabilityChangedNotification. When that 
     200     * notification is posted, the method "reachabilityChanged" will be called. 
     201     */ 
     202    [[NSNotificationCenter defaultCenter] addObserver: self 
     203          selector: @selector(reachabilityChanged:) 
     204          name: kReachabilityChangedNotification object: nil]; 
     205     
     206    internetReach = [Reachability reachabilityForInternetConnection]; 
     207    [internetReach startNotifier]; 
     208    [self updateWithReachability: internetReach]; 
    157209     
    158210    app = self; 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app_cli.c

    r5626 r5649  
    3939#define CMD_QUIT                    110 
    4040#define CMD_RESTART                 120 
     41#define CMD_HANDLE_IP_CHANGE        130 
    4142 
    4243/* call level 2 command */ 
     
    25842585    /* Invoke CLI stop callback (defined in pjsua_app.c) */ 
    25852586    cli_on_stopped(PJ_FALSE, 0, NULL); 
     2587 
     2588    return PJ_SUCCESS; 
     2589} 
     2590 
     2591static pj_status_t cmd_ip_change_handler(pj_cli_cmd_val *cval) 
     2592{ 
     2593    pj_status_t status = PJ_SUCCESS; 
     2594    pjsua_ip_change_param param; 
     2595    PJ_UNUSED_ARG(cval); 
     2596 
     2597    pjsua_ip_change_param_default(&param); 
     2598    pjsua_handle_ip_change(&param);     
    25862599 
    25872600    return PJ_SUCCESS; 
     
    30693082        "</CMD>"; 
    30703083 
     3084    char* ip_change_command = 
     3085        "<CMD name='ip_change' id='130' desc='Handle IP change'/>"; 
     3086 
    30713087    pj_status_t status; 
    30723088    pj_str_t sleep_xml = pj_str(sleep_command); 
     
    30743090    pj_str_t shutdown_xml = pj_str(shutdown_command); 
    30753091    pj_str_t restart_xml = pj_str(restart_command); 
     3092    pj_str_t ip_change_xml = pj_str(ip_change_command); 
    30763093 
    30773094    status = pj_cli_add_cmd_from_xml(c, NULL, 
     
    30983115                                     NULL, NULL); 
    30993116 
     3117    if (status != PJ_SUCCESS) 
     3118        return status; 
     3119 
     3120    status = pj_cli_add_cmd_from_xml(c, NULL, 
     3121                                     &ip_change_xml, cmd_ip_change_handler, 
     3122                                     NULL, NULL); 
     3123 
    31003124    return status; 
    31013125} 
  • pjproject/trunk/pjsip-apps/src/swig/java/android/app/src/main/java/org/pjsip/pjsua2/app/MainActivity.java

    r5502 r5649  
    1919package org.pjsip.pjsua2.app; 
    2020 
     21import android.content.IntentFilter; 
    2122import android.os.Bundle; 
    2223import android.os.Handler; 
     
    2728import android.content.Intent; 
    2829import android.content.pm.ApplicationInfo; 
     30import android.content.BroadcastReceiver; 
     31import android.content.Context; 
    2932import android.view.LayoutInflater; 
    3033import android.view.Menu; 
     
    3740import android.widget.SimpleAdapter; 
    3841import android.widget.TextView; 
     42import android.net.ConnectivityManager; 
     43import android.net.NetworkInfo; 
    3944 
    4045import java.util.ArrayList; 
     
    5156    public static MyAccount account = null; 
    5257    public static AccountConfig accCfg = null; 
     58    public static MyBroadcastReceiver receiver = null; 
     59    public static IntentFilter intentFilter = null; 
    5360 
    5461    private ListView buddyListView; 
     
    6673        public final static int BUDDY_STATE = 4; 
    6774        public final static int CALL_MEDIA_STATE = 5; 
     75        public final static int CHANGE_NETWORK = 6; 
     76    } 
     77 
     78    private class MyBroadcastReceiver extends BroadcastReceiver { 
     79        private String conn_name = ""; 
     80 
     81        @Override 
     82        public void onReceive(Context context, Intent intent) { 
     83            if (isNetworkChange(context)) 
     84                notifyChangeNetwork(); 
     85        } 
     86 
     87        private boolean isNetworkChange(Context context) { 
     88            boolean network_changed = false; 
     89            ConnectivityManager connectivity_mgr = 
     90                ((ConnectivityManager)context.getSystemService( 
     91                                                 Context.CONNECTIVITY_SERVICE)); 
     92 
     93            NetworkInfo net_info = connectivity_mgr.getActiveNetworkInfo(); 
     94            if(net_info != null && net_info.isConnectedOrConnecting() && 
     95               !conn_name.equalsIgnoreCase("")) 
     96            { 
     97                String new_con = net_info.getExtraInfo(); 
     98                if (new_con != null && !new_con.equalsIgnoreCase(conn_name)) 
     99                    network_changed = true; 
     100 
     101                conn_name = (new_con == null)?"":new_con; 
     102            } else { 
     103                if (conn_name.equalsIgnoreCase("")) 
     104                    conn_name = net_info.getExtraInfo(); 
     105            } 
     106            return network_changed; 
     107        } 
    68108    } 
    69109 
     
    144184            } 
    145185        ); 
    146  
     186        if (receiver == null) { 
     187            receiver = new MyBroadcastReceiver(); 
     188            intentFilter = new IntentFilter( 
     189                                       ConnectivityManager.CONNECTIVITY_ACTION); 
     190            registerReceiver(receiver, intentFilter); 
     191        } 
    147192    } 
    148193 
     
    264309            showCallActivity(); 
    265310 
     311        } else if (m.what == MSG_TYPE.CHANGE_NETWORK) { 
     312            app.handleNetworkChange(); 
    266313        } else { 
    267314 
     
    577624    } 
    578625 
     626    public void notifyChangeNetwork() 
     627    { 
     628        Message m = Message.obtain(handler, MSG_TYPE.CHANGE_NETWORK, null); 
     629        m.sendToTarget(); 
     630    } 
     631 
    579632    /* === end of MyAppObserver ==== */ 
    580633 
  • pjproject/trunk/pjsip-apps/src/swig/java/android/app/src/main/java/org/pjsip/pjsua2/app/MyApp.java

    r5611 r5649  
    3434    abstract void notifyCallMediaState(MyCall call); 
    3535    abstract void notifyBuddyState(MyBuddy buddy); 
     36    abstract void notifyChangeNetwork(); 
    3637} 
    3738 
     
    535536    } 
    536537 
     538    public void handleNetworkChange() 
     539    { 
     540        try{ 
     541            System.out.println("Network change detected"); 
     542            IpChangeParam changeParam = new IpChangeParam(); 
     543            ep.handleIpChange(changeParam); 
     544        } catch (Exception e) { 
     545            System.out.println(e); 
     546        } 
     547    } 
     548 
    537549    public void deinit() 
    538550    { 
  • pjproject/trunk/pjsip-apps/src/swig/java/sample.java

    r5392 r5649  
    6464        @Override 
    6565        public void notifyBuddyState(MyBuddy buddy) {}   
     66 
     67        @Override 
     68        public void notifyChangeNetwork() {} 
    6669} 
    6770 
  • pjproject/trunk/pjsip-apps/src/swig/symbols.i

    r5636 r5649  
    176176typedef enum pjsua_snd_dev_mode {PJSUA_SND_DEV_SPEAKER_ONLY = 1, PJSUA_SND_DEV_NO_IMMEDIATE_OPEN = 2} pjsua_snd_dev_mode; 
    177177 
     178typedef enum pjsua_ip_change_op {PJSUA_IP_CHANGE_OP_NULL, PJSUA_IP_CHANGE_OP_RESTART_LIS, PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP, PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT, PJSUA_IP_CHANGE_OP_ACC_HANGUP_CALLS, PJSUA_IP_CHANGE_OP_ACC_REINVITE_CALLS} pjsua_ip_change_op; 
     179 
  • pjproject/trunk/pjsip-apps/src/swig/symbols.lst

    r5636 r5649  
    3434pjsip-ua/sip_inv.h              pjsip_inv_state 
    3535 
    36 pjsua-lib/pjsua.h               pjsua_invalid_id_const_ pjsua_state pjsua_stun_use pjsua_call_hold_type pjsua_acc_id pjsua_destroy_flag pjsua_100rel_use pjsua_sip_timer_use pjsua_ipv6_use pjsua_nat64_opt pjsua_buddy_status pjsua_call_media_status pjsua_vid_win_id pjsua_call_id pjsua_med_tp_st pjsua_call_vid_strm_op pjsua_vid_req_keyframe_method pjsua_call_flag pjsua_create_media_transport_flag pjsua_snd_dev_mode 
     36pjsua-lib/pjsua.h               pjsua_invalid_id_const_ pjsua_state pjsua_stun_use pjsua_call_hold_type pjsua_acc_id pjsua_destroy_flag pjsua_100rel_use pjsua_sip_timer_use pjsua_ipv6_use pjsua_nat64_opt pjsua_buddy_status pjsua_call_media_status pjsua_vid_win_id pjsua_call_id pjsua_med_tp_st pjsua_call_vid_strm_op pjsua_vid_req_keyframe_method pjsua_call_flag pjsua_create_media_transport_flag pjsua_snd_dev_mode pjsua_ip_change_op 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport_tcp.h

    r4860 r5649  
    226226PJ_DECL(pj_sock_t) pjsip_tcp_transport_get_socket(pjsip_transport *transport); 
    227227 
     228/** 
     229 * Start the TCP listener, if the listener is not started yet. This is useful 
     230 * to start the listener manually, if listener was not started when  
     231 * PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER is set to 0.  
     232 * 
     233 * @param factory       The SIP TCP transport factory. 
     234 * 
     235 * @param local         The address where the listener should be bound to.  
     236 *                      Both IP interface address and port fields are optional. 
     237 *                      If IP interface address is not specified, socket 
     238 *                      will be bound to PJ_INADDR_ANY. If port is not 
     239 *                      specified, socket will be bound to any port 
     240 *                      selected by the operating system. 
     241 * 
     242 * @param a_name        The published address for the listener.  
     243 *                      If this argument is NULL, then the bound address will  
     244 *                      be used as the published address. 
     245 * 
     246 * @return              PJ_SUCCESS when the listener has been successfully 
     247 *                      started. 
     248 */ 
     249PJ_DECL(pj_status_t) pjsip_tcp_transport_lis_start(pjsip_tpfactory *factory, 
     250                                                const pj_sockaddr *local, 
     251                                                const pjsip_host_port *a_name); 
     252 
     253/** 
     254 * Restart the TCP listener. This will close the listener socket and recreate 
     255 * the socket based on the config used when starting the transport. 
     256 * 
     257 * @param factory       The SIP TCP transport factory. 
     258 *  
     259 * @param local         The address where the listener should be bound to. 
     260 *                      Both IP interface address and port fields are optional. 
     261 *                      If IP interface address is not specified, socket 
     262 *                      will be bound to PJ_INADDR_ANY. If port is not 
     263 *                      specified, socket will be bound to any port 
     264 *                      selected by the operating system. 
     265 * 
     266 * @param a_name        The published address for the listener.  
     267 *                      If this argument is NULL, then the bound address will 
     268 *                      be used as the published address. 
     269 * 
     270 * @return              PJ_SUCCESS when the listener has been successfully  
     271 *                      restarted. 
     272 * 
     273 */ 
     274PJ_DECL(pj_status_t) pjsip_tcp_transport_restart(pjsip_tpfactory *factory,  
     275                                                const pj_sockaddr *local, 
     276                                                const pjsip_host_port *a_name); 
     277 
     278 
    228279PJ_END_DECL 
    229280 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h

    r5472 r5649  
    430430 */ 
    431431PJ_DECL(pj_status_t) pjsip_tls_transport_start2(pjsip_endpoint *endpt, 
    432                                                 const pjsip_tls_setting *opt, 
    433                                                 const pj_sockaddr *local, 
    434                                                 const pjsip_host_port *a_name, 
    435                                                 unsigned async_cnt, 
    436                                                 pjsip_tpfactory **p_factory); 
     432                                                const pjsip_tls_setting *opt, 
     433                                                const pj_sockaddr *local, 
     434                                                const pjsip_host_port *a_name, 
     435                                                unsigned async_cnt, 
     436                                                pjsip_tpfactory **p_factory); 
     437 
     438/** 
     439 * Start the TLS listener, if the listener is not started yet. This is useful 
     440 * to start the listener manually, if listener was not started when 
     441 * PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER is set to 0. 
     442 * 
     443 * @param factory       The SIP TLS transport factory. 
     444 * 
     445 * @param local         The address where the listener should be bound to. 
     446 *                      Both IP interface address and port fields are optional. 
     447 *                      If IP interface address is not specified, socket 
     448 *                      will be bound to PJ_INADDR_ANY. If port is not 
     449 *                      specified, socket will be bound to any port 
     450 *                      selected by the operating system. 
     451 * 
     452 * @param a_name        The published address for the listener. 
     453 *                      If this argument is NULL, then the bound address will 
     454 *                      be used as the published address. 
     455 * 
     456 * @return              PJ_SUCCESS when the listener has been successfully 
     457 *                      started. 
     458 */ 
     459PJ_DECL(pj_status_t) pjsip_tls_transport_lis_start(pjsip_tpfactory *factory, 
     460                                                const pj_sockaddr *local, 
     461                                                const pjsip_host_port *a_name); 
     462 
     463 
     464/** 
     465 * Restart the TLS listener. This will close the listener socket and recreate 
     466 * the socket based on the config used when starting the transport. 
     467 * 
     468 * @param factory       The SIP TLS transport factory. 
     469 * 
     470 * @param local         The address where the listener should be bound to. 
     471 *                      Both IP interface address and port fields are optional. 
     472 *                      If IP interface address is not specified, socket 
     473 *                      will be bound to PJ_INADDR_ANY. If port is not 
     474 *                      specified, socket will be bound to any port 
     475 *                      selected by the operating system. 
     476 * 
     477 * @param a_name        The published address for the listener. 
     478 *                      If this argument is NULL, then the bound address will 
     479 *                      be used as the published address. 
     480 * 
     481 * @return              PJ_SUCCESS when the listener has been successfully 
     482 *                      restarted. 
     483 * 
     484 */ 
     485PJ_DECL(pj_status_t) pjsip_tls_transport_restart(pjsip_tpfactory *factory, 
     486                                                const pj_sockaddr *local, 
     487                                                const pjsip_host_port *a_name); 
    437488 
    438489PJ_END_DECL 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport_udp.h

    r5284 r5649  
    320320                                                 const pjsip_host_port *a_name); 
    321321 
     322/** 
     323 * Restart the transport. Several operations are supported by this function: 
     324 *  - if transport was made temporarily unavailable to SIP stack with 
     325 *    pjsip_udp_transport_pause() and PJSIP_UDP_TRANSPORT_KEEP_SOCKET, 
     326 *    application can make the transport available to the SIP stack 
     327 *    again, by specifying PJSIP_UDP_TRANSPORT_KEEP_SOCKET flag here. 
     328 *  - if application wants to replace the internal socket with a new 
     329 *    socket, it must specify PJSIP_UDP_TRANSPORT_DESTROY_SOCKET when 
     330 *    calling this function, so that the internal socket will be destroyed 
     331 *    if it hasn't been closed. In this case, application has two choices 
     332 *    on how to create the new socket: 1) to let the transport create 
     333 *    the new socket, in this case the \a sock option should be set 
     334 *    to \a PJ_INVALID_SOCKET and optionally the \a local parameter can be 
     335 *    filled with the desired address and port where the new socket  
     336 *    should be bound to, or 2) to specify its own socket to be used 
     337 *    by this transport, by specifying a valid socket in \a sock argument 
     338 *    and set the \a local argument to NULL. In both cases, application 
     339 *    may specify the published address of the socket in \a a_name 
     340 *    argument. This is another version of pjsip_udp_transport_restart()  
     341 *    able to restart IPv6 transport. 
     342 * 
     343 * @param transport     The UDP transport. 
     344 * @param option        Restart option. 
     345 * @param sock          Optional socket to be used by the transport. 
     346 * @param local         The address where the socket should be bound to. 
     347 *                      If this argument is NULL, socket will be bound 
     348 *                      to any available port. 
     349 * @param a_name        Optionally specify the published address for 
     350 *                      this transport. If the socket is not replaced 
     351 *                      (PJSIP_UDP_TRANSPORT_KEEP_SOCKET flag is 
     352 *                      specified), then if this argument is NULL, the 
     353 *                      previous value will be used. If the socket is 
     354 *                      replaced and this argument is NULL, the bound 
     355 *                      address will be used as the published address  
     356 *                      of the transport. 
     357 * 
     358 * @return              PJ_SUCCESS if transport can be restarted, or 
     359 *                      the appropriate error code. 
     360 */ 
     361PJ_DECL(pj_status_t) pjsip_udp_transport_restart2(pjsip_transport *transport, 
     362                                                unsigned option, 
     363                                                pj_sock_t sock, 
     364                                                const pj_sockaddr *local, 
     365                                                const pjsip_host_port *a_name); 
     366 
    322367 
    323368PJ_END_DECL 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r5636 r5649  
    617617 
    618618} pjsua_contact_rewrite_method; 
     619 
     620 
     621/** 
     622 * This enumeration specifies the operation when handling IP change. 
     623 */ 
     624typedef enum pjsua_ip_change_op { 
     625    /** 
     626     * Hasn't start ip change process. 
     627     */ 
     628    PJSUA_IP_CHANGE_OP_NULL, 
     629 
     630    /** 
     631     * The restart listener process. 
     632     */ 
     633    PJSUA_IP_CHANGE_OP_RESTART_LIS, 
     634 
     635    /** 
     636     * The shutdown transport process. 
     637     */ 
     638    PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP, 
     639 
     640    /** 
     641     * The update contact process. 
     642     */ 
     643    PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT, 
     644 
     645    /** 
     646     * The hanging up call process. 
     647     */ 
     648    PJSUA_IP_CHANGE_OP_ACC_HANGUP_CALLS, 
     649 
     650    /** 
     651     * The re-INVITE call process. 
     652     */ 
     653    PJSUA_IP_CHANGE_OP_ACC_REINVITE_CALLS 
     654 
     655} pjsua_ip_change_op; 
     656 
     657 
     658/** 
     659 * This will contain the information of the callback \a on_ip_change_progress. 
     660 */ 
     661typedef union pjsua_ip_change_op_info { 
     662    /** 
     663     * The information from listener restart operation. 
     664     */ 
     665    struct { 
     666        int transport_id; 
     667    } lis_restart; 
     668 
     669    /** 
     670     * The information from shutdown transport. 
     671     */ 
     672    struct { 
     673        int acc_id; 
     674    } acc_shutdown_tp; 
     675 
     676    /** 
     677     * The information from updating contact. 
     678     */ 
     679    struct { 
     680        pjsua_acc_id acc_id; 
     681        pj_bool_t is_register;  /**< SIP Register if PJ_TRUE.       */ 
     682        int code;               /**< SIP status code received.      */ 
     683    } acc_update_contact; 
     684 
     685    /** 
     686     * The information from hanging up call operation. 
     687     */ 
     688    struct { 
     689        pjsua_acc_id acc_id; 
     690        pjsua_call_id call_id; 
     691    } acc_hangup_calls; 
     692 
     693    /** 
     694     * The information from re-Invite call operation. 
     695     */ 
     696    struct { 
     697        pjsua_acc_id acc_id; 
     698        pjsua_call_id call_id; 
     699    } acc_reinvite_calls; 
     700} pjsua_ip_change_op_info; 
    619701 
    620702 
     
    14171499    pj_stun_resolve_cb on_stun_resolution_complete; 
    14181500 
     1501    /**  
     1502     * Calling #pjsua_handle_ip_change() may involve different operation. This  
     1503     * callback is called to report the progress of each enabled operation. 
     1504     * 
     1505     * @param op        The operation. 
     1506     * @param status    The status of operation. 
     1507     * @param info      The info from the operation 
     1508     *  
     1509     */ 
     1510    void (*on_ip_change_progress)(pjsua_ip_change_op op, 
     1511                                  pj_status_t status, 
     1512                                  const pjsua_ip_change_op_info *info); 
     1513 
    14191514} pjsua_callback; 
    14201515 
     
    20812176    unsigned         index; 
    20822177}; 
     2178 
     2179 
     2180/** 
     2181 * This structure describe the parameter passed to #pjsua_handle_ip_change(). 
     2182 */ 
     2183typedef struct pjsua_ip_change_param 
     2184{ 
     2185    /** 
     2186     * If set to PJ_TRUE, this will restart the transport listener. 
     2187     *  
     2188     * Default : PJ_TRUE 
     2189     */ 
     2190    pj_bool_t       restart_listener; 
     2191 
     2192    /**  
     2193     * If \a restart listener is set to PJ_TRUE, some delay might be needed  
     2194     * for the listener to be restarted. Use this to set the delay. 
     2195     *  
     2196     * Default : PJSUA_TRANSPORT_RESTART_DELAY_TIME 
     2197     */ 
     2198    unsigned        restart_lis_delay; 
     2199 
     2200} pjsua_ip_change_param; 
     2201 
     2202 
     2203/** 
     2204 * This structure describe the account config specific to IP address change. 
     2205 */ 
     2206typedef struct pjsua_ip_change_acc_cfg 
     2207{     
     2208    /** 
     2209     * Shutdown the transport used for account registration. If this is set to 
     2210     * PJ_TRUE, the transport will be shutdown altough it's used by multiple 
     2211     * account. Shutdown transport will be followed by re-Registration if 
     2212     * pjsua_acc_config.allow_contact_rewrite is enabled. 
     2213     * 
     2214     * Default: PJ_TRUE 
     2215     */ 
     2216    pj_bool_t           shutdown_tp; 
     2217 
     2218    /** 
     2219     * Hangup active calls associated with the account. If this is set to  
     2220     * PJ_TRUE, then the calls will be hang up. 
     2221     * 
     2222     * Default: PJ_FALSE 
     2223     */ 
     2224    pj_bool_t           hangup_calls; 
     2225 
     2226    /** 
     2227     * Specify the call flags used in the re-INVITE when \a hangup_calls is set  
     2228     * to PJ_FALSE. If this is set to 0, no re-INVITE will be sent. The  
     2229     * re-INVITE will be sent after re-Registration is finished. 
     2230     * 
     2231     * Default: PJSUA_CALL_REINIT_MEDIA | PJSUA_CALL_UPDATE_CONTACT | 
     2232     *          PJSUA_CALL_UPDATE_VIA 
     2233     */ 
     2234    unsigned            reinvite_flags; 
     2235     
     2236} pjsua_ip_change_acc_cfg; 
     2237 
     2238 
     2239/** 
     2240 * Call this function to initialize \a pjsua_ip_change_param with default  
     2241 * values. 
     2242 * 
     2243 * @param param     The IP change param to be initialized. 
     2244 */ 
     2245PJ_DECL(void) pjsua_ip_change_param_default(pjsua_ip_change_param *param); 
    20832246 
    20842247 
     
    23032466PJ_DECL(void) pjsua_dump(pj_bool_t detail); 
    23042467 
     2468 
     2469/** 
     2470 * Inform the stack that IP address change event was detected.  
     2471 * The stack will: 
     2472 * 1. Restart the listener (this step is configurable via  
     2473 *    \a pjsua_ip_change_param.restart_listener). 
     2474 * 2. Shutdown the transport used by account registration (this step is  
     2475 *    configurable via \a pjsua_acc_config.ip_change_cfg.shutdown_tp). 
     2476 * 3. Update contact URI by sending re-Registration (this step is configurable  
     2477 *    via a\ pjsua_acc_config.allow_contact_rewrite and  
     2478 *    a\ pjsua_acc_config.contact_rewrite_method) 
     2479 * 4. Hangup active calls (this step is configurable via  
     2480 *    a\ pjsua_acc_config.ip_change_cfg.hangup_calls) or  
     2481 *    continue the call by sending re-INVITE  
     2482 *    (configurable via \a pjsua_acc_config.ip_change_cfg.reinvite_flags). 
     2483 * 
     2484 * @param param         The IP change parameter, have a look at  
     2485 *                      #pjsua_ip_change_param. 
     2486 * 
     2487 * @return              PJ_SUCCESS on success, other on error. 
     2488 */ 
     2489PJ_DECL(pj_status_t) pjsua_handle_ip_change( 
     2490                                           const pjsua_ip_change_param *param); 
     2491 
     2492 
    23052493/** 
    23062494 * @} 
     
    25772765PJ_DECL(pj_status_t) pjsua_transport_close( pjsua_transport_id id, 
    25782766                                            pj_bool_t force ); 
     2767 
     2768 
     2769/** 
     2770 * Start the listener of the transport. This is useful when listener is not  
     2771 * automatically started when creating the transport. 
     2772 * 
     2773 * @param id            Transport ID. 
     2774 * @param cfg           The new transport config used by the listener.  
     2775 *                      Only port, public_addr and bound_addr are used at the  
     2776 *                      moment. 
     2777 * 
     2778 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     2779 */ 
     2780PJ_DECL(pj_status_t) pjsua_transport_lis_start( pjsua_transport_id id, 
     2781                                            const pjsua_transport_config *cfg); 
     2782 
    25792783 
    25802784/** 
     
    35423746     * Default: PJ_TRUE 
    35433747     */ 
    3544     pj_bool_t         register_on_acc_add; 
     3748    pj_bool_t           register_on_acc_add; 
     3749 
     3750    /** 
     3751     * Specify account configuration specific to IP address change used when 
     3752     * calling #pjsua_handle_ip_change(). 
     3753     */ 
     3754    pjsua_ip_change_acc_cfg ip_change_cfg; 
    35453755 
    35463756} pjsua_acc_config; 
     
    57295939 
    57305940/** 
     5941 * Specify the delay needed when restarting the transport/listener. 
     5942 * e.g: 10 msec on Linux or Android, and 0 on the other platforms. 
     5943 */ 
     5944#ifndef PJSUA_TRANSPORT_RESTART_DELAY_TIME 
     5945#   define PJSUA_TRANSPORT_RESTART_DELAY_TIME   10 
     5946#endif 
     5947 
     5948 
     5949/** 
    57315950 * This structure describes media configuration, which will be specified 
    57325951 * when calling #pjsua_init(). Application MUST initialize this structure 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r5636 r5649  
    286286    pjsip_transport_type_e tp_type; /**< Transport type (for local acc or 
    287287                                         transport binding)             */ 
     288    pjsua_ip_change_op ip_change_op;/**< IP change process progress.    */ 
    288289} pjsua_acc; 
    289290 
     
    304305    } data; 
    305306 
     307    pj_bool_t                is_restarting; 
    306308} pjsua_transport_data; 
    307309 
     
    868870void pjsua_call_schedule_reinvite_check(pjsua_call *call, unsigned delay_ms); 
    869871 
     872/* 
     873 * Update contact per account on IP change process. 
     874 */ 
     875pj_status_t pjsua_acc_update_contact_on_ip_change(pjsua_acc *acc); 
     876 
     877/* 
     878 * Call handling per account on IP change process. 
     879 */ 
     880pj_status_t pjsua_acc_handle_call_on_ip_change(pjsua_acc *acc); 
     881 
    870882PJ_END_DECL 
    871883 
  • pjproject/trunk/pjsip/include/pjsua2/account.hpp

    r5636 r5649  
    882882 
    883883/** 
     884 * Account config specific to IP address change. 
     885 */ 
     886typedef struct AccountIpChangeConfig 
     887{     
     888    /** 
     889     * Shutdown the transport used for account registration. If this is set to 
     890     * PJ_TRUE, the transport will be shutdown altough it's used by multiple 
     891     * account. Shutdown transport will be followed by re-Registration if 
     892     * AccountConfig.natConfig.contactRewriteUse is enabled. 
     893     * 
     894     * Default: true 
     895     */ 
     896    bool                shutdownTp; 
     897 
     898    /** 
     899     * Hangup active calls associated with the acount. If this is set to true,  
     900     * then the calls will be hang up. 
     901     * 
     902     * Default: false 
     903     */ 
     904    bool                hangupCalls; 
     905 
     906    /** 
     907     * Specify the call flags used in the re-INVITE when \a hangupCalls is set  
     908     * to false. If this is set to 0, no re-INVITE will be sent. The  
     909     * re-INVITE will be sent after re-Registration is finished. 
     910     * 
     911     * Default: PJSUA_CALL_REINIT_MEDIA | PJSUA_CALL_UPDATE_CONTACT | 
     912     *          PJSUA_CALL_UPDATE_VIA 
     913     */ 
     914    unsigned            reinviteFlags; 
     915 
     916public: 
     917    /** 
     918     * Read this object from a container node. 
     919     * 
     920     * @param node              Container to read values from. 
     921     */ 
     922    virtual void readObject(const ContainerNode &node) throw(Error); 
     923 
     924    /** 
     925     * Write this object to a container node. 
     926     * 
     927     * @param node              Container to write values to. 
     928     */ 
     929    virtual void writeObject(ContainerNode &node) const throw(Error); 
     930     
     931} AccountIpChangeConfig; 
     932 
     933/** 
    884934 * Account configuration. 
    885935 */ 
     
    941991     */ 
    942992    AccountVideoConfig  videoConfig; 
     993 
     994    /** 
     995     * IP Change settings. 
     996     */ 
     997    AccountIpChangeConfig ipChangeConfig; 
    943998 
    944999public: 
  • pjproject/trunk/pjsip/include/pjsua2/endpoint.hpp

    r5636 r5649  
    319319    int                 accountIndex; 
    320320}; 
     321 
     322/** 
     323 * Parameter of Endpoint::handleIpChange(). 
     324 */ 
     325struct IpChangeParam { 
     326    /** 
     327     * If set to PJ_TRUE, this will restart the transport listener. 
     328     *  
     329     * Default : PJ_TRUE 
     330     */ 
     331    bool            restartListener; 
     332 
     333    /**  
     334     * If \a restartListener is set to PJ_TRUE, some delay might be needed  
     335     * for the listener to be restarted. Use this to set the delay. 
     336     *  
     337     * Default : PJSUA_TRANSPORT_RESTART_DELAY_TIME 
     338     */ 
     339    unsigned        restartLisDelay; 
     340public: 
     341    /** 
     342     * Constructor. 
     343     */ 
     344    IpChangeParam(); 
     345 
     346    /** 
     347     * Export to pjsua_ip_change_param. 
     348     */ 
     349    pjsua_ip_change_param toPj() const; 
     350 
     351    /** 
     352     * Convert from pjsip 
     353     */ 
     354    void fromPj(const pjsua_ip_change_param &param); 
     355}; 
     356 
     357/** 
     358 * Information of Update contact on IP change progress. 
     359 */ 
     360struct RegProgressParam 
     361{ 
     362    /** 
     363     * Indicate if this is a Register or Un-Register message. 
     364     */ 
     365    bool    isRegister; 
     366 
     367    /** 
     368     * SIP status code received. 
     369     */ 
     370    int     code; 
     371}; 
     372 
     373/** 
     374 * Parameter of Endpoint::onIpChangeProgress(). 
     375 */ 
     376struct OnIpChangeProgressParam 
     377{ 
     378    /** 
     379     * The IP change progress operation. 
     380     */ 
     381    pjsua_ip_change_op  op; 
     382 
     383    /** 
     384     * The operation progress status. 
     385     */ 
     386    pj_status_t         status; 
     387 
     388    /** 
     389     * Information of the transport id. This is only available when the  
     390     * operation is PJSUA_IP_CHANGE_OP_RESTART_LIS. 
     391     */ 
     392    TransportId         transportId; 
     393 
     394    /** 
     395     * Information of the account id. This is only available when the  
     396     * operation is: 
     397     * - PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP  
     398     * - PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT  
     399     * - PJSUA_IP_CHANGE_OP_ACC_HANGUP_CALLS 
     400     * - PJSUA_IP_CHANGE_OP_ACC_REINVITE_CALLS 
     401     */ 
     402    int                 accId; 
     403 
     404    /** 
     405     * Information of the call id. This is only available when the operation is 
     406     * PJSUA_IP_CHANGE_OP_ACC_HANGUP_CALLS or  
     407     * PJSUA_IP_CHANGE_OP_ACC_REINVITE_CALLS 
     408     */ 
     409    int                 callId; 
     410 
     411    /** 
     412     * Registration information. This is only available when the operation is 
     413     * PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT 
     414     */ 
     415    RegProgressParam    regInfo; 
     416}; 
     417 
    321418 
    322419////////////////////////////////////////////////////////////////////////////// 
     
    13771474    void resetVideoCodecParam(const string &codec_id) throw(Error); 
    13781475 
     1476    /************************************************************************* 
     1477     * IP Change 
     1478     */ 
     1479 
     1480    /** 
     1481     * Inform the stack that IP address change event was detected. 
     1482     * The stack will: 
     1483     * 1. Restart the listener (this step is configurable via 
     1484     *    \a IpChangeParam.restartListener). 
     1485     * 2. Shutdown the transport used by account registration (this step is 
     1486     *    configurable via \a AccountConfig.ipChangeConfig.shutdownTp). 
     1487     * 3. Update contact URI by sending re-Registration (this step is  
     1488     *    configurable via a\ AccountConfig.natConfig.contactRewriteUse and 
     1489     *    a\ AccountConfig.natConfig.contactRewriteMethod) 
     1490     * 4. Hangup active calls (this step is configurable via 
     1491     *    a\ AccountConfig.ipChangeConfig.hangupCalls) or 
     1492     *    continue the call by sending re-INVITE 
     1493     *    (configurable via \a AccountConfig.ipChangeConfig.reinviteFlags). 
     1494     * 
     1495     * @param param     The IP change parameter, have a look at #IpChangeParam. 
     1496     * 
     1497     * @return          PJ_SUCCESS on success, other on error. 
     1498     */ 
     1499    void handleIpChange(const IpChangeParam &param) throw(Error); 
     1500 
    13791501public: 
    13801502    /* 
     
    14381560     */ 
    14391561    virtual void onSelectAccount(OnSelectAccountParam &prm) 
     1562    { PJ_UNUSED_ARG(prm); } 
     1563 
     1564    /** 
     1565     * Calling #handleIpChange() may involve different operation. This  
     1566     * callback is called to report the progress of each enabled operation. 
     1567     * 
     1568     * @param prm       Callback parameters. 
     1569     *  
     1570     */ 
     1571    virtual void onIpChangeProgress(OnIpChangeProgressParam &prm) 
    14401572    { PJ_UNUSED_ARG(prm); } 
    14411573 
     
    15881720                                   pjmedia_srtp_setting *srtp_opt); 
    15891721 
     1722    static void 
     1723    on_ip_change_progress(pjsua_ip_change_op op, 
     1724                          pj_status_t status, 
     1725                          const pjsua_ip_change_op_info *info); 
     1726 
    15901727private: 
    15911728    void clearCodecInfoList(CodecInfoVector &codec_list); 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c

    r5534 r5649  
    6262    pj_qos_params            qos_params; 
    6363    pj_sockopt_params        sockopt_params; 
     64    pj_bool_t                reuse_addr;         
     65    unsigned                 async_cnt;     
    6466 
    6567    /* Group lock to be used by TCP listener and ioqueue key */ 
     
    242244 */ 
    243245 
     246static void update_bound_addr(struct tcp_listener *listener, 
     247                              const pj_sockaddr *local) 
     248{ 
     249    pj_sockaddr *listener_addr = &listener->factory.local_addr; 
     250    int af = pjsip_transport_type_get_af(listener->factory.type); 
     251 
     252    /* Bind address may be different than factory.local_addr because 
     253     * factory.local_addr will be resolved. 
     254     */ 
     255    if (local) { 
     256        pj_sockaddr_cp(&listener->bound_addr, local); 
     257    } 
     258    else { 
     259        pj_sockaddr_init(af, &listener->bound_addr, NULL, 0); 
     260    } 
     261    pj_sockaddr_cp(listener_addr, &listener->bound_addr); 
     262} 
     263 
     264static pj_status_t update_factory_addr(struct tcp_listener *listener,                                   
     265                                       const pjsip_host_port *addr_name) 
     266{ 
     267    pj_status_t status = PJ_SUCCESS;     
     268    pj_sockaddr *listener_addr = &listener->factory.local_addr;     
     269 
     270    /* If published host/IP is specified, then use that address as the 
     271     * listener advertised address. 
     272     */ 
     273    if (addr_name && addr_name->host.slen) { 
     274        pj_sockaddr tmp; 
     275        int af = pjsip_transport_type_get_af(listener->factory.type); 
     276 
     277        /* Verify that address given in a_name (if any) is valid */ 
     278        status = pj_sockaddr_init(af, &tmp, &addr_name->host, 
     279                                  (pj_uint16_t)addr_name->port); 
     280        if (status != PJ_SUCCESS || !pj_sockaddr_has_addr(&tmp) || 
     281            (af == pj_AF_INET() && tmp.ipv4.sin_addr.s_addr == PJ_INADDR_NONE)) 
     282        { 
     283            /* Invalid address */ 
     284            return PJ_EINVAL; 
     285        } 
     286 
     287        /* Copy the address */ 
     288        listener->factory.addr_name = *addr_name; 
     289        pj_strdup(listener->factory.pool, &listener->factory.addr_name.host, 
     290                  &addr_name->host); 
     291        listener->factory.addr_name.port = addr_name->port; 
     292 
     293    } else { 
     294        /* No published address is given, use the bound address */ 
     295 
     296        /* If the address returns 0.0.0.0, use the default 
     297         * interface address as the transport's address. 
     298         */ 
     299        if (!pj_sockaddr_has_addr(listener_addr)) { 
     300            pj_sockaddr hostip; 
     301 
     302            status = pj_gethostip(listener->bound_addr.addr.sa_family, 
     303                                  &hostip); 
     304            if (status != PJ_SUCCESS) 
     305                return status; 
     306 
     307            pj_sockaddr_copy_addr(listener_addr, &hostip); 
     308        } 
     309 
     310        /* Save the address name */ 
     311        sockaddr_to_host_port(listener->factory.pool, 
     312                              &listener->factory.addr_name, 
     313                              listener_addr); 
     314    } 
     315 
     316    /* If port is zero, get the bound port */ 
     317    if (listener->factory.addr_name.port == 0) { 
     318        listener->factory.addr_name.port = pj_sockaddr_get_port(listener_addr); 
     319    } 
     320 
     321    pj_ansi_snprintf(listener->factory.obj_name, 
     322                     sizeof(listener->factory.obj_name), 
     323                     "tcptp:%d", listener->factory.addr_name.port); 
     324    return status; 
     325} 
     326 
     327static void update_transport_info(struct tcp_listener *listener) 
     328{     
     329    enum { INFO_LEN = 100 }; 
     330    char local_addr[PJ_INET6_ADDRSTRLEN + 10]; 
     331    pj_sockaddr *listener_addr = &listener->factory.local_addr; 
     332 
     333    /* Set transport info. */ 
     334    if (listener->factory.info == NULL) { 
     335        listener->factory.info = (char*)pj_pool_alloc(listener->factory.pool, 
     336                                                      INFO_LEN); 
     337    } 
     338    pj_sockaddr_print(listener_addr, local_addr, sizeof(local_addr), 3); 
     339    pj_ansi_snprintf( 
     340            listener->factory.info, INFO_LEN, "tcp %s [published as %.*s:%d]", 
     341            local_addr, 
     342            (int)listener->factory.addr_name.host.slen, 
     343            listener->factory.addr_name.host.ptr, 
     344            listener->factory.addr_name.port); 
     345 
     346    if (listener->asock) { 
     347        PJ_LOG(4, (listener->factory.obj_name, 
     348               "SIP TCP listener ready for incoming connections at %.*s:%d", 
     349               (int)listener->factory.addr_name.host.slen, 
     350               listener->factory.addr_name.host.ptr, 
     351               listener->factory.addr_name.port)); 
     352    } else { 
     353        PJ_LOG(4, (listener->factory.obj_name, "SIP TCP is ready " 
     354               "(client only)")); 
     355    } 
     356} 
     357 
    244358/* 
    245359 * This is the public API to create, initialize, register, and start the 
     
    251365                                        pjsip_tpfactory **p_factory 
    252366                                        ) 
    253 { 
    254     enum { INFO_LEN = 100 }; 
    255     char local_addr[PJ_INET6_ADDRSTRLEN+10]; 
    256     pj_pool_t *pool; 
    257     pj_sock_t sock = PJ_INVALID_SOCKET; 
    258     struct tcp_listener *listener; 
    259     pj_activesock_cfg asock_cfg; 
    260     pj_activesock_cb listener_cb; 
    261     pj_sockaddr *listener_addr; 
    262     int addr_len; 
    263     pj_bool_t has_listener = PJ_FALSE; 
     367{         
     368    pj_pool_t *pool;     
     369    struct tcp_listener *listener;         
    264370    pj_status_t status; 
    265371 
    266372    /* Sanity check */ 
    267373    PJ_ASSERT_RETURN(endpt && cfg->async_cnt, PJ_EINVAL); 
    268  
    269     /* Verify that address given in a_name (if any) is valid */ 
    270     if (cfg->addr_name.host.slen) { 
    271         pj_sockaddr tmp; 
    272  
    273         status = pj_sockaddr_init(cfg->af, &tmp, &cfg->addr_name.host,  
    274                                   (pj_uint16_t)cfg->addr_name.port); 
    275         if (status != PJ_SUCCESS || !pj_sockaddr_has_addr(&tmp) || 
    276             (cfg->af==pj_AF_INET() &&  
    277              tmp.ipv4.sin_addr.s_addr==PJ_INADDR_NONE))  
    278         { 
    279             /* Invalid address */ 
    280             return PJ_EINVAL; 
    281         } 
    282     } 
    283374 
    284375    pool = pjsip_endpt_create_pool(endpt, "tcptp", POOL_LIS_INIT,  
     
    292383                                                     PJSIP_TRANSPORT_TCP6; 
    293384    listener->factory.type_name = (char*) 
    294                 pjsip_transport_get_type_name(listener->factory.type); 
     385                         pjsip_transport_get_type_name(listener->factory.type); 
    295386    listener->factory.flag =  
    296         pjsip_transport_get_flag_from_type(listener->factory.type); 
     387                    pjsip_transport_get_flag_from_type(listener->factory.type); 
    297388    listener->qos_type = cfg->qos_type; 
     389    listener->reuse_addr = cfg->reuse_addr; 
     390    listener->async_cnt = cfg->async_cnt; 
    298391    pj_memcpy(&listener->qos_params, &cfg->qos_params, 
    299392              sizeof(cfg->qos_params)); 
     
    308401                                            &listener->factory.lock); 
    309402    if (status != PJ_SUCCESS) 
    310         goto on_error; 
    311  
    312 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \ 
    313       PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0) 
    314  
    315     /* Create socket */ 
    316     status = pj_sock_socket(cfg->af, pj_SOCK_STREAM(), 0, &sock); 
    317     if (status != PJ_SUCCESS) 
    318         goto on_error; 
    319  
    320     /* Apply QoS, if specified */ 
    321     status = pj_sock_apply_qos2(sock, cfg->qos_type, &cfg->qos_params,  
    322                                 2, listener->factory.obj_name,  
    323                                 "SIP TCP listener socket"); 
    324  
    325     /* Apply SO_REUSEADDR */ 
    326     if (cfg->reuse_addr) { 
    327         int enabled = 1; 
    328         status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), 
    329                                     &enabled, sizeof(enabled)); 
    330         if (status != PJ_SUCCESS) { 
    331             PJ_PERROR(4,(listener->factory.obj_name, status, 
    332                          "Warning: error applying SO_REUSEADDR")); 
    333         } 
    334     } 
    335  
    336     /* Apply socket options, if specified */ 
    337     if (cfg->sockopt_params.cnt) 
    338         status = pj_sock_setsockopt_params(sock, &cfg->sockopt_params); 
    339  
    340 #else 
    341     PJ_UNUSED_ARG(addr_len); 
    342 #endif 
    343  
    344     /* Bind address may be different than factory.local_addr because 
    345      * factory.local_addr will be resolved below. 
    346      */ 
    347     pj_sockaddr_cp(&listener->bound_addr, &cfg->bind_addr); 
    348  
    349     /* Bind socket */ 
    350     listener_addr = &listener->factory.local_addr; 
    351     pj_sockaddr_cp(listener_addr, &cfg->bind_addr); 
    352  
    353 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \ 
    354       PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0) 
    355  
    356     status = pj_sock_bind(sock, listener_addr,  
    357                           pj_sockaddr_get_len(listener_addr)); 
    358     if (status != PJ_SUCCESS) 
    359         goto on_error; 
    360  
    361     /* Retrieve the bound address */ 
    362     addr_len = pj_sockaddr_get_len(listener_addr); 
    363     status = pj_sock_getsockname(sock, listener_addr, &addr_len); 
    364     if (status != PJ_SUCCESS) 
    365         goto on_error; 
    366  
    367 #endif 
    368  
    369     /* If published host/IP is specified, then use that address as the 
    370      * listener advertised address. 
    371      */ 
    372     if (cfg->addr_name.host.slen) { 
    373         /* Copy the address */ 
    374         listener->factory.addr_name = cfg->addr_name; 
    375         pj_strdup(listener->factory.pool, &listener->factory.addr_name.host,  
    376                   &cfg->addr_name.host); 
    377         listener->factory.addr_name.port = cfg->addr_name.port; 
    378  
    379     } else { 
    380         /* No published address is given, use the bound address */ 
    381  
    382         /* If the address returns 0.0.0.0, use the default 
    383          * interface address as the transport's address. 
    384          */ 
    385         if (!pj_sockaddr_has_addr(listener_addr)) { 
    386             pj_sockaddr hostip; 
    387  
    388             status = pj_gethostip(listener->bound_addr.addr.sa_family, 
    389                                   &hostip); 
    390             if (status != PJ_SUCCESS) 
    391                 goto on_error; 
    392  
    393             pj_sockaddr_copy_addr(listener_addr, &hostip); 
    394         } 
    395  
    396         /* Save the address name */ 
    397         sockaddr_to_host_port(listener->factory.pool,  
    398                               &listener->factory.addr_name,  
    399                               listener_addr); 
    400     } 
    401  
    402     /* If port is zero, get the bound port */ 
    403     if (listener->factory.addr_name.port == 0) { 
    404         listener->factory.addr_name.port = pj_sockaddr_get_port(listener_addr); 
    405     } 
    406  
    407     pj_ansi_snprintf(listener->factory.obj_name,  
    408                      sizeof(listener->factory.obj_name), 
    409                      "tcptp:%d",  listener->factory.addr_name.port); 
    410  
    411  
    412 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \ 
    413       PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0) 
    414  
    415     /* Start listening to the address */ 
    416     status = pj_sock_listen(sock, PJSIP_TCP_TRANSPORT_BACKLOG); 
    417     if (status != PJ_SUCCESS) 
    418         goto on_error; 
    419  
    420  
    421     /* Create active socket */ 
    422     pj_activesock_cfg_default(&asock_cfg); 
    423     if (cfg->async_cnt > MAX_ASYNC_CNT)  
    424         asock_cfg.async_cnt = MAX_ASYNC_CNT; 
    425     else 
    426         asock_cfg.async_cnt = cfg->async_cnt; 
    427  
    428 #endif 
     403        goto on_error;     
    429404 
    430405    /* Create group lock */ 
    431406    status = pj_grp_lock_create(pool, NULL, &listener->grp_lock); 
    432407    if (status != PJ_SUCCESS) 
    433         return status; 
     408        goto on_error; 
    434409 
    435410    pj_grp_lock_add_ref(listener->grp_lock); 
    436411    pj_grp_lock_add_handler(listener->grp_lock, pool, listener, 
    437412                            &lis_on_destroy); 
    438  
    439     asock_cfg.grp_lock = listener->grp_lock; 
    440  
    441     pj_bzero(&listener_cb, sizeof(listener_cb)); 
    442     listener_cb.on_accept_complete = &on_accept_complete; 
    443  
    444 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \ 
    445       PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0) 
    446  
    447     status = pj_activesock_create(pool, sock, pj_SOCK_STREAM(), &asock_cfg, 
    448                                   pjsip_endpt_get_ioqueue(endpt),  
    449                                   &listener_cb, listener, 
    450                                   &listener->asock); 
    451  
    452 #endif 
    453413 
    454414    /* Register to transport manager */ 
     
    456416    listener->tpmgr = pjsip_endpt_get_tpmgr(endpt); 
    457417    listener->factory.create_transport = lis_create_transport; 
    458     listener->factory.destroy = lis_destroy; 
     418    listener->factory.destroy = lis_destroy;     
     419 
     420#if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \ 
     421              PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0) 
     422    /* Start listener. */ 
     423    status = pjsip_tcp_transport_lis_start(&listener->factory, &cfg->bind_addr,  
     424                                           &cfg->addr_name); 
     425    if (status != PJ_SUCCESS) 
     426        goto on_error; 
     427 
     428#else 
     429    update_bound_addr(listener, &cfg->bind_addr); 
     430    status = update_factory_addr(listener, &cfg->addr_name); 
     431    if (status != PJ_SUCCESS) 
     432        goto on_error; 
     433 
     434    /* Set transport info. */ 
     435    update_transport_info(listener); 
     436#endif 
     437 
    459438    listener->is_registered = PJ_TRUE; 
    460439    status = pjsip_tpmgr_register_tpfactory(listener->tpmgr, 
     
    465444    } 
    466445 
    467 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \ 
    468       PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0) 
    469  
    470     /* Start pending accept() operations */ 
    471     status = pj_activesock_start_accept(listener->asock, pool); 
    472     if (status != PJ_SUCCESS) 
    473         goto on_error; 
    474          
    475     has_listener = PJ_TRUE; 
    476  
    477 #endif 
    478  
    479     /* Set transport info. */ 
    480     if (listener->factory.info == NULL) { 
    481         listener->factory.info = (char*) pj_pool_alloc(listener->factory.pool, 
    482                                                        INFO_LEN); 
    483     } 
    484     pj_sockaddr_print(listener_addr, local_addr, sizeof(local_addr), 3); 
    485     pj_ansi_snprintf(  
    486         listener->factory.info, INFO_LEN, "tcp %s [published as %.*s:%d]", 
    487         local_addr, 
    488         (int)listener->factory.addr_name.host.slen, 
    489         listener->factory.addr_name.host.ptr, 
    490         listener->factory.addr_name.port); 
    491  
    492     if (has_listener) { 
    493         PJ_LOG(4,(listener->factory.obj_name,  
    494                  "SIP TCP listener ready for incoming connections at %.*s:%d", 
    495                  (int)listener->factory.addr_name.host.slen, 
    496                  listener->factory.addr_name.host.ptr, 
    497                  listener->factory.addr_name.port)); 
    498     } else { 
    499         PJ_LOG(4,(listener->factory.obj_name, "SIP TCP is ready " 
    500                   "(client only)"));     
    501     } 
    502  
    503446    /* Return the pointer to user */ 
    504447    if (p_factory) *p_factory = &listener->factory; 
     
    507450 
    508451on_error: 
    509     if (listener->asock==NULL && sock!=PJ_INVALID_SOCKET) 
    510         pj_sock_close(sock); 
    511452    lis_destroy(&listener->factory); 
    512453    return status; 
     
    572513} 
    573514 
    574  
    575 /* This callback is called by transport manager to destroy listener */ 
    576 static pj_status_t lis_destroy(pjsip_tpfactory *factory) 
    577 { 
    578     struct tcp_listener *listener = (struct tcp_listener *)factory; 
    579  
     515/* This will close the listener. */ 
     516static void lis_close(struct tcp_listener *listener) 
     517{ 
    580518    if (listener->is_registered) { 
    581519        pjsip_tpmgr_unregister_tpfactory(listener->tpmgr, &listener->factory); 
     
    587525        listener->asock = NULL; 
    588526    } 
     527} 
     528 
     529/* This callback is called by transport manager to destroy listener */ 
     530static pj_status_t lis_destroy(pjsip_tpfactory *factory) 
     531{ 
     532    struct tcp_listener *listener = (struct tcp_listener *)factory; 
     533 
     534    lis_close(listener); 
    589535 
    590536    if (listener->grp_lock) { 
     
    16381584 
    16391585 
     1586PJ_DEF(pj_status_t) pjsip_tcp_transport_lis_start(pjsip_tpfactory *factory, 
     1587                                                 const pj_sockaddr *local, 
     1588                                                 const pjsip_host_port *a_name) 
     1589{ 
     1590    pj_activesock_cfg asock_cfg; 
     1591    pj_activesock_cb listener_cb; 
     1592    pj_sock_t sock = PJ_INVALID_SOCKET; 
     1593    int addr_len, af;     
     1594    struct tcp_listener *listener = (struct tcp_listener *)factory; 
     1595    pj_sockaddr *listener_addr = &factory->local_addr; 
     1596    pj_status_t status = PJ_SUCCESS; 
     1597 
     1598    /* Nothing to be done, if listener already started. */ 
     1599    if (listener->asock) 
     1600        return PJ_SUCCESS; 
     1601     
     1602    update_bound_addr(listener, local); 
     1603       
     1604    addr_len = pj_sockaddr_get_len(listener_addr); 
     1605    af = pjsip_transport_type_get_af(listener->factory.type); 
     1606 
     1607    /* Create socket */ 
     1608    status = pj_sock_socket(af, pj_SOCK_STREAM(), 0, &sock); 
     1609    if (status != PJ_SUCCESS) 
     1610        goto on_error; 
     1611 
     1612    /* Apply QoS, if specified */ 
     1613    status = pj_sock_apply_qos2(sock, listener->qos_type, 
     1614                                &listener->qos_params, 2, 
     1615                                listener->factory.obj_name, 
     1616                                "SIP TCP listener socket"); 
     1617 
     1618    /* Apply SO_REUSEADDR */ 
     1619    if (listener->reuse_addr) { 
     1620        int enabled = 1; 
     1621        status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), 
     1622                                    &enabled, sizeof(enabled)); 
     1623        if (status != PJ_SUCCESS) { 
     1624            PJ_LOG(1, ("TRACE", "fail set reuseaddr")); 
     1625            PJ_PERROR(4, (listener->factory.obj_name, status, 
     1626                "Warning: error applying SO_REUSEADDR")); 
     1627        } 
     1628    } 
     1629 
     1630    /* Apply socket options, if specified */ 
     1631    if (listener->sockopt_params.cnt) 
     1632        status = pj_sock_setsockopt_params(sock, &listener->sockopt_params); 
     1633 
     1634    status = pj_sock_bind(sock, listener_addr, addr_len); 
     1635    if (status != PJ_SUCCESS) 
     1636        goto on_error; 
     1637 
     1638    /* Retrieve the bound address */ 
     1639    status = pj_sock_getsockname(sock, &listener->factory.local_addr,  
     1640                                 &addr_len); 
     1641    if (status != PJ_SUCCESS) 
     1642        goto on_error; 
     1643 
     1644    status = update_factory_addr(listener, a_name); 
     1645    if (status != PJ_SUCCESS) 
     1646        goto on_error; 
     1647 
     1648    /* Start listening to the address */ 
     1649    status = pj_sock_listen(sock, PJSIP_TCP_TRANSPORT_BACKLOG); 
     1650    if (status != PJ_SUCCESS) 
     1651        goto on_error; 
     1652 
     1653 
     1654    /* Create active socket */ 
     1655    pj_activesock_cfg_default(&asock_cfg); 
     1656    if (listener->async_cnt > MAX_ASYNC_CNT) 
     1657        asock_cfg.async_cnt = MAX_ASYNC_CNT; 
     1658    else 
     1659        asock_cfg.async_cnt = listener->async_cnt; 
     1660 
     1661    asock_cfg.grp_lock = listener->grp_lock; 
     1662    pj_bzero(&listener_cb, sizeof(listener_cb)); 
     1663    listener_cb.on_accept_complete = &on_accept_complete; 
     1664 
     1665    status = pj_activesock_create(listener->factory.pool, sock, 
     1666                                  pj_SOCK_STREAM(), &asock_cfg, 
     1667                                  pjsip_endpt_get_ioqueue(listener->endpt), 
     1668                                  &listener_cb, listener, 
     1669                                  &listener->asock); 
     1670 
     1671    /* Start pending accept() operations */ 
     1672    status = pj_activesock_start_accept(listener->asock, 
     1673                                        listener->factory.pool); 
     1674 
     1675    update_transport_info(listener); 
     1676 
     1677    return status; 
     1678 
     1679on_error: 
     1680    if (listener->asock == NULL && sock != PJ_INVALID_SOCKET) 
     1681        pj_sock_close(sock); 
     1682 
     1683    return status; 
     1684} 
     1685 
     1686 
     1687PJ_DEF(pj_status_t) pjsip_tcp_transport_restart(pjsip_tpfactory *factory, 
     1688                                                const pj_sockaddr *local, 
     1689                                                const pjsip_host_port *a_name) 
     1690{ 
     1691    pj_status_t status = PJ_SUCCESS; 
     1692    struct tcp_listener *listener = (struct tcp_listener *)factory; 
     1693 
     1694    lis_close(listener); 
     1695 
     1696    status = pjsip_tcp_transport_lis_start(factory, local, a_name); 
     1697    if (status != PJ_SUCCESS) {  
     1698        tcp_perror(listener->factory.obj_name, 
     1699                   "Unable to start listener after closing it", status); 
     1700 
     1701        return status; 
     1702    } 
     1703     
     1704    status = pjsip_tpmgr_register_tpfactory(listener->tpmgr, 
     1705                                            &listener->factory); 
     1706    if (status != PJ_SUCCESS) { 
     1707        tcp_perror(listener->factory.obj_name, 
     1708                   "Unable to register the transport listener", status); 
     1709    } else { 
     1710        listener->is_registered = PJ_TRUE;       
     1711    }     
     1712 
     1713    return status; 
     1714} 
     1715 
    16401716#endif  /* PJ_HAS_TCP */ 
    16411717 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c

    r5534 r5649  
    5858    pj_sockaddr              bound_addr; 
    5959    pj_ssl_cert_t           *cert; 
    60     pjsip_tls_setting        tls_setting; 
     60    pjsip_tls_setting        tls_setting;     
     61    unsigned                 async_cnt;     
    6162 
    6263    /* Group lock to be used by TLS transport and ioqueue key */ 
     
    283284 */ 
    284285 
     286 
     287static void set_ssock_param(pj_ssl_sock_param *ssock_param, 
     288    struct tls_listener *listener) 
     289{ 
     290    int af, sip_ssl_method; 
     291    pj_uint32_t sip_ssl_proto; 
     292 
     293    /* Build SSL socket param */ 
     294    af = pjsip_transport_type_get_af(listener->factory.type); 
     295    pj_ssl_sock_param_default(ssock_param); 
     296    ssock_param->sock_af = af; 
     297    ssock_param->cb.on_accept_complete = &on_accept_complete; 
     298    ssock_param->async_cnt = listener->async_cnt; 
     299    ssock_param->ioqueue = pjsip_endpt_get_ioqueue(listener->endpt); 
     300    ssock_param->timer_heap = pjsip_endpt_get_timer_heap(listener->endpt); 
     301    ssock_param->require_client_cert = listener->tls_setting.require_client_cert; 
     302    ssock_param->timeout = listener->tls_setting.timeout; 
     303    ssock_param->user_data = listener; 
     304    ssock_param->verify_peer = PJ_FALSE; /* avoid SSL socket closing the socket 
     305                                          * due to verification error */ 
     306    if (ssock_param->send_buffer_size < PJSIP_MAX_PKT_LEN) 
     307        ssock_param->send_buffer_size = PJSIP_MAX_PKT_LEN; 
     308    if (ssock_param->read_buffer_size < PJSIP_MAX_PKT_LEN) 
     309        ssock_param->read_buffer_size = PJSIP_MAX_PKT_LEN; 
     310    ssock_param->ciphers_num = listener->tls_setting.ciphers_num; 
     311    ssock_param->ciphers = listener->tls_setting.ciphers; 
     312    ssock_param->curves_num = listener->tls_setting.curves_num; 
     313    ssock_param->curves = listener->tls_setting.curves; 
     314    ssock_param->sigalgs = listener->tls_setting.sigalgs; 
     315    ssock_param->entropy_type = listener->tls_setting.entropy_type; 
     316    ssock_param->entropy_path = listener->tls_setting.entropy_path; 
     317    ssock_param->reuse_addr = listener->tls_setting.reuse_addr; 
     318    ssock_param->qos_type = listener->tls_setting.qos_type; 
     319    ssock_param->qos_ignore_error = listener->tls_setting.qos_ignore_error; 
     320    pj_memcpy(&ssock_param->qos_params, &listener->tls_setting.qos_params, 
     321              sizeof(ssock_param->qos_params)); 
     322 
     323    ssock_param->sockopt_ignore_error = 
     324                                    listener->tls_setting.sockopt_ignore_error; 
     325    /* Copy the sockopt */ 
     326    pj_memcpy(&ssock_param->sockopt_params, 
     327              &listener->tls_setting.sockopt_params, 
     328              sizeof(listener->tls_setting.sockopt_params)); 
     329 
     330    sip_ssl_method = listener->tls_setting.method; 
     331    sip_ssl_proto = listener->tls_setting.proto; 
     332    ssock_param->proto = ssl_get_proto(sip_ssl_method, sip_ssl_proto); 
     333} 
     334 
     335static void update_bound_addr(struct tls_listener *listener, 
     336                              const pj_sockaddr *local) 
     337{ 
     338    pj_sockaddr *listener_addr = &listener->factory.local_addr; 
     339    int af = pjsip_transport_type_get_af(listener->factory.type); 
     340 
     341    /* Bind address may be different than factory.local_addr because 
     342     * factory.local_addr will be resolved. 
     343     */ 
     344    if (local) { 
     345        pj_sockaddr_cp(&listener->bound_addr, local); 
     346    } else { 
     347        pj_sockaddr_init(af, &listener->bound_addr, NULL, 0); 
     348    } 
     349    pj_sockaddr_cp(listener_addr, &listener->bound_addr);     
     350} 
     351 
     352static pj_status_t update_factory_addr(struct tls_listener *listener, 
     353                                       const pjsip_host_port *addr_name) 
     354{ 
     355    pj_status_t status = PJ_SUCCESS; 
     356    pj_sockaddr *listener_addr = &listener->factory.local_addr; 
     357 
     358    if (addr_name && addr_name->host.slen) { 
     359        pj_sockaddr tmp; 
     360        int af = pjsip_transport_type_get_af(listener->factory.type); 
     361 
     362        status = pj_sockaddr_init(af, &tmp, &addr_name->host, 
     363                                  (pj_uint16_t)addr_name->port); 
     364        if (status != PJ_SUCCESS || !pj_sockaddr_has_addr(&tmp) || 
     365            (af == pj_AF_INET() && tmp.ipv4.sin_addr.s_addr == PJ_INADDR_NONE)) 
     366        { 
     367            /* Invalid address */ 
     368            return PJ_EINVAL; 
     369        } 
     370 
     371        /* Copy the address */ 
     372        listener->factory.addr_name = *addr_name; 
     373        pj_strdup(listener->factory.pool, &listener->factory.addr_name.host, 
     374                  &addr_name->host); 
     375        listener->factory.addr_name.port = addr_name->port; 
     376 
     377    } 
     378    else { 
     379        /* No published address is given, use the bound address */ 
     380 
     381        /* If the address returns 0.0.0.0, use the default 
     382        * interface address as the transport's address. 
     383        */ 
     384        if (!pj_sockaddr_has_addr(listener_addr)) { 
     385            pj_sockaddr hostip; 
     386 
     387            status = pj_gethostip(listener->bound_addr.addr.sa_family, 
     388                                  &hostip); 
     389            if (status != PJ_SUCCESS) 
     390                return status; 
     391 
     392            pj_sockaddr_copy_addr(listener_addr, &hostip); 
     393        } 
     394 
     395        /* Save the address name */ 
     396        sockaddr_to_host_port(listener->factory.pool, 
     397                              &listener->factory.addr_name, listener_addr); 
     398    } 
     399 
     400    /* If port is zero, get the bound port */ 
     401    if (listener->factory.addr_name.port == 0) { 
     402        listener->factory.addr_name.port = pj_sockaddr_get_port(listener_addr); 
     403    } 
     404 
     405    pj_ansi_snprintf(listener->factory.obj_name, 
     406                     sizeof(listener->factory.obj_name), 
     407                     "tlstp:%d", listener->factory.addr_name.port); 
     408    return status; 
     409} 
     410 
     411static void update_transport_info(struct tls_listener *listener) 
     412{ 
     413    enum { INFO_LEN = 100 }; 
     414    char local_addr[PJ_INET6_ADDRSTRLEN + 10]; 
     415    pj_sockaddr *listener_addr = &listener->factory.local_addr; 
     416 
     417    if (listener->factory.info == NULL) { 
     418        listener->factory.info = (char*)pj_pool_alloc(listener->factory.pool, 
     419                                                      INFO_LEN); 
     420    } 
     421    pj_sockaddr_print(listener_addr, local_addr, sizeof(local_addr), 3); 
     422    pj_ansi_snprintf( 
     423            listener->factory.info, INFO_LEN, "tls %s [published as %.*s:%d]", 
     424            local_addr, 
     425            (int)listener->factory.addr_name.host.slen, 
     426            listener->factory.addr_name.host.ptr, 
     427            listener->factory.addr_name.port); 
     428 
     429    if (listener->ssock) { 
     430        PJ_LOG(4, (listener->factory.obj_name, 
     431               "SIP TLS listener is ready for incoming connections " 
     432               "at %.*s:%d", 
     433               (int)listener->factory.addr_name.host.slen, 
     434               listener->factory.addr_name.host.ptr, 
     435               listener->factory.addr_name.port)); 
     436    } else { 
     437        PJ_LOG(4, (listener->factory.obj_name, "SIP TLS is ready " 
     438               "(client only)")); 
     439    } 
     440} 
     441 
     442 
    285443/* 
    286444 * This is the public API to create, initialize, register, and start the 
    287445 * TLS listener. 
    288446 */ 
    289 PJ_DEF(pj_status_t) pjsip_tls_transport_start (pjsip_endpoint *endpt, 
    290                                                const pjsip_tls_setting *opt, 
    291                                                const pj_sockaddr_in *local_in, 
    292                                                const pjsip_host_port *a_name, 
    293                                                unsigned async_cnt, 
    294                                                pjsip_tpfactory **p_factory) 
     447PJ_DEF(pj_status_t) pjsip_tls_transport_start(pjsip_endpoint *endpt, 
     448    const pjsip_tls_setting *opt, 
     449    const pj_sockaddr_in *local_in, 
     450    const pjsip_host_port *a_name, 
     451    unsigned async_cnt, 
     452    pjsip_tpfactory **p_factory) 
    295453{ 
    296454    pj_sockaddr local; 
     
    299457        pj_sockaddr_cp(&local, local_in); 
    300458 
    301     return pjsip_tls_transport_start2(endpt, opt, (local_in? &local : NULL), 
    302                                       a_name, async_cnt, p_factory); 
    303 } 
     459    return pjsip_tls_transport_start2(endpt, opt, (local_in ? &local : NULL), 
     460                                      a_name, async_cnt, p_factory); 
     461} 
     462 
     463 
     464PJ_DEF(pj_status_t) pjsip_tls_transport_lis_start(pjsip_tpfactory *factory, 
     465                                                const pj_sockaddr *local, 
     466                                                const pjsip_host_port *a_name) 
     467{ 
     468    pj_status_t status = PJ_SUCCESS; 
     469    pj_ssl_sock_param ssock_param, newsock_param; 
     470    struct tls_listener *listener = (struct tls_listener *)factory; 
     471    pj_sockaddr *listener_addr = &listener->factory.local_addr; 
     472 
     473    if (listener->ssock) 
     474        return PJ_SUCCESS; 
     475 
     476    set_ssock_param(&ssock_param, listener); 
     477    update_bound_addr(listener, local); 
     478    ssock_param.grp_lock = listener->grp_lock; 
     479 
     480    /* Create SSL socket */ 
     481    status = pj_ssl_sock_create(listener->factory.pool, &ssock_param,  
     482                                &listener->ssock); 
     483    if (status != PJ_SUCCESS) 
     484        return status; 
     485 
     486    if (listener->cert) { 
     487        status = pj_ssl_sock_set_certificate(listener->ssock,  
     488                                       listener->factory.pool, listener->cert); 
     489        if (status != PJ_SUCCESS) 
     490            return status; 
     491    } 
     492 
     493    /* Start accepting incoming connections. Note that some TLS/SSL 
     494     * backends may not support for SSL socket server. 
     495     */     
     496    pj_memcpy(&newsock_param, &ssock_param, sizeof(newsock_param)); 
     497    newsock_param.async_cnt = 1; 
     498    newsock_param.cb.on_data_read = &on_data_read; 
     499    newsock_param.cb.on_data_sent = &on_data_sent; 
     500    status = pj_ssl_sock_start_accept2(listener->ssock, listener->factory.pool, 
     501                            (pj_sockaddr_t*)listener_addr, 
     502                            pj_sockaddr_get_len((pj_sockaddr_t*)listener_addr), 
     503                            &newsock_param); 
     504 
     505    if (status == PJ_SUCCESS || status == PJ_EPENDING) { 
     506        pj_ssl_sock_info info;   
     507 
     508        /* Retrieve the bound address */ 
     509        status = pj_ssl_sock_get_info(listener->ssock, &info); 
     510        if (status == PJ_SUCCESS) 
     511            pj_sockaddr_cp(listener_addr, (pj_sockaddr_t*)&info.local_addr); 
     512 
     513    } 
     514    status = update_factory_addr(listener, a_name); 
     515    if (status != PJ_SUCCESS) 
     516        return status; 
     517 
     518    update_transport_info(listener); 
     519 
     520    return status;     
     521} 
     522 
    304523 
    305524PJ_DEF(pj_status_t) pjsip_tls_transport_start2( pjsip_endpoint *endpt, 
     
    309528                                                unsigned async_cnt, 
    310529                                                pjsip_tpfactory **p_factory) 
    311 { 
    312     enum { INFO_LEN = 100 }; 
    313     char local_addr[PJ_INET6_ADDRSTRLEN+10]; 
     530{         
    314531    pj_pool_t *pool; 
    315     pj_bool_t is_ipv6; 
    316     int af, sip_ssl_method; 
    317     pj_uint32_t sip_ssl_proto; 
    318     struct tls_listener *listener; 
    319     pj_ssl_sock_param ssock_param, newsock_param; 
    320     pj_sockaddr *listener_addr; 
    321     pj_bool_t has_listener; 
     532    pj_bool_t is_ipv6;     
     533    struct tls_listener *listener;     
    322534    pj_status_t status; 
    323535 
     
    325537    PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL); 
    326538 
    327     is_ipv6 = (local && local->addr.sa_family == pj_AF_INET6()); 
    328     af = is_ipv6 ? pj_AF_INET6() : pj_AF_INET(); 
    329  
    330     /* Verify that address given in a_name (if any) is valid */ 
    331     if (a_name && a_name->host.slen) { 
    332         pj_sockaddr tmp; 
    333  
    334         status = pj_sockaddr_init(af, &tmp, &a_name->host, 
    335                                   (pj_uint16_t)a_name->port); 
    336         if (status != PJ_SUCCESS || !pj_sockaddr_has_addr(&tmp) || 
    337             (!is_ipv6 && tmp.ipv4.sin_addr.s_addr == PJ_INADDR_NONE)) 
    338         { 
    339             /* Invalid address */ 
    340             return PJ_EINVAL; 
    341         } 
    342     } 
     539    is_ipv6 = (local && local->addr.sa_family == pj_AF_INET6());     
    343540 
    344541    pool = pjsip_endpt_create_pool(endpt, "tlstp", POOL_LIS_INIT,  
     
    355552                pjsip_transport_get_type_name(listener->factory.type); 
    356553    listener->factory.flag =  
    357         pjsip_transport_get_flag_from_type(listener->factory.type); 
     554                pjsip_transport_get_flag_from_type(listener->factory.type); 
     555    listener->endpt = endpt; 
    358556 
    359557    pj_ansi_strcpy(listener->factory.obj_name, "tlstp"); 
     
    374572        async_cnt = MAX_ASYNC_CNT; 
    375573 
    376     /* Build SSL socket param */ 
    377     pj_ssl_sock_param_default(&ssock_param); 
    378     ssock_param.sock_af = af; 
    379     ssock_param.cb.on_accept_complete = &on_accept_complete; 
    380     ssock_param.async_cnt = async_cnt; 
    381     ssock_param.ioqueue = pjsip_endpt_get_ioqueue(endpt); 
    382     ssock_param.timer_heap = pjsip_endpt_get_timer_heap(endpt);     
    383     ssock_param.require_client_cert = listener->tls_setting.require_client_cert; 
    384     ssock_param.timeout = listener->tls_setting.timeout; 
    385     ssock_param.user_data = listener; 
    386     ssock_param.verify_peer = PJ_FALSE; /* avoid SSL socket closing the socket 
    387                                          * due to verification error */ 
    388     if (ssock_param.send_buffer_size < PJSIP_MAX_PKT_LEN) 
    389         ssock_param.send_buffer_size = PJSIP_MAX_PKT_LEN; 
    390     if (ssock_param.read_buffer_size < PJSIP_MAX_PKT_LEN) 
    391         ssock_param.read_buffer_size = PJSIP_MAX_PKT_LEN; 
    392     ssock_param.ciphers_num = listener->tls_setting.ciphers_num; 
    393     ssock_param.ciphers = listener->tls_setting.ciphers; 
    394     ssock_param.curves_num = listener->tls_setting.curves_num; 
    395     ssock_param.curves = listener->tls_setting.curves; 
    396     ssock_param.sigalgs = listener->tls_setting.sigalgs; 
    397     ssock_param.entropy_type = listener->tls_setting.entropy_type; 
    398     ssock_param.entropy_path = listener->tls_setting.entropy_path; 
    399     ssock_param.reuse_addr = listener->tls_setting.reuse_addr; 
    400     ssock_param.qos_type = listener->tls_setting.qos_type; 
    401     ssock_param.qos_ignore_error = listener->tls_setting.qos_ignore_error; 
    402     pj_memcpy(&ssock_param.qos_params, &listener->tls_setting.qos_params, 
    403               sizeof(ssock_param.qos_params)); 
    404  
    405     ssock_param.sockopt_ignore_error =  
    406                                      listener->tls_setting.sockopt_ignore_error; 
    407     /* Copy the sockopt */ 
    408     pj_memcpy(&ssock_param.sockopt_params,  
    409               &listener->tls_setting.sockopt_params, 
    410               sizeof(listener->tls_setting.sockopt_params)); 
    411  
    412     has_listener = PJ_FALSE; 
    413  
    414     sip_ssl_method = listener->tls_setting.method; 
    415     sip_ssl_proto = listener->tls_setting.proto; 
    416     ssock_param.proto = ssl_get_proto(sip_ssl_method, sip_ssl_proto);  
     574    listener->async_cnt = async_cnt;     
    417575 
    418576    /* Create group lock */ 
    419577    status = pj_grp_lock_create(pool, NULL, &listener->grp_lock); 
    420578    if (status != PJ_SUCCESS) 
    421         return status; 
     579        goto on_error; 
    422580 
    423581    /* Setup group lock handler */ 
     
    425583    pj_grp_lock_add_handler(listener->grp_lock, pool, listener, 
    426584                            &lis_on_destroy); 
    427  
    428 #if !(defined(PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER) && \ 
    429       PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER != 0) 
    430  
    431     ssock_param.grp_lock = listener->grp_lock; 
    432  
    433     /* Create SSL socket */ 
    434     status = pj_ssl_sock_create(pool, &ssock_param, &listener->ssock); 
    435     if (status != PJ_SUCCESS) 
    436         goto on_error; 
    437  
    438 #endif 
    439  
    440     /* Bind address may be different than factory.local_addr because 
    441      * factory.local_addr will be resolved below. 
    442      */ 
    443     listener_addr = &listener->factory.local_addr; 
    444     if (local) { 
    445         pj_sockaddr_cp((pj_sockaddr_t*)listener_addr,  
    446                        (const pj_sockaddr_t*)local); 
    447         pj_sockaddr_cp(&listener->bound_addr, local); 
    448     } else { 
    449         pj_sockaddr_init(af, listener_addr, NULL, 0); 
    450         pj_sockaddr_init(af, &listener->bound_addr, NULL, 0); 
    451     } 
    452585 
    453586    /* Check if certificate/CA list for SSL socket is set */ 
     
    465598        if (status != PJ_SUCCESS) 
    466599            goto on_error; 
    467      } 
    468  
    469 #if !(defined(PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER) && \ 
    470       PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER != 0) 
    471  
    472      if (listener->cert) { 
    473         status = pj_ssl_sock_set_certificate(listener->ssock, pool,  
    474                                              listener->cert); 
    475         if (status != PJ_SUCCESS) 
    476             goto on_error; 
    477     } 
    478  
    479     /* Start accepting incoming connections. Note that some TLS/SSL backends 
    480      * may not support for SSL socket server. 
    481      */ 
    482     has_listener = PJ_FALSE; 
    483  
    484     pj_memcpy(&newsock_param, &ssock_param, sizeof(newsock_param)); 
    485     newsock_param.async_cnt = 1; 
    486     newsock_param.cb.on_data_read = &on_data_read; 
    487     newsock_param.cb.on_data_sent = &on_data_sent; 
    488     status = pj_ssl_sock_start_accept2(listener->ssock, pool,  
    489                           (pj_sockaddr_t*)listener_addr,  
    490                           pj_sockaddr_get_len((pj_sockaddr_t*)listener_addr), 
    491                           &newsock_param); 
    492     if (status == PJ_SUCCESS || status == PJ_EPENDING) { 
    493         pj_ssl_sock_info info; 
    494         has_listener = PJ_TRUE; 
    495  
    496         /* Retrieve the bound address */ 
    497         status = pj_ssl_sock_get_info(listener->ssock, &info); 
    498         if (status == PJ_SUCCESS) 
    499             pj_sockaddr_cp(listener_addr, (pj_sockaddr_t*)&info.local_addr); 
    500     } else if (status != PJ_ENOTSUP) { 
    501         goto on_error; 
    502     } 
    503  
    504 #endif 
    505  
    506     /* If published host/IP is specified, then use that address as the 
    507      * listener advertised address. 
    508      */ 
    509     if (a_name && a_name->host.slen) { 
    510         /* Copy the address */ 
    511         listener->factory.addr_name = *a_name; 
    512         pj_strdup(listener->factory.pool, &listener->factory.addr_name.host,  
    513                   &a_name->host); 
    514         listener->factory.addr_name.port = a_name->port; 
    515  
    516     } else { 
    517         /* No published address is given, use the bound address */ 
    518  
    519         /* If the address returns 0.0.0.0, use the default 
    520          * interface address as the transport's address. 
    521          */ 
    522         if (!pj_sockaddr_has_addr(listener_addr)) { 
    523             pj_sockaddr hostip; 
    524  
    525             status = pj_gethostip(af, &hostip); 
    526             if (status != PJ_SUCCESS) 
    527                 goto on_error; 
    528  
    529             pj_sockaddr_copy_addr(listener_addr, &hostip); 
    530         } 
    531  
    532         /* Save the address name */ 
    533         sockaddr_to_host_port(listener->factory.pool,  
    534                               &listener->factory.addr_name, listener_addr); 
    535     } 
    536  
    537     /* If port is zero, get the bound port */ 
    538     if (listener->factory.addr_name.port == 0) { 
    539         listener->factory.addr_name.port = pj_sockaddr_get_port(listener_addr); 
    540     } 
    541  
    542     pj_ansi_snprintf(listener->factory.obj_name,  
    543                      sizeof(listener->factory.obj_name), 
    544                      "tlstp:%d",  listener->factory.addr_name.port); 
     600    } 
    545601 
    546602    /* Register to transport manager */ 
     
    549605    listener->factory.create_transport2 = lis_create_transport; 
    550606    listener->factory.destroy = lis_destroy; 
     607 
     608#if !(defined(PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER) && \ 
     609    PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER != 0) 
     610    /* Start listener. */ 
     611    status = pjsip_tls_transport_lis_start(&listener->factory, local, a_name); 
     612    if (status != PJ_SUCCESS) 
     613        goto on_error; 
     614#else 
     615    update_bound_addr(listener, local); 
     616    /* If published host/IP is specified, then use that address as the 
     617     * listener advertised address. 
     618     */ 
     619    status = update_factory_addr(listener, a_name); 
     620    if (status != PJ_SUCCESS) 
     621        goto on_error; 
     622 
     623    /* Set transport info. */ 
     624    update_transport_info(listener); 
     625#endif 
     626 
    551627    listener->is_registered = PJ_TRUE; 
    552628    status = pjsip_tpmgr_register_tpfactory(listener->tpmgr, 
     
    557633    } 
    558634 
    559     /* Set transport info. */ 
    560     if (listener->factory.info == NULL) { 
    561         listener->factory.info = (char*) pj_pool_alloc(listener->factory.pool, 
    562                                                        INFO_LEN); 
    563     } 
    564     pj_sockaddr_print(listener_addr, local_addr, sizeof(local_addr), 3); 
    565     pj_ansi_snprintf(  
    566         listener->factory.info, INFO_LEN, "tls %s [published as %.*s:%d]", 
    567         local_addr, 
    568         (int)listener->factory.addr_name.host.slen, 
    569         listener->factory.addr_name.host.ptr, 
    570         listener->factory.addr_name.port); 
    571  
    572     if (has_listener) { 
    573         PJ_LOG(4,(listener->factory.obj_name,  
    574                  "SIP TLS listener is ready for incoming connections " 
    575                  "at %.*s:%d", 
    576                  (int)listener->factory.addr_name.host.slen, 
    577                  listener->factory.addr_name.host.ptr, 
    578                  listener->factory.addr_name.port)); 
    579     } else { 
    580         PJ_LOG(4,(listener->factory.obj_name, "SIP TLS is ready " 
    581                   "(client only)")); 
    582     } 
    583  
    584635    /* Return the pointer to user */ 
    585636    if (p_factory) *p_factory = &listener->factory; 
     
    610661 
    611662 
    612 /* This callback is called by transport manager to destroy listener */ 
    613 static pj_status_t lis_destroy(pjsip_tpfactory *factory) 
    614 { 
    615     struct tls_listener *listener = (struct tls_listener *)factory; 
    616  
     663static void lis_close(struct tls_listener *listener) 
     664{ 
    617665    if (listener->is_registered) { 
    618666        pjsip_tpmgr_unregister_tpfactory(listener->tpmgr, &listener->factory); 
     
    624672        listener->ssock = NULL; 
    625673    } 
     674} 
     675 
     676 
     677/* This callback is called by transport manager to destroy listener */ 
     678static pj_status_t lis_destroy(pjsip_tpfactory *factory) 
     679{ 
     680    struct tls_listener *listener = (struct tls_listener *)factory; 
     681 
     682    lis_close(listener); 
    626683 
    627684    if (listener->grp_lock) { 
     
    635692 
    636693    return PJ_SUCCESS; 
     694} 
     695 
     696 
     697PJ_DEF(pj_status_t) pjsip_tls_transport_restart(pjsip_tpfactory *factory, 
     698                                                const pj_sockaddr *local, 
     699                                                const pjsip_host_port *a_name) 
     700{ 
     701    pj_status_t status = PJ_SUCCESS; 
     702    struct tls_listener *listener = (struct tls_listener *)factory; 
     703 
     704    lis_close(listener); 
     705 
     706    status = pjsip_tls_transport_lis_start(factory, local, a_name); 
     707    if (status != PJ_SUCCESS) {  
     708        tls_perror(listener->factory.obj_name,  
     709                   "Unable to start listener after closing it", status); 
     710 
     711        return status; 
     712    } 
     713     
     714    status = pjsip_tpmgr_register_tpfactory(listener->tpmgr, 
     715                                            &listener->factory); 
     716    if (status != PJ_SUCCESS) { 
     717        tls_perror(listener->factory.obj_name, 
     718                    "Unable to register the transport listener", status); 
     719 
     720        listener->is_registered = PJ_FALSE;      
     721    } else { 
     722        listener->is_registered = PJ_TRUE;       
     723    }     
     724 
     725    return status; 
    637726} 
    638727 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c

    r5636 r5649  
    10811081 */ 
    10821082PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport, 
    1083                                                 unsigned option, 
     1083                                                unsigned option, 
    10841084                                                pj_sock_t sock, 
    10851085                                                const pj_sockaddr_in *local, 
    10861086                                                const pjsip_host_port *a_name) 
     1087{ 
     1088    return pjsip_udp_transport_restart2(transport, option, sock,  
     1089                                        (pj_sockaddr*)local, a_name); 
     1090} 
     1091 
     1092 
     1093PJ_DEF(pj_status_t) pjsip_udp_transport_restart2(pjsip_transport *transport, 
     1094                                                 unsigned option, 
     1095                                                 pj_sock_t sock, 
     1096                                                 const pj_sockaddr *local, 
     1097                                                 const pjsip_host_port *a_name) 
    10871098{ 
    10881099    struct udp_transport *tp; 
     
    10991110     */ 
    11001111    tp->is_paused = PJ_TRUE; 
    1101  
     1112     
    11021113    if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) { 
    11031114        char addr_buf[PJ_INET6_ADDRSTRLEN]; 
     
    11221133        /* Create the socket if it's not specified */ 
    11231134        if (sock == PJ_INVALID_SOCKET) { 
    1124             status = create_socket(pj_AF_INET(), local,  
    1125                                    sizeof(pj_sockaddr_in), &sock); 
     1135            status = create_socket(local->addr.sa_family, local,  
     1136                                   pj_sockaddr_get_len(local), &sock); 
    11261137            if (status != PJ_SUCCESS) 
    11271138                return status; 
     
    11901201    return PJ_SUCCESS; 
    11911202} 
    1192  
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c

    r5636 r5649  
    402402        acc->tp_type = pjsua_var.tpdata[acc_cfg->transport_id].type; 
    403403 
     404    acc->ip_change_op = PJSUA_IP_CHANGE_OP_NULL; 
     405 
    404406    return PJ_SUCCESS; 
    405407} 
     
    688690    acc->via_tp = NULL; 
    689691    acc->next_rtp_port = 0; 
     692    acc->ip_change_op = PJSUA_IP_CHANGE_OP_NULL;     
    690693 
    691694    /* Remove from array */ 
     
    14171420        } 
    14181421    } 
     1422 
     1423    /* IP Change config */ 
     1424    acc->cfg.ip_change_cfg.shutdown_tp = cfg->ip_change_cfg.shutdown_tp; 
     1425    acc->cfg.ip_change_cfg.hangup_calls = cfg->ip_change_cfg.hangup_calls;     
     1426    acc->cfg.ip_change_cfg.reinvite_flags = cfg->ip_change_cfg.reinvite_flags; 
    14191427 
    14201428on_return: 
     
    22002208 
    22012209/* 
     2210 * Timer callback to handle call on IP change process. 
     2211 */ 
     2212static void handle_call_on_ip_change_cb(void *user_data) 
     2213{ 
     2214    pjsua_acc *acc = (pjsua_acc*)user_data; 
     2215    pjsua_acc_handle_call_on_ip_change(acc); 
     2216} 
     2217 
     2218/* 
    22022219 * This callback is called by pjsip_regc when outgoing register 
    22032220 * request has completed. 
     
    22662283            PJ_LOG(3,(THIS_FILE, "%s: unregistration success", 
    22672284                      pjsua_var.acc[acc->index].cfg.id.ptr)); 
    2268         } else { 
     2285 
     2286        } else {             
    22692287            /* Check and update SIP outbound status first, since the result 
    22702288             * will determine if we should update re-registration 
     
    23062324            if (acc->cfg.mwi_enabled) 
    23072325                pjsua_start_mwi(acc->index, PJ_FALSE); 
    2308         } 
    2309  
     2326 
     2327        } 
    23102328    } else { 
    23112329        PJ_LOG(4, (THIS_FILE, "SIP registration updated status=%d", param->code)); 
     
    23492367        reg_info.renew = !param->is_unreg; 
    23502368        (*pjsua_var.ua_cfg.cb.on_reg_state2)(acc->index, &reg_info); 
     2369    } 
     2370 
     2371    if (acc->ip_change_op == PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT) { 
     2372        if (pjsua_var.ua_cfg.cb.on_ip_change_progress) { 
     2373            pjsua_ip_change_op_info ip_chg_info; 
     2374            pjsip_regc_info rinfo; 
     2375 
     2376            pj_bzero(&ip_chg_info, sizeof(ip_chg_info)); 
     2377            pjsip_regc_get_info(param->regc, &rinfo);        
     2378            ip_chg_info.acc_update_contact.acc_id = acc->index; 
     2379            ip_chg_info.acc_update_contact.code = param->code; 
     2380            ip_chg_info.acc_update_contact.is_register = !param->is_unreg; 
     2381            (*pjsua_var.ua_cfg.cb.on_ip_change_progress)(acc->ip_change_op,  
     2382                                                         param->status,  
     2383                                                         &ip_chg_info); 
     2384        } 
     2385 
     2386        if (PJSIP_IS_STATUS_IN_CLASS(param->code, 200)) { 
     2387            if (param->expiration < 1) { 
     2388                pj_status_t status; 
     2389                /* Send re-register. */ 
     2390                PJ_LOG(3, (THIS_FILE, "%.*s: send registration triggered by IP" 
     2391                           " change", pjsua_var.acc[acc->index].cfg.id.slen, 
     2392                           pjsua_var.acc[acc->index].cfg.id.ptr)); 
     2393 
     2394                status = pjsua_acc_set_registration(acc->index, PJ_TRUE); 
     2395                if ((status != PJ_SUCCESS) &&  
     2396                    pjsua_var.ua_cfg.cb.on_ip_change_progress)  
     2397                { 
     2398                    pjsua_ip_change_op_info ip_chg_info; 
     2399 
     2400                    pj_bzero(&ip_chg_info, sizeof(ip_chg_info)); 
     2401                    ip_chg_info.acc_update_contact.acc_id = acc->index; 
     2402                    ip_chg_info.acc_update_contact.is_register = PJ_TRUE; 
     2403                    (*pjsua_var.ua_cfg.cb.on_ip_change_progress)( 
     2404                                                            acc->ip_change_op,  
     2405                                                            status,  
     2406                                                            &ip_chg_info); 
     2407                } 
     2408            } else { 
     2409                /* Avoid deadlock issue when sending BYE or Re-INVITE.  */ 
     2410                pjsua_schedule_timer2(&handle_call_on_ip_change_cb,  
     2411                                      (void*)acc, 0); 
     2412            } 
     2413        }  
    23512414    } 
    23522415     
     
    26762739        //pjsip_regc_get_info(pjsua_var.acc[acc_id].regc, &reg_info); 
    26772740        //pjsua_var.acc[acc_id].auto_rereg.reg_tp = reg_info.transport; 
    2678          
     2741 
    26792742        if (pjsua_var.ua_cfg.cb.on_reg_started) { 
    26802743            (*pjsua_var.ua_cfg.cb.on_reg_started)(acc_id, renew); 
     
    37703833            pjsip_regc_release_transport(pjsua_var.acc[i].regc); 
    37713834 
    3772             /* Schedule reregistration for this account */ 
    3773             if (acc->cfg.reg_retry_interval) { 
     3835            if (pjsua_var.acc[i].ip_change_op ==  
     3836                                            PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP) 
     3837            { 
     3838                if (acc->cfg.allow_contact_rewrite) { 
     3839                    pjsua_acc_update_contact_on_ip_change(acc); 
     3840                } else { 
     3841                    pjsua_acc_handle_call_on_ip_change(acc); 
     3842                } 
     3843            } else if (acc->cfg.reg_retry_interval) { 
     3844                /* Schedule reregistration for this account */ 
    37743845                schedule_reregistration(acc); 
    37753846            } 
     
    37803851    pj_log_pop_indent(); 
    37813852} 
     3853 
     3854 
     3855/* 
     3856 * Internal function to update contact on ip change process. 
     3857 */ 
     3858pj_status_t pjsua_acc_update_contact_on_ip_change(pjsua_acc *acc) 
     3859{ 
     3860    pj_status_t status; 
     3861    pj_bool_t need_unreg = ((acc->cfg.contact_rewrite_method & 
     3862                             PJSUA_CONTACT_REWRITE_UNREGISTER) != 0); 
     3863 
     3864    acc->ip_change_op = PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT; 
     3865 
     3866    PJ_LOG(3, (THIS_FILE, "%.*s: send %sregistration triggered " 
     3867               "by IP change", acc->cfg.id.slen, 
     3868               acc->cfg.id.ptr, (need_unreg ? "un-" : ""))); 
     3869 
     3870    status = pjsua_acc_set_registration(acc->index, !need_unreg); 
     3871 
     3872    if ((status != PJ_SUCCESS) && (pjsua_var.ua_cfg.cb.on_ip_change_progress))  
     3873    { 
     3874        pjsua_ip_change_op_info info; 
     3875         
     3876        pj_bzero(&info, sizeof(info)); 
     3877        info.acc_update_contact.acc_id = acc->index; 
     3878        info.acc_update_contact.is_register = !need_unreg;       
     3879 
     3880        pjsua_var.ua_cfg.cb.on_ip_change_progress(acc->ip_change_op, 
     3881                                                  status, 
     3882                                                  &info); 
     3883    } 
     3884    return status; 
     3885} 
     3886 
     3887 
     3888/* 
     3889 * Internal function to handle call on ip change process. 
     3890 */ 
     3891pj_status_t pjsua_acc_handle_call_on_ip_change(pjsua_acc *acc) 
     3892{ 
     3893    pj_status_t status = PJ_SUCCESS; 
     3894    unsigned i = 0; 
     3895 
     3896    if (acc->cfg.ip_change_cfg.hangup_calls ||  
     3897        acc->cfg.ip_change_cfg.reinvite_flags) 
     3898    { 
     3899        for (i = 0; i < (int)pjsua_var.ua_cfg.max_calls; ++i) { 
     3900            pjsua_call_info call_info; 
     3901            pjsua_call_get_info(i, &call_info); 
     3902 
     3903            if (pjsua_var.calls[i].acc_id != acc->index) 
     3904            { 
     3905                continue; 
     3906            } 
     3907 
     3908            if (acc->cfg.ip_change_cfg.hangup_calls) { 
     3909                acc->ip_change_op = PJSUA_IP_CHANGE_OP_ACC_HANGUP_CALLS; 
     3910                PJ_LOG(3, (THIS_FILE, "call to %.*s: hangup " 
     3911                           "triggered by IP change", 
     3912                           call_info.remote_info.slen, 
     3913                           call_info.remote_info.ptr)); 
     3914 
     3915                status = pjsua_call_hangup(i, PJSIP_SC_GONE, NULL, NULL); 
     3916 
     3917                if (pjsua_var.ua_cfg.cb.on_ip_change_progress) { 
     3918                    pjsua_ip_change_op_info info; 
     3919 
     3920                    pj_bzero(&info, sizeof(info)); 
     3921                    info.acc_hangup_calls.acc_id = acc->index; 
     3922                    info.acc_hangup_calls.call_id = call_info.id; 
     3923 
     3924                    pjsua_var.ua_cfg.cb.on_ip_change_progress( 
     3925                                                             acc->ip_change_op, 
     3926                                                             status, 
     3927                                                             &info); 
     3928                } 
     3929            } else if ((acc->cfg.ip_change_cfg.reinvite_flags) && 
     3930                (call_info.state == PJSIP_INV_STATE_CONFIRMED)) 
     3931            { 
     3932                acc->ip_change_op = PJSUA_IP_CHANGE_OP_ACC_REINVITE_CALLS; 
     3933 
     3934                call_info.setting.flag |= 
     3935                                         acc->cfg.ip_change_cfg.reinvite_flags; 
     3936 
     3937                PJ_LOG(3, (THIS_FILE, "call to %.*s: send " 
     3938                           "re-INVITE with flags 0x%x triggered " 
     3939                           "by IP change", 
     3940                           call_info.remote_info.slen, 
     3941                           call_info.remote_info.ptr, 
     3942                           acc->cfg.ip_change_cfg.reinvite_flags)); 
     3943 
     3944                status = pjsua_call_reinvite(i, call_info.setting.flag, NULL); 
     3945 
     3946                if (pjsua_var.ua_cfg.cb.on_ip_change_progress) { 
     3947                    pjsua_ip_change_op_info info; 
     3948 
     3949                    pj_bzero(&info, sizeof(info)); 
     3950                    info.acc_reinvite_calls.acc_id = acc->index; 
     3951                    info.acc_reinvite_calls.call_id = call_info.id; 
     3952 
     3953                    pjsua_var.ua_cfg.cb.on_ip_change_progress( 
     3954                                                             acc->ip_change_op, 
     3955                                                             status, 
     3956                                                             &info); 
     3957                } 
     3958 
     3959            } 
     3960        } 
     3961    }     
     3962    acc->ip_change_op = PJSUA_IP_CHANGE_OP_NULL; 
     3963    return status; 
     3964} 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r5636 r5649  
    306306 
    307307    cfg->media_stun_use = PJSUA_STUN_RETRY_ON_FAILURE; 
     308    cfg->ip_change_cfg.shutdown_tp = PJ_TRUE; 
     309    cfg->ip_change_cfg.hangup_calls = PJ_FALSE; 
     310    cfg->ip_change_cfg.reinvite_flags = PJSUA_CALL_REINIT_MEDIA | 
     311                                        PJSUA_CALL_UPDATE_CONTACT | 
     312                                        PJSUA_CALL_UPDATE_VIA; 
    308313} 
    309314 
     
    23682373        pj_memcpy(&tcp_cfg.sockopt_params, &cfg->sockopt_params, 
    23692374                  sizeof(tcp_cfg.sockopt_params)); 
    2370          
     2375 
    23712376        /* Create the TCP transport */ 
    23722377        status = pjsip_tcp_transport_start3(pjsua_var.endpt, &tcp_cfg, &tcp); 
     
    24262431            a_name.host = cfg->public_addr; 
    24272432 
    2428         status = pjsip_tls_transport_start2(pjsua_var.endpt, 
    2429                                             &cfg->tls_setting, 
     2433        status = pjsip_tls_transport_start2(pjsua_var.endpt, &cfg->tls_setting, 
    24302434                                            &local_addr, &a_name, 1, &tls); 
    24312435        if (status != PJ_SUCCESS) { 
     
    27122716 
    27132717 
     2718PJ_DEF(pj_status_t) pjsua_transport_lis_start(pjsua_transport_id id, 
     2719                                             const pjsua_transport_config *cfg) 
     2720{ 
     2721    pj_status_t status = PJ_SUCCESS; 
     2722    pjsip_transport_type_e tp_type; 
     2723 
     2724    /* Make sure id is in range. */ 
     2725    PJ_ASSERT_RETURN(id>=0 && id<(int)PJ_ARRAY_SIZE(pjsua_var.tpdata),  
     2726                     PJ_EINVAL); 
     2727 
     2728    /* Make sure that transport exists */ 
     2729    PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL); 
     2730 
     2731    tp_type = pjsua_var.tpdata[id].type & ~PJSIP_TRANSPORT_IPV6; 
     2732  
     2733    if ((tp_type == PJSIP_TRANSPORT_TLS) || (tp_type == PJSIP_TRANSPORT_TCP)) { 
     2734        pj_sockaddr bind_addr; 
     2735        pjsip_host_port addr_name; 
     2736        pjsip_tpfactory *factory = pjsua_var.tpdata[id].data.factory; 
     2737         
     2738        int af = pjsip_transport_type_get_af(factory->type); 
     2739 
     2740        if (cfg->port) 
     2741            pj_sockaddr_set_port(&bind_addr, (pj_uint16_t)cfg->port); 
     2742 
     2743        if (cfg->bound_addr.slen) { 
     2744            status = pj_sockaddr_set_str_addr(af,  
     2745                                              &bind_addr, 
     2746                                              &cfg->bound_addr); 
     2747            if (status != PJ_SUCCESS) { 
     2748                pjsua_perror(THIS_FILE,  
     2749                             "Unable to resolve transport bound address",  
     2750                             status); 
     2751                return status; 
     2752            } 
     2753        } 
     2754 
     2755        /* Set published name */ 
     2756        if (cfg->public_addr.slen) 
     2757            addr_name.host = cfg->public_addr; 
     2758 
     2759        if (tp_type == PJSIP_TRANSPORT_TCP) { 
     2760            status = pjsip_tcp_transport_lis_start(factory, &bind_addr, 
     2761                                                   &addr_name); 
     2762        } 
     2763#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0 
     2764        else { 
     2765            status = pjsip_tls_transport_lis_start(factory, &bind_addr, 
     2766                                                   &addr_name);  
     2767        } 
     2768#endif   
     2769    } else if (tp_type == PJSIP_TRANSPORT_UDP) { 
     2770        status = PJ_SUCCESS; 
     2771    } else { 
     2772        status = PJ_EINVAL; 
     2773    } 
     2774    return status; 
     2775} 
     2776 
     2777 
    27142778/* 
    27152779 * Add additional headers etc in msg_data specified by application 
     
    28632927        sel->u.listener = tpdata->data.factory; 
    28642928    } 
     2929} 
     2930 
     2931 
     2932PJ_DEF(void) pjsua_ip_change_param_default(pjsua_ip_change_param *param) 
     2933{ 
     2934    pj_bzero(param, sizeof(*param)); 
     2935    param->restart_listener = PJ_TRUE; 
     2936    param->restart_lis_delay = PJSUA_TRANSPORT_RESTART_DELAY_TIME; 
    28652937} 
    28662938 
     
    32723344} 
    32733345 
     3346 
     3347/* Forward declaration. */ 
     3348static void restart_listener_cb(void *user_data); 
     3349 
     3350 
     3351static pj_status_t handle_ip_change_on_acc() 
     3352{ 
     3353    int i = 0; 
     3354    pj_status_t status = PJ_SUCCESS; 
     3355    pj_bool_t acc_done[PJSUA_MAX_ACC]; 
     3356 
     3357    /* Reset ip_change_active flag. */ 
     3358    for (; i < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { 
     3359        pjsua_var.acc[i].ip_change_op = PJSUA_IP_CHANGE_OP_NULL; 
     3360        acc_done[i] = PJ_FALSE; 
     3361    }     
     3362     
     3363    for (i = 0; i < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { 
     3364        pj_bool_t shutdown_transport = PJ_FALSE; 
     3365        pjsip_regc_info regc_info; 
     3366        char acc_id[PJSUA_MAX_ACC * 4]; 
     3367        pjsua_acc *acc = &pjsua_var.acc[i]; 
     3368        pjsip_transport *transport = NULL; 
     3369        pjsua_acc_id shut_acc_ids[PJSUA_MAX_ACC]; 
     3370        unsigned shut_acc_cnt = 0; 
     3371 
     3372        if (!acc->valid || (acc_done[i])) 
     3373            continue; 
     3374 
     3375        if (acc->regc) {                     
     3376            pjsip_regc_get_info(acc->regc, &regc_info); 
     3377            if ((regc_info.transport) && 
     3378                ((regc_info.transport->flag & PJSIP_TRANSPORT_DATAGRAM) == 0)) 
     3379            { 
     3380                transport = regc_info.transport; 
     3381                shutdown_transport = acc->cfg.ip_change_cfg.shutdown_tp; 
     3382                shut_acc_ids[shut_acc_cnt++] = acc->index; 
     3383            }    
     3384        } else if (acc->reg_last_code != PJSIP_SC_BAD_GATEWAY && 
     3385                   acc->reg_last_code != PJSIP_SC_REQUEST_TIMEOUT && 
     3386                   acc->reg_last_code != PJSIP_SC_INTERNAL_SERVER_ERROR && 
     3387                   acc->reg_last_code != PJSIP_SC_BAD_GATEWAY && 
     3388                   acc->reg_last_code != PJSIP_SC_SERVICE_UNAVAILABLE && 
     3389                   acc->reg_last_code != PJSIP_SC_SERVER_TIMEOUT && 
     3390                   acc->reg_last_code != PJSIP_SC_TEMPORARILY_UNAVAILABLE)  
     3391        { 
     3392            continue; 
     3393        }  
     3394        pj_ansi_snprintf(acc_id, sizeof(acc_id), "#%d", i);      
     3395 
     3396        if (transport) { 
     3397            unsigned j = i + 1; 
     3398 
     3399            /* Find other account that uses the same transport. */ 
     3400            for (; j < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++j) { 
     3401                pjsip_regc_info tmp_regc_info; 
     3402                pjsua_acc *next_acc = &pjsua_var.acc[j]; 
     3403 
     3404                if (!next_acc->valid || !next_acc->regc || 
     3405                    (next_acc->ip_change_op > PJSUA_IP_CHANGE_OP_NULL))  
     3406                { 
     3407                    continue; 
     3408                } 
     3409 
     3410                pjsip_regc_get_info(next_acc->regc, &tmp_regc_info); 
     3411                if (transport == tmp_regc_info.transport) { 
     3412                    char tmp_buf[PJSUA_MAX_ACC * 4]; 
     3413 
     3414                    pj_ansi_strncpy(tmp_buf, acc_id, sizeof(acc_id)); 
     3415                    pj_ansi_snprintf(acc_id, sizeof(acc_id), "%s #%d",  
     3416                                     tmp_buf, j); 
     3417                    shut_acc_ids[shut_acc_cnt++] = j; 
     3418                    if (!shutdown_transport) { 
     3419                        shutdown_transport = 
     3420                                    next_acc->cfg.ip_change_cfg.shutdown_tp;                         
     3421                    } 
     3422                } 
     3423            } 
     3424        } 
     3425 
     3426        if (shutdown_transport) { 
     3427            unsigned j; 
     3428            /* Shutdown the transport. */            
     3429            PJ_LOG(3, (THIS_FILE, "Shutdown transport %s used by account %s " 
     3430                       "triggered by IP change", transport->obj_name, acc_id)); 
     3431 
     3432            for (j = 0; j < shut_acc_cnt; ++j) { 
     3433                pjsua_acc *tmp_acc = &pjsua_var.acc[shut_acc_ids[j]]; 
     3434                tmp_acc->ip_change_op = PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP; 
     3435                acc_done[shut_acc_ids[j]] = PJ_TRUE; 
     3436            } 
     3437 
     3438            status = pjsip_transport_shutdown2(transport, PJ_TRUE); 
     3439 
     3440            /* Report progress to each acc which uses the same transport. */ 
     3441            for (j = 0; j < shut_acc_cnt; ++j) { 
     3442                pjsua_acc *tmp_acc = &pjsua_var.acc[shut_acc_ids[j]]; 
     3443 
     3444                if (pjsua_var.ua_cfg.cb.on_ip_change_progress) { 
     3445                    pjsua_ip_change_op_info info; 
     3446 
     3447                    pj_bzero(&info, sizeof(info)); 
     3448                    info.acc_shutdown_tp.acc_id = tmp_acc->index; 
     3449 
     3450                    pjsua_var.ua_cfg.cb.on_ip_change_progress( 
     3451                                                         tmp_acc->ip_change_op, 
     3452                                                         status, 
     3453                                                         &info); 
     3454                } 
     3455 
     3456            } 
     3457        } else { 
     3458            acc_done[i] = PJ_TRUE; 
     3459            if (acc->cfg.allow_contact_rewrite) { 
     3460                status = pjsua_acc_update_contact_on_ip_change(acc); 
     3461            } else { 
     3462                status = pjsua_acc_handle_call_on_ip_change(acc); 
     3463            } 
     3464        } 
     3465    } 
     3466    return status; 
     3467} 
     3468 
     3469 
     3470static pj_status_t restart_listener(pjsua_transport_id id,  
     3471                                    unsigned restart_lis_delay) 
     3472{ 
     3473    pj_sockaddr bind_addr; 
     3474    pjsua_transport_info tp_info; 
     3475    pj_status_t status;     
     3476 
     3477    pjsua_transport_get_info(id, &tp_info);         
     3478    pj_sockaddr_init(pjsip_transport_type_get_af(tp_info.type), 
     3479                     &bind_addr, 
     3480                     NULL, 
     3481                     pj_sockaddr_get_port(&tp_info.local_addr)); 
     3482     
     3483    switch (tp_info.type) { 
     3484    case PJSIP_TRANSPORT_UDP: 
     3485    case PJSIP_TRANSPORT_UDP6: 
     3486        status = pjsip_udp_transport_restart2( 
     3487                                       pjsua_var.tpdata[id].data.tp, 
     3488                                       PJSIP_UDP_TRANSPORT_DESTROY_SOCKET, 
     3489                                       PJ_INVALID_SOCKET, 
     3490                                       &bind_addr, 
     3491                                       NULL); 
     3492        break; 
     3493 
     3494#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0 
     3495    case PJSIP_TRANSPORT_TLS: 
     3496    case PJSIP_TRANSPORT_TLS6: 
     3497        status = pjsip_tls_transport_restart( 
     3498                                        pjsua_var.tpdata[id].data.factory, 
     3499                                        &bind_addr, 
     3500                                        NULL); 
     3501        break; 
     3502#endif 
     3503    case PJSIP_TRANSPORT_TCP: 
     3504    case PJSIP_TRANSPORT_TCP6: 
     3505        status = pjsip_tcp_transport_restart( 
     3506                                        pjsua_var.tpdata[id].data.factory, 
     3507                                        &bind_addr, 
     3508                                        NULL); 
     3509        break; 
     3510 
     3511    default: 
     3512        status = PJ_EINVAL; 
     3513    } 
     3514    if (status != PJ_SUCCESS && (restart_lis_delay > 0)) { 
     3515        /* Try restarting again, with delay. */ 
     3516        pjsua_schedule_timer2(&restart_listener_cb,  
     3517                              (void*)(pj_size_t)id,  
     3518                              restart_lis_delay); 
     3519    } else { 
     3520        int i = 0; 
     3521        pj_bool_t all_done = PJ_TRUE; 
     3522 
     3523        pjsua_var.tpdata[id].is_restarting = PJ_FALSE;   
     3524        if (pjsua_var.ua_cfg.cb.on_ip_change_progress) { 
     3525            pjsua_ip_change_op_info info; 
     3526 
     3527            pj_bzero(&info, sizeof(info)); 
     3528            info.lis_restart.transport_id = id; 
     3529            pjsua_var.ua_cfg.cb.on_ip_change_progress( 
     3530                                                PJSUA_IP_CHANGE_OP_RESTART_LIS,  
     3531                                                status,  
     3532                                                &info); 
     3533        } 
     3534 
     3535        /* Move forward if all listener has been restarted. */ 
     3536        for (; i < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) { 
     3537            if (pjsua_var.tpdata[i].data.ptr != NULL &&  
     3538                pjsua_var.tpdata[i].is_restarting)  
     3539            { 
     3540                all_done = PJ_FALSE; 
     3541                break; 
     3542            } 
     3543        } 
     3544        if (all_done) 
     3545            status = handle_ip_change_on_acc(); 
     3546    } 
     3547    return status; 
     3548} 
     3549 
     3550 
     3551static void restart_listener_cb(void *user_data) 
     3552{ 
     3553    pjsua_transport_id transport_id = (pjsua_transport_id)(pj_size_t)user_data; 
     3554    restart_listener(transport_id, 0); 
     3555} 
     3556 
     3557 
     3558PJ_DEF(pj_status_t) pjsua_handle_ip_change(const pjsua_ip_change_param *param) 
     3559{ 
     3560    pj_status_t status = PJ_SUCCESS; 
     3561    int i = 0; 
     3562 
     3563    PJ_ASSERT_RETURN(param, PJ_EINVAL); 
     3564 
     3565    PJ_LOG(3, (THIS_FILE, "Start handling IP address change")); 
     3566     
     3567    if (param->restart_listener) { 
     3568        /* Restart listener/transport, handle_ip_change_on_acc() will 
     3569         * be called after listener restart is completed successfully. 
     3570         */ 
     3571        for (i = 0; i < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) { 
     3572            if (pjsua_var.tpdata[i].data.ptr != NULL) { 
     3573                pjsua_var.tpdata[i].is_restarting = PJ_TRUE; 
     3574            } 
     3575        } 
     3576        for (i = 0; i < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) { 
     3577            if (pjsua_var.tpdata[i].data.ptr != NULL) {          
     3578                status = restart_listener(i, param->restart_lis_delay); 
     3579            } 
     3580        } 
     3581    } else { 
     3582        status = handle_ip_change_on_acc(); 
     3583    } 
     3584 
     3585    return status; 
     3586} 
  • pjproject/trunk/pjsip/src/pjsua2/account.cpp

    r5636 r5649  
    300300    NODE_WRITE_UNSIGNED( this_node, startKeyframeInterval); 
    301301} 
     302/////////////////////////////////////////////////////////////////////////////// 
     303 
     304void AccountIpChangeConfig::readObject(const ContainerNode &node) throw(Error) 
     305{ 
     306    ContainerNode this_node = node.readContainer("AccountIpChangeConfig"); 
     307 
     308    NODE_READ_BOOL    ( this_node, shutdownTp); 
     309    NODE_READ_BOOL    ( this_node, hangupCalls); 
     310    NODE_READ_UNSIGNED( this_node, reinviteFlags); 
     311} 
     312 
     313void AccountIpChangeConfig::writeObject(ContainerNode &node) const throw(Error) 
     314{ 
     315    ContainerNode this_node = node.writeNewContainer("AccountIpChangeConfig"); 
     316 
     317    NODE_WRITE_BOOL    ( this_node, shutdownTp); 
     318    NODE_WRITE_BOOL    ( this_node, hangupCalls); 
     319    NODE_WRITE_UNSIGNED( this_node, reinviteFlags); 
     320} 
    302321 
    303322/////////////////////////////////////////////////////////////////////////////// 
     
    446465    ret.vid_stream_sk_cfg.count = videoConfig.startKeyframeCount; 
    447466    ret.vid_stream_sk_cfg.interval = videoConfig.startKeyframeInterval; 
     467 
     468    // AccountIpChangeConfig 
     469    ret.ip_change_cfg.shutdown_tp = ipChangeConfig.shutdownTp; 
     470    ret.ip_change_cfg.hangup_calls = ipChangeConfig.hangupCalls; 
     471    ret.ip_change_cfg.reinvite_flags = ipChangeConfig.reinviteFlags; 
    448472} 
    449473 
     
    615639    videoConfig.startKeyframeCount      = prm.vid_stream_sk_cfg.count; 
    616640    videoConfig.startKeyframeInterval   = prm.vid_stream_sk_cfg.interval; 
     641 
     642    // AccountIpChangeConfig 
     643    ipChangeConfig.shutdownTp = PJ2BOOL(prm.ip_change_cfg.shutdown_tp); 
     644    ipChangeConfig.hangupCalls = PJ2BOOL(prm.ip_change_cfg.hangup_calls); 
     645    ipChangeConfig.reinviteFlags = prm.ip_change_cfg.reinvite_flags; 
    617646} 
    618647 
  • pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp

    r5645 r5649  
    123123 
    124124/////////////////////////////////////////////////////////////////////////////// 
    125  
     125IpChangeParam::IpChangeParam() 
     126{ 
     127    pjsua_ip_change_param param;     
     128    pjsua_ip_change_param_default(&param); 
     129    fromPj(param); 
     130} 
     131 
     132 
     133pjsua_ip_change_param IpChangeParam::toPj() const 
     134{ 
     135    pjsua_ip_change_param param; 
     136    pjsua_ip_change_param_default(&param); 
     137 
     138    param.restart_listener = restartListener; 
     139    param.restart_lis_delay = restartLisDelay; 
     140 
     141    return param; 
     142} 
     143 
     144 
     145void IpChangeParam::fromPj(const pjsua_ip_change_param &param) 
     146{ 
     147    restartListener = PJ2BOOL(param.restart_listener); 
     148    restartLisDelay = param.restart_lis_delay; 
     149} 
     150 
     151/////////////////////////////////////////////////////////////////////////////// 
    126152UaConfig::UaConfig() 
    127153: mainThreadOnly(false) 
     
    14071433} 
    14081434 
     1435void Endpoint::on_ip_change_progress(pjsua_ip_change_op op, 
     1436                                     pj_status_t status, 
     1437                                     const pjsua_ip_change_op_info *info) 
     1438{ 
     1439    Endpoint &ep = Endpoint::instance(); 
     1440    OnIpChangeProgressParam param; 
     1441 
     1442    param.op = op; 
     1443    param.status = status; 
     1444    switch (op) { 
     1445    case PJSUA_IP_CHANGE_OP_RESTART_LIS:                 
     1446        param.transportId = info->lis_restart.transport_id;      
     1447        break; 
     1448    case PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP: 
     1449        param.accId = info->acc_shutdown_tp.acc_id; 
     1450        break; 
     1451    case PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT:  
     1452        param.accId = info->acc_update_contact.acc_id;   
     1453        param.regInfo.code = info->acc_update_contact.code; 
     1454        param.regInfo.isRegister =  
     1455                                 PJ2BOOL(info->acc_update_contact.is_register); 
     1456        break; 
     1457    case PJSUA_IP_CHANGE_OP_ACC_HANGUP_CALLS: 
     1458        param.accId = info->acc_hangup_calls.acc_id; 
     1459        param.callId = info->acc_hangup_calls.call_id; 
     1460        break; 
     1461    case PJSUA_IP_CHANGE_OP_ACC_REINVITE_CALLS: 
     1462        param.accId = info->acc_reinvite_calls.acc_id; 
     1463        param.callId = info->acc_reinvite_calls.call_id; 
     1464        break; 
     1465    default: 
     1466        param.accId = PJSUA_INVALID_ID; 
     1467        break; 
     1468    } 
     1469    ep.onIpChangeProgress(param); 
     1470} 
     1471 
    14091472/////////////////////////////////////////////////////////////////////////////// 
    14101473/* 
     
    14691532    ua_cfg.cb.on_buddy_state    = &Endpoint::on_buddy_state; 
    14701533    ua_cfg.cb.on_acc_find_for_incoming  = &Endpoint::on_acc_find_for_incoming; 
     1534    ua_cfg.cb.on_ip_change_progress     = &Endpoint::on_ip_change_progress; 
    14711535 
    14721536    /* Call callbacks */ 
     
    19892053#endif   
    19902054} 
     2055 
     2056void Endpoint::handleIpChange(const IpChangeParam &param) throw(Error) 
     2057{ 
     2058    pjsua_ip_change_param ip_change_param = param.toPj(); 
     2059    PJSUA2_CHECK_EXPR(pjsua_handle_ip_change(&ip_change_param)); 
     2060} 
Note: See TracChangeset for help on using the changeset viewer.