- Timestamp:
- Sep 15, 2017 5:32:08 AM (7 years ago)
- 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 40 40 3AF253001EFBD15E00213893 /* libyuv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF252FF1EFBD15E00213893 /* libyuv.a */; }; 41 41 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 */; }; 42 44 E5E991E61B67A45500017E67 /* libg7221codec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E991D41B67A45500017E67 /* libg7221codec.a */; }; 43 45 E5E991E71B67A45500017E67 /* libgsmcodec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E991D51B67A45500017E67 /* libgsmcodec.a */; }; … … 98 100 3AF252FF1EFBD15E00213893 /* libyuv.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libyuv.a; sourceTree = "<group>"; }; 99 101 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; }; 100 106 E5E991D41B67A45500017E67 /* libg7221codec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libg7221codec.a; sourceTree = "<group>"; }; 101 107 E5E991D51B67A45500017E67 /* libgsmcodec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgsmcodec.a; sourceTree = "<group>"; }; … … 123 129 buildActionMask = 2147483647; 124 130 files = ( 131 7485A6B11F09B2D500122F1A /* SystemConfiguration.framework in Frameworks */, 125 132 3AF253021EFBD36E00213893 /* VideoToolbox.framework in Frameworks */, 126 133 3AB0EC581DA76B39008A0F62 /* libc++.tbd in Frameworks */, … … 197 204 isa = PBXGroup; 198 205 children = ( 206 741C73BA1F0E64AF00887FB6 /* libopenh264.a */, 207 7485A6B01F09B2D500122F1A /* SystemConfiguration.framework */, 199 208 3AF253011EFBD36E00213893 /* VideoToolbox.framework */, 200 209 3AB0EC571DA76B39008A0F62 /* libc++.tbd */, … … 224 233 3AF0582016F050780046B835 /* ipjsuaViewController.h */, 225 234 3AF0582116F050780046B835 /* ipjsuaViewController.m */, 235 7485A6AD1F09AAE500122F1A /* Reachability.h */, 236 7485A6AE1F09AAE500122F1A /* Reachability.m */, 226 237 3AF0582316F050780046B835 /* ipjsuaViewController_iPhone.xib */, 227 238 3AF0582616F050780046B835 /* ipjsuaViewController_iPad.xib */, … … 354 365 3ADCCD2F172E40120007BE8E /* pjsua_app_config.c in Sources */, 355 366 3ADCCD30172E40120007BE8E /* pjsua_app_legacy.c in Sources */, 367 7485A6AF1F09AAE500122F1A /* Reachability.m in Sources */, 356 368 3ADCCD31172E40120007BE8E /* pjsua_app.c in Sources */, 357 369 ); -
pjproject/trunk/pjsip-apps/src/pjsua/ios/ipjsua/ipjsuaAppDelegate.m
r5628 r5649 28 28 29 29 #import "ipjsuaViewController.h" 30 #import "Reachability.h" 30 31 31 32 @implementation ipjsuaAppDelegate … … 40 41 static char **restartArgv; 41 42 static int restartArgc; 43 Reachability *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(¶m); 79 pjsua_handle_ip_change(¶m); 80 } 81 } 82 42 83 43 84 void displayLog(const char *msg, int len) … … 155 196 self.window.rootViewController = self.viewController; 156 197 [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]; 157 209 158 210 app = self; -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app_cli.c
r5626 r5649 39 39 #define CMD_QUIT 110 40 40 #define CMD_RESTART 120 41 #define CMD_HANDLE_IP_CHANGE 130 41 42 42 43 /* call level 2 command */ … … 2584 2585 /* Invoke CLI stop callback (defined in pjsua_app.c) */ 2585 2586 cli_on_stopped(PJ_FALSE, 0, NULL); 2587 2588 return PJ_SUCCESS; 2589 } 2590 2591 static 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(¶m); 2598 pjsua_handle_ip_change(¶m); 2586 2599 2587 2600 return PJ_SUCCESS; … … 3069 3082 "</CMD>"; 3070 3083 3084 char* ip_change_command = 3085 "<CMD name='ip_change' id='130' desc='Handle IP change'/>"; 3086 3071 3087 pj_status_t status; 3072 3088 pj_str_t sleep_xml = pj_str(sleep_command); … … 3074 3090 pj_str_t shutdown_xml = pj_str(shutdown_command); 3075 3091 pj_str_t restart_xml = pj_str(restart_command); 3092 pj_str_t ip_change_xml = pj_str(ip_change_command); 3076 3093 3077 3094 status = pj_cli_add_cmd_from_xml(c, NULL, … … 3098 3115 NULL, NULL); 3099 3116 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 3100 3124 return status; 3101 3125 } -
pjproject/trunk/pjsip-apps/src/swig/java/android/app/src/main/java/org/pjsip/pjsua2/app/MainActivity.java
r5502 r5649 19 19 package org.pjsip.pjsua2.app; 20 20 21 import android.content.IntentFilter; 21 22 import android.os.Bundle; 22 23 import android.os.Handler; … … 27 28 import android.content.Intent; 28 29 import android.content.pm.ApplicationInfo; 30 import android.content.BroadcastReceiver; 31 import android.content.Context; 29 32 import android.view.LayoutInflater; 30 33 import android.view.Menu; … … 37 40 import android.widget.SimpleAdapter; 38 41 import android.widget.TextView; 42 import android.net.ConnectivityManager; 43 import android.net.NetworkInfo; 39 44 40 45 import java.util.ArrayList; … … 51 56 public static MyAccount account = null; 52 57 public static AccountConfig accCfg = null; 58 public static MyBroadcastReceiver receiver = null; 59 public static IntentFilter intentFilter = null; 53 60 54 61 private ListView buddyListView; … … 66 73 public final static int BUDDY_STATE = 4; 67 74 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 } 68 108 } 69 109 … … 144 184 } 145 185 ); 146 186 if (receiver == null) { 187 receiver = new MyBroadcastReceiver(); 188 intentFilter = new IntentFilter( 189 ConnectivityManager.CONNECTIVITY_ACTION); 190 registerReceiver(receiver, intentFilter); 191 } 147 192 } 148 193 … … 264 309 showCallActivity(); 265 310 311 } else if (m.what == MSG_TYPE.CHANGE_NETWORK) { 312 app.handleNetworkChange(); 266 313 } else { 267 314 … … 577 624 } 578 625 626 public void notifyChangeNetwork() 627 { 628 Message m = Message.obtain(handler, MSG_TYPE.CHANGE_NETWORK, null); 629 m.sendToTarget(); 630 } 631 579 632 /* === end of MyAppObserver ==== */ 580 633 -
pjproject/trunk/pjsip-apps/src/swig/java/android/app/src/main/java/org/pjsip/pjsua2/app/MyApp.java
r5611 r5649 34 34 abstract void notifyCallMediaState(MyCall call); 35 35 abstract void notifyBuddyState(MyBuddy buddy); 36 abstract void notifyChangeNetwork(); 36 37 } 37 38 … … 535 536 } 536 537 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 537 549 public void deinit() 538 550 { -
pjproject/trunk/pjsip-apps/src/swig/java/sample.java
r5392 r5649 64 64 @Override 65 65 public void notifyBuddyState(MyBuddy buddy) {} 66 67 @Override 68 public void notifyChangeNetwork() {} 66 69 } 67 70 -
pjproject/trunk/pjsip-apps/src/swig/symbols.i
r5636 r5649 176 176 typedef enum pjsua_snd_dev_mode {PJSUA_SND_DEV_SPEAKER_ONLY = 1, PJSUA_SND_DEV_NO_IMMEDIATE_OPEN = 2} pjsua_snd_dev_mode; 177 177 178 typedef 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 34 34 pjsip-ua/sip_inv.h pjsip_inv_state 35 35 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 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 pjsua_ip_change_op -
pjproject/trunk/pjsip/include/pjsip/sip_transport_tcp.h
r4860 r5649 226 226 PJ_DECL(pj_sock_t) pjsip_tcp_transport_get_socket(pjsip_transport *transport); 227 227 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 */ 249 PJ_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 */ 274 PJ_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 228 279 PJ_END_DECL 229 280 -
pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h
r5472 r5649 430 430 */ 431 431 PJ_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 */ 459 PJ_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 */ 485 PJ_DECL(pj_status_t) pjsip_tls_transport_restart(pjsip_tpfactory *factory, 486 const pj_sockaddr *local, 487 const pjsip_host_port *a_name); 437 488 438 489 PJ_END_DECL -
pjproject/trunk/pjsip/include/pjsip/sip_transport_udp.h
r5284 r5649 320 320 const pjsip_host_port *a_name); 321 321 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 */ 361 PJ_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 322 367 323 368 PJ_END_DECL -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r5636 r5649 617 617 618 618 } pjsua_contact_rewrite_method; 619 620 621 /** 622 * This enumeration specifies the operation when handling IP change. 623 */ 624 typedef 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 */ 661 typedef 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; 619 701 620 702 … … 1417 1499 pj_stun_resolve_cb on_stun_resolution_complete; 1418 1500 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 1419 1514 } pjsua_callback; 1420 1515 … … 2081 2176 unsigned index; 2082 2177 }; 2178 2179 2180 /** 2181 * This structure describe the parameter passed to #pjsua_handle_ip_change(). 2182 */ 2183 typedef 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 */ 2206 typedef 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 */ 2245 PJ_DECL(void) pjsua_ip_change_param_default(pjsua_ip_change_param *param); 2083 2246 2084 2247 … … 2303 2466 PJ_DECL(void) pjsua_dump(pj_bool_t detail); 2304 2467 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 */ 2489 PJ_DECL(pj_status_t) pjsua_handle_ip_change( 2490 const pjsua_ip_change_param *param); 2491 2492 2305 2493 /** 2306 2494 * @} … … 2577 2765 PJ_DECL(pj_status_t) pjsua_transport_close( pjsua_transport_id id, 2578 2766 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 */ 2780 PJ_DECL(pj_status_t) pjsua_transport_lis_start( pjsua_transport_id id, 2781 const pjsua_transport_config *cfg); 2782 2579 2783 2580 2784 /** … … 3542 3746 * Default: PJ_TRUE 3543 3747 */ 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; 3545 3755 3546 3756 } pjsua_acc_config; … … 5729 5939 5730 5940 /** 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 /** 5731 5950 * This structure describes media configuration, which will be specified 5732 5951 * when calling #pjsua_init(). Application MUST initialize this structure -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
r5636 r5649 286 286 pjsip_transport_type_e tp_type; /**< Transport type (for local acc or 287 287 transport binding) */ 288 pjsua_ip_change_op ip_change_op;/**< IP change process progress. */ 288 289 } pjsua_acc; 289 290 … … 304 305 } data; 305 306 307 pj_bool_t is_restarting; 306 308 } pjsua_transport_data; 307 309 … … 868 870 void pjsua_call_schedule_reinvite_check(pjsua_call *call, unsigned delay_ms); 869 871 872 /* 873 * Update contact per account on IP change process. 874 */ 875 pj_status_t pjsua_acc_update_contact_on_ip_change(pjsua_acc *acc); 876 877 /* 878 * Call handling per account on IP change process. 879 */ 880 pj_status_t pjsua_acc_handle_call_on_ip_change(pjsua_acc *acc); 881 870 882 PJ_END_DECL 871 883 -
pjproject/trunk/pjsip/include/pjsua2/account.hpp
r5636 r5649 882 882 883 883 /** 884 * Account config specific to IP address change. 885 */ 886 typedef 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 916 public: 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 /** 884 934 * Account configuration. 885 935 */ … … 941 991 */ 942 992 AccountVideoConfig videoConfig; 993 994 /** 995 * IP Change settings. 996 */ 997 AccountIpChangeConfig ipChangeConfig; 943 998 944 999 public: -
pjproject/trunk/pjsip/include/pjsua2/endpoint.hpp
r5636 r5649 319 319 int accountIndex; 320 320 }; 321 322 /** 323 * Parameter of Endpoint::handleIpChange(). 324 */ 325 struct 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; 340 public: 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 ¶m); 355 }; 356 357 /** 358 * Information of Update contact on IP change progress. 359 */ 360 struct 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 */ 376 struct 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 321 418 322 419 ////////////////////////////////////////////////////////////////////////////// … … 1377 1474 void resetVideoCodecParam(const string &codec_id) throw(Error); 1378 1475 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 ¶m) throw(Error); 1500 1379 1501 public: 1380 1502 /* … … 1438 1560 */ 1439 1561 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) 1440 1572 { PJ_UNUSED_ARG(prm); } 1441 1573 … … 1588 1720 pjmedia_srtp_setting *srtp_opt); 1589 1721 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 1590 1727 private: 1591 1728 void clearCodecInfoList(CodecInfoVector &codec_list); -
pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c
r5534 r5649 62 62 pj_qos_params qos_params; 63 63 pj_sockopt_params sockopt_params; 64 pj_bool_t reuse_addr; 65 unsigned async_cnt; 64 66 65 67 /* Group lock to be used by TCP listener and ioqueue key */ … … 242 244 */ 243 245 246 static 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 264 static 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 327 static 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 244 358 /* 245 359 * This is the public API to create, initialize, register, and start the … … 251 365 pjsip_tpfactory **p_factory 252 366 ) 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; 264 370 pj_status_t status; 265 371 266 372 /* Sanity check */ 267 373 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 }283 374 284 375 pool = pjsip_endpt_create_pool(endpt, "tcptp", POOL_LIS_INIT, … … 292 383 PJSIP_TRANSPORT_TCP6; 293 384 listener->factory.type_name = (char*) 294 pjsip_transport_get_type_name(listener->factory.type);385 pjsip_transport_get_type_name(listener->factory.type); 295 386 listener->factory.flag = 296 pjsip_transport_get_flag_from_type(listener->factory.type);387 pjsip_transport_get_flag_from_type(listener->factory.type); 297 388 listener->qos_type = cfg->qos_type; 389 listener->reuse_addr = cfg->reuse_addr; 390 listener->async_cnt = cfg->async_cnt; 298 391 pj_memcpy(&listener->qos_params, &cfg->qos_params, 299 392 sizeof(cfg->qos_params)); … … 308 401 &listener->factory.lock); 309 402 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; 429 404 430 405 /* Create group lock */ 431 406 status = pj_grp_lock_create(pool, NULL, &listener->grp_lock); 432 407 if (status != PJ_SUCCESS) 433 return status;408 goto on_error; 434 409 435 410 pj_grp_lock_add_ref(listener->grp_lock); 436 411 pj_grp_lock_add_handler(listener->grp_lock, pool, listener, 437 412 &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 #endif453 413 454 414 /* Register to transport manager */ … … 456 416 listener->tpmgr = pjsip_endpt_get_tpmgr(endpt); 457 417 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 459 438 listener->is_registered = PJ_TRUE; 460 439 status = pjsip_tpmgr_register_tpfactory(listener->tpmgr, … … 465 444 } 466 445 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 #endif478 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 503 446 /* Return the pointer to user */ 504 447 if (p_factory) *p_factory = &listener->factory; … … 507 450 508 451 on_error: 509 if (listener->asock==NULL && sock!=PJ_INVALID_SOCKET)510 pj_sock_close(sock);511 452 lis_destroy(&listener->factory); 512 453 return status; … … 572 513 } 573 514 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. */ 516 static void lis_close(struct tcp_listener *listener) 517 { 580 518 if (listener->is_registered) { 581 519 pjsip_tpmgr_unregister_tpfactory(listener->tpmgr, &listener->factory); … … 587 525 listener->asock = NULL; 588 526 } 527 } 528 529 /* This callback is called by transport manager to destroy listener */ 530 static pj_status_t lis_destroy(pjsip_tpfactory *factory) 531 { 532 struct tcp_listener *listener = (struct tcp_listener *)factory; 533 534 lis_close(listener); 589 535 590 536 if (listener->grp_lock) { … … 1638 1584 1639 1585 1586 PJ_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 1679 on_error: 1680 if (listener->asock == NULL && sock != PJ_INVALID_SOCKET) 1681 pj_sock_close(sock); 1682 1683 return status; 1684 } 1685 1686 1687 PJ_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 1640 1716 #endif /* PJ_HAS_TCP */ 1641 1717 -
pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c
r5534 r5649 58 58 pj_sockaddr bound_addr; 59 59 pj_ssl_cert_t *cert; 60 pjsip_tls_setting tls_setting; 60 pjsip_tls_setting tls_setting; 61 unsigned async_cnt; 61 62 62 63 /* Group lock to be used by TLS transport and ioqueue key */ … … 283 284 */ 284 285 286 287 static 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 335 static 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 352 static 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 411 static 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 285 443 /* 286 444 * This is the public API to create, initialize, register, and start the 287 445 * TLS listener. 288 446 */ 289 PJ_DEF(pj_status_t) pjsip_tls_transport_start 290 291 292 293 294 447 PJ_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) 295 453 { 296 454 pj_sockaddr local; … … 299 457 pj_sockaddr_cp(&local, local_in); 300 458 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 464 PJ_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 304 523 305 524 PJ_DEF(pj_status_t) pjsip_tls_transport_start2( pjsip_endpoint *endpt, … … 309 528 unsigned async_cnt, 310 529 pjsip_tpfactory **p_factory) 311 { 312 enum { INFO_LEN = 100 }; 313 char local_addr[PJ_INET6_ADDRSTRLEN+10]; 530 { 314 531 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; 322 534 pj_status_t status; 323 535 … … 325 537 PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL); 326 538 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()); 343 540 344 541 pool = pjsip_endpt_create_pool(endpt, "tlstp", POOL_LIS_INIT, … … 355 552 pjsip_transport_get_type_name(listener->factory.type); 356 553 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; 358 556 359 557 pj_ansi_strcpy(listener->factory.obj_name, "tlstp"); … … 374 572 async_cnt = MAX_ASYNC_CNT; 375 573 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; 417 575 418 576 /* Create group lock */ 419 577 status = pj_grp_lock_create(pool, NULL, &listener->grp_lock); 420 578 if (status != PJ_SUCCESS) 421 return status;579 goto on_error; 422 580 423 581 /* Setup group lock handler */ … … 425 583 pj_grp_lock_add_handler(listener->grp_lock, pool, listener, 426 584 &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 #endif439 440 /* Bind address may be different than factory.local_addr because441 * 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 }452 585 453 586 /* Check if certificate/CA list for SSL socket is set */ … … 465 598 if (status != PJ_SUCCESS) 466 599 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 } 545 601 546 602 /* Register to transport manager */ … … 549 605 listener->factory.create_transport2 = lis_create_transport; 550 606 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 551 627 listener->is_registered = PJ_TRUE; 552 628 status = pjsip_tpmgr_register_tpfactory(listener->tpmgr, … … 557 633 } 558 634 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 584 635 /* Return the pointer to user */ 585 636 if (p_factory) *p_factory = &listener->factory; … … 610 661 611 662 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 663 static void lis_close(struct tls_listener *listener) 664 { 617 665 if (listener->is_registered) { 618 666 pjsip_tpmgr_unregister_tpfactory(listener->tpmgr, &listener->factory); … … 624 672 listener->ssock = NULL; 625 673 } 674 } 675 676 677 /* This callback is called by transport manager to destroy listener */ 678 static pj_status_t lis_destroy(pjsip_tpfactory *factory) 679 { 680 struct tls_listener *listener = (struct tls_listener *)factory; 681 682 lis_close(listener); 626 683 627 684 if (listener->grp_lock) { … … 635 692 636 693 return PJ_SUCCESS; 694 } 695 696 697 PJ_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; 637 726 } 638 727 -
pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c
r5636 r5649 1081 1081 */ 1082 1082 PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport, 1083 1083 unsigned option, 1084 1084 pj_sock_t sock, 1085 1085 const pj_sockaddr_in *local, 1086 1086 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 1093 PJ_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) 1087 1098 { 1088 1099 struct udp_transport *tp; … … 1099 1110 */ 1100 1111 tp->is_paused = PJ_TRUE; 1101 1112 1102 1113 if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) { 1103 1114 char addr_buf[PJ_INET6_ADDRSTRLEN]; … … 1122 1133 /* Create the socket if it's not specified */ 1123 1134 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); 1126 1137 if (status != PJ_SUCCESS) 1127 1138 return status; … … 1190 1201 return PJ_SUCCESS; 1191 1202 } 1192 -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c
r5636 r5649 402 402 acc->tp_type = pjsua_var.tpdata[acc_cfg->transport_id].type; 403 403 404 acc->ip_change_op = PJSUA_IP_CHANGE_OP_NULL; 405 404 406 return PJ_SUCCESS; 405 407 } … … 688 690 acc->via_tp = NULL; 689 691 acc->next_rtp_port = 0; 692 acc->ip_change_op = PJSUA_IP_CHANGE_OP_NULL; 690 693 691 694 /* Remove from array */ … … 1417 1420 } 1418 1421 } 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; 1419 1427 1420 1428 on_return: … … 2200 2208 2201 2209 /* 2210 * Timer callback to handle call on IP change process. 2211 */ 2212 static 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 /* 2202 2219 * This callback is called by pjsip_regc when outgoing register 2203 2220 * request has completed. … … 2266 2283 PJ_LOG(3,(THIS_FILE, "%s: unregistration success", 2267 2284 pjsua_var.acc[acc->index].cfg.id.ptr)); 2268 } else { 2285 2286 } else { 2269 2287 /* Check and update SIP outbound status first, since the result 2270 2288 * will determine if we should update re-registration … … 2306 2324 if (acc->cfg.mwi_enabled) 2307 2325 pjsua_start_mwi(acc->index, PJ_FALSE); 2308 } 2309 2326 2327 } 2310 2328 } else { 2311 2329 PJ_LOG(4, (THIS_FILE, "SIP registration updated status=%d", param->code)); … … 2349 2367 reg_info.renew = !param->is_unreg; 2350 2368 (*pjsua_var.ua_cfg.cb.on_reg_state2)(acc->index, ®_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 } 2351 2414 } 2352 2415 … … 2676 2739 //pjsip_regc_get_info(pjsua_var.acc[acc_id].regc, ®_info); 2677 2740 //pjsua_var.acc[acc_id].auto_rereg.reg_tp = reg_info.transport; 2678 2741 2679 2742 if (pjsua_var.ua_cfg.cb.on_reg_started) { 2680 2743 (*pjsua_var.ua_cfg.cb.on_reg_started)(acc_id, renew); … … 3770 3833 pjsip_regc_release_transport(pjsua_var.acc[i].regc); 3771 3834 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 */ 3774 3845 schedule_reregistration(acc); 3775 3846 } … … 3780 3851 pj_log_pop_indent(); 3781 3852 } 3853 3854 3855 /* 3856 * Internal function to update contact on ip change process. 3857 */ 3858 pj_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 */ 3891 pj_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 306 306 307 307 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; 308 313 } 309 314 … … 2368 2373 pj_memcpy(&tcp_cfg.sockopt_params, &cfg->sockopt_params, 2369 2374 sizeof(tcp_cfg.sockopt_params)); 2370 2375 2371 2376 /* Create the TCP transport */ 2372 2377 status = pjsip_tcp_transport_start3(pjsua_var.endpt, &tcp_cfg, &tcp); … … 2426 2431 a_name.host = cfg->public_addr; 2427 2432 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, 2430 2434 &local_addr, &a_name, 1, &tls); 2431 2435 if (status != PJ_SUCCESS) { … … 2712 2716 2713 2717 2718 PJ_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 2714 2778 /* 2715 2779 * Add additional headers etc in msg_data specified by application … … 2863 2927 sel->u.listener = tpdata->data.factory; 2864 2928 } 2929 } 2930 2931 2932 PJ_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; 2865 2937 } 2866 2938 … … 3272 3344 } 3273 3345 3346 3347 /* Forward declaration. */ 3348 static void restart_listener_cb(void *user_data); 3349 3350 3351 static 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, ®c_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 3470 static 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 3551 static 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 3558 PJ_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 300 300 NODE_WRITE_UNSIGNED( this_node, startKeyframeInterval); 301 301 } 302 /////////////////////////////////////////////////////////////////////////////// 303 304 void 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 313 void 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 } 302 321 303 322 /////////////////////////////////////////////////////////////////////////////// … … 446 465 ret.vid_stream_sk_cfg.count = videoConfig.startKeyframeCount; 447 466 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; 448 472 } 449 473 … … 615 639 videoConfig.startKeyframeCount = prm.vid_stream_sk_cfg.count; 616 640 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; 617 646 } 618 647 -
pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp
r5645 r5649 123 123 124 124 /////////////////////////////////////////////////////////////////////////////// 125 125 IpChangeParam::IpChangeParam() 126 { 127 pjsua_ip_change_param param; 128 pjsua_ip_change_param_default(¶m); 129 fromPj(param); 130 } 131 132 133 pjsua_ip_change_param IpChangeParam::toPj() const 134 { 135 pjsua_ip_change_param param; 136 pjsua_ip_change_param_default(¶m); 137 138 param.restart_listener = restartListener; 139 param.restart_lis_delay = restartLisDelay; 140 141 return param; 142 } 143 144 145 void IpChangeParam::fromPj(const pjsua_ip_change_param ¶m) 146 { 147 restartListener = PJ2BOOL(param.restart_listener); 148 restartLisDelay = param.restart_lis_delay; 149 } 150 151 /////////////////////////////////////////////////////////////////////////////// 126 152 UaConfig::UaConfig() 127 153 : mainThreadOnly(false) … … 1407 1433 } 1408 1434 1435 void 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 1409 1472 /////////////////////////////////////////////////////////////////////////////// 1410 1473 /* … … 1469 1532 ua_cfg.cb.on_buddy_state = &Endpoint::on_buddy_state; 1470 1533 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; 1471 1535 1472 1536 /* Call callbacks */ … … 1989 2053 #endif 1990 2054 } 2055 2056 void Endpoint::handleIpChange(const IpChangeParam ¶m) 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.