Add parsing of initial WISPr response
[platform/upstream/connman.git] / tools / wispr.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <signal.h>
30
31 #include <gweb/gweb.h>
32
33 #define DEFAULT_URL  "http://www.connman.net/online/status.html"
34
35 static GTimer *timer;
36
37 static GMainLoop *main_loop;
38
39 static void web_debug(const char *str, void *data)
40 {
41         g_print("%s: %s\n", (const char *) data, str);
42 }
43
44 static void sig_term(int sig)
45 {
46         g_main_loop_quit(main_loop);
47 }
48
49 enum wispr_elements {
50         WISPR_NONE,
51         WISPR_ACCESS_PROCEDURE,
52         WISPR_ACCESS_LOCATION,
53         WISPR_LOCATION_NAME,
54         WISPR_LOGIN_URL,
55         WISPR_ABORT_LOGIN_URL,
56         WISPR_MESSAGE_TYPE,
57         WISPR_RESPONSE_CODE,
58         WISPR_NEXT_URL,
59         WISPR_DELAY,
60         WISPR_REPLY_MESSAGE,
61         WISPR_LOGIN_RESULTS_URL,
62         WISPR_LOGOFF_URL,
63 };
64
65 static enum wispr_elements current_element = WISPR_NONE;
66
67 static void start_element_handler(GMarkupParseContext *context,
68                                         const gchar *element_name,
69                                         const gchar **attribute_names,
70                                         const gchar **attribute_values,
71                                         gpointer user_data, GError **error)
72 {
73         if (g_str_equal(element_name, "AccessProcedure") == TRUE)
74                 current_element = WISPR_ACCESS_PROCEDURE;
75         else if (g_str_equal(element_name, "AccessLocation") == TRUE)
76                 current_element = WISPR_ACCESS_LOCATION;
77         else if (g_str_equal(element_name, "LocationName") == TRUE)
78                 current_element = WISPR_LOCATION_NAME;
79         else if (g_str_equal(element_name, "LoginURL") == TRUE)
80                 current_element = WISPR_LOGIN_URL;
81         else if (g_str_equal(element_name, "AbortLoginURL") == TRUE)
82                 current_element = WISPR_ABORT_LOGIN_URL;
83         else if (g_str_equal(element_name, "MessageType") == TRUE)
84                 current_element = WISPR_MESSAGE_TYPE;
85         else if (g_str_equal(element_name, "ResponseCode") == TRUE)
86                 current_element = WISPR_RESPONSE_CODE;
87         else if (g_str_equal(element_name, "NextURL") == TRUE)
88                 current_element = WISPR_NEXT_URL;
89         else if (g_str_equal(element_name, "Delay") == TRUE)
90                 current_element = WISPR_DELAY;
91         else if (g_str_equal(element_name, "ReplyMessage") == TRUE)
92                 current_element = WISPR_REPLY_MESSAGE;
93         else if (g_str_equal(element_name, "LoginResultsURL") == TRUE)
94                 current_element = WISPR_LOGIN_RESULTS_URL;
95         else if (g_str_equal(element_name, "LogoffURL") == TRUE)
96                 current_element = WISPR_LOGOFF_URL;
97 }
98
99 static void end_element_handler(GMarkupParseContext *context,
100                                         const gchar *element_name,
101                                         gpointer user_data, GError **error)
102 {
103         current_element = WISPR_NONE;
104 }
105
106 static void text_handler(GMarkupParseContext *context,
107                                         const gchar *text, gsize text_len,
108                                         gpointer user_data, GError **error)
109 {
110         int value;
111
112         switch (current_element) {
113         case WISPR_NONE:
114                 break;
115         case WISPR_ACCESS_PROCEDURE:
116                 printf("Access procedure: %s\n", text);
117                 break;
118         case WISPR_ACCESS_LOCATION:
119                 printf("Access location: %s\n", text);
120                 break;
121         case WISPR_LOCATION_NAME:
122                 printf("Location name: %s\n", text);
123                 break;
124         case WISPR_LOGIN_URL:
125                 printf("Login URL: %s\n", text);
126                 break;
127         case WISPR_ABORT_LOGIN_URL:
128                 printf("Abort login URL: %s\n", text);
129                 break;
130         case WISPR_MESSAGE_TYPE:
131                 value = atoi(text);
132                 printf("Message type: %d\n", value);
133                 switch (value) {
134                 case 100:
135                         printf("  Initial redirect message\n");
136                         break;
137                 case 110:
138                         printf("  Proxy notification\n");
139                         break;
140                 case 120:
141                         printf("  Authentication notification\n");
142                         break;
143                 case 130:
144                         printf("  Logoff notification\n");
145                         break;
146                 case 140:
147                         printf("  Response to Authentication Poll\n");
148                         break;
149                 case 150:
150                         printf("  Response to Abort Login\n");
151                         break;
152                 }
153                 break;
154         case WISPR_RESPONSE_CODE:
155                 value = atoi(text);
156                 printf("Response code: %d\n", value);
157                 switch (value) {
158                 case 0:
159                         printf("  No error\n");
160                         break;
161                 case 50:
162                         printf("  Login succeeded (Access ACCEPT)\n");
163                         break;
164                 case 100:
165                         printf("  Login failed (Access REJECT)\n");
166                         break;
167                 case 102:
168                         printf("  RADIUS server error/timeout\n");
169                         break;
170                 case 105:
171                         printf("  RADIUS server not enabled\n");
172                         break;
173                 case 150:
174                         printf("  Logoff succeeded\n");
175                         break;
176                 case 151:
177                         printf("  Login aborted\n");
178                         break;
179                 case 200:
180                         printf("  Proxy detection/repeat operation\n");
181                         break;
182                 case 201:
183                         printf("  Authentication pending\n");
184                         break;
185                 case 255:
186                         printf("  Access gateway internal error\n");
187                         break;
188                 }
189                 break;
190         case WISPR_NEXT_URL:
191                 printf("Next URL: %s\n", text);
192                 break;
193         case WISPR_DELAY:
194                 value = atoi(text);
195                 printf("Delay: %d seconds\n", value);
196                 break;
197         case WISPR_REPLY_MESSAGE:
198                 printf("Reply message: %s\n", text);
199                 break;
200         case WISPR_LOGIN_RESULTS_URL:
201                 printf("Login results URL: %s\n", text);
202                 break;
203         case WISPR_LOGOFF_URL:
204                 printf("Logoff URL: %s\n", text);
205                 break;
206         }
207 }
208
209 static void error_handler(GMarkupParseContext *context,
210                                         GError *error, gpointer user_data)
211 {
212         printf("%s\n", error->message);
213 }
214
215 static const GMarkupParser wispr_parser = {
216         start_element_handler,
217         end_element_handler,
218         text_handler,
219         NULL,
220         error_handler,
221 };
222
223 static void parser_callback(const char *str, gpointer user_data)
224 {
225         GMarkupParseContext *context;
226         gboolean result;
227
228         //printf("%s\n", str);
229
230         context = g_markup_parse_context_new(&wispr_parser,
231                                 G_MARKUP_TREAT_CDATA_AS_TEXT, NULL, NULL);
232
233         result = g_markup_parse_context_parse(context, str, strlen(str), NULL);
234
235         result = g_markup_parse_context_end_parse(context, NULL);
236
237         g_markup_parse_context_free(context);
238 }
239
240 static guint request_id;
241 static GWebParser *request_parser;
242
243 static void web_result(guint16 status, GWebResult *result, gpointer user_data)
244 {
245         const guint8 *chunk;
246         gsize length;
247         gdouble elapsed;
248
249         status = g_web_result_get_status(result);
250         if (status == 200)
251                 goto done;
252
253         g_web_result_get_chunk(result, &chunk, &length);
254
255         if (length > 0) {
256                 //printf("%s\n", (char *) chunk);
257                 g_web_parser_feed_data(request_parser, chunk, length);
258                 return;
259         }
260
261         g_web_parser_end_data(request_parser);
262
263 done:
264         g_print("status: %03u\n", status);
265
266         elapsed = g_timer_elapsed(timer, NULL);
267
268         g_print("elapse: %f seconds\n", elapsed);
269
270         g_main_loop_quit(main_loop);
271 }
272
273 static gboolean option_debug = FALSE;
274 static gchar *option_nameserver = NULL;
275 static gchar *option_url = NULL;
276
277 static GOptionEntry options[] = {
278         { "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug,
279                                         "Enable debug output" },
280         { "nameserver", 'n', 0, G_OPTION_ARG_STRING, &option_nameserver,
281                                         "Specify nameserver", "ADDRESS" },
282         { "url", 'u', 0, G_OPTION_ARG_STRING, &option_url,
283                                         "Specify arbitrary request", "URL" },
284         { NULL },
285 };
286
287 int main(int argc, char *argv[])
288 {
289         GOptionContext *context;
290         GError *error = NULL;
291         struct sigaction sa;
292         GWeb *web;
293         int index = 0;
294
295         context = g_option_context_new(NULL);
296         g_option_context_add_main_entries(context, options, NULL);
297
298         if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) {
299                 if (error != NULL) {
300                         g_printerr("%s\n", error->message);
301                         g_error_free(error);
302                 } else
303                         g_printerr("An unknown error occurred\n");
304                 return 1;
305         }
306
307         g_option_context_free(context);
308
309         web = g_web_new(index);
310         if (web == NULL) {
311                 fprintf(stderr, "Failed to create web service\n");
312                 return 1;
313         }
314
315         if (option_debug == TRUE)
316                 g_web_set_debug(web, web_debug, "WEB");
317
318         main_loop = g_main_loop_new(NULL, FALSE);
319
320         if (option_nameserver != NULL) {
321                 g_web_add_nameserver(web, option_nameserver);
322                 g_free(option_nameserver);
323         }
324
325         g_web_set_accept(web, NULL);
326         g_web_set_user_agent(web, "SmartClient/%s wispr", VERSION);
327         g_web_set_close_connection(web, TRUE);
328
329         if (option_url == NULL)
330                 option_url = g_strdup(DEFAULT_URL);
331
332         timer = g_timer_new();
333
334         request_parser = g_web_parser_new("<WISPAccessGatewayParam",
335                                                 "WISPAccessGatewayParam>",
336                                                 parser_callback, NULL);
337
338         g_web_parser_ref(request_parser);
339         g_web_parser_unref(request_parser);
340
341         request_id = g_web_request(web, G_WEB_METHOD_GET, option_url,
342                                                         web_result, NULL);
343
344         g_free(option_url);
345
346         if (request_id == 0) {
347                 fprintf(stderr, "Failed to start request\n");
348                 return 1;
349         }
350
351         memset(&sa, 0, sizeof(sa));
352         sa.sa_handler = sig_term;
353         sigaction(SIGINT, &sa, NULL);
354         sigaction(SIGTERM, &sa, NULL);
355
356         g_main_loop_run(main_loop);
357
358         g_timer_destroy(timer);
359
360         g_web_unref(web);
361
362         g_main_loop_unref(main_loop);
363
364         return 0;
365 }