Keep a global reference to the CharonVpnService object in charonservice
[strongswan.git] / src / frontends / android / jni / libandroidbridge / charonservice.c
1 /*
2 * Copyright (C) 2012 Giuliano Grassi
3 * Copyright (C) 2012 Ralf Sager
4 * Copyright (C) 2012 Tobias Brunner
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include <signal.h>
19 #include <string.h>
20 #include <android/log.h>
21
22 #include "charonservice.h"
23 #include "android_jni.h"
24
25 #include <daemon.h>
26 #include <hydra.h>
27 #include <ipsec.h>
28 #include <library.h>
29 #include <threading/thread.h>
30
31 #define ANDROID_DEBUG_LEVEL 1
32
33 typedef struct private_charonservice_t private_charonservice_t;
34
35 /**
36 * private data of charonservice
37 */
38 struct private_charonservice_t {
39
40 /**
41 * public interface
42 */
43 charonservice_t public;
44
45 /**
46 * CharonVpnService reference
47 */
48 jobject vpn_service;
49 };
50
51 /**
52 * Single instance of charonservice_t.
53 */
54 charonservice_t *charonservice;
55
56 /**
57 * hook in library for debugging messages
58 */
59 extern void (*dbg)(debug_t group, level_t level, char *fmt, ...);
60
61 /**
62 * Logging hook for library logs, using android specific logging
63 */
64 static void dbg_android(debug_t group, level_t level, char *fmt, ...)
65 {
66 va_list args;
67
68 if (level <= ANDROID_DEBUG_LEVEL)
69 {
70 char sgroup[16], buffer[8192];
71 char *current = buffer, *next;
72
73 snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group);
74 va_start(args, fmt);
75 vsnprintf(buffer, sizeof(buffer), fmt, args);
76 va_end(args);
77 while (current)
78 { /* log each line separately */
79 next = strchr(current, '\n');
80 if (next)
81 {
82 *(next++) = '\0';
83 }
84 __android_log_print(ANDROID_LOG_INFO, "charon", "00[%s] %s\n",
85 sgroup, current);
86 current = next;
87 }
88 }
89 }
90
91 /**
92 * Initialize the charonservice object
93 */
94 static void charonservice_init(JNIEnv *env, jobject service)
95 {
96 private_charonservice_t *this;
97
98 INIT(this,
99 .public = {
100 },
101 .vpn_service = (*env)->NewGlobalRef(env, service),
102 );
103 charonservice = &this->public;
104
105 lib->settings->set_int(lib->settings,
106 "charon.plugins.android_log.loglevel", ANDROID_DEBUG_LEVEL);
107 }
108
109 /**
110 * Deinitialize the charonservice object
111 */
112 static void charonservice_deinit(JNIEnv *env)
113 {
114 private_charonservice_t *this = (private_charonservice_t*)charonservice;
115
116 (*env)->DeleteGlobalRef(env, this->vpn_service);
117 free(this);
118 charonservice = NULL;
119 }
120
121 /**
122 * Handle SIGSEGV/SIGILL signals raised by threads
123 */
124 static void segv_handler(int signal)
125 {
126 dbg_android(DBG_DMN, 1, "thread %u received %d", thread_current_id(),
127 signal);
128 exit(1);
129 }
130
131 /**
132 * Initialize charon and the libraries via JNI
133 */
134 JNI_METHOD(CharonVpnService, initializeCharon, void)
135 {
136 struct sigaction action;
137
138 /* logging for library during initialization, as we have no bus yet */
139 dbg = dbg_android;
140
141 /* initialize library */
142 if (!library_init(NULL))
143 {
144 library_deinit();
145 return;
146 }
147
148 if (!libhydra_init("charon"))
149 {
150 libhydra_deinit();
151 library_deinit();
152 return;
153 }
154
155 if (!libipsec_init())
156 {
157 libipsec_deinit();
158 libhydra_deinit();
159 library_deinit();
160 return;
161 }
162
163 charonservice_init(env, this);
164
165 if (!libcharon_init("charon") ||
166 !charon->initialize(charon, PLUGINS))
167 {
168 libcharon_deinit();
169 charonservice_deinit(env);
170 libipsec_deinit();
171 libhydra_deinit();
172 library_deinit();
173 return;
174 }
175
176 /* add handler for SEGV and ILL etc. */
177 action.sa_handler = segv_handler;
178 action.sa_flags = 0;
179 sigemptyset(&action.sa_mask);
180 sigaction(SIGSEGV, &action, NULL);
181 sigaction(SIGILL, &action, NULL);
182 sigaction(SIGBUS, &action, NULL);
183 action.sa_handler = SIG_IGN;
184 sigaction(SIGPIPE, &action, NULL);
185
186 /* start daemon (i.e. the threads in the thread-pool) */
187 charon->start(charon);
188 }
189
190 /**
191 * Deinitialize charon and all libraries
192 */
193 JNI_METHOD(CharonVpnService, deinitializeCharon, void)
194 {
195 libcharon_deinit();
196 charonservice_deinit(env);
197 libipsec_deinit();
198 libhydra_deinit();
199 library_deinit();
200 }
201