make use of the crypto_tester in the crypto_factory
[strongswan.git] / src / dumm / main.c
1 /*
2 * Copyright (C) 2008 Martin Willi
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 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "dumm.h"
17
18 #include <utils/linked_list.h>
19
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include <sched.h>
23
24 #include <glib.h>
25 #include <gtk/gtk.h>
26 #include <vte/vte.h>
27 #include <vte/reaper.h>
28
29 /**
30 * notebook page with vte and guest
31 */
32 typedef struct {
33 gint num;
34 GtkWidget *vte;
35 guest_t *guest;
36 } page_t;
37
38 /**
39 * Main window
40 */
41 GtkWidget *window;
42
43 /**
44 * notebook with guests, vtes
45 */
46 GtkWidget *notebook;
47
48 /**
49 * dumm context
50 */
51 dumm_t *dumm;
52
53 /**
54 * pages in notebook, page_t
55 */
56 linked_list_t *pages;
57
58 /**
59 * handle guest termination, SIGCHILD
60 */
61 static void child_exited(VteReaper *vtereaper, gint pid, gint status)
62 {
63 enumerator_t *enumerator;
64 page_t *page;
65
66 enumerator = pages->create_enumerator(pages);
67 while (enumerator->enumerate(enumerator, (void**)&page))
68 {
69 if (page->guest->get_pid(page->guest) == pid)
70 {
71 page->guest->sigchild(page->guest);
72 vte_terminal_feed(VTE_TERMINAL(page->vte),
73 "\n\r--- guest terminated ---\n\r", -1);
74 break;
75 }
76 }
77 enumerator->destroy(enumerator);
78 }
79
80 static page_t* get_page(int num)
81 {
82 enumerator_t *enumerator;
83 page_t *page, *found = NULL;
84
85 enumerator = pages->create_enumerator(pages);
86 while (enumerator->enumerate(enumerator, (void**)&page))
87 {
88 if (page->num == num)
89 {
90 found = page;
91 break;
92 }
93 }
94 enumerator->destroy(enumerator);
95 return found;
96 }
97
98 /**
99 * Guest invocation callback
100 */
101 static pid_t invoke(void *vte, guest_t *guest,
102 char *args[], int argc)
103 {
104 return vte_terminal_fork_command(VTE_TERMINAL(vte), args[0], args, NULL,
105 NULL, FALSE, FALSE, FALSE);
106 }
107
108 void idle(void)
109 {
110 gtk_main_iteration_do(FALSE);
111 sched_yield();
112 }
113
114 static void start_guest()
115 {
116 page_t *page;
117
118 page = get_page(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
119 if (page && page->guest->get_state(page->guest) == GUEST_STOPPED)
120 {
121 vte_terminal_feed(VTE_TERMINAL(page->vte),
122 "--- starting guest ---\n\r", -1);
123 page->guest->start(page->guest, invoke, VTE_TERMINAL(page->vte), idle);
124 }
125 }
126
127 static void start_all_guests()
128 {
129 enumerator_t *enumerator;
130 page_t *page;
131
132 enumerator = pages->create_enumerator(pages);
133 while (enumerator->enumerate(enumerator, (void**)&page))
134 {
135 if (page->guest->get_state(page->guest) == GUEST_STOPPED)
136 {
137 vte_terminal_feed(VTE_TERMINAL(page->vte),
138 "--- starting all guests ---\n\r", -1);
139 page->guest->start(page->guest, invoke,
140 VTE_TERMINAL(page->vte), idle);
141 }
142 }
143 enumerator->destroy(enumerator);
144 }
145
146 static void stop_guest()
147 {
148 page_t *page;
149
150 page = get_page(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
151 if (page && page->guest->get_state(page->guest) == GUEST_RUNNING)
152 {
153 page->guest->stop(page->guest, idle);
154 }
155 }
156
157 /**
158 * quit signal handler
159 */
160 static void quit()
161 {
162 enumerator_t *enumerator;
163 page_t *page;
164
165 dumm->load_template(dumm, NULL);
166
167 enumerator = pages->create_enumerator(pages);
168 while (enumerator->enumerate(enumerator, &page))
169 {
170 if (page->guest->get_state(page->guest) != GUEST_STOPPED)
171 {
172 page->guest->stop(page->guest, idle);
173 }
174 }
175 enumerator->destroy(enumerator);
176 gtk_main_quit();
177 }
178
179 static void error_dialog(char *msg)
180 {
181 GtkWidget *error;
182
183 error = gtk_message_dialog_new(GTK_WINDOW(window),
184 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
185 GTK_BUTTONS_CLOSE, msg);
186 gtk_dialog_run(GTK_DIALOG(error));
187 gtk_widget_destroy(error);
188 }
189
190 static void create_switch()
191 {
192 GtkWidget *dialog, *table, *label, *name;
193 bridge_t *bridge;
194
195 dialog = gtk_dialog_new_with_buttons("Create new switch", GTK_WINDOW(window),
196 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
197 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
198 GTK_STOCK_NEW, GTK_RESPONSE_ACCEPT, NULL);
199
200 table = gtk_table_new(1, 2, TRUE);
201 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table);
202
203 label = gtk_label_new("Switch name");
204 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, 0, 0, 0, 0);
205 gtk_widget_show(label);
206
207 name = gtk_entry_new();
208 gtk_table_attach(GTK_TABLE(table), name, 1, 2, 0, 1,
209 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
210 gtk_widget_show(name);
211
212 gtk_widget_show(table);
213
214 while (TRUE)
215 {
216 switch (gtk_dialog_run(GTK_DIALOG(dialog)))
217 {
218 case GTK_RESPONSE_ACCEPT:
219 {
220 if (streq(gtk_entry_get_text(GTK_ENTRY(name)), ""))
221 {
222 continue;
223 }
224 bridge = dumm->create_bridge(dumm,
225 (char*)gtk_entry_get_text(GTK_ENTRY(name)));
226 if (!bridge)
227 {
228 error_dialog("creating bridge failed!");
229 continue;
230 }
231 break;
232 }
233 default:
234 break;
235 }
236 break;
237 }
238 gtk_widget_destroy(dialog);
239 }
240
241 static void delete_switch()
242 {
243
244 }
245
246 static void connect_guest()
247 {
248 page_t *page;
249 GtkWidget *dialog, *table, *label, *name, *box;
250 bridge_t *bridge;
251 iface_t *iface;
252 enumerator_t *enumerator;
253
254 page = get_page(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
255 if (!page || page->guest->get_state(page->guest) != GUEST_RUNNING)
256 {
257 return;
258 }
259
260 dialog = gtk_dialog_new_with_buttons("Connect guest", GTK_WINDOW(window),
261 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
262 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
263 GTK_STOCK_NEW, GTK_RESPONSE_ACCEPT, NULL);
264
265 table = gtk_table_new(2, 2, TRUE);
266 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table);
267
268 label = gtk_label_new("Interface name");
269 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, 0, 0, 0, 0);
270 gtk_widget_show(label);
271
272 name = gtk_entry_new();
273 gtk_table_attach(GTK_TABLE(table), name, 1, 2, 0, 1,
274 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
275 gtk_widget_show(name);
276
277 label = gtk_label_new("Connected switch");
278 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, 0, 0, 0, 0);
279 gtk_widget_show(label);
280
281 box = gtk_combo_box_new_text();
282 gtk_table_attach(GTK_TABLE(table), box, 1, 2, 1, 2,
283 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
284 enumerator = dumm->create_bridge_enumerator(dumm);
285 while (enumerator->enumerate(enumerator, &bridge))
286 {
287 gtk_combo_box_append_text(GTK_COMBO_BOX(box), bridge->get_name(bridge));
288 }
289 enumerator->destroy(enumerator);
290 gtk_widget_show(box);
291
292 gtk_widget_show(table);
293
294 while (TRUE)
295 {
296 switch (gtk_dialog_run(GTK_DIALOG(dialog)))
297 {
298 case GTK_RESPONSE_ACCEPT:
299 {
300 if (streq(gtk_entry_get_text(GTK_ENTRY(name)), ""))
301 {
302 continue;
303 }
304
305 iface = page->guest->create_iface(page->guest,
306 (char*)gtk_entry_get_text(GTK_ENTRY(name)));
307 if (!iface)
308 {
309 error_dialog("creating interface failed!");
310 continue;
311 }
312 enumerator = dumm->create_bridge_enumerator(dumm);
313 while (enumerator->enumerate(enumerator, &bridge))
314 {
315 if (!bridge->connect_iface(bridge, iface))
316 {
317 error_dialog("connecting interface failed!");
318 }
319 break;
320 }
321 enumerator->destroy(enumerator);
322 break;
323 }
324 default:
325 break;
326 }
327 break;
328 }
329 gtk_widget_destroy(dialog);
330 }
331
332 static void disconnect_guest()
333 {
334
335 }
336
337 static void delete_guest()
338 {
339 page_t *page;
340
341 page = get_page(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
342 if (page)
343 {
344 page->guest->stop(page->guest, idle);
345 dumm->delete_guest(dumm, page->guest);
346 gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), page->num);
347 pages->remove(pages, page, NULL);
348 g_free(page);
349 }
350 }
351
352 /**
353 * create a new page for a guest
354 */
355 static page_t* create_page(guest_t *guest)
356 {
357 GtkWidget *label;
358 page_t *page;
359
360 page = g_new(page_t, 1);
361 page->guest = guest;
362 page->vte = vte_terminal_new();
363 label = gtk_label_new(guest->get_name(guest));
364 page->num = gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
365 page->vte, label);
366 gtk_widget_show(page->vte);
367 pages->insert_last(pages, page);
368 return page;
369 }
370
371 /**
372 * create a new guest
373 */
374 static void create_guest()
375 {
376 guest_t *guest;
377 GtkWidget *dialog, *table, *label, *name, *kernel, *master, *args;
378
379 dialog = gtk_dialog_new_with_buttons("Create new guest", GTK_WINDOW(window),
380 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
381 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
382 GTK_STOCK_NEW, GTK_RESPONSE_ACCEPT, NULL);
383
384 table = gtk_table_new(4, 2, TRUE);
385 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table);
386
387 label = gtk_label_new("Guest name");
388 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, 0, 0, 0, 0);
389 gtk_widget_show(label);
390
391 label = gtk_label_new("UML kernel");
392 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, 0, 0, 0, 0);
393 gtk_widget_show(label);
394
395 label = gtk_label_new("Master filesystem");
396 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, 0, 0, 0, 0);
397 gtk_widget_show(label);
398
399 label = gtk_label_new("Kernel arguments");
400 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, 0, 0, 0, 0);
401 gtk_widget_show(label);
402
403 name = gtk_entry_new();
404 gtk_table_attach(GTK_TABLE(table), name, 1, 2, 0, 1,
405 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
406 gtk_widget_show(name);
407
408 kernel = gtk_file_chooser_button_new("Select UML kernel image",
409 GTK_FILE_CHOOSER_ACTION_OPEN);
410 gtk_table_attach(GTK_TABLE(table), kernel, 1, 2, 1, 2,
411 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
412 gtk_widget_show(kernel);
413
414 master = gtk_file_chooser_button_new("Select master filesystem",
415 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
416 gtk_table_attach(GTK_TABLE(table), master, 1, 2, 2, 3,
417 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
418 gtk_widget_show(master);
419
420 args = gtk_entry_new();
421 gtk_table_attach(GTK_TABLE(table), args, 1, 2, 3, 4,
422 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
423 gtk_widget_show(args);
424
425 gtk_widget_show(table);
426
427 while (TRUE)
428 {
429 switch (gtk_dialog_run(GTK_DIALOG(dialog)))
430 {
431 case GTK_RESPONSE_ACCEPT:
432 {
433 char *sname, *skernel, *smaster, *sargs;
434 page_t *page;
435
436 sname = (char*)gtk_entry_get_text(GTK_ENTRY(name));
437 skernel = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(kernel));
438 smaster = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(master));
439 sargs = (char*)gtk_entry_get_text(GTK_ENTRY(args));
440
441 if (!sname[0] || !skernel || !smaster)
442 {
443 continue;
444 }
445 guest = dumm->create_guest(dumm, sname, skernel, smaster, sargs);
446 if (!guest)
447 {
448 error_dialog("creating guest failed!");
449 continue;
450 }
451 page = create_page(guest);
452 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page->num);
453 break;
454 }
455 default:
456 break;
457 }
458 break;
459 }
460 gtk_widget_destroy(dialog);
461 }
462
463 /**
464 * main routine, parses args and reads from console
465 */
466 int main(int argc, char *argv[])
467 {
468 GtkWidget *menubar, *menu, *menuitem, *vbox;
469 GtkWidget *dummMenu, *guestMenu, *switchMenu;
470 enumerator_t *enumerator;
471 guest_t *guest;
472
473 library_init(NULL);
474 gtk_init(&argc, &argv);
475
476 pages = linked_list_create();
477 dumm = dumm_create(NULL);
478
479 /* setup window */
480 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
481 g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(quit), NULL);
482 gtk_window_set_title(GTK_WINDOW (window), "Dumm");
483 gtk_window_set_default_size(GTK_WINDOW (window), 1000, 500);
484 g_signal_connect(G_OBJECT(vte_reaper_get()), "child-exited",
485 G_CALLBACK(child_exited), NULL);
486
487 /* add vbox with menubar, notebook */
488 vbox = gtk_vbox_new(FALSE, 0);
489 gtk_container_add(GTK_CONTAINER(window), vbox);
490 menubar = gtk_menu_bar_new();
491 gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
492 notebook = gtk_notebook_new();
493 g_object_set(G_OBJECT(notebook), "homogeneous", TRUE, NULL);
494 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_BOTTOM);
495 gtk_container_add(GTK_CONTAINER(vbox), notebook);
496
497 /* Dumm menu */
498 menu = gtk_menu_new();
499 dummMenu = gtk_menu_item_new_with_mnemonic("_Dumm");
500 gtk_menu_bar_append(GTK_MENU_BAR(menubar), dummMenu);
501 gtk_widget_show(dummMenu);
502 gtk_menu_item_set_submenu(GTK_MENU_ITEM(dummMenu), menu);
503
504 /* Dumm -> exit */
505 menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
506 g_signal_connect(G_OBJECT(menuitem), "activate",
507 G_CALLBACK(quit), NULL);
508 gtk_menu_append(GTK_MENU(menu), menuitem);
509 gtk_widget_show(menuitem);
510
511 /* Guest menu */
512 menu = gtk_menu_new();
513 guestMenu = gtk_menu_item_new_with_mnemonic("_Guest");
514 gtk_menu_bar_append(GTK_MENU_BAR(menubar), guestMenu);
515 gtk_widget_show(guestMenu);
516 gtk_menu_item_set_submenu(GTK_MENU_ITEM(guestMenu), menu);
517
518 /* Guest -> new */
519 menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
520 g_signal_connect(G_OBJECT(menuitem), "activate",
521 G_CALLBACK(create_guest), NULL);
522 gtk_menu_append(GTK_MENU(menu), menuitem);
523 gtk_widget_show(menuitem);
524
525 /* Guest -> delete */
526 menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, NULL);
527 g_signal_connect(G_OBJECT(menuitem), "activate",
528 G_CALLBACK(delete_guest), NULL);
529 gtk_menu_append(GTK_MENU(menu), menuitem);
530 gtk_widget_show(menuitem);
531
532 menuitem = gtk_separator_menu_item_new();
533 gtk_menu_append(GTK_MENU(menu), menuitem);
534 gtk_widget_show(menuitem);
535
536 /* Guest -> start */
537 menuitem = gtk_menu_item_new_with_mnemonic("_Start");
538 g_signal_connect(G_OBJECT(menuitem), "activate",
539 G_CALLBACK(start_guest), NULL);
540 gtk_menu_append(GTK_MENU(menu), menuitem);
541 gtk_widget_show(menuitem);
542
543 /* Guest -> startall */
544 menuitem = gtk_menu_item_new_with_mnemonic("Start _all");
545 g_signal_connect(G_OBJECT(menuitem), "activate",
546 G_CALLBACK(start_all_guests), NULL);
547 gtk_menu_append(GTK_MENU(menu), menuitem);
548 gtk_widget_show(menuitem);
549
550 /* Guest -> stop */
551 menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_STOP, NULL);
552 g_signal_connect(G_OBJECT(menuitem), "activate",
553 G_CALLBACK(stop_guest), NULL);
554 gtk_menu_append(GTK_MENU(menu), menuitem);
555 gtk_widget_show(menuitem);
556
557 menuitem = gtk_separator_menu_item_new();
558 gtk_menu_append(GTK_MENU(menu), menuitem);
559 gtk_widget_show(menuitem);
560
561 /* Guest -> connect */
562 menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_CONNECT, NULL);
563 g_signal_connect(G_OBJECT(menuitem), "activate",
564 G_CALLBACK(connect_guest), NULL);
565 gtk_menu_append(GTK_MENU(menu), menuitem);
566 gtk_widget_show(menuitem);
567
568 /* Guest -> disconnect */
569 menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_DISCONNECT, NULL);
570 g_signal_connect(G_OBJECT(menuitem), "activate",
571 G_CALLBACK(disconnect_guest), NULL);
572 gtk_menu_append(GTK_MENU(menu), menuitem);
573 gtk_widget_set_sensitive(menuitem, FALSE);
574 gtk_widget_show(menuitem);
575
576 /* Switch menu */
577 menu = gtk_menu_new();
578 switchMenu = gtk_menu_item_new_with_mnemonic("_Switch");
579 gtk_menu_bar_append(GTK_MENU_BAR(menubar), switchMenu);
580 gtk_widget_show(switchMenu);
581 gtk_menu_item_set_submenu(GTK_MENU_ITEM(switchMenu), menu);
582
583 /* Switch -> new */
584 menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
585 g_signal_connect(G_OBJECT(menuitem), "activate",
586 G_CALLBACK(create_switch), NULL);
587 gtk_menu_append(GTK_MENU(menu), menuitem);
588 gtk_widget_show(menuitem);
589
590 /* Switch -> delete */
591 menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, NULL);
592 g_signal_connect(G_OBJECT(menuitem), "activate",
593 G_CALLBACK(delete_switch), NULL);
594 gtk_menu_append(GTK_MENU(menu), menuitem);
595 gtk_widget_set_sensitive(menuitem, FALSE);
596 gtk_widget_show(menuitem);
597
598 /* show widgets */
599 gtk_widget_show(menubar);
600 gtk_widget_show(notebook);
601 gtk_widget_show(vbox);
602 gtk_widget_show(window);
603
604 /* fill notebook with guests */
605 enumerator = dumm->create_guest_enumerator(dumm);
606 while (enumerator->enumerate(enumerator, (void**)&guest))
607 {
608 create_page(guest);
609 }
610 enumerator->destroy(enumerator);
611
612 gtk_main();
613
614 dumm->destroy(dumm);
615 pages->destroy_function(pages, g_free);
616
617 library_deinit();
618 return 0;
619 }
620