ext/rubymain.cpp in eventmachine-eventmachine-0.12.7 vs ext/rubymain.cpp in eventmachine-eventmachine-0.12.8

- old
+ new

@@ -19,12 +19,14 @@ #include "project.h" #include "eventmachine.h" #include <ruby.h> +#ifndef RFLOAT_VALUE +#define RFLOAT_VALUE(arg) RFLOAT(arg)->value +#endif - /******* Statics *******/ static VALUE EmModule; @@ -41,12 +43,14 @@ static VALUE Intern_run_deferred_callbacks; static VALUE Intern_delete; static VALUE Intern_call; static VALUE Intern_receive_data; static VALUE Intern_ssl_handshake_completed; +static VALUE Intern_ssl_verify_peer; static VALUE Intern_notify_readable; static VALUE Intern_notify_writable; +static VALUE Intern_proxy_target_unbound; static VALUE rb_cProcStatus; struct em_event { const char *a1; @@ -91,21 +95,43 @@ rb_funcall (EmModule, Intern_run_deferred_callbacks, 0); } else if (a2 == EM_TIMER_FIRED) { VALUE t = rb_ivar_get (EmModule, Intern_at_timers); VALUE q = rb_funcall (t, Intern_delete, 1, rb_str_new(a3, a4)); - if (q == Qnil) + if (q == Qnil) { rb_raise (EM_eUnknownTimerFired, "no such timer: %s", a1); - rb_funcall (q, Intern_call, 0); + } else if (q == Qfalse) { + /* Timer Canceled */ + } else { + rb_funcall (q, Intern_call, 0); + } } + #ifdef WITH_SSL else if (a2 == EM_SSL_HANDSHAKE_COMPLETED) { VALUE t = rb_ivar_get (EmModule, Intern_at_conns); VALUE q = rb_hash_aref (t, rb_str_new2(a1)); if (q == Qnil) rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1); rb_funcall (q, Intern_ssl_handshake_completed, 0); } + else if (a2 == EM_SSL_VERIFY) { + VALUE t = rb_ivar_get (EmModule, Intern_at_conns); + VALUE q = rb_hash_aref (t, rb_str_new2(a1)); + if (q == Qnil) + rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1); + VALUE r = rb_funcall (q, Intern_ssl_verify_peer, 1, rb_str_new(a3, a4)); + if (RTEST(r)) + evma_accept_ssl_peer (a1); + } + #endif + else if (a2 == EM_PROXY_TARGET_UNBOUND) { + VALUE t = rb_ivar_get (EmModule, Intern_at_conns); + VALUE q = rb_hash_aref (t, rb_str_new2(a1)); + if (q == Qnil) + rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1); + rb_funcall (q, Intern_proxy_target_unbound, 0); + } else rb_funcall (EmModule, Intern_event_callback, 3, rb_str_new2(a1), (a2 << 1) | 1, rb_str_new(a3,a4)); } /******************* @@ -232,24 +258,24 @@ /*************** t_set_tls_parms ***************/ -static VALUE t_set_tls_parms (VALUE self, VALUE signature, VALUE privkeyfile, VALUE certchainfile) +static VALUE t_set_tls_parms (VALUE self, VALUE signature, VALUE privkeyfile, VALUE certchainfile, VALUE verify_peer) { /* set_tls_parms takes a series of positional arguments for specifying such things * as private keys and certificate chains. * It's expected that the parameter list will grow as we add more supported features. * ALL of these parameters are optional, and can be specified as empty or NULL strings. */ - evma_set_tls_parms (StringValuePtr (signature), StringValuePtr (privkeyfile), StringValuePtr (certchainfile) ); + evma_set_tls_parms (StringValuePtr (signature), StringValuePtr (privkeyfile), StringValuePtr (certchainfile), (verify_peer == Qtrue ? 1 : 0)); return Qnil; } -/*********** +/*************** t_get_peer_cert -***********/ +***************/ static VALUE t_get_peer_cert (VALUE self, VALUE signature) { VALUE ret = Qnil; @@ -350,26 +376,23 @@ t_get_comm_inactivity_timeout *****************************/ static VALUE t_get_comm_inactivity_timeout (VALUE self, VALUE signature) { - int timeout; - if (evma_get_comm_inactivity_timeout (StringValuePtr (signature), &timeout)) - return INT2FIX (timeout); - return Qnil; + return rb_float_new(evma_get_comm_inactivity_timeout(StringValuePtr(signature))); } /***************************** t_set_comm_inactivity_timeout *****************************/ static VALUE t_set_comm_inactivity_timeout (VALUE self, VALUE signature, VALUE timeout) { - int ti = FIX2INT (timeout); - if (evma_set_comm_inactivity_timeout (StringValuePtr (signature), &ti)); + float ti = RFLOAT_VALUE(timeout); + if (evma_set_comm_inactivity_timeout (StringValuePtr (signature), ti)); return Qtrue; - return Qnil; + return Qfalse; } /*************** t_send_datagram @@ -412,17 +435,38 @@ { // Avoid FIX2INT in this case, because it doesn't deal with type errors properly. // Specifically, if the value of port comes in as a string rather than an integer, // NUM2INT will throw a type error, but FIX2INT will generate garbage. - const char *f = evma_connect_to_server (StringValuePtr(server), NUM2INT(port)); + const char *f = evma_connect_to_server (NULL, 0, StringValuePtr(server), NUM2INT(port)); if (!f || !*f) rb_raise (rb_eRuntimeError, "no connection"); return rb_str_new2 (f); } /********************* +t_bind_connect_server +*********************/ + +static VALUE t_bind_connect_server (VALUE self, VALUE bind_addr, VALUE bind_port, VALUE server, VALUE port) +{ + // Avoid FIX2INT in this case, because it doesn't deal with type errors properly. + // Specifically, if the value of port comes in as a string rather than an integer, + // NUM2INT will throw a type error, but FIX2INT will generate garbage. + + const char *f; + try { + f = evma_connect_to_server (StringValuePtr(bind_addr), NUM2INT(bind_port), StringValuePtr(server), NUM2INT(port)); + if (!f || !*f) + rb_raise (rb_eRuntimeError, "no connection"); + } catch (std::runtime_error e) { + rb_sys_fail(e.what()); + } + return rb_str_new2 (f); +} + +/********************* t_connect_unix_server *********************/ static VALUE t_connect_unix_server (VALUE self, VALUE serversocket) { @@ -607,21 +651,60 @@ rb_raise (rb_eRuntimeError, "no keyboard reader"); return rb_str_new2 (f); } -/******** -t__epoll -********/ +/**************** +t_watch_filename +****************/ -static VALUE t__epoll (VALUE self) +static VALUE t_watch_filename (VALUE self, VALUE fname) { - // Temporary. - evma__epoll(); + try { + return rb_str_new2(evma_watch_filename(StringValuePtr(fname))); + } catch (std::runtime_error e) { + rb_sys_fail(e.what()); + } +} + + +/****************** +t_unwatch_filename +******************/ + +static VALUE t_unwatch_filename (VALUE self, VALUE sig) +{ + evma_unwatch_filename(StringValuePtr(sig)); return Qnil; } + +/*********** +t_watch_pid +***********/ + +static VALUE t_watch_pid (VALUE self, VALUE pid) +{ + try { + return rb_str_new2(evma_watch_pid(NUM2INT(pid))); + } catch (std::runtime_error e) { + rb_sys_fail(e.what()); + } +} + + +/************* +t_unwatch_pid +*************/ + +static VALUE t_unwatch_pid (VALUE self, VALUE sig) +{ + evma_unwatch_pid(StringValuePtr(sig)); + return Qnil; +} + + /********** t__epoll_p **********/ static VALUE t__epoll_p (VALUE self) @@ -631,22 +714,37 @@ #else return Qfalse; #endif } +/******** +t__epoll +********/ -/********* -t__kqueue -*********/ +static VALUE t__epoll (VALUE self) +{ + if (t__epoll_p(self) == Qfalse) + return Qfalse; -static VALUE t__kqueue (VALUE self) + evma_set_epoll (1); + return Qtrue; +} + +/*********** +t__epoll_set +***********/ + +static VALUE t__epoll_set (VALUE self, VALUE val) { - // Temporary. - evma__kqueue(); - return Qnil; + if (t__epoll_p(self) == Qfalse) + return Qfalse; + + evma_set_epoll (val == Qtrue ? 1 : 0); + return val; } + /*********** t__kqueue_p ***********/ static VALUE t__kqueue_p (VALUE self) @@ -656,11 +754,51 @@ #else return Qfalse; #endif } +/********* +t__kqueue +*********/ +static VALUE t__kqueue (VALUE self) +{ + if (t__kqueue_p(self) == Qfalse) + return Qfalse; + + evma_set_kqueue (1); + return Qtrue; +} + +/************* +t__kqueue_set +*************/ + +static VALUE t__kqueue_set (VALUE self, VALUE val) +{ + if (t__kqueue_p(self) == Qfalse) + return Qfalse; + + evma_set_kqueue (val == Qtrue ? 1 : 0); + return val; +} + + +/******** +t__ssl_p +********/ + +static VALUE t__ssl_p (VALUE self) +{ + #ifdef WITH_SSL + return Qtrue; + #else + return Qfalse; + #endif +} + + /**************** t_send_file_data ****************/ static VALUE t_send_file_data (VALUE self, VALUE signature, VALUE filename) @@ -737,10 +875,55 @@ } return Qnil; } +/************* +t_start_proxy +**************/ + +static VALUE t_start_proxy (VALUE self, VALUE from, VALUE to) +{ + evma_start_proxy(StringValuePtr(from), StringValuePtr(to)); + return Qnil; +} + + +/************ +t_stop_proxy +*************/ + +static VALUE t_stop_proxy (VALUE self, VALUE from) +{ + evma_stop_proxy(StringValuePtr(from)); + return Qnil; +} + + +/************************ +t_get_heartbeat_interval +*************************/ + +static VALUE t_get_heartbeat_interval (VALUE self) +{ + return rb_float_new(evma_get_heartbeat_interval()); +} + + +/************************ +t_set_heartbeat_interval +*************************/ + +static VALUE t_set_heartbeat_interval (VALUE self, VALUE interval) +{ + float iv = RFLOAT_VALUE(interval); + if (evma_set_heartbeat_interval(iv)) + return Qtrue; + return Qfalse; +} + + /********************* Init_rubyeventmachine *********************/ extern "C" void Init_rubyeventmachine() @@ -759,12 +942,14 @@ Intern_run_deferred_callbacks = rb_intern ("run_deferred_callbacks"); Intern_delete = rb_intern ("delete"); Intern_call = rb_intern ("call"); Intern_receive_data = rb_intern ("receive_data"); Intern_ssl_handshake_completed = rb_intern ("ssl_handshake_completed"); + Intern_ssl_verify_peer = rb_intern ("ssl_verify_peer"); Intern_notify_readable = rb_intern ("notify_readable"); Intern_notify_writable = rb_intern ("notify_writable"); + Intern_proxy_target_unbound = rb_intern ("proxy_target_unbound"); // INCOMPLETE, we need to define class Connections inside module EventMachine // run_machine and run_machine_without_threads are now identical. // Must deprecate the without_threads variant. EmModule = rb_define_module ("EventMachine"); @@ -779,23 +964,33 @@ rb_define_module_function (EmModule, "run_machine_without_threads", (VALUE(*)(...))t_run_machine_without_threads, 0); rb_define_module_function (EmModule, "add_oneshot_timer", (VALUE(*)(...))t_add_oneshot_timer, 1); rb_define_module_function (EmModule, "start_tcp_server", (VALUE(*)(...))t_start_server, 2); rb_define_module_function (EmModule, "stop_tcp_server", (VALUE(*)(...))t_stop_server, 1); rb_define_module_function (EmModule, "start_unix_server", (VALUE(*)(...))t_start_unix_server, 1); - rb_define_module_function (EmModule, "set_tls_parms", (VALUE(*)(...))t_set_tls_parms, 3); + rb_define_module_function (EmModule, "set_tls_parms", (VALUE(*)(...))t_set_tls_parms, 4); rb_define_module_function (EmModule, "start_tls", (VALUE(*)(...))t_start_tls, 1); rb_define_module_function (EmModule, "get_peer_cert", (VALUE(*)(...))t_get_peer_cert, 1); rb_define_module_function (EmModule, "send_data", (VALUE(*)(...))t_send_data, 3); rb_define_module_function (EmModule, "send_datagram", (VALUE(*)(...))t_send_datagram, 5); rb_define_module_function (EmModule, "close_connection", (VALUE(*)(...))t_close_connection, 2); rb_define_module_function (EmModule, "report_connection_error_status", (VALUE(*)(...))t_report_connection_error_status, 1); rb_define_module_function (EmModule, "connect_server", (VALUE(*)(...))t_connect_server, 2); + rb_define_module_function (EmModule, "bind_connect_server", (VALUE(*)(...))t_bind_connect_server, 4); rb_define_module_function (EmModule, "connect_unix_server", (VALUE(*)(...))t_connect_unix_server, 1); rb_define_module_function (EmModule, "attach_fd", (VALUE (*)(...))t_attach_fd, 3); rb_define_module_function (EmModule, "detach_fd", (VALUE (*)(...))t_detach_fd, 1); + rb_define_module_function (EmModule, "start_proxy", (VALUE (*)(...))t_start_proxy, 2); + rb_define_module_function (EmModule, "stop_proxy", (VALUE (*)(...))t_stop_proxy, 1); + + rb_define_module_function (EmModule, "watch_filename", (VALUE (*)(...))t_watch_filename, 1); + rb_define_module_function (EmModule, "unwatch_filename", (VALUE (*)(...))t_unwatch_filename, 1); + + rb_define_module_function (EmModule, "watch_pid", (VALUE (*)(...))t_watch_pid, 1); + rb_define_module_function (EmModule, "unwatch_pid", (VALUE (*)(...))t_unwatch_pid, 1); + rb_define_module_function (EmModule, "current_time", (VALUE(*)(...))t_get_loop_time, 0); rb_define_module_function (EmModule, "open_udp_socket", (VALUE(*)(...))t_open_udp_socket, 2); rb_define_module_function (EmModule, "read_keyboard", (VALUE(*)(...))t_read_keyboard, 0); rb_define_module_function (EmModule, "release_machine", (VALUE(*)(...))t_release_machine, 0); @@ -806,10 +1001,12 @@ rb_define_module_function (EmModule, "get_max_timer_count", (VALUE(*)(...))t_get_max_timer_count, 0); rb_define_module_function (EmModule, "set_max_timer_count", (VALUE(*)(...))t_set_max_timer_count, 1); rb_define_module_function (EmModule, "setuid_string", (VALUE(*)(...))t_setuid_string, 1); rb_define_module_function (EmModule, "invoke_popen", (VALUE(*)(...))t_invoke_popen, 1); rb_define_module_function (EmModule, "send_file_data", (VALUE(*)(...))t_send_file_data, 2); + rb_define_module_function (EmModule, "get_heartbeat_interval", (VALUE(*)(...))t_get_heartbeat_interval, 0); + rb_define_module_function (EmModule, "set_heartbeat_interval", (VALUE(*)(...))t_set_heartbeat_interval, 1); // Provisional: rb_define_module_function (EmModule, "_write_file", (VALUE(*)(...))t__write_file, 1); rb_define_module_function (EmModule, "get_peername", (VALUE(*)(...))t_get_peername, 1); @@ -819,15 +1016,18 @@ rb_define_module_function (EmModule, "get_comm_inactivity_timeout", (VALUE(*)(...))t_get_comm_inactivity_timeout, 1); rb_define_module_function (EmModule, "set_comm_inactivity_timeout", (VALUE(*)(...))t_set_comm_inactivity_timeout, 2); rb_define_module_function (EmModule, "set_rlimit_nofile", (VALUE(*)(...))t_set_rlimit_nofile, 1); rb_define_module_function (EmModule, "get_connection_count", (VALUE(*)(...))t_get_connection_count, 0); - // Temporary: rb_define_module_function (EmModule, "epoll", (VALUE(*)(...))t__epoll, 0); - rb_define_module_function (EmModule, "kqueue", (VALUE(*)(...))t__kqueue, 0); - + rb_define_module_function (EmModule, "epoll=", (VALUE(*)(...))t__epoll_set, 1); rb_define_module_function (EmModule, "epoll?", (VALUE(*)(...))t__epoll_p, 0); + + rb_define_module_function (EmModule, "kqueue", (VALUE(*)(...))t__kqueue, 0); + rb_define_module_function (EmModule, "kqueue=", (VALUE(*)(...))t__kqueue_set, 1); rb_define_module_function (EmModule, "kqueue?", (VALUE(*)(...))t__kqueue_p, 0); + + rb_define_module_function (EmModule, "ssl?", (VALUE(*)(...))t__ssl_p, 0); rb_define_method (EmConnection, "get_outbound_data_size", (VALUE(*)(...))conn_get_outbound_data_size, 0); rb_define_method (EmConnection, "associate_callback_target", (VALUE(*)(...))conn_associate_callback_target, 1); rb_define_const (EmModule, "TimerFired", INT2NUM(100));