72
72
(** Actaully make a tap at the OS level: *)
73
73
let make_system_tap (tap_name : tap_name) uid ip_address =
74
Log.printf "Making the tap %s...\n" tap_name;
74
Log.printf1 "Making the tap %s...\n" tap_name;
77
77
"{ tunctl -u %i -t %s && ifconfig %s 172.23.0.254 netmask 255.255.255.255 up; route add %s %s; }"
78
78
uid tap_name tap_name ip_address tap_name in
79
79
Log.system_or_fail command_line;
80
Log.printf "The tap %s was created with success\n" tap_name
80
Log.printf1 "The tap %s was created with success\n" tap_name
83
83
(** Actually make a tap at the OS level for the bridge socket component: *)
84
84
let make_system_tap_for_socket (tap_name : tap_name) uid bridge_name =
85
Log.printf "Making the tap %s...\n" tap_name;
85
Log.printf1 "Making the tap %s...\n" tap_name;
88
88
"{ tunctl -u %i -t %s && ifconfig %s 0.0.0.0 promisc up && brctl addif %s %s; }"
92
92
bridge_name tap_name in
93
93
let on_error = Printf.sprintf "tunctl -d %s" tap_name in
94
94
Log.system_or_fail ~on_error command_line;
95
Log.printf "The tap %s was created with success\n" tap_name
95
Log.printf1 "The tap %s was created with success\n" tap_name
98
98
(** Actually destroy a tap at the OS level: *)
99
99
let destroy_system_tap (tap_name : tap_name) =
100
Log.printf "Destroying the tap %s...\n" tap_name;
100
Log.printf1 "Destroying the tap %s...\n" tap_name;
101
101
let redirection = Global_options.Debug_level.redirection () in
102
102
let command_line =
104
104
"while ! (ifconfig %s down && tunctl -d %s %s); do echo 'I can not destroy %s yet %s...'; sleep 1; done&"
105
105
tap_name tap_name redirection tap_name redirection in
106
106
Log.system_or_fail ~hide_output:false ~hide_errors:false command_line;
107
Log.printf "The tap %s was destroyed with success\n" tap_name
107
Log.printf1 "The tap %s was destroyed with success\n" tap_name
110
110
(** Actually destroy a tap at the OS level for the socket component: *)
111
111
let destroy_system_tap_for_socket (tap_name : tap_name) uid bridge_name =
112
Log.printf "Destroying the tap %s...\n" tap_name;
112
Log.printf1 "Destroying the tap %s...\n" tap_name;
113
113
let command_line =
114
114
(* This is currently disabled. We have to decide what to do about this: *)
116
116
"{ ifconfig %s down && brctl delif %s %s && tunctl -d %s; }"
117
117
tap_name bridge_name tap_name tap_name in
118
118
Log.system_or_fail command_line;
119
Log.printf "The tap %s was destroyed with success\n" tap_name;
119
Log.printf1 "The tap %s was destroyed with success\n" tap_name;
122
122
(** Instantiate the given pattern, actually create the system object, and return
150
150
(* Create a resource satisfying the given specification, and return it: *)
152
152
"Making %s for %s\n"
153
153
(string_of_daemon_resource_pattern resource_pattern)
154
154
(string_of_client client);
155
155
let resource = make_system_resource resource_pattern in
156
Log.printf "Adding %s for %s\n" (string_of_daemon_resource resource) (string_of_client client);
156
Log.printf2 "Adding %s for %s\n" (string_of_daemon_resource resource) (string_of_client client);
157
157
resource_map#add client resource;
160
Log.printf "Failed (%s) when making the resource %s for %s; bailing out.\n"
160
Log.printf3 "Failed (%s) when making the resource %s for %s; bailing out.\n"
161
161
(Printexc.to_string e)
162
162
(string_of_daemon_resource_pattern resource_pattern)
163
163
(string_of_client client);
170
170
Recursive_mutex.with_mutex the_daemon_mutex
173
Log.printf "Removing %s %s\n" (string_of_client client) (string_of_daemon_resource resource);
174
Log.printf "** resource_map has %i bindings\n" (List.length resource_map#to_list); flush_all ();
173
Log.printf2 "Removing %s %s\n" (string_of_client client) (string_of_daemon_resource resource);
174
Log.printf1 "** resource_map has %i bindings\n" (List.length resource_map#to_list);
175
175
resource_map#remove_key_value_or_fail client resource;
176
176
(* resource_map#remove_key_value client resource; *)
177
Log.printf "** resource_map has %i bindings\n" (List.length resource_map#to_list); flush_all ();
177
Log.printf1 "** resource_map has %i bindings\n" (List.length resource_map#to_list);
178
178
destroy_system_resource resource;
180
Log.printf "WARNING: failed (%s) when destroying %s for %s.\n"
180
Log.printf3 "WARNING: failed (%s) when destroying %s for %s.\n"
181
181
(Printexc.to_string e)
182
182
(string_of_daemon_resource resource)
183
183
(string_of_client client);
188
188
Recursive_mutex.with_mutex the_daemon_mutex
191
Log.printf "Removing all %s's resources:\n" (string_of_client client);
191
Log.printf1 "Removing all %s's resources:\n" (string_of_client client);
193
193
(fun resource -> destroy_resource client resource)
194
194
(resource_map#lookup client);
195
Log.printf "All %s's resources were removed with success.\n" (string_of_client client);
195
Log.printf1 "All %s's resources were removed with success.\n" (string_of_client client);
198
Log.printf "Failed (%s) when removing %s's resources; continuing anyway.\n"
197
Log.printf2 "Failed (%s) when removing %s's resources; continuing anyway.\n"
199
198
(Printexc.to_string e)
200
199
(string_of_client client);
209
208
destroy_all_client_resources client
211
Log.printf "Failed (%s) when removing %s's resources (while removing *all* resources); continuing anyway.\n"
210
Log.printf2 "Failed (%s) when removing %s's resources (while removing *all* resources); continuing anyway.\n"
212
211
(Printexc.to_string e)
213
212
(string_of_client client);
223
222
let current_time = Unix.time () in
224
223
let death_time = current_time +. timeout_interval in
225
224
client_death_time_map#add client death_time;
227
226
"I will not kill %s until %f (it's now %f)\n"
228
227
(string_of_client client)
232
231
with Not_found -> begin
234
233
"keep_client_alive failed because the client %s is not alive.\n"
235
234
(string_of_client client);
236
235
failwith ("keep_alive_client: " ^ (string_of_client client) ^ " is not alive.");
270
269
Log.printf "There is at least one client now. Creating global resources...\n";
271
270
make_global_resources_unlocked_ ();
272
271
Log.printf "Global resources were created with success.\n";
275
273
client_no := !client_no + 1);;
276
274
let decrement_client_no () =
281
279
Log.printf "There are no more clients now. Destroying global resources...\n";
282
280
destroy_global_resources_unlocked_ ();
283
281
Log.printf "Global resources were destroyed with success.\n";
287
284
(** Create a new client on which we're going to interact with the given socket,
296
293
next_client_no := !next_client_no + 1;
297
294
(* First add any number to the data structure, then call keep_alive_client to make
298
295
the death time correct: *)
299
Log.printf "Creating %s.\n" (string_of_client result); flush_all ();
296
Log.printf1 "Creating %s.\n" (string_of_client result);
300
297
client_death_time_map#add result 42.42;
301
298
socket_map#add result socket;
302
299
keep_alive_client result;
303
300
increment_client_no ();
304
Log.printf "Created %s.\n" (string_of_client result); flush_all ();
301
Log.printf1 "Created %s.\n" (string_of_client result);
307
304
let destroy_client client =
308
305
Recursive_mutex.with_mutex the_daemon_mutex
310
Log.printf "Killing %s.\n" (string_of_client client); flush_all ();
307
Log.printf1 "Killing %s.\n" (string_of_client client);
311
308
(try client_death_time_map#remove client with _ -> ());
312
309
(try destroy_all_client_resources client with _ -> ());
313
310
decrement_client_no ();
315
312
Unix.close (socket_map#lookup client);
317
"The socket serving the client %i was closed with success.\n" client;
313
Log.printf1 "The socket serving the client %i was closed with success.\n" client;
321
316
"Closing the socket serving the client %i failed (%s).\n"
322
317
client (Printexc.to_string e);
325
319
(try socket_map#remove client with _ -> ());
326
Log.printf "%s was killed.\n" (string_of_client client); flush_all ());;
320
Log.printf1 "%s was killed.\n" (string_of_client client));;
328
322
let debugging_thread_thunk () =
330
324
Thread.delay debug_interval;
331
325
Recursive_mutex.with_mutex the_daemon_mutex
333
Log.printf "--------------------------------------------\n";
334
Log.printf "Currently existing non-global resources are:\n";
327
Log.printf "--------------------------------------------\nCurrently existing non-global resources are:\n";
336
329
(fun (client, resource) ->
337
Log.printf "* %s (owned by %s)\n" (string_of_daemon_resource resource) (string_of_client client))
330
Log.printf2 "* %s (owned by %s)\n" (string_of_daemon_resource resource) (string_of_client client))
338
331
(resource_map#to_list);
339
332
Log.printf "--------------------------------------------\n";
345
336
(** The 'timeout thread' wakes up every timeout_interval seconds and kills
361
352
(fun (client, death_time) ->
362
353
if current_time >= death_time then begin
363
Log.printf "Client %s didn't send enough keep-alive's.\n" (string_of_client client);
354
Log.printf1 "Client %s didn't send enough keep-alive's.\n" (string_of_client client);
364
355
destroy_client client;
371
360
(** Serve the given single request from the given client, and return the
389
378
let connection_server_thread (client, socket) =
391
Log.printf "This is the connection server thread for client %i.\n" client;
380
Log.printf1 "This is the connection server thread for client %i.\n" client;
394
Log.printf "Beginning of the iteration.\n"; flush_all ();
382
Log.printf "Beginning of the iteration.\n";
395
383
(* We want the message to be initially invalid, at every iteration, to
396
384
avoid the risk of not seeing a receive error. Just to play it extra
399
387
(* We don't want to block indefinitely on read() because the socket could
400
388
be closed by another thread; so we simply select() with a timeout: *)
401
389
let (ready_for_read, _, failed) =
404
391
Unix.select [socket] [] [socket] select_timeout
406
393
Log.printf "!!!!FAILED IN select (connection_server_thread)!!!!\n";
408
394
failwith "select() failed";
409
395
(* ([], [], []); *)
413
(* Unix.select [socket] [] [socket] select_timeout in *)
399
(* Unix.select [socket] [] [socket] select_timeout in *)
414
400
if (List.length failed) > 0 then
415
401
failwith "select() reported failure with the socket"
416
402
else if (List.length ready_for_read) > 0 then begin
420
406
failwith "recv() failed, or the message is ill-formed"
422
408
let request = parse_request buffer in
423
Log.printf "The request is\n %s\n" (string_of_daemon_request request); flush_all ();
409
Log.printf1 "The request is\n %s\n" (string_of_daemon_request request);
424
410
keep_alive_client client;
429
415
Error (Printexc.to_string e)
431
Log.printf "My response is\n %s\n" (string_of_daemon_response response); flush_all ();
417
Log.printf1 "My response is\n %s\n" (string_of_daemon_response response);
432
418
let sent_byte_no = Unix.send socket (print_response response) 0 message_length [] in
433
419
(if not (sent_byte_no == sent_byte_no) then
434
420
failwith "send() failed");
443
429
"Failed in connection_server_thread (%s) for client %i.\nBailing out.\n"
444
430
(Printexc.to_string e)
446
432
destroy_client client; (* This also closes the socket *)
447
Log.printf "Exiting from the thread which was serving client %i\n" client;
433
Log.printf1 "Exiting from the thread which was serving client %i\n" client;
451
436
(** Remove an old socket file, remained from an old instance or from ours
453
438
let remove_socket_file_if_any () =
455
440
Unix.unlink socket_name;
456
Log.printf "[Removed the old socket file %s]\n" socket_name;
441
Log.printf1 "[Removed the old socket file %s]\n" socket_name;
459
Log.printf "[There was no need to remove the socket file %s]\n" socket_name;;
443
Log.printf1 "[There was no need to remove the socket file %s]\n" socket_name;;
461
445
(** Destroy all resources, destroy the socket and exit on either SIGINT and SIGTERM: *)
462
446
let signal_handler signal =
463
Log.printf "=========================\n";
464
Log.printf "I received the signal %i!\n" signal;
465
Log.printf "=========================\n";
466
Log.printf "Destroying all resources...\n";
447
Log.printf1 "=========================\nI received the signal %i!\n=========================\nDestroying all resources...\n" signal;
467
448
destroy_all_resources ();
468
Log.printf "Ok, all resources were destroyed.\n";
469
Log.printf "Removing the socket file...\n";
449
Log.printf "Ok, all resources were destroyed.\nRemoving the socket file...\n";
470
450
remove_socket_file_if_any ();
471
451
Log.printf "Ok, the socket file was removed.\n";
475
454
(** Strangely, without calling this the program is uninterruptable from the
501
480
Unix.bind accepting_socket sock_addr;
502
481
(* Everybody must be able to send messages to us: *)
503
482
Unix.chmod socket_name 438 (* a+rw *);
504
Log.printf "I am waiting on %s.\n" socket_name; flush_all ();
483
Log.printf1 "I am waiting on %s.\n" socket_name;
505
484
Unix.listen accepting_socket connection_no_limit;
508
Log.printf "Waiting for the next connection...\n"; flush_all ();
487
Log.printf "Waiting for the next connection...\n";
509
488
let (socket_to_client, socket_to_client_address) = Unix.accept accepting_socket in
510
489
let client_id = make_client socket_to_client in
511
Log.printf "A new connection was accepted; the new client id is %i\n" client_id; flush_all ();
490
Log.printf1 "A new connection was accepted; the new client id is %i\n" client_id;
512
491
ignore (Thread.create connection_server_thread (client_id, socket_to_client));
515
"Failed in the main thread (%s). Bailing out.\n"
516
(Printexc.to_string e);
493
Log.printf1 "Failed in the main thread (%s). Bailing out.\n" (Printexc.to_string e);