1281681Srpaulo/*
2281681Srpaulo * Hotspot 2.0 client - Web browser using system browser
3281681Srpaulo * Copyright (c) 2013, Qualcomm Atheros, Inc.
4281681Srpaulo *
5281681Srpaulo * This software may be distributed under the terms of the BSD license.
6281681Srpaulo * See README for more details.
7281681Srpaulo */
8281681Srpaulo
9281681Srpaulo#include "includes.h"
10281681Srpaulo
11281681Srpaulo#include "common.h"
12281681Srpaulo#include "utils/eloop.h"
13281681Srpaulo#include "wps/http_server.h"
14281681Srpaulo#include "browser.h"
15281681Srpaulo
16281681Srpaulo
17281681Srpaulostruct browser_data {
18281681Srpaulo	int success;
19281681Srpaulo};
20281681Srpaulo
21281681Srpaulo
22281681Srpaulostatic void browser_timeout(void *eloop_data, void *user_ctx)
23281681Srpaulo{
24281681Srpaulo	wpa_printf(MSG_INFO, "Timeout on waiting browser interaction to "
25281681Srpaulo		   "complete");
26281681Srpaulo	eloop_terminate();
27281681Srpaulo}
28281681Srpaulo
29281681Srpaulo
30281681Srpaulostatic void http_req(void *ctx, struct http_request *req)
31281681Srpaulo{
32281681Srpaulo	struct browser_data *data = ctx;
33281681Srpaulo	struct wpabuf *resp;
34281681Srpaulo	const char *url;
35281681Srpaulo	int done = 0;
36281681Srpaulo
37281681Srpaulo	url = http_request_get_uri(req);
38281681Srpaulo	wpa_printf(MSG_INFO, "Browser response received: %s", url);
39281681Srpaulo
40281681Srpaulo	if (os_strcmp(url, "/") == 0) {
41281681Srpaulo		data->success = 1;
42281681Srpaulo		done = 1;
43281681Srpaulo	} else if (os_strncmp(url, "/osu/", 5) == 0) {
44281681Srpaulo		data->success = atoi(url + 5);
45281681Srpaulo		done = 1;
46281681Srpaulo	}
47281681Srpaulo
48281681Srpaulo	resp = wpabuf_alloc(1);
49281681Srpaulo	if (resp == NULL) {
50281681Srpaulo		http_request_deinit(req);
51281681Srpaulo		if (done)
52281681Srpaulo			eloop_terminate();
53281681Srpaulo		return;
54281681Srpaulo	}
55281681Srpaulo
56281681Srpaulo	if (done) {
57281681Srpaulo		eloop_cancel_timeout(browser_timeout, NULL, NULL);
58281681Srpaulo		eloop_register_timeout(0, 500000, browser_timeout, &data, NULL);
59281681Srpaulo	}
60281681Srpaulo
61281681Srpaulo	http_request_send_and_deinit(req, resp);
62281681Srpaulo}
63281681Srpaulo
64281681Srpaulo
65281681Srpauloint hs20_web_browser(const char *url)
66281681Srpaulo{
67281681Srpaulo	struct http_server *http;
68281681Srpaulo	struct in_addr addr;
69281681Srpaulo	struct browser_data data;
70281681Srpaulo	pid_t pid;
71281681Srpaulo
72281681Srpaulo	wpa_printf(MSG_INFO, "Launching system browser to %s", url);
73281681Srpaulo
74281681Srpaulo	os_memset(&data, 0, sizeof(data));
75281681Srpaulo
76281681Srpaulo	if (eloop_init() < 0) {
77281681Srpaulo		wpa_printf(MSG_ERROR, "eloop_init failed");
78281681Srpaulo		return -1;
79281681Srpaulo	}
80281681Srpaulo	addr.s_addr = htonl((127 << 24) | 1);
81281681Srpaulo	http = http_server_init(&addr, 12345, http_req, &data);
82281681Srpaulo	if (http == NULL) {
83281681Srpaulo		wpa_printf(MSG_ERROR, "http_server_init failed");
84281681Srpaulo		eloop_destroy();
85281681Srpaulo		return -1;
86281681Srpaulo	}
87281681Srpaulo
88281681Srpaulo	pid = fork();
89281681Srpaulo	if (pid < 0) {
90281681Srpaulo		wpa_printf(MSG_ERROR, "fork: %s", strerror(errno));
91281681Srpaulo		http_server_deinit(http);
92281681Srpaulo		eloop_destroy();
93281681Srpaulo		return -1;
94281681Srpaulo	}
95281681Srpaulo
96281681Srpaulo	if (pid == 0) {
97281681Srpaulo		/* run the external command in the child process */
98281681Srpaulo		char *argv[3];
99281681Srpaulo
100281681Srpaulo		argv[0] = "browser-system";
101281681Srpaulo		argv[1] = (void *) url;
102281681Srpaulo		argv[2] = NULL;
103281681Srpaulo
104281681Srpaulo		execv("/usr/bin/x-www-browser", argv);
105281681Srpaulo		wpa_printf(MSG_ERROR, "execv: %s", strerror(errno));
106281681Srpaulo		exit(0);
107281681Srpaulo		return -1;
108281681Srpaulo	}
109281681Srpaulo
110281681Srpaulo	eloop_register_timeout(120, 0, browser_timeout, &data, NULL);
111281681Srpaulo	eloop_run();
112281681Srpaulo	eloop_cancel_timeout(browser_timeout, &data, NULL);
113281681Srpaulo	http_server_deinit(http);
114281681Srpaulo	eloop_destroy();
115281681Srpaulo
116281681Srpaulo	/* TODO: Close browser */
117281681Srpaulo
118281681Srpaulo	return data.success;
119281681Srpaulo}
120