5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include <gweb/gweb.h>
33 #define STATUS_URL "http://www.connman.net/online/status.html"
35 struct connman_wispr_portal_context {
36 struct connman_service *service;
37 enum connman_ipconfig_type type;
39 /* Portal/WISPr common */
45 struct connman_wispr_portal {
46 struct connman_wispr_portal_context *ipv4_context;
47 struct connman_wispr_portal_context *ipv6_context;
50 static GHashTable *wispr_portal_list = NULL;
52 static void free_connman_wispr_portal_context(struct connman_wispr_portal_context *wp_context)
56 if (wp_context == NULL)
59 if (wp_context->token > 0)
60 connman_proxy_lookup_cancel(wp_context->token);
62 if (wp_context->request_id > 0)
63 g_web_cancel_request(wp_context->web, wp_context->request_id);
65 g_web_unref(wp_context->web);
70 static void free_connman_wispr_portal(gpointer data)
72 struct connman_wispr_portal *wispr_portal = data;
76 if (wispr_portal == NULL)
79 free_connman_wispr_portal_context(wispr_portal->ipv4_context);
80 free_connman_wispr_portal_context(wispr_portal->ipv6_context);
85 static void web_debug(const char *str, void *data)
87 connman_info("%s: %s\n", (const char *) data, str);
90 static void wispr_portal_error(struct connman_wispr_portal_context *wp_context)
92 DBG("Failed to proceed wispr/portal web request");
95 static void portal_manage_status(GWebResult *result,
96 struct connman_wispr_portal_context *wp_context)
98 const char *str = NULL;
102 /* We currently don't do anything with this info */
103 if (g_web_result_get_header(result, "X-ConnMan-Client-IP",
105 connman_info("Client-IP: %s", str);
107 if (g_web_result_get_header(result, "X-ConnMan-Client-Country",
109 connman_info("Client-Country: %s", str);
111 if (g_web_result_get_header(result, "X-ConnMan-Client-Region",
113 connman_info("Client-Region: %s", str);
115 __connman_service_ipconfig_indicate_state(wp_context->service,
116 CONNMAN_SERVICE_STATE_ONLINE,
120 static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data)
122 struct connman_wispr_portal_context *wp_context = user_data;
123 const char *redirect = NULL;
124 const char *str = NULL;
129 if (wp_context->request_id == 0)
132 status = g_web_result_get_status(result);
134 DBG("status: %03u", status);
138 if (g_web_result_get_header(result, "X-ConnMan-Status",
140 portal_manage_status(result, wp_context);
144 if (g_web_result_get_header(result, "Location",
148 DBG("Redirect URL: %s", redirect);
152 wispr_portal_error(wp_context);
159 wp_context->request_id = 0;
164 static void wispr_portal_request_portal(struct connman_wispr_portal_context *wp_context)
168 wp_context->request_id = g_web_request_get(wp_context->web,
169 STATUS_URL, wispr_portal_web_result, wp_context);
171 if (wp_context->request_id == 0)
172 wispr_portal_error(wp_context);
175 static void proxy_callback(const char *proxy, void *user_data)
177 struct connman_wispr_portal_context *wp_context = user_data;
179 DBG("proxy %s", proxy);
181 wp_context->token = 0;
184 proxy = getenv("http_proxy");
186 if (getenv("CONNMAN_WEB_DEBUG"))
187 g_web_set_debug(wp_context->web, web_debug, "WEB");
189 if (proxy != NULL && g_strcmp0(proxy, "DIRECT") != 0)
190 g_web_set_proxy(wp_context->web, proxy);
192 g_web_set_accept(wp_context->web, NULL);
193 g_web_set_user_agent(wp_context->web, "ConnMan/%s", VERSION);
194 g_web_set_close_connection(wp_context->web, TRUE);
196 wispr_portal_request_portal(wp_context);
199 static int wispr_portal_detect(struct connman_wispr_portal_context *wp_context)
201 enum connman_service_type service_type;
202 char *interface = NULL;
205 DBG("wispr/portal context %p", wp_context);
206 DBG("service %p", wp_context->service);
208 service_type = connman_service_get_type(wp_context->service);
210 switch (service_type) {
211 case CONNMAN_SERVICE_TYPE_ETHERNET:
212 case CONNMAN_SERVICE_TYPE_WIFI:
213 case CONNMAN_SERVICE_TYPE_WIMAX:
214 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
215 case CONNMAN_SERVICE_TYPE_CELLULAR:
217 case CONNMAN_SERVICE_TYPE_UNKNOWN:
218 case CONNMAN_SERVICE_TYPE_SYSTEM:
219 case CONNMAN_SERVICE_TYPE_GPS:
220 case CONNMAN_SERVICE_TYPE_VPN:
221 case CONNMAN_SERVICE_TYPE_GADGET:
225 interface = connman_service_get_interface(wp_context->service);
226 if (interface == NULL)
229 DBG("interface %s", interface);
231 wp_context->web = g_web_new(0);
232 if (wp_context->web == NULL) {
237 if (wp_context->type == CONNMAN_IPCONFIG_TYPE_IPV4)
238 g_web_set_address_family(wp_context->web, AF_INET);
240 g_web_set_address_family(wp_context->web, AF_INET6);
242 wp_context->token = connman_proxy_lookup(interface,
243 STATUS_URL, wp_context->service,
244 proxy_callback, wp_context);
245 if (wp_context->token == 0)
253 int __connman_wispr_start(struct connman_service *service,
254 enum connman_ipconfig_type type)
256 struct connman_wispr_portal_context *wp_context = NULL;
257 struct connman_wispr_portal *wispr_portal = NULL;
260 DBG("service %p", service);
262 if (wispr_portal_list == NULL)
265 index = __connman_service_get_index(service);
269 wispr_portal = g_hash_table_lookup(wispr_portal_list,
270 GINT_TO_POINTER(index));
271 if (wispr_portal == NULL) {
272 wispr_portal = g_try_new0(struct connman_wispr_portal, 1);
273 if (wispr_portal == NULL)
276 g_hash_table_replace(wispr_portal_list,
277 GINT_TO_POINTER(index), wispr_portal);
280 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
281 wp_context = wispr_portal->ipv4_context;
282 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
283 wp_context = wispr_portal->ipv6_context;
287 if (wp_context == NULL) {
288 wp_context = g_try_new0(struct connman_wispr_portal_context, 1);
289 if (wp_context == NULL)
292 wp_context->service = service;
293 wp_context->type = type;
295 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
296 wispr_portal->ipv4_context = wp_context;
298 wispr_portal->ipv6_context = wp_context;
300 return wispr_portal_detect(wp_context);
306 void __connman_wispr_stop(struct connman_service *service)
310 DBG("service %p", service);
312 if (wispr_portal_list == NULL)
315 index = __connman_service_get_index(service);
319 g_hash_table_remove(wispr_portal_list, GINT_TO_POINTER(index));
322 int __connman_wispr_init(void)
326 wispr_portal_list = g_hash_table_new_full(g_direct_hash,
327 g_direct_equal, NULL,
328 free_connman_wispr_portal);
333 void __connman_wispr_cleanup(void)
337 g_hash_table_destroy(wispr_portal_list);
338 wispr_portal_list = NULL;