]> sjero.net Git - linphone/commitdiff
Fix loop in upnp context release
authorYann Diorcet <yann.diorcet@belledonne-communications.com>
Wed, 13 Feb 2013 10:55:05 +0000 (11:55 +0100)
committerYann Diorcet <yann.diorcet@belledonne-communications.com>
Wed, 13 Feb 2013 10:55:05 +0000 (11:55 +0100)
Add upnp public function
Add upnp jni
Improve uPnP support when a device is removed

README
coreapi/linphonecore.c
coreapi/linphonecore.h
coreapi/linphonecore_jni.cc
coreapi/private.h
coreapi/proxy.c
coreapi/upnp.c
java/common/org/linphone/core/LinphoneCore.java
java/impl/org/linphone/core/LinphoneCoreImpl.java

diff --git a/README b/README
index 7e68bb1996fd378fe4271ce3d58c85a1073902ac..05b0b1dcb23559aa259ee85ac271abb3e34b301d 100644 (file)
--- a/README
+++ b/README
@@ -15,6 +15,8 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
                - libavcodec (ffmpeg) 
                - libswscale (part of ffmpeg too) for better scaling performance
                - theora (optional)
+       + if you want uPnP support:
+               - libupnp
 
 with their corresponding -dev or -devel package if you don't use source packages.
 
index 8930f3a8912ff6295c4c9e1909f043eafaefcff9..1be92ef30de86b1c408688c63baaa8cbdf9f75f9 100644 (file)
@@ -697,6 +697,8 @@ static void sip_config_read(LinphoneCore *lc)
        lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0);
        lc->sip_conf.register_only_when_network_is_up=
                lp_config_get_int(lc->config,"sip","register_only_when_network_is_up",1);
+       lc->sip_conf.register_only_when_upnp_is_ok=
+               lp_config_get_int(lc->config,"sip","register_only_when_upnp_is_ok",1);
        lc->sip_conf.ping_with_options=lp_config_get_int(lc->config,"sip","ping_with_options",1);
        lc->sip_conf.auto_net_state_mon=lp_config_get_int(lc->config,"sip","auto_net_state_mon",1);
        lc->sip_conf.keepalive_period=lp_config_get_int(lc->config,"sip","keepalive_period",10000);
@@ -4123,6 +4125,31 @@ const char * linphone_core_get_stun_server(const LinphoneCore *lc){
        return lc->net_conf.stun_server;
 }
 
+bool_t linphone_core_upnp_available(const LinphoneCore *lc){
+#ifdef BUILD_UPNP
+       return TRUE;
+#else
+       return FALSE;
+#endif //BUILD_UPNP
+}
+
+LinphoneUpnpState linphone_core_get_upnp_state(const LinphoneCore *lc){
+#ifdef BUILD_UPNP
+       return linphone_upnp_context_get_state(lc->upnp);
+#else
+       return LinphoneUpnpStateNotAvailable;
+#endif //BUILD_UPNP
+}
+
+const char * linphone_core_get_upnp_external_ipaddress(const LinphoneCore *lc){
+#ifdef BUILD_UPNP
+       return linphone_upnp_context_get_external_ipaddress(lc->upnp);
+#else
+       return NULL;
+#endif //BUILD_UPNP
+}
+
+
 const char * linphone_core_get_relay_addr(const LinphoneCore *lc){
        return lc->net_conf.relay;
 }
@@ -4977,7 +5004,7 @@ void sip_config_uninit(LinphoneCore *lc)
        lp_config_set_int(lc->config,"sip","use_rfc2833",config->use_rfc2833);
        lp_config_set_int(lc->config,"sip","use_ipv6",config->ipv6_enabled);
        lp_config_set_int(lc->config,"sip","register_only_when_network_is_up",config->register_only_when_network_is_up);
-
+       lp_config_set_int(lc->config,"sip","register_only_when_upnp_is_ok",config->register_only_when_upnp_is_ok);
 
        
 
index 4d4a919883c3a38710c4548d31fdce060c58250b..1de97d0b015e451948f138a098bae3e2b432ea55 100644 (file)
@@ -1105,6 +1105,36 @@ void linphone_core_set_stun_server(LinphoneCore *lc, const char *server);
 
 const char * linphone_core_get_stun_server(const LinphoneCore *lc);
 
+/**
+ * @ingroup network_parameters
+ * Return the availability of uPnP.
+ *
+ * @param lc #LinphoneCore
+ * @return true if uPnP is available otherwise return false. 
+ */
+bool_t linphone_core_upnp_available(const LinphoneCore *lc);
+
+/**
+ * @ingroup network_parameters
+ * Return the internal state of uPnP. 
+ *
+ * @param lc #LinphoneCore
+ * @return an LinphoneUpnpState. 
+ */
+LinphoneUpnpState linphone_core_get_upnp_state(const LinphoneCore *lc);
+
+/**
+ * @ingroup network_parameters
+ * Return the external ip address of router. 
+ * In some cases the uPnP can have an external ip address but not a usable uPnP
+ * (state different of Ok). 
+ *
+ * @param lc #LinphoneCore
+ * @return a null terminated string containing the external ip address. If the
+ * the external ip address is not available return null. 
+ */
+const char * linphone_core_get_upnp_external_ipaddress(const LinphoneCore *lc);
+
 void linphone_core_set_nat_address(LinphoneCore *lc, const char *addr);
 
 const char *linphone_core_get_nat_address(const LinphoneCore *lc);
index 81179be53699e85adeac71aeb2f70a3ca5b36803..64897b2189a89b53e03c06fa28b5d6e7173339a8 100644 (file)
@@ -2288,6 +2288,19 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getConfig(JNIEnv *env,
        return (jlong) linphone_core_get_config((LinphoneCore *)lc);
 }
 
+extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_upnpAvailable(JNIEnv *env, jobject thiz, jlong lc) {
+       return (jboolean) linphone_core_upnp_available((LinphoneCore *)lc);
+}
+
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getUpnpState(JNIEnv *env, jobject thiz, jlong lc) {
+       return (jint) linphone_core_get_upnp_state((LinphoneCore *)lc);
+}
+
+extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getUpnpExternalIpaddress(JNIEnv *env, jobject thiz, jlong lc) {
+       jstring jvalue = env->NewStringUTF(linphone_core_get_upnp_external_ipaddress((LinphoneCore *)lc));
+       return jvalue;
+}
+
 extern "C" jlong Java_org_linphone_core_LpConfigImpl_newLpConfigImpl(JNIEnv *env, jobject thiz, jstring file) {
         const char *cfile = env->GetStringUTFChars(file, NULL);
         LpConfig *lp = lp_config_new(cfile);
index 1f3ed6abad1566f43f76f6392c5093169aee2947..e4420d9b9933479247f464ecd15db7be4a8a532e 100644 (file)
@@ -429,6 +429,7 @@ typedef struct sip_config
        bool_t ipv6_enabled;
        bool_t sdp_200_ack;
        bool_t register_only_when_network_is_up;
+       bool_t register_only_when_upnp_is_ok;
        bool_t ping_with_options;
        bool_t auto_net_state_mon;
        bool_t tcp_tls_keepalive;
index bb6c8ec6a0100384dcb62d449e0cccca7e6d8078..fb650c852133e4f33ed7e206b0c0adea36a7e63e 100644 (file)
@@ -1082,7 +1082,8 @@ void linphone_proxy_config_update(LinphoneProxyConfig *cfg){
                if (cfg->type && cfg->ssctx==NULL){
                        linphone_proxy_config_activate_sip_setup(cfg);
                }
-               if (!lc->sip_conf.register_only_when_network_is_up || lc->network_reachable)
+               if ((!lc->sip_conf.register_only_when_network_is_up || lc->network_reachable) &&
+                       (!lc->sip_conf.register_only_when_upnp_is_ok || linphone_core_get_upnp_state(lc) == LinphoneUpnpStateOk))
                        linphone_proxy_config_register(cfg);
                if (cfg->publish && cfg->publish_op==NULL){
                        linphone_proxy_config_send_publish(cfg,lc->presence_mode);
index 5ef70ba25c1b14aa678f632d8b1e5a07cc102fa0..d86c8a42a4234a3fe51dd6cc278fbacf32e42225 100644 (file)
@@ -133,6 +133,8 @@ void linphone_upnp_igd_callback(void *cookie, upnp_igd_event event, void *arg) {
        old_state = lupnp->state;
 
        switch(event) {
+       case UPNP_IGD_DEVICE_ADDED:
+       case UPNP_IGD_DEVICE_REMOVED:
        case UPNP_IGD_EXTERNAL_IPADDRESS_CHANGED:
        case UPNP_IGD_NAT_ENABLED_CHANGED:
        case UPNP_IGD_CONNECTION_STATUS_CHANGED:
@@ -315,15 +317,12 @@ void linphone_upnp_context_destroy(UpnpContext *lupnp) {
        /* Send port binding removes */
        if(lupnp->sip_udp != NULL) {
                linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_udp);
-               lupnp->sip_udp = NULL;
        }
        if(lupnp->sip_tcp != NULL) {
                linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_tcp);
-               lupnp->sip_tcp = NULL;
        }
        if(lupnp->sip_tls != NULL) {
                linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_tls);
-               lupnp->sip_tcp = NULL;
        }
 
        /* Wait all pending bindings are done */
@@ -381,6 +380,10 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind
        upnp_igd_port_mapping mapping;
        char description[128];
        int ret;
+       
+       if(lupnp->state != LinphoneUpnpStateOk) {
+               return -2;
+       }
 
        // Compute port binding state
        if(port->state != LinphoneUpnpStateAdding) {
@@ -435,6 +438,10 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind
 int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port) {
        upnp_igd_port_mapping mapping;
        int ret;
+       
+       if(lupnp->state != LinphoneUpnpStateOk) {
+               return -2;
+       }
 
        // Compute port binding state
        if(port->state != LinphoneUpnpStateRemoving) {
@@ -848,16 +855,18 @@ UpnpPortBinding *linphone_upnp_port_binding_copy(const UpnpPortBinding *port) {
 
 void linphone_upnp_port_binding_log(int level, const char *msg, const UpnpPortBinding *port) {
        if(strlen(port->local_addr)) {
-               ortp_log(level, "uPnP IGD: %s %s|%d->%s:%d", msg,
+               ortp_log(level, "uPnP IGD: %s %s|%d->%s:%d (retry %d)", msg,
                                                        (port->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP",
                                                                        port->external_port,
                                                                        port->local_addr,
-                                                                       port->local_port);
+                                                                       port->local_port,
+                                                                       port->retry - 1);
        } else {
-               ortp_log(level, "uPnP IGD: %s %s|%d->%d", msg,
+               ortp_log(level, "uPnP IGD: %s %s|%d->%d (retry %d)", msg,
                                                        (port->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP",
                                                                        port->external_port,
-                                                                       port->local_port);
+                                                                       port->local_port,
+                                                                       port->retry - 1);
        }
 }
 
index 08371f5155ede74f78cc0eb2f4520f88660e8fe1..11a7c275f9f569c8c1f7b7068f69c436dd9fb144 100644 (file)
@@ -278,6 +278,56 @@ public interface LinphoneCore {
                        return mValue;
                }
        }
+       
+       static public class UpnpState {
+               static private Vector<UpnpState> values = new Vector<UpnpState>();
+               /**
+                * Idle 
+                */
+               static public UpnpState Idle = new UpnpState(0, "Idle");
+               /**
+                * Pending
+                */
+               static public UpnpState Pending = new UpnpState(1, "Pending");
+               /**
+                * Adding
+                */
+               static public UpnpState Adding = new UpnpState(2, "Adding");
+               /**
+                * Removing
+                */
+               static public UpnpState Removing = new UpnpState(3, "Removing");
+               /**
+                * Not Available
+                */
+               static public UpnpState NotAvailable = new UpnpState(4, "Not available");
+               /**
+                * Ok
+                */
+               static public UpnpState Ok = new UpnpState(5, "Ok");
+               /**
+                * Ko 
+                */
+               static public UpnpState Ko = new UpnpState(6, "Ko");
+               protected final int mValue;
+               private final String mStringValue;
+
+               private UpnpState(int value, String stringValue) {
+                       mValue = value;
+                       values.addElement(this);
+                       mStringValue = stringValue;
+               }
+               public static UpnpState fromInt(int value) {
+                       for (int i = 0; i < values.size(); i++) {
+                               UpnpState mstate = (UpnpState) values.elementAt(i);
+                               if (mstate.mValue == value) return mstate;
+                       }
+                       throw new RuntimeException("UpnpState not found [" + value + "]");
+               }
+               public String toString() {
+                       return mStringValue;
+               }
+       }
 
        /**
         * Set the context of creation of the LinphoneCore.
@@ -882,4 +932,30 @@ public interface LinphoneCore {
         * the config file with your own sections
         */
        LpConfig getConfig();
+
+
+       /**
+        * Return the availability of uPnP.
+        *
+        * @return true if uPnP is available otherwise return false. 
+        */
+       public boolean upnpAvailable();
+
+       /**
+        * Return the internal state of uPnP. 
+        *
+        * @return an UpnpState. 
+        */
+       public UpnpState getUpnpState();
+
+       /**
+        * Return the external ip address of router. 
+        * In some cases the uPnP can have an external ip address but not a usable uPnP
+        * (state different of Ok). 
+        *
+        * @return a null terminated string containing the external ip address. If the
+        * the external ip address is not available return null. 
+        */
+       public String getUpnpExternalIpaddress();
+
 }
index 02e31f9a1bfa0566fa93036a41dbc1947c774c0d..2d42c8f550ed5727b5ea079b6ae6c25346f49c68 100644 (file)
@@ -872,4 +872,19 @@ class LinphoneCoreImpl implements LinphoneCore {
                long configPtr=getConfig(nativePtr);
                return new LpConfigImpl(configPtr);
        }
+       
+       private native boolean upnpAvailable(long ptr);
+       public boolean upnpAvailable() {
+               return upnpAvailable(nativePtr);
+       } 
+
+       private native int getUpnpState(long ptr);
+       public UpnpState getUpnpState() {
+               return UpnpState.fromInt(getUpnpState(nativePtr));      
+       }
+       
+       private native String getUpnpExternalIpaddress(long ptr);
+       public String getUpnpExternalIpaddress() {
+               return getUpnpExternalIpaddress(nativePtr);
+       }
 }