Add support for decoding WISPr page elements
[framework/connectivity/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_pages {
50         WISPR_PAGE_NONE,
51         WISPR_PAGE_REDIRECT,
52         WISPR_PAGE_PROXY,
53         WISPR_PAGE_AUTHENTICATION_REPLY,
54         WISPR_PAGE_AUTHENTICATION_POLL_REPLY,
55         WISPR_PAGE_LOGOFF_REPLY,
56         WISPR_PAGE_ABORT_LOGIN_REPLY,
57 };
58
59 enum wispr_elements {
60         WISPR_NONE,
61         WISPR_ACCESS_PROCEDURE,
62         WISPR_ACCESS_LOCATION,
63         WISPR_LOCATION_NAME,
64         WISPR_LOGIN_URL,
65         WISPR_ABORT_LOGIN_URL,
66         WISPR_MESSAGE_TYPE,
67         WISPR_RESPONSE_CODE,
68         WISPR_NEXT_URL,
69         WISPR_DELAY,
70         WISPR_REPLY_MESSAGE,
71         WISPR_LOGIN_RESULTS_URL,
72         WISPR_LOGOFF_URL,
73 };
74
75 static enum wispr_pages current_page = WISPR_NONE;
76 static enum wispr_elements current_element = WISPR_NONE;
77
78 static void start_element_handler(GMarkupParseContext *context,
79                                         const gchar *element_name,
80                                         const gchar **attribute_names,
81                                         const gchar **attribute_values,
82                                         gpointer user_data, GError **error)
83 {
84         if (g_str_equal(element_name, "Redirect") == TRUE)
85                 current_page = WISPR_PAGE_REDIRECT;
86         else if (g_str_equal(element_name, "Proxy") == TRUE)
87                 current_page = WISPR_PAGE_PROXY;
88         else if (g_str_equal(element_name, "AuthenticationReply") == TRUE)
89                 current_page = WISPR_PAGE_AUTHENTICATION_REPLY;
90         else if (g_str_equal(element_name, "AuthenticationPollReply") == TRUE)
91                 current_page = WISPR_PAGE_AUTHENTICATION_POLL_REPLY;
92         else if (g_str_equal(element_name, "LogoffReply") == TRUE)
93                 current_page = WISPR_PAGE_LOGOFF_REPLY;
94         else if (g_str_equal(element_name, "AbortLoginReply") == TRUE)
95                 current_page = WISPR_PAGE_ABORT_LOGIN_REPLY;
96         else
97                 current_page = WISPR_PAGE_NONE;
98
99         if (g_str_equal(element_name, "AccessProcedure") == TRUE)
100                 current_element = WISPR_ACCESS_PROCEDURE;
101         else if (g_str_equal(element_name, "AccessLocation") == TRUE)
102                 current_element = WISPR_ACCESS_LOCATION;
103         else if (g_str_equal(element_name, "LocationName") == TRUE)
104                 current_element = WISPR_LOCATION_NAME;
105         else if (g_str_equal(element_name, "LoginURL") == TRUE)
106                 current_element = WISPR_LOGIN_URL;
107         else if (g_str_equal(element_name, "AbortLoginURL") == TRUE)
108                 current_element = WISPR_ABORT_LOGIN_URL;
109         else if (g_str_equal(element_name, "MessageType") == TRUE)
110                 current_element = WISPR_MESSAGE_TYPE;
111         else if (g_str_equal(element_name, "ResponseCode") == TRUE)
112                 current_element = WISPR_RESPONSE_CODE;
113         else if (g_str_equal(element_name, "NextURL") == TRUE)
114                 current_element = WISPR_NEXT_URL;
115         else if (g_str_equal(element_name, "Delay") == TRUE)
116                 current_element = WISPR_DELAY;
117         else if (g_str_equal(element_name, "ReplyMessage") == TRUE)
118                 current_element = WISPR_REPLY_MESSAGE;
119         else if (g_str_equal(element_name, "LoginResultsURL") == TRUE)
120                 current_element = WISPR_LOGIN_RESULTS_URL;
121         else if (g_str_equal(element_name, "LogoffURL") == TRUE)
122                 current_element = WISPR_LOGOFF_URL;
123         else
124                 current_element = WISPR_NONE;
125 }
126
127 static void end_element_handler(GMarkupParseContext *context,
128                                         const gchar *element_name,
129                                         gpointer user_data, GError **error)
130 {
131         current_page = WISPR_PAGE_NONE;
132
133         current_element = WISPR_NONE;
134 }
135
136 static void text_handler(GMarkupParseContext *context,
137                                         const gchar *text, gsize text_len,
138                                         gpointer user_data, GError **error)
139 {
140         int value;
141
142         switch (current_page) {
143         case WISPR_PAGE_NONE:
144                 break;
145         case WISPR_PAGE_REDIRECT:
146                 printf("[ Redirect ]\n");
147                 break;
148         case WISPR_PAGE_PROXY:
149                 printf("[ Proxy ]\n");
150                 break;
151         case WISPR_PAGE_AUTHENTICATION_REPLY:
152                 printf("[ Authentication reply ]\n");
153                 break;
154         case WISPR_PAGE_AUTHENTICATION_POLL_REPLY:
155                 printf("[ Authentication poll reply ]\n");
156                 break;
157         case WISPR_PAGE_LOGOFF_REPLY:
158                 printf("[ Logoff reply ]\n");
159                 break;
160         case WISPR_PAGE_ABORT_LOGIN_REPLY:
161                 printf("[ Abort login reply ]\n");
162                 break;
163         }
164
165         switch (current_element) {
166         case WISPR_NONE:
167                 break;
168         case WISPR_ACCESS_PROCEDURE:
169                 printf("Access procedure: %s\n", text);
170                 break;
171         case WISPR_ACCESS_LOCATION:
172                 printf("Access location: %s\n", text);
173                 break;
174         case WISPR_LOCATION_NAME:
175                 printf("Location name: %s\n", text);
176                 break;
177         case WISPR_LOGIN_URL:
178                 printf("Login URL: %s\n", text);
179                 break;
180         case WISPR_ABORT_LOGIN_URL:
181                 printf("Abort login URL: %s\n", text);
182                 break;
183         case WISPR_MESSAGE_TYPE:
184                 value = atoi(text);
185                 printf("Message type: %d\n", value);
186                 switch (value) {
187                 case 100:
188                         printf("  Initial redirect message\n");
189                         break;
190                 case 110:
191                         printf("  Proxy notification\n");
192                         break;
193                 case 120:
194                         printf("  Authentication notification\n");
195                         break;
196                 case 130:
197                         printf("  Logoff notification\n");
198                         break;
199                 case 140:
200                         printf("  Response to Authentication Poll\n");
201                         break;
202                 case 150:
203                         printf("  Response to Abort Login\n");
204                         break;
205                 }
206                 break;
207         case WISPR_RESPONSE_CODE:
208                 value = atoi(text);
209                 printf("Response code: %d\n", value);
210                 switch (value) {
211                 case 0:
212                         printf("  No error\n");
213                         break;
214                 case 50:
215                         printf("  Login succeeded (Access ACCEPT)\n");
216                         break;
217                 case 100:
218                         printf("  Login failed (Access REJECT)\n");
219                         break;
220                 case 102:
221                         printf("  RADIUS server error/timeout\n");
222                         break;
223                 case 105:
224                         printf("  RADIUS server not enabled\n");
225                         break;
226                 case 150:
227                         printf("  Logoff succeeded\n");
228                         break;
229                 case 151:
230                         printf("  Login aborted\n");
231                         break;
232                 case 200:
233                         printf("  Proxy detection/repeat operation\n");
234                         break;
235                 case 201:
236                         printf("  Authentication pending\n");
237                         break;
238                 case 255:
239                         printf("  Access gateway internal error\n");
240                         break;
241                 }
242                 break;
243         case WISPR_NEXT_URL:
244                 printf("Next URL: %s\n", text);
245                 break;
246         case WISPR_DELAY:
247                 value = atoi(text);
248                 printf("Delay: %d seconds\n", value);
249                 break;
250         case WISPR_REPLY_MESSAGE:
251                 printf("Reply message: %s\n", text);
252                 break;
253         case WISPR_LOGIN_RESULTS_URL:
254                 printf("Login results URL: %s\n", text);
255                 break;
256         case WISPR_LOGOFF_URL:
257                 printf("Logoff URL: %s\n", text);
258                 break;
259         }
260 }
261
262 static void error_handler(GMarkupParseContext *context,
263                                         GError *error, gpointer user_data)
264 {
265         printf("%s\n", error->message);
266 }
267
268 static const GMarkupParser wispr_parser = {
269         start_element_handler,
270         end_element_handler,
271         text_handler,
272         NULL,
273         error_handler,
274 };
275
276 static void parser_callback(const char *str, gpointer user_data)
277 {
278         GMarkupParseContext *context;
279         gboolean result;
280
281         //printf("%s\n", str);
282
283         context = g_markup_parse_context_new(&wispr_parser,
284                                 G_MARKUP_TREAT_CDATA_AS_TEXT, NULL, NULL);
285
286         result = g_markup_parse_context_parse(context, str, strlen(str), NULL);
287
288         result = g_markup_parse_context_end_parse(context, NULL);
289
290         g_markup_parse_context_free(context);
291 }
292
293 static guint request_id;
294 static GWebParser *request_parser;
295
296 static gboolean web_result(GWebResult *result, gpointer user_data)
297 {
298         const guint8 *chunk;
299         gsize length;
300         guint16 status;
301         gdouble elapsed;
302
303         status = g_web_result_get_status(result);
304         if (status == 200)
305                 goto done;
306
307         g_web_result_get_chunk(result, &chunk, &length);
308
309         if (length > 0) {
310                 //printf("%s\n", (char *) chunk);
311                 g_web_parser_feed_data(request_parser, chunk, length);
312                 return TRUE;
313         }
314
315         g_web_parser_end_data(request_parser);
316
317 done:
318         g_print("status: %03u\n", status);
319
320         elapsed = g_timer_elapsed(timer, NULL);
321
322         g_print("elapse: %f seconds\n", elapsed);
323
324         g_main_loop_quit(main_loop);
325
326         return FALSE;
327 }
328
329 static gboolean option_debug = FALSE;
330 static gchar *option_nameserver = NULL;
331 static gchar *option_url = NULL;
332
333 static GOptionEntry options[] = {
334         { "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug,
335                                         "Enable debug output" },
336         { "nameserver", 'n', 0, G_OPTION_ARG_STRING, &option_nameserver,
337                                         "Specify nameserver", "ADDRESS" },
338         { "url", 'u', 0, G_OPTION_ARG_STRING, &option_url,
339                                         "Specify arbitrary request", "URL" },
340         { NULL },
341 };
342
343 int main(int argc, char *argv[])
344 {
345         GOptionContext *context;
346         GError *error = NULL;
347         struct sigaction sa;
348         GWeb *web;
349         int index = 0;
350
351         context = g_option_context_new(NULL);
352         g_option_context_add_main_entries(context, options, NULL);
353
354         if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) {
355                 if (error != NULL) {
356                         g_printerr("%s\n", error->message);
357                         g_error_free(error);
358                 } else
359                         g_printerr("An unknown error occurred\n");
360                 return 1;
361         }
362
363         g_option_context_free(context);
364
365         web = g_web_new(index);
366         if (web == NULL) {
367                 fprintf(stderr, "Failed to create web service\n");
368                 return 1;
369         }
370
371         if (option_debug == TRUE)
372                 g_web_set_debug(web, web_debug, "WEB");
373
374         main_loop = g_main_loop_new(NULL, FALSE);
375
376         if (option_nameserver != NULL) {
377                 g_web_add_nameserver(web, option_nameserver);
378                 g_free(option_nameserver);
379         }
380
381         g_web_set_accept(web, NULL);
382         g_web_set_user_agent(web, "SmartClient/%s wispr", VERSION);
383         g_web_set_close_connection(web, TRUE);
384
385         if (option_url == NULL)
386                 option_url = g_strdup(DEFAULT_URL);
387
388         timer = g_timer_new();
389
390         request_parser = g_web_parser_new("<WISPAccessGatewayParam",
391                                                 "WISPAccessGatewayParam>",
392                                                 parser_callback, NULL);
393
394         g_web_parser_ref(request_parser);
395         g_web_parser_unref(request_parser);
396
397         request_id = g_web_request(web, G_WEB_METHOD_GET, option_url,
398                                                         web_result, NULL);
399
400         g_free(option_url);
401
402         if (request_id == 0) {
403                 fprintf(stderr, "Failed to start request\n");
404                 return 1;
405         }
406
407         memset(&sa, 0, sizeof(sa));
408         sa.sa_handler = sig_term;
409         sigaction(SIGINT, &sa, NULL);
410         sigaction(SIGTERM, &sa, NULL);
411
412         g_main_loop_run(main_loop);
413
414         g_timer_destroy(timer);
415
416         g_web_unref(web);
417
418         g_main_loop_unref(main_loop);
419
420         return 0;
421 }