diff options
Diffstat (limited to 'test/scanners/cpp/eventmachine.expected.raydebug')
-rw-r--r-- | test/scanners/cpp/eventmachine.expected.raydebug | 7035 |
1 files changed, 7035 insertions, 0 deletions
diff --git a/test/scanners/cpp/eventmachine.expected.raydebug b/test/scanners/cpp/eventmachine.expected.raydebug new file mode 100644 index 0000000..82004cd --- /dev/null +++ b/test/scanners/cpp/eventmachine.expected.raydebug @@ -0,0 +1,7035 @@ +comment(/***************************************************************************** + +$Id$ + +File: binder.cpp +Date: 07Apr06 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + +preprocessor(#include) include("project.h") + +preprocessor(#define) ident(DEV_URANDOM) string<delimiter(")content(/dev/urandom)delimiter(")> + + +ident(map)operator(<)pre_type(string)operator(,) ident(Bindable_t)operator(*>) ident(Bindable_t)operator(::)ident(BindingBag)operator(;) + + +comment(/******************************** +STATIC Bindable_t::CreateBinding +********************************/) + +pre_type(string) ident(Bindable_t)operator(::)ident(CreateBinding)operator((\)) +operator({) + directive(static) pre_type(int) ident(index) operator(=) integer(0)operator(;) + directive(static) pre_type(string) ident(seed)operator(;) + + reserved(if) operator((()ident(index) operator(>=) integer(1000000)operator(\)) operator(||) operator(()ident(seed)operator(.)ident(length)operator((\)) operator(==) integer(0)operator(\)\)) operator({) + preprocessor(#ifdef) ident(OS_UNIX) + pre_type(int) ident(fd) operator(=) ident(open) operator(()ident(DEV_URANDOM)operator(,) ident(O_RDONLY)operator(\);) + reserved(if) operator(()ident(fd) operator(<) integer(0)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(No entropy device)delimiter(")>operator(\);) + + pre_type(unsigned) pre_type(char) ident(u)operator([)integer(16)operator(];) + ident(size_t) ident(r) operator(=) ident(read) operator(()ident(fd)operator(,) ident(u)operator(,) reserved(sizeof)operator(()ident(u)operator(\)\);) + reserved(if) operator(()ident(r) operator(<) reserved(sizeof)operator(()ident(u)operator(\)\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(Unable to read entropy device)delimiter(")>operator(\);) + + pre_type(unsigned) pre_type(char) operator(*)ident(u1) operator(=) operator(()pre_type(unsigned) pre_type(char)operator(*\))ident(u)operator(;) + pre_type(char) ident(u2) operator([)reserved(sizeof)operator(()ident(u)operator(\)) operator(*) integer(2) operator(+) integer(1)operator(];) + + reserved(for) operator(()ident(size_t) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) reserved(sizeof)operator(()ident(u)operator(\);) ident(i)operator(++\)) + ident(sprintf) operator(()ident(u2) operator(+) operator(()ident(i) operator(*) integer(2)operator(\),) string<delimiter(")content(%02x)delimiter(")>operator(,) ident(u1)operator([)ident(i)operator(]\);) + + ident(seed) operator(=) pre_type(string) operator(()ident(u2)operator(\);) + preprocessor(#endif) + + + preprocessor(#ifdef) ident(OS_WIN32) + ident(UUID) ident(uuid)operator(;) + ident(UuidCreate) operator((&)ident(uuid)operator(\);) + pre_type(unsigned) pre_type(char) operator(*)ident(uuidstring) operator(=) pre_constant(NULL)operator(;) + ident(UuidToString) operator((&)ident(uuid)operator(,) operator(&)ident(uuidstring)operator(\);) + reserved(if) operator((!)ident(uuidstring)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(Unable to read uuid)delimiter(")>operator(\);) + ident(seed) operator(=) pre_type(string) operator((()directive(const) pre_type(char)operator(*\))ident(uuidstring)operator(\);) + + ident(RpcStringFree) operator((&)ident(uuidstring)operator(\);) + preprocessor(#endif) + + ident(index) operator(=) integer(0)operator(;) + + + operator(}) + + ident(stringstream) ident(ss)operator(;) + ident(ss) operator(<<) ident(seed) operator(<<) operator((++)ident(index)operator(\);) + reserved(return) ident(ss)operator(.)ident(str)operator((\);) +operator(}) + + +comment(/***************************** +STATIC: Bindable_t::GetObject +*****************************/) + +ident(Bindable_t) operator(*)ident(Bindable_t)operator(::)ident(GetObject) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(\)) +operator({) + pre_type(string) ident(s) operator(()ident(binding) operator(?) ident(binding) operator(:) string<delimiter(")delimiter(")>operator(\);) + reserved(return) ident(GetObject) operator(()ident(s)operator(\);) +operator(}) + +comment(/***************************** +STATIC: Bindable_t::GetObject +*****************************/) + +ident(Bindable_t) operator(*)ident(Bindable_t)operator(::)ident(GetObject) operator(()directive(const) pre_type(string) operator(&)ident(binding)operator(\)) +operator({) + ident(map)operator(<)pre_type(string)operator(,) ident(Bindable_t)operator(*>::)ident(const_iterator) ident(i) operator(=) ident(BindingBag)operator(.)ident(find) operator(()ident(binding)operator(\);) + reserved(if) operator(()ident(i) operator(!=) ident(BindingBag)operator(.)ident(end)operator((\)\)) + reserved(return) ident(i)operator(->)ident(second)operator(;) + reserved(else) + reserved(return) pre_constant(NULL)operator(;) +operator(}) + + +comment(/********************** +Bindable_t::Bindable_t +**********************/) + +ident(Bindable_t)operator(::)ident(Bindable_t)operator((\)) +operator({) + ident(Binding) operator(=) ident(Bindable_t)operator(::)ident(CreateBinding)operator((\);) + ident(BindingBag) operator([)ident(Binding)operator(]) operator(=) local_variable(this)operator(;) +operator(}) + + + +comment(/*********************** +Bindable_t::~Bindable_t +***********************/) + +ident(Bindable_t)operator(::~)ident(Bindable_t)operator((\)) +operator({) + ident(BindingBag)operator(.)ident(erase) operator(()ident(Binding)operator(\);) +operator(}) + + +comment(/***************************************************************************** + +$Id$ + +File: cmain.cpp +Date: 06Apr06 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + +preprocessor(#include) include("project.h") + + +directive(static) ident(EventMachine_t) operator(*)ident(EventMachine)operator(;) +directive(static) pre_type(int) ident(bUseEpoll) operator(=) integer(0)operator(;) +directive(static) pre_type(int) ident(bUseKqueue) operator(=) integer(0)operator(;) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(ensure_eventmachine) operator(()directive(const) pre_type(char) operator(*)ident(caller) operator(=) string<delimiter(")content(unknown caller)delimiter(")>operator(\)) +operator({) + reserved(if) operator((!)ident(EventMachine)operator(\)) operator({) + directive(const) pre_type(int) ident(err_size) operator(=) integer(128)operator(;) + pre_type(char) ident(err_string)operator([)ident(err_size)operator(];) + ident(snprintf) operator(()ident(err_string)operator(,) ident(err_size)operator(,) string<delimiter(")content(eventmachine not initialized: %s)delimiter(")>operator(,) ident(caller)operator(\);) + preprocessor(#ifdef) ident(BUILD_FOR_RUBY) + ident(rb_raise)operator(()ident(rb_eRuntimeError)operator(,) ident(err_string)operator(\);) + preprocessor(#else) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()ident(err_string)operator(\);) + preprocessor(#endif) + operator(}) +operator(}) + +comment(/*********************** +evma_initialize_library +***********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_initialize_library) operator(()directive(void)operator((*)ident(cb)operator(\)()directive(const) pre_type(char)operator(*,) pre_type(int)operator(,) directive(const) pre_type(char)operator(*,) pre_type(int)operator(\)\)) +operator({) + comment(// Probably a bad idea to mess with the signal mask of a process) + comment(// we're just being linked into.) + comment(//InstallSignalHandlers(\);) + reserved(if) operator(()ident(EventMachine)operator(\)) + preprocessor(#ifdef) ident(BUILD_FOR_RUBY) + ident(rb_raise)operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(eventmachine already initialized: evma_initialize_library)delimiter(")>operator(\);) + preprocessor(#else) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(eventmachine already initialized: evma_initialize_library)delimiter(")>operator(\);) + preprocessor(#endif) + ident(EventMachine) operator(=) reserved(new) ident(EventMachine_t) operator(()ident(cb)operator(\);) + reserved(if) operator(()ident(bUseEpoll)operator(\)) + ident(EventMachine)operator(->)ident(_UseEpoll)operator((\);) + reserved(if) operator(()ident(bUseKqueue)operator(\)) + ident(EventMachine)operator(->)ident(_UseKqueue)operator((\);) +operator(}) + + +comment(/******************** +evma_release_library +********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_release_library)operator((\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_release_library)delimiter(")>operator(\);) + reserved(delete) ident(EventMachine)operator(;) + ident(EventMachine) operator(=) pre_constant(NULL)operator(;) +operator(}) + + +comment(/**************** +evma_run_machine +****************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_run_machine)operator((\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_run_machine)delimiter(")>operator(\);) + ident(EventMachine)operator(->)ident(Run)operator((\);) +operator(}) + + +comment(/************************** +evma_install_oneshot_timer +**************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(const) pre_type(char) operator(*)ident(evma_install_oneshot_timer) operator(()pre_type(int) ident(seconds)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_install_oneshot_timer)delimiter(")>operator(\);) + reserved(return) ident(EventMachine)operator(->)ident(InstallOneshotTimer) operator(()ident(seconds)operator(\);) +operator(}) + + +comment(/********************** +evma_connect_to_server +**********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(const) pre_type(char) operator(*)ident(evma_connect_to_server) operator(()directive(const) pre_type(char) operator(*)ident(server)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_connect_to_server)delimiter(")>operator(\);) + reserved(return) ident(EventMachine)operator(->)ident(ConnectToServer) operator(()ident(server)operator(,) ident(port)operator(\);) +operator(}) + +comment(/*************************** +evma_connect_to_unix_server +***************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(const) pre_type(char) operator(*)ident(evma_connect_to_unix_server) operator(()directive(const) pre_type(char) operator(*)ident(server)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_connect_to_unix_server)delimiter(")>operator(\);) + reserved(return) ident(EventMachine)operator(->)ident(ConnectToUnixServer) operator(()ident(server)operator(\);) +operator(}) + +comment(/************** +evma_attach_fd +**************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(const) pre_type(char) operator(*)ident(evma_attach_fd) operator(()pre_type(int) ident(file_descriptor)operator(,) pre_type(int) ident(notify_readable)operator(,) pre_type(int) ident(notify_writable)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_attach_fd)delimiter(")>operator(\);) + reserved(return) ident(EventMachine)operator(->)ident(AttachFD) operator(()ident(file_descriptor)operator(,) operator(()ident(notify_readable) operator(?) pre_constant(true) operator(:) pre_constant(false)operator(\),) operator(()ident(notify_writable) operator(?) pre_constant(true) operator(:) pre_constant(false)operator(\)\);) +operator(}) + +comment(/************** +evma_detach_fd +**************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_detach_fd) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_dettach_fd)delimiter(")>operator(\);) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) reserved(dynamic_cast) operator(<)ident(EventableDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ed)operator(\)) + reserved(return) ident(EventMachine)operator(->)ident(DetachFD) operator(()ident(ed)operator(\);) + reserved(else) + preprocessor(#ifdef) ident(BUILD_FOR_RUBY) + ident(rb_raise)operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(invalid binding to detach)delimiter(")>operator(\);) + preprocessor(#else) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(invalid binding to detach)delimiter(")>operator(\);) + preprocessor(#endif) +operator(}) + +comment(/********************** +evma_create_tcp_server +**********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(const) pre_type(char) operator(*)ident(evma_create_tcp_server) operator(()directive(const) pre_type(char) operator(*)ident(address)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_create_tcp_server)delimiter(")>operator(\);) + reserved(return) ident(EventMachine)operator(->)ident(CreateTcpServer) operator(()ident(address)operator(,) ident(port)operator(\);) +operator(}) + +comment(/****************************** +evma_create_unix_domain_server +******************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(const) pre_type(char) operator(*)ident(evma_create_unix_domain_server) operator(()directive(const) pre_type(char) operator(*)ident(filename)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_create_unix_domain_server)delimiter(")>operator(\);) + reserved(return) ident(EventMachine)operator(->)ident(CreateUnixDomainServer) operator(()ident(filename)operator(\);) +operator(}) + +comment(/************************* +evma_open_datagram_socket +*************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(const) pre_type(char) operator(*)ident(evma_open_datagram_socket) operator(()directive(const) pre_type(char) operator(*)ident(address)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_open_datagram_socket)delimiter(")>operator(\);) + reserved(return) ident(EventMachine)operator(->)ident(OpenDatagramSocket) operator(()ident(address)operator(,) ident(port)operator(\);) +operator(}) + +comment(/****************** +evma_open_keyboard +******************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(const) pre_type(char) operator(*)ident(evma_open_keyboard)operator((\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_open_keyboard)delimiter(")>operator(\);) + reserved(return) ident(EventMachine)operator(->)ident(OpenKeyboard)operator((\);) +operator(}) + + + +comment(/**************************** +evma_send_data_to_connection +****************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_send_data_to_connection) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(data_length)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_send_data_to_connection)delimiter(")>operator(\);) + reserved(return) ident(ConnectionDescriptor)operator(::)ident(SendDataToConnection) operator(()ident(binding)operator(,) ident(data)operator(,) ident(data_length)operator(\);) +operator(}) + +comment(/****************** +evma_send_datagram +******************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_send_datagram) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(data_length)operator(,) directive(const) pre_type(char) operator(*)ident(address)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_send_datagram)delimiter(")>operator(\);) + reserved(return) ident(DatagramDescriptor)operator(::)ident(SendDatagram) operator(()ident(binding)operator(,) ident(data)operator(,) ident(data_length)operator(,) ident(address)operator(,) ident(port)operator(\);) +operator(}) + + +comment(/********************* +evma_close_connection +*********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_close_connection) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) pre_type(int) ident(after_writing)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_close_connection)delimiter(")>operator(\);) + ident(ConnectionDescriptor)operator(::)ident(CloseConnection) operator(()ident(binding)operator(,) operator(()ident(after_writing) operator(?) pre_constant(true) operator(:) pre_constant(false)operator(\)\);) +operator(}) + +comment(/*********************************** +evma_report_connection_error_status +***********************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_report_connection_error_status) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_report_connection_error_status)delimiter(")>operator(\);) + reserved(return) ident(ConnectionDescriptor)operator(::)ident(ReportErrorStatus) operator(()ident(binding)operator(\);) +operator(}) + +comment(/******************** +evma_stop_tcp_server +********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_stop_tcp_server) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_stop_tcp_server)delimiter(")>operator(\);) + ident(AcceptorDescriptor)operator(::)ident(StopAcceptor) operator(()ident(binding)operator(\);) +operator(}) + + +comment(/***************** +evma_stop_machine +*****************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_stop_machine)operator((\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_stop_machine)delimiter(")>operator(\);) + ident(EventMachine)operator(->)ident(ScheduleHalt)operator((\);) +operator(}) + + +comment(/************** +evma_start_tls +**************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_start_tls) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_start_tls)delimiter(")>operator(\);) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) reserved(dynamic_cast) operator(<)ident(EventableDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ed)operator(\)) + ident(ed)operator(->)ident(StartTls)operator((\);) +operator(}) + +comment(/****************** +evma_set_tls_parms +******************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_set_tls_parms) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) directive(const) pre_type(char) operator(*)ident(privatekey_filename)operator(,) directive(const) pre_type(char) operator(*)ident(certchain_filename)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_set_tls_parms)delimiter(")>operator(\);) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) reserved(dynamic_cast) operator(<)ident(EventableDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ed)operator(\)) + ident(ed)operator(->)ident(SetTlsParms) operator(()ident(privatekey_filename)operator(,) ident(certchain_filename)operator(\);) +operator(}) + + +comment(/***************** +evma_get_peername +*****************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_get_peername) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) reserved(struct) ident(sockaddr) operator(*)ident(sa)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_get_peername)delimiter(")>operator(\);) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) reserved(dynamic_cast) operator(<)ident(EventableDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ed)operator(\)) operator({) + reserved(return) ident(ed)operator(->)ident(GetPeername) operator(()ident(sa)operator(\)) operator(?) integer(1) operator(:) integer(0)operator(;) + operator(}) + reserved(else) + reserved(return) integer(0)operator(;) +operator(}) + +comment(/***************** +evma_get_sockname +*****************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_get_sockname) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) reserved(struct) ident(sockaddr) operator(*)ident(sa)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_get_sockname)delimiter(")>operator(\);) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) reserved(dynamic_cast) operator(<)ident(EventableDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ed)operator(\)) operator({) + reserved(return) ident(ed)operator(->)ident(GetSockname) operator(()ident(sa)operator(\)) operator(?) integer(1) operator(:) integer(0)operator(;) + operator(}) + reserved(else) + reserved(return) integer(0)operator(;) +operator(}) + +comment(/*********************** +evma_get_subprocess_pid +***********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_get_subprocess_pid) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) ident(pid_t) operator(*)ident(pid)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_get_subprocess_pid)delimiter(")>operator(\);) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) reserved(dynamic_cast) operator(<)ident(EventableDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ed)operator(\)) operator({) + reserved(return) ident(ed)operator(->)ident(GetSubprocessPid) operator(()ident(pid)operator(\)) operator(?) integer(1) operator(:) integer(0)operator(;) + operator(}) + reserved(else) + reserved(return) integer(0)operator(;) +operator(}) + +comment(/************************** +evma_get_subprocess_status +**************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_get_subprocess_status) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) pre_type(int) operator(*)ident(status)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_get_subprocess_status)delimiter(")>operator(\);) + reserved(if) operator(()ident(status)operator(\)) operator({) + operator(*)ident(status) operator(=) ident(EventMachine)operator(->)ident(SubprocessExitStatus)operator(;) + reserved(return) integer(1)operator(;) + operator(}) + reserved(else) + reserved(return) integer(0)operator(;) +operator(}) + + +comment(/********************* +evma_signal_loopbreak +*********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_signal_loopbreak)operator((\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_signal_loopbreak)delimiter(")>operator(\);) + ident(EventMachine)operator(->)ident(SignalLoopBreaker)operator((\);) +operator(}) + + + +comment(/**************** +evma__write_file +****************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(const) pre_type(char) operator(*)ident(evma__write_file) operator(()directive(const) pre_type(char) operator(*)ident(filename)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma__write_file)delimiter(")>operator(\);) + reserved(return) ident(EventMachine)operator(->)ident(_OpenFileForWriting) operator(()ident(filename)operator(\);) +operator(}) + + +comment(/******************************** +evma_get_comm_inactivity_timeout +********************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_get_comm_inactivity_timeout) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) pre_type(int) operator(*)ident(value)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_get_comm_inactivity_timeout)delimiter(")>operator(\);) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) reserved(dynamic_cast) operator(<)ident(EventableDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ed)operator(\)) operator({) + reserved(return) ident(ed)operator(->)ident(GetCommInactivityTimeout) operator(()ident(value)operator(\);) + operator(}) + reserved(else) + reserved(return) integer(0)operator(;) comment(//Perhaps this should be an exception. Access to an unknown binding.) +operator(}) + +comment(/******************************** +evma_set_comm_inactivity_timeout +********************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_set_comm_inactivity_timeout) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) pre_type(int) operator(*)ident(value)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_set_comm_inactivity_timeout)delimiter(")>operator(\);) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) reserved(dynamic_cast) operator(<)ident(EventableDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ed)operator(\)) operator({) + reserved(return) ident(ed)operator(->)ident(SetCommInactivityTimeout) operator(()ident(value)operator(\);) + operator(}) + reserved(else) + reserved(return) integer(0)operator(;) comment(//Perhaps this should be an exception. Access to an unknown binding.) +operator(}) + + +comment(/********************** +evma_set_timer_quantum +**********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_set_timer_quantum) operator(()pre_type(int) ident(interval)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_set_timer_quantum)delimiter(")>operator(\);) + ident(EventMachine)operator(->)ident(SetTimerQuantum) operator(()ident(interval)operator(\);) +operator(}) + +comment(/************************ +evma_set_max_timer_count +************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_set_max_timer_count) operator(()pre_type(int) ident(ct)operator(\)) +operator({) + comment(// This may only be called if the reactor is not running.) + + reserved(if) operator(()ident(EventMachine)operator(\)) + preprocessor(#ifdef) ident(BUILD_FOR_RUBY) + ident(rb_raise)operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(eventmachine already initialized: evma_set_max_timer_count)delimiter(")>operator(\);) + preprocessor(#else) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(eventmachine already initialized: evma_set_max_timer_count)delimiter(")>operator(\);) + preprocessor(#endif) + ident(EventMachine_t)operator(::)ident(SetMaxTimerCount) operator(()ident(ct)operator(\);) +operator(}) + +comment(/****************** +evma_setuid_string +******************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma_setuid_string) operator(()directive(const) pre_type(char) operator(*)ident(username)operator(\)) +operator({) + comment(// We do NOT need to be running an EM instance because this method is static.) + ident(EventMachine_t)operator(::)ident(SetuidString) operator(()ident(username)operator(\);) +operator(}) + + +comment(/********** +evma_popen +**********/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(const) pre_type(char) operator(*)ident(evma_popen) operator(()pre_type(char) operator(*) directive(const)operator(*)ident(cmd_strings)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_popen)delimiter(")>operator(\);) + reserved(return) ident(EventMachine)operator(->)ident(Socketpair) operator(()ident(cmd_strings)operator(\);) +operator(}) + + +comment(/*************************** +evma_get_outbound_data_size +***************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_get_outbound_data_size) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(\)) +operator({) + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_get_outbound_data_size)delimiter(")>operator(\);) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) reserved(dynamic_cast) operator(<)ident(EventableDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(return) ident(ed) operator(?) ident(ed)operator(->)ident(GetOutboundDataSize)operator((\)) operator(:) integer(0)operator(;) +operator(}) + + +comment(/*********** +evma__epoll +***********/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma__epoll)operator((\)) +operator({) + ident(bUseEpoll) operator(=) integer(1)operator(;) +operator(}) + +comment(/************ +evma__kqueue +************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(evma__kqueue)operator((\)) +operator({) + ident(bUseKqueue) operator(=) integer(1)operator(;) +operator(}) + + +comment(/********************** +evma_set_rlimit_nofile +**********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_set_rlimit_nofile) operator(()pre_type(int) ident(nofiles)operator(\)) +operator({) + reserved(return) ident(EventMachine_t)operator(::)ident(SetRlimitNofile) operator(()ident(nofiles)operator(\);) +operator(}) + + +comment(/********************************* +evma_send_file_data_to_connection +*********************************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(evma_send_file_data_to_connection) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) directive(const) pre_type(char) operator(*)ident(filename)operator(\)) +operator({) + comment(/* This is a sugaring over send_data_to_connection that reads a file into a + * locally-allocated buffer, and sends the file data to the remote peer. + * Return the number of bytes written to the caller. + * TODO, needs to impose a limit on the file size. This is intended only for + * small files. (I don't know, maybe 8K or less.\) For larger files, use interleaved + * I/O to avoid slowing the rest of the system down. + * TODO: we should return a code rather than barf, in case of file-not-found. + * TODO, does this compile on Windows? + * TODO, given that we want this to work only with small files, how about allocating + * the buffer on the stack rather than the heap? + * + * Modified 25Jul07. This now returns -1 on file-too-large; 0 for success, and a positive + * errno in case of other errors. + * + /* Contributed by Kirk Haines. + */) + + pre_type(char) ident(data)operator([)integer(32)operator(*)integer(1024)operator(];) + pre_type(int) ident(r)operator(;) + + ident(ensure_eventmachine)operator(()string<delimiter(")content(evma_send_file_data_to_connection)delimiter(")>operator(\);) + + pre_type(int) ident(Fd) operator(=) ident(open) operator(()ident(filename)operator(,) ident(O_RDONLY)operator(\);) + + reserved(if) operator(()ident(Fd) operator(<) integer(0)operator(\)) + reserved(return) ident(errno)operator(;) + comment(// From here on, all early returns MUST close Fd.) + + reserved(struct) ident(stat) ident(st)operator(;) + reserved(if) operator(()ident(fstat) operator(()ident(Fd)operator(,) operator(&)ident(st)operator(\)\)) operator({) + pre_type(int) ident(e) operator(=) ident(errno)operator(;) + ident(close) operator(()ident(Fd)operator(\);) + reserved(return) ident(e)operator(;) + operator(}) + + pre_type(int) ident(filesize) operator(=) ident(st)operator(.)ident(st_size)operator(;) + reserved(if) operator(()ident(filesize) operator(<=) integer(0)operator(\)) operator({) + ident(close) operator(()ident(Fd)operator(\);) + reserved(return) integer(0)operator(;) + operator(}) + reserved(else) reserved(if) operator(()ident(filesize) operator(>) reserved(sizeof)operator(()ident(data)operator(\)\)) operator({) + ident(close) operator(()ident(Fd)operator(\);) + reserved(return) operator(-)integer(1)operator(;) + operator(}) + + + ident(r) operator(=) ident(read) operator(()ident(Fd)operator(,) ident(data)operator(,) ident(filesize)operator(\);) + reserved(if) operator(()ident(r) operator(!=) ident(filesize)operator(\)) operator({) + pre_type(int) ident(e) operator(=) ident(errno)operator(;) + ident(close) operator(()ident(Fd)operator(\);) + reserved(return) ident(e)operator(;) + operator(}) + ident(evma_send_data_to_connection) operator(()ident(binding)operator(,) ident(data)operator(,) ident(r)operator(\);) + ident(close) operator(()ident(Fd)operator(\);) + + reserved(return) integer(0)operator(;) +operator(}) + +comment(/***************************************************************************** + +$Id$ + +File: cplusplus.cpp +Date: 27Jul07 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + + +preprocessor(#include) include("project.h") + + +reserved(namespace) ident(EM) operator({) + directive(static) ident(map)operator(<)pre_type(string)operator(,) ident(Eventable)operator(*>) ident(Eventables)operator(;) + directive(static) ident(map)operator(<)pre_type(string)operator(,) directive(void)operator((*\)(\)>) ident(Timers)operator(;) +operator(}) + + +comment(/******* +EM::Run +*******/) + +directive(void) ident(EM)operator(::)ident(Run) operator(()directive(void) operator((*)ident(start_func)operator(\)(\)\)) +operator({) + ident(evma__epoll)operator((\);) + ident(evma_initialize_library) operator(()ident(EM)operator(::)ident(Callback)operator(\);) + reserved(if) operator(()ident(start_func)operator(\)) + ident(AddTimer) operator(()integer(0)operator(,) ident(start_func)operator(\);) + ident(evma_run_machine)operator((\);) + ident(evma_release_library)operator((\);) +operator(}) + +comment(/************ +EM::AddTimer +************/) + +directive(void) ident(EM)operator(::)ident(AddTimer) operator(()pre_type(int) ident(milliseconds)operator(,) directive(void) operator((*)ident(func)operator(\)(\)\)) +operator({) + reserved(if) operator(()ident(func)operator(\)) operator({) + directive(const) pre_type(char) operator(*)ident(sig) operator(=) ident(evma_install_oneshot_timer) operator(()ident(milliseconds)operator(\);) + ident(Timers)operator(.)ident(insert) operator(()ident(make_pair) operator(()ident(sig)operator(,) ident(func)operator(\)\);) + operator(}) +operator(}) + + +comment(/*************** +EM::StopReactor +***************/) + +directive(void) ident(EM)operator(::)ident(StopReactor)operator((\)) +operator({) + ident(evma_stop_machine)operator((\);) +operator(}) + + +comment(/******************** +EM::Acceptor::Accept +********************/) + +directive(void) ident(EM)operator(::)ident(Acceptor)operator(::)ident(Accept) operator(()directive(const) pre_type(char) operator(*)ident(signature)operator(\)) +operator({) + ident(Connection) operator(*)ident(c) operator(=) ident(MakeConnection)operator((\);) + ident(c)operator(->)ident(Signature) operator(=) ident(signature)operator(;) + ident(Eventables)operator(.)ident(insert) operator(()ident(make_pair) operator(()ident(c)operator(->)ident(Signature)operator(,) ident(c)operator(\)\);) + ident(c)operator(->)ident(PostInit)operator((\);) +operator(}) + +comment(/************************ +EM::Connection::SendData +************************/) + +directive(void) ident(EM)operator(::)ident(Connection)operator(::)ident(SendData) operator(()directive(const) pre_type(char) operator(*)ident(data)operator(\)) +operator({) + reserved(if) operator(()ident(data)operator(\)) + ident(SendData) operator(()ident(data)operator(,) ident(strlen) operator(()ident(data)operator(\)\);) +operator(}) + + +comment(/************************ +EM::Connection::SendData +************************/) + +directive(void) ident(EM)operator(::)ident(Connection)operator(::)ident(SendData) operator(()directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(length)operator(\)) +operator({) + ident(evma_send_data_to_connection) operator(()ident(Signature)operator(.)ident(c_str)operator((\),) ident(data)operator(,) ident(length)operator(\);) +operator(}) + + +comment(/********************* +EM::Connection::Close +*********************/) + +directive(void) ident(EM)operator(::)ident(Connection)operator(::)ident(Close) operator(()pre_type(bool) ident(afterWriting)operator(\)) +operator({) + ident(evma_close_connection) operator(()ident(Signature)operator(.)ident(c_str)operator((\),) ident(afterWriting)operator(\);) +operator(}) + + +comment(/*********************** +EM::Connection::Connect +***********************/) + +directive(void) ident(EM)operator(::)ident(Connection)operator(::)ident(Connect) operator(()directive(const) pre_type(char) operator(*)ident(host)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + ident(Signature) operator(=) ident(evma_connect_to_server) operator(()ident(host)operator(,) ident(port)operator(\);) + ident(Eventables)operator(.)ident(insert)operator(() ident(make_pair) operator(()ident(Signature)operator(,) local_variable(this)operator(\)\);) +operator(}) + +comment(/******************* +EM::Acceptor::Start +*******************/) + +directive(void) ident(EM)operator(::)ident(Acceptor)operator(::)ident(Start) operator(()directive(const) pre_type(char) operator(*)ident(host)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + ident(Signature) operator(=) ident(evma_create_tcp_server) operator(()ident(host)operator(,) ident(port)operator(\);) + ident(Eventables)operator(.)ident(insert)operator(() ident(make_pair) operator(()ident(Signature)operator(,) local_variable(this)operator(\)\);) +operator(}) + + + +comment(/************ +EM::Callback +************/) + +directive(void) ident(EM)operator(::)ident(Callback) operator(()directive(const) pre_type(char) operator(*)ident(sig)operator(,) pre_type(int) ident(ev)operator(,) directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(length)operator(\)) +operator({) + ident(EM)operator(::)ident(Eventable) operator(*)ident(e)operator(;) + directive(void) operator((*)ident(f)operator(\)(\);) + + reserved(switch) operator(()ident(ev)operator(\)) operator({) + reserved(case) label(EM_TIMER_FIRED)operator(:) + ident(f) operator(=) ident(Timers) operator([)ident(data)operator(];) + reserved(if) operator(()ident(f)operator(\)) + operator((*)ident(f)operator(\)(\);) + ident(Timers)operator(.)ident(erase) operator(()ident(sig)operator(\);) + reserved(break)operator(;) + + reserved(case) label(EM_CONNECTION_READ)operator(:) + ident(e) operator(=) ident(EM)operator(::)ident(Eventables) operator([)ident(sig)operator(];) + ident(e)operator(->)ident(ReceiveData) operator(()ident(data)operator(,) ident(length)operator(\);) + reserved(break)operator(;) + + reserved(case) label(EM_CONNECTION_COMPLETED)operator(:) + ident(e) operator(=) ident(EM)operator(::)ident(Eventables) operator([)ident(sig)operator(];) + ident(e)operator(->)ident(ConnectionCompleted)operator((\);) + reserved(break)operator(;) + + reserved(case) label(EM_CONNECTION_ACCEPTED)operator(:) + ident(e) operator(=) ident(EM)operator(::)ident(Eventables) operator([)ident(sig)operator(];) + ident(e)operator(->)ident(Accept) operator(()ident(data)operator(\);) + reserved(break)operator(;) + + reserved(case) label(EM_CONNECTION_UNBOUND)operator(:) + ident(e) operator(=) ident(EM)operator(::)ident(Eventables) operator([)ident(sig)operator(];) + ident(e)operator(->)ident(Unbind)operator((\);) + ident(EM)operator(::)ident(Eventables)operator(.)ident(erase) operator(()ident(sig)operator(\);) + reserved(delete) ident(e)operator(;) + reserved(break)operator(;) + operator(}) +operator(}) + +comment(/***************************************************************************** + +$Id$ + +File: ed.cpp +Date: 06Apr06 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + +preprocessor(#include) include("project.h") + + + +comment(/******************** +SetSocketNonblocking +********************/) + +pre_type(bool) ident(SetSocketNonblocking) operator(()ident(SOCKET) ident(sd)operator(\)) +operator({) + preprocessor(#ifdef) ident(OS_UNIX) + pre_type(int) ident(val) operator(=) ident(fcntl) operator(()ident(sd)operator(,) ident(F_GETFL)operator(,) integer(0)operator(\);) + reserved(return) operator(()ident(fcntl) operator(()ident(sd)operator(,) ident(F_SETFL)operator(,) ident(val) operator(|) ident(O_NONBLOCK)operator(\)) operator(!=) ident(SOCKET_ERROR)operator(\)) operator(?) pre_constant(true) operator(:) pre_constant(false)operator(;) + preprocessor(#endif) + + preprocessor(#ifdef) ident(OS_WIN32) + pre_type(unsigned) pre_type(long) ident(one) operator(=) integer(1)operator(;) + reserved(return) operator(()ident(ioctlsocket) operator(()ident(sd)operator(,) ident(FIONBIO)operator(,) operator(&)ident(one)operator(\)) operator(==) integer(0)operator(\)) operator(?) pre_constant(true) operator(:) pre_constant(false)operator(;) + preprocessor(#endif) +operator(}) + + +comment(/**************************************** +EventableDescriptor::EventableDescriptor +****************************************/) + +ident(EventableDescriptor)operator(::)ident(EventableDescriptor) operator(()pre_type(int) ident(sd)operator(,) ident(EventMachine_t) operator(*)ident(em)operator(\):) + ident(bCloseNow) operator(()pre_constant(false)operator(\),) + ident(bCloseAfterWriting) operator(()pre_constant(false)operator(\),) + ident(MySocket) operator(()ident(sd)operator(\),) + ident(EventCallback) operator(()pre_constant(NULL)operator(\),) + ident(LastRead) operator(()integer(0)operator(\),) + ident(LastWritten) operator(()integer(0)operator(\),) + ident(bCallbackUnbind) operator(()pre_constant(true)operator(\),) + ident(MyEventMachine) operator(()ident(em)operator(\)) +operator({) + comment(/* There are three ways to close a socket, all of which should + * automatically signal to the event machine that this object + * should be removed from the polling scheduler. + * First is a hard close, intended for bad errors or possible + * security violations. It immediately closes the connection + * and puts this object into an error state. + * Second is to set bCloseNow, which will cause the event machine + * to delete this object (and thus close the connection in our + * destructor\) the next chance it gets. bCloseNow also inhibits + * the writing of new data on the socket (but not necessarily + * the reading of new data\). + * The third way is to set bCloseAfterWriting, which inhibits + * the writing of new data and converts to bCloseNow as soon + * as everything in the outbound queue has been written. + * bCloseAfterWriting is really for use only by protocol handlers + * (for example, HTTP writes an HTML page and then closes the + * connection\). All of the error states we generate internally + * cause an immediate close to be scheduled, which may have the + * effect of discarding outbound data. + */) + + reserved(if) operator(()ident(sd) operator(==) ident(INVALID_SOCKET)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad eventable descriptor)delimiter(")>operator(\);) + reserved(if) operator(()ident(MyEventMachine) operator(==) pre_constant(NULL)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad em in eventable descriptor)delimiter(")>operator(\);) + ident(CreatedAt) operator(=) ident(gCurrentLoopTime)operator(;) + + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(data)operator(.)ident(ptr) operator(=) local_variable(this)operator(;) + preprocessor(#endif) +operator(}) + + +comment(/***************************************** +EventableDescriptor::~EventableDescriptor +*****************************************/) + +ident(EventableDescriptor)operator(::~)ident(EventableDescriptor)operator((\)) +operator({) + reserved(if) operator(()ident(EventCallback) operator(&&) ident(bCallbackUnbind)operator(\)) + operator((*)ident(EventCallback)operator(\)()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_UNBOUND)operator(,) pre_constant(NULL)operator(,) integer(0)operator(\);) + ident(Close)operator((\);) +operator(}) + + +comment(/************************************* +EventableDescriptor::SetEventCallback +*************************************/) + +directive(void) ident(EventableDescriptor)operator(::)ident(SetEventCallback) operator(()directive(void)operator((*)ident(cb)operator(\)()directive(const) pre_type(char)operator(*,) pre_type(int)operator(,) directive(const) pre_type(char)operator(*,) pre_type(int)operator(\)\)) +operator({) + ident(EventCallback) operator(=) ident(cb)operator(;) +operator(}) + + +comment(/************************** +EventableDescriptor::Close +**************************/) + +directive(void) ident(EventableDescriptor)operator(::)ident(Close)operator((\)) +operator({) + comment(// Close the socket right now. Intended for emergencies.) + reserved(if) operator(()ident(MySocket) operator(!=) ident(INVALID_SOCKET)operator(\)) operator({) + ident(shutdown) operator(()ident(MySocket)operator(,) integer(1)operator(\);) + ident(closesocket) operator(()ident(MySocket)operator(\);) + ident(MySocket) operator(=) ident(INVALID_SOCKET)operator(;) + operator(}) +operator(}) + + +comment(/********************************* +EventableDescriptor::ShouldDelete +*********************************/) + +pre_type(bool) ident(EventableDescriptor)operator(::)ident(ShouldDelete)operator((\)) +operator({) + comment(/* For use by a socket manager, which needs to know if this object + * should be removed from scheduling events and deleted. + * Has an immediate close been scheduled, or are we already closed? + * If either of these are the case, return true. In theory, the manager will + * then delete us, which in turn will make sure the socket is closed. + * Note, if bCloseAfterWriting is true, we check a virtual method to see + * if there is outbound data to write, and only request a close if there is none. + */) + + reserved(return) operator((()ident(MySocket) operator(==) ident(INVALID_SOCKET)operator(\)) operator(||) ident(bCloseNow) operator(||) operator(()ident(bCloseAfterWriting) operator(&&) operator(()ident(GetOutboundDataSize)operator((\)) operator(<=) integer(0)operator(\)\)\);) +operator(}) + + +comment(/********************************** +EventableDescriptor::ScheduleClose +**********************************/) + +directive(void) ident(EventableDescriptor)operator(::)ident(ScheduleClose) operator(()pre_type(bool) ident(after_writing)operator(\)) +operator({) + comment(// KEEP THIS SYNCHRONIZED WITH ::IsCloseScheduled.) + reserved(if) operator(()ident(after_writing)operator(\)) + ident(bCloseAfterWriting) operator(=) pre_constant(true)operator(;) + reserved(else) + ident(bCloseNow) operator(=) pre_constant(true)operator(;) +operator(}) + + +comment(/************************************* +EventableDescriptor::IsCloseScheduled +*************************************/) + +pre_type(bool) ident(EventableDescriptor)operator(::)ident(IsCloseScheduled)operator((\)) +operator({) + comment(// KEEP THIS SYNCHRONIZED WITH ::ScheduleClose.) + reserved(return) operator(()ident(bCloseNow) operator(||) ident(bCloseAfterWriting)operator(\);) +operator(}) + + +comment(/****************************************** +ConnectionDescriptor::ConnectionDescriptor +******************************************/) + +ident(ConnectionDescriptor)operator(::)ident(ConnectionDescriptor) operator(()pre_type(int) ident(sd)operator(,) ident(EventMachine_t) operator(*)ident(em)operator(\):) + ident(EventableDescriptor) operator(()ident(sd)operator(,) ident(em)operator(\),) + ident(bConnectPending) operator(()pre_constant(false)operator(\),) + ident(bNotifyReadable) operator(()pre_constant(false)operator(\),) + ident(bNotifyWritable) operator(()pre_constant(false)operator(\),) + ident(bReadAttemptedAfterClose) operator(()pre_constant(false)operator(\),) + ident(bWriteAttemptedAfterClose) operator(()pre_constant(false)operator(\),) + ident(OutboundDataSize) operator(()integer(0)operator(\),) + preprocessor(#ifdef) ident(WITH_SSL) + ident(SslBox) operator(()pre_constant(NULL)operator(\),) + preprocessor(#endif) + ident(bIsServer) operator(()pre_constant(false)operator(\),) + ident(LastIo) operator(()ident(gCurrentLoopTime)operator(\),) + ident(InactivityTimeout) operator(()integer(0)operator(\)) +operator({) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) ident(EPOLLOUT)operator(;) + preprocessor(#endif) + comment(// 22Jan09: Moved ArmKqueueWriter into SetConnectPending(\) to fix assertion failure in _WriteOutboundData(\)) +operator(}) + + +comment(/******************************************* +ConnectionDescriptor::~ConnectionDescriptor +*******************************************/) + +ident(ConnectionDescriptor)operator(::~)ident(ConnectionDescriptor)operator((\)) +operator({) + comment(// Run down any stranded outbound data.) + reserved(for) operator(()ident(size_t) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) ident(OutboundPages)operator(.)ident(size)operator((\);) ident(i)operator(++\)) + ident(OutboundPages)operator([)ident(i)operator(])operator(.)ident(Free)operator((\);) + + preprocessor(#ifdef) ident(WITH_SSL) + reserved(if) operator(()ident(SslBox)operator(\)) + reserved(delete) ident(SslBox)operator(;) + preprocessor(#endif) +operator(}) + + +comment(/************************************************** +STATIC: ConnectionDescriptor::SendDataToConnection +**************************************************/) + +pre_type(int) ident(ConnectionDescriptor)operator(::)ident(SendDataToConnection) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(data_length)operator(\)) +operator({) + comment(// TODO: This is something of a hack, or at least it's a static method of the wrong class.) + comment(// TODO: Poor polymorphism here. We should be calling one virtual method) + comment(// instead of hacking out the runtime information of the target object.) + ident(ConnectionDescriptor) operator(*)ident(cd) operator(=) reserved(dynamic_cast) operator(<)ident(ConnectionDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(cd)operator(\)) + reserved(return) ident(cd)operator(->)ident(SendOutboundData) operator(()ident(data)operator(,) ident(data_length)operator(\);) + ident(DatagramDescriptor) operator(*)ident(ds) operator(=) reserved(dynamic_cast) operator(<)ident(DatagramDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ds)operator(\)) + reserved(return) ident(ds)operator(->)ident(SendOutboundData) operator(()ident(data)operator(,) ident(data_length)operator(\);) + preprocessor(#ifdef) ident(OS_UNIX) + ident(PipeDescriptor) operator(*)ident(ps) operator(=) reserved(dynamic_cast) operator(<)ident(PipeDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ps)operator(\)) + reserved(return) ident(ps)operator(->)ident(SendOutboundData) operator(()ident(data)operator(,) ident(data_length)operator(\);) + preprocessor(#endif) + reserved(return) operator(-)integer(1)operator(;) +operator(}) + + +comment(/********************************************* +STATIC: ConnectionDescriptor::CloseConnection +*********************************************/) + +directive(void) ident(ConnectionDescriptor)operator(::)ident(CloseConnection) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) pre_type(bool) ident(after_writing)operator(\)) +operator({) + comment(// TODO: This is something of a hack, or at least it's a static method of the wrong class.) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) reserved(dynamic_cast) operator(<)ident(EventableDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ed)operator(\)) + ident(ed)operator(->)ident(ScheduleClose) operator(()ident(after_writing)operator(\);) +operator(}) + +comment(/*********************************************** +STATIC: ConnectionDescriptor::ReportErrorStatus +***********************************************/) + +pre_type(int) ident(ConnectionDescriptor)operator(::)ident(ReportErrorStatus) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(\)) +operator({) + comment(// TODO: This is something of a hack, or at least it's a static method of the wrong class.) + comment(// TODO: Poor polymorphism here. We should be calling one virtual method) + comment(// instead of hacking out the runtime information of the target object.) + ident(ConnectionDescriptor) operator(*)ident(cd) operator(=) reserved(dynamic_cast) operator(<)ident(ConnectionDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(cd)operator(\)) + reserved(return) ident(cd)operator(->)ident(_ReportErrorStatus)operator((\);) + reserved(return) operator(-)integer(1)operator(;) +operator(}) + +comment(/*************************************** +ConnectionDescriptor::SetConnectPending +****************************************/) + +directive(void) ident(ConnectionDescriptor)operator(::)ident(SetConnectPending)operator(()pre_type(bool) ident(f)operator(\)) +operator({) + ident(bConnectPending) operator(=) ident(f)operator(;) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + ident(MyEventMachine)operator(->)ident(ArmKqueueWriter) operator(()local_variable(this)operator(\);) + preprocessor(#endif) +operator(}) + + +comment(/************************************** +ConnectionDescriptor::SendOutboundData +**************************************/) + +pre_type(int) ident(ConnectionDescriptor)operator(::)ident(SendOutboundData) operator(()directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(length)operator(\)) +operator({) + preprocessor(#ifdef) ident(WITH_SSL) + reserved(if) operator(()ident(SslBox)operator(\)) operator({) + reserved(if) operator(()ident(length) operator(>) integer(0)operator(\)) operator({) + pre_type(int) ident(w) operator(=) ident(SslBox)operator(->)ident(PutPlaintext) operator(()ident(data)operator(,) ident(length)operator(\);) + reserved(if) operator(()ident(w) operator(<) integer(0)operator(\)) + ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + reserved(else) + ident(_DispatchCiphertext)operator((\);) + operator(}) + comment(// TODO: What's the correct return value?) + reserved(return) integer(1)operator(;) comment(// That's a wild guess, almost certainly wrong.) + operator(}) + reserved(else) + preprocessor(#endif) + reserved(return) ident(_SendRawOutboundData) operator(()ident(data)operator(,) ident(length)operator(\);) +operator(}) + + + +comment(/****************************************** +ConnectionDescriptor::_SendRawOutboundData +******************************************/) + +pre_type(int) ident(ConnectionDescriptor)operator(::)ident(_SendRawOutboundData) operator(()directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(length)operator(\)) +operator({) + comment(/* This internal method is called to schedule bytes that + * will be sent out to the remote peer. + * It's not directly accessed by the caller, who hits ::SendOutboundData, + * which may or may not filter or encrypt the caller's data before + * sending it here. + */) + + comment(// Highly naive and incomplete implementation.) + comment(// There's no throttle for runaways (which should abort only this connection) + comment(// and not the whole process\), and no coalescing of small pages.) + comment(// (Well, not so bad, small pages are coalesced in ::Write\)) + + reserved(if) operator(()ident(IsCloseScheduled)operator((\)\)) + comment(//if (bCloseNow || bCloseAfterWriting\)) + reserved(return) integer(0)operator(;) + + reserved(if) operator((!)ident(data) operator(&&) operator(()ident(length) operator(>) integer(0)operator(\)\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad outbound data)delimiter(")>operator(\);) + pre_type(char) operator(*)ident(buffer) operator(=) operator(()pre_type(char) operator(*\)) ident(malloc) operator(()ident(length) operator(+) integer(1)operator(\);) + reserved(if) operator((!)ident(buffer)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no allocation for outbound data)delimiter(")>operator(\);) + ident(memcpy) operator(()ident(buffer)operator(,) ident(data)operator(,) ident(length)operator(\);) + ident(buffer) operator([)ident(length)operator(]) operator(=) integer(0)operator(;) + ident(OutboundPages)operator(.)ident(push_back) operator(()ident(OutboundPage) operator(()ident(buffer)operator(,) ident(length)operator(\)\);) + ident(OutboundDataSize) operator(+=) ident(length)operator(;) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) operator(()ident(EPOLLIN) operator(|) ident(EPOLLOUT)operator(\);) + ident(assert) operator(()ident(MyEventMachine)operator(\);) + ident(MyEventMachine)operator(->)ident(Modify) operator(()local_variable(this)operator(\);) + preprocessor(#endif) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + ident(MyEventMachine)operator(->)ident(ArmKqueueWriter) operator(()local_variable(this)operator(\);) + preprocessor(#endif) + reserved(return) ident(length)operator(;) +operator(}) + + + +comment(/*********************************** +ConnectionDescriptor::SelectForRead +***********************************/) + +pre_type(bool) ident(ConnectionDescriptor)operator(::)ident(SelectForRead)operator((\)) +operator({) + comment(/* A connection descriptor is always scheduled for read, + * UNLESS it's in a pending-connect state. + * On Linux, unlike Unix, a nonblocking socket on which + * connect has been called, does NOT necessarily select + * both readable and writable in case of error. + * The socket will select writable when the disposition + * of the connect is known. On the other hand, a socket + * which successfully connects and selects writable may + * indeed have some data available on it, so it will + * select readable in that case, violating expectations! + * So we will not poll for readability until the socket + * is known to be in a connected state. + */) + + reserved(return) ident(bConnectPending) operator(?) pre_constant(false) operator(:) pre_constant(true)operator(;) +operator(}) + + +comment(/************************************ +ConnectionDescriptor::SelectForWrite +************************************/) + +pre_type(bool) ident(ConnectionDescriptor)operator(::)ident(SelectForWrite)operator((\)) +operator({) + comment(/* Cf the notes under SelectForRead. + * In a pending-connect state, we ALWAYS select for writable. + * In a normal state, we only select for writable when we + * have outgoing data to send. + */) + + reserved(if) operator(()ident(bConnectPending) operator(||) ident(bNotifyWritable)operator(\)) + reserved(return) pre_constant(true)operator(;) + reserved(else) operator({) + reserved(return) operator(()ident(GetOutboundDataSize)operator((\)) operator(>) integer(0)operator(\);) + operator(}) +operator(}) + + +comment(/************************** +ConnectionDescriptor::Read +**************************/) + +directive(void) ident(ConnectionDescriptor)operator(::)ident(Read)operator((\)) +operator({) + comment(/* Read and dispatch data on a socket that has selected readable. + * It's theoretically possible to get and dispatch incoming data on + * a socket that has already been scheduled for closing or close-after-writing. + * In those cases, we'll leave it up the to protocol handler to "do the + * right thing" (which probably means to ignore the incoming data\). + * + * 22Aug06: Chris Ochs reports that on FreeBSD, it's possible to come + * here with the socket already closed, after the process receives + * a ctrl-C signal (not sure if that's TERM or INT on BSD\). The application + * was one in which network connections were doing a lot of interleaved reads + * and writes. + * Since we always write before reading (in order to keep the outbound queues + * as light as possible\), I think what happened is that an interrupt caused + * the socket to be closed in ConnectionDescriptor::Write. We'll then + * come here in the same pass through the main event loop, and won't get + * cleaned up until immediately after. + * We originally asserted that the socket was valid when we got here. + * To deal properly with the possibility that we are closed when we get here, + * I removed the assert. HOWEVER, the potential for an infinite loop scares me, + * so even though this is really clunky, I added a flag to assert that we never + * come here more than once after being closed. (FCianfrocca\) + */) + + pre_type(int) ident(sd) operator(=) ident(GetSocket)operator((\);) + comment(//assert (sd != INVALID_SOCKET\); (original, removed 22Aug06\)) + reserved(if) operator(()ident(sd) operator(==) ident(INVALID_SOCKET)operator(\)) operator({) + ident(assert) operator((!)ident(bReadAttemptedAfterClose)operator(\);) + ident(bReadAttemptedAfterClose) operator(=) pre_constant(true)operator(;) + reserved(return)operator(;) + operator(}) + + reserved(if) operator(()ident(bNotifyReadable)operator(\)) operator({) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_NOTIFY_READABLE)operator(,) pre_constant(NULL)operator(,) integer(0)operator(\);) + reserved(return)operator(;) + operator(}) + + ident(LastIo) operator(=) ident(gCurrentLoopTime)operator(;) + + pre_type(int) ident(total_bytes_read) operator(=) integer(0)operator(;) + pre_type(char) ident(readbuffer) operator([)integer(16) operator(*) integer(1024) operator(+) integer(1)operator(];) + + reserved(for) operator(()pre_type(int) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) integer(10)operator(;) ident(i)operator(++\)) operator({) + comment(// Don't read just one buffer and then move on. This is faster) + comment(// if there is a lot of incoming.) + comment(// But don't read indefinitely. Give other sockets a chance to run.) + comment(// NOTICE, we're reading one less than the buffer size.) + comment(// That's so we can put a guard byte at the end of what we send) + comment(// to user code.) + + + pre_type(int) ident(r) operator(=) ident(recv) operator(()ident(sd)operator(,) ident(readbuffer)operator(,) reserved(sizeof)operator(()ident(readbuffer)operator(\)) operator(-) integer(1)operator(,) integer(0)operator(\);) + comment(//cerr << "<R:" << r << ">";) + + reserved(if) operator(()ident(r) operator(>) integer(0)operator(\)) operator({) + ident(total_bytes_read) operator(+=) ident(r)operator(;) + ident(LastRead) operator(=) ident(gCurrentLoopTime)operator(;) + + comment(// Add a null-terminator at the the end of the buffer) + comment(// that we will send to the callback.) + comment(// DO NOT EVER CHANGE THIS. We want to explicitly allow users) + comment(// to be able to depend on this behavior, so they will have) + comment(// the option to do some things faster. Additionally it's) + comment(// a security guard against buffer overflows.) + ident(readbuffer) operator([)ident(r)operator(]) operator(=) integer(0)operator(;) + ident(_DispatchInboundData) operator(()ident(readbuffer)operator(,) ident(r)operator(\);) + operator(}) + reserved(else) reserved(if) operator(()ident(r) operator(==) integer(0)operator(\)) operator({) + reserved(break)operator(;) + operator(}) + reserved(else) operator({) + comment(// Basically a would-block, meaning we've read everything there is to read.) + reserved(break)operator(;) + operator(}) + + operator(}) + + + reserved(if) operator(()ident(total_bytes_read) operator(==) integer(0)operator(\)) operator({) + comment(// If we read no data on a socket that selected readable,) + comment(// it generally means the other end closed the connection gracefully.) + ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + comment(//bCloseNow = true;) + operator(}) + +operator(}) + + + +comment(/****************************************** +ConnectionDescriptor::_DispatchInboundData +******************************************/) + +directive(void) ident(ConnectionDescriptor)operator(::)ident(_DispatchInboundData) operator(()directive(const) pre_type(char) operator(*)ident(buffer)operator(,) pre_type(int) ident(size)operator(\)) +operator({) + preprocessor(#ifdef) ident(WITH_SSL) + reserved(if) operator(()ident(SslBox)operator(\)) operator({) + ident(SslBox)operator(->)ident(PutCiphertext) operator(()ident(buffer)operator(,) ident(size)operator(\);) + + pre_type(int) ident(s)operator(;) + pre_type(char) ident(B) operator([)integer(2048)operator(];) + reserved(while) operator((()ident(s) operator(=) ident(SslBox)operator(->)ident(GetPlaintext) operator(()ident(B)operator(,) reserved(sizeof)operator(()ident(B)operator(\)) operator(-) integer(1)operator(\)\)) operator(>) integer(0)operator(\)) operator({) + ident(B) operator([)ident(s)operator(]) operator(=) integer(0)operator(;) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_READ)operator(,) ident(B)operator(,) ident(s)operator(\);) + operator(}) + comment(// INCOMPLETE, s may indicate an SSL error that would force the connection down.) + ident(_DispatchCiphertext)operator((\);) + operator(}) + reserved(else) operator({) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_READ)operator(,) ident(buffer)operator(,) ident(size)operator(\);) + operator(}) + preprocessor(#endif) + + preprocessor(#ifdef) ident(WITHOUT_SSL) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_READ)operator(,) ident(buffer)operator(,) ident(size)operator(\);) + preprocessor(#endif) +operator(}) + + + + + +comment(/*************************** +ConnectionDescriptor::Write +***************************/) + +directive(void) ident(ConnectionDescriptor)operator(::)ident(Write)operator((\)) +operator({) + comment(/* A socket which is in a pending-connect state will select + * writable when the disposition of the connect is known. + * At that point, check to be sure there are no errors, + * and if none, then promote the socket out of the pending + * state. + * TODO: I haven't figured out how Windows signals errors on + * unconnected sockets. Maybe it does the untraditional but + * logical thing and makes the socket selectable for error. + * If so, it's unsupported here for the time being, and connect + * errors will have to be caught by the timeout mechanism. + */) + + reserved(if) operator(()ident(bConnectPending)operator(\)) operator({) + pre_type(int) ident(error)operator(;) + ident(socklen_t) ident(len)operator(;) + ident(len) operator(=) reserved(sizeof)operator(()ident(error)operator(\);) + preprocessor(#ifdef) ident(OS_UNIX) + pre_type(int) ident(o) operator(=) ident(getsockopt) operator(()ident(GetSocket)operator((\),) ident(SOL_SOCKET)operator(,) ident(SO_ERROR)operator(,) operator(&)ident(error)operator(,) operator(&)ident(len)operator(\);) + preprocessor(#endif) + preprocessor(#ifdef) ident(OS_WIN32) + pre_type(int) ident(o) operator(=) ident(getsockopt) operator(()ident(GetSocket)operator((\),) ident(SOL_SOCKET)operator(,) ident(SO_ERROR)operator(,) operator(()pre_type(char)operator(*\)&)ident(error)operator(,) operator(&)ident(len)operator(\);) + preprocessor(#endif) + reserved(if) operator((()ident(o) operator(==) integer(0)operator(\)) operator(&&) operator(()ident(error) operator(==) integer(0)operator(\)\)) operator({) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_COMPLETED)operator(,) string<delimiter(")delimiter(")>operator(,) integer(0)operator(\);) + ident(bConnectPending) operator(=) pre_constant(false)operator(;) + preprocessor(#ifdef) ident(HAVE_EPOLL) + comment(// The callback may have scheduled outbound data.) + ident(EpollEvent)operator(.)ident(events) operator(=) ident(EPOLLIN) operator(|) operator(()ident(SelectForWrite)operator((\)) operator(?) ident(EPOLLOUT) operator(:) integer(0)operator(\);) + preprocessor(#endif) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + ident(MyEventMachine)operator(->)ident(ArmKqueueReader) operator(()local_variable(this)operator(\);) + comment(// The callback may have scheduled outbound data.) + reserved(if) operator(()ident(SelectForWrite)operator((\)\)) + ident(MyEventMachine)operator(->)ident(ArmKqueueWriter) operator(()local_variable(this)operator(\);) + preprocessor(#endif) + operator(}) + reserved(else) + ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + comment(//bCloseNow = true;) + operator(}) + reserved(else) operator({) + + reserved(if) operator(()ident(bNotifyWritable)operator(\)) operator({) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_NOTIFY_WRITABLE)operator(,) pre_constant(NULL)operator(,) integer(0)operator(\);) + reserved(return)operator(;) + operator(}) + + ident(_WriteOutboundData)operator((\);) + operator(}) +operator(}) + + +comment(/**************************************** +ConnectionDescriptor::_WriteOutboundData +****************************************/) + +directive(void) ident(ConnectionDescriptor)operator(::)ident(_WriteOutboundData)operator((\)) +operator({) + comment(/* This is a helper function called by ::Write. + * It's possible for a socket to select writable and then no longer + * be writable by the time we get around to writing. The kernel might + * have used up its available output buffers between the select call + * and when we get here. So this condition is not an error. + * + * 20Jul07, added the same kind of protection against an invalid socket + * that is at the top of ::Read. Not entirely how this could happen in + * real life (connection-reset from the remote peer, perhaps?\), but I'm + * doing it to address some reports of crashing under heavy loads. + */) + + pre_type(int) ident(sd) operator(=) ident(GetSocket)operator((\);) + comment(//assert (sd != INVALID_SOCKET\);) + reserved(if) operator(()ident(sd) operator(==) ident(INVALID_SOCKET)operator(\)) operator({) + ident(assert) operator((!)ident(bWriteAttemptedAfterClose)operator(\);) + ident(bWriteAttemptedAfterClose) operator(=) pre_constant(true)operator(;) + reserved(return)operator(;) + operator(}) + + ident(LastIo) operator(=) ident(gCurrentLoopTime)operator(;) + pre_type(char) ident(output_buffer) operator([)integer(16) operator(*) integer(1024)operator(];) + ident(size_t) ident(nbytes) operator(=) integer(0)operator(;) + + reserved(while) operator((()ident(OutboundPages)operator(.)ident(size)operator((\)) operator(>) integer(0)operator(\)) operator(&&) operator(()ident(nbytes) operator(<) reserved(sizeof)operator(()ident(output_buffer)operator(\)\)\)) operator({) + ident(OutboundPage) operator(*)ident(op) operator(=) operator(&()ident(OutboundPages)operator([)integer(0)operator(]\);) + reserved(if) operator((()ident(nbytes) operator(+) ident(op)operator(->)ident(Length) operator(-) ident(op)operator(->)ident(Offset)operator(\)) operator(<) reserved(sizeof) operator(()ident(output_buffer)operator(\)\)) operator({) + ident(memcpy) operator(()ident(output_buffer) operator(+) ident(nbytes)operator(,) ident(op)operator(->)ident(Buffer) operator(+) ident(op)operator(->)ident(Offset)operator(,) ident(op)operator(->)ident(Length) operator(-) ident(op)operator(->)ident(Offset)operator(\);) + ident(nbytes) operator(+=) operator(()ident(op)operator(->)ident(Length) operator(-) ident(op)operator(->)ident(Offset)operator(\);) + ident(op)operator(->)ident(Free)operator((\);) + ident(OutboundPages)operator(.)ident(pop_front)operator((\);) + operator(}) + reserved(else) operator({) + pre_type(int) ident(len) operator(=) reserved(sizeof)operator(()ident(output_buffer)operator(\)) operator(-) ident(nbytes)operator(;) + ident(memcpy) operator(()ident(output_buffer) operator(+) ident(nbytes)operator(,) ident(op)operator(->)ident(Buffer) operator(+) ident(op)operator(->)ident(Offset)operator(,) ident(len)operator(\);) + ident(op)operator(->)ident(Offset) operator(+=) ident(len)operator(;) + ident(nbytes) operator(+=) ident(len)operator(;) + operator(}) + operator(}) + + comment(// We should never have gotten here if there were no data to write,) + comment(// so assert that as a sanity check.) + comment(// Don't bother to make sure nbytes is less than output_buffer because) + comment(// if it were we probably would have crashed already.) + ident(assert) operator(()ident(nbytes) operator(>) integer(0)operator(\);) + + ident(assert) operator(()ident(GetSocket)operator((\)) operator(!=) ident(INVALID_SOCKET)operator(\);) + pre_type(int) ident(bytes_written) operator(=) ident(send) operator(()ident(GetSocket)operator((\),) ident(output_buffer)operator(,) ident(nbytes)operator(,) integer(0)operator(\);) + + pre_type(bool) ident(err) operator(=) pre_constant(false)operator(;) + reserved(if) operator(()ident(bytes_written) operator(<) integer(0)operator(\)) operator({) + ident(err) operator(=) pre_constant(true)operator(;) + ident(bytes_written) operator(=) integer(0)operator(;) + operator(}) + + ident(assert) operator(()ident(bytes_written) operator(>=) integer(0)operator(\);) + ident(OutboundDataSize) operator(-=) ident(bytes_written)operator(;) + reserved(if) operator((()ident(size_t)operator(\))ident(bytes_written) operator(<) ident(nbytes)operator(\)) operator({) + pre_type(int) ident(len) operator(=) ident(nbytes) operator(-) ident(bytes_written)operator(;) + pre_type(char) operator(*)ident(buffer) operator(=) operator(()pre_type(char)operator(*\)) ident(malloc) operator(()ident(len) operator(+) integer(1)operator(\);) + reserved(if) operator((!)ident(buffer)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad alloc throwing back data)delimiter(")>operator(\);) + ident(memcpy) operator(()ident(buffer)operator(,) ident(output_buffer) operator(+) ident(bytes_written)operator(,) ident(len)operator(\);) + ident(buffer) operator([)ident(len)operator(]) operator(=) integer(0)operator(;) + ident(OutboundPages)operator(.)ident(push_front) operator(()ident(OutboundPage) operator(()ident(buffer)operator(,) ident(len)operator(\)\);) + operator(}) + + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) operator(()ident(EPOLLIN) operator(|) operator(()ident(SelectForWrite)operator((\)) operator(?) ident(EPOLLOUT) operator(:) integer(0)operator(\)\);) + ident(assert) operator(()ident(MyEventMachine)operator(\);) + ident(MyEventMachine)operator(->)ident(Modify) operator(()local_variable(this)operator(\);) + preprocessor(#endif) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + reserved(if) operator(()ident(SelectForWrite)operator((\)\)) + ident(MyEventMachine)operator(->)ident(ArmKqueueWriter) operator(()local_variable(this)operator(\);) + preprocessor(#endif) + + + reserved(if) operator(()ident(err)operator(\)) operator({) + preprocessor(#ifdef) ident(OS_UNIX) + reserved(if) operator((()ident(errno) operator(!=) ident(EINPROGRESS)operator(\)) operator(&&) operator(()ident(errno) operator(!=) ident(EWOULDBLOCK)operator(\)) operator(&&) operator(()ident(errno) operator(!=) ident(EINTR)operator(\)\)) + preprocessor(#endif) + preprocessor(#ifdef) ident(OS_WIN32) + reserved(if) operator((()ident(errno) operator(!=) ident(WSAEINPROGRESS)operator(\)) operator(&&) operator(()ident(errno) operator(!=) ident(WSAEWOULDBLOCK)operator(\)\)) + preprocessor(#endif) + ident(Close)operator((\);) + operator(}) +operator(}) + + +comment(/**************************************** +ConnectionDescriptor::_ReportErrorStatus +****************************************/) + +pre_type(int) ident(ConnectionDescriptor)operator(::)ident(_ReportErrorStatus)operator((\)) +operator({) + pre_type(int) ident(error)operator(;) + ident(socklen_t) ident(len)operator(;) + ident(len) operator(=) reserved(sizeof)operator(()ident(error)operator(\);) + preprocessor(#ifdef) ident(OS_UNIX) + pre_type(int) ident(o) operator(=) ident(getsockopt) operator(()ident(GetSocket)operator((\),) ident(SOL_SOCKET)operator(,) ident(SO_ERROR)operator(,) operator(&)ident(error)operator(,) operator(&)ident(len)operator(\);) + preprocessor(#endif) + preprocessor(#ifdef) ident(OS_WIN32) + pre_type(int) ident(o) operator(=) ident(getsockopt) operator(()ident(GetSocket)operator((\),) ident(SOL_SOCKET)operator(,) ident(SO_ERROR)operator(,) operator(()pre_type(char)operator(*\)&)ident(error)operator(,) operator(&)ident(len)operator(\);) + preprocessor(#endif) + reserved(if) operator((()ident(o) operator(==) integer(0)operator(\)) operator(&&) operator(()ident(error) operator(==) integer(0)operator(\)\)) + reserved(return) integer(0)operator(;) + reserved(else) + reserved(return) integer(1)operator(;) +operator(}) + + +comment(/****************************** +ConnectionDescriptor::StartTls +******************************/) + +directive(void) ident(ConnectionDescriptor)operator(::)ident(StartTls)operator((\)) +operator({) + preprocessor(#ifdef) ident(WITH_SSL) + reserved(if) operator(()ident(SslBox)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(SSL/TLS already running on connection)delimiter(")>operator(\);) + + ident(SslBox) operator(=) reserved(new) ident(SslBox_t) operator(()ident(bIsServer)operator(,) ident(PrivateKeyFilename)operator(,) ident(CertChainFilename)operator(\);) + ident(_DispatchCiphertext)operator((\);) + preprocessor(#endif) + + preprocessor(#ifdef) ident(WITHOUT_SSL) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(Encryption not available on this event-machine)delimiter(")>operator(\);) + preprocessor(#endif) +operator(}) + + +comment(/********************************* +ConnectionDescriptor::SetTlsParms +*********************************/) + +directive(void) ident(ConnectionDescriptor)operator(::)ident(SetTlsParms) operator(()directive(const) pre_type(char) operator(*)ident(privkey_filename)operator(,) directive(const) pre_type(char) operator(*)ident(certchain_filename)operator(\)) +operator({) + preprocessor(#ifdef) ident(WITH_SSL) + reserved(if) operator(()ident(SslBox)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(call SetTlsParms before calling StartTls)delimiter(")>operator(\);) + reserved(if) operator(()ident(privkey_filename) operator(&&) operator(*)ident(privkey_filename)operator(\)) + ident(PrivateKeyFilename) operator(=) ident(privkey_filename)operator(;) + reserved(if) operator(()ident(certchain_filename) operator(&&) operator(*)ident(certchain_filename)operator(\)) + ident(CertChainFilename) operator(=) ident(certchain_filename)operator(;) + preprocessor(#endif) + + preprocessor(#ifdef) ident(WITHOUT_SSL) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(Encryption not available on this event-machine)delimiter(")>operator(\);) + preprocessor(#endif) +operator(}) + + + +comment(/***************************************** +ConnectionDescriptor::_DispatchCiphertext +*****************************************/) +preprocessor(#ifdef) ident(WITH_SSL) +directive(void) ident(ConnectionDescriptor)operator(::)ident(_DispatchCiphertext)operator((\)) +operator({) + ident(assert) operator(()ident(SslBox)operator(\);) + + + pre_type(char) ident(BigBuf) operator([)integer(2048)operator(];) + pre_type(bool) ident(did_work)operator(;) + + reserved(do) operator({) + ident(did_work) operator(=) pre_constant(false)operator(;) + + comment(// try to drain ciphertext) + reserved(while) operator(()ident(SslBox)operator(->)ident(CanGetCiphertext)operator((\)\)) operator({) + pre_type(int) ident(r) operator(=) ident(SslBox)operator(->)ident(GetCiphertext) operator(()ident(BigBuf)operator(,) reserved(sizeof)operator(()ident(BigBuf)operator(\)\);) + ident(assert) operator(()ident(r) operator(>) integer(0)operator(\);) + ident(_SendRawOutboundData) operator(()ident(BigBuf)operator(,) ident(r)operator(\);) + ident(did_work) operator(=) pre_constant(true)operator(;) + operator(}) + + comment(// Pump the SslBox, in case it has queued outgoing plaintext) + comment(// This will return >0 if data was written,) + comment(// 0 if no data was written, and <0 if there was a fatal error.) + pre_type(bool) ident(pump)operator(;) + reserved(do) operator({) + ident(pump) operator(=) pre_constant(false)operator(;) + pre_type(int) ident(w) operator(=) ident(SslBox)operator(->)ident(PutPlaintext) operator(()pre_constant(NULL)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(w) operator(>) integer(0)operator(\)) operator({) + ident(did_work) operator(=) pre_constant(true)operator(;) + ident(pump) operator(=) pre_constant(true)operator(;) + operator(}) + reserved(else) reserved(if) operator(()ident(w) operator(<) integer(0)operator(\)) + ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + operator(}) reserved(while) operator(()ident(pump)operator(\);) + + comment(// try to put plaintext. INCOMPLETE, doesn't belong here?) + comment(// In SendOutboundData, we're spooling plaintext directly) + comment(// into SslBox. That may be wrong, we may need to buffer it) + comment(// up here! ) + comment(/* + const char *ptr; + int ptr_length; + while (OutboundPlaintext.GetPage (&ptr, &ptr_length\)\) { + assert (ptr && (ptr_length > 0\)\); + int w = SslMachine.PutPlaintext (ptr, ptr_length\); + if (w > 0\) { + OutboundPlaintext.DiscardBytes (w\); + did_work = true; + } + else + break; + } + */) + + operator(}) reserved(while) operator(()ident(did_work)operator(\);) + +operator(}) +preprocessor(#endif) + + + +comment(/******************************* +ConnectionDescriptor::Heartbeat +*******************************/) + +directive(void) ident(ConnectionDescriptor)operator(::)ident(Heartbeat)operator((\)) +operator({) + comment(/* Only allow a certain amount of time to go by while waiting + * for a pending connect. If it expires, then kill the socket. + * For a connected socket, close it if its inactivity timer + * has expired. + */) + + reserved(if) operator(()ident(bConnectPending)operator(\)) operator({) + reserved(if) operator((()ident(gCurrentLoopTime) operator(-) ident(CreatedAt)operator(\)) operator(>=) ident(PendingConnectTimeout)operator(\)) + ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + comment(//bCloseNow = true;) + operator(}) + reserved(else) operator({) + reserved(if) operator(()ident(InactivityTimeout) operator(&&) operator((()ident(gCurrentLoopTime) operator(-) ident(LastIo)operator(\)) operator(>=) ident(InactivityTimeout)operator(\)\)) + ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + comment(//bCloseNow = true;) + operator(}) +operator(}) + + +comment(/**************************************** +LoopbreakDescriptor::LoopbreakDescriptor +****************************************/) + +ident(LoopbreakDescriptor)operator(::)ident(LoopbreakDescriptor) operator(()pre_type(int) ident(sd)operator(,) ident(EventMachine_t) operator(*)ident(parent_em)operator(\):) + ident(EventableDescriptor) operator(()ident(sd)operator(,) ident(parent_em)operator(\)) +operator({) + comment(/* This is really bad and ugly. Change someday if possible. + * We have to know about an event-machine (probably the one that owns us\), + * so we can pass newly-created connections to it. + */) + + ident(bCallbackUnbind) operator(=) pre_constant(false)operator(;) + + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) ident(EPOLLIN)operator(;) + preprocessor(#endif) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + ident(MyEventMachine)operator(->)ident(ArmKqueueReader) operator(()local_variable(this)operator(\);) + preprocessor(#endif) +operator(}) + + + + +comment(/************************* +LoopbreakDescriptor::Read +*************************/) + +directive(void) ident(LoopbreakDescriptor)operator(::)ident(Read)operator((\)) +operator({) + comment(// TODO, refactor, this code is probably in the wrong place.) + ident(assert) operator(()ident(MyEventMachine)operator(\);) + ident(MyEventMachine)operator(->)ident(_ReadLoopBreaker)operator((\);) +operator(}) + + +comment(/************************** +LoopbreakDescriptor::Write +**************************/) + +directive(void) ident(LoopbreakDescriptor)operator(::)ident(Write)operator((\)) +operator({) + comment(// Why are we here?) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad code path in loopbreak)delimiter(")>operator(\);) +operator(}) + +comment(/************************************** +AcceptorDescriptor::AcceptorDescriptor +**************************************/) + +ident(AcceptorDescriptor)operator(::)ident(AcceptorDescriptor) operator(()pre_type(int) ident(sd)operator(,) ident(EventMachine_t) operator(*)ident(parent_em)operator(\):) + ident(EventableDescriptor) operator(()ident(sd)operator(,) ident(parent_em)operator(\)) +operator({) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) ident(EPOLLIN)operator(;) + preprocessor(#endif) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + ident(MyEventMachine)operator(->)ident(ArmKqueueReader) operator(()local_variable(this)operator(\);) + preprocessor(#endif) +operator(}) + + +comment(/*************************************** +AcceptorDescriptor::~AcceptorDescriptor +***************************************/) + +ident(AcceptorDescriptor)operator(::~)ident(AcceptorDescriptor)operator((\)) +operator({) +operator(}) + +comment(/**************************************** +STATIC: AcceptorDescriptor::StopAcceptor +****************************************/) + +directive(void) ident(AcceptorDescriptor)operator(::)ident(StopAcceptor) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(\)) +operator({) + comment(// TODO: This is something of a hack, or at least it's a static method of the wrong class.) + ident(AcceptorDescriptor) operator(*)ident(ad) operator(=) reserved(dynamic_cast) operator(<)ident(AcceptorDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(ad)operator(\)) + ident(ad)operator(->)ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + reserved(else) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(failed to close nonexistent acceptor)delimiter(")>operator(\);) +operator(}) + + +comment(/************************ +AcceptorDescriptor::Read +************************/) + +directive(void) ident(AcceptorDescriptor)operator(::)ident(Read)operator((\)) +operator({) + comment(/* Accept up to a certain number of sockets on the listening connection. + * Don't try to accept all that are present, because this would allow a DoS attack + * in which no data were ever read or written. We should accept more than one, + * if available, to keep the partially accepted sockets from backing up in the kernel. + */) + + comment(/* Make sure we use non-blocking i/o on the acceptor socket, since we're selecting it + * for readability. According to Stevens UNP, it's possible for an acceptor to select readable + * and then block when we call accept. For example, the other end resets the connection after + * the socket selects readable and before we call accept. The kernel will remove the dead + * socket from the accept queue. If the accept queue is now empty, accept will block. + */) + + + reserved(struct) ident(sockaddr_in) ident(pin)operator(;) + ident(socklen_t) ident(addrlen) operator(=) reserved(sizeof) operator(()ident(pin)operator(\);) + + reserved(for) operator(()pre_type(int) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) integer(10)operator(;) ident(i)operator(++\)) operator({) + pre_type(int) ident(sd) operator(=) ident(accept) operator(()ident(GetSocket)operator((\),) operator(()reserved(struct) ident(sockaddr)operator(*\)&)ident(pin)operator(,) operator(&)ident(addrlen)operator(\);) + reserved(if) operator(()ident(sd) operator(==) ident(INVALID_SOCKET)operator(\)) operator({) + comment(// This breaks the loop when we've accepted everything on the kernel queue,) + comment(// up to 10 new connections. But what if the *first* accept fails?) + comment(// Does that mean anything serious is happening, beyond the situation) + comment(// described in the note above?) + reserved(break)operator(;) + operator(}) + + comment(// Set the newly-accepted socket non-blocking.) + comment(// On Windows, this may fail because, weirdly, Windows inherits the non-blocking) + comment(// attribute that we applied to the acceptor socket into the accepted one.) + reserved(if) operator((!)ident(SetSocketNonblocking) operator(()ident(sd)operator(\)\)) operator({) + comment(//int val = fcntl (sd, F_GETFL, 0\);) + comment(//if (fcntl (sd, F_SETFL, val | O_NONBLOCK\) == -1\) {) + ident(shutdown) operator(()ident(sd)operator(,) integer(1)operator(\);) + ident(closesocket) operator(()ident(sd)operator(\);) + reserved(continue)operator(;) + operator(}) + + + comment(// Disable slow-start (Nagle algorithm\). Eventually make this configurable.) + pre_type(int) ident(one) operator(=) integer(1)operator(;) + ident(setsockopt) operator(()ident(sd)operator(,) ident(IPPROTO_TCP)operator(,) ident(TCP_NODELAY)operator(,) operator(()pre_type(char)operator(*\)) operator(&)ident(one)operator(,) reserved(sizeof)operator(()ident(one)operator(\)\);) + + + ident(ConnectionDescriptor) operator(*)ident(cd) operator(=) reserved(new) ident(ConnectionDescriptor) operator(()ident(sd)operator(,) ident(MyEventMachine)operator(\);) + reserved(if) operator((!)ident(cd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no newly accepted connection)delimiter(")>operator(\);) + ident(cd)operator(->)ident(SetServerMode)operator((\);) + reserved(if) operator(()ident(EventCallback)operator(\)) operator({) + operator((*)ident(EventCallback)operator(\)) operator(()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_ACCEPTED)operator(,) ident(cd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(cd)operator(->)ident(GetBinding)operator((\))operator(.)ident(size)operator((\)\);) + operator(}) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(cd)operator(->)ident(GetEpollEvent)operator((\)->)ident(events) operator(=) ident(EPOLLIN) operator(|) operator(()ident(cd)operator(->)ident(SelectForWrite)operator((\)) operator(?) ident(EPOLLOUT) operator(:) integer(0)operator(\);) + preprocessor(#endif) + ident(assert) operator(()ident(MyEventMachine)operator(\);) + ident(MyEventMachine)operator(->)ident(Add) operator(()ident(cd)operator(\);) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + reserved(if) operator(()ident(cd)operator(->)ident(SelectForWrite)operator((\)\)) + ident(MyEventMachine)operator(->)ident(ArmKqueueWriter) operator(()ident(cd)operator(\);) + ident(MyEventMachine)operator(->)ident(ArmKqueueReader) operator(()ident(cd)operator(\);) + preprocessor(#endif) + operator(}) + +operator(}) + + +comment(/************************* +AcceptorDescriptor::Write +*************************/) + +directive(void) ident(AcceptorDescriptor)operator(::)ident(Write)operator((\)) +operator({) + comment(// Why are we here?) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad code path in acceptor)delimiter(")>operator(\);) +operator(}) + + +comment(/***************************** +AcceptorDescriptor::Heartbeat +*****************************/) + +directive(void) ident(AcceptorDescriptor)operator(::)ident(Heartbeat)operator((\)) +operator({) + comment(// No-op) +operator(}) + + +comment(/******************************* +AcceptorDescriptor::GetSockname +*******************************/) + +pre_type(bool) ident(AcceptorDescriptor)operator(::)ident(GetSockname) operator(()reserved(struct) ident(sockaddr) operator(*)ident(s)operator(\)) +operator({) + pre_type(bool) ident(ok) operator(=) pre_constant(false)operator(;) + reserved(if) operator(()ident(s)operator(\)) operator({) + ident(socklen_t) ident(len) operator(=) reserved(sizeof)operator((*)ident(s)operator(\);) + pre_type(int) ident(gp) operator(=) ident(getsockname) operator(()ident(GetSocket)operator((\),) ident(s)operator(,) operator(&)ident(len)operator(\);) + reserved(if) operator(()ident(gp) operator(==) integer(0)operator(\)) + ident(ok) operator(=) pre_constant(true)operator(;) + operator(}) + reserved(return) ident(ok)operator(;) +operator(}) + + + +comment(/************************************** +DatagramDescriptor::DatagramDescriptor +**************************************/) + +ident(DatagramDescriptor)operator(::)ident(DatagramDescriptor) operator(()pre_type(int) ident(sd)operator(,) ident(EventMachine_t) operator(*)ident(parent_em)operator(\):) + ident(EventableDescriptor) operator(()ident(sd)operator(,) ident(parent_em)operator(\),) + ident(OutboundDataSize) operator(()integer(0)operator(\),) + ident(LastIo) operator(()ident(gCurrentLoopTime)operator(\),) + ident(InactivityTimeout) operator(()integer(0)operator(\)) +operator({) + ident(memset) operator((&)ident(ReturnAddress)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(ReturnAddress)operator(\)\);) + + comment(/* Provisionally added 19Oct07. All datagram sockets support broadcasting. + * Until now, sending to a broadcast address would give EACCES (permission denied\) + * on systems like Linux and BSD that require the SO_BROADCAST socket-option in order + * to accept a packet to a broadcast address. Solaris doesn't require it. I think + * Windows DOES require it but I'm not sure. + * + * Ruby does NOT do what we're doing here. In Ruby, you have to explicitly set SO_BROADCAST + * on a UDP socket in order to enable broadcasting. The reason for requiring the option + * in the first place is so that applications don't send broadcast datagrams by mistake. + * I imagine that could happen if a user of an application typed in an address that happened + * to be a broadcast address on that particular subnet. + * + * This is provisional because someone may eventually come up with a good reason not to + * do it for all UDP sockets. If that happens, then we'll need to add a usercode-level API + * to set the socket option, just like Ruby does. AND WE'LL ALSO BREAK CODE THAT DOESN'T + * EXPLICITLY SET THE OPTION. + */) + + pre_type(int) ident(oval) operator(=) integer(1)operator(;) + pre_type(int) ident(sob) operator(=) ident(setsockopt) operator(()ident(GetSocket)operator((\),) ident(SOL_SOCKET)operator(,) ident(SO_BROADCAST)operator(,) operator(()pre_type(char)operator(*\)&)ident(oval)operator(,) reserved(sizeof)operator(()ident(oval)operator(\)\);) + + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) ident(EPOLLIN)operator(;) + preprocessor(#endif) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + ident(MyEventMachine)operator(->)ident(ArmKqueueReader) operator(()local_variable(this)operator(\);) + preprocessor(#endif) +operator(}) + + +comment(/*************************************** +DatagramDescriptor::~DatagramDescriptor +***************************************/) + +ident(DatagramDescriptor)operator(::~)ident(DatagramDescriptor)operator((\)) +operator({) + comment(// Run down any stranded outbound data.) + reserved(for) operator(()ident(size_t) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) ident(OutboundPages)operator(.)ident(size)operator((\);) ident(i)operator(++\)) + ident(OutboundPages)operator([)ident(i)operator(])operator(.)ident(Free)operator((\);) +operator(}) + + +comment(/***************************** +DatagramDescriptor::Heartbeat +*****************************/) + +directive(void) ident(DatagramDescriptor)operator(::)ident(Heartbeat)operator((\)) +operator({) + comment(// Close it if its inactivity timer has expired.) + + reserved(if) operator(()ident(InactivityTimeout) operator(&&) operator((()ident(gCurrentLoopTime) operator(-) ident(LastIo)operator(\)) operator(>=) ident(InactivityTimeout)operator(\)\)) + ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + comment(//bCloseNow = true;) +operator(}) + + +comment(/************************ +DatagramDescriptor::Read +************************/) + +directive(void) ident(DatagramDescriptor)operator(::)ident(Read)operator((\)) +operator({) + pre_type(int) ident(sd) operator(=) ident(GetSocket)operator((\);) + ident(assert) operator(()ident(sd) operator(!=) ident(INVALID_SOCKET)operator(\);) + ident(LastIo) operator(=) ident(gCurrentLoopTime)operator(;) + + comment(// This is an extremely large read buffer.) + comment(// In many cases you wouldn't expect to get any more than 4K.) + pre_type(char) ident(readbuffer) operator([)integer(16) operator(*) integer(1024)operator(];) + + reserved(for) operator(()pre_type(int) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) integer(10)operator(;) ident(i)operator(++\)) operator({) + comment(// Don't read just one buffer and then move on. This is faster) + comment(// if there is a lot of incoming.) + comment(// But don't read indefinitely. Give other sockets a chance to run.) + comment(// NOTICE, we're reading one less than the buffer size.) + comment(// That's so we can put a guard byte at the end of what we send) + comment(// to user code.) + + reserved(struct) ident(sockaddr_in) ident(sin)operator(;) + ident(socklen_t) ident(slen) operator(=) reserved(sizeof) operator(()ident(sin)operator(\);) + ident(memset) operator((&)ident(sin)operator(,) integer(0)operator(,) ident(slen)operator(\);) + + pre_type(int) ident(r) operator(=) ident(recvfrom) operator(()ident(sd)operator(,) ident(readbuffer)operator(,) reserved(sizeof)operator(()ident(readbuffer)operator(\)) operator(-) integer(1)operator(,) integer(0)operator(,) operator(()reserved(struct) ident(sockaddr)operator(*\)&)ident(sin)operator(,) operator(&)ident(slen)operator(\);) + comment(//cerr << "<R:" << r << ">";) + + comment(// In UDP, a zero-length packet is perfectly legal.) + reserved(if) operator(()ident(r) operator(>=) integer(0)operator(\)) operator({) + ident(LastRead) operator(=) ident(gCurrentLoopTime)operator(;) + + comment(// Add a null-terminator at the the end of the buffer) + comment(// that we will send to the callback.) + comment(// DO NOT EVER CHANGE THIS. We want to explicitly allow users) + comment(// to be able to depend on this behavior, so they will have) + comment(// the option to do some things faster. Additionally it's) + comment(// a security guard against buffer overflows.) + ident(readbuffer) operator([)ident(r)operator(]) operator(=) integer(0)operator(;) + + + comment(// Set up a "temporary" return address so that callers can "reply" to us) + comment(// from within the callback we are about to invoke. That means that ordinary) + comment(// calls to "send_data_to_connection" (which is of course misnamed in this) + comment(// case\) will result in packets being sent back to the same place that sent) + comment(// us this one.) + comment(// There is a different call (evma_send_datagram\) for cases where the caller) + comment(// actually wants to send a packet somewhere else.) + + ident(memset) operator((&)ident(ReturnAddress)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(ReturnAddress)operator(\)\);) + ident(memcpy) operator((&)ident(ReturnAddress)operator(,) operator(&)ident(sin)operator(,) ident(slen)operator(\);) + + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_READ)operator(,) ident(readbuffer)operator(,) ident(r)operator(\);) + + operator(}) + reserved(else) operator({) + comment(// Basically a would-block, meaning we've read everything there is to read.) + reserved(break)operator(;) + operator(}) + + operator(}) + + +operator(}) + + +comment(/************************* +DatagramDescriptor::Write +*************************/) + +directive(void) ident(DatagramDescriptor)operator(::)ident(Write)operator((\)) +operator({) + comment(/* It's possible for a socket to select writable and then no longer + * be writable by the time we get around to writing. The kernel might + * have used up its available output buffers between the select call + * and when we get here. So this condition is not an error. + * This code is very reminiscent of ConnectionDescriptor::_WriteOutboundData, + * but differs in the that the outbound data pages (received from the + * user\) are _message-structured._ That is, we send each of them out + * one message at a time. + * TODO, we are currently suppressing the EMSGSIZE error!!! + */) + + pre_type(int) ident(sd) operator(=) ident(GetSocket)operator((\);) + ident(assert) operator(()ident(sd) operator(!=) ident(INVALID_SOCKET)operator(\);) + ident(LastIo) operator(=) ident(gCurrentLoopTime)operator(;) + + ident(assert) operator(()ident(OutboundPages)operator(.)ident(size)operator((\)) operator(>) integer(0)operator(\);) + + comment(// Send out up to 10 packets, then cycle the machine.) + reserved(for) operator(()pre_type(int) ident(i) operator(=) integer(0)operator(;) ident(i) operator(<) integer(10)operator(;) ident(i)operator(++\)) operator({) + reserved(if) operator(()ident(OutboundPages)operator(.)ident(size)operator((\)) operator(<=) integer(0)operator(\)) + reserved(break)operator(;) + ident(OutboundPage) operator(*)ident(op) operator(=) operator(&()ident(OutboundPages)operator([)integer(0)operator(]\);) + + comment(// The nasty cast to (char*\) is needed because Windows is brain-dead.) + pre_type(int) ident(s) operator(=) ident(sendto) operator(()ident(sd)operator(,) operator(()pre_type(char)operator(*\))ident(op)operator(->)ident(Buffer)operator(,) ident(op)operator(->)ident(Length)operator(,) integer(0)operator(,) operator(()reserved(struct) ident(sockaddr)operator(*\)&()ident(op)operator(->)ident(From)operator(\),) reserved(sizeof)operator(()ident(op)operator(->)ident(From)operator(\)\);) + pre_type(int) ident(e) operator(=) ident(errno)operator(;) + + ident(OutboundDataSize) operator(-=) ident(op)operator(->)ident(Length)operator(;) + ident(op)operator(->)ident(Free)operator((\);) + ident(OutboundPages)operator(.)ident(pop_front)operator((\);) + + reserved(if) operator(()ident(s) operator(==) ident(SOCKET_ERROR)operator(\)) operator({) + preprocessor(#ifdef) ident(OS_UNIX) + reserved(if) operator((()ident(e) operator(!=) ident(EINPROGRESS)operator(\)) operator(&&) operator(()ident(e) operator(!=) ident(EWOULDBLOCK)operator(\)) operator(&&) operator(()ident(e) operator(!=) ident(EINTR)operator(\)\)) operator({) + preprocessor(#endif) + preprocessor(#ifdef) ident(OS_WIN32) + reserved(if) operator((()ident(e) operator(!=) ident(WSAEINPROGRESS)operator(\)) operator(&&) operator(()ident(e) operator(!=) ident(WSAEWOULDBLOCK)operator(\)\)) operator({) + preprocessor(#endif) + ident(Close)operator((\);) + reserved(break)operator(;) + operator(}) + operator(}) + operator(}) + + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) operator(()ident(EPOLLIN) operator(|) operator(()ident(SelectForWrite)operator((\)) operator(?) ident(EPOLLOUT) operator(:) integer(0)operator(\)\);) + ident(assert) operator(()ident(MyEventMachine)operator(\);) + ident(MyEventMachine)operator(->)ident(Modify) operator(()local_variable(this)operator(\);) + preprocessor(#endif) +operator(}) + + +comment(/********************************** +DatagramDescriptor::SelectForWrite +**********************************/) + +pre_type(bool) ident(DatagramDescriptor)operator(::)ident(SelectForWrite)operator((\)) +operator({) + comment(/* Changed 15Nov07, per bug report by Mark Zvillius. + * The outbound data size will be zero if there are zero-length outbound packets, + * so we now select writable in case the outbound page buffer is not empty. + * Note that the superclass ShouldDelete method still checks for outbound data size, + * which may be wrong. + */) + comment(//return (GetOutboundDataSize(\) > 0\); (Original\)) + reserved(return) operator(()ident(OutboundPages)operator(.)ident(size)operator((\)) operator(>) integer(0)operator(\);) +operator(}) + + +comment(/************************************ +DatagramDescriptor::SendOutboundData +************************************/) + +pre_type(int) ident(DatagramDescriptor)operator(::)ident(SendOutboundData) operator(()directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(length)operator(\)) +operator({) + comment(// This is an exact clone of ConnectionDescriptor::SendOutboundData.) + comment(// That means it needs to move to a common ancestor.) + + reserved(if) operator(()ident(IsCloseScheduled)operator((\)\)) + comment(//if (bCloseNow || bCloseAfterWriting\)) + reserved(return) integer(0)operator(;) + + reserved(if) operator((!)ident(data) operator(&&) operator(()ident(length) operator(>) integer(0)operator(\)\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad outbound data)delimiter(")>operator(\);) + pre_type(char) operator(*)ident(buffer) operator(=) operator(()pre_type(char) operator(*\)) ident(malloc) operator(()ident(length) operator(+) integer(1)operator(\);) + reserved(if) operator((!)ident(buffer)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no allocation for outbound data)delimiter(")>operator(\);) + ident(memcpy) operator(()ident(buffer)operator(,) ident(data)operator(,) ident(length)operator(\);) + ident(buffer) operator([)ident(length)operator(]) operator(=) integer(0)operator(;) + ident(OutboundPages)operator(.)ident(push_back) operator(()ident(OutboundPage) operator(()ident(buffer)operator(,) ident(length)operator(,) ident(ReturnAddress)operator(\)\);) + ident(OutboundDataSize) operator(+=) ident(length)operator(;) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) operator(()ident(EPOLLIN) operator(|) ident(EPOLLOUT)operator(\);) + ident(assert) operator(()ident(MyEventMachine)operator(\);) + ident(MyEventMachine)operator(->)ident(Modify) operator(()local_variable(this)operator(\);) + preprocessor(#endif) + reserved(return) ident(length)operator(;) +operator(}) + + +comment(/**************************************** +DatagramDescriptor::SendOutboundDatagram +****************************************/) + +pre_type(int) ident(DatagramDescriptor)operator(::)ident(SendOutboundDatagram) operator(()directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(length)operator(,) directive(const) pre_type(char) operator(*)ident(address)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + comment(// This is an exact clone of ConnectionDescriptor::SendOutboundData.) + comment(// That means it needs to move to a common ancestor.) + comment(// TODO: Refactor this so there's no overlap with SendOutboundData.) + + reserved(if) operator(()ident(IsCloseScheduled)operator((\)\)) + comment(//if (bCloseNow || bCloseAfterWriting\)) + reserved(return) integer(0)operator(;) + + reserved(if) operator((!)ident(address) operator(||) operator(!*)ident(address) operator(||) operator(!)ident(port)operator(\)) + reserved(return) integer(0)operator(;) + + ident(sockaddr_in) ident(pin)operator(;) + pre_type(unsigned) pre_type(long) ident(HostAddr)operator(;) + + ident(HostAddr) operator(=) ident(inet_addr) operator(()ident(address)operator(\);) + reserved(if) operator(()ident(HostAddr) operator(==) ident(INADDR_NONE)operator(\)) operator({) + comment(// The nasty cast to (char*\) is because Windows is brain-dead.) + ident(hostent) operator(*)ident(hp) operator(=) ident(gethostbyname) operator((()pre_type(char)operator(*\))ident(address)operator(\);) + reserved(if) operator((!)ident(hp)operator(\)) + reserved(return) integer(0)operator(;) + ident(HostAddr) operator(=) operator((()ident(in_addr)operator(*\)()ident(hp)operator(->)ident(h_addr)operator(\)\)->)ident(s_addr)operator(;) + operator(}) + + ident(memset) operator((&)ident(pin)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(pin)operator(\)\);) + ident(pin)operator(.)ident(sin_family) operator(=) ident(AF_INET)operator(;) + ident(pin)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) ident(HostAddr)operator(;) + ident(pin)operator(.)ident(sin_port) operator(=) ident(htons) operator(()ident(port)operator(\);) + + + + reserved(if) operator((!)ident(data) operator(&&) operator(()ident(length) operator(>) integer(0)operator(\)\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad outbound data)delimiter(")>operator(\);) + pre_type(char) operator(*)ident(buffer) operator(=) operator(()pre_type(char) operator(*\)) ident(malloc) operator(()ident(length) operator(+) integer(1)operator(\);) + reserved(if) operator((!)ident(buffer)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no allocation for outbound data)delimiter(")>operator(\);) + ident(memcpy) operator(()ident(buffer)operator(,) ident(data)operator(,) ident(length)operator(\);) + ident(buffer) operator([)ident(length)operator(]) operator(=) integer(0)operator(;) + ident(OutboundPages)operator(.)ident(push_back) operator(()ident(OutboundPage) operator(()ident(buffer)operator(,) ident(length)operator(,) ident(pin)operator(\)\);) + ident(OutboundDataSize) operator(+=) ident(length)operator(;) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) operator(()ident(EPOLLIN) operator(|) ident(EPOLLOUT)operator(\);) + ident(assert) operator(()ident(MyEventMachine)operator(\);) + ident(MyEventMachine)operator(->)ident(Modify) operator(()local_variable(this)operator(\);) + preprocessor(#endif) + reserved(return) ident(length)operator(;) +operator(}) + + +comment(/**************************************** +STATIC: DatagramDescriptor::SendDatagram +****************************************/) + +pre_type(int) ident(DatagramDescriptor)operator(::)ident(SendDatagram) operator(()directive(const) pre_type(char) operator(*)ident(binding)operator(,) directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(length)operator(,) directive(const) pre_type(char) operator(*)ident(address)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + ident(DatagramDescriptor) operator(*)ident(dd) operator(=) reserved(dynamic_cast) operator(<)ident(DatagramDescriptor)operator(*>) operator(()ident(Bindable_t)operator(::)ident(GetObject) operator(()ident(binding)operator(\)\);) + reserved(if) operator(()ident(dd)operator(\)) + reserved(return) ident(dd)operator(->)ident(SendOutboundDatagram) operator(()ident(data)operator(,) ident(length)operator(,) ident(address)operator(,) ident(port)operator(\);) + reserved(else) + reserved(return) operator(-)integer(1)operator(;) +operator(}) + + +comment(/********************************* +ConnectionDescriptor::GetPeername +*********************************/) + +pre_type(bool) ident(ConnectionDescriptor)operator(::)ident(GetPeername) operator(()reserved(struct) ident(sockaddr) operator(*)ident(s)operator(\)) +operator({) + pre_type(bool) ident(ok) operator(=) pre_constant(false)operator(;) + reserved(if) operator(()ident(s)operator(\)) operator({) + ident(socklen_t) ident(len) operator(=) reserved(sizeof)operator((*)ident(s)operator(\);) + pre_type(int) ident(gp) operator(=) ident(getpeername) operator(()ident(GetSocket)operator((\),) ident(s)operator(,) operator(&)ident(len)operator(\);) + reserved(if) operator(()ident(gp) operator(==) integer(0)operator(\)) + ident(ok) operator(=) pre_constant(true)operator(;) + operator(}) + reserved(return) ident(ok)operator(;) +operator(}) + +comment(/********************************* +ConnectionDescriptor::GetSockname +*********************************/) + +pre_type(bool) ident(ConnectionDescriptor)operator(::)ident(GetSockname) operator(()reserved(struct) ident(sockaddr) operator(*)ident(s)operator(\)) +operator({) + pre_type(bool) ident(ok) operator(=) pre_constant(false)operator(;) + reserved(if) operator(()ident(s)operator(\)) operator({) + ident(socklen_t) ident(len) operator(=) reserved(sizeof)operator((*)ident(s)operator(\);) + pre_type(int) ident(gp) operator(=) ident(getsockname) operator(()ident(GetSocket)operator((\),) ident(s)operator(,) operator(&)ident(len)operator(\);) + reserved(if) operator(()ident(gp) operator(==) integer(0)operator(\)) + ident(ok) operator(=) pre_constant(true)operator(;) + operator(}) + reserved(return) ident(ok)operator(;) +operator(}) + + +comment(/********************************************** +ConnectionDescriptor::GetCommInactivityTimeout +**********************************************/) + +pre_type(int) ident(ConnectionDescriptor)operator(::)ident(GetCommInactivityTimeout) operator(()pre_type(int) operator(*)ident(value)operator(\)) +operator({) + reserved(if) operator(()ident(value)operator(\)) operator({) + operator(*)ident(value) operator(=) ident(InactivityTimeout)operator(;) + reserved(return) integer(1)operator(;) + operator(}) + reserved(else) operator({) + comment(// TODO, extended logging, got bad parameter.) + reserved(return) integer(0)operator(;) + operator(}) +operator(}) + + +comment(/********************************************** +ConnectionDescriptor::SetCommInactivityTimeout +**********************************************/) + +pre_type(int) ident(ConnectionDescriptor)operator(::)ident(SetCommInactivityTimeout) operator(()pre_type(int) operator(*)ident(value)operator(\)) +operator({) + pre_type(int) ident(out) operator(=) integer(0)operator(;) + + reserved(if) operator(()ident(value)operator(\)) operator({) + reserved(if) operator(((*)ident(value)operator(==)integer(0)operator(\)) operator(||) operator((*)ident(value) operator(>=) integer(2)operator(\)\)) operator({) + comment(// Replace the value and send the old one back to the caller.) + pre_type(int) ident(v) operator(=) operator(*)ident(value)operator(;) + operator(*)ident(value) operator(=) ident(InactivityTimeout)operator(;) + ident(InactivityTimeout) operator(=) ident(v)operator(;) + ident(out) operator(=) integer(1)operator(;) + operator(}) + reserved(else) operator({) + comment(// TODO, extended logging, got bad value.) + operator(}) + operator(}) + reserved(else) operator({) + comment(// TODO, extended logging, got bad parameter.) + operator(}) + + reserved(return) ident(out)operator(;) +operator(}) + +comment(/******************************* +DatagramDescriptor::GetPeername +*******************************/) + +pre_type(bool) ident(DatagramDescriptor)operator(::)ident(GetPeername) operator(()reserved(struct) ident(sockaddr) operator(*)ident(s)operator(\)) +operator({) + pre_type(bool) ident(ok) operator(=) pre_constant(false)operator(;) + reserved(if) operator(()ident(s)operator(\)) operator({) + ident(memset) operator(()ident(s)operator(,) integer(0)operator(,) reserved(sizeof)operator(()reserved(struct) ident(sockaddr)operator(\)\);) + ident(memcpy) operator(()ident(s)operator(,) operator(&)ident(ReturnAddress)operator(,) reserved(sizeof)operator(()ident(ReturnAddress)operator(\)\);) + ident(ok) operator(=) pre_constant(true)operator(;) + operator(}) + reserved(return) ident(ok)operator(;) +operator(}) + +comment(/******************************* +DatagramDescriptor::GetSockname +*******************************/) + +pre_type(bool) ident(DatagramDescriptor)operator(::)ident(GetSockname) operator(()reserved(struct) ident(sockaddr) operator(*)ident(s)operator(\)) +operator({) + pre_type(bool) ident(ok) operator(=) pre_constant(false)operator(;) + reserved(if) operator(()ident(s)operator(\)) operator({) + ident(socklen_t) ident(len) operator(=) reserved(sizeof)operator((*)ident(s)operator(\);) + pre_type(int) ident(gp) operator(=) ident(getsockname) operator(()ident(GetSocket)operator((\),) ident(s)operator(,) operator(&)ident(len)operator(\);) + reserved(if) operator(()ident(gp) operator(==) integer(0)operator(\)) + ident(ok) operator(=) pre_constant(true)operator(;) + operator(}) + reserved(return) ident(ok)operator(;) +operator(}) + + + +comment(/******************************************** +DatagramDescriptor::GetCommInactivityTimeout +********************************************/) + +pre_type(int) ident(DatagramDescriptor)operator(::)ident(GetCommInactivityTimeout) operator(()pre_type(int) operator(*)ident(value)operator(\)) +operator({) + reserved(if) operator(()ident(value)operator(\)) operator({) + operator(*)ident(value) operator(=) ident(InactivityTimeout)operator(;) + reserved(return) integer(1)operator(;) + operator(}) + reserved(else) operator({) + comment(// TODO, extended logging, got bad parameter.) + reserved(return) integer(0)operator(;) + operator(}) +operator(}) + +comment(/******************************************** +DatagramDescriptor::SetCommInactivityTimeout +********************************************/) + +pre_type(int) ident(DatagramDescriptor)operator(::)ident(SetCommInactivityTimeout) operator(()pre_type(int) operator(*)ident(value)operator(\)) +operator({) + pre_type(int) ident(out) operator(=) integer(0)operator(;) + + reserved(if) operator(()ident(value)operator(\)) operator({) + reserved(if) operator(((*)ident(value)operator(==)integer(0)operator(\)) operator(||) operator((*)ident(value) operator(>=) integer(2)operator(\)\)) operator({) + comment(// Replace the value and send the old one back to the caller.) + pre_type(int) ident(v) operator(=) operator(*)ident(value)operator(;) + operator(*)ident(value) operator(=) ident(InactivityTimeout)operator(;) + ident(InactivityTimeout) operator(=) ident(v)operator(;) + ident(out) operator(=) integer(1)operator(;) + operator(}) + reserved(else) operator({) + comment(// TODO, extended logging, got bad value.) + operator(}) + operator(}) + reserved(else) operator({) + comment(// TODO, extended logging, got bad parameter.) + operator(}) + + reserved(return) ident(out)operator(;) +operator(}) + +comment(/***************************************************************************** + +$Id$ + +File: em.cpp +Date: 06Apr06 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + +comment(// THIS ENTIRE FILE WILL EVENTUALLY BE FOR UNIX BUILDS ONLY.) +comment(//#ifdef OS_UNIX) + + +preprocessor(#include) include("project.h") + +comment(// Keep a global variable floating around) +comment(// with the current loop time as set by the Event Machine.) +comment(// This avoids the need for frequent expensive calls to time(NULL\);) +ident(time_t) ident(gCurrentLoopTime)operator(;) + +preprocessor(#ifdef) ident(OS_WIN32) +pre_type(unsigned) ident(gTickCountTickover)operator(;) +pre_type(unsigned) ident(gLastTickCount)operator(;) +preprocessor(#endif) + + +comment(/* The numer of max outstanding timers was once a const enum defined in em.h. + * Now we define it here so that users can change its value if necessary. + */) +directive(static) pre_type(int) ident(MaxOutstandingTimers) operator(=) integer(1000)operator(;) + + +comment(/* Internal helper to convert strings to internet addresses. IPv6-aware. + * Not reentrant or threadsafe, optimized for speed. + */) +directive(static) reserved(struct) ident(sockaddr) operator(*)ident(name2address) operator(()directive(const) pre_type(char) operator(*)ident(server)operator(,) pre_type(int) ident(port)operator(,) pre_type(int) operator(*)ident(family)operator(,) pre_type(int) operator(*)ident(bind_size)operator(\);) + + +comment(/*************************************** +STATIC EventMachine_t::SetMaxTimerCount +***************************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(SetMaxTimerCount) operator(()pre_type(int) ident(count)operator(\)) +operator({) + comment(/* Allow a user to increase the maximum number of outstanding timers. + * If this gets "too high" (a metric that is of course platform dependent\), + * bad things will happen like performance problems and possible overuse + * of memory. + * The actual timer mechanism is very efficient so it's hard to know what + * the practical max, but 100,000 shouldn't be too problematical. + */) + reserved(if) operator(()ident(count) operator(<) integer(100)operator(\)) + ident(count) operator(=) integer(100)operator(;) + ident(MaxOutstandingTimers) operator(=) ident(count)operator(;) +operator(}) + + + +comment(/****************************** +EventMachine_t::EventMachine_t +******************************/) + +ident(EventMachine_t)operator(::)ident(EventMachine_t) operator(()directive(void) operator((*)ident(event_callback)operator(\)()directive(const) pre_type(char)operator(*,) pre_type(int)operator(,) directive(const) pre_type(char)operator(*,) pre_type(int)operator(\)\):) + ident(EventCallback) operator(()ident(event_callback)operator(\),) + ident(NextHeartbeatTime) operator(()integer(0)operator(\),) + ident(LoopBreakerReader) operator((-)integer(1)operator(\),) + ident(LoopBreakerWriter) operator((-)integer(1)operator(\),) + ident(bEpoll) operator(()pre_constant(false)operator(\),) + ident(bKqueue) operator(()pre_constant(false)operator(\),) + ident(epfd) operator((-)integer(1)operator(\)) +operator({) + comment(// Default time-slice is just smaller than one hundred mills.) + ident(Quantum)operator(.)ident(tv_sec) operator(=) integer(0)operator(;) + ident(Quantum)operator(.)ident(tv_usec) operator(=) integer(90000)operator(;) + + ident(gTerminateSignalReceived) operator(=) pre_constant(false)operator(;) + comment(// Make sure the current loop time is sane, in case we do any initializations of) + comment(// objects before we start running.) + ident(gCurrentLoopTime) operator(=) ident(time)operator(()pre_constant(NULL)operator(\);) + + comment(/* We initialize the network library here (only on Windows of course\) + * and initialize "loop breakers." Our destructor also does some network-level + * cleanup. There's thus an implicit assumption that any given instance of EventMachine_t + * will only call ::Run once. Is that a good assumption? Should we move some of these + * inits and de-inits into ::Run? + */) + preprocessor(#ifdef) ident(OS_WIN32) + ident(WSADATA) ident(w)operator(;) + ident(WSAStartup) operator(()ident(MAKEWORD) operator(()integer(1)operator(,) integer(1)operator(\),) operator(&)ident(w)operator(\);) + preprocessor(#endif) + + ident(_InitializeLoopBreaker)operator((\);) +operator(}) + + +comment(/******************************* +EventMachine_t::~EventMachine_t +*******************************/) + +ident(EventMachine_t)operator(::~)ident(EventMachine_t)operator((\)) +operator({) + comment(// Run down descriptors) + ident(size_t) ident(i)operator(;) + reserved(for) operator(()ident(i) operator(=) integer(0)operator(;) ident(i) operator(<) ident(NewDescriptors)operator(.)ident(size)operator((\);) ident(i)operator(++\)) + reserved(delete) ident(NewDescriptors)operator([)ident(i)operator(];) + reserved(for) operator(()ident(i) operator(=) integer(0)operator(;) ident(i) operator(<) ident(Descriptors)operator(.)ident(size)operator((\);) ident(i)operator(++\)) + reserved(delete) ident(Descriptors)operator([)ident(i)operator(];) + + ident(close) operator(()ident(LoopBreakerReader)operator(\);) + ident(close) operator(()ident(LoopBreakerWriter)operator(\);) + + reserved(if) operator(()ident(epfd) operator(!=) operator(-)integer(1)operator(\)) + ident(close) operator(()ident(epfd)operator(\);) + reserved(if) operator(()ident(kqfd) operator(!=) operator(-)integer(1)operator(\)) + ident(close) operator(()ident(kqfd)operator(\);) +operator(}) + + +comment(/************************* +EventMachine_t::_UseEpoll +*************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(_UseEpoll)operator((\)) +operator({) + comment(/* Temporary. + * Use an internal flag to switch in epoll-based functionality until we determine + * how it should be integrated properly and the extent of the required changes. + * A permanent solution needs to allow the integration of additional technologies, + * like kqueue and Solaris's events. + */) + + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(bEpoll) operator(=) pre_constant(true)operator(;) + preprocessor(#endif) +operator(}) + +comment(/************************** +EventMachine_t::_UseKqueue +**************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(_UseKqueue)operator((\)) +operator({) + comment(/* Temporary. + * See comments under _UseEpoll. + */) + + preprocessor(#ifdef) ident(HAVE_KQUEUE) + ident(bKqueue) operator(=) pre_constant(true)operator(;) + preprocessor(#endif) +operator(}) + + +comment(/**************************** +EventMachine_t::ScheduleHalt +****************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(ScheduleHalt)operator((\)) +operator({) + comment(/* This is how we stop the machine. + * This can be called by clients. Signal handlers will probably + * set the global flag. + * For now this means there can only be one EventMachine ever running at a time. + * + * IMPORTANT: keep this light, fast, and async-safe. Don't do anything frisky in here, + * because it may be called from signal handlers invoked from code that we don't + * control. At this writing (20Sep06\), EM does NOT install any signal handlers of + * its own. + * + * We need a FAQ. And one of the questions is: how do I stop EM when Ctrl-C happens? + * The answer is to call evma_stop_machine, which calls here, from a SIGINT handler. + */) + ident(gTerminateSignalReceived) operator(=) pre_constant(true)operator(;) +operator(}) + + + +comment(/******************************* +EventMachine_t::SetTimerQuantum +*******************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(SetTimerQuantum) operator(()pre_type(int) ident(interval)operator(\)) +operator({) + comment(/* We get a timer-quantum expressed in milliseconds. + * Don't set a quantum smaller than 5 or larger than 2500. + */) + + reserved(if) operator((()ident(interval) operator(<) integer(5)operator(\)) operator(||) operator(()ident(interval) operator(>) integer(2500)operator(\)\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(invalid timer-quantum)delimiter(")>operator(\);) + + ident(Quantum)operator(.)ident(tv_sec) operator(=) ident(interval) operator(/) integer(1000)operator(;) + ident(Quantum)operator(.)ident(tv_usec) operator(=) operator(()ident(interval) operator(%) integer(1000)operator(\)) operator(*) integer(1000)operator(;) +operator(}) + + +comment(/************************************* +(STATIC\) EventMachine_t::SetuidString +*************************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(SetuidString) operator(()directive(const) pre_type(char) operator(*)ident(username)operator(\)) +operator({) + comment(/* This method takes a caller-supplied username and tries to setuid + * to that user. There is no meaningful implementation (and no error\) + * on Windows. On Unix, a failure to setuid the caller-supplied string + * causes a fatal abort, because presumably the program is calling here + * in order to fulfill a security requirement. If we fail silently, + * the user may continue to run with too much privilege. + * + * TODO, we need to decide on and document a way of generating C++ level errors + * that can be wrapped in documented Ruby exceptions, so users can catch + * and handle them. And distinguish it from errors that we WON'T let the Ruby + * user catch (like security-violations and resource-overallocation\). + * A setuid failure here would be in the latter category. + */) + + preprocessor(#ifdef) ident(OS_UNIX) + reserved(if) operator((!)ident(username) operator(||) operator(!*)ident(username)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(setuid_string failed: no username specified)delimiter(")>operator(\);) + + reserved(struct) ident(passwd) operator(*)ident(p) operator(=) ident(getpwnam) operator(()ident(username)operator(\);) + reserved(if) operator((!)ident(p)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(setuid_string failed: unknown username)delimiter(")>operator(\);) + + reserved(if) operator(()ident(setuid) operator(()ident(p)operator(->)ident(pw_uid)operator(\)) operator(!=) integer(0)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(setuid_string failed: no setuid)delimiter(")>operator(\);) + + comment(// Success.) + preprocessor(#endif) +operator(}) + + +comment(/**************************************** +(STATIC\) EventMachine_t::SetRlimitNofile +****************************************/) + +pre_type(int) ident(EventMachine_t)operator(::)ident(SetRlimitNofile) operator(()pre_type(int) ident(nofiles)operator(\)) +operator({) + preprocessor(#ifdef) ident(OS_UNIX) + reserved(struct) ident(rlimit) ident(rlim)operator(;) + ident(getrlimit) operator(()ident(RLIMIT_NOFILE)operator(,) operator(&)ident(rlim)operator(\);) + reserved(if) operator(()ident(nofiles) operator(>=) integer(0)operator(\)) operator({) + ident(rlim)operator(.)ident(rlim_cur) operator(=) ident(nofiles)operator(;) + reserved(if) operator(()ident(nofiles) operator(>) ident(rlim)operator(.)ident(rlim_max)operator(\)) + ident(rlim)operator(.)ident(rlim_max) operator(=) ident(nofiles)operator(;) + ident(setrlimit) operator(()ident(RLIMIT_NOFILE)operator(,) operator(&)ident(rlim)operator(\);) + comment(// ignore the error return, for now at least.) + comment(// TODO, emit an error message someday when we have proper debug levels.) + operator(}) + ident(getrlimit) operator(()ident(RLIMIT_NOFILE)operator(,) operator(&)ident(rlim)operator(\);) + reserved(return) ident(rlim)operator(.)ident(rlim_cur)operator(;) + preprocessor(#endif) + + preprocessor(#ifdef) ident(OS_WIN32) + comment(// No meaningful implementation on Windows.) + reserved(return) integer(0)operator(;) + preprocessor(#endif) +operator(}) + + +comment(/********************************* +EventMachine_t::SignalLoopBreaker +*********************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(SignalLoopBreaker)operator((\)) +operator({) + preprocessor(#ifdef) ident(OS_UNIX) + ident(write) operator(()ident(LoopBreakerWriter)operator(,) string<delimiter(")delimiter(")>operator(,) integer(1)operator(\);) + preprocessor(#endif) + preprocessor(#ifdef) ident(OS_WIN32) + ident(sendto) operator(()ident(LoopBreakerReader)operator(,) string<delimiter(")delimiter(")>operator(,) integer(0)operator(,) integer(0)operator(,) operator(()reserved(struct) ident(sockaddr)operator(*\)&()ident(LoopBreakerTarget)operator(\),) reserved(sizeof)operator(()ident(LoopBreakerTarget)operator(\)\);) + preprocessor(#endif) +operator(}) + + +comment(/************************************** +EventMachine_t::_InitializeLoopBreaker +**************************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(_InitializeLoopBreaker)operator((\)) +operator({) + comment(/* A "loop-breaker" is a socket-descriptor that we can write to in order + * to break the main select loop. Primarily useful for things running on + * threads other than the main EM thread, so they can trigger processing + * of events that arise exogenously to the EM. + * Keep the loop-breaker pipe out of the main descriptor set, otherwise + * its events will get passed on to user code. + */) + + preprocessor(#ifdef) ident(OS_UNIX) + pre_type(int) ident(fd)operator([)integer(2)operator(];) + reserved(if) operator(()ident(pipe) operator(()ident(fd)operator(\)\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no loop breaker)delimiter(")>operator(\);) + + ident(LoopBreakerWriter) operator(=) ident(fd)operator([)integer(1)operator(];) + ident(LoopBreakerReader) operator(=) ident(fd)operator([)integer(0)operator(];) + preprocessor(#endif) + + preprocessor(#ifdef) ident(OS_WIN32) + pre_type(int) ident(sd) operator(=) ident(socket) operator(()ident(AF_INET)operator(,) ident(SOCK_DGRAM)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(sd) operator(==) ident(INVALID_SOCKET)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no loop breaker socket)delimiter(")>operator(\);) + ident(SetSocketNonblocking) operator(()ident(sd)operator(\);) + + ident(memset) operator((&)ident(LoopBreakerTarget)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(LoopBreakerTarget)operator(\)\);) + ident(LoopBreakerTarget)operator(.)ident(sin_family) operator(=) ident(AF_INET)operator(;) + ident(LoopBreakerTarget)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) ident(inet_addr) operator(()string<delimiter(")content(127.0.0.1)delimiter(")>operator(\);) + + ident(srand) operator((()pre_type(int)operator(\))ident(time)operator(()pre_constant(NULL)operator(\)\);) + pre_type(int) ident(i)operator(;) + reserved(for) operator(()ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) integer(100)operator(;) ident(i)operator(++\)) operator({) + pre_type(int) ident(r) operator(=) operator(()ident(rand)operator((\)) operator(%) integer(10000)operator(\)) operator(+) integer(20000)operator(;) + ident(LoopBreakerTarget)operator(.)ident(sin_port) operator(=) ident(htons) operator(()ident(r)operator(\);) + reserved(if) operator(()ident(bind) operator(()ident(sd)operator(,) operator(()reserved(struct) ident(sockaddr)operator(*\)&)ident(LoopBreakerTarget)operator(,) reserved(sizeof)operator(()ident(LoopBreakerTarget)operator(\)\)) operator(==) integer(0)operator(\)) + reserved(break)operator(;) + operator(}) + + reserved(if) operator(()ident(i) operator(==) integer(100)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no loop breaker)delimiter(")>operator(\);) + ident(LoopBreakerReader) operator(=) ident(sd)operator(;) + preprocessor(#endif) +operator(}) + + +comment(/******************* +EventMachine_t::Run +*******************/) + +directive(void) ident(EventMachine_t)operator(::)ident(Run)operator((\)) +operator({) + preprocessor(#ifdef) ident(OS_WIN32) + ident(HookControlC) operator(()pre_constant(true)operator(\);) + preprocessor(#endif) + + preprocessor(#ifdef) ident(HAVE_EPOLL) + reserved(if) operator(()ident(bEpoll)operator(\)) operator({) + ident(epfd) operator(=) ident(epoll_create) operator(()ident(MaxEpollDescriptors)operator(\);) + reserved(if) operator(()ident(epfd) operator(==) operator(-)integer(1)operator(\)) operator({) + pre_type(char) ident(buf)operator([)integer(200)operator(];) + ident(snprintf) operator(()ident(buf)operator(,) reserved(sizeof)operator(()ident(buf)operator(\)-)integer(1)operator(,) string<delimiter(")content(unable to create epoll descriptor: %s)delimiter(")>operator(,) ident(strerror)operator(()ident(errno)operator(\)\);) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()ident(buf)operator(\);) + operator(}) + pre_type(int) ident(cloexec) operator(=) ident(fcntl) operator(()ident(epfd)operator(,) ident(F_GETFD)operator(,) integer(0)operator(\);) + ident(assert) operator(()ident(cloexec) operator(>=) integer(0)operator(\);) + ident(cloexec) operator(|=) ident(FD_CLOEXEC)operator(;) + ident(fcntl) operator(()ident(epfd)operator(,) ident(F_SETFD)operator(,) ident(cloexec)operator(\);) + + ident(assert) operator(()ident(LoopBreakerReader) operator(>=) integer(0)operator(\);) + ident(LoopbreakDescriptor) operator(*)ident(ld) operator(=) reserved(new) ident(LoopbreakDescriptor) operator(()ident(LoopBreakerReader)operator(,) local_variable(this)operator(\);) + ident(assert) operator(()ident(ld)operator(\);) + ident(Add) operator(()ident(ld)operator(\);) + operator(}) + preprocessor(#endif) + + preprocessor(#ifdef) ident(HAVE_KQUEUE) + reserved(if) operator(()ident(bKqueue)operator(\)) operator({) + ident(kqfd) operator(=) ident(kqueue)operator((\);) + reserved(if) operator(()ident(kqfd) operator(==) operator(-)integer(1)operator(\)) operator({) + pre_type(char) ident(buf)operator([)integer(200)operator(];) + ident(snprintf) operator(()ident(buf)operator(,) reserved(sizeof)operator(()ident(buf)operator(\)-)integer(1)operator(,) string<delimiter(")content(unable to create kqueue descriptor: %s)delimiter(")>operator(,) ident(strerror)operator(()ident(errno)operator(\)\);) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()ident(buf)operator(\);) + operator(}) + comment(// cloexec not needed. By definition, kqueues are not carried across forks.) + + ident(assert) operator(()ident(LoopBreakerReader) operator(>=) integer(0)operator(\);) + ident(LoopbreakDescriptor) operator(*)ident(ld) operator(=) reserved(new) ident(LoopbreakDescriptor) operator(()ident(LoopBreakerReader)operator(,) local_variable(this)operator(\);) + ident(assert) operator(()ident(ld)operator(\);) + ident(Add) operator(()ident(ld)operator(\);) + operator(}) + preprocessor(#endif) + + reserved(while) operator(()pre_constant(true)operator(\)) operator({) + ident(gCurrentLoopTime) operator(=) ident(time)operator(()pre_constant(NULL)operator(\);) + reserved(if) operator((!)ident(_RunTimers)operator((\)\)) + reserved(break)operator(;) + + comment(/* _Add must precede _Modify because the same descriptor might + * be on both lists during the same pass through the machine, + * and to modify a descriptor before adding it would fail. + */) + ident(_AddNewDescriptors)operator((\);) + ident(_ModifyDescriptors)operator((\);) + + reserved(if) operator((!)ident(_RunOnce)operator((\)\)) + reserved(break)operator(;) + reserved(if) operator(()ident(gTerminateSignalReceived)operator(\)) + reserved(break)operator(;) + operator(}) + + preprocessor(#ifdef) ident(OS_WIN32) + ident(HookControlC) operator(()pre_constant(false)operator(\);) + preprocessor(#endif) +operator(}) + + +comment(/************************ +EventMachine_t::_RunOnce +************************/) + +pre_type(bool) ident(EventMachine_t)operator(::)ident(_RunOnce)operator((\)) +operator({) + reserved(if) operator(()ident(bEpoll)operator(\)) + reserved(return) ident(_RunEpollOnce)operator((\);) + reserved(else) reserved(if) operator(()ident(bKqueue)operator(\)) + reserved(return) ident(_RunKqueueOnce)operator((\);) + reserved(else) + reserved(return) ident(_RunSelectOnce)operator((\);) +operator(}) + + + +comment(/***************************** +EventMachine_t::_RunEpollOnce +*****************************/) + +pre_type(bool) ident(EventMachine_t)operator(::)ident(_RunEpollOnce)operator((\)) +operator({) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(assert) operator(()ident(epfd) operator(!=) operator(-)integer(1)operator(\);) + reserved(struct) ident(epoll_event) ident(ev) operator([)ident(MaxEpollDescriptors)operator(];) + pre_type(int) ident(s)operator(;) + + preprocessor(#ifdef) ident(BUILD_FOR_RUBY) + ident(TRAP_BEG)operator(;) + preprocessor(#endif) + ident(s) operator(=) ident(epoll_wait) operator(()ident(epfd)operator(,) ident(ev)operator(,) ident(MaxEpollDescriptors)operator(,) integer(50)operator(\);) + preprocessor(#ifdef) ident(BUILD_FOR_RUBY) + ident(TRAP_END)operator(;) + preprocessor(#endif) + + reserved(if) operator(()ident(s) operator(>) integer(0)operator(\)) operator({) + reserved(for) operator(()pre_type(int) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) ident(s)operator(;) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) operator(()ident(EventableDescriptor)operator(*\)) ident(ev)operator([)ident(i)operator(])operator(.)ident(data)operator(.)ident(ptr)operator(;) + + reserved(if) operator(()ident(ev)operator([)ident(i)operator(])operator(.)ident(events) operator(&) operator(()ident(EPOLLERR) operator(|) ident(EPOLLHUP)operator(\)\)) + ident(ed)operator(->)ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + reserved(if) operator(()ident(ev)operator([)ident(i)operator(])operator(.)ident(events) operator(&) ident(EPOLLIN)operator(\)) + ident(ed)operator(->)ident(Read)operator((\);) + reserved(if) operator(()ident(ev)operator([)ident(i)operator(])operator(.)ident(events) operator(&) ident(EPOLLOUT)operator(\)) operator({) + ident(ed)operator(->)ident(Write)operator((\);) + ident(epoll_ctl) operator(()ident(epfd)operator(,) ident(EPOLL_CTL_MOD)operator(,) ident(ed)operator(->)ident(GetSocket)operator((\),) ident(ed)operator(->)ident(GetEpollEvent)operator((\)\);) + comment(// Ignoring return value) + operator(}) + operator(}) + operator(}) + reserved(else) reserved(if) operator(()ident(s) operator(<) integer(0)operator(\)) operator({) + comment(// epoll_wait can fail on error in a handful of ways.) + comment(// If this happens, then wait for a little while to avoid busy-looping.) + comment(// If the error was EINTR, we probably caught SIGCHLD or something,) + comment(// so keep the wait short.) + ident(timeval) ident(tv) operator(=) operator({)integer(0)operator(,) operator((()ident(errno) operator(==) ident(EINTR)operator(\)) operator(?) integer(5) operator(:) integer(50)operator(\)) operator(*) integer(1000)operator(};) + ident(EmSelect) operator(()integer(0)operator(,) pre_constant(NULL)operator(,) pre_constant(NULL)operator(,) pre_constant(NULL)operator(,) operator(&)ident(tv)operator(\);) + operator(}) + + operator({) comment(// cleanup dying sockets) + comment(// vector::pop_back works in constant time.) + comment(// TODO, rip this out and only delete the descriptors we know have died,) + comment(// rather than traversing the whole list.) + comment(// Modified 05Jan08 per suggestions by Chris Heath. It's possible that) + comment(// an EventableDescriptor will have a descriptor value of -1. That will) + comment(// happen if EventableDescriptor::Close was called on it. In that case,) + comment(// don't call epoll_ctl to remove the socket's filters from the epoll set.) + comment(// According to the epoll docs, this happens automatically when the) + comment(// descriptor is closed anyway. This is different from the case where) + comment(// the socket has already been closed but the descriptor in the ED object) + comment(// hasn't yet been set to INVALID_SOCKET.) + pre_type(int) ident(i)operator(,) ident(j)operator(;) + pre_type(int) ident(nSockets) operator(=) ident(Descriptors)operator(.)ident(size)operator((\);) + reserved(for) operator(()ident(i)operator(=)integer(0)operator(,) ident(j)operator(=)integer(0)operator(;) ident(i) operator(<) ident(nSockets)operator(;) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(Descriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ed)operator(\);) + reserved(if) operator(()ident(ed)operator(->)ident(ShouldDelete)operator((\)\)) operator({) + reserved(if) operator(()ident(ed)operator(->)ident(GetSocket)operator((\)) operator(!=) ident(INVALID_SOCKET)operator(\)) operator({) + ident(assert) operator(()ident(bEpoll)operator(\);) comment(// wouldn't be in this method otherwise.) + ident(assert) operator(()ident(epfd) operator(!=) operator(-)integer(1)operator(\);) + pre_type(int) ident(e) operator(=) ident(epoll_ctl) operator(()ident(epfd)operator(,) ident(EPOLL_CTL_DEL)operator(,) ident(ed)operator(->)ident(GetSocket)operator((\),) ident(ed)operator(->)ident(GetEpollEvent)operator((\)\);) + comment(// ENOENT or EBADF are not errors because the socket may be already closed when we get here.) + reserved(if) operator(()ident(e) operator(&&) operator(()ident(errno) operator(!=) ident(ENOENT)operator(\)) operator(&&) operator(()ident(errno) operator(!=) ident(EBADF)operator(\)\)) operator({) + pre_type(char) ident(buf) operator([)integer(200)operator(];) + ident(snprintf) operator(()ident(buf)operator(,) reserved(sizeof)operator(()ident(buf)operator(\)-)integer(1)operator(,) string<delimiter(")content(unable to delete epoll event: %s)delimiter(")>operator(,) ident(strerror)operator(()ident(errno)operator(\)\);) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()ident(buf)operator(\);) + operator(}) + operator(}) + + ident(ModifiedDescriptors)operator(.)ident(erase) operator(()ident(ed)operator(\);) + reserved(delete) ident(ed)operator(;) + operator(}) + reserved(else) + ident(Descriptors) operator([)ident(j)operator(++]) operator(=) ident(ed)operator(;) + operator(}) + reserved(while) operator((()ident(size_t)operator(\))ident(j) operator(<) ident(Descriptors)operator(.)ident(size)operator((\)\)) + ident(Descriptors)operator(.)ident(pop_back)operator((\);) + + operator(}) + + comment(// TODO, heartbeats.) + comment(// Added 14Sep07, its absence was noted by Brian Candler. But the comment was here, indicated) + comment(// that this got thought about and not done when EPOLL was originally written. Was there a reason) + comment(// not to do it, or was it an oversight? Certainly, running a heartbeat on 50,000 connections every) + comment(// two seconds can get to be a real bear, especially if all we're doing is timing out dead ones.) + comment(// Maybe there's a better way to do this. (Or maybe it's not that expensive after all.\)) + comment(//) + operator({) comment(// dispatch heartbeats) + reserved(if) operator(()ident(gCurrentLoopTime) operator(>=) ident(NextHeartbeatTime)operator(\)) operator({) + ident(NextHeartbeatTime) operator(=) ident(gCurrentLoopTime) operator(+) ident(HeartbeatInterval)operator(;) + + reserved(for) operator(()pre_type(int) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) ident(Descriptors)operator(.)ident(size)operator((\);) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(Descriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ed)operator(\);) + ident(ed)operator(->)ident(Heartbeat)operator((\);) + operator(}) + operator(}) + operator(}) + + preprocessor(#ifdef) ident(BUILD_FOR_RUBY) + reserved(if) operator((!)ident(rb_thread_alone)operator((\)\)) operator({) + ident(rb_thread_schedule)operator((\);) + operator(}) + preprocessor(#endif) + + reserved(return) pre_constant(true)operator(;) + preprocessor(#else) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(epoll is not implemented on this platform)delimiter(")>operator(\);) + preprocessor(#endif) +operator(}) + + +comment(/****************************** +EventMachine_t::_RunKqueueOnce +******************************/) + +pre_type(bool) ident(EventMachine_t)operator(::)ident(_RunKqueueOnce)operator((\)) +operator({) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + ident(assert) operator(()ident(kqfd) operator(!=) operator(-)integer(1)operator(\);) + directive(const) pre_type(int) ident(maxKevents) operator(=) integer(2000)operator(;) + reserved(struct) ident(kevent) ident(Karray) operator([)ident(maxKevents)operator(];) + reserved(struct) ident(timespec) ident(ts) operator(=) operator({)integer(0)operator(,) integer(10000000)operator(};) comment(// Too frequent. Use blocking_region) + + pre_type(int) ident(k)operator(;) + preprocessor(#ifdef) ident(BUILD_FOR_RUBY) + ident(TRAP_BEG)operator(;) + preprocessor(#endif) + ident(k) operator(=) ident(kevent) operator(()ident(kqfd)operator(,) pre_constant(NULL)operator(,) integer(0)operator(,) ident(Karray)operator(,) ident(maxKevents)operator(,) operator(&)ident(ts)operator(\);) + preprocessor(#ifdef) ident(BUILD_FOR_RUBY) + ident(TRAP_END)operator(;) + preprocessor(#endif) + reserved(struct) ident(kevent) operator(*)ident(ke) operator(=) ident(Karray)operator(;) + reserved(while) operator(()ident(k) operator(>) integer(0)operator(\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) operator(()ident(EventableDescriptor)operator(*\)) operator(()ident(ke)operator(->)ident(udata)operator(\);) + ident(assert) operator(()ident(ed)operator(\);) + + reserved(if) operator(()ident(ke)operator(->)ident(filter) operator(==) ident(EVFILT_READ)operator(\)) + ident(ed)operator(->)ident(Read)operator((\);) + reserved(else) reserved(if) operator(()ident(ke)operator(->)ident(filter) operator(==) ident(EVFILT_WRITE)operator(\)) + ident(ed)operator(->)ident(Write)operator((\);) + reserved(else) + ident(cerr) operator(<<) string<delimiter(")content(Discarding unknown kqueue event )delimiter(")> operator(<<) ident(ke)operator(->)ident(filter) operator(<<) ident(endl)operator(;) + + operator(--)ident(k)operator(;) + operator(++)ident(ke)operator(;) + operator(}) + + operator({) comment(// cleanup dying sockets) + comment(// vector::pop_back works in constant time.) + comment(// TODO, rip this out and only delete the descriptors we know have died,) + comment(// rather than traversing the whole list.) + comment(// In kqueue, closing a descriptor automatically removes its event filters.) + + pre_type(int) ident(i)operator(,) ident(j)operator(;) + pre_type(int) ident(nSockets) operator(=) ident(Descriptors)operator(.)ident(size)operator((\);) + reserved(for) operator(()ident(i)operator(=)integer(0)operator(,) ident(j)operator(=)integer(0)operator(;) ident(i) operator(<) ident(nSockets)operator(;) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(Descriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ed)operator(\);) + reserved(if) operator(()ident(ed)operator(->)ident(ShouldDelete)operator((\)\)) operator({) + ident(ModifiedDescriptors)operator(.)ident(erase) operator(()ident(ed)operator(\);) + reserved(delete) ident(ed)operator(;) + operator(}) + reserved(else) + ident(Descriptors) operator([)ident(j)operator(++]) operator(=) ident(ed)operator(;) + operator(}) + reserved(while) operator((()ident(size_t)operator(\))ident(j) operator(<) ident(Descriptors)operator(.)ident(size)operator((\)\)) + ident(Descriptors)operator(.)ident(pop_back)operator((\);) + + operator(}) + + operator({) comment(// dispatch heartbeats) + reserved(if) operator(()ident(gCurrentLoopTime) operator(>=) ident(NextHeartbeatTime)operator(\)) operator({) + ident(NextHeartbeatTime) operator(=) ident(gCurrentLoopTime) operator(+) ident(HeartbeatInterval)operator(;) + + reserved(for) operator(()pre_type(int) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) ident(Descriptors)operator(.)ident(size)operator((\);) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(Descriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ed)operator(\);) + ident(ed)operator(->)ident(Heartbeat)operator((\);) + operator(}) + operator(}) + operator(}) + + + comment(// TODO, replace this with rb_thread_blocking_region for 1.9 builds.) + preprocessor(#ifdef) ident(BUILD_FOR_RUBY) + reserved(if) operator((!)ident(rb_thread_alone)operator((\)\)) operator({) + ident(rb_thread_schedule)operator((\);) + operator(}) + preprocessor(#endif) + + reserved(return) pre_constant(true)operator(;) + preprocessor(#else) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(kqueue is not implemented on this platform)delimiter(")>operator(\);) + preprocessor(#endif) +operator(}) + + +comment(/********************************* +EventMachine_t::_ModifyEpollEvent +*********************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(_ModifyEpollEvent) operator(()ident(EventableDescriptor) operator(*)ident(ed)operator(\)) +operator({) + preprocessor(#ifdef) ident(HAVE_EPOLL) + reserved(if) operator(()ident(bEpoll)operator(\)) operator({) + ident(assert) operator(()ident(epfd) operator(!=) operator(-)integer(1)operator(\);) + ident(assert) operator(()ident(ed)operator(\);) + pre_type(int) ident(e) operator(=) ident(epoll_ctl) operator(()ident(epfd)operator(,) ident(EPOLL_CTL_MOD)operator(,) ident(ed)operator(->)ident(GetSocket)operator((\),) ident(ed)operator(->)ident(GetEpollEvent)operator((\)\);) + reserved(if) operator(()ident(e)operator(\)) operator({) + pre_type(char) ident(buf) operator([)integer(200)operator(];) + ident(snprintf) operator(()ident(buf)operator(,) reserved(sizeof)operator(()ident(buf)operator(\)-)integer(1)operator(,) string<delimiter(")content(unable to modify epoll event: %s)delimiter(")>operator(,) ident(strerror)operator(()ident(errno)operator(\)\);) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()ident(buf)operator(\);) + operator(}) + operator(}) + preprocessor(#endif) +operator(}) + + + +comment(/************************** +SelectData_t::SelectData_t +**************************/) + +ident(SelectData_t)operator(::)ident(SelectData_t)operator((\)) +operator({) + ident(maxsocket) operator(=) integer(0)operator(;) + ident(FD_ZERO) operator((&)ident(fdreads)operator(\);) + ident(FD_ZERO) operator((&)ident(fdwrites)operator(\);) +operator(}) + + +preprocessor(#ifdef) ident(BUILD_FOR_RUBY) +comment(/***************** +_SelectDataSelect +*****************/) + +preprocessor(#ifdef) ident(HAVE_TBR) +directive(static) ident(VALUE) ident(_SelectDataSelect) operator(()directive(void) operator(*)ident(v)operator(\)) +operator({) + ident(SelectData_t) operator(*)ident(sd) operator(=) operator(()ident(SelectData_t)operator(*\))ident(v)operator(;) + ident(sd)operator(->)ident(nSockets) operator(=) ident(select) operator(()ident(sd)operator(->)ident(maxsocket)operator(+)integer(1)operator(,) operator(&()ident(sd)operator(->)ident(fdreads)operator(\),) operator(&()ident(sd)operator(->)ident(fdwrites)operator(\),) pre_constant(NULL)operator(,) operator(&()ident(sd)operator(->)ident(tv)operator(\)\);) + reserved(return) ident(Qnil)operator(;) +operator(}) +preprocessor(#endif) + +comment(/********************* +SelectData_t::_Select +*********************/) + +pre_type(int) ident(SelectData_t)operator(::)ident(_Select)operator((\)) +operator({) + preprocessor(#ifdef) ident(HAVE_TBR) + ident(rb_thread_blocking_region) operator(()ident(_SelectDataSelect)operator(,) operator(()directive(void)operator(*\))local_variable(this)operator(,) ident(RUBY_UBF_IO)operator(,) integer(0)operator(\);) + reserved(return) ident(nSockets)operator(;) + preprocessor(#endif) + + preprocessor(#ifndef) ident(HAVE_TBR) + reserved(return) ident(EmSelect) operator(()ident(maxsocket)operator(+)integer(1)operator(,) operator(&)ident(fdreads)operator(,) operator(&)ident(fdwrites)operator(,) pre_constant(NULL)operator(,) operator(&)ident(tv)operator(\);) + preprocessor(#endif) +operator(}) +preprocessor(#endif) + + + +comment(/****************************** +EventMachine_t::_RunSelectOnce +******************************/) + +pre_type(bool) ident(EventMachine_t)operator(::)ident(_RunSelectOnce)operator((\)) +operator({) + comment(// Crank the event machine once.) + comment(// If there are no descriptors to process, then sleep) + comment(// for a few hundred mills to avoid busy-looping.) + comment(// Return T/F to indicate whether we should continue.) + comment(// This is based on a select loop. Alternately provide epoll) + comment(// if we know we're running on a 2.6 kernel.) + comment(// epoll will be effective if we provide it as an alternative,) + comment(// however it has the same problem interoperating with Ruby) + comment(// threads that select does.) + + comment(//cerr << "X";) + + comment(/* This protection is now obsolete, because we will ALWAYS + * have at least one descriptor (the loop-breaker\) to read. + */) + comment(/* + if (Descriptors.size(\) == 0\) { + #ifdef OS_UNIX + timeval tv = {0, 200 * 1000}; + EmSelect (0, NULL, NULL, NULL, &tv\); + return true; + #endif + #ifdef OS_WIN32 + Sleep (200\); + return true; + #endif + } + */) + + ident(SelectData_t) ident(SelectData)operator(;) + comment(/* + fd_set fdreads, fdwrites; + FD_ZERO (&fdreads\); + FD_ZERO (&fdwrites\); + + int maxsocket = 0; + */) + + comment(// Always read the loop-breaker reader.) + comment(// Changed 23Aug06, provisionally implemented for Windows with a UDP socket) + comment(// running on localhost with a randomly-chosen port. (*Puke*\)) + comment(// Windows has a version of the Unix pipe(\) library function, but it doesn't) + comment(// give you back descriptors that are selectable.) + ident(FD_SET) operator(()ident(LoopBreakerReader)operator(,) operator(&()ident(SelectData)operator(.)ident(fdreads)operator(\)\);) + reserved(if) operator(()ident(SelectData)operator(.)ident(maxsocket) operator(<) ident(LoopBreakerReader)operator(\)) + ident(SelectData)operator(.)ident(maxsocket) operator(=) ident(LoopBreakerReader)operator(;) + + comment(// prepare the sockets for reading and writing) + ident(size_t) ident(i)operator(;) + reserved(for) operator(()ident(i) operator(=) integer(0)operator(;) ident(i) operator(<) ident(Descriptors)operator(.)ident(size)operator((\);) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(Descriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ed)operator(\);) + pre_type(int) ident(sd) operator(=) ident(ed)operator(->)ident(GetSocket)operator((\);) + ident(assert) operator(()ident(sd) operator(!=) ident(INVALID_SOCKET)operator(\);) + + reserved(if) operator(()ident(ed)operator(->)ident(SelectForRead)operator((\)\)) + ident(FD_SET) operator(()ident(sd)operator(,) operator(&()ident(SelectData)operator(.)ident(fdreads)operator(\)\);) + reserved(if) operator(()ident(ed)operator(->)ident(SelectForWrite)operator((\)\)) + ident(FD_SET) operator(()ident(sd)operator(,) operator(&()ident(SelectData)operator(.)ident(fdwrites)operator(\)\);) + + reserved(if) operator(()ident(SelectData)operator(.)ident(maxsocket) operator(<) ident(sd)operator(\)) + ident(SelectData)operator(.)ident(maxsocket) operator(=) ident(sd)operator(;) + operator(}) + + + operator({) comment(// read and write the sockets) + comment(//timeval tv = {1, 0}; // Solaris fails if the microseconds member is >= 1000000.) + comment(//timeval tv = Quantum;) + ident(SelectData)operator(.)ident(tv) operator(=) ident(Quantum)operator(;) + pre_type(int) ident(s) operator(=) ident(SelectData)operator(.)ident(_Select)operator((\);) + comment(//rb_thread_blocking_region(xxx,(void*\)&SelectData,RUBY_UBF_IO,0\);) + comment(//int s = EmSelect (SelectData.maxsocket+1, &(SelectData.fdreads\), &(SelectData.fdwrites\), NULL, &(SelectData.tv\)\);) + comment(//int s = SelectData.nSockets;) + reserved(if) operator(()ident(s) operator(>) integer(0)operator(\)) operator({) + comment(/* Changed 01Jun07. We used to handle the Loop-breaker right here. + * Now we do it AFTER all the regular descriptors. There's an + * incredibly important and subtle reason for this. Code on + * loop breakers is sometimes used to cause the reactor core to + * cycle (for example, to allow outbound network buffers to drain\). + * If a loop-breaker handler reschedules itself (say, after determining + * that the write buffers are still too full\), then it will execute + * IMMEDIATELY if _ReadLoopBreaker is done here instead of after + * the other descriptors are processed. That defeats the whole purpose. + */) + reserved(for) operator(()ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) ident(Descriptors)operator(.)ident(size)operator((\);) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(Descriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ed)operator(\);) + pre_type(int) ident(sd) operator(=) ident(ed)operator(->)ident(GetSocket)operator((\);) + ident(assert) operator(()ident(sd) operator(!=) ident(INVALID_SOCKET)operator(\);) + + reserved(if) operator(()ident(FD_ISSET) operator(()ident(sd)operator(,) operator(&()ident(SelectData)operator(.)ident(fdwrites)operator(\)\)\)) + ident(ed)operator(->)ident(Write)operator((\);) + reserved(if) operator(()ident(FD_ISSET) operator(()ident(sd)operator(,) operator(&()ident(SelectData)operator(.)ident(fdreads)operator(\)\)\)) + ident(ed)operator(->)ident(Read)operator((\);) + operator(}) + + reserved(if) operator(()ident(FD_ISSET) operator(()ident(LoopBreakerReader)operator(,) operator(&()ident(SelectData)operator(.)ident(fdreads)operator(\)\)\)) + ident(_ReadLoopBreaker)operator((\);) + operator(}) + reserved(else) reserved(if) operator(()ident(s) operator(<) integer(0)operator(\)) operator({) + comment(// select can fail on error in a handful of ways.) + comment(// If this happens, then wait for a little while to avoid busy-looping.) + comment(// If the error was EINTR, we probably caught SIGCHLD or something,) + comment(// so keep the wait short.) + ident(timeval) ident(tv) operator(=) operator({)integer(0)operator(,) operator((()ident(errno) operator(==) ident(EINTR)operator(\)) operator(?) integer(5) operator(:) integer(50)operator(\)) operator(*) integer(1000)operator(};) + ident(EmSelect) operator(()integer(0)operator(,) pre_constant(NULL)operator(,) pre_constant(NULL)operator(,) pre_constant(NULL)operator(,) operator(&)ident(tv)operator(\);) + operator(}) + operator(}) + + + operator({) comment(// dispatch heartbeats) + reserved(if) operator(()ident(gCurrentLoopTime) operator(>=) ident(NextHeartbeatTime)operator(\)) operator({) + ident(NextHeartbeatTime) operator(=) ident(gCurrentLoopTime) operator(+) ident(HeartbeatInterval)operator(;) + + reserved(for) operator(()ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) ident(Descriptors)operator(.)ident(size)operator((\);) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(Descriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ed)operator(\);) + ident(ed)operator(->)ident(Heartbeat)operator((\);) + operator(}) + operator(}) + operator(}) + + operator({) comment(// cleanup dying sockets) + comment(// vector::pop_back works in constant time.) + pre_type(int) ident(i)operator(,) ident(j)operator(;) + pre_type(int) ident(nSockets) operator(=) ident(Descriptors)operator(.)ident(size)operator((\);) + reserved(for) operator(()ident(i)operator(=)integer(0)operator(,) ident(j)operator(=)integer(0)operator(;) ident(i) operator(<) ident(nSockets)operator(;) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(Descriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ed)operator(\);) + reserved(if) operator(()ident(ed)operator(->)ident(ShouldDelete)operator((\)\)) + reserved(delete) ident(ed)operator(;) + reserved(else) + ident(Descriptors) operator([)ident(j)operator(++]) operator(=) ident(ed)operator(;) + operator(}) + reserved(while) operator((()ident(size_t)operator(\))ident(j) operator(<) ident(Descriptors)operator(.)ident(size)operator((\)\)) + ident(Descriptors)operator(.)ident(pop_back)operator((\);) + + operator(}) + + reserved(return) pre_constant(true)operator(;) +operator(}) + + +comment(/******************************** +EventMachine_t::_ReadLoopBreaker +********************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(_ReadLoopBreaker)operator((\)) +operator({) + comment(/* The loop breaker has selected readable. + * Read it ONCE (it may block if we try to read it twice\) + * and send a loop-break event back to user code. + */) + pre_type(char) ident(buffer) operator([)integer(1024)operator(];) + ident(read) operator(()ident(LoopBreakerReader)operator(,) ident(buffer)operator(,) reserved(sizeof)operator(()ident(buffer)operator(\)\);) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)()string<delimiter(")delimiter(")>operator(,) ident(EM_LOOPBREAK_SIGNAL)operator(,) string<delimiter(")delimiter(")>operator(,) integer(0)operator(\);) +operator(}) + + +comment(/************************** +EventMachine_t::_RunTimers +**************************/) + +pre_type(bool) ident(EventMachine_t)operator(::)ident(_RunTimers)operator((\)) +operator({) + comment(// These are caller-defined timer handlers.) + comment(// Return T/F to indicate whether we should continue the main loop.) + comment(// We rely on the fact that multimaps sort by their keys to avoid) + comment(// inspecting the whole list every time we come here.) + comment(// Just keep inspecting and processing the list head until we hit) + comment(// one that hasn't expired yet.) + + preprocessor(#ifdef) ident(OS_UNIX) + reserved(struct) ident(timeval) ident(tv)operator(;) + ident(gettimeofday) operator((&)ident(tv)operator(,) pre_constant(NULL)operator(\);) + ident(Int64) ident(now) operator(=) operator(((()ident(Int64)operator(\)()ident(tv)operator(.)ident(tv_sec)operator(\)\)) operator(*) integer(1000000LL)operator(\)) operator(+) operator((()ident(Int64)operator(\)()ident(tv)operator(.)ident(tv_usec)operator(\)\);) + preprocessor(#endif) + + preprocessor(#ifdef) ident(OS_WIN32) + pre_type(unsigned) ident(tick) operator(=) ident(GetTickCount)operator((\);) + reserved(if) operator(()ident(tick) operator(<) ident(gLastTickCount)operator(\)) + ident(gTickCountTickover) operator(+=) integer(1)operator(;) + ident(gLastTickCount) operator(=) ident(tick)operator(;) + ident(Int64) ident(now) operator(=) operator((()ident(Int64)operator(\))ident(gTickCountTickover) operator(<<) integer(32)operator(\)) operator(+) operator(()ident(Int64)operator(\))ident(tick)operator(;) + preprocessor(#endif) + + reserved(while) operator(()pre_constant(true)operator(\)) operator({) + ident(multimap)operator(<)ident(Int64)operator(,)ident(Timer_t)operator(>::)ident(iterator) ident(i) operator(=) ident(Timers)operator(.)ident(begin)operator((\);) + reserved(if) operator(()ident(i) operator(==) ident(Timers)operator(.)ident(end)operator((\)\)) + reserved(break)operator(;) + reserved(if) operator(()ident(i)operator(->)ident(first) operator(>) ident(now)operator(\)) + reserved(break)operator(;) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)) operator(()string<delimiter(")delimiter(")>operator(,) ident(EM_TIMER_FIRED)operator(,) ident(i)operator(->)ident(second)operator(.)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(i)operator(->)ident(second)operator(.)ident(GetBinding)operator((\))operator(.)ident(length)operator((\)\);) + ident(Timers)operator(.)ident(erase) operator(()ident(i)operator(\);) + operator(}) + reserved(return) pre_constant(true)operator(;) +operator(}) + + + +comment(/*********************************** +EventMachine_t::InstallOneshotTimer +***********************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(InstallOneshotTimer) operator(()pre_type(int) ident(milliseconds)operator(\)) +operator({) + reserved(if) operator(()ident(Timers)operator(.)ident(size)operator((\)) operator(>) ident(MaxOutstandingTimers)operator(\)) + reserved(return) pre_constant(false)operator(;) + comment(// Don't use the global loop-time variable here, because we might) + comment(// get called before the main event machine is running.) + + preprocessor(#ifdef) ident(OS_UNIX) + reserved(struct) ident(timeval) ident(tv)operator(;) + ident(gettimeofday) operator((&)ident(tv)operator(,) pre_constant(NULL)operator(\);) + ident(Int64) ident(fire_at) operator(=) operator(((()ident(Int64)operator(\)()ident(tv)operator(.)ident(tv_sec)operator(\)\)) operator(*) integer(1000000LL)operator(\)) operator(+) operator((()ident(Int64)operator(\)()ident(tv)operator(.)ident(tv_usec)operator(\)\);) + ident(fire_at) operator(+=) operator((()ident(Int64)operator(\))ident(milliseconds)operator(\)) operator(*) integer(1000LL)operator(;) + preprocessor(#endif) + + preprocessor(#ifdef) ident(OS_WIN32) + pre_type(unsigned) ident(tick) operator(=) ident(GetTickCount)operator((\);) + reserved(if) operator(()ident(tick) operator(<) ident(gLastTickCount)operator(\)) + ident(gTickCountTickover) operator(+=) integer(1)operator(;) + ident(gLastTickCount) operator(=) ident(tick)operator(;) + + ident(Int64) ident(fire_at) operator(=) operator((()ident(Int64)operator(\))ident(gTickCountTickover) operator(<<) integer(32)operator(\)) operator(+) operator(()ident(Int64)operator(\))ident(tick)operator(;) + ident(fire_at) operator(+=) operator(()ident(Int64)operator(\))ident(milliseconds)operator(;) + preprocessor(#endif) + + ident(Timer_t) ident(t)operator(;) + ident(multimap)operator(<)ident(Int64)operator(,)ident(Timer_t)operator(>::)ident(iterator) ident(i) operator(=) + ident(Timers)operator(.)ident(insert) operator(()ident(make_pair) operator(()ident(fire_at)operator(,) ident(t)operator(\)\);) + reserved(return) ident(i)operator(->)ident(second)operator(.)ident(GetBindingChars)operator((\);) +operator(}) + + +comment(/******************************* +EventMachine_t::ConnectToServer +*******************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(ConnectToServer) operator(()directive(const) pre_type(char) operator(*)ident(server)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + comment(/* We want to spend no more than a few seconds waiting for a connection + * to a remote host. So we use a nonblocking connect. + * Linux disobeys the usual rules for nonblocking connects. + * Per Stevens (UNP p.410\), you expect a nonblocking connect to select + * both readable and writable on error, and not to return EINPROGRESS + * if the connect can be fulfilled immediately. Linux violates both + * of these expectations. + * Any kind of nonblocking connect on Linux returns EINPROGRESS. + * The socket will then return writable when the disposition of the + * connect is known, but it will not also be readable in case of + * error! Weirdly, it will be readable in case there is data to read!!! + * (Which can happen with protocols like SSH and SMTP.\) + * I suppose if you were so inclined you could consider this logical, + * but it's not the way Unix has historically done it. + * So we ignore the readable flag and read getsockopt to see if there + * was an error connecting. A select timeout works as expected. + * In regard to getsockopt: Linux does the Berkeley-style thing, + * not the Solaris-style, and returns zero with the error code in + * the error parameter. + * Return the binding-text of the newly-created pending connection, + * or NULL if there was a problem. + */) + + reserved(if) operator((!)ident(server) operator(||) operator(!*)ident(server) operator(||) operator(!)ident(port)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + + pre_type(int) ident(family)operator(,) ident(bind_size)operator(;) + reserved(struct) ident(sockaddr) operator(*)ident(bind_as) operator(=) ident(name2address) operator(()ident(server)operator(,) ident(port)operator(,) operator(&)ident(family)operator(,) operator(&)ident(bind_size)operator(\);) + reserved(if) operator((!)ident(bind_as)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + + pre_type(int) ident(sd) operator(=) ident(socket) operator(()ident(family)operator(,) ident(SOCK_STREAM)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(sd) operator(==) ident(INVALID_SOCKET)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + + comment(/* + sockaddr_in pin; + unsigned long HostAddr; + + HostAddr = inet_addr (server\); + if (HostAddr == INADDR_NONE\) { + hostent *hp = gethostbyname ((char*\)server\); // Windows requires (char*\) + if (!hp\) { + // TODO: This gives the caller a fatal error. Not good. + // They can respond by catching RuntimeError (blecch\). + // Possibly we need to fire an unbind event and provide + // a status code so user code can detect the cause of the + // failure. + return NULL; + } + HostAddr = ((in_addr*\)(hp->h_addr\)\)->s_addr; + } + + memset (&pin, 0, sizeof(pin\)\); + pin.sin_family = AF_INET; + pin.sin_addr.s_addr = HostAddr; + pin.sin_port = htons (port\); + + int sd = socket (AF_INET, SOCK_STREAM, 0\); + if (sd == INVALID_SOCKET\) + return NULL; + */) + + comment(// From here on, ALL error returns must close the socket.) + comment(// Set the new socket nonblocking.) + reserved(if) operator((!)ident(SetSocketNonblocking) operator(()ident(sd)operator(\)\)) operator({) + ident(closesocket) operator(()ident(sd)operator(\);) + reserved(return) pre_constant(NULL)operator(;) + operator(}) + comment(// Disable slow-start (Nagle algorithm\).) + pre_type(int) ident(one) operator(=) integer(1)operator(;) + ident(setsockopt) operator(()ident(sd)operator(,) ident(IPPROTO_TCP)operator(,) ident(TCP_NODELAY)operator(,) operator(()pre_type(char)operator(*\)) operator(&)ident(one)operator(,) reserved(sizeof)operator(()ident(one)operator(\)\);) + + directive(const) pre_type(char) operator(*)ident(out) operator(=) pre_constant(NULL)operator(;) + + preprocessor(#ifdef) ident(OS_UNIX) + comment(//if (connect (sd, (sockaddr*\)&pin, sizeof pin\) == 0\) {) + reserved(if) operator(()ident(connect) operator(()ident(sd)operator(,) ident(bind_as)operator(,) ident(bind_size)operator(\)) operator(==) integer(0)operator(\)) operator({) + comment(// This is a connect success, which Linux appears) + comment(// never to give when the socket is nonblocking,) + comment(// even if the connection is intramachine or to) + comment(// localhost.) + + comment(/* Changed this branch 08Aug06. Evidently some kernels + * (FreeBSD for example\) will actually return success from + * a nonblocking connect. This is a pretty simple case, + * just set up the new connection and clear the pending flag. + * Thanks to Chris Ochs for helping track this down. + * This branch never gets taken on Linux or (oddly\) OSX. + * The original behavior was to throw an unimplemented, + * which the user saw as a fatal exception. Very unfriendly. + * + * Tweaked 10Aug06. Even though the connect disposition is + * known, we still set the connect-pending flag. That way + * some needed initialization will happen in the ConnectionDescriptor. + * (To wit, the ConnectionCompleted event gets sent to the client.\) + */) + ident(ConnectionDescriptor) operator(*)ident(cd) operator(=) reserved(new) ident(ConnectionDescriptor) operator(()ident(sd)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(cd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no connection allocated)delimiter(")>operator(\);) + ident(cd)operator(->)ident(SetConnectPending) operator(()pre_constant(true)operator(\);) + ident(Add) operator(()ident(cd)operator(\);) + ident(out) operator(=) ident(cd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + operator(}) + reserved(else) reserved(if) operator(()ident(errno) operator(==) ident(EINPROGRESS)operator(\)) operator({) + comment(// Errno will generally always be EINPROGRESS, but on Linux) + comment(// we have to look at getsockopt to be sure what really happened.) + pre_type(int) ident(error)operator(;) + ident(socklen_t) ident(len)operator(;) + ident(len) operator(=) reserved(sizeof)operator(()ident(error)operator(\);) + pre_type(int) ident(o) operator(=) ident(getsockopt) operator(()ident(sd)operator(,) ident(SOL_SOCKET)operator(,) ident(SO_ERROR)operator(,) operator(&)ident(error)operator(,) operator(&)ident(len)operator(\);) + reserved(if) operator((()ident(o) operator(==) integer(0)operator(\)) operator(&&) operator(()ident(error) operator(==) integer(0)operator(\)\)) operator({) + comment(// Here, there's no disposition.) + comment(// Put the connection on the stack and wait for it to complete) + comment(// or time out.) + ident(ConnectionDescriptor) operator(*)ident(cd) operator(=) reserved(new) ident(ConnectionDescriptor) operator(()ident(sd)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(cd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no connection allocated)delimiter(")>operator(\);) + ident(cd)operator(->)ident(SetConnectPending) operator(()pre_constant(true)operator(\);) + ident(Add) operator(()ident(cd)operator(\);) + ident(out) operator(=) ident(cd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + operator(}) + reserved(else) operator({) + comment(/* This could be connection refused or some such thing. + * We will come here on Linux if a localhost connection fails. + * Changed 16Jul06: Originally this branch was a no-op, and + * we'd drop down to the end of the method, close the socket, + * and return NULL, which would cause the caller to GET A + * FATAL EXCEPTION. Now we keep the socket around but schedule an + * immediate close on it, so the caller will get a close-event + * scheduled on it. This was only an issue for localhost connections + * to non-listening ports. We may eventually need to revise this + * revised behavior, in case it causes problems like making it hard + * for people to know that a failure occurred. + */) + ident(ConnectionDescriptor) operator(*)ident(cd) operator(=) reserved(new) ident(ConnectionDescriptor) operator(()ident(sd)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(cd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no connection allocated)delimiter(")>operator(\);) + ident(cd)operator(->)ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + ident(Add) operator(()ident(cd)operator(\);) + ident(out) operator(=) ident(cd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + operator(}) + operator(}) + reserved(else) operator({) + comment(// The error from connect was something other then EINPROGRESS.) + operator(}) + preprocessor(#endif) + + preprocessor(#ifdef) ident(OS_WIN32) + comment(//if (connect (sd, (sockaddr*\)&pin, sizeof pin\) == 0\) {) + reserved(if) operator(()ident(connect) operator(()ident(sd)operator(,) ident(bind_as)operator(,) ident(bind_size)operator(\)) operator(==) integer(0)operator(\)) operator({) + comment(// This is a connect success, which Windows appears) + comment(// never to give when the socket is nonblocking,) + comment(// even if the connection is intramachine or to) + comment(// localhost.) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unimplemented)delimiter(")>operator(\);) + operator(}) + reserved(else) reserved(if) operator(()ident(WSAGetLastError)operator((\)) operator(==) ident(WSAEWOULDBLOCK)operator(\)) operator({) + comment(// Here, there's no disposition.) + comment(// Windows appears not to surface refused connections or) + comment(// such stuff at this point.) + comment(// Put the connection on the stack and wait for it to complete) + comment(// or time out.) + ident(ConnectionDescriptor) operator(*)ident(cd) operator(=) reserved(new) ident(ConnectionDescriptor) operator(()ident(sd)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(cd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no connection allocated)delimiter(")>operator(\);) + ident(cd)operator(->)ident(SetConnectPending) operator(()pre_constant(true)operator(\);) + ident(Add) operator(()ident(cd)operator(\);) + ident(out) operator(=) ident(cd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + operator(}) + reserved(else) operator({) + comment(// The error from connect was something other then WSAEWOULDBLOCK.) + operator(}) + + preprocessor(#endif) + + reserved(if) operator(()ident(out) operator(==) pre_constant(NULL)operator(\)) + ident(closesocket) operator(()ident(sd)operator(\);) + reserved(return) ident(out)operator(;) +operator(}) + +comment(/*********************************** +EventMachine_t::ConnectToUnixServer +***********************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(ConnectToUnixServer) operator(()directive(const) pre_type(char) operator(*)ident(server)operator(\)) +operator({) + comment(/* Connect to a Unix-domain server, which by definition is running + * on the same host. + * There is no meaningful implementation on Windows. + * There's no need to do a nonblocking connect, since the connection + * is always local and can always be fulfilled immediately. + */) + + preprocessor(#ifdef) ident(OS_WIN32) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unix-domain connection unavailable on this platform)delimiter(")>operator(\);) + reserved(return) pre_constant(NULL)operator(;) + preprocessor(#endif) + + comment(// The whole rest of this function is only compiled on Unix systems.) + preprocessor(#ifdef) ident(OS_UNIX) + + directive(const) pre_type(char) operator(*)ident(out) operator(=) pre_constant(NULL)operator(;) + + reserved(if) operator((!)ident(server) operator(||) operator(!*)ident(server)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + + ident(sockaddr_un) ident(pun)operator(;) + ident(memset) operator((&)ident(pun)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(pun)operator(\)\);) + ident(pun)operator(.)ident(sun_family) operator(=) ident(AF_LOCAL)operator(;) + + comment(// You ordinarily expect the server name field to be at least 1024 bytes long,) + comment(// but on Linux it can be MUCH shorter.) + reserved(if) operator(()ident(strlen)operator(()ident(server)operator(\)) operator(>=) reserved(sizeof)operator(()ident(pun)operator(.)ident(sun_path)operator(\)\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unix-domain server name is too long)delimiter(")>operator(\);) + + + ident(strcpy) operator(()ident(pun)operator(.)ident(sun_path)operator(,) ident(server)operator(\);) + + pre_type(int) ident(fd) operator(=) ident(socket) operator(()ident(AF_LOCAL)operator(,) ident(SOCK_STREAM)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(fd) operator(==) ident(INVALID_SOCKET)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + + comment(// From here on, ALL error returns must close the socket.) + comment(// NOTE: At this point, the socket is still a blocking socket.) + reserved(if) operator(()ident(connect) operator(()ident(fd)operator(,) operator(()reserved(struct) ident(sockaddr)operator(*\)&)ident(pun)operator(,) reserved(sizeof)operator(()ident(pun)operator(\)\)) operator(!=) integer(0)operator(\)) operator({) + ident(closesocket) operator(()ident(fd)operator(\);) + reserved(return) pre_constant(NULL)operator(;) + operator(}) + + comment(// Set the newly-connected socket nonblocking.) + reserved(if) operator((!)ident(SetSocketNonblocking) operator(()ident(fd)operator(\)\)) operator({) + ident(closesocket) operator(()ident(fd)operator(\);) + reserved(return) pre_constant(NULL)operator(;) + operator(}) + + comment(// Set up a connection descriptor and add it to the event-machine.) + comment(// Observe, even though we know the connection status is connect-success,) + comment(// we still set the "pending" flag, so some needed initializations take) + comment(// place.) + ident(ConnectionDescriptor) operator(*)ident(cd) operator(=) reserved(new) ident(ConnectionDescriptor) operator(()ident(fd)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(cd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no connection allocated)delimiter(")>operator(\);) + ident(cd)operator(->)ident(SetConnectPending) operator(()pre_constant(true)operator(\);) + ident(Add) operator(()ident(cd)operator(\);) + ident(out) operator(=) ident(cd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + + reserved(if) operator(()ident(out) operator(==) pre_constant(NULL)operator(\)) + ident(closesocket) operator(()ident(fd)operator(\);) + + reserved(return) ident(out)operator(;) + preprocessor(#endif) +operator(}) + +comment(/************************ +EventMachine_t::AttachFD +************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(AttachFD) operator(()pre_type(int) ident(fd)operator(,) pre_type(bool) ident(notify_readable)operator(,) pre_type(bool) ident(notify_writable)operator(\)) +operator({) + preprocessor(#ifdef) ident(OS_UNIX) + reserved(if) operator(()ident(fcntl)operator(()ident(fd)operator(,) ident(F_GETFL)operator(,) integer(0)operator(\)) operator(<) integer(0)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(invalid file descriptor)delimiter(")>operator(\);) + preprocessor(#endif) + + preprocessor(#ifdef) ident(OS_WIN32) + comment(// TODO: add better check for invalid file descriptors (see ioctlsocket or getsockopt\)) + reserved(if) operator(()ident(fd) operator(==) ident(INVALID_SOCKET)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(invalid file descriptor)delimiter(")>operator(\);) + preprocessor(#endif) + + operator({//) ident(Check) reserved(for) ident(duplicate) ident(descriptors) + ident(size_t) ident(i)operator(;) + reserved(for) operator(()ident(i) operator(=) integer(0)operator(;) ident(i) operator(<) ident(Descriptors)operator(.)ident(size)operator((\);) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(Descriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ed)operator(\);) + reserved(if) operator(()ident(ed)operator(->)ident(GetSocket)operator((\)) operator(==) ident(fd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(adding existing descriptor)delimiter(")>operator(\);) + operator(}) + + reserved(for) operator(()ident(i) operator(=) integer(0)operator(;) ident(i) operator(<) ident(NewDescriptors)operator(.)ident(size)operator((\);) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(NewDescriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ed)operator(\);) + reserved(if) operator(()ident(ed)operator(->)ident(GetSocket)operator((\)) operator(==) ident(fd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(adding existing new descriptor)delimiter(")>operator(\);) + operator(}) + operator(}) + + ident(ConnectionDescriptor) operator(*)ident(cd) operator(=) reserved(new) ident(ConnectionDescriptor) operator(()ident(fd)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(cd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no connection allocated)delimiter(")>operator(\);) + + ident(cd)operator(->)ident(SetConnectPending) operator(()pre_constant(true)operator(\);) + ident(cd)operator(->)ident(SetNotifyReadable) operator(()ident(notify_readable)operator(\);) + ident(cd)operator(->)ident(SetNotifyWritable) operator(()ident(notify_writable)operator(\);) + + ident(Add) operator(()ident(cd)operator(\);) + + directive(const) pre_type(char) operator(*)ident(out) operator(=) pre_constant(NULL)operator(;) + ident(out) operator(=) ident(cd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + reserved(if) operator(()ident(out) operator(==) pre_constant(NULL)operator(\)) + ident(closesocket) operator(()ident(fd)operator(\);) + reserved(return) ident(out)operator(;) +operator(}) + +comment(/************************ +EventMachine_t::DetachFD +************************/) + +pre_type(int) ident(EventMachine_t)operator(::)ident(DetachFD) operator(()ident(EventableDescriptor) operator(*)ident(ed)operator(\)) +operator({) + reserved(if) operator((!)ident(ed)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(detaching bad descriptor)delimiter(")>operator(\);) + + preprocessor(#ifdef) ident(HAVE_EPOLL) + reserved(if) operator(()ident(bEpoll)operator(\)) operator({) + reserved(if) operator(()ident(ed)operator(->)ident(GetSocket)operator((\)) operator(!=) ident(INVALID_SOCKET)operator(\)) operator({) + ident(assert) operator(()ident(bEpoll)operator(\);) comment(// wouldn't be in this method otherwise.) + ident(assert) operator(()ident(epfd) operator(!=) operator(-)integer(1)operator(\);) + pre_type(int) ident(e) operator(=) ident(epoll_ctl) operator(()ident(epfd)operator(,) ident(EPOLL_CTL_DEL)operator(,) ident(ed)operator(->)ident(GetSocket)operator((\),) ident(ed)operator(->)ident(GetEpollEvent)operator((\)\);) + comment(// ENOENT or EBADF are not errors because the socket may be already closed when we get here.) + reserved(if) operator(()ident(e) operator(&&) operator(()ident(errno) operator(!=) ident(ENOENT)operator(\)) operator(&&) operator(()ident(errno) operator(!=) ident(EBADF)operator(\)\)) operator({) + pre_type(char) ident(buf) operator([)integer(200)operator(];) + ident(snprintf) operator(()ident(buf)operator(,) reserved(sizeof)operator(()ident(buf)operator(\)-)integer(1)operator(,) string<delimiter(")content(unable to delete epoll event: %s)delimiter(")>operator(,) ident(strerror)operator(()ident(errno)operator(\)\);) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()ident(buf)operator(\);) + operator(}) + operator(}) + operator(}) + preprocessor(#endif) + + preprocessor(#ifdef) ident(HAVE_KQUEUE) + reserved(if) operator(()ident(bKqueue)operator(\)) operator({) + reserved(struct) ident(kevent) ident(k)operator(;) + ident(EV_SET) operator((&)ident(k)operator(,) ident(ed)operator(->)ident(GetSocket)operator((\),) ident(EVFILT_READ)operator(,) ident(EV_DELETE)operator(,) integer(0)operator(,) integer(0)operator(,) ident(ed)operator(\);) + pre_type(int) ident(t) operator(=) ident(kevent) operator(()ident(kqfd)operator(,) operator(&)ident(k)operator(,) integer(1)operator(,) pre_constant(NULL)operator(,) integer(0)operator(,) pre_constant(NULL)operator(\);) + ident(assert) operator(()ident(t) operator(==) integer(0)operator(\);) + operator(}) + preprocessor(#endif) + + operator({) comment(// remove descriptor from lists) + pre_type(int) ident(i)operator(,) ident(j)operator(;) + pre_type(int) ident(nSockets) operator(=) ident(Descriptors)operator(.)ident(size)operator((\);) + reserved(for) operator(()ident(i)operator(=)integer(0)operator(,) ident(j)operator(=)integer(0)operator(;) ident(i) operator(<) ident(nSockets)operator(;) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ted) operator(=) ident(Descriptors)operator([)ident(i)operator(];) + ident(assert) operator(()ident(ted)operator(\);) + reserved(if) operator(()ident(ted) operator(!=) ident(ed)operator(\)) + ident(Descriptors) operator([)ident(j)operator(++]) operator(=) ident(ted)operator(;) + operator(}) + reserved(while) operator((()ident(size_t)operator(\))ident(j) operator(<) ident(Descriptors)operator(.)ident(size)operator((\)\)) + ident(Descriptors)operator(.)ident(pop_back)operator((\);) + + ident(ModifiedDescriptors)operator(.)ident(erase) operator(()ident(ed)operator(\);) + operator(}) + + pre_type(int) ident(fd) operator(=) ident(ed)operator(->)ident(GetSocket)operator((\);) + + comment(// We depend on ~EventableDescriptor not calling close(\) if the socket is invalid) + ident(ed)operator(->)ident(SetSocketInvalid)operator((\);) + reserved(delete) ident(ed)operator(;) + + reserved(return) ident(fd)operator(;) +operator(}) + +comment(/************ +name2address +************/) + +reserved(struct) ident(sockaddr) operator(*)ident(name2address) operator(()directive(const) pre_type(char) operator(*)ident(server)operator(,) pre_type(int) ident(port)operator(,) pre_type(int) operator(*)ident(family)operator(,) pre_type(int) operator(*)ident(bind_size)operator(\)) +operator({) + comment(// THIS IS NOT RE-ENTRANT OR THREADSAFE. Optimize for speed.) + comment(// Check the more-common cases first.) + comment(// Return NULL if no resolution.) + + directive(static) reserved(struct) ident(sockaddr_in) ident(in4)operator(;) + preprocessor(#ifndef) ident(__CYGWIN__) + directive(static) reserved(struct) ident(sockaddr_in6) ident(in6)operator(;) + preprocessor(#endif) + reserved(struct) ident(hostent) operator(*)ident(hp)operator(;) + + reserved(if) operator((!)ident(server) operator(||) operator(!*)ident(server)operator(\)) + ident(server) operator(=) string<delimiter(")content(0.0.0.0)delimiter(")>operator(;) + + ident(memset) operator((&)ident(in4)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(in4)operator(\)\);) + reserved(if) operator(() operator(()ident(in4)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) ident(inet_addr) operator(()ident(server)operator(\)\)) operator(!=) ident(INADDR_NONE)operator(\)) operator({) + reserved(if) operator(()ident(family)operator(\)) + operator(*)ident(family) operator(=) ident(AF_INET)operator(;) + reserved(if) operator(()ident(bind_size)operator(\)) + operator(*)ident(bind_size) operator(=) reserved(sizeof)operator(()ident(in4)operator(\);) + ident(in4)operator(.)ident(sin_family) operator(=) ident(AF_INET)operator(;) + ident(in4)operator(.)ident(sin_port) operator(=) ident(htons) operator(()ident(port)operator(\);) + reserved(return) operator(()reserved(struct) ident(sockaddr)operator(*\)&)ident(in4)operator(;) + operator(}) + + preprocessor(#if) ident(defined)operator(()ident(OS_UNIX)operator(\)) operator(&&) operator(!)ident(defined)operator(()ident(__CYGWIN__)operator(\)) + ident(memset) operator((&)ident(in6)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(in6)operator(\)\);) + reserved(if) operator(()ident(inet_pton) operator(()ident(AF_INET6)operator(,) ident(server)operator(,) ident(in6)operator(.)ident(sin6_addr)operator(.)ident(s6_addr)operator(\)) operator(>) integer(0)operator(\)) operator({) + reserved(if) operator(()ident(family)operator(\)) + operator(*)ident(family) operator(=) ident(AF_INET6)operator(;) + reserved(if) operator(()ident(bind_size)operator(\)) + operator(*)ident(bind_size) operator(=) reserved(sizeof)operator(()ident(in6)operator(\);) + ident(in6)operator(.)ident(sin6_family) operator(=) ident(AF_INET6)operator(;) + ident(in6)operator(.)ident(sin6_port) operator(=) ident(htons) operator(()ident(port)operator(\);) + reserved(return) operator(()reserved(struct) ident(sockaddr)operator(*\)&)ident(in6)operator(;) + operator(}) + preprocessor(#endif) + + preprocessor(#ifdef) ident(OS_WIN32) + comment(// TODO, must complete this branch. Windows doesn't have inet_pton.) + comment(// A possible approach is to make a getaddrinfo call with the supplied) + comment(// server address, constraining the hints to ipv6 and seeing if we) + comment(// get any addresses.) + comment(// For the time being, Ipv6 addresses aren't supported on Windows.) + preprocessor(#endif) + + ident(hp) operator(=) ident(gethostbyname) operator((()pre_type(char)operator(*\))ident(server)operator(\);) comment(// Windows requires the cast.) + reserved(if) operator(()ident(hp)operator(\)) operator({) + ident(in4)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) operator((()ident(in_addr)operator(*\)()ident(hp)operator(->)ident(h_addr)operator(\)\)->)ident(s_addr)operator(;) + reserved(if) operator(()ident(family)operator(\)) + operator(*)ident(family) operator(=) ident(AF_INET)operator(;) + reserved(if) operator(()ident(bind_size)operator(\)) + operator(*)ident(bind_size) operator(=) reserved(sizeof)operator(()ident(in4)operator(\);) + ident(in4)operator(.)ident(sin_family) operator(=) ident(AF_INET)operator(;) + ident(in4)operator(.)ident(sin_port) operator(=) ident(htons) operator(()ident(port)operator(\);) + reserved(return) operator(()reserved(struct) ident(sockaddr)operator(*\)&)ident(in4)operator(;) + operator(}) + + reserved(return) pre_constant(NULL)operator(;) +operator(}) + + +comment(/******************************* +EventMachine_t::CreateTcpServer +*******************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(CreateTcpServer) operator(()directive(const) pre_type(char) operator(*)ident(server)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + comment(/* Create a TCP-acceptor (server\) socket and add it to the event machine. + * Return the binding of the new acceptor to the caller. + * This binding will be referenced when the new acceptor sends events + * to indicate accepted connections. + */) + + + pre_type(int) ident(family)operator(,) ident(bind_size)operator(;) + reserved(struct) ident(sockaddr) operator(*)ident(bind_here) operator(=) ident(name2address) operator(()ident(server)operator(,) ident(port)operator(,) operator(&)ident(family)operator(,) operator(&)ident(bind_size)operator(\);) + reserved(if) operator((!)ident(bind_here)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + + directive(const) pre_type(char) operator(*)ident(output_binding) operator(=) pre_constant(NULL)operator(;) + + comment(//struct sockaddr_in sin;) + + pre_type(int) ident(sd_accept) operator(=) ident(socket) operator(()ident(family)operator(,) ident(SOCK_STREAM)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(sd_accept) operator(==) ident(INVALID_SOCKET)operator(\)) operator({) + reserved(goto) ident(fail)operator(;) + operator(}) + + comment(/* + memset (&sin, 0, sizeof(sin\)\); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_port = htons (port\); + + if (server && *server\) { + sin.sin_addr.s_addr = inet_addr (server\); + if (sin.sin_addr.s_addr == INADDR_NONE\) { + hostent *hp = gethostbyname ((char*\)server\); // Windows requires the cast. + if (hp == NULL\) { + //__warning ("hostname not resolved: ", server\); + goto fail; + } + sin.sin_addr.s_addr = ((in_addr*\)(hp->h_addr\)\)->s_addr; + } + } + */) + + operator({) comment(// set reuseaddr to improve performance on restarts.) + pre_type(int) ident(oval) operator(=) integer(1)operator(;) + reserved(if) operator(()ident(setsockopt) operator(()ident(sd_accept)operator(,) ident(SOL_SOCKET)operator(,) ident(SO_REUSEADDR)operator(,) operator(()pre_type(char)operator(*\)&)ident(oval)operator(,) reserved(sizeof)operator(()ident(oval)operator(\)\)) operator(<) integer(0)operator(\)) operator({) + comment(//__warning ("setsockopt failed while creating listener",""\);) + reserved(goto) ident(fail)operator(;) + operator(}) + operator(}) + + operator({) comment(// set CLOEXEC. Only makes sense on Unix) + preprocessor(#ifdef) ident(OS_UNIX) + pre_type(int) ident(cloexec) operator(=) ident(fcntl) operator(()ident(sd_accept)operator(,) ident(F_GETFD)operator(,) integer(0)operator(\);) + ident(assert) operator(()ident(cloexec) operator(>=) integer(0)operator(\);) + ident(cloexec) operator(|=) ident(FD_CLOEXEC)operator(;) + ident(fcntl) operator(()ident(sd_accept)operator(,) ident(F_SETFD)operator(,) ident(cloexec)operator(\);) + preprocessor(#endif) + operator(}) + + + comment(//if (bind (sd_accept, (struct sockaddr*\)&sin, sizeof(sin\)\)\) {) + reserved(if) operator(()ident(bind) operator(()ident(sd_accept)operator(,) ident(bind_here)operator(,) ident(bind_size)operator(\)\)) operator({) + comment(//__warning ("binding failed"\);) + reserved(goto) ident(fail)operator(;) + operator(}) + + reserved(if) operator(()ident(listen) operator(()ident(sd_accept)operator(,) integer(100)operator(\)\)) operator({) + comment(//__warning ("listen failed"\);) + reserved(goto) ident(fail)operator(;) + operator(}) + + operator({) + comment(// Set the acceptor non-blocking.) + comment(// THIS IS CRUCIALLY IMPORTANT because we read it in a select loop.) + reserved(if) operator((!)ident(SetSocketNonblocking) operator(()ident(sd_accept)operator(\)\)) operator({) + comment(//int val = fcntl (sd_accept, F_GETFL, 0\);) + comment(//if (fcntl (sd_accept, F_SETFL, val | O_NONBLOCK\) == -1\) {) + reserved(goto) ident(fail)operator(;) + operator(}) + operator(}) + + operator({) comment(// Looking good.) + ident(AcceptorDescriptor) operator(*)ident(ad) operator(=) reserved(new) ident(AcceptorDescriptor) operator(()ident(sd_accept)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(ad)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unable to allocate acceptor)delimiter(")>operator(\);) + ident(Add) operator(()ident(ad)operator(\);) + ident(output_binding) operator(=) ident(ad)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + operator(}) + + reserved(return) ident(output_binding)operator(;) + + label(fail)operator(:) + reserved(if) operator(()ident(sd_accept) operator(!=) ident(INVALID_SOCKET)operator(\)) + ident(closesocket) operator(()ident(sd_accept)operator(\);) + reserved(return) pre_constant(NULL)operator(;) +operator(}) + + +comment(/********************************** +EventMachine_t::OpenDatagramSocket +**********************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(OpenDatagramSocket) operator(()directive(const) pre_type(char) operator(*)ident(address)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + directive(const) pre_type(char) operator(*)ident(output_binding) operator(=) pre_constant(NULL)operator(;) + + pre_type(int) ident(sd) operator(=) ident(socket) operator(()ident(AF_INET)operator(,) ident(SOCK_DGRAM)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(sd) operator(==) ident(INVALID_SOCKET)operator(\)) + reserved(goto) ident(fail)operator(;) + comment(// from here on, early returns must close the socket!) + + + reserved(struct) ident(sockaddr_in) ident(sin)operator(;) + ident(memset) operator((&)ident(sin)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(sin)operator(\)\);) + ident(sin)operator(.)ident(sin_family) operator(=) ident(AF_INET)operator(;) + ident(sin)operator(.)ident(sin_port) operator(=) ident(htons) operator(()ident(port)operator(\);) + + + reserved(if) operator(()ident(address) operator(&&) operator(*)ident(address)operator(\)) operator({) + ident(sin)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) ident(inet_addr) operator(()ident(address)operator(\);) + reserved(if) operator(()ident(sin)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(==) ident(INADDR_NONE)operator(\)) operator({) + ident(hostent) operator(*)ident(hp) operator(=) ident(gethostbyname) operator((()pre_type(char)operator(*\))ident(address)operator(\);) comment(// Windows requires the cast.) + reserved(if) operator(()ident(hp) operator(==) pre_constant(NULL)operator(\)) + reserved(goto) ident(fail)operator(;) + ident(sin)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) operator((()ident(in_addr)operator(*\)()ident(hp)operator(->)ident(h_addr)operator(\)\)->)ident(s_addr)operator(;) + operator(}) + operator(}) + reserved(else) + ident(sin)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) ident(htonl) operator(()ident(INADDR_ANY)operator(\);) + + + comment(// Set the new socket nonblocking.) + operator({) + reserved(if) operator((!)ident(SetSocketNonblocking) operator(()ident(sd)operator(\)\)) + comment(//int val = fcntl (sd, F_GETFL, 0\);) + comment(//if (fcntl (sd, F_SETFL, val | O_NONBLOCK\) == -1\)) + reserved(goto) ident(fail)operator(;) + operator(}) + + reserved(if) operator(()ident(bind) operator(()ident(sd)operator(,) operator(()reserved(struct) ident(sockaddr)operator(*\)&)ident(sin)operator(,) reserved(sizeof)operator(()ident(sin)operator(\)\)) operator(!=) integer(0)operator(\)) + reserved(goto) ident(fail)operator(;) + + operator({) comment(// Looking good.) + ident(DatagramDescriptor) operator(*)ident(ds) operator(=) reserved(new) ident(DatagramDescriptor) operator(()ident(sd)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(ds)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unable to allocate datagram-socket)delimiter(")>operator(\);) + ident(Add) operator(()ident(ds)operator(\);) + ident(output_binding) operator(=) ident(ds)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + operator(}) + + reserved(return) ident(output_binding)operator(;) + + label(fail)operator(:) + reserved(if) operator(()ident(sd) operator(!=) ident(INVALID_SOCKET)operator(\)) + ident(closesocket) operator(()ident(sd)operator(\);) + reserved(return) pre_constant(NULL)operator(;) +operator(}) + + + +comment(/******************* +EventMachine_t::Add +*******************/) + +directive(void) ident(EventMachine_t)operator(::)ident(Add) operator(()ident(EventableDescriptor) operator(*)ident(ed)operator(\)) +operator({) + reserved(if) operator((!)ident(ed)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(added bad descriptor)delimiter(")>operator(\);) + ident(ed)operator(->)ident(SetEventCallback) operator(()ident(EventCallback)operator(\);) + ident(NewDescriptors)operator(.)ident(push_back) operator(()ident(ed)operator(\);) +operator(}) + + +comment(/******************************* +EventMachine_t::ArmKqueueWriter +*******************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(ArmKqueueWriter) operator(()ident(EventableDescriptor) operator(*)ident(ed)operator(\)) +operator({) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + reserved(if) operator(()ident(bKqueue)operator(\)) operator({) + reserved(if) operator((!)ident(ed)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(added bad descriptor)delimiter(")>operator(\);) + reserved(struct) ident(kevent) ident(k)operator(;) + ident(EV_SET) operator((&)ident(k)operator(,) ident(ed)operator(->)ident(GetSocket)operator((\),) ident(EVFILT_WRITE)operator(,) ident(EV_ADD) operator(|) ident(EV_ONESHOT)operator(,) integer(0)operator(,) integer(0)operator(,) ident(ed)operator(\);) + pre_type(int) ident(t) operator(=) ident(kevent) operator(()ident(kqfd)operator(,) operator(&)ident(k)operator(,) integer(1)operator(,) pre_constant(NULL)operator(,) integer(0)operator(,) pre_constant(NULL)operator(\);) + ident(assert) operator(()ident(t) operator(==) integer(0)operator(\);) + operator(}) + preprocessor(#endif) +operator(}) + +comment(/******************************* +EventMachine_t::ArmKqueueReader +*******************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(ArmKqueueReader) operator(()ident(EventableDescriptor) operator(*)ident(ed)operator(\)) +operator({) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + reserved(if) operator(()ident(bKqueue)operator(\)) operator({) + reserved(if) operator((!)ident(ed)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(added bad descriptor)delimiter(")>operator(\);) + reserved(struct) ident(kevent) ident(k)operator(;) + ident(EV_SET) operator((&)ident(k)operator(,) ident(ed)operator(->)ident(GetSocket)operator((\),) ident(EVFILT_READ)operator(,) ident(EV_ADD)operator(,) integer(0)operator(,) integer(0)operator(,) ident(ed)operator(\);) + pre_type(int) ident(t) operator(=) ident(kevent) operator(()ident(kqfd)operator(,) operator(&)ident(k)operator(,) integer(1)operator(,) pre_constant(NULL)operator(,) integer(0)operator(,) pre_constant(NULL)operator(\);) + ident(assert) operator(()ident(t) operator(==) integer(0)operator(\);) + operator(}) + preprocessor(#endif) +operator(}) + +comment(/********************************** +EventMachine_t::_AddNewDescriptors +**********************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(_AddNewDescriptors)operator((\)) +operator({) + comment(/* Avoid adding descriptors to the main descriptor list + * while we're actually traversing the list. + * Any descriptors that are added as a result of processing timers + * or acceptors should go on a temporary queue and then added + * while we're not traversing the main list. + * Also, it (rarely\) happens that a newly-created descriptor + * is immediately scheduled to close. It might be a good + * idea not to bother scheduling these for I/O but if + * we do that, we might bypass some important processing. + */) + + reserved(for) operator(()ident(size_t) ident(i) operator(=) integer(0)operator(;) ident(i) operator(<) ident(NewDescriptors)operator(.)ident(size)operator((\);) ident(i)operator(++\)) operator({) + ident(EventableDescriptor) operator(*)ident(ed) operator(=) ident(NewDescriptors)operator([)ident(i)operator(];) + reserved(if) operator(()ident(ed) operator(==) pre_constant(NULL)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(adding bad descriptor)delimiter(")>operator(\);) + + preprocessor(#if) ident(HAVE_EPOLL) + reserved(if) operator(()ident(bEpoll)operator(\)) operator({) + ident(assert) operator(()ident(epfd) operator(!=) operator(-)integer(1)operator(\);) + pre_type(int) ident(e) operator(=) ident(epoll_ctl) operator(()ident(epfd)operator(,) ident(EPOLL_CTL_ADD)operator(,) ident(ed)operator(->)ident(GetSocket)operator((\),) ident(ed)operator(->)ident(GetEpollEvent)operator((\)\);) + reserved(if) operator(()ident(e)operator(\)) operator({) + pre_type(char) ident(buf) operator([)integer(200)operator(];) + ident(snprintf) operator(()ident(buf)operator(,) reserved(sizeof)operator(()ident(buf)operator(\)-)integer(1)operator(,) string<delimiter(")content(unable to add new descriptor: %s)delimiter(")>operator(,) ident(strerror)operator(()ident(errno)operator(\)\);) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()ident(buf)operator(\);) + operator(}) + operator(}) + preprocessor(#endif) + + preprocessor(#if) ident(HAVE_KQUEUE) + comment(/* + if (bKqueue\) { + // INCOMPLETE. Some descriptors don't want to be readable. + assert (kqfd != -1\); + struct kevent k; + EV_SET (&k, ed->GetSocket(\), EVFILT_READ, EV_ADD, 0, 0, ed\); + int t = kevent (kqfd, &k, 1, NULL, 0, NULL\); + assert (t == 0\); + } + */) + preprocessor(#endif) + + ident(Descriptors)operator(.)ident(push_back) operator(()ident(ed)operator(\);) + operator(}) + ident(NewDescriptors)operator(.)ident(clear)operator((\);) +operator(}) + + +comment(/********************************** +EventMachine_t::_ModifyDescriptors +**********************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(_ModifyDescriptors)operator((\)) +operator({) + comment(/* For implementations which don't level check every descriptor on + * every pass through the machine, as select does. + * If we're not selecting, then descriptors need a way to signal to the + * machine that their readable or writable status has changed. + * That's what the ::Modify call is for. We do it this way to avoid + * modifying descriptors during the loop traversal, where it can easily + * happen that an object (like a UDP socket\) gets data written on it by + * the application during #post_init. That would take place BEFORE the + * descriptor even gets added to the epoll descriptor, so the modify + * operation will crash messily. + * Another really messy possibility is for a descriptor to put itself + * on the Modified list, and then get deleted before we get here. + * Remember, deletes happen after the I/O traversal and before the + * next pass through here. So we have to make sure when we delete a + * descriptor to remove it from the Modified list. + */) + + preprocessor(#ifdef) ident(HAVE_EPOLL) + reserved(if) operator(()ident(bEpoll)operator(\)) operator({) + ident(set)operator(<)ident(EventableDescriptor)operator(*>::)ident(iterator) ident(i) operator(=) ident(ModifiedDescriptors)operator(.)ident(begin)operator((\);) + reserved(while) operator(()ident(i) operator(!=) ident(ModifiedDescriptors)operator(.)ident(end)operator((\)\)) operator({) + ident(assert) operator((*)ident(i)operator(\);) + ident(_ModifyEpollEvent) operator((*)ident(i)operator(\);) + operator(++)ident(i)operator(;) + operator(}) + operator(}) + preprocessor(#endif) + + ident(ModifiedDescriptors)operator(.)ident(clear)operator((\);) +operator(}) + + +comment(/********************** +EventMachine_t::Modify +**********************/) + +directive(void) ident(EventMachine_t)operator(::)ident(Modify) operator(()ident(EventableDescriptor) operator(*)ident(ed)operator(\)) +operator({) + reserved(if) operator((!)ident(ed)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(modified bad descriptor)delimiter(")>operator(\);) + ident(ModifiedDescriptors)operator(.)ident(insert) operator(()ident(ed)operator(\);) +operator(}) + + +comment(/*********************************** +EventMachine_t::_OpenFileForWriting +***********************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(_OpenFileForWriting) operator(()directive(const) pre_type(char) operator(*)ident(filename)operator(\)) +operator({) + comment(/* + * Return the binding-text of the newly-opened file, + * or NULL if there was a problem. + */) + + reserved(if) operator((!)ident(filename) operator(||) operator(!*)ident(filename)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + + pre_type(int) ident(fd) operator(=) ident(open) operator(()ident(filename)operator(,) ident(O_CREAT)operator(|)ident(O_TRUNC)operator(|)ident(O_WRONLY)operator(|)ident(O_NONBLOCK)operator(,) oct(0644)operator(\);) + + ident(FileStreamDescriptor) operator(*)ident(fsd) operator(=) reserved(new) ident(FileStreamDescriptor) operator(()ident(fd)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(fsd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no file-stream allocated)delimiter(")>operator(\);) + ident(Add) operator(()ident(fsd)operator(\);) + reserved(return) ident(fsd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + +operator(}) + + +comment(/************************************** +EventMachine_t::CreateUnixDomainServer +**************************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(CreateUnixDomainServer) operator(()directive(const) pre_type(char) operator(*)ident(filename)operator(\)) +operator({) + comment(/* Create a UNIX-domain acceptor (server\) socket and add it to the event machine. + * Return the binding of the new acceptor to the caller. + * This binding will be referenced when the new acceptor sends events + * to indicate accepted connections. + * THERE IS NO MEANINGFUL IMPLEMENTATION ON WINDOWS. + */) + + preprocessor(#ifdef) ident(OS_WIN32) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unix-domain server unavailable on this platform)delimiter(")>operator(\);) + preprocessor(#endif) + + comment(// The whole rest of this function is only compiled on Unix systems.) + preprocessor(#ifdef) ident(OS_UNIX) + directive(const) pre_type(char) operator(*)ident(output_binding) operator(=) pre_constant(NULL)operator(;) + + reserved(struct) ident(sockaddr_un) ident(s_sun)operator(;) + + pre_type(int) ident(sd_accept) operator(=) ident(socket) operator(()ident(AF_LOCAL)operator(,) ident(SOCK_STREAM)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(sd_accept) operator(==) ident(INVALID_SOCKET)operator(\)) operator({) + reserved(goto) ident(fail)operator(;) + operator(}) + + reserved(if) operator((!)ident(filename) operator(||) operator(!*)ident(filename)operator(\)) + reserved(goto) ident(fail)operator(;) + ident(unlink) operator(()ident(filename)operator(\);) + + ident(bzero) operator((&)ident(s_sun)operator(,) reserved(sizeof)operator(()ident(s_sun)operator(\)\);) + ident(s_sun)operator(.)ident(sun_family) operator(=) ident(AF_LOCAL)operator(;) + ident(strncpy) operator(()ident(s_sun)operator(.)ident(sun_path)operator(,) ident(filename)operator(,) reserved(sizeof)operator(()ident(s_sun)operator(.)ident(sun_path)operator(\)-)integer(1)operator(\);) + + comment(// don't bother with reuseaddr for a local socket.) + + operator({) comment(// set CLOEXEC. Only makes sense on Unix) + preprocessor(#ifdef) ident(OS_UNIX) + pre_type(int) ident(cloexec) operator(=) ident(fcntl) operator(()ident(sd_accept)operator(,) ident(F_GETFD)operator(,) integer(0)operator(\);) + ident(assert) operator(()ident(cloexec) operator(>=) integer(0)operator(\);) + ident(cloexec) operator(|=) ident(FD_CLOEXEC)operator(;) + ident(fcntl) operator(()ident(sd_accept)operator(,) ident(F_SETFD)operator(,) ident(cloexec)operator(\);) + preprocessor(#endif) + operator(}) + + reserved(if) operator(()ident(bind) operator(()ident(sd_accept)operator(,) operator(()reserved(struct) ident(sockaddr)operator(*\)&)ident(s_sun)operator(,) reserved(sizeof)operator(()ident(s_sun)operator(\)\)\)) operator({) + comment(//__warning ("binding failed"\);) + reserved(goto) ident(fail)operator(;) + operator(}) + + reserved(if) operator(()ident(listen) operator(()ident(sd_accept)operator(,) integer(100)operator(\)\)) operator({) + comment(//__warning ("listen failed"\);) + reserved(goto) ident(fail)operator(;) + operator(}) + + operator({) + comment(// Set the acceptor non-blocking.) + comment(// THIS IS CRUCIALLY IMPORTANT because we read it in a select loop.) + reserved(if) operator((!)ident(SetSocketNonblocking) operator(()ident(sd_accept)operator(\)\)) operator({) + comment(//int val = fcntl (sd_accept, F_GETFL, 0\);) + comment(//if (fcntl (sd_accept, F_SETFL, val | O_NONBLOCK\) == -1\) {) + reserved(goto) ident(fail)operator(;) + operator(}) + operator(}) + + operator({) comment(// Looking good.) + ident(AcceptorDescriptor) operator(*)ident(ad) operator(=) reserved(new) ident(AcceptorDescriptor) operator(()ident(sd_accept)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(ad)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unable to allocate acceptor)delimiter(")>operator(\);) + ident(Add) operator(()ident(ad)operator(\);) + ident(output_binding) operator(=) ident(ad)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + operator(}) + + reserved(return) ident(output_binding)operator(;) + + label(fail)operator(:) + reserved(if) operator(()ident(sd_accept) operator(!=) ident(INVALID_SOCKET)operator(\)) + ident(closesocket) operator(()ident(sd_accept)operator(\);) + reserved(return) pre_constant(NULL)operator(;) + preprocessor(#endif) comment(// OS_UNIX) +operator(}) + + +comment(/********************* +EventMachine_t::Popen +*********************/) +preprocessor(#if) ident(OBSOLETE) +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(Popen) operator(()directive(const) pre_type(char) operator(*)ident(cmd)operator(,) directive(const) pre_type(char) operator(*)ident(mode)operator(\)) +operator({) + preprocessor(#ifdef) ident(OS_WIN32) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(popen is currently unavailable on this platform)delimiter(")>operator(\);) + preprocessor(#endif) + + comment(// The whole rest of this function is only compiled on Unix systems.) + comment(// Eventually we need this functionality (or a full-duplex equivalent\) on Windows.) + preprocessor(#ifdef) ident(OS_UNIX) + directive(const) pre_type(char) operator(*)ident(output_binding) operator(=) pre_constant(NULL)operator(;) + + ident(FILE) operator(*)ident(fp) operator(=) ident(popen) operator(()ident(cmd)operator(,) ident(mode)operator(\);) + reserved(if) operator((!)ident(fp)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + + comment(// From here, all early returns must pclose the stream.) + + comment(// According to the pipe(2\) manpage, descriptors returned from pipe have both) + comment(// CLOEXEC and NONBLOCK clear. Do NOT set CLOEXEC. DO set nonblocking.) + reserved(if) operator((!)ident(SetSocketNonblocking) operator(()ident(fileno) operator(()ident(fp)operator(\)\)\)) operator({) + ident(pclose) operator(()ident(fp)operator(\);) + reserved(return) pre_constant(NULL)operator(;) + operator(}) + + operator({) comment(// Looking good.) + ident(PipeDescriptor) operator(*)ident(pd) operator(=) reserved(new) ident(PipeDescriptor) operator(()ident(fp)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(pd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unable to allocate pipe)delimiter(")>operator(\);) + ident(Add) operator(()ident(pd)operator(\);) + ident(output_binding) operator(=) ident(pd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + operator(}) + + reserved(return) ident(output_binding)operator(;) + preprocessor(#endif) +operator(}) +preprocessor(#endif) comment(// OBSOLETE) + +comment(/************************** +EventMachine_t::Socketpair +**************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(Socketpair) operator(()pre_type(char) operator(*) directive(const)operator(*)ident(cmd_strings)operator(\)) +operator({) + preprocessor(#ifdef) ident(OS_WIN32) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(socketpair is currently unavailable on this platform)delimiter(")>operator(\);) + preprocessor(#endif) + + comment(// The whole rest of this function is only compiled on Unix systems.) + comment(// Eventually we need this functionality (or a full-duplex equivalent\) on Windows.) + preprocessor(#ifdef) ident(OS_UNIX) + comment(// Make sure the incoming array of command strings is sane.) + reserved(if) operator((!)ident(cmd_strings)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + pre_type(int) ident(j)operator(;) + reserved(for) operator(()ident(j)operator(=)integer(0)operator(;) ident(j) operator(<) integer(100) operator(&&) ident(cmd_strings)operator([)ident(j)operator(];) ident(j)operator(++\)) + operator(;) + reserved(if) operator((()ident(j)operator(==)integer(0)operator(\)) operator(||) operator(()ident(j)operator(==)integer(100)operator(\)\)) + reserved(return) pre_constant(NULL)operator(;) + + directive(const) pre_type(char) operator(*)ident(output_binding) operator(=) pre_constant(NULL)operator(;) + + pre_type(int) ident(sv)operator([)integer(2)operator(];) + reserved(if) operator(()ident(socketpair) operator(()ident(AF_LOCAL)operator(,) ident(SOCK_STREAM)operator(,) integer(0)operator(,) ident(sv)operator(\)) operator(<) integer(0)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + comment(// from here, all early returns must close the pair of sockets.) + + comment(// Set the parent side of the socketpair nonblocking.) + comment(// We don't care about the child side, and most child processes will expect their) + comment(// stdout to be blocking. Thanks to Duane Johnson and Bill Kelly for pointing this out.) + comment(// Obviously DON'T set CLOEXEC.) + reserved(if) operator((!)ident(SetSocketNonblocking) operator(()ident(sv)operator([)integer(0)operator(]\)\)) operator({) + ident(close) operator(()ident(sv)operator([)integer(0)operator(]\);) + ident(close) operator(()ident(sv)operator([)integer(1)operator(]\);) + reserved(return) pre_constant(NULL)operator(;) + operator(}) + + ident(pid_t) ident(f) operator(=) ident(fork)operator((\);) + reserved(if) operator(()ident(f) operator(>) integer(0)operator(\)) operator({) + ident(close) operator(()ident(sv)operator([)integer(1)operator(]\);) + ident(PipeDescriptor) operator(*)ident(pd) operator(=) reserved(new) ident(PipeDescriptor) operator(()ident(sv)operator([)integer(0)operator(],) ident(f)operator(,) local_variable(this)operator(\);) + reserved(if) operator((!)ident(pd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unable to allocate pipe)delimiter(")>operator(\);) + ident(Add) operator(()ident(pd)operator(\);) + ident(output_binding) operator(=) ident(pd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + operator(}) + reserved(else) reserved(if) operator(()ident(f) operator(==) integer(0)operator(\)) operator({) + ident(close) operator(()ident(sv)operator([)integer(0)operator(]\);) + ident(dup2) operator(()ident(sv)operator([)integer(1)operator(],) ident(STDIN_FILENO)operator(\);) + ident(close) operator(()ident(sv)operator([)integer(1)operator(]\);) + ident(dup2) operator(()ident(STDIN_FILENO)operator(,) ident(STDOUT_FILENO)operator(\);) + ident(execvp) operator(()ident(cmd_strings)operator([)integer(0)operator(],) ident(cmd_strings)operator(+)integer(1)operator(\);) + ident(exit) operator((-)integer(1)operator(\);) comment(// end the child process if the exec doesn't work.) + operator(}) + reserved(else) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no fork)delimiter(")>operator(\);) + + reserved(return) ident(output_binding)operator(;) + preprocessor(#endif) +operator(}) + + +comment(/**************************** +EventMachine_t::OpenKeyboard +****************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(OpenKeyboard)operator((\)) +operator({) + ident(KeyboardDescriptor) operator(*)ident(kd) operator(=) reserved(new) ident(KeyboardDescriptor) operator(()local_variable(this)operator(\);) + reserved(if) operator((!)ident(kd)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no keyboard-object allocated)delimiter(")>operator(\);) + ident(Add) operator(()ident(kd)operator(\);) + reserved(return) ident(kd)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) +operator(}) + + + + + +comment(//#endif // OS_UNIX) + +comment(/***************************************************************************** + +$Id$ + +File: emwin.cpp +Date: 05May06 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + + +comment(// THIS ENTIRE FILE IS FOR WINDOWS BUILDS ONLY) +comment(// INCOMPLETE AND DISABLED FOR NOW.) +preprocessor(#ifdef) ident(xOS_WIN32) + +preprocessor(#include) include("project.h") + + +comment(// Keep a global variable floating around) +comment(// with the current loop time as set by the Event Machine.) +comment(// This avoids the need for frequent expensive calls to time(NULL\);) +ident(time_t) ident(gCurrentLoopTime)operator(;) + + +comment(/****************************** +EventMachine_t::EventMachine_t +******************************/) + +ident(EventMachine_t)operator(::)ident(EventMachine_t) operator(()directive(void) operator((*)ident(event_callback)operator(\)()directive(const) pre_type(char)operator(*,) pre_type(int)operator(,) directive(const) pre_type(char)operator(*,) pre_type(int)operator(\)\):) + ident(EventCallback) operator(()ident(event_callback)operator(\),) + ident(NextHeartbeatTime) operator(()integer(0)operator(\)) +operator({) + ident(gTerminateSignalReceived) operator(=) pre_constant(false)operator(;) + ident(Iocp) operator(=) pre_constant(NULL)operator(;) +operator(}) + + +comment(/******************************* +EventMachine_t::~EventMachine_t +*******************************/) + +ident(EventMachine_t)operator(::~)ident(EventMachine_t)operator((\)) +operator({) + ident(cerr) operator(<<) string<delimiter(")content(EM __dt)char(\\n)delimiter(")>operator(;) + reserved(if) operator(()ident(Iocp)operator(\)) + ident(CloseHandle) operator(()ident(Iocp)operator(\);) +operator(}) + + +comment(/**************************** +EventMachine_t::ScheduleHalt +****************************/) + +directive(void) ident(EventMachine_t)operator(::)ident(ScheduleHalt)operator((\)) +operator({) + comment(/* This is how we stop the machine. + * This can be called by clients. Signal handlers will probably + * set the global flag. + * For now this means there can only be one EventMachine ever running at a time. + */) + ident(gTerminateSignalReceived) operator(=) pre_constant(true)operator(;) +operator(}) + + + +comment(/******************* +EventMachine_t::Run +*******************/) + +directive(void) ident(EventMachine_t)operator(::)ident(Run)operator((\)) +operator({) + ident(HookControlC) operator(()pre_constant(true)operator(\);) + + ident(Iocp) operator(=) ident(CreateIoCompletionPort) operator(()ident(INVALID_HANDLE_VALUE)operator(,) pre_constant(NULL)operator(,) integer(0)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(Iocp) operator(==) pre_constant(NULL)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no completion port)delimiter(")>operator(\);) + + + ident(DWORD) ident(nBytes)operator(,) ident(nCompletionKey)operator(;) + ident(LPOVERLAPPED) ident(Overlapped)operator(;) + + reserved(do) operator({) + ident(gCurrentLoopTime) operator(=) ident(time)operator(()pre_constant(NULL)operator(\);) + comment(// Have some kind of strategy that will dequeue maybe up to 10 completions ) + comment(// without running the timers as long as they are available immediately.) + comment(// Otherwise in a busy server we're calling them every time through the loop.) + reserved(if) operator((!)ident(_RunTimers)operator((\)\)) + reserved(break)operator(;) + reserved(if) operator(()ident(GetQueuedCompletionStatus) operator(()ident(Iocp)operator(,) operator(&)ident(nBytes)operator(,) operator(&)ident(nCompletionKey)operator(,) operator(&)ident(Overlapped)operator(,) integer(1000)operator(\)\)) operator({) + operator(}) + ident(cerr) operator(<<) string<delimiter(")content(+)delimiter(")>operator(;) + operator(}) reserved(while) operator((!)ident(gTerminateSignalReceived)operator(\);) + + + comment(/* + while (true\) { + gCurrentLoopTime = time(NULL\); + if (!_RunTimers(\)\) + break; + _AddNewDescriptors(\); + if (!_RunOnce(\)\) + break; + if (gTerminateSignalReceived\) + break; + } + */) + + ident(HookControlC) operator(()pre_constant(false)operator(\);) +operator(}) + + +comment(/************************** +EventMachine_t::_RunTimers +**************************/) + +pre_type(bool) ident(EventMachine_t)operator(::)ident(_RunTimers)operator((\)) +operator({) + comment(// These are caller-defined timer handlers.) + comment(// Return T/F to indicate whether we should continue the main loop.) + comment(// We rely on the fact that multimaps sort by their keys to avoid) + comment(// inspecting the whole list every time we come here.) + comment(// Just keep inspecting and processing the list head until we hit) + comment(// one that hasn't expired yet.) + + reserved(while) operator(()pre_constant(true)operator(\)) operator({) + ident(multimap)operator(<)ident(time_t)operator(,)ident(Timer_t)operator(>::)ident(iterator) ident(i) operator(=) ident(Timers)operator(.)ident(begin)operator((\);) + reserved(if) operator(()ident(i) operator(==) ident(Timers)operator(.)ident(end)operator((\)\)) + reserved(break)operator(;) + reserved(if) operator(()ident(i)operator(->)ident(first) operator(>) ident(gCurrentLoopTime)operator(\)) + reserved(break)operator(;) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)) operator(()string<delimiter(")delimiter(")>operator(,) ident(EM_TIMER_FIRED)operator(,) ident(i)operator(->)ident(second)operator(.)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(i)operator(->)ident(second)operator(.)ident(GetBinding)operator((\))operator(.)ident(length)operator((\)\);) + ident(Timers)operator(.)ident(erase) operator(()ident(i)operator(\);) + operator(}) + reserved(return) pre_constant(true)operator(;) +operator(}) + + +comment(/*********************************** +EventMachine_t::InstallOneshotTimer +***********************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(InstallOneshotTimer) operator(()pre_type(int) ident(seconds)operator(\)) +operator({) + reserved(if) operator(()ident(Timers)operator(.)ident(size)operator((\)) operator(>) ident(MaxOutstandingTimers)operator(\)) + reserved(return) pre_constant(false)operator(;) + comment(// Don't use the global loop-time variable here, because we might) + comment(// get called before the main event machine is running.) + + ident(Timer_t) ident(t)operator(;) + ident(Timers)operator(.)ident(insert) operator(()ident(make_pair) operator(()ident(time)operator(()pre_constant(NULL)operator(\)) operator(+) ident(seconds)operator(,) ident(t)operator(\)\);) + reserved(return) ident(t)operator(.)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) +operator(}) + + +comment(/********************************** +EventMachine_t::OpenDatagramSocket +**********************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(OpenDatagramSocket) operator(()directive(const) pre_type(char) operator(*)ident(address)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + ident(cerr) operator(<<) string<delimiter(")content(OPEN DATAGRAM SOCKET)char(\\n)delimiter(")>operator(;) + reserved(return) string<delimiter(")content(Unimplemented)delimiter(")>operator(;) +operator(}) + + +comment(/******************************* +EventMachine_t::CreateTcpServer +*******************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(CreateTcpServer) operator(()directive(const) pre_type(char) operator(*)ident(server)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + comment(/* Create a TCP-acceptor (server\) socket and add it to the event machine. + * Return the binding of the new acceptor to the caller. + * This binding will be referenced when the new acceptor sends events + * to indicate accepted connections. + */) + + directive(const) pre_type(char) operator(*)ident(output_binding) operator(=) pre_constant(NULL)operator(;) + + reserved(struct) ident(sockaddr_in) ident(sin)operator(;) + + ident(SOCKET) ident(sd_accept) operator(=) ident(socket) operator(()ident(AF_INET)operator(,) ident(SOCK_STREAM)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(sd_accept) operator(==) ident(INVALID_SOCKET)operator(\)) operator({) + reserved(goto) ident(fail)operator(;) + operator(}) + + ident(memset) operator((&)ident(sin)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(sin)operator(\)\);) + ident(sin)operator(.)ident(sin_family) operator(=) ident(AF_INET)operator(;) + ident(sin)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) ident(INADDR_ANY)operator(;) + ident(sin)operator(.)ident(sin_port) operator(=) ident(htons) operator(()ident(port)operator(\);) + + reserved(if) operator(()ident(server) operator(&&) operator(*)ident(server)operator(\)) operator({) + ident(sin)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) ident(inet_addr) operator(()ident(server)operator(\);) + reserved(if) operator(()ident(sin)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(==) ident(INADDR_NONE)operator(\)) operator({) + ident(hostent) operator(*)ident(hp) operator(=) ident(gethostbyname) operator(()ident(server)operator(\);) + reserved(if) operator(()ident(hp) operator(==) pre_constant(NULL)operator(\)) operator({) + comment(//__warning ("hostname not resolved: ", server\);) + reserved(goto) ident(fail)operator(;) + operator(}) + ident(sin)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) operator((()ident(in_addr)operator(*\)()ident(hp)operator(->)ident(h_addr)operator(\)\)->)ident(s_addr)operator(;) + operator(}) + operator(}) + + + comment(// No need to set reuseaddr on Windows.) + + + reserved(if) operator(()ident(bind) operator(()ident(sd_accept)operator(,) operator(()reserved(struct) ident(sockaddr)operator(*\)&)ident(sin)operator(,) reserved(sizeof)operator(()ident(sin)operator(\)\)\)) operator({) + comment(//__warning ("binding failed"\);) + reserved(goto) ident(fail)operator(;) + operator(}) + + reserved(if) operator(()ident(listen) operator(()ident(sd_accept)operator(,) integer(100)operator(\)\)) operator({) + comment(//__warning ("listen failed"\);) + reserved(goto) ident(fail)operator(;) + operator(}) + + operator({) comment(// Looking good.) + ident(AcceptorDescriptor) operator(*)ident(ad) operator(=) reserved(new) ident(AcceptorDescriptor) operator(()local_variable(this)operator(,) ident(sd_accept)operator(\);) + reserved(if) operator((!)ident(ad)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unable to allocate acceptor)delimiter(")>operator(\);) + ident(Add) operator(()ident(ad)operator(\);) + ident(output_binding) operator(=) ident(ad)operator(->)ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\);) + + ident(CreateIoCompletionPort) operator((()ident(HANDLE)operator(\))ident(sd_accept)operator(,) ident(Iocp)operator(,) pre_constant(NULL)operator(,) integer(0)operator(\);) + ident(SOCKET) ident(sd) operator(=) ident(socket) operator(()ident(AF_INET)operator(,) ident(SOCK_STREAM)operator(,) integer(0)operator(\);) + ident(CreateIoCompletionPort) operator((()ident(HANDLE)operator(\))ident(sd)operator(,) ident(Iocp)operator(,) pre_constant(NULL)operator(,) integer(0)operator(\);) + ident(AcceptEx) operator(()ident(sd_accept)operator(,) ident(sd)operator(,) + operator(}) + + reserved(return) ident(output_binding)operator(;) + + label(fail)operator(:) + reserved(if) operator(()ident(sd_accept) operator(!=) ident(INVALID_SOCKET)operator(\)) + ident(closesocket) operator(()ident(sd_accept)operator(\);) + reserved(return) pre_constant(NULL)operator(;) +operator(}) + + +comment(/******************************* +EventMachine_t::ConnectToServer +*******************************/) + +directive(const) pre_type(char) operator(*)ident(EventMachine_t)operator(::)ident(ConnectToServer) operator(()directive(const) pre_type(char) operator(*)ident(server)operator(,) pre_type(int) ident(port)operator(\)) +operator({) + reserved(if) operator((!)ident(server) operator(||) operator(!*)ident(server) operator(||) operator(!)ident(port)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + + ident(sockaddr_in) ident(pin)operator(;) + pre_type(unsigned) pre_type(long) ident(HostAddr)operator(;) + + ident(HostAddr) operator(=) ident(inet_addr) operator(()ident(server)operator(\);) + reserved(if) operator(()ident(HostAddr) operator(==) ident(INADDR_NONE)operator(\)) operator({) + ident(hostent) operator(*)ident(hp) operator(=) ident(gethostbyname) operator(()ident(server)operator(\);) + reserved(if) operator((!)ident(hp)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + ident(HostAddr) operator(=) operator((()ident(in_addr)operator(*\)()ident(hp)operator(->)ident(h_addr)operator(\)\)->)ident(s_addr)operator(;) + operator(}) + + ident(memset) operator((&)ident(pin)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(pin)operator(\)\);) + ident(pin)operator(.)ident(sin_family) operator(=) ident(AF_INET)operator(;) + ident(pin)operator(.)ident(sin_addr)operator(.)ident(s_addr) operator(=) ident(HostAddr)operator(;) + ident(pin)operator(.)ident(sin_port) operator(=) ident(htons) operator(()ident(port)operator(\);) + + pre_type(int) ident(sd) operator(=) ident(socket) operator(()ident(AF_INET)operator(,) ident(SOCK_STREAM)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(sd) operator(==) ident(INVALID_SOCKET)operator(\)) + reserved(return) pre_constant(NULL)operator(;) + + + ident(LPOVERLAPPED) ident(olap) operator(=) operator(()ident(LPOVERLAPPED)operator(\)) ident(calloc) operator(()integer(1)operator(,) reserved(sizeof) operator(()ident(OVERLAPPED)operator(\)\);) + ident(cerr) operator(<<) string<delimiter(")content(I'm dying now)char(\\n)delimiter(")>operator(;) + reserved(throw) ident(runtime_error) operator(()string<delimiter(")content(UNIMPLEMENTED!!!)char(\\n)delimiter(")>operator(\);) + +operator(}) + + + +comment(/******************* +EventMachine_t::Add +*******************/) + +directive(void) ident(EventMachine_t)operator(::)ident(Add) operator(()ident(EventableDescriptor) operator(*)ident(ed)operator(\)) +operator({) + ident(cerr) operator(<<) string<delimiter(")content(ADD)char(\\n)delimiter(")>operator(;) +operator(}) + + + +preprocessor(#endif) comment(// OS_WIN32) + +comment(/***************************************************************************** + +$Id$ + +File: epoll.cpp +Date: 06Jun07 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + + +preprocessor(#ifdef) ident(HAVE_EPOLL) + +preprocessor(#include) include("project.h") + +preprocessor(#endif) comment(// HAVE_EPOLL) + +comment(/***************************************************************************** + +$Id: mapper.cpp 4527 2007-07-04 10:21:34Z francis $ + +File: mapper.cpp +Date: 02Jul07 + +Copyright (C\) 2007 by Francis Cianfrocca. All Rights Reserved. +Gmail: garbagecat10 + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + + +comment(//////////////////////////////////////////////////////////////////////) +comment(// UNIX implementation) +comment(//////////////////////////////////////////////////////////////////////) + + +preprocessor(#ifdef) ident(OS_UNIX) + +preprocessor(#include) include(<sys/types.h>) +preprocessor(#include) include(<sys/stat.h>) +preprocessor(#include) include(<sys/mman.h>) +preprocessor(#include) include(<fcntl.h>) +preprocessor(#include) include(<errno.h>) + +preprocessor(#include) include(<iostream>) +preprocessor(#include) include("unistd.h") +preprocessor(#include) include(<string>) +preprocessor(#include) include(<cstring>) +preprocessor(#include) include(<stdexcept>) +directive(using) reserved(namespace) ident(std)operator(;) + +preprocessor(#include) include("mapper.h") + +comment(/****************** +Mapper_t::Mapper_t +******************/) + +ident(Mapper_t)operator(::)ident(Mapper_t) operator(()directive(const) pre_type(string) operator(&)ident(filename)operator(\)) +operator({) + comment(/* We ASSUME we can open the file. + * (More precisely, we assume someone else checked before we got here.\) + */) + + ident(Fd) operator(=) ident(open) operator(()ident(filename)operator(.)ident(c_str)operator((\),) ident(O_RDONLY)operator(\);) + reserved(if) operator(()ident(Fd) operator(<) integer(0)operator(\)) + reserved(throw) ident(runtime_error) operator(()ident(strerror) operator(()ident(errno)operator(\)\);) + + reserved(struct) ident(stat) ident(st)operator(;) + reserved(if) operator(()ident(fstat) operator(()ident(Fd)operator(,) operator(&)ident(st)operator(\)\)) + reserved(throw) ident(runtime_error) operator(()ident(strerror) operator(()ident(errno)operator(\)\);) + ident(FileSize) operator(=) ident(st)operator(.)ident(st_size)operator(;) + + ident(MapPoint) operator(=) operator(()directive(const) pre_type(char)operator(*\)) ident(mmap) operator(()integer(0)operator(,) ident(FileSize)operator(,) ident(PROT_READ)operator(,) ident(MAP_SHARED)operator(,) ident(Fd)operator(,) integer(0)operator(\);) + reserved(if) operator(()ident(MapPoint) operator(==) ident(MAP_FAILED)operator(\)) + reserved(throw) ident(runtime_error) operator(()ident(strerror) operator(()ident(errno)operator(\)\);) +operator(}) + + +comment(/******************* +Mapper_t::~Mapper_t +*******************/) + +ident(Mapper_t)operator(::~)ident(Mapper_t)operator((\)) +operator({) + ident(Close)operator((\);) +operator(}) + + +comment(/*************** +Mapper_t::Close +***************/) + +directive(void) ident(Mapper_t)operator(::)ident(Close)operator((\)) +operator({) + comment(// Can be called multiple times.) + comment(// Calls to GetChunk are invalid after a call to Close.) + reserved(if) operator(()ident(MapPoint)operator(\)) operator({) + ident(munmap) operator((()directive(void)operator(*\))ident(MapPoint)operator(,) ident(FileSize)operator(\);) + ident(MapPoint) operator(=) pre_constant(NULL)operator(;) + operator(}) + reserved(if) operator(()ident(Fd) operator(>=) integer(0)operator(\)) operator({) + ident(close) operator(()ident(Fd)operator(\);) + ident(Fd) operator(=) operator(-)integer(1)operator(;) + operator(}) +operator(}) + +comment(/****************** +Mapper_t::GetChunk +******************/) + +directive(const) pre_type(char) operator(*)ident(Mapper_t)operator(::)ident(GetChunk) operator(()pre_type(unsigned) ident(start)operator(\)) +operator({) + reserved(return) ident(MapPoint) operator(+) ident(start)operator(;) +operator(}) + + + +preprocessor(#endif) comment(// OS_UNIX) + + +comment(//////////////////////////////////////////////////////////////////////) +comment(// WINDOWS implementation) +comment(//////////////////////////////////////////////////////////////////////) + +preprocessor(#ifdef) ident(OS_WIN32) + +preprocessor(#include) include(<windows.h>) + +preprocessor(#include) include(<iostream>) +preprocessor(#include) include(<string>) +preprocessor(#include) include(<stdexcept>) +directive(using) reserved(namespace) ident(std)operator(;) + +preprocessor(#include) include("mapper.h") + +comment(/****************** +Mapper_t::Mapper_t +******************/) + +ident(Mapper_t)operator(::)ident(Mapper_t) operator(()directive(const) pre_type(string) operator(&)ident(filename)operator(\)) +operator({) + comment(/* We ASSUME we can open the file. + * (More precisely, we assume someone else checked before we got here.\) + */) + + ident(hFile) operator(=) ident(INVALID_HANDLE_VALUE)operator(;) + ident(hMapping) operator(=) pre_constant(NULL)operator(;) + ident(MapPoint) operator(=) pre_constant(NULL)operator(;) + ident(FileSize) operator(=) integer(0)operator(;) + + ident(hFile) operator(=) ident(CreateFile) operator(()ident(filename)operator(.)ident(c_str)operator((\),) ident(GENERIC_READ)operator(|)ident(GENERIC_WRITE)operator(,) ident(FILE_SHARE_DELETE)operator(|)ident(FILE_SHARE_READ)operator(|)ident(FILE_SHARE_WRITE)operator(,) pre_constant(NULL)operator(,) ident(OPEN_EXISTING)operator(,) ident(FILE_ATTRIBUTE_NORMAL)operator(,) pre_constant(NULL)operator(\);) + + reserved(if) operator(()ident(hFile) operator(==) ident(INVALID_HANDLE_VALUE)operator(\)) + reserved(throw) ident(runtime_error) operator(()string<delimiter(")content(File not found)delimiter(")>operator(\);) + + ident(BY_HANDLE_FILE_INFORMATION) ident(i)operator(;) + reserved(if) operator(()ident(GetFileInformationByHandle) operator(()ident(hFile)operator(,) operator(&)ident(i)operator(\)\)) + ident(FileSize) operator(=) ident(i)operator(.)ident(nFileSizeLow)operator(;) + + ident(hMapping) operator(=) ident(CreateFileMapping) operator(()ident(hFile)operator(,) pre_constant(NULL)operator(,) ident(PAGE_READWRITE)operator(,) integer(0)operator(,) integer(0)operator(,) pre_constant(NULL)operator(\);) + reserved(if) operator((!)ident(hMapping)operator(\)) + reserved(throw) ident(runtime_error) operator(()string<delimiter(")content(File not mapped)delimiter(")>operator(\);) + + ident(MapPoint) operator(=) operator(()directive(const) pre_type(char)operator(*\)) ident(MapViewOfFile) operator(()ident(hMapping)operator(,) ident(FILE_MAP_WRITE)operator(,) integer(0)operator(,) integer(0)operator(,) integer(0)operator(\);) + reserved(if) operator((!)ident(MapPoint)operator(\)) + reserved(throw) ident(runtime_error) operator(()string<delimiter(")content(Mappoint not read)delimiter(")>operator(\);) +operator(}) + + +comment(/******************* +Mapper_t::~Mapper_t +*******************/) + +ident(Mapper_t)operator(::~)ident(Mapper_t)operator((\)) +operator({) + ident(Close)operator((\);) +operator(}) + +comment(/*************** +Mapper_t::Close +***************/) + +directive(void) ident(Mapper_t)operator(::)ident(Close)operator((\)) +operator({) + comment(// Can be called multiple times.) + comment(// Calls to GetChunk are invalid after a call to Close.) + reserved(if) operator(()ident(MapPoint)operator(\)) operator({) + ident(UnmapViewOfFile) operator(()ident(MapPoint)operator(\);) + ident(MapPoint) operator(=) pre_constant(NULL)operator(;) + operator(}) + reserved(if) operator(()ident(hMapping) operator(!=) pre_constant(NULL)operator(\)) operator({) + ident(CloseHandle) operator(()ident(hMapping)operator(\);) + ident(hMapping) operator(=) pre_constant(NULL)operator(;) + operator(}) + reserved(if) operator(()ident(hFile) operator(!=) ident(INVALID_HANDLE_VALUE)operator(\)) operator({) + ident(CloseHandle) operator(()ident(hFile)operator(\);) + ident(hMapping) operator(=) ident(INVALID_HANDLE_VALUE)operator(;) + operator(}) +operator(}) + + +comment(/****************** +Mapper_t::GetChunk +******************/) + +directive(const) pre_type(char) operator(*)ident(Mapper_t)operator(::)ident(GetChunk) operator(()pre_type(unsigned) ident(start)operator(\)) +operator({) + reserved(return) ident(MapPoint) operator(+) ident(start)operator(;) +operator(}) + + + +preprocessor(#endif) comment(// OS_WINDOWS) +comment(/***************************************************************************** + +$Id: rubymain.cpp 4529 2007-07-04 11:32:22Z francis $ + +File: rubymain.cpp +Date: 02Jul07 + +Copyright (C\) 2007 by Francis Cianfrocca. All Rights Reserved. +Gmail: garbagecat10 + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + + + +preprocessor(#include) include(<iostream>) +preprocessor(#include) include(<stdexcept>) +directive(using) reserved(namespace) ident(std)operator(;) + +preprocessor(#include) include(<ruby.h>) +preprocessor(#include) include("mapper.h") + +directive(static) ident(VALUE) ident(EmModule)operator(;) +directive(static) ident(VALUE) ident(FastFileReader)operator(;) +directive(static) ident(VALUE) ident(Mapper)operator(;) + + + +comment(/********* +mapper_dt +*********/) + +directive(static) directive(void) ident(mapper_dt) operator(()directive(void) operator(*)ident(ptr)operator(\)) +operator({) + reserved(if) operator(()ident(ptr)operator(\)) + reserved(delete) operator(()ident(Mapper_t)operator(*\)) ident(ptr)operator(;) +operator(}) + +comment(/********** +mapper_new +**********/) + +directive(static) ident(VALUE) ident(mapper_new) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(filename)operator(\)) +operator({) + ident(Mapper_t) operator(*)ident(m) operator(=) reserved(new) ident(Mapper_t) operator(()ident(StringValuePtr) operator(()ident(filename)operator(\)\);) + reserved(if) operator((!)ident(m)operator(\)) + ident(rb_raise) operator(()ident(rb_eException)operator(,) string<delimiter(")content(No Mapper Object)delimiter(")>operator(\);) + ident(VALUE) ident(v) operator(=) ident(Data_Wrap_Struct) operator(()ident(Mapper)operator(,) integer(0)operator(,) ident(mapper_dt)operator(,) operator(()directive(void)operator(*\))ident(m)operator(\);) + reserved(return) ident(v)operator(;) +operator(}) + + +comment(/**************** +mapper_get_chunk +****************/) + +directive(static) ident(VALUE) ident(mapper_get_chunk) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(start)operator(,) ident(VALUE) ident(length)operator(\)) +operator({) + ident(Mapper_t) operator(*)ident(m) operator(=) pre_constant(NULL)operator(;) + ident(Data_Get_Struct) operator(()ident(self)operator(,) ident(Mapper_t)operator(,) ident(m)operator(\);) + reserved(if) operator((!)ident(m)operator(\)) + ident(rb_raise) operator(()ident(rb_eException)operator(,) string<delimiter(")content(No Mapper Object)delimiter(")>operator(\);) + + comment(// TODO, what if some moron sends us a negative start value?) + pre_type(unsigned) ident(_start) operator(=) ident(NUM2INT) operator(()ident(start)operator(\);) + pre_type(unsigned) ident(_length) operator(=) ident(NUM2INT) operator(()ident(length)operator(\);) + reserved(if) operator((()ident(_start) operator(+) ident(_length)operator(\)) operator(>) ident(m)operator(->)ident(GetFileSize)operator((\)\)) + ident(rb_raise) operator(()ident(rb_eException)operator(,) string<delimiter(")content(Mapper Range Error)delimiter(")>operator(\);) + + directive(const) pre_type(char) operator(*)ident(chunk) operator(=) ident(m)operator(->)ident(GetChunk) operator(()ident(_start)operator(\);) + reserved(if) operator((!)ident(chunk)operator(\)) + ident(rb_raise) operator(()ident(rb_eException)operator(,) string<delimiter(")content(No Mapper Chunk)delimiter(")>operator(\);) + reserved(return) ident(rb_str_new) operator(()ident(chunk)operator(,) ident(_length)operator(\);) +operator(}) + +comment(/************ +mapper_close +************/) + +directive(static) ident(VALUE) ident(mapper_close) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + ident(Mapper_t) operator(*)ident(m) operator(=) pre_constant(NULL)operator(;) + ident(Data_Get_Struct) operator(()ident(self)operator(,) ident(Mapper_t)operator(,) ident(m)operator(\);) + reserved(if) operator((!)ident(m)operator(\)) + ident(rb_raise) operator(()ident(rb_eException)operator(,) string<delimiter(")content(No Mapper Object)delimiter(")>operator(\);) + ident(m)operator(->)ident(Close)operator((\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/*********** +mapper_size +***********/) + +directive(static) ident(VALUE) ident(mapper_size) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + ident(Mapper_t) operator(*)ident(m) operator(=) pre_constant(NULL)operator(;) + ident(Data_Get_Struct) operator(()ident(self)operator(,) ident(Mapper_t)operator(,) ident(m)operator(\);) + reserved(if) operator((!)ident(m)operator(\)) + ident(rb_raise) operator(()ident(rb_eException)operator(,) string<delimiter(")content(No Mapper Object)delimiter(")>operator(\);) + reserved(return) ident(INT2NUM) operator(()ident(m)operator(->)ident(GetFileSize)operator((\)\);) +operator(}) + + +comment(/********************** +Init_fastfilereaderext +**********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(Init_fastfilereaderext)operator((\)) +operator({) + ident(EmModule) operator(=) ident(rb_define_module) operator(()string<delimiter(")content(EventMachine)delimiter(")>operator(\);) + ident(FastFileReader) operator(=) ident(rb_define_class_under) operator(()ident(EmModule)operator(,) string<delimiter(")content(FastFileReader)delimiter(")>operator(,) ident(rb_cObject)operator(\);) + ident(Mapper) operator(=) ident(rb_define_class_under) operator(()ident(FastFileReader)operator(,) string<delimiter(")content(Mapper)delimiter(")>operator(,) ident(rb_cObject)operator(\);) + + ident(rb_define_module_function) operator(()ident(Mapper)operator(,) string<delimiter(")content(new)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(mapper_new)operator(,) integer(1)operator(\);) + ident(rb_define_method) operator(()ident(Mapper)operator(,) string<delimiter(")content(size)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(mapper_size)operator(,) integer(0)operator(\);) + ident(rb_define_method) operator(()ident(Mapper)operator(,) string<delimiter(")content(close)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(mapper_close)operator(,) integer(0)operator(\);) + ident(rb_define_method) operator(()ident(Mapper)operator(,) string<delimiter(")content(get_chunk)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(mapper_get_chunk)operator(,) integer(2)operator(\);) +operator(}) + + + +comment(/***************************************************************************** + +$Id$ + +File: files.cpp +Date: 26Aug06 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + +preprocessor(#include) include("project.h") + + +comment(/****************************************** +FileStreamDescriptor::FileStreamDescriptor +******************************************/) + +ident(FileStreamDescriptor)operator(::)ident(FileStreamDescriptor) operator(()pre_type(int) ident(fd)operator(,) ident(EventMachine_t) operator(*)ident(em)operator(\):) + ident(EventableDescriptor) operator(()ident(fd)operator(,) ident(em)operator(\),) + ident(OutboundDataSize) operator(()integer(0)operator(\)) +operator({) +ident(cerr) operator(<<) string<delimiter(")content(#####)delimiter(")>operator(;) +operator(}) + + +comment(/******************************************* +FileStreamDescriptor::~FileStreamDescriptor +*******************************************/) + +ident(FileStreamDescriptor)operator(::~)ident(FileStreamDescriptor)operator((\)) +operator({) + comment(// Run down any stranded outbound data.) + reserved(for) operator(()ident(size_t) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) ident(OutboundPages)operator(.)ident(size)operator((\);) ident(i)operator(++\)) + ident(OutboundPages)operator([)ident(i)operator(])operator(.)ident(Free)operator((\);) +operator(}) + + +comment(/************************** +FileStreamDescriptor::Read +**************************/) + +directive(void) ident(FileStreamDescriptor)operator(::)ident(Read)operator((\)) +operator({) +operator(}) + +comment(/*************************** +FileStreamDescriptor::Write +***************************/) + +directive(void) ident(FileStreamDescriptor)operator(::)ident(Write)operator((\)) +operator({) +operator(}) + + +comment(/******************************* +FileStreamDescriptor::Heartbeat +*******************************/) + +directive(void) ident(FileStreamDescriptor)operator(::)ident(Heartbeat)operator((\)) +operator({) +operator(}) + + +comment(/*********************************** +FileStreamDescriptor::SelectForRead +***********************************/) + +pre_type(bool) ident(FileStreamDescriptor)operator(::)ident(SelectForRead)operator((\)) +operator({) + ident(cerr) operator(<<) string<delimiter(")content(R?)delimiter(")>operator(;) + reserved(return) pre_constant(false)operator(;) +operator(}) + + +comment(/************************************ +FileStreamDescriptor::SelectForWrite +************************************/) + +pre_type(bool) ident(FileStreamDescriptor)operator(::)ident(SelectForWrite)operator((\)) +operator({) + ident(cerr) operator(<<) string<delimiter(")content(W?)delimiter(")>operator(;) + reserved(return) pre_constant(false)operator(;) +operator(}) + + +comment(/***************************************************************************** + +$Id$ + +File: kb.cpp +Date: 24Aug07 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + +preprocessor(#include) include("project.h") + + +comment(/************************************** +KeyboardDescriptor::KeyboardDescriptor +**************************************/) + +ident(KeyboardDescriptor)operator(::)ident(KeyboardDescriptor) operator(()ident(EventMachine_t) operator(*)ident(parent_em)operator(\):) + ident(EventableDescriptor) operator(()integer(0)operator(,) ident(parent_em)operator(\),) + ident(bReadAttemptedAfterClose) operator(()pre_constant(false)operator(\),) + ident(LastIo) operator(()ident(gCurrentLoopTime)operator(\),) + ident(InactivityTimeout) operator(()integer(0)operator(\)) +operator({) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) ident(EPOLLIN)operator(;) + preprocessor(#endif) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + ident(MyEventMachine)operator(->)ident(ArmKqueueReader) operator(()local_variable(this)operator(\);) + preprocessor(#endif) +operator(}) + + +comment(/*************************************** +KeyboardDescriptor::~KeyboardDescriptor +***************************************/) + +ident(KeyboardDescriptor)operator(::~)ident(KeyboardDescriptor)operator((\)) +operator({) +operator(}) + + +comment(/************************* +KeyboardDescriptor::Write +*************************/) + +directive(void) ident(KeyboardDescriptor)operator(::)ident(Write)operator((\)) +operator({) + comment(// Why are we here?) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad code path in keyboard handler)delimiter(")>operator(\);) +operator(}) + + +comment(/***************************** +KeyboardDescriptor::Heartbeat +*****************************/) + +directive(void) ident(KeyboardDescriptor)operator(::)ident(Heartbeat)operator((\)) +operator({) + comment(// no-op) +operator(}) + + +comment(/************************ +KeyboardDescriptor::Read +************************/) + +directive(void) ident(KeyboardDescriptor)operator(::)ident(Read)operator((\)) +operator({) + pre_type(char) ident(c)operator(;) + ident(read) operator(()ident(GetSocket)operator((\),) operator(&)ident(c)operator(,) integer(1)operator(\);) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_READ)operator(,) operator(&)ident(c)operator(,) integer(1)operator(\);) +operator(}) + + + + +comment(#if 0 +/****************************** +PipeDescriptor::PipeDescriptor +******************************/ + +PipeDescriptor::PipeDescriptor (int fd, pid_t subpid, EventMachine_t *parent_em\): + EventableDescriptor (fd, parent_em\), + bReadAttemptedAfterClose (false\), + LastIo (gCurrentLoopTime\), + InactivityTimeout (0\), + OutboundDataSize (0\), + SubprocessPid (subpid\) +{ + #ifdef HAVE_EPOLL + EpollEvent.events = EPOLLIN; + #endif +} + + +/******************************* +PipeDescriptor::~PipeDescriptor +*******************************/ + +PipeDescriptor::~PipeDescriptor(\) +{ + // Run down any stranded outbound data. + for (size_t i=0; i < OutboundPages.size(\); i++\) + OutboundPages[i].Free(\); + + /* As a virtual destructor, we come here before the base-class + * destructor that closes our file-descriptor. + * We have to make sure the subprocess goes down (if it's not + * already down\) and we have to reap the zombie. + * + * This implementation is PROVISIONAL and will surely be improved. + * The intention here is that we never block, hence the highly + * undesirable sleeps. But if we can't reap the subprocess even + * after sending it SIGKILL, then something is wrong and we + * throw a fatal exception, which is also not something we should + * be doing. + * + * Eventually the right thing to do will be to have the reactor + * core respond to SIGCHLD by chaining a handler on top of the + * one Ruby may have installed, and dealing with a list of dead + * children that are pending cleanup. + * + * Since we want to have a signal processor integrated into the + * client-visible API, let's wait until that is done before cleaning + * this up. + */ + + struct timespec req = {0, 10000000}; + kill (SubprocessPid, SIGTERM\); + nanosleep (&req, NULL\); + if (waitpid (SubprocessPid, NULL, WNOHANG\) == 0\) { + kill (SubprocessPid, SIGKILL\); + nanosleep (&req, NULL\); + if (waitpid (SubprocessPid, NULL, WNOHANG\) == 0\) + throw std::runtime_error ("unable to reap subprocess"\); + } +} + + + +/******************** +PipeDescriptor::Read +********************/ + +void PipeDescriptor::Read(\) +{ + int sd = GetSocket(\); + if (sd == INVALID_SOCKET\) { + assert (!bReadAttemptedAfterClose\); + bReadAttemptedAfterClose = true; + return; + } + + LastIo = gCurrentLoopTime; + + int total_bytes_read = 0; + char readbuffer [16 * 1024]; + + for (int i=0; i < 10; i++\) { + // Don't read just one buffer and then move on. This is faster + // if there is a lot of incoming. + // But don't read indefinitely. Give other sockets a chance to run. + // NOTICE, we're reading one less than the buffer size. + // That's so we can put a guard byte at the end of what we send + // to user code. + // Use read instead of recv, which on Linux gives a "socket operation + // on nonsocket" error. + + + int r = read (sd, readbuffer, sizeof(readbuffer\) - 1\); + //cerr << "<R:" << r << ">"; + + if (r > 0\) { + total_bytes_read += r; + LastRead = gCurrentLoopTime; + + // Add a null-terminator at the the end of the buffer + // that we will send to the callback. + // DO NOT EVER CHANGE THIS. We want to explicitly allow users + // to be able to depend on this behavior, so they will have + // the option to do some things faster. Additionally it's + // a security guard against buffer overflows. + readbuffer [r] = 0; + if (EventCallback\) + (*EventCallback\)(GetBinding(\).c_str(\), EM_CONNECTION_READ, readbuffer, r\); + } + else if (r == 0\) { + break; + } + else { + // Basically a would-block, meaning we've read everything there is to read. + break; + } + + } + + + if (total_bytes_read == 0\) { + // If we read no data on a socket that selected readable, + // it generally means the other end closed the connection gracefully. + ScheduleClose (false\); + //bCloseNow = true; + } + +} + +/********************* +PipeDescriptor::Write +*********************/ + +void PipeDescriptor::Write(\) +{ + int sd = GetSocket(\); + assert (sd != INVALID_SOCKET\); + + LastIo = gCurrentLoopTime; + char output_buffer [16 * 1024]; + size_t nbytes = 0; + + while ((OutboundPages.size(\) > 0\) && (nbytes < sizeof(output_buffer\)\)\) { + OutboundPage *op = &(OutboundPages[0]\); + if ((nbytes + op->Length - op->Offset\) < sizeof (output_buffer\)\) { + memcpy (output_buffer + nbytes, op->Buffer + op->Offset, op->Length - op->Offset\); + nbytes += (op->Length - op->Offset\); + op->Free(\); + OutboundPages.pop_front(\); + } + else { + int len = sizeof(output_buffer\) - nbytes; + memcpy (output_buffer + nbytes, op->Buffer + op->Offset, len\); + op->Offset += len; + nbytes += len; + } + } + + // We should never have gotten here if there were no data to write, + // so assert that as a sanity check. + // Don't bother to make sure nbytes is less than output_buffer because + // if it were we probably would have crashed already. + assert (nbytes > 0\); + + assert (GetSocket(\) != INVALID_SOCKET\); + int bytes_written = write (GetSocket(\), output_buffer, nbytes\); + + if (bytes_written > 0\) { + OutboundDataSize -= bytes_written; + if ((size_t\)bytes_written < nbytes\) { + int len = nbytes - bytes_written; + char *buffer = (char*\) malloc (len + 1\); + if (!buffer\) + throw std::runtime_error ("bad alloc throwing back data"\); + memcpy (buffer, output_buffer + bytes_written, len\); + buffer [len] = 0; + OutboundPages.push_front (OutboundPage (buffer, len\)\); + } + #ifdef HAVE_EPOLL + EpollEvent.events = (EPOLLIN | (SelectForWrite(\) ? EPOLLOUT : 0\)\); + assert (MyEventMachine\); + MyEventMachine->Modify (this\); + #endif + } + else { + #ifdef OS_UNIX + if ((errno != EINPROGRESS\) && (errno != EWOULDBLOCK\) && (errno != EINTR\)\) + #endif + #ifdef OS_WIN32 + if ((errno != WSAEINPROGRESS\) && (errno != WSAEWOULDBLOCK\)\) + #endif + Close(\); + } +} + + +/************************* +PipeDescriptor::Heartbeat +*************************/ + +void PipeDescriptor::Heartbeat(\) +{ + // If an inactivity timeout is defined, then check for it. + if (InactivityTimeout && ((gCurrentLoopTime - LastIo\) >= InactivityTimeout\)\) + ScheduleClose (false\); + //bCloseNow = true; +} + + +/***************************** +PipeDescriptor::SelectForRead +*****************************/ + +bool PipeDescriptor::SelectForRead(\) +{ + /* Pipe descriptors, being local by definition, don't have + * a pending state, so this is simpler than for the + * ConnectionDescriptor object. + */ + return true; +} + +/****************************** +PipeDescriptor::SelectForWrite +******************************/ + +bool PipeDescriptor::SelectForWrite(\) +{ + /* Pipe descriptors, being local by definition, don't have + * a pending state, so this is simpler than for the + * ConnectionDescriptor object. + */ + return (GetOutboundDataSize(\) > 0\); +} + + + + +/******************************** +PipeDescriptor::SendOutboundData +********************************/ + +int PipeDescriptor::SendOutboundData (const char *data, int length\) +{ + //if (bCloseNow || bCloseAfterWriting\) + if (IsCloseScheduled(\)\) + return 0; + + if (!data && (length > 0\)\) + throw std::runtime_error ("bad outbound data"\); + char *buffer = (char *\) malloc (length + 1\); + if (!buffer\) + throw std::runtime_error ("no allocation for outbound data"\); + memcpy (buffer, data, length\); + buffer [length] = 0; + OutboundPages.push_back (OutboundPage (buffer, length\)\); + OutboundDataSize += length; + #ifdef HAVE_EPOLL + EpollEvent.events = (EPOLLIN | EPOLLOUT\); + assert (MyEventMachine\); + MyEventMachine->Modify (this\); + #endif + return length; +} + +/******************************** +PipeDescriptor::GetSubprocessPid +********************************/ + +bool PipeDescriptor::GetSubprocessPid (pid_t *pid\) +{ + bool ok = false; + if (pid && (SubprocessPid > 0\)\) { + *pid = SubprocessPid; + ok = true; + } + return ok; +} + +#endif ) + +comment(/***************************************************************************** + +$Id$ + +File: page.cpp +Date: 30Apr06 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + + +preprocessor(#include) include("project.h") + + +comment(/****************** +PageList::PageList +******************/) + +ident(PageList)operator(::)ident(PageList)operator((\)) +operator({) +operator(}) + + +comment(/******************* +PageList::~PageList +*******************/) + +ident(PageList)operator(::~)ident(PageList)operator((\)) +operator({) + reserved(while) operator(()ident(HasPages)operator((\)\)) + ident(PopFront)operator((\);) +operator(}) + + +comment(/*************** +PageList::Front +***************/) + +directive(void) ident(PageList)operator(::)ident(Front) operator(()directive(const) pre_type(char) operator(**)ident(page)operator(,) pre_type(int) operator(*)ident(length)operator(\)) +operator({) + ident(assert) operator(()ident(page) operator(&&) ident(length)operator(\);) + + reserved(if) operator(()ident(HasPages)operator((\)\)) operator({) + ident(Page) ident(p) operator(=) ident(Pages)operator(.)ident(front)operator((\);) + operator(*)ident(page) operator(=) ident(p)operator(.)ident(Buffer)operator(;) + operator(*)ident(length) operator(=) ident(p)operator(.)ident(Size)operator(;) + operator(}) + reserved(else) operator({) + operator(*)ident(page) operator(=) pre_constant(NULL)operator(;) + operator(*)ident(length) operator(=) integer(0)operator(;) + operator(}) +operator(}) + + +comment(/****************** +PageList::PopFront +******************/) + +directive(void) ident(PageList)operator(::)ident(PopFront)operator((\)) +operator({) + reserved(if) operator(()ident(HasPages)operator((\)\)) operator({) + ident(Page) ident(p) operator(=) ident(Pages)operator(.)ident(front)operator((\);) + ident(Pages)operator(.)ident(pop_front)operator((\);) + reserved(if) operator(()ident(p)operator(.)ident(Buffer)operator(\)) + ident(free) operator((()directive(void)operator(*\))ident(p)operator(.)ident(Buffer)operator(\);) + operator(}) +operator(}) + + +comment(/****************** +PageList::HasPages +******************/) + +pre_type(bool) ident(PageList)operator(::)ident(HasPages)operator((\)) +operator({) + reserved(return) operator(()ident(Pages)operator(.)ident(size)operator((\)) operator(>) integer(0)operator(\)) operator(?) pre_constant(true) operator(:) pre_constant(false)operator(;) +operator(}) + + +comment(/************** +PageList::Push +**************/) + +directive(void) ident(PageList)operator(::)ident(Push) operator(()directive(const) pre_type(char) operator(*)ident(buf)operator(,) pre_type(int) ident(size)operator(\)) +operator({) + reserved(if) operator(()ident(buf) operator(&&) operator(()ident(size) operator(>) integer(0)operator(\)\)) operator({) + pre_type(char) operator(*)ident(copy) operator(=) operator(()pre_type(char)operator(*\)) ident(malloc) operator(()ident(size)operator(\);) + reserved(if) operator((!)ident(copy)operator(\)) + reserved(throw) ident(runtime_error) operator(()string<delimiter(")content(no memory in pagelist)delimiter(")>operator(\);) + ident(memcpy) operator(()ident(copy)operator(,) ident(buf)operator(,) ident(size)operator(\);) + ident(Pages)operator(.)ident(push_back) operator(()ident(Page) operator(()ident(copy)operator(,) ident(size)operator(\)\);) + operator(}) +operator(}) + + + + + +comment(/***************************************************************************** + +$Id$ + +File: pipe.cpp +Date: 30May07 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + +preprocessor(#include) include("project.h") + + +preprocessor(#ifdef) ident(OS_UNIX) +comment(// THIS ENTIRE FILE IS ONLY COMPILED ON UNIX-LIKE SYSTEMS.) + +comment(/****************************** +PipeDescriptor::PipeDescriptor +******************************/) + +ident(PipeDescriptor)operator(::)ident(PipeDescriptor) operator(()pre_type(int) ident(fd)operator(,) ident(pid_t) ident(subpid)operator(,) ident(EventMachine_t) operator(*)ident(parent_em)operator(\):) + ident(EventableDescriptor) operator(()ident(fd)operator(,) ident(parent_em)operator(\),) + ident(bReadAttemptedAfterClose) operator(()pre_constant(false)operator(\),) + ident(LastIo) operator(()ident(gCurrentLoopTime)operator(\),) + ident(InactivityTimeout) operator(()integer(0)operator(\),) + ident(OutboundDataSize) operator(()integer(0)operator(\),) + ident(SubprocessPid) operator(()ident(subpid)operator(\)) +operator({) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) ident(EPOLLIN)operator(;) + preprocessor(#endif) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + ident(MyEventMachine)operator(->)ident(ArmKqueueReader) operator(()local_variable(this)operator(\);) + preprocessor(#endif) +operator(}) + + +comment(/******************************* +PipeDescriptor::~PipeDescriptor +*******************************/) + +ident(PipeDescriptor)operator(::~)ident(PipeDescriptor)operator((\)) +operator({) + comment(// Run down any stranded outbound data.) + reserved(for) operator(()ident(size_t) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) ident(OutboundPages)operator(.)ident(size)operator((\);) ident(i)operator(++\)) + ident(OutboundPages)operator([)ident(i)operator(])operator(.)ident(Free)operator((\);) + + comment(/* As a virtual destructor, we come here before the base-class + * destructor that closes our file-descriptor. + * We have to make sure the subprocess goes down (if it's not + * already down\) and we have to reap the zombie. + * + * This implementation is PROVISIONAL and will surely be improved. + * The intention here is that we never block, hence the highly + * undesirable sleeps. But if we can't reap the subprocess even + * after sending it SIGKILL, then something is wrong and we + * throw a fatal exception, which is also not something we should + * be doing. + * + * Eventually the right thing to do will be to have the reactor + * core respond to SIGCHLD by chaining a handler on top of the + * one Ruby may have installed, and dealing with a list of dead + * children that are pending cleanup. + * + * Since we want to have a signal processor integrated into the + * client-visible API, let's wait until that is done before cleaning + * this up. + * + * Added a very ugly hack to support passing the subprocess's exit + * status to the user. It only makes logical sense for user code to access + * the subprocess exit status in the unbind callback. But unbind is called + * back during the EventableDescriptor destructor. So by that time there's + * no way to call back this object through an object binding, because it's + * already been cleaned up. We might have added a parameter to the unbind + * callback, but that would probably break a huge amount of existing code. + * So the hack-solution is to define an instance variable in the EventMachine + * object and stick the exit status in there, where it can easily be accessed + * with an accessor visible to user code. + * User code should ONLY access the exit status from within the unbind callback. + * Otherwise there's no guarantee it'll be valid. + * This hack won't make it impossible to run multiple EventMachines in a single + * process, but it will make it impossible to reliably nest unbind calls + * within other unbind calls. (Not sure if that's even possible.\) + */) + + ident(assert) operator(()ident(MyEventMachine)operator(\);) + + comment(// check if the process is already dead) + reserved(if) operator(()ident(waitpid) operator(()ident(SubprocessPid)operator(,) operator(&()ident(MyEventMachine)operator(->)ident(SubprocessExitStatus)operator(\),) ident(WNOHANG)operator(\)) operator(==) integer(0)operator(\)) operator({) + ident(kill) operator(()ident(SubprocessPid)operator(,) ident(SIGTERM)operator(\);) + comment(// wait 0.25s for process to die) + reserved(struct) ident(timespec) ident(req) operator(=) operator({)integer(0)operator(,) integer(250000000)operator(};) + ident(nanosleep) operator((&)ident(req)operator(,) pre_constant(NULL)operator(\);) + reserved(if) operator(()ident(waitpid) operator(()ident(SubprocessPid)operator(,) operator(&()ident(MyEventMachine)operator(->)ident(SubprocessExitStatus)operator(\),) ident(WNOHANG)operator(\)) operator(==) integer(0)operator(\)) operator({) + ident(kill) operator(()ident(SubprocessPid)operator(,) ident(SIGKILL)operator(\);) + comment(// wait 0.5s for process to die) + reserved(struct) ident(timespec) ident(req) operator(=) operator({)integer(0)operator(,) integer(500000000)operator(};) + ident(nanosleep) operator((&)ident(req)operator(,) pre_constant(NULL)operator(\);) + reserved(if) operator(()ident(waitpid) operator(()ident(SubprocessPid)operator(,) operator(&()ident(MyEventMachine)operator(->)ident(SubprocessExitStatus)operator(\),) ident(WNOHANG)operator(\)) operator(==) integer(0)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(unable to reap subprocess)delimiter(")>operator(\);) + operator(}) + operator(}) +operator(}) + + + +comment(/******************** +PipeDescriptor::Read +********************/) + +directive(void) ident(PipeDescriptor)operator(::)ident(Read)operator((\)) +operator({) + pre_type(int) ident(sd) operator(=) ident(GetSocket)operator((\);) + reserved(if) operator(()ident(sd) operator(==) ident(INVALID_SOCKET)operator(\)) operator({) + ident(assert) operator((!)ident(bReadAttemptedAfterClose)operator(\);) + ident(bReadAttemptedAfterClose) operator(=) pre_constant(true)operator(;) + reserved(return)operator(;) + operator(}) + + ident(LastIo) operator(=) ident(gCurrentLoopTime)operator(;) + + pre_type(int) ident(total_bytes_read) operator(=) integer(0)operator(;) + pre_type(char) ident(readbuffer) operator([)integer(16) operator(*) integer(1024)operator(];) + + reserved(for) operator(()pre_type(int) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) integer(10)operator(;) ident(i)operator(++\)) operator({) + comment(// Don't read just one buffer and then move on. This is faster) + comment(// if there is a lot of incoming.) + comment(// But don't read indefinitely. Give other sockets a chance to run.) + comment(// NOTICE, we're reading one less than the buffer size.) + comment(// That's so we can put a guard byte at the end of what we send) + comment(// to user code.) + comment(// Use read instead of recv, which on Linux gives a "socket operation) + comment(// on nonsocket" error.) + + + pre_type(int) ident(r) operator(=) ident(read) operator(()ident(sd)operator(,) ident(readbuffer)operator(,) reserved(sizeof)operator(()ident(readbuffer)operator(\)) operator(-) integer(1)operator(\);) + comment(//cerr << "<R:" << r << ">";) + + reserved(if) operator(()ident(r) operator(>) integer(0)operator(\)) operator({) + ident(total_bytes_read) operator(+=) ident(r)operator(;) + ident(LastRead) operator(=) ident(gCurrentLoopTime)operator(;) + + comment(// Add a null-terminator at the the end of the buffer) + comment(// that we will send to the callback.) + comment(// DO NOT EVER CHANGE THIS. We want to explicitly allow users) + comment(// to be able to depend on this behavior, so they will have) + comment(// the option to do some things faster. Additionally it's) + comment(// a security guard against buffer overflows.) + ident(readbuffer) operator([)ident(r)operator(]) operator(=) integer(0)operator(;) + reserved(if) operator(()ident(EventCallback)operator(\)) + operator((*)ident(EventCallback)operator(\)()ident(GetBinding)operator((\))operator(.)ident(c_str)operator((\),) ident(EM_CONNECTION_READ)operator(,) ident(readbuffer)operator(,) ident(r)operator(\);) + operator(}) + reserved(else) reserved(if) operator(()ident(r) operator(==) integer(0)operator(\)) operator({) + reserved(break)operator(;) + operator(}) + reserved(else) operator({) + comment(// Basically a would-block, meaning we've read everything there is to read.) + reserved(break)operator(;) + operator(}) + + operator(}) + + + reserved(if) operator(()ident(total_bytes_read) operator(==) integer(0)operator(\)) operator({) + comment(// If we read no data on a socket that selected readable,) + comment(// it generally means the other end closed the connection gracefully.) + ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + comment(//bCloseNow = true;) + operator(}) + +operator(}) + +comment(/********************* +PipeDescriptor::Write +*********************/) + +directive(void) ident(PipeDescriptor)operator(::)ident(Write)operator((\)) +operator({) + pre_type(int) ident(sd) operator(=) ident(GetSocket)operator((\);) + ident(assert) operator(()ident(sd) operator(!=) ident(INVALID_SOCKET)operator(\);) + + ident(LastIo) operator(=) ident(gCurrentLoopTime)operator(;) + pre_type(char) ident(output_buffer) operator([)integer(16) operator(*) integer(1024)operator(];) + ident(size_t) ident(nbytes) operator(=) integer(0)operator(;) + + reserved(while) operator((()ident(OutboundPages)operator(.)ident(size)operator((\)) operator(>) integer(0)operator(\)) operator(&&) operator(()ident(nbytes) operator(<) reserved(sizeof)operator(()ident(output_buffer)operator(\)\)\)) operator({) + ident(OutboundPage) operator(*)ident(op) operator(=) operator(&()ident(OutboundPages)operator([)integer(0)operator(]\);) + reserved(if) operator((()ident(nbytes) operator(+) ident(op)operator(->)ident(Length) operator(-) ident(op)operator(->)ident(Offset)operator(\)) operator(<) reserved(sizeof) operator(()ident(output_buffer)operator(\)\)) operator({) + ident(memcpy) operator(()ident(output_buffer) operator(+) ident(nbytes)operator(,) ident(op)operator(->)ident(Buffer) operator(+) ident(op)operator(->)ident(Offset)operator(,) ident(op)operator(->)ident(Length) operator(-) ident(op)operator(->)ident(Offset)operator(\);) + ident(nbytes) operator(+=) operator(()ident(op)operator(->)ident(Length) operator(-) ident(op)operator(->)ident(Offset)operator(\);) + ident(op)operator(->)ident(Free)operator((\);) + ident(OutboundPages)operator(.)ident(pop_front)operator((\);) + operator(}) + reserved(else) operator({) + pre_type(int) ident(len) operator(=) reserved(sizeof)operator(()ident(output_buffer)operator(\)) operator(-) ident(nbytes)operator(;) + ident(memcpy) operator(()ident(output_buffer) operator(+) ident(nbytes)operator(,) ident(op)operator(->)ident(Buffer) operator(+) ident(op)operator(->)ident(Offset)operator(,) ident(len)operator(\);) + ident(op)operator(->)ident(Offset) operator(+=) ident(len)operator(;) + ident(nbytes) operator(+=) ident(len)operator(;) + operator(}) + operator(}) + + comment(// We should never have gotten here if there were no data to write,) + comment(// so assert that as a sanity check.) + comment(// Don't bother to make sure nbytes is less than output_buffer because) + comment(// if it were we probably would have crashed already.) + ident(assert) operator(()ident(nbytes) operator(>) integer(0)operator(\);) + + ident(assert) operator(()ident(GetSocket)operator((\)) operator(!=) ident(INVALID_SOCKET)operator(\);) + pre_type(int) ident(bytes_written) operator(=) ident(write) operator(()ident(GetSocket)operator((\),) ident(output_buffer)operator(,) ident(nbytes)operator(\);) + + reserved(if) operator(()ident(bytes_written) operator(>) integer(0)operator(\)) operator({) + ident(OutboundDataSize) operator(-=) ident(bytes_written)operator(;) + reserved(if) operator((()ident(size_t)operator(\))ident(bytes_written) operator(<) ident(nbytes)operator(\)) operator({) + pre_type(int) ident(len) operator(=) ident(nbytes) operator(-) ident(bytes_written)operator(;) + pre_type(char) operator(*)ident(buffer) operator(=) operator(()pre_type(char)operator(*\)) ident(malloc) operator(()ident(len) operator(+) integer(1)operator(\);) + reserved(if) operator((!)ident(buffer)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad alloc throwing back data)delimiter(")>operator(\);) + ident(memcpy) operator(()ident(buffer)operator(,) ident(output_buffer) operator(+) ident(bytes_written)operator(,) ident(len)operator(\);) + ident(buffer) operator([)ident(len)operator(]) operator(=) integer(0)operator(;) + ident(OutboundPages)operator(.)ident(push_front) operator(()ident(OutboundPage) operator(()ident(buffer)operator(,) ident(len)operator(\)\);) + operator(}) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) operator(()ident(EPOLLIN) operator(|) operator(()ident(SelectForWrite)operator((\)) operator(?) ident(EPOLLOUT) operator(:) integer(0)operator(\)\);) + ident(assert) operator(()ident(MyEventMachine)operator(\);) + ident(MyEventMachine)operator(->)ident(Modify) operator(()local_variable(this)operator(\);) + preprocessor(#endif) + operator(}) + reserved(else) operator({) + preprocessor(#ifdef) ident(OS_UNIX) + reserved(if) operator((()ident(errno) operator(!=) ident(EINPROGRESS)operator(\)) operator(&&) operator(()ident(errno) operator(!=) ident(EWOULDBLOCK)operator(\)) operator(&&) operator(()ident(errno) operator(!=) ident(EINTR)operator(\)\)) + preprocessor(#endif) + preprocessor(#ifdef) ident(OS_WIN32) + reserved(if) operator((()ident(errno) operator(!=) ident(WSAEINPROGRESS)operator(\)) operator(&&) operator(()ident(errno) operator(!=) ident(WSAEWOULDBLOCK)operator(\)\)) + preprocessor(#endif) + ident(Close)operator((\);) + operator(}) +operator(}) + + +comment(/************************* +PipeDescriptor::Heartbeat +*************************/) + +directive(void) ident(PipeDescriptor)operator(::)ident(Heartbeat)operator((\)) +operator({) + comment(// If an inactivity timeout is defined, then check for it.) + reserved(if) operator(()ident(InactivityTimeout) operator(&&) operator((()ident(gCurrentLoopTime) operator(-) ident(LastIo)operator(\)) operator(>=) ident(InactivityTimeout)operator(\)\)) + ident(ScheduleClose) operator(()pre_constant(false)operator(\);) + comment(//bCloseNow = true;) +operator(}) + + +comment(/***************************** +PipeDescriptor::SelectForRead +*****************************/) + +pre_type(bool) ident(PipeDescriptor)operator(::)ident(SelectForRead)operator((\)) +operator({) + comment(/* Pipe descriptors, being local by definition, don't have + * a pending state, so this is simpler than for the + * ConnectionDescriptor object. + */) + reserved(return) pre_constant(true)operator(;) +operator(}) + +comment(/****************************** +PipeDescriptor::SelectForWrite +******************************/) + +pre_type(bool) ident(PipeDescriptor)operator(::)ident(SelectForWrite)operator((\)) +operator({) + comment(/* Pipe descriptors, being local by definition, don't have + * a pending state, so this is simpler than for the + * ConnectionDescriptor object. + */) + reserved(return) operator(()ident(GetOutboundDataSize)operator((\)) operator(>) integer(0)operator(\);) +operator(}) + + + + +comment(/******************************** +PipeDescriptor::SendOutboundData +********************************/) + +pre_type(int) ident(PipeDescriptor)operator(::)ident(SendOutboundData) operator(()directive(const) pre_type(char) operator(*)ident(data)operator(,) pre_type(int) ident(length)operator(\)) +operator({) + comment(//if (bCloseNow || bCloseAfterWriting\)) + reserved(if) operator(()ident(IsCloseScheduled)operator((\)\)) + reserved(return) integer(0)operator(;) + + reserved(if) operator((!)ident(data) operator(&&) operator(()ident(length) operator(>) integer(0)operator(\)\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(bad outbound data)delimiter(")>operator(\);) + pre_type(char) operator(*)ident(buffer) operator(=) operator(()pre_type(char) operator(*\)) ident(malloc) operator(()ident(length) operator(+) integer(1)operator(\);) + reserved(if) operator((!)ident(buffer)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no allocation for outbound data)delimiter(")>operator(\);) + ident(memcpy) operator(()ident(buffer)operator(,) ident(data)operator(,) ident(length)operator(\);) + ident(buffer) operator([)ident(length)operator(]) operator(=) integer(0)operator(;) + ident(OutboundPages)operator(.)ident(push_back) operator(()ident(OutboundPage) operator(()ident(buffer)operator(,) ident(length)operator(\)\);) + ident(OutboundDataSize) operator(+=) ident(length)operator(;) + preprocessor(#ifdef) ident(HAVE_EPOLL) + ident(EpollEvent)operator(.)ident(events) operator(=) operator(()ident(EPOLLIN) operator(|) ident(EPOLLOUT)operator(\);) + ident(assert) operator(()ident(MyEventMachine)operator(\);) + ident(MyEventMachine)operator(->)ident(Modify) operator(()local_variable(this)operator(\);) + preprocessor(#endif) + reserved(return) ident(length)operator(;) +operator(}) + +comment(/******************************** +PipeDescriptor::GetSubprocessPid +********************************/) + +pre_type(bool) ident(PipeDescriptor)operator(::)ident(GetSubprocessPid) operator(()ident(pid_t) operator(*)ident(pid)operator(\)) +operator({) + pre_type(bool) ident(ok) operator(=) pre_constant(false)operator(;) + reserved(if) operator(()ident(pid) operator(&&) operator(()ident(SubprocessPid) operator(>) integer(0)operator(\)\)) operator({) + operator(*)ident(pid) operator(=) ident(SubprocessPid)operator(;) + ident(ok) operator(=) pre_constant(true)operator(;) + operator(}) + reserved(return) ident(ok)operator(;) +operator(}) + + +preprocessor(#endif) comment(// OS_UNIX) + +comment(/***************************************************************************** + +$Id$ + +File: rubymain.cpp +Date: 06Apr06 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + +preprocessor(#include) include("project.h") +preprocessor(#include) include("eventmachine.h") +preprocessor(#include) include(<ruby.h>) + + + +comment(/******* +Statics +*******/) + +directive(static) ident(VALUE) ident(EmModule)operator(;) +directive(static) ident(VALUE) ident(EmConnection)operator(;) + +directive(static) ident(VALUE) ident(Intern_at_signature)operator(;) +directive(static) ident(VALUE) ident(Intern_at_timers)operator(;) +directive(static) ident(VALUE) ident(Intern_at_conns)operator(;) +directive(static) ident(VALUE) ident(Intern_event_callback)operator(;) +directive(static) ident(VALUE) ident(Intern_run_deferred_callbacks)operator(;) +directive(static) ident(VALUE) ident(Intern_delete)operator(;) +directive(static) ident(VALUE) ident(Intern_call)operator(;) +directive(static) ident(VALUE) ident(Intern_receive_data)operator(;) + +directive(static) ident(VALUE) ident(Intern_notify_readable)operator(;) +directive(static) ident(VALUE) ident(Intern_notify_writable)operator(;) + +comment(/**************** +t_event_callback +****************/) + +directive(static) directive(void) ident(event_callback) operator(()directive(const) pre_type(char) operator(*)ident(a1)operator(,) pre_type(int) ident(a2)operator(,) directive(const) pre_type(char) operator(*)ident(a3)operator(,) pre_type(int) ident(a4)operator(\)) +operator({) + reserved(if) operator(()ident(a2) operator(==) ident(EM_CONNECTION_READ)operator(\)) operator({) + ident(VALUE) ident(t) operator(=) ident(rb_ivar_get) operator(()ident(EmModule)operator(,) ident(Intern_at_conns)operator(\);) + ident(VALUE) ident(q) operator(=) ident(rb_hash_aref) operator(()ident(t)operator(,) ident(rb_str_new2)operator(()ident(a1)operator(\)\);) + reserved(if) operator(()ident(q) operator(==) ident(Qnil)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no connection)delimiter(")>operator(\);) + ident(rb_funcall) operator(()ident(q)operator(,) ident(Intern_receive_data)operator(,) integer(1)operator(,) ident(rb_str_new) operator(()ident(a3)operator(,) ident(a4)operator(\)\);) + operator(}) + reserved(else) reserved(if) operator(()ident(a2) operator(==) ident(EM_CONNECTION_NOTIFY_READABLE)operator(\)) operator({) + ident(VALUE) ident(t) operator(=) ident(rb_ivar_get) operator(()ident(EmModule)operator(,) ident(Intern_at_conns)operator(\);) + ident(VALUE) ident(q) operator(=) ident(rb_hash_aref) operator(()ident(t)operator(,) ident(rb_str_new2)operator(()ident(a1)operator(\)\);) + reserved(if) operator(()ident(q) operator(==) ident(Qnil)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no connection)delimiter(")>operator(\);) + ident(rb_funcall) operator(()ident(q)operator(,) ident(Intern_notify_readable)operator(,) integer(0)operator(\);) + operator(}) + reserved(else) reserved(if) operator(()ident(a2) operator(==) ident(EM_CONNECTION_NOTIFY_WRITABLE)operator(\)) operator({) + ident(VALUE) ident(t) operator(=) ident(rb_ivar_get) operator(()ident(EmModule)operator(,) ident(Intern_at_conns)operator(\);) + ident(VALUE) ident(q) operator(=) ident(rb_hash_aref) operator(()ident(t)operator(,) ident(rb_str_new2)operator(()ident(a1)operator(\)\);) + reserved(if) operator(()ident(q) operator(==) ident(Qnil)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no connection)delimiter(")>operator(\);) + ident(rb_funcall) operator(()ident(q)operator(,) ident(Intern_notify_writable)operator(,) integer(0)operator(\);) + operator(}) + reserved(else) reserved(if) operator(()ident(a2) operator(==) ident(EM_LOOPBREAK_SIGNAL)operator(\)) operator({) + ident(rb_funcall) operator(()ident(EmModule)operator(,) ident(Intern_run_deferred_callbacks)operator(,) integer(0)operator(\);) + operator(}) + reserved(else) reserved(if) operator(()ident(a2) operator(==) ident(EM_TIMER_FIRED)operator(\)) operator({) + ident(VALUE) ident(t) operator(=) ident(rb_ivar_get) operator(()ident(EmModule)operator(,) ident(Intern_at_timers)operator(\);) + ident(VALUE) ident(q) operator(=) ident(rb_funcall) operator(()ident(t)operator(,) ident(Intern_delete)operator(,) integer(1)operator(,) ident(rb_str_new)operator(()ident(a3)operator(,) ident(a4)operator(\)\);) + reserved(if) operator(()ident(q) operator(==) ident(Qnil)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no timer)delimiter(")>operator(\);) + ident(rb_funcall) operator(()ident(q)operator(,) ident(Intern_call)operator(,) integer(0)operator(\);) + operator(}) + reserved(else) + ident(rb_funcall) operator(()ident(EmModule)operator(,) ident(Intern_event_callback)operator(,) integer(3)operator(,) ident(rb_str_new2)operator(()ident(a1)operator(\),) operator(()ident(a2) operator(<<) integer(1)operator(\)) operator(|) integer(1)operator(,) ident(rb_str_new)operator(()ident(a3)operator(,)ident(a4)operator(\)\);) +operator(}) + + + +comment(/************************** +t_initialize_event_machine +**************************/) + +directive(static) ident(VALUE) ident(t_initialize_event_machine) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + ident(evma_initialize_library) operator(()ident(event_callback)operator(\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + + + +comment(/***************************** +t_run_machine_without_threads +*****************************/) + +directive(static) ident(VALUE) ident(t_run_machine_without_threads) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + ident(evma_run_machine)operator((\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + + +comment(/******************* +t_add_oneshot_timer +*******************/) + +directive(static) ident(VALUE) ident(t_add_oneshot_timer) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(interval)operator(\)) +operator({) + directive(const) pre_type(char) operator(*)ident(f) operator(=) ident(evma_install_oneshot_timer) operator(()ident(FIX2INT) operator(()ident(interval)operator(\)\);) + reserved(if) operator((!)ident(f) operator(||) operator(!*)ident(f)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no timer)delimiter(")>operator(\);) + reserved(return) ident(rb_str_new2) operator(()ident(f)operator(\);) +operator(}) + + +comment(/************** +t_start_server +**************/) + +directive(static) ident(VALUE) ident(t_start_server) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(server)operator(,) ident(VALUE) ident(port)operator(\)) +operator({) + directive(const) pre_type(char) operator(*)ident(f) operator(=) ident(evma_create_tcp_server) operator(()ident(StringValuePtr)operator(()ident(server)operator(\),) ident(FIX2INT)operator(()ident(port)operator(\)\);) + reserved(if) operator((!)ident(f) operator(||) operator(!*)ident(f)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no acceptor)delimiter(")>operator(\);) + reserved(return) ident(rb_str_new2) operator(()ident(f)operator(\);) +operator(}) + +comment(/************* +t_stop_server +*************/) + +directive(static) ident(VALUE) ident(t_stop_server) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(\)) +operator({) + ident(evma_stop_tcp_server) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\)\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + + +comment(/******************* +t_start_unix_server +*******************/) + +directive(static) ident(VALUE) ident(t_start_unix_server) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(filename)operator(\)) +operator({) + directive(const) pre_type(char) operator(*)ident(f) operator(=) ident(evma_create_unix_domain_server) operator(()ident(StringValuePtr)operator(()ident(filename)operator(\)\);) + reserved(if) operator((!)ident(f) operator(||) operator(!*)ident(f)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no unix-domain acceptor)delimiter(")>operator(\);) + reserved(return) ident(rb_str_new2) operator(()ident(f)operator(\);) +operator(}) + + + +comment(/*********** +t_send_data +***********/) + +directive(static) ident(VALUE) ident(t_send_data) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(,) ident(VALUE) ident(data)operator(,) ident(VALUE) ident(data_length)operator(\)) +operator({) + pre_type(int) ident(b) operator(=) ident(evma_send_data_to_connection) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\),) ident(StringValuePtr) operator(()ident(data)operator(\),) ident(FIX2INT) operator(()ident(data_length)operator(\)\);) + reserved(return) ident(INT2NUM) operator(()ident(b)operator(\);) +operator(}) + + +comment(/*********** +t_start_tls +***********/) + +directive(static) ident(VALUE) ident(t_start_tls) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(\)) +operator({) + ident(evma_start_tls) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\)\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/*************** +t_set_tls_parms +***************/) + +directive(static) ident(VALUE) ident(t_set_tls_parms) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(,) ident(VALUE) ident(privkeyfile)operator(,) ident(VALUE) ident(certchainfile)operator(\)) +operator({) + comment(/* 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. + */) + ident(evma_set_tls_parms) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\),) ident(StringValuePtr) operator(()ident(privkeyfile)operator(\),) ident(StringValuePtr) operator(()ident(certchainfile)operator(\)) operator(\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/************** +t_get_peername +**************/) + +directive(static) ident(VALUE) ident(t_get_peername) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(\)) +operator({) + reserved(struct) ident(sockaddr) ident(s)operator(;) + reserved(if) operator(()ident(evma_get_peername) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\),) operator(&)ident(s)operator(\)\)) operator({) + reserved(return) ident(rb_str_new) operator((()directive(const) pre_type(char)operator(*\)&)ident(s)operator(,) reserved(sizeof)operator(()ident(s)operator(\)\);) + operator(}) + + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/************** +t_get_sockname +**************/) + +directive(static) ident(VALUE) ident(t_get_sockname) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(\)) +operator({) + reserved(struct) ident(sockaddr) ident(s)operator(;) + reserved(if) operator(()ident(evma_get_sockname) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\),) operator(&)ident(s)operator(\)\)) operator({) + reserved(return) ident(rb_str_new) operator((()directive(const) pre_type(char)operator(*\)&)ident(s)operator(,) reserved(sizeof)operator(()ident(s)operator(\)\);) + operator(}) + + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/******************** +t_get_subprocess_pid +********************/) + +directive(static) ident(VALUE) ident(t_get_subprocess_pid) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(\)) +operator({) + ident(pid_t) ident(pid)operator(;) + reserved(if) operator(()ident(evma_get_subprocess_pid) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\),) operator(&)ident(pid)operator(\)\)) operator({) + reserved(return) ident(INT2NUM) operator(()ident(pid)operator(\);) + operator(}) + + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/*********************** +t_get_subprocess_status +***********************/) + +directive(static) ident(VALUE) ident(t_get_subprocess_status) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(\)) +operator({) + pre_type(int) ident(status)operator(;) + reserved(if) operator(()ident(evma_get_subprocess_status) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\),) operator(&)ident(status)operator(\)\)) operator({) + reserved(return) ident(INT2NUM) operator(()ident(status)operator(\);) + operator(}) + + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/***************************** +t_get_comm_inactivity_timeout +*****************************/) + +directive(static) ident(VALUE) ident(t_get_comm_inactivity_timeout) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(\)) +operator({) + pre_type(int) ident(timeout)operator(;) + reserved(if) operator(()ident(evma_get_comm_inactivity_timeout) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\),) operator(&)ident(timeout)operator(\)\)) + reserved(return) ident(INT2FIX) operator(()ident(timeout)operator(\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/***************************** +t_set_comm_inactivity_timeout +*****************************/) + +directive(static) ident(VALUE) ident(t_set_comm_inactivity_timeout) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(,) ident(VALUE) ident(timeout)operator(\)) +operator({) + pre_type(int) ident(ti) operator(=) ident(FIX2INT) operator(()ident(timeout)operator(\);) + reserved(if) operator(()ident(evma_set_comm_inactivity_timeout) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\),) operator(&)ident(ti)operator(\)\);) + reserved(return) ident(Qtrue)operator(;) + reserved(return) ident(Qnil)operator(;) +operator(}) + + +comment(/*************** +t_send_datagram +***************/) + +directive(static) ident(VALUE) ident(t_send_datagram) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(,) ident(VALUE) ident(data)operator(,) ident(VALUE) ident(data_length)operator(,) ident(VALUE) ident(address)operator(,) ident(VALUE) ident(port)operator(\)) +operator({) + pre_type(int) ident(b) operator(=) ident(evma_send_datagram) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\),) ident(StringValuePtr) operator(()ident(data)operator(\),) ident(FIX2INT) operator(()ident(data_length)operator(\),) ident(StringValuePtr)operator(()ident(address)operator(\),) ident(FIX2INT)operator(()ident(port)operator(\)\);) + reserved(return) ident(INT2NUM) operator(()ident(b)operator(\);) +operator(}) + + +comment(/****************** +t_close_connection +******************/) + +directive(static) ident(VALUE) ident(t_close_connection) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(,) ident(VALUE) ident(after_writing)operator(\)) +operator({) + ident(evma_close_connection) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\),) operator((()ident(after_writing) operator(==) ident(Qtrue)operator(\)) operator(?) integer(1) operator(:) integer(0)operator(\)\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/******************************** +t_report_connection_error_status +********************************/) + +directive(static) ident(VALUE) ident(t_report_connection_error_status) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(\)) +operator({) + pre_type(int) ident(b) operator(=) ident(evma_report_connection_error_status) operator(()ident(StringValuePtr) operator(()ident(signature)operator(\)\);) + reserved(return) ident(INT2NUM) operator(()ident(b)operator(\);) +operator(}) + + + +comment(/**************** +t_connect_server +****************/) + +directive(static) ident(VALUE) ident(t_connect_server) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(server)operator(,) ident(VALUE) ident(port)operator(\)) +operator({) + comment(// Avoid FIX2INT in this case, because it doesn't deal with type errors properly.) + comment(// Specifically, if the value of port comes in as a string rather than an integer,) + comment(// NUM2INT will throw a type error, but FIX2INT will generate garbage.) + + directive(const) pre_type(char) operator(*)ident(f) operator(=) ident(evma_connect_to_server) operator(()ident(StringValuePtr)operator(()ident(server)operator(\),) ident(NUM2INT)operator(()ident(port)operator(\)\);) + reserved(if) operator((!)ident(f) operator(||) operator(!*)ident(f)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no connection)delimiter(")>operator(\);) + reserved(return) ident(rb_str_new2) operator(()ident(f)operator(\);) +operator(}) + +comment(/********************* +t_connect_unix_server +*********************/) + +directive(static) ident(VALUE) ident(t_connect_unix_server) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(serversocket)operator(\)) +operator({) + directive(const) pre_type(char) operator(*)ident(f) operator(=) ident(evma_connect_to_unix_server) operator(()ident(StringValuePtr)operator(()ident(serversocket)operator(\)\);) + reserved(if) operator((!)ident(f) operator(||) operator(!*)ident(f)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no connection)delimiter(")>operator(\);) + reserved(return) ident(rb_str_new2) operator(()ident(f)operator(\);) +operator(}) + +comment(/*********** +t_attach_fd +***********/) + +directive(static) ident(VALUE) ident(t_attach_fd) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(file_descriptor)operator(,) ident(VALUE) ident(read_mode)operator(,) ident(VALUE) ident(write_mode)operator(\)) +operator({) + directive(const) pre_type(char) operator(*)ident(f) operator(=) ident(evma_attach_fd) operator(()ident(NUM2INT)operator(()ident(file_descriptor)operator(\),) operator(()ident(read_mode) operator(==) ident(Qtrue)operator(\)) operator(?) integer(1) operator(:) integer(0)operator(,) operator(()ident(write_mode) operator(==) ident(Qtrue)operator(\)) operator(?) integer(1) operator(:) integer(0)operator(\);) + reserved(if) operator((!)ident(f) operator(||) operator(!*)ident(f)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no connection)delimiter(")>operator(\);) + reserved(return) ident(rb_str_new2) operator(()ident(f)operator(\);) +operator(}) + +comment(/*********** +t_detach_fd +***********/) + +directive(static) ident(VALUE) ident(t_detach_fd) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(\)) +operator({) + reserved(return) ident(INT2NUM)operator(()ident(evma_detach_fd) operator(()ident(StringValuePtr)operator(()ident(signature)operator(\)\)\);) +operator(}) + +comment(/***************** +t_open_udp_socket +*****************/) + +directive(static) ident(VALUE) ident(t_open_udp_socket) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(server)operator(,) ident(VALUE) ident(port)operator(\)) +operator({) + directive(const) pre_type(char) operator(*)ident(f) operator(=) ident(evma_open_datagram_socket) operator(()ident(StringValuePtr)operator(()ident(server)operator(\),) ident(FIX2INT)operator(()ident(port)operator(\)\);) + reserved(if) operator((!)ident(f) operator(||) operator(!*)ident(f)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no datagram socket)delimiter(")>operator(\);) + reserved(return) ident(rb_str_new2) operator(()ident(f)operator(\);) +operator(}) + + + +comment(/***************** +t_release_machine +*****************/) + +directive(static) ident(VALUE) ident(t_release_machine) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + ident(evma_release_library)operator((\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + + +comment(/****** +t_stop +******/) + +directive(static) ident(VALUE) ident(t_stop) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + ident(evma_stop_machine)operator((\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/****************** +t_signal_loopbreak +******************/) + +directive(static) ident(VALUE) ident(t_signal_loopbreak) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + ident(evma_signal_loopbreak)operator((\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/************** +t_library_type +**************/) + +directive(static) ident(VALUE) ident(t_library_type) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + reserved(return) ident(rb_eval_string) operator(()string<delimiter(")content(:extension)delimiter(")>operator(\);) +operator(}) + + + +comment(/******************* +t_set_timer_quantum +*******************/) + +directive(static) ident(VALUE) ident(t_set_timer_quantum) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(interval)operator(\)) +operator({) + ident(evma_set_timer_quantum) operator(()ident(FIX2INT) operator(()ident(interval)operator(\)\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/******************** +t_set_max_timer_count +********************/) + +directive(static) ident(VALUE) ident(t_set_max_timer_count) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(ct)operator(\)) +operator({) + ident(evma_set_max_timer_count) operator(()ident(FIX2INT) operator(()ident(ct)operator(\)\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/*************** +t_setuid_string +***************/) + +directive(static) ident(VALUE) ident(t_setuid_string) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(username)operator(\)) +operator({) + ident(evma_setuid_string) operator(()ident(StringValuePtr) operator(()ident(username)operator(\)\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + + + +comment(/************* +t__write_file +*************/) + +directive(static) ident(VALUE) ident(t__write_file) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(filename)operator(\)) +operator({) + directive(const) pre_type(char) operator(*)ident(f) operator(=) ident(evma__write_file) operator(()ident(StringValuePtr) operator(()ident(filename)operator(\)\);) + reserved(if) operator((!)ident(f) operator(||) operator(!*)ident(f)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(file not opened)delimiter(")>operator(\);) + reserved(return) ident(rb_str_new2) operator(()ident(f)operator(\);) +operator(}) + +comment(/************** +t_invoke_popen +**************/) + +directive(static) ident(VALUE) ident(t_invoke_popen) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(cmd)operator(\)) +operator({) + comment(// 1.8.7+) + preprocessor(#ifdef) ident(RARRAY_LEN) + pre_type(int) ident(len) operator(=) ident(RARRAY_LEN)operator(()ident(cmd)operator(\);) + preprocessor(#else) + pre_type(int) ident(len) operator(=) ident(RARRAY) operator(()ident(cmd)operator(\)->)ident(len)operator(;) + preprocessor(#endif) + reserved(if) operator(()ident(len) operator(>) integer(98)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(too many arguments to popen)delimiter(")>operator(\);) + pre_type(char) operator(*)ident(strings) operator([)integer(100)operator(];) + reserved(for) operator(()pre_type(int) ident(i)operator(=)integer(0)operator(;) ident(i) operator(<) ident(len)operator(;) ident(i)operator(++\)) operator({) + ident(VALUE) ident(ix) operator(=) ident(INT2FIX) operator(()ident(i)operator(\);) + ident(VALUE) ident(s) operator(=) ident(rb_ary_aref) operator(()integer(1)operator(,) operator(&)ident(ix)operator(,) ident(cmd)operator(\);) + ident(strings)operator([)ident(i)operator(]) operator(=) ident(StringValuePtr) operator(()ident(s)operator(\);) + operator(}) + ident(strings)operator([)ident(len)operator(]) operator(=) pre_constant(NULL)operator(;) + + directive(const) pre_type(char) operator(*)ident(f) operator(=) ident(evma_popen) operator(()ident(strings)operator(\);) + reserved(if) operator((!)ident(f) operator(||) operator(!*)ident(f)operator(\)) operator({) + pre_type(char) operator(*)ident(err) operator(=) ident(strerror) operator(()ident(errno)operator(\);) + pre_type(char) ident(buf)operator([)integer(100)operator(];) + ident(memset) operator(()ident(buf)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(buf)operator(\)\);) + ident(snprintf) operator(()ident(buf)operator(,) reserved(sizeof)operator(()ident(buf)operator(\)-)integer(1)operator(,) string<delimiter(")content(no popen: %s)delimiter(")>operator(,) operator(()ident(err)operator(?)ident(err)operator(:)string<delimiter(")content(???)delimiter(")>operator(\)\);) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) ident(buf)operator(\);) + operator(}) + reserved(return) ident(rb_str_new2) operator(()ident(f)operator(\);) +operator(}) + + +comment(/*************** +t_read_keyboard +***************/) + +directive(static) ident(VALUE) ident(t_read_keyboard) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + directive(const) pre_type(char) operator(*)ident(f) operator(=) ident(evma_open_keyboard)operator((\);) + reserved(if) operator((!)ident(f) operator(||) operator(!*)ident(f)operator(\)) + ident(rb_raise) operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(no keyboard reader)delimiter(")>operator(\);) + reserved(return) ident(rb_str_new2) operator(()ident(f)operator(\);) +operator(}) + + +comment(/******** +t__epoll +********/) + +directive(static) ident(VALUE) ident(t__epoll) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + comment(// Temporary.) + ident(evma__epoll)operator((\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/********** +t__epoll_p +**********/) + +directive(static) ident(VALUE) ident(t__epoll_p) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + preprocessor(#ifdef) ident(HAVE_EPOLL) + reserved(return) ident(Qtrue)operator(;) + preprocessor(#else) + reserved(return) ident(Qfalse)operator(;) + preprocessor(#endif) +operator(}) + + +comment(/********* +t__kqueue +*********/) + +directive(static) ident(VALUE) ident(t__kqueue) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + comment(// Temporary.) + ident(evma__kqueue)operator((\);) + reserved(return) ident(Qnil)operator(;) +operator(}) + +comment(/*********** +t__kqueue_p +***********/) + +directive(static) ident(VALUE) ident(t__kqueue_p) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + preprocessor(#ifdef) ident(HAVE_KQUEUE) + reserved(return) ident(Qtrue)operator(;) + preprocessor(#else) + reserved(return) ident(Qfalse)operator(;) + preprocessor(#endif) +operator(}) + + +comment(/**************** +t_send_file_data +****************/) + +directive(static) ident(VALUE) ident(t_send_file_data) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(signature)operator(,) ident(VALUE) ident(filename)operator(\)) +operator({) + + comment(/* The current implementation of evma_send_file_data_to_connection enforces a strict + * upper limit on the file size it will transmit (currently 32K\). The function returns + * zero on success, -1 if the requested file exceeds its size limit, and a positive + * number for other errors. + * TODO: Positive return values are actually errno's, which is probably the wrong way to + * do this. For one thing it's ugly. For another, we can't be sure zero is never a real errno. + */) + + pre_type(int) ident(b) operator(=) ident(evma_send_file_data_to_connection) operator(()ident(StringValuePtr)operator(()ident(signature)operator(\),) ident(StringValuePtr)operator(()ident(filename)operator(\)\);) + reserved(if) operator(()ident(b) operator(==) operator(-)integer(1)operator(\)) + ident(rb_raise)operator(()ident(rb_eRuntimeError)operator(,) string<delimiter(")content(File too large. send_file_data(\) supports files under 32k.)delimiter(")>operator(\);) + reserved(if) operator(()ident(b) operator(>) integer(0)operator(\)) operator({) + pre_type(char) operator(*)ident(err) operator(=) ident(strerror) operator(()ident(b)operator(\);) + pre_type(char) ident(buf)operator([)integer(1024)operator(];) + ident(memset) operator(()ident(buf)operator(,) integer(0)operator(,) reserved(sizeof)operator(()ident(buf)operator(\)\);) + ident(snprintf) operator(()ident(buf)operator(,) reserved(sizeof)operator(()ident(buf)operator(\)-)integer(1)operator(,) string<delimiter(")content(: %s %s)delimiter(")>operator(,) ident(StringValuePtr)operator(()ident(filename)operator(\),()ident(err)operator(?)ident(err)operator(:)string<delimiter(")content(???)delimiter(")>operator(\)\);) + + ident(rb_raise) operator(()ident(rb_eIOError)operator(,) ident(buf)operator(\);) + operator(}) + + reserved(return) ident(INT2NUM) operator(()integer(0)operator(\);) +operator(}) + + +comment(/******************* +t_set_rlimit_nofile +*******************/) + +directive(static) ident(VALUE) ident(t_set_rlimit_nofile) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(arg)operator(\)) +operator({) + ident(arg) operator(=) operator(()ident(NIL_P)operator(()ident(arg)operator(\)\)) operator(?) operator(-)integer(1) operator(:) ident(NUM2INT) operator(()ident(arg)operator(\);) + reserved(return) ident(INT2NUM) operator(()ident(evma_set_rlimit_nofile) operator(()ident(arg)operator(\)\);) +operator(}) + +comment(/*************************** +conn_get_outbound_data_size +***************************/) + +directive(static) ident(VALUE) ident(conn_get_outbound_data_size) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + ident(VALUE) ident(sig) operator(=) ident(rb_ivar_get) operator(()ident(self)operator(,) ident(Intern_at_signature)operator(\);) + reserved(return) ident(INT2NUM) operator(()ident(evma_get_outbound_data_size) operator(()ident(StringValuePtr)operator(()ident(sig)operator(\)\)\);) +operator(}) + + +comment(/****************************** +conn_associate_callback_target +******************************/) + +directive(static) ident(VALUE) ident(conn_associate_callback_target) operator(()ident(VALUE) ident(self)operator(,) ident(VALUE) ident(sig)operator(\)) +operator({) + comment(// No-op for the time being.) + reserved(return) ident(Qnil)operator(;) +operator(}) + + +comment(/*************** +t_get_loop_time +****************/) + +directive(static) ident(VALUE) ident(t_get_loop_time) operator(()ident(VALUE) ident(self)operator(\)) +operator({) + ident(VALUE) ident(cTime) operator(=) ident(rb_path2class)operator(()string<delimiter(")content(Time)delimiter(")>operator(\);) + reserved(if) operator(()ident(gCurrentLoopTime) operator(!=) integer(0)operator(\)) operator({) + reserved(return) ident(rb_funcall)operator(()ident(cTime)operator(,) + ident(rb_intern)operator(()string<delimiter(")content(at)delimiter(")>operator(\),) + integer(1)operator(,) + ident(INT2NUM)operator(()ident(gCurrentLoopTime)operator(\)\);) + operator(}) + reserved(return) ident(Qnil)operator(;) +operator(}) + + +comment(/********************* +Init_rubyeventmachine +*********************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> directive(void) ident(Init_rubyeventmachine)operator((\)) +operator({) + comment(// Tuck away some symbol values so we don't have to look 'em up every time we need 'em.) + ident(Intern_at_signature) operator(=) ident(rb_intern) operator(()string<delimiter(")content(@signature)delimiter(")>operator(\);) + ident(Intern_at_timers) operator(=) ident(rb_intern) operator(()string<delimiter(")content(@timers)delimiter(")>operator(\);) + ident(Intern_at_conns) operator(=) ident(rb_intern) operator(()string<delimiter(")content(@conns)delimiter(")>operator(\);) + + ident(Intern_event_callback) operator(=) ident(rb_intern) operator(()string<delimiter(")content(event_callback)delimiter(")>operator(\);) + ident(Intern_run_deferred_callbacks) operator(=) ident(rb_intern) operator(()string<delimiter(")content(run_deferred_callbacks)delimiter(")>operator(\);) + ident(Intern_delete) operator(=) ident(rb_intern) operator(()string<delimiter(")content(delete)delimiter(")>operator(\);) + ident(Intern_call) operator(=) ident(rb_intern) operator(()string<delimiter(")content(call)delimiter(")>operator(\);) + ident(Intern_receive_data) operator(=) ident(rb_intern) operator(()string<delimiter(")content(receive_data)delimiter(")>operator(\);) + + ident(Intern_notify_readable) operator(=) ident(rb_intern) operator(()string<delimiter(")content(notify_readable)delimiter(")>operator(\);) + ident(Intern_notify_writable) operator(=) ident(rb_intern) operator(()string<delimiter(")content(notify_writable)delimiter(")>operator(\);) + + comment(// INCOMPLETE, we need to define class Connections inside module EventMachine) + comment(// run_machine and run_machine_without_threads are now identical.) + comment(// Must deprecate the without_threads variant.) + ident(EmModule) operator(=) ident(rb_define_module) operator(()string<delimiter(")content(EventMachine)delimiter(")>operator(\);) + ident(EmConnection) operator(=) ident(rb_define_class_under) operator(()ident(EmModule)operator(,) string<delimiter(")content(Connection)delimiter(")>operator(,) ident(rb_cObject)operator(\);) + + ident(rb_define_class_under) operator(()ident(EmModule)operator(,) string<delimiter(")content(ConnectionNotBound)delimiter(")>operator(,) ident(rb_eException)operator(\);) + ident(rb_define_class_under) operator(()ident(EmModule)operator(,) string<delimiter(")content(NoHandlerForAcceptedConnection)delimiter(")>operator(,) ident(rb_eException)operator(\);) + ident(rb_define_class_under) operator(()ident(EmModule)operator(,) string<delimiter(")content(UnknownTimerFired)delimiter(")>operator(,) ident(rb_eException)operator(\);) + + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(initialize_event_machine)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_initialize_event_machine)operator(,) integer(0)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(run_machine)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_run_machine_without_threads)operator(,) integer(0)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(run_machine_without_threads)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_run_machine_without_threads)operator(,) integer(0)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(add_oneshot_timer)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_add_oneshot_timer)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(start_tcp_server)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_start_server)operator(,) integer(2)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(stop_tcp_server)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_stop_server)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(start_unix_server)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_start_unix_server)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(set_tls_parms)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_set_tls_parms)operator(,) integer(3)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(start_tls)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_start_tls)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(send_data)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_send_data)operator(,) integer(3)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(send_datagram)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_send_datagram)operator(,) integer(5)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(close_connection)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_close_connection)operator(,) integer(2)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(report_connection_error_status)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_report_connection_error_status)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(connect_server)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_connect_server)operator(,) integer(2)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(connect_unix_server)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_connect_unix_server)operator(,) integer(1)operator(\);) + + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(attach_fd)delimiter(")>operator(,) operator(()ident(VALUE) operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_attach_fd)operator(,) integer(3)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(detach_fd)delimiter(")>operator(,) operator(()ident(VALUE) operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_detach_fd)operator(,) integer(1)operator(\);) + + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(current_time)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_get_loop_time)operator(,) integer(0)operator(\);) + + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(open_udp_socket)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_open_udp_socket)operator(,) integer(2)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(read_keyboard)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_read_keyboard)operator(,) integer(0)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(release_machine)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_release_machine)operator(,) integer(0)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(stop)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_stop)operator(,) integer(0)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(signal_loopbreak)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_signal_loopbreak)operator(,) integer(0)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(library_type)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_library_type)operator(,) integer(0)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(set_timer_quantum)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_set_timer_quantum)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(set_max_timer_count)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_set_max_timer_count)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(setuid_string)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_setuid_string)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(invoke_popen)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_invoke_popen)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(send_file_data)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_send_file_data)operator(,) integer(2)operator(\);) + + comment(// Provisional:) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(_write_file)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t__write_file)operator(,) integer(1)operator(\);) + + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(get_peername)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_get_peername)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(get_sockname)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_get_sockname)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(get_subprocess_pid)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_get_subprocess_pid)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(get_subprocess_status)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_get_subprocess_status)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(get_comm_inactivity_timeout)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_get_comm_inactivity_timeout)operator(,) integer(1)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(set_comm_inactivity_timeout)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_set_comm_inactivity_timeout)operator(,) integer(2)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(set_rlimit_nofile)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t_set_rlimit_nofile)operator(,) integer(1)operator(\);) + + comment(// Temporary:) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(epoll)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t__epoll)operator(,) integer(0)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(kqueue)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t__kqueue)operator(,) integer(0)operator(\);) + + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(epoll?)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t__epoll_p)operator(,) integer(0)operator(\);) + ident(rb_define_module_function) operator(()ident(EmModule)operator(,) string<delimiter(")content(kqueue?)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(t__kqueue_p)operator(,) integer(0)operator(\);) + + ident(rb_define_method) operator(()ident(EmConnection)operator(,) string<delimiter(")content(get_outbound_data_size)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(conn_get_outbound_data_size)operator(,) integer(0)operator(\);) + ident(rb_define_method) operator(()ident(EmConnection)operator(,) string<delimiter(")content(associate_callback_target)delimiter(")>operator(,) operator(()ident(VALUE)operator((*\)()operator(.)operator(.)operator(.)operator(\)\))ident(conn_associate_callback_target)operator(,) integer(1)operator(\);) + + ident(rb_define_const) operator(()ident(EmModule)operator(,) string<delimiter(")content(TimerFired)delimiter(")>operator(,) ident(INT2NUM)operator(()integer(100)operator(\)\);) + ident(rb_define_const) operator(()ident(EmModule)operator(,) string<delimiter(")content(ConnectionData)delimiter(")>operator(,) ident(INT2NUM)operator(()integer(101)operator(\)\);) + ident(rb_define_const) operator(()ident(EmModule)operator(,) string<delimiter(")content(ConnectionUnbound)delimiter(")>operator(,) ident(INT2NUM)operator(()integer(102)operator(\)\);) + ident(rb_define_const) operator(()ident(EmModule)operator(,) string<delimiter(")content(ConnectionAccepted)delimiter(")>operator(,) ident(INT2NUM)operator(()integer(103)operator(\)\);) + ident(rb_define_const) operator(()ident(EmModule)operator(,) string<delimiter(")content(ConnectionCompleted)delimiter(")>operator(,) ident(INT2NUM)operator(()integer(104)operator(\)\);) + ident(rb_define_const) operator(()ident(EmModule)operator(,) string<delimiter(")content(LoopbreakSignalled)delimiter(")>operator(,) ident(INT2NUM)operator(()integer(105)operator(\)\);) + + ident(rb_define_const) operator(()ident(EmModule)operator(,) string<delimiter(")content(ConnectionNotifyReadable)delimiter(")>operator(,) ident(INT2NUM)operator(()integer(106)operator(\)\);) + ident(rb_define_const) operator(()ident(EmModule)operator(,) string<delimiter(")content(ConnectionNotifyWritable)delimiter(")>operator(,) ident(INT2NUM)operator(()integer(107)operator(\)\);) + +operator(}) + +comment(/***************************************************************************** + +$Id$ + +File: sigs.cpp +Date: 06Apr06 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + +preprocessor(#include) include("project.h") + + +pre_type(bool) ident(gTerminateSignalReceived)operator(;) + + +comment(/************** +SigtermHandler +**************/) + +directive(void) ident(SigtermHandler) operator(()pre_type(int) ident(sig)operator(\)) +operator({) + comment(// This is a signal-handler, don't do anything frisky. Interrupts are disabled.) + comment(// Set the terminate flag WITHOUT trying to lock a mutex- otherwise we can easily) + comment(// self-deadlock, especially if the event machine is looping quickly.) + ident(gTerminateSignalReceived) operator(=) pre_constant(true)operator(;) +operator(}) + + +comment(/********************* +InstallSignalHandlers +*********************/) + +directive(void) ident(InstallSignalHandlers)operator((\)) +operator({) + preprocessor(#ifdef) ident(OS_UNIX) + directive(static) pre_type(bool) ident(bInstalled) operator(=) pre_constant(false)operator(;) + reserved(if) operator((!)ident(bInstalled)operator(\)) operator({) + ident(bInstalled) operator(=) pre_constant(true)operator(;) + ident(signal) operator(()ident(SIGINT)operator(,) ident(SigtermHandler)operator(\);) + ident(signal) operator(()ident(SIGTERM)operator(,) ident(SigtermHandler)operator(\);) + ident(signal) operator(()ident(SIGPIPE)operator(,) ident(SIG_IGN)operator(\);) + operator(}) + preprocessor(#endif) +operator(}) + + + +comment(/******************* +WintelSignalHandler +*******************/) + +preprocessor(#ifdef) ident(OS_WIN32) +ident(BOOL) ident(WINAPI) ident(WintelSignalHandler) operator(()ident(DWORD) ident(control)operator(\)) +operator({) + reserved(if) operator(()ident(control) operator(==) ident(CTRL_C_EVENT)operator(\)) + ident(gTerminateSignalReceived) operator(=) pre_constant(true)operator(;) + reserved(return) ident(TRUE)operator(;) +operator(}) +preprocessor(#endif) + +comment(/************ +HookControlC +************/) + +preprocessor(#ifdef) ident(OS_WIN32) +directive(void) ident(HookControlC) operator(()pre_type(bool) ident(hook)operator(\)) +operator({) + reserved(if) operator(()ident(hook)operator(\)) operator({) + comment(// INSTALL hook) + ident(SetConsoleCtrlHandler) operator(()ident(WintelSignalHandler)operator(,) ident(TRUE)operator(\);) + operator(}) + reserved(else) operator({) + comment(// UNINSTALL hook) + ident(SetConsoleCtrlHandler) operator(()ident(WintelSignalHandler)operator(,) ident(FALSE)operator(\);) + operator(}) +operator(}) +preprocessor(#endif) + + +comment(/***************************************************************************** + +$Id$ + +File: ssl.cpp +Date: 30Apr06 + +Copyright (C\) 2006-07 by Francis Cianfrocca. All Rights Reserved. +Gmail: blackhedd + +This program is free software; you can redistribute it and/or modify +it under the terms of either: 1\) the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option\) any later version; or 2\) Ruby's License. + +See the file COPYING for complete licensing information. + +*****************************************************************************/) + + +preprocessor(#ifdef) ident(WITH_SSL) + +preprocessor(#include) include("project.h") + + +pre_type(bool) ident(SslContext_t)operator(::)ident(bLibraryInitialized) operator(=) pre_constant(false)operator(;) + + + +directive(static) directive(void) ident(InitializeDefaultCredentials)operator((\);) +directive(static) ident(EVP_PKEY) operator(*)ident(DefaultPrivateKey) operator(=) pre_constant(NULL)operator(;) +directive(static) ident(X509) operator(*)ident(DefaultCertificate) operator(=) pre_constant(NULL)operator(;) + +directive(static) pre_type(char) ident(PrivateMaterials)operator([]) operator(=) operator({) +string<delimiter(")content(-----BEGIN RSA PRIVATE KEY-----)char(\\n)delimiter(")> +string<delimiter(")content(MIICXAIBAAKBgQDCYYhcw6cGRbhBVShKmbWm7UVsEoBnUf0cCh8AX+MKhMxwVDWV)char(\\n)delimiter(")> +string<delimiter(")content(Igdskntn3cSJjRtmgVJHIK0lpb/FYHQB93Ohpd9/Z18pDmovfFF9nDbFF0t39hJ/)char(\\n)delimiter(")> +string<delimiter(")content(AqSzFB3GiVPoFFZJEE1vJqh+3jzsSF5K56bZ6azz38VlZgXeSozNW5bXkQIDAQAB)char(\\n)delimiter(")> +string<delimiter(")content(AoGALA89gIFcr6BIBo8N5fL3aNHpZXjAICtGav+kTUpuxSiaym9cAeTHuAVv8Xgk)char(\\n)delimiter(")> +string<delimiter(")content(H2Wbq11uz+6JMLpkQJH/WZ7EV59DPOicXrp0Imr73F3EXBfR7t2EQDYHPMthOA1D)char(\\n)delimiter(")> +string<delimiter(")content(I9EtCzvV608Ze90hiJ7E3guGrGppZfJ+eUWCPgy8CZH1vRECQQDv67rwV/oU1aDo)char(\\n)delimiter(")> +string<delimiter(")content(6/+d5nqjeW6mWkGqTnUU96jXap8EIw6B+0cUKskwx6mHJv+tEMM2748ZY7b0yBlg)char(\\n)delimiter(")> +string<delimiter(")content(w4KDghbFAkEAz2h8PjSJG55LwqmXih1RONSgdN9hjB12LwXL1CaDh7/lkEhq0PlK)char(\\n)delimiter(")> +string<delimiter(")content(PCAUwQSdM17Sl0Xxm2CZiekTSlwmHrtqXQJAF3+8QJwtV2sRJp8u2zVe37IeH1cJ)char(\\n)delimiter(")> +string<delimiter(")content(xXeHyjTzqZ2803fnjN2iuZvzNr7noOA1/Kp+pFvUZUU5/0G2Ep8zolPUjQJAFA7k)char(\\n)delimiter(")> +string<delimiter(")content(xRdLkzIx3XeNQjwnmLlncyYPRv+qaE3FMpUu7zftuZBnVCJnvXzUxP3vPgKTlzGa)char(\\n)delimiter(")> +string<delimiter(")content(dg5XivDRfsV+okY5uQJBAMV4FesUuLQVEKb6lMs7rzZwpeGQhFDRfywJzfom2TLn)char(\\n)delimiter(")> +string<delimiter(")content(2RdJQQ3dcgnhdVDgt5o1qkmsqQh8uJrJ9SdyLIaZQIc=)char(\\n)delimiter(")> +string<delimiter(")content(-----END RSA PRIVATE KEY-----)char(\\n)delimiter(")> +string<delimiter(")content(-----BEGIN CERTIFICATE-----)char(\\n)delimiter(")> +string<delimiter(")content(MIID6TCCA1KgAwIBAgIJANm4W/Tzs+s+MA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD)char(\\n)delimiter(")> +string<delimiter(")content(VQQGEwJVUzERMA8GA1UECBMITmV3IFlvcmsxETAPBgNVBAcTCE5ldyBZb3JrMRYw)char(\\n)delimiter(")> +string<delimiter(")content(FAYDVQQKEw1TdGVhbWhlYXQubmV0MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEdMBsG)char(\\n)delimiter(")> +string<delimiter(")content(A1UEAxMUb3BlbmNhLnN0ZWFtaGVhdC5uZXQxKDAmBgkqhkiG9w0BCQEWGWVuZ2lu)char(\\n)delimiter(")> +string<delimiter(")content(ZWVyaW5nQHN0ZWFtaGVhdC5uZXQwHhcNMDYwNTA1MTcwNjAzWhcNMjQwMjIwMTcw)char(\\n)delimiter(")> +string<delimiter(")content(NjAzWjCBqjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQH)char(\\n)delimiter(")> +string<delimiter(")content(EwhOZXcgWW9yazEWMBQGA1UEChMNU3RlYW1oZWF0Lm5ldDEUMBIGA1UECxMLRW5n)char(\\n)delimiter(")> +string<delimiter(")content(aW5lZXJpbmcxHTAbBgNVBAMTFG9wZW5jYS5zdGVhbWhlYXQubmV0MSgwJgYJKoZI)char(\\n)delimiter(")> +string<delimiter(")content(hvcNAQkBFhllbmdpbmVlcmluZ0BzdGVhbWhlYXQubmV0MIGfMA0GCSqGSIb3DQEB)char(\\n)delimiter(")> +string<delimiter(")content(AQUAA4GNADCBiQKBgQDCYYhcw6cGRbhBVShKmbWm7UVsEoBnUf0cCh8AX+MKhMxw)char(\\n)delimiter(")> +string<delimiter(")content(VDWVIgdskntn3cSJjRtmgVJHIK0lpb/FYHQB93Ohpd9/Z18pDmovfFF9nDbFF0t3)char(\\n)delimiter(")> +string<delimiter(")content(9hJ/AqSzFB3GiVPoFFZJEE1vJqh+3jzsSF5K56bZ6azz38VlZgXeSozNW5bXkQID)char(\\n)delimiter(")> +string<delimiter(")content(AQABo4IBEzCCAQ8wHQYDVR0OBBYEFPJvPd1Fcmd8o/Tm88r+NjYPICCkMIHfBgNV)char(\\n)delimiter(")> +string<delimiter(")content(HSMEgdcwgdSAFPJvPd1Fcmd8o/Tm88r+NjYPICCkoYGwpIGtMIGqMQswCQYDVQQG)char(\\n)delimiter(")> +string<delimiter(")content(EwJVUzERMA8GA1UECBMITmV3IFlvcmsxETAPBgNVBAcTCE5ldyBZb3JrMRYwFAYD)char(\\n)delimiter(")> +string<delimiter(")content(VQQKEw1TdGVhbWhlYXQubmV0MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEdMBsGA1UE)char(\\n)delimiter(")> +string<delimiter(")content(AxMUb3BlbmNhLnN0ZWFtaGVhdC5uZXQxKDAmBgkqhkiG9w0BCQEWGWVuZ2luZWVy)char(\\n)delimiter(")> +string<delimiter(")content(aW5nQHN0ZWFtaGVhdC5uZXSCCQDZuFv087PrPjAMBgNVHRMEBTADAQH/MA0GCSqG)char(\\n)delimiter(")> +string<delimiter(")content(SIb3DQEBBQUAA4GBAC1CXey/4UoLgJiwcEMDxOvW74plks23090iziFIlGgcIhk0)char(\\n)delimiter(")> +string<delimiter(")content(Df6hTAs7H3MWww62ddvR8l07AWfSzSP5L6mDsbvq7EmQsmPODwb6C+i2aF3EDL8j)char(\\n)delimiter(")> +string<delimiter(")content(uw73m4YIGI0Zw2XdBpiOGkx2H56Kya6mJJe/5XORZedh1wpI7zki01tHYbcy)char(\\n)delimiter(")> +string<delimiter(")content(-----END CERTIFICATE-----)char(\\n)delimiter(")>operator(};) + +comment(/* These private materials were made with: + * openssl req -new -x509 -keyout cakey.pem -out cacert.pem -nodes -days 6500 + * TODO: We need a full-blown capability to work with user-supplied + * keypairs and properly-signed certificates. + */) + + +comment(/***************** +builtin_passwd_cb +*****************/) + +directive(extern) string<delimiter(")content(C)delimiter(")> pre_type(int) ident(builtin_passwd_cb) operator(()pre_type(char) operator(*)ident(buf)operator(,) pre_type(int) ident(bufsize)operator(,) pre_type(int) ident(rwflag)operator(,) directive(void) operator(*)ident(userdata)operator(\)) +operator({) + ident(strcpy) operator(()ident(buf)operator(,) string<delimiter(")content(kittycat)delimiter(")>operator(\);) + reserved(return) integer(8)operator(;) +operator(}) + +comment(/**************************** +InitializeDefaultCredentials +****************************/) + +directive(static) directive(void) ident(InitializeDefaultCredentials)operator((\)) +operator({) + ident(BIO) operator(*)ident(bio) operator(=) ident(BIO_new_mem_buf) operator(()ident(PrivateMaterials)operator(,) operator(-)integer(1)operator(\);) + ident(assert) operator(()ident(bio)operator(\);) + + reserved(if) operator(()ident(DefaultPrivateKey)operator(\)) operator({) + comment(// we may come here in a restart.) + ident(EVP_PKEY_free) operator(()ident(DefaultPrivateKey)operator(\);) + ident(DefaultPrivateKey) operator(=) pre_constant(NULL)operator(;) + operator(}) + ident(PEM_read_bio_PrivateKey) operator(()ident(bio)operator(,) operator(&)ident(DefaultPrivateKey)operator(,) ident(builtin_passwd_cb)operator(,) integer(0)operator(\);) + + reserved(if) operator(()ident(DefaultCertificate)operator(\)) operator({) + comment(// we may come here in a restart.) + ident(X509_free) operator(()ident(DefaultCertificate)operator(\);) + ident(DefaultCertificate) operator(=) pre_constant(NULL)operator(;) + operator(}) + ident(PEM_read_bio_X509) operator(()ident(bio)operator(,) operator(&)ident(DefaultCertificate)operator(,) pre_constant(NULL)operator(,) integer(0)operator(\);) + + ident(BIO_free) operator(()ident(bio)operator(\);) +operator(}) + + + +comment(/************************** +SslContext_t::SslContext_t +**************************/) + +ident(SslContext_t)operator(::)ident(SslContext_t) operator(()pre_type(bool) ident(is_server)operator(,) directive(const) pre_type(string) operator(&)ident(privkeyfile)operator(,) directive(const) pre_type(string) operator(&)ident(certchainfile)operator(\):) + ident(pCtx) operator(()pre_constant(NULL)operator(\),) + ident(PrivateKey) operator(()pre_constant(NULL)operator(\),) + ident(Certificate) operator(()pre_constant(NULL)operator(\)) +operator({) + comment(/* TODO: the usage of the specified private-key and cert-chain filenames only applies to + * client-side connections at this point. Server connections currently use the default materials. + * That needs to be fixed asap. + * Also, in this implementation, server-side connections use statically defined X-509 defaults. + * One thing I'm really not clear on is whether or not you have to explicitly free X509 and EVP_PKEY + * objects when we call our destructor, or whether just calling SSL_CTX_free is enough. + */) + + reserved(if) operator((!)ident(bLibraryInitialized)operator(\)) operator({) + ident(bLibraryInitialized) operator(=) pre_constant(true)operator(;) + ident(SSL_library_init)operator((\);) + ident(OpenSSL_add_ssl_algorithms)operator((\);) + ident(OpenSSL_add_all_algorithms)operator((\);) + ident(SSL_load_error_strings)operator((\);) + ident(ERR_load_crypto_strings)operator((\);) + + ident(InitializeDefaultCredentials)operator((\);) + operator(}) + + ident(bIsServer) operator(=) ident(is_server)operator(;) + ident(pCtx) operator(=) ident(SSL_CTX_new) operator(()ident(is_server) operator(?) ident(SSLv23_server_method)operator((\)) operator(:) ident(SSLv23_client_method)operator((\)\);) + reserved(if) operator((!)ident(pCtx)operator(\)) + reserved(throw) ident(std)operator(::)ident(runtime_error) operator(()string<delimiter(")content(no SSL context)delimiter(")>operator(\);) + + ident(SSL_CTX_set_options) operator(()ident(pCtx)operator(,) ident(SSL_OP_ALL)operator(\);) + comment(//SSL_CTX_set_options (pCtx, (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3\)\);) + + reserved(if) operator(()ident(is_server)operator(\)) operator({) + comment(// The SSL_CTX calls here do NOT allocate memory.) + pre_type(int) ident(e)operator(;) + reserved(if) operator(()ident(privkeyfile)operator(.)ident(length)operator((\)) operator(>) integer(0)operator(\)) + ident(e) operator(=) ident(SSL_CTX_use_PrivateKey_file) operator(()ident(pCtx)operator(,) ident(privkeyfile)operator(.)ident(c_str)operator((\),) ident(SSL_FILETYPE_PEM)operator(\);) + reserved(else) + ident(e) operator(=) ident(SSL_CTX_use_PrivateKey) operator(()ident(pCtx)operator(,) ident(DefaultPrivateKey)operator(\);) + ident(assert) operator(()ident(e) operator(>) integer(0)operator(\);) + reserved(if) operator(()ident(certchainfile)operator(.)ident(length)operator((\)) operator(>) integer(0)operator(\)) + ident(e) operator(=) ident(SSL_CTX_use_certificate_chain_file) operator(()ident(pCtx)operator(,) ident(certchainfile)operator(.)ident(c_str)operator((\)\);) + reserved(else) + ident(e) operator(=) ident(SSL_CTX_use_certificate) operator(()ident(pCtx)operator(,) ident(DefaultCertificate)operator(\);) + ident(assert) operator(()ident(e) operator(>) integer(0)operator(\);) + operator(}) + + ident(SSL_CTX_set_cipher_list) operator(()ident(pCtx)operator(,) string<delimiter(")content(ALL:!ADH:!LOW:!EXP:!DES-CBC3-SHA:@STRENGTH)delimiter(")>operator(\);) + + reserved(if) operator(()ident(is_server)operator(\)) operator({) + ident(SSL_CTX_sess_set_cache_size) operator(()ident(pCtx)operator(,) integer(128)operator(\);) + ident(SSL_CTX_set_session_id_context) operator(()ident(pCtx)operator(,) operator(()pre_type(unsigned) pre_type(char)operator(*\))string<delimiter(")content(eventmachine)delimiter(")>operator(,) integer(12)operator(\);) + operator(}) + reserved(else) operator({) + pre_type(int) ident(e)operator(;) + reserved(if) operator(()ident(privkeyfile)operator(.)ident(length)operator((\)) operator(>) integer(0)operator(\)) operator({) + ident(e) operator(=) ident(SSL_CTX_use_PrivateKey_file) operator(()ident(pCtx)operator(,) ident(privkeyfile)operator(.)ident(c_str)operator((\),) ident(SSL_FILETYPE_PEM)operator(\);) + ident(assert) operator(()ident(e) operator(>) integer(0)operator(\);) + operator(}) + reserved(if) operator(()ident(certchainfile)operator(.)ident(length)operator((\)) operator(>) integer(0)operator(\)) operator({) + ident(e) operator(=) ident(SSL_CTX_use_certificate_chain_file) operator(()ident(pCtx)operator(,) ident(certchainfile)operator(.)ident(c_str)operator((\)\);) + ident(assert) operator(()ident(e) operator(>) integer(0)operator(\);) + operator(}) + operator(}) +operator(}) + + + +comment(/*************************** +SslContext_t::~SslContext_t +***************************/) + +ident(SslContext_t)operator(::~)ident(SslContext_t)operator((\)) +operator({) + reserved(if) operator(()ident(pCtx)operator(\)) + ident(SSL_CTX_free) operator(()ident(pCtx)operator(\);) + reserved(if) operator(()ident(PrivateKey)operator(\)) + ident(EVP_PKEY_free) operator(()ident(PrivateKey)operator(\);) + reserved(if) operator(()ident(Certificate)operator(\)) + ident(X509_free) operator(()ident(Certificate)operator(\);) +operator(}) + + + +comment(/****************** +SslBox_t::SslBox_t +******************/) + +ident(SslBox_t)operator(::)ident(SslBox_t) operator(()pre_type(bool) ident(is_server)operator(,) directive(const) pre_type(string) operator(&)ident(privkeyfile)operator(,) directive(const) pre_type(string) operator(&)ident(certchainfile)operator(\):) + ident(bIsServer) operator(()ident(is_server)operator(\),) + ident(pSSL) operator(()pre_constant(NULL)operator(\),) + ident(pbioRead) operator(()pre_constant(NULL)operator(\),) + ident(pbioWrite) operator(()pre_constant(NULL)operator(\)) +operator({) + comment(/* TODO someday: make it possible to re-use SSL contexts so we don't have to create + * a new one every time we come here. + */) + + ident(Context) operator(=) reserved(new) ident(SslContext_t) operator(()ident(bIsServer)operator(,) ident(privkeyfile)operator(,) ident(certchainfile)operator(\);) + ident(assert) operator(()ident(Context)operator(\);) + + ident(pbioRead) operator(=) ident(BIO_new) operator(()ident(BIO_s_mem)operator((\)\);) + ident(assert) operator(()ident(pbioRead)operator(\);) + + ident(pbioWrite) operator(=) ident(BIO_new) operator(()ident(BIO_s_mem)operator((\)\);) + ident(assert) operator(()ident(pbioWrite)operator(\);) + + ident(pSSL) operator(=) ident(SSL_new) operator(()ident(Context)operator(->)ident(pCtx)operator(\);) + ident(assert) operator(()ident(pSSL)operator(\);) + ident(SSL_set_bio) operator(()ident(pSSL)operator(,) ident(pbioRead)operator(,) ident(pbioWrite)operator(\);) + + reserved(if) operator((!)ident(bIsServer)operator(\)) + ident(SSL_connect) operator(()ident(pSSL)operator(\);) +operator(}) + + + +comment(/******************* +SslBox_t::~SslBox_t +*******************/) + +ident(SslBox_t)operator(::~)ident(SslBox_t)operator((\)) +operator({) + comment(// Freeing pSSL will also free the associated BIOs, so DON'T free them separately.) + reserved(if) operator(()ident(pSSL)operator(\)) operator({) + reserved(if) operator(()ident(SSL_get_shutdown) operator(()ident(pSSL)operator(\)) operator(&) ident(SSL_RECEIVED_SHUTDOWN)operator(\)) + ident(SSL_shutdown) operator(()ident(pSSL)operator(\);) + reserved(else) + ident(SSL_clear) operator(()ident(pSSL)operator(\);) + ident(SSL_free) operator(()ident(pSSL)operator(\);) + operator(}) + + reserved(delete) ident(Context)operator(;) +operator(}) + + + +comment(/*********************** +SslBox_t::PutCiphertext +***********************/) + +pre_type(bool) ident(SslBox_t)operator(::)ident(PutCiphertext) operator(()directive(const) pre_type(char) operator(*)ident(buf)operator(,) pre_type(int) ident(bufsize)operator(\)) +operator({) + ident(assert) operator(()ident(buf) operator(&&) operator(()ident(bufsize) operator(>) integer(0)operator(\)\);) + + ident(assert) operator(()ident(pbioRead)operator(\);) + pre_type(int) ident(n) operator(=) ident(BIO_write) operator(()ident(pbioRead)operator(,) ident(buf)operator(,) ident(bufsize)operator(\);) + + reserved(return) operator(()ident(n) operator(==) ident(bufsize)operator(\)) operator(?) pre_constant(true) operator(:) pre_constant(false)operator(;) +operator(}) + + +comment(/********************** +SslBox_t::GetPlaintext +**********************/) + +pre_type(int) ident(SslBox_t)operator(::)ident(GetPlaintext) operator(()pre_type(char) operator(*)ident(buf)operator(,) pre_type(int) ident(bufsize)operator(\)) +operator({) + reserved(if) operator((!)ident(SSL_is_init_finished) operator(()ident(pSSL)operator(\)\)) operator({) + pre_type(int) ident(e) operator(=) ident(bIsServer) operator(?) ident(SSL_accept) operator(()ident(pSSL)operator(\)) operator(:) ident(SSL_connect) operator(()ident(pSSL)operator(\);) + reserved(if) operator(()ident(e) operator(<) integer(0)operator(\)) operator({) + pre_type(int) ident(er) operator(=) ident(SSL_get_error) operator(()ident(pSSL)operator(,) ident(e)operator(\);) + reserved(if) operator(()ident(er) operator(!=) ident(SSL_ERROR_WANT_READ)operator(\)) operator({) + comment(// Return -1 for a nonfatal error, -2 for an error that should force the connection down.) + reserved(return) operator(()ident(er) operator(==) ident(SSL_ERROR_SSL)operator(\)) operator(?) operator((-)integer(2)operator(\)) operator(:) operator((-)integer(1)operator(\);) + operator(}) + reserved(else) + reserved(return) integer(0)operator(;) + operator(}) + comment(// If handshake finished, FALL THROUGH and return the available plaintext.) + operator(}) + + reserved(if) operator((!)ident(SSL_is_init_finished) operator(()ident(pSSL)operator(\)\)) operator({) + comment(// We can get here if a browser abandons a handshake.) + comment(// The user can see a warning dialog and abort the connection.) + ident(cerr) operator(<<) string<delimiter(")content(<SSL_incomp>)delimiter(")>operator(;) + reserved(return) integer(0)operator(;) + operator(}) + + comment(//cerr << "CIPH: " << SSL_get_cipher (pSSL\) << endl;) + + pre_type(int) ident(n) operator(=) ident(SSL_read) operator(()ident(pSSL)operator(,) ident(buf)operator(,) ident(bufsize)operator(\);) + reserved(if) operator(()ident(n) operator(>=) integer(0)operator(\)) operator({) + reserved(return) ident(n)operator(;) + operator(}) + reserved(else) operator({) + reserved(if) operator(()ident(SSL_get_error) operator(()ident(pSSL)operator(,) ident(n)operator(\)) operator(==) ident(SSL_ERROR_WANT_READ)operator(\)) operator({) + reserved(return) integer(0)operator(;) + operator(}) + reserved(else) operator({) + reserved(return) operator(-)integer(1)operator(;) + operator(}) + operator(}) + + reserved(return) integer(0)operator(;) +operator(}) + + + +comment(/************************** +SslBox_t::CanGetCiphertext +**************************/) + +pre_type(bool) ident(SslBox_t)operator(::)ident(CanGetCiphertext)operator((\)) +operator({) + ident(assert) operator(()ident(pbioWrite)operator(\);) + reserved(return) ident(BIO_pending) operator(()ident(pbioWrite)operator(\)) operator(?) pre_constant(true) operator(:) pre_constant(false)operator(;) +operator(}) + + + +comment(/*********************** +SslBox_t::GetCiphertext +***********************/) + +pre_type(int) ident(SslBox_t)operator(::)ident(GetCiphertext) operator(()pre_type(char) operator(*)ident(buf)operator(,) pre_type(int) ident(bufsize)operator(\)) +operator({) + ident(assert) operator(()ident(pbioWrite)operator(\);) + ident(assert) operator(()ident(buf) operator(&&) operator(()ident(bufsize) operator(>) integer(0)operator(\)\);) + + reserved(return) ident(BIO_read) operator(()ident(pbioWrite)operator(,) ident(buf)operator(,) ident(bufsize)operator(\);) +operator(}) + + + +comment(/********************** +SslBox_t::PutPlaintext +**********************/) + +pre_type(int) ident(SslBox_t)operator(::)ident(PutPlaintext) operator(()directive(const) pre_type(char) operator(*)ident(buf)operator(,) pre_type(int) ident(bufsize)operator(\)) +operator({) + comment(// The caller will interpret the return value as the number of bytes written.) + comment(// WARNING WARNING WARNING, are there any situations in which a 0 or -1 return) + comment(// from SSL_write means we should immediately retry? The socket-machine loop) + comment(// will probably wait for a time-out cycle (perhaps a second\) before re-trying.) + comment(// THIS WOULD CAUSE A PERCEPTIBLE DELAY!) + + comment(/* We internally queue any outbound plaintext that can't be dispatched + * because we're in the middle of a handshake or something. + * When we get called, try to send any queued data first, and then + * send the caller's data (or queue it\). We may get called with no outbound + * data, which means we try to send the outbound queue and that's all. + * + * Return >0 if we wrote any data, 0 if we didn't, and <0 for a fatal error. + * Note that if we return 0, the connection is still considered live + * and we are signalling that we have accepted the outbound data (if any\). + */) + + ident(OutboundQ)operator(.)ident(Push) operator(()ident(buf)operator(,) ident(bufsize)operator(\);) + + reserved(if) operator((!)ident(SSL_is_init_finished) operator(()ident(pSSL)operator(\)\)) + reserved(return) integer(0)operator(;) + + pre_type(bool) ident(fatal) operator(=) pre_constant(false)operator(;) + pre_type(bool) ident(did_work) operator(=) pre_constant(false)operator(;) + + reserved(while) operator(()ident(OutboundQ)operator(.)ident(HasPages)operator((\)\)) operator({) + directive(const) pre_type(char) operator(*)ident(page)operator(;) + pre_type(int) ident(length)operator(;) + ident(OutboundQ)operator(.)ident(Front) operator((&)ident(page)operator(,) operator(&)ident(length)operator(\);) + ident(assert) operator(()ident(page) operator(&&) operator(()ident(length) operator(>) integer(0)operator(\)\);) + pre_type(int) ident(n) operator(=) ident(SSL_write) operator(()ident(pSSL)operator(,) ident(page)operator(,) ident(length)operator(\);) + reserved(if) operator(()ident(n) operator(>) integer(0)operator(\)) operator({) + ident(did_work) operator(=) pre_constant(true)operator(;) + ident(OutboundQ)operator(.)ident(PopFront)operator((\);) + operator(}) + reserved(else) operator({) + pre_type(int) ident(er) operator(=) ident(SSL_get_error) operator(()ident(pSSL)operator(,) ident(n)operator(\);) + reserved(if) operator((()ident(er) operator(!=) ident(SSL_ERROR_WANT_READ)operator(\)) operator(&&) operator(()ident(er) operator(!=) ident(SSL_ERROR_WANT_WRITE)operator(\)\)) + ident(fatal) operator(=) pre_constant(true)operator(;) + reserved(break)operator(;) + operator(}) + operator(}) + + + reserved(if) operator(()ident(did_work)operator(\)) + reserved(return) integer(1)operator(;) + reserved(else) reserved(if) operator(()ident(fatal)operator(\)) + reserved(return) operator(-)integer(1)operator(;) + reserved(else) + reserved(return) integer(0)operator(;) +operator(}) + + +preprocessor(#endif) comment(// WITH_SSL) + |