]>
Commit | Line | Data |
---|---|---|
8f092a22 TB |
1 | /* |
2 | * Copyright (C) 2012 Tobias Brunner | |
3 | * Hochschule fuer Technik Rapperswil | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation; either version 2 of the License, or (at your | |
8 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. * | |
9 | * This program is distributed in the hope that it will be useful, but | |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
11 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 | * for more details. | |
13 | */ | |
14 | ||
15 | #include "network_manager.h" | |
16 | ||
17 | #include "../android_jni.h" | |
ef3d1a1b | 18 | #include "../charonservice.h" |
f05b4272 | 19 | #include <utils/debug.h> |
ef3d1a1b | 20 | #include <threading/mutex.h> |
8f092a22 TB |
21 | |
22 | typedef struct private_network_manager_t private_network_manager_t; | |
23 | ||
24 | struct private_network_manager_t { | |
25 | ||
26 | /** | |
27 | * Public interface | |
28 | */ | |
29 | network_manager_t public; | |
30 | ||
31 | /** | |
32 | * Reference to NetworkManager object | |
33 | */ | |
34 | jobject obj; | |
35 | ||
36 | /** | |
37 | * Java class for NetworkManager | |
38 | */ | |
39 | jclass cls; | |
ef3d1a1b TB |
40 | |
41 | /** | |
42 | * Registered callback | |
43 | */ | |
44 | struct { | |
45 | connectivity_cb_t cb; | |
46 | void *data; | |
47 | } connectivity_cb; | |
48 | ||
49 | /** | |
50 | * Mutex to access callback | |
51 | */ | |
52 | mutex_t *mutex; | |
8f092a22 TB |
53 | }; |
54 | ||
55 | METHOD(network_manager_t, get_local_address, host_t*, | |
56 | private_network_manager_t *this, bool ipv4) | |
57 | { | |
58 | JNIEnv *env; | |
59 | jmethodID method_id; | |
60 | jstring jaddr; | |
61 | char *addr; | |
62 | host_t *host; | |
63 | ||
64 | androidjni_attach_thread(&env); | |
65 | method_id = (*env)->GetMethodID(env, this->cls, "getLocalAddress", | |
66 | "(Z)Ljava/lang/String;"); | |
67 | if (!method_id) | |
68 | { | |
69 | goto failed; | |
70 | } | |
71 | jaddr = (*env)->CallObjectMethod(env, this->obj, method_id, ipv4); | |
72 | if (!jaddr) | |
73 | { | |
74 | goto failed; | |
75 | } | |
76 | addr = androidjni_convert_jstring(env, jaddr); | |
77 | androidjni_detach_thread(); | |
78 | host = host_create_from_string(addr, 0); | |
79 | free(addr); | |
80 | return host; | |
81 | ||
82 | failed: | |
83 | androidjni_exception_occurred(env); | |
84 | androidjni_detach_thread(); | |
85 | return NULL; | |
86 | } | |
87 | ||
ef3d1a1b TB |
88 | JNI_METHOD(NetworkManager, networkChanged, void, |
89 | bool disconnected) | |
90 | { | |
91 | private_network_manager_t *nm; | |
92 | ||
93 | nm = (private_network_manager_t*)charonservice->get_network_manager( | |
94 | charonservice); | |
95 | nm->mutex->lock(nm->mutex); | |
96 | if (nm->connectivity_cb.cb) | |
97 | { | |
98 | nm->connectivity_cb.cb(nm->connectivity_cb.data, disconnected); | |
99 | } | |
100 | nm->mutex->unlock(nm->mutex); | |
101 | } | |
102 | ||
103 | METHOD(network_manager_t, add_connectivity_cb, void, | |
104 | private_network_manager_t *this, connectivity_cb_t cb, void *data) | |
105 | { | |
106 | this->mutex->lock(this->mutex); | |
107 | if (!this->connectivity_cb.cb) | |
108 | { | |
109 | JNIEnv *env; | |
110 | jmethodID method_id; | |
111 | ||
112 | androidjni_attach_thread(&env); | |
113 | method_id = (*env)->GetMethodID(env, this->cls, "Register", "()V"); | |
114 | if (!method_id) | |
115 | { | |
116 | androidjni_exception_occurred(env); | |
117 | } | |
118 | else | |
119 | { | |
120 | (*env)->CallVoidMethod(env, this->obj, method_id); | |
121 | if (!androidjni_exception_occurred(env)) | |
122 | { | |
123 | this->connectivity_cb.cb = cb; | |
124 | this->connectivity_cb.data = data; | |
125 | } | |
126 | androidjni_detach_thread(); | |
127 | } | |
128 | } | |
129 | this->mutex->unlock(this->mutex); | |
130 | } | |
131 | ||
132 | /** | |
133 | * Unregister the NetworkManager via JNI. | |
134 | * | |
135 | * this->mutex has to be locked | |
136 | */ | |
137 | static void unregister_network_manager(private_network_manager_t *this) | |
138 | { | |
139 | JNIEnv *env; | |
140 | jmethodID method_id; | |
141 | ||
142 | androidjni_attach_thread(&env); | |
143 | method_id = (*env)->GetMethodID(env, this->cls, "Unregister", "()V"); | |
144 | if (!method_id) | |
145 | { | |
146 | androidjni_exception_occurred(env); | |
147 | } | |
148 | else | |
149 | { | |
150 | (*env)->CallVoidMethod(env, this->obj, method_id); | |
151 | androidjni_exception_occurred(env); | |
152 | } | |
153 | androidjni_detach_thread(); | |
154 | } | |
155 | ||
156 | METHOD(network_manager_t, remove_connectivity_cb, void, | |
157 | private_network_manager_t *this, connectivity_cb_t cb) | |
158 | { | |
159 | this->mutex->lock(this->mutex); | |
160 | if (this->connectivity_cb.cb == cb) | |
161 | { | |
162 | this->connectivity_cb.cb = NULL; | |
163 | unregister_network_manager(this); | |
164 | } | |
165 | this->mutex->unlock(this->mutex); | |
166 | } | |
167 | ||
8f092a22 TB |
168 | METHOD(network_manager_t, destroy, void, |
169 | private_network_manager_t *this) | |
170 | { | |
171 | JNIEnv *env; | |
172 | ||
ef3d1a1b TB |
173 | this->mutex->lock(this->mutex); |
174 | if (this->connectivity_cb.cb) | |
175 | { | |
176 | this->connectivity_cb.cb = NULL; | |
177 | unregister_network_manager(this); | |
178 | } | |
179 | this->mutex->unlock(this->mutex); | |
180 | ||
8f092a22 TB |
181 | androidjni_attach_thread(&env); |
182 | if (this->obj) | |
183 | { | |
184 | (*env)->DeleteGlobalRef(env, this->obj); | |
185 | } | |
186 | if (this->cls) | |
187 | { | |
188 | (*env)->DeleteGlobalRef(env, this->cls); | |
189 | } | |
190 | androidjni_detach_thread(); | |
ef3d1a1b | 191 | this->mutex->destroy(this->mutex); |
8f092a22 TB |
192 | free(this); |
193 | } | |
194 | ||
195 | /* | |
196 | * Described in header. | |
197 | */ | |
ef3d1a1b | 198 | network_manager_t *network_manager_create(jobject context) |
8f092a22 TB |
199 | { |
200 | private_network_manager_t *this; | |
201 | JNIEnv *env; | |
202 | jmethodID method_id; | |
203 | jobject obj; | |
204 | jclass cls; | |
205 | ||
206 | INIT(this, | |
207 | .public = { | |
208 | .get_local_address = _get_local_address, | |
ef3d1a1b TB |
209 | .add_connectivity_cb = _add_connectivity_cb, |
210 | .remove_connectivity_cb = _remove_connectivity_cb, | |
8f092a22 TB |
211 | .destroy = _destroy, |
212 | }, | |
ef3d1a1b | 213 | .mutex = mutex_create(MUTEX_TYPE_DEFAULT), |
8f092a22 TB |
214 | ); |
215 | ||
216 | androidjni_attach_thread(&env); | |
217 | cls = (*env)->FindClass(env, JNI_PACKAGE_STRING "/NetworkManager"); | |
218 | if (!cls) | |
219 | { | |
220 | goto failed; | |
221 | } | |
222 | this->cls = (*env)->NewGlobalRef(env, cls); | |
223 | method_id = (*env)->GetMethodID(env, cls, "<init>", | |
ef3d1a1b | 224 | "(Landroid/content/Context;)V"); |
8f092a22 TB |
225 | if (!method_id) |
226 | { | |
227 | goto failed; | |
228 | } | |
ef3d1a1b | 229 | obj = (*env)->NewObject(env, cls, method_id, context); |
8f092a22 TB |
230 | if (!obj) |
231 | { | |
232 | goto failed; | |
233 | } | |
234 | this->obj = (*env)->NewGlobalRef(env, obj); | |
235 | androidjni_detach_thread(); | |
236 | return &this->public; | |
237 | ||
238 | failed: | |
239 | DBG1(DBG_KNL, "failed to build NetworkManager object"); | |
240 | androidjni_exception_occurred(env); | |
241 | androidjni_detach_thread(); | |
242 | destroy(this); | |
243 | return NULL; | |
244 | }; |