diff --git a/unsorted/ecore/efl_io_copier_example.c b/unsorted/ecore/efl_io_copier_example.c index d6b2907b..cedd41b0 100644 --- a/unsorted/ecore/efl_io_copier_example.c +++ b/unsorted/ecore/efl_io_copier_example.c @@ -322,6 +322,8 @@ static const Ecore_Getopt options = { "If set will limit buffer size to this limit of bytes. If used alongside with --line-delimiter and that delimiter was not found but bffer limit was reached, the line event will be triggered without the delimiter at the end."), ECORE_GETOPT_STORE_ULONG('c', "read-chunk-size", "If set will change the base chunk size used while reading."), + ECORE_GETOPT_STORE_DOUBLE('t', "inactivity-timeout", + "If greater than zero, specifies the number of seconds without any reads or writes that the copier will be timed out."), ECORE_GETOPT_VERSION('V', "version"), ECORE_GETOPT_COPYRIGHT('C', "copyright"), ECORE_GETOPT_LICENSE('L', "license"), @@ -359,11 +361,13 @@ main(int argc, char **argv) char *line_delimiter = NULL; unsigned long buffer_limit = 0; unsigned long read_chunk_size = 0; + double timeout = 0.0; Eina_Bool quit_option = EINA_FALSE; Ecore_Getopt_Value values[] = { ECORE_GETOPT_VALUE_STR(line_delimiter), ECORE_GETOPT_VALUE_ULONG(buffer_limit), ECORE_GETOPT_VALUE_ULONG(read_chunk_size), + ECORE_GETOPT_VALUE_DOUBLE(timeout), /* standard block to provide version, copyright, license and help */ ECORE_GETOPT_VALUE_BOOL(quit_option), /* -V/--version quits */ @@ -723,6 +727,7 @@ main(int argc, char **argv) efl_io_copier_line_delimiter_set(efl_added, &line_delm_slice), /* optional */ efl_io_copier_buffer_limit_set(efl_added, buffer_limit), /* optional, defaults to unlimited */ efl_io_copier_read_chunk_size_set(efl_added, read_chunk_size), /* optional, defaults to 4096 */ + efl_io_copier_inactivity_timeout_set(efl_added, timeout), /* optional, defaults to 0.0 (disabled) */ efl_event_callback_array_add(efl_added, copier_cbs(), NULL) /* recommended, at least EFL_IO_COPIER_EVENT_DONE. */ ); if (!copier) diff --git a/unsorted/ecore/efl_net_server_example.c b/unsorted/ecore/efl_net_server_example.c index d5980c1b..2028a421 100644 --- a/unsorted/ecore/efl_net_server_example.c +++ b/unsorted/ecore/efl_net_server_example.c @@ -7,6 +7,7 @@ static int retval = EXIT_SUCCESS; static Eina_Bool echo = EINA_FALSE; +static double timeout = 10.0; /* NOTE: client i/o events are only used as debug, you can omit these */ @@ -67,6 +68,15 @@ _echo_copier_error(void *data EINA_UNUSED, const Efl_Event *event) Eo *copier = event->object; const Eina_Error *perr = event->info; + if (*perr == ETIMEDOUT) + { + Eo *client = efl_io_copier_source_get(copier); + fprintf(stderr, "INFO: client '%s' timed out, delete it.\n", + efl_net_socket_address_remote_get(client)); + efl_del(copier); + return; + } + retval = EXIT_FAILURE; fprintf(stderr, "ERROR: echo copier %p failed %d '%s', close and del.\n", @@ -146,6 +156,12 @@ _send_copier_done(void *data, const Efl_Event *event) efl_net_socket_address_remote_get(client), slice.len, EINA_SLICE_STR_PRINT(slice)); + if (d->recv_copier) + { + /* only start the reader inactivity timeout once the sender is done */ + efl_io_copier_inactivity_timeout_set(d->recv_copier, efl_io_copier_inactivity_timeout_get(copier)); + } + fprintf(stderr, "INFO: send copier done, check if should close %p\n", copier); _send_recv_done(d, copier); } @@ -161,6 +177,14 @@ _send_copier_error(void *data, const Efl_Event *event) uint64_t offset; Eina_Slice slice; + if (*perr == ETIMEDOUT) + { + fprintf(stderr, "INFO: client '%s' timed out send, delete it.\n", + efl_net_socket_address_remote_get(client)); + efl_io_closer_close(copier); /* forces client to be closed, thus closes the recv copier as an effect */ + return; + } + retval = EXIT_FAILURE; offset = efl_io_buffer_position_read_get(buffer); @@ -235,12 +259,20 @@ static void _recv_copier_error(void *data, const Efl_Event *event) { Eo *copier = event->object; - Eo *buffer = efl_io_copier_source_get(copier); - Eo *client = efl_io_copier_destination_get(copier); + Eo *buffer = efl_io_copier_destination_get(copier); + Eo *client = efl_io_copier_source_get(copier); const Eina_Error *perr = event->info; Send_Recv_Data *d = data; Eina_Slice slice; + if (*perr == ETIMEDOUT) + { + fprintf(stderr, "INFO: client '%s' timed out recv, delete it.\n", + efl_net_socket_address_remote_get(client)); + efl_io_closer_close(copier); /* forces client to be closed, thus closes the send copier as an effect */ + return; + } + retval = EXIT_FAILURE; if (!efl_io_buffer_slice_get(buffer, &slice)) @@ -303,6 +335,7 @@ _server_client_add(void *data EINA_UNUSED, const Efl_Event *event) Eo *echo_copier = efl_add(EFL_IO_COPIER_CLASS, efl_parent_get(client), efl_io_copier_source_set(efl_added, client), efl_io_copier_destination_set(efl_added, client), + efl_io_copier_inactivity_timeout_set(efl_added, timeout), efl_event_callback_array_add(efl_added, echo_copier_cbs(), client), efl_io_closer_close_on_destructor_set(efl_added, EINA_TRUE) /* we want to auto-close as we have a single copier */ ); @@ -345,6 +378,7 @@ _server_client_add(void *data EINA_UNUSED, const Efl_Event *event) d->send_copier = efl_add(EFL_IO_COPIER_CLASS, efl_parent_get(client), efl_io_copier_source_set(efl_added, send_buffer), efl_io_copier_destination_set(efl_added, client), + efl_io_copier_inactivity_timeout_set(efl_added, timeout), efl_event_callback_array_add(efl_added, send_copier_cbs(), d), efl_io_closer_close_on_destructor_set(efl_added, EINA_FALSE) /* we must wait both copiers to finish before we close! */ ); @@ -361,6 +395,7 @@ _server_client_add(void *data EINA_UNUSED, const Efl_Event *event) d->recv_copier = efl_add(EFL_IO_COPIER_CLASS, efl_parent_get(client), efl_io_copier_source_set(efl_added, client), efl_io_copier_destination_set(efl_added, recv_buffer), + efl_io_copier_inactivity_timeout_set(efl_added, 0.0), /* we'll only set an inactivity timeout once the sender is done */ efl_event_callback_array_add(efl_added, recv_copier_cbs(), d), efl_io_closer_close_on_destructor_set(efl_added, EINA_FALSE) /* we must wait both copiers to finish before we close! */ ); @@ -433,6 +468,9 @@ static const Ecore_Getopt options = { "If true, excess clients will be immediately rejected."), ECORE_GETOPT_STORE_BOOL(0, "ipv6-only", "If true (default), only IPv6 clients will be allowed for a server if an IPv6 was used, otherwise IPv4 clients will be automatically converted into IPv6 and handled transparently."), + ECORE_GETOPT_STORE_DOUBLE('t', "inactivity-timeout", + "The timeout in seconds to disconnect a client. The timeout is restarted for each client when there is some activity. It's particularly useful for UDP where there is no disconnection event."), + ECORE_GETOPT_VERSION('V', "version"), ECORE_GETOPT_COPYRIGHT('C', "copyright"), ECORE_GETOPT_LICENSE('L', "license"), @@ -463,6 +501,7 @@ main(int argc, char **argv) ECORE_GETOPT_VALUE_UINT(clients_limit), ECORE_GETOPT_VALUE_BOOL(clients_reject_excess), ECORE_GETOPT_VALUE_BOOL(ipv6_only), + ECORE_GETOPT_VALUE_DOUBLE(timeout), /* standard block to provide version, copyright, license and help */ ECORE_GETOPT_VALUE_BOOL(quit_option), /* -V/--version quits */