More ticket #399: added PJSUA API to retrieve the remote NAT type

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1533 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/build.symbian/pjsua_libU.def b/build.symbian/pjsua_libU.def
index 932587e..a277601 100644
--- a/build.symbian/pjsua_libU.def
+++ b/build.symbian/pjsua_libU.def
@@ -32,87 +32,89 @@
 	pjsua_call_get_count                     @ 31 NONAME
 	pjsua_call_get_info                      @ 32 NONAME
 	pjsua_call_get_max_count                 @ 33 NONAME
-	pjsua_call_get_user_data                 @ 34 NONAME
-	pjsua_call_hangup                        @ 35 NONAME
-	pjsua_call_hangup_all                    @ 36 NONAME
-	pjsua_call_has_media                     @ 37 NONAME
-	pjsua_call_is_active                     @ 38 NONAME
-	pjsua_call_make_call                     @ 39 NONAME
-	pjsua_call_reinvite                      @ 40 NONAME
-	pjsua_call_send_im                       @ 41 NONAME
-	pjsua_call_send_request                  @ 42 NONAME
-	pjsua_call_send_typing_ind               @ 43 NONAME
-	pjsua_call_set_hold                      @ 44 NONAME
-	pjsua_call_set_user_data                 @ 45 NONAME
-	pjsua_call_update                        @ 46 NONAME
-	pjsua_call_xfer                          @ 47 NONAME
-	pjsua_call_xfer_replaces                 @ 48 NONAME
-	pjsua_codec_get_param                    @ 49 NONAME
-	pjsua_codec_set_param                    @ 50 NONAME
-	pjsua_codec_set_priority                 @ 51 NONAME
-	pjsua_conf_add_port                      @ 52 NONAME
-	pjsua_conf_adjust_rx_level               @ 53 NONAME
-	pjsua_conf_adjust_tx_level               @ 54 NONAME
-	pjsua_conf_connect                       @ 55 NONAME
-	pjsua_conf_disconnect                    @ 56 NONAME
-	pjsua_conf_get_active_ports              @ 57 NONAME
-	pjsua_conf_get_max_ports                 @ 58 NONAME
-	pjsua_conf_get_port_info                 @ 59 NONAME
-	pjsua_conf_get_signal_level              @ 60 NONAME
-	pjsua_conf_remove_port                   @ 61 NONAME
-	pjsua_config_default                     @ 62 NONAME
-	pjsua_config_dup                         @ 63 NONAME
-	pjsua_create                             @ 64 NONAME
-	pjsua_destroy                            @ 65 NONAME
-	pjsua_detect_nat_type                    @ 66 NONAME
-	pjsua_dump                               @ 67 NONAME
-	pjsua_enum_accs                          @ 68 NONAME
-	pjsua_enum_buddies                       @ 69 NONAME
-	pjsua_enum_calls                         @ 70 NONAME
-	pjsua_enum_codecs                        @ 71 NONAME
-	pjsua_enum_conf_ports                    @ 72 NONAME
-	pjsua_enum_snd_devs                      @ 73 NONAME
-	pjsua_enum_transports                    @ 74 NONAME
-	pjsua_get_buddy_count                    @ 75 NONAME
-	pjsua_get_ec_tail                        @ 76 NONAME
-	pjsua_get_nat_type                       @ 77 NONAME
-	pjsua_get_pjmedia_endpt                  @ 78 NONAME
-	pjsua_get_pjsip_endpt                    @ 79 NONAME
-	pjsua_get_pool_factory                   @ 80 NONAME
-	pjsua_get_snd_dev                        @ 81 NONAME
-	pjsua_handle_events                      @ 82 NONAME
-	pjsua_im_send                            @ 83 NONAME
-	pjsua_im_typing                          @ 84 NONAME
-	pjsua_init                               @ 85 NONAME
-	pjsua_logging_config_default             @ 86 NONAME
-	pjsua_logging_config_dup                 @ 87 NONAME
-	pjsua_media_config_default               @ 88 NONAME
-	pjsua_media_transports_create            @ 89 NONAME
-	pjsua_msg_data_init                      @ 90 NONAME
-	pjsua_perror                             @ 91 NONAME
-	pjsua_player_create                      @ 92 NONAME
-	pjsua_player_destroy                     @ 93 NONAME
-	pjsua_player_get_conf_port               @ 94 NONAME
-	pjsua_player_get_port                    @ 95 NONAME
-	pjsua_player_set_pos                     @ 96 NONAME
-	pjsua_playlist_create                    @ 97 NONAME
-	pjsua_pool_create                        @ 98 NONAME
-	pjsua_pres_dump                          @ 99 NONAME
-	pjsua_reconfigure_logging                @ 100 NONAME
-	pjsua_recorder_create                    @ 101 NONAME
-	pjsua_recorder_destroy                   @ 102 NONAME
-	pjsua_recorder_get_conf_port             @ 103 NONAME
-	pjsua_recorder_get_port                  @ 104 NONAME
-	pjsua_set_ec                             @ 105 NONAME
-	pjsua_set_no_snd_dev                     @ 106 NONAME
-	pjsua_set_null_snd_dev                   @ 107 NONAME
-	pjsua_set_snd_dev                        @ 108 NONAME
-	pjsua_start                              @ 109 NONAME
-	pjsua_transport_close                    @ 110 NONAME
-	pjsua_transport_config_default           @ 111 NONAME
-	pjsua_transport_config_dup               @ 112 NONAME
-	pjsua_transport_create                   @ 113 NONAME
-	pjsua_transport_get_info                 @ 114 NONAME
-	pjsua_transport_register                 @ 115 NONAME
-	pjsua_transport_set_enable               @ 116 NONAME
-	pjsua_verify_sip_url                     @ 117 NONAME
+	pjsua_call_get_rem_nat_type              @ 34 NONAME
+	pjsua_call_get_user_data                 @ 35 NONAME
+	pjsua_call_hangup                        @ 36 NONAME
+	pjsua_call_hangup_all                    @ 37 NONAME
+	pjsua_call_has_media                     @ 38 NONAME
+	pjsua_call_is_active                     @ 39 NONAME
+	pjsua_call_make_call                     @ 40 NONAME
+	pjsua_call_reinvite                      @ 41 NONAME
+	pjsua_call_send_im                       @ 42 NONAME
+	pjsua_call_send_request                  @ 43 NONAME
+	pjsua_call_send_typing_ind               @ 44 NONAME
+	pjsua_call_set_hold                      @ 45 NONAME
+	pjsua_call_set_user_data                 @ 46 NONAME
+	pjsua_call_update                        @ 47 NONAME
+	pjsua_call_xfer                          @ 48 NONAME
+	pjsua_call_xfer_replaces                 @ 49 NONAME
+	pjsua_codec_get_param                    @ 50 NONAME
+	pjsua_codec_set_param                    @ 51 NONAME
+	pjsua_codec_set_priority                 @ 52 NONAME
+	pjsua_conf_add_port                      @ 53 NONAME
+	pjsua_conf_adjust_rx_level               @ 54 NONAME
+	pjsua_conf_adjust_tx_level               @ 55 NONAME
+	pjsua_conf_connect                       @ 56 NONAME
+	pjsua_conf_disconnect                    @ 57 NONAME
+	pjsua_conf_get_active_ports              @ 58 NONAME
+	pjsua_conf_get_max_ports                 @ 59 NONAME
+	pjsua_conf_get_port_info                 @ 60 NONAME
+	pjsua_conf_get_signal_level              @ 61 NONAME
+	pjsua_conf_remove_port                   @ 62 NONAME
+	pjsua_config_default                     @ 63 NONAME
+	pjsua_config_dup                         @ 64 NONAME
+	pjsua_create                             @ 65 NONAME
+	pjsua_destroy                            @ 66 NONAME
+	pjsua_detect_nat_type                    @ 67 NONAME
+	pjsua_dump                               @ 68 NONAME
+	pjsua_enum_accs                          @ 69 NONAME
+	pjsua_enum_buddies                       @ 70 NONAME
+	pjsua_enum_calls                         @ 71 NONAME
+	pjsua_enum_codecs                        @ 72 NONAME
+	pjsua_enum_conf_ports                    @ 73 NONAME
+	pjsua_enum_snd_devs                      @ 74 NONAME
+	pjsua_enum_transports                    @ 75 NONAME
+	pjsua_get_buddy_count                    @ 76 NONAME
+	pjsua_get_ec_tail                        @ 77 NONAME
+	pjsua_get_nat_type                       @ 78 NONAME
+	pjsua_get_pjmedia_endpt                  @ 79 NONAME
+	pjsua_get_pjsip_endpt                    @ 80 NONAME
+	pjsua_get_pool_factory                   @ 81 NONAME
+	pjsua_get_snd_dev                        @ 82 NONAME
+	pjsua_get_var                            @ 83 NONAME
+	pjsua_handle_events                      @ 84 NONAME
+	pjsua_im_send                            @ 85 NONAME
+	pjsua_im_typing                          @ 86 NONAME
+	pjsua_init                               @ 87 NONAME
+	pjsua_logging_config_default             @ 88 NONAME
+	pjsua_logging_config_dup                 @ 89 NONAME
+	pjsua_media_config_default               @ 90 NONAME
+	pjsua_media_transports_create            @ 91 NONAME
+	pjsua_msg_data_init                      @ 92 NONAME
+	pjsua_perror                             @ 93 NONAME
+	pjsua_player_create                      @ 94 NONAME
+	pjsua_player_destroy                     @ 95 NONAME
+	pjsua_player_get_conf_port               @ 96 NONAME
+	pjsua_player_get_port                    @ 97 NONAME
+	pjsua_player_set_pos                     @ 98 NONAME
+	pjsua_playlist_create                    @ 99 NONAME
+	pjsua_pool_create                        @ 100 NONAME
+	pjsua_pres_dump                          @ 101 NONAME
+	pjsua_reconfigure_logging                @ 102 NONAME
+	pjsua_recorder_create                    @ 103 NONAME
+	pjsua_recorder_destroy                   @ 104 NONAME
+	pjsua_recorder_get_conf_port             @ 105 NONAME
+	pjsua_recorder_get_port                  @ 106 NONAME
+	pjsua_set_ec                             @ 107 NONAME
+	pjsua_set_no_snd_dev                     @ 108 NONAME
+	pjsua_set_null_snd_dev                   @ 109 NONAME
+	pjsua_set_snd_dev                        @ 110 NONAME
+	pjsua_start                              @ 111 NONAME
+	pjsua_transport_close                    @ 112 NONAME
+	pjsua_transport_config_default           @ 113 NONAME
+	pjsua_transport_config_dup               @ 114 NONAME
+	pjsua_transport_create                   @ 115 NONAME
+	pjsua_transport_get_info                 @ 116 NONAME
+	pjsua_transport_register                 @ 117 NONAME
+	pjsua_transport_set_enable               @ 118 NONAME
+	pjsua_verify_sip_url                     @ 119 NONAME
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index d076c66..695e2c8 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -989,13 +989,13 @@
     pj_str_t	    stun_relay_host;
 
     /**
-     * Include local endpoint's NAT type in the SDP to assist troubleshooting.
-     * The valid values are:
-     *	- 0: no information will be added in SDP.
+     * Support for adding and parsing NAT type in the SDP to assist 
+     * troubleshooting. The valid values are:
+     *	- 0: no information will be added in SDP, and parsing is disabled.
      *	- 1: only the NAT type number is added.
      *	- 2: add both NAT type number and name.
      *
-     * Default: 2
+     * Default: 1
      */
     int		    nat_type_in_sdp;
 
@@ -1365,6 +1365,8 @@
  *			PJ_SUCCESS and \a type will be set to the correct
  *			value. Other return values indicate error and
  *			\a type will be set to PJ_STUN_NAT_TYPE_ERR_UNKNOWN.
+ *
+ * @see pjsua_call_get_rem_nat_type()
  */
 PJ_DECL(pj_status_t) pjsua_get_nat_type(pj_stun_nat_type *type);
 
@@ -2731,6 +2733,30 @@
 
 
 /**
+ * Get the NAT type of remote's endpoint. This is a proprietary feature
+ * of PJSUA-LIB which sends its NAT type in the SDP when \a nat_type_in_sdp
+ * is set in #pjsua_config.
+ *
+ * This function can only be called after SDP has been received from remote,
+ * which means for incoming call, this function can be called as soon as
+ * call is received as long as incoming call contains SDP, and for outgoing
+ * call, this function can be called only after SDP is received (normally in
+ * 200/OK response to INVITE). As a general case, application should call 
+ * this function after or in \a on_call_media_state() callback.
+ *
+ * @param call_id	Call identification.
+ * @param p_type	Pointer to store the NAT type. Application can then
+ *			retrieve the string description of the NAT type
+ *			by calling pj_stun_get_nat_name().
+ *
+ * @return		PJ_SUCCESS on success.
+ *
+ * @see pjsua_get_nat_type(), nat_type_in_sdp
+ */
+PJ_DECL(pj_status_t) pjsua_call_get_rem_nat_type(pjsua_call_id call_id,
+						 pj_stun_nat_type *p_type);
+
+/**
  * Send response to incoming INVITE request. Depending on the status
  * code specified as parameter, this function may send provisional
  * response, establish the call, or terminate the call.
diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h
index 530dc89..004c1ca 100644
--- a/pjsip/include/pjsua-lib/pjsua_internal.h
+++ b/pjsip/include/pjsua-lib/pjsua_internal.h
@@ -52,6 +52,7 @@
     pjmedia_transport	*med_tp;    /**< Media transport.		    */
     pj_timer_entry	 refresh_tm;/**< Timer to send re-INVITE.	    */
     pj_timer_entry	 hangup_tm; /**< Timer to hangup call.		    */
+    pj_stun_nat_type	 rem_nat_type; /**< NAT type of remote endpoint.    */
 
     char    last_text_buf_[128];    /**< Buffer for last_text.		    */
 
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index 220e2b1..f1fe320 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -98,6 +98,7 @@
     call->conn_time.msec = 0;
     call->res_time.sec = 0;
     call->res_time.msec = 0;
+    call->rem_nat_type = PJ_STUN_NAT_TYPE_UNKNOWN;
 }
 
 
@@ -429,6 +430,24 @@
 }
 
 
+/* Get the NAT type information in remote's SDP */
+static void update_remote_nat_type(pjsua_call *call, 
+				   const pjmedia_sdp_session *sdp)
+{
+    const pjmedia_sdp_attr *xnat;
+
+    xnat = pjmedia_sdp_attr_find2(sdp->attr_count, sdp->attr, "X-nat", NULL);
+    if (xnat) {
+	call->rem_nat_type = (pj_stun_nat_type) (xnat->value.ptr[0] - '0');
+    } else {
+	call->rem_nat_type = PJ_STUN_NAT_TYPE_UNKNOWN;
+    }
+
+    PJ_LOG(5,(THIS_FILE, "Call %d: remote NAT type is %d (%s)", call->index,
+	      call->rem_nat_type, pj_stun_get_nat_name(call->rem_nat_type)));
+}
+
+
 /**
  * Handle incoming INVITE request.
  * Called by pjsua_core.c
@@ -658,6 +677,13 @@
 	return PJ_TRUE;
     }
 
+    /* Update NAT type of remote endpoint */
+    if (pjsua_var.ua_cfg.nat_type_in_sdp) {
+	const pjmedia_sdp_session *remote_sdp;
+
+	if (pjmedia_sdp_neg_get_neg_remote(inv->neg, &remote_sdp)==PJ_SUCCESS)
+	    update_remote_nat_type(call, remote_sdp);
+    }
 
     /* Create and attach pjsua_var data to the dialog: */
     call->inv = inv;
@@ -1023,6 +1049,21 @@
 
 
 /*
+ * Get remote's NAT type.
+ */
+PJ_DEF(pj_status_t) pjsua_call_get_rem_nat_type(pjsua_call_id call_id,
+						pj_stun_nat_type *p_type)
+{
+    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
+		     PJ_EINVAL);
+    PJ_ASSERT_RETURN(p_type != NULL, PJ_EINVAL);
+
+    *p_type = pjsua_var.calls[call_id].rem_nat_type;
+    return PJ_SUCCESS;
+}
+
+
+/*
  * Send response to incoming INVITE request.
  */
 PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id, 
@@ -2267,7 +2308,6 @@
 	return;
     }
 
-
     status = pjmedia_sdp_neg_get_active_remote(call->inv->neg, &remote_sdp);
     if (status != PJ_SUCCESS) {
 	pjsua_perror(THIS_FILE, 
@@ -2278,6 +2318,12 @@
 	return;
     }
 
+    /* Update remote's NAT type */
+    if (pjsua_var.ua_cfg.nat_type_in_sdp) {
+	update_remote_nat_type(call, remote_sdp);
+    }
+
+    /* Update media channel with the new SDP */
     status = pjsua_media_channel_update(call->index, local_sdp, remote_sdp);
     if (status != PJ_SUCCESS) {
 	pjsua_perror(THIS_FILE, "Unable to create media session", 
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index a60301a..2cfca8d 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -86,7 +86,7 @@
 
     cfg->max_calls = 4;
     cfg->thread_cnt = 1;
-    cfg->nat_type_in_sdp = 2;
+    cfg->nat_type_in_sdp = 1;
 }
 
 PJ_DEF(void) pjsua_config_dup(pj_pool_t *pool,