Function added that allows to update VPN state via JNI
authorTobias Brunner <tobias@strongswan.org>
Wed, 8 Aug 2012 10:31:58 +0000 (12:31 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 13 Aug 2012 09:00:28 +0000 (11:00 +0200)
src/frontends/android/jni/libandroidbridge/charonservice.c
src/frontends/android/jni/libandroidbridge/charonservice.h
src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java

index 974875e..874258b 100644 (file)
@@ -90,6 +90,30 @@ static void dbg_android(debug_t group, level_t level, char *fmt, ...)
        }
 }
 
        }
 }
 
+METHOD(charonservice_t, update_status, bool,
+       private_charonservice_t *this, android_vpn_state_t code)
+{
+       JNIEnv *env;
+       jmethodID method_id;
+       bool success = FALSE;
+
+       androidjni_attach_thread(&env);
+
+       method_id = (*env)->GetMethodID(env, android_charonvpnservice_class,
+                                                                       "updateStatus", "(I)V");
+       if (!method_id)
+       {
+               goto failed;
+       }
+       (*env)->CallVoidMethod(env, this->vpn_service, method_id, (jint)code);
+       success = !androidjni_exception_occurred(env);
+
+failed:
+       androidjni_exception_occurred(env);
+       androidjni_detach_thread();
+       return success;
+}
+
 METHOD(charonservice_t, bypass_socket, bool,
        private_charonservice_t *this, int fd, int family)
 {
 METHOD(charonservice_t, bypass_socket, bool,
        private_charonservice_t *this, int fd, int family)
 {
@@ -133,6 +157,7 @@ static void charonservice_init(JNIEnv *env, jobject service)
 
        INIT(this,
                .public = {
 
        INIT(this,
                .public = {
+                       .update_status = _update_status,
                        .bypass_socket = _bypass_socket,
                },
                .vpn_service = (*env)->NewGlobalRef(env, service),
                        .bypass_socket = _bypass_socket,
                },
                .vpn_service = (*env)->NewGlobalRef(env, service),
index 8bacd0a..c537165 100644 (file)
 
 #include <library.h>
 
 
 #include <library.h>
 
+typedef enum android_vpn_state_t android_vpn_state_t;
 typedef struct charonservice_t charonservice_t;
 
 /**
 typedef struct charonservice_t charonservice_t;
 
 /**
+ * VPN status codes. As defined in CharonVpnService.java
+ */
+enum android_vpn_state_t {
+       CHARONSERVICE_CHILD_STATE_UP = 1,
+       CHARONSERVICE_CHILD_STATE_DOWN,
+       CHARONSERVICE_AUTH_ERROR,
+       CHARONSERVICE_PEER_AUTH_ERROR,
+       CHARONSERVICE_LOOKUP_ERROR,
+       CHARONSERVICE_UNREACHABLE_ERROR,
+       CHARONSERVICE_GENERIC_ERROR,
+};
+
+/**
  * Public interface of charonservice.
  *
  * Used to communicate with CharonVpnService via JNI
  * Public interface of charonservice.
  *
  * Used to communicate with CharonVpnService via JNI
@@ -40,6 +54,14 @@ typedef struct charonservice_t charonservice_t;
 struct charonservice_t {
 
        /**
 struct charonservice_t {
 
        /**
+        * Update the status in the Java domain (UI)
+        *
+        * @param code                  status code
+        * @return                              TRUE on success
+        */
+       bool (*update_status)(charonservice_t *this, android_vpn_state_t code);
+
+       /**
         * Install a bypass policy for the given socket using the protect() Method
         * of the Android VpnService interface
         *
         * Install a bypass policy for the given socket using the protect() Method
         * of the Android VpnService interface
         *
index 083b98c..c3bb1ad 100644 (file)
@@ -64,6 +64,17 @@ public class CharonVpnService extends VpnService implements Runnable
                }
        };
 
                }
        };
 
+       /**
+        * as defined in charonservice.h
+        */
+       static final int STATE_CHILD_SA_UP = 1;
+       static final int STATE_CHILD_SA_DOWN = 2;
+       static final int STATE_AUTH_ERROR = 3;
+       static final int STATE_PEER_AUTH_ERROR = 4;
+       static final int STATE_LOOKUP_ERROR = 5;
+       static final int STATE_UNREACHABLE_ERROR = 6;
+       static final int STATE_GENERIC_ERROR = 7;
+
        @Override
        public int onStartCommand(Intent intent, int flags, int startId)
        {
        @Override
        public int onStartCommand(Intent intent, int flags, int startId)
        {
@@ -254,6 +265,70 @@ public class CharonVpnService extends VpnService implements Runnable
        }
 
        /**
        }
 
        /**
+        * Set an error on the state service and disconnect the current connection.
+        * This is not done by calling stopCurrentConnection() above, but instead
+        * is done asynchronously via state service.
+        *
+        * @param error error state
+        */
+       private void setErrorDisconnect(ErrorState error)
+       {
+               synchronized (mServiceLock)
+               {
+                       if (mService != null)
+                       {
+                               mService.setError(error);
+                               mService.disconnect();
+                       }
+               }
+       }
+
+       /**
+        * Updates the state of the current connection.
+        * Called via JNI by different threads (but not concurrently).
+        *
+        * @param status new state
+        */
+       public void updateStatus(int status)
+       {
+               switch (status)
+               {
+                       case STATE_CHILD_SA_DOWN:
+                               synchronized (mServiceLock)
+                               {
+                                       /* since this state is also reached when the SA is closed remotely,
+                                        * we call disconnect() to make sure charon is properly deinitialized */
+                                       if (mService != null)
+                                       {
+                                               mService.disconnect();
+                                       }
+                               }
+                               break;
+                       case STATE_CHILD_SA_UP:
+                               setState(State.CONNECTED);
+                               break;
+                       case STATE_AUTH_ERROR:
+                               setErrorDisconnect(ErrorState.AUTH_FAILED);
+                               break;
+                       case STATE_PEER_AUTH_ERROR:
+                               setErrorDisconnect(ErrorState.PEER_AUTH_FAILED);
+                               break;
+                       case STATE_LOOKUP_ERROR:
+                               setErrorDisconnect(ErrorState.LOOKUP_FAILED);
+                               break;
+                       case STATE_UNREACHABLE_ERROR:
+                               setErrorDisconnect(ErrorState.UNREACHABLE);
+                               break;
+                       case STATE_GENERIC_ERROR:
+                               setErrorDisconnect(ErrorState.GENERIC_ERROR);
+                               break;
+                       default:
+                               Log.e(TAG, "Unknown status code received");
+                               break;
+               }
+       }
+
+       /**
         * Initialization of charon, provided by libandroidbridge.so
         */
        public native void initializeCharon();
         * Initialization of charon, provided by libandroidbridge.so
         */
        public native void initializeCharon();