From 9095e6a2fc69654f993c37c0e5e4159dbd88028d Mon Sep 17 00:00:00 2001 From: David Brodski Date: Wed, 26 Oct 2011 00:02:43 +0000 Subject: [PATCH] Bugfix where no data was send. Added restart of helper process when not working anymore. --- src/transport/plugin_transport_wlan.c | 885 +++++++++++++++----------- 1 file changed, 509 insertions(+), 376 deletions(-) diff --git a/src/transport/plugin_transport_wlan.c b/src/transport/plugin_transport_wlan.c index b3faf4480..b4d219f28 100644 --- a/src/transport/plugin_transport_wlan.c +++ b/src/transport/plugin_transport_wlan.c @@ -67,6 +67,11 @@ */ #define HELLO_BEACON_SCALING_FACTOR 30 +/** + * scaling factor for restarting the helper + */ +#define HELPER_RESTART_SCALING_FACTOR 2 + /** * max size of fragment queue */ @@ -93,8 +98,8 @@ /** * LLC fields for better compatibility */ -#define WLAN_LLC_DSAP_FIELD 0xf -#define WLAN_LLC_SSAP_FIELD 0xf +#define WLAN_LLC_DSAP_FIELD 0x1f +#define WLAN_LLC_SSAP_FIELD 0x1f /** @@ -250,6 +255,11 @@ struct Plugin */ char *interface; + /** + * Mode of operation for the helper, 0 = normal, 1 = first loopback, 2 = second loopback + */ + long long unsigned int testmode; + /** * The mac_address of the wlan card given to us by the helper. */ @@ -311,9 +321,24 @@ struct Plugin */ struct Finish_send { + /** + * pointer to the global plugin struct + */ struct Plugin *plugin; - char *msgheader; + + /** + * head of the next part to send to the helper + */ + char *head_of_next_write; + + /** + * Start of the message to send, needed for free + */ struct GNUNET_MessageHeader *msgstart; + + /** + * rest size to send + */ ssize_t size; }; @@ -680,6 +705,9 @@ free_session (struct Plugin *plugin, struct Sessionqueue *queue, static struct MacEndpoint * create_macendpoint (struct Plugin *plugin, const struct MacAddress *addr); +static void +finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + /** * Generates a nice hexdump of a memory area. * @@ -1393,137 +1421,468 @@ add_message_for_send (void *cls, const struct GNUNET_MessageHeader *hdr) set_next_send (plugin); } + /** - * function to send a hello beacon - * @param plugin pointer to the plugin struct + * We have been notified that wlan-helper has written something to stdout. + * Handle the output, then reschedule this function to be called again once + * more is available. + * + * @param cls the plugin handle + * @param tc the scheduling context */ static void -send_hello_beacon (struct Plugin *plugin) +wlan_plugin_helper_read (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { + struct Plugin *plugin = cls; -#if DEBUG_wlan - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, - "Sending hello beacon\n"); -#endif - - uint16_t size; - ssize_t bytes; - uint16_t hello_size; - struct GNUNET_MessageHeader *msgheader; - struct ieee80211_frame *ieeewlanheader; - struct Radiotap_Send *radioHeader; - struct GNUNET_MessageHeader *msgheader2; - const struct GNUNET_MessageHeader *hello; - - GNUNET_assert (plugin != NULL); - - GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan hello beacons send"), 1, GNUNET_NO); - - hello = plugin->env->get_our_hello (); - hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello); - GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU); - size = - sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) + - sizeof (struct ieee80211_frame) + hello_size; - - msgheader = GNUNET_malloc (size); - msgheader->size = htons (size); - msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA); - - radioHeader = (struct Radiotap_Send *) &msgheader[1]; - getRadiotapHeader (plugin, NULL, radioHeader); - ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1]; - getWlanHeader (ieeewlanheader, &bc_all_mac, plugin, size); - - msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1]; - /*msgheader2->size = - htons (GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello) + - sizeof (struct GNUNET_MessageHeader)); + plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK; - msgheader2->type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);*/ - memcpy (msgheader2, hello, hello_size); + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + return; - bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, msgheader, size); + char mybuf[WLAN_MTU + sizeof (struct GNUNET_MessageHeader)]; + ssize_t bytes; - if (bytes == GNUNET_SYSERR) + bytes = + GNUNET_DISK_file_read (plugin->server_stdout_handle, mybuf, + sizeof (mybuf)); + if (bytes <= 0) { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, +#if DEBUG_wlan + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, _ - ("Error writing to wlan healper. errno == %d, ERROR: %s\n"), - errno, strerror (errno)); - + ("Finished reading from wlan-helper stdout with code: %d\n"), + bytes); +#endif + return; } - GNUNET_assert (bytes != GNUNET_SYSERR); - GNUNET_assert (bytes == size); - GNUNET_free (msgheader); + GNUNET_SERVER_mst_receive (plugin->suid_tokenizer, NULL, mybuf, bytes, + GNUNET_NO, GNUNET_NO); - set_next_beacon_time (plugin); - set_next_send (plugin); + GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK); + plugin->server_read_task = + GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + plugin->server_stdout_handle, + &wlan_plugin_helper_read, plugin); } /** - * function to add an ack to send it for a received fragment - * @param cls MacEndpoint this ack belongs to - * @param msg_id id of the message - * @param hdr pointer to the hdr where the ack is stored + * Start the gnunet-wlan-helper process. * + * @param plugin the transport plugin + * @return GNUNET_YES if process was started, GNUNET_SYSERR on error */ - -static void -add_ack_for_send (void *cls, uint32_t msg_id, - const struct GNUNET_MessageHeader *hdr) +static int +wlan_transport_start_wlan_helper (struct Plugin *plugin) { + const char *filenamehw = "gnunet-transport-wlan-helper"; + const char *filenameloopback = "gnunet-transport-wlan-helper-dummy"; - struct AckSendQueue *ack; + plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); + if (plugin->server_stdout == NULL) + return GNUNET_SYSERR; - GNUNET_assert (cls != NULL); - struct MacEndpoint *endpoint = cls; - struct Plugin *plugin = endpoint->plugin; - struct GNUNET_MessageHeader *msgheader; - struct GNUNET_MessageHeader *msgheader2; - uint16_t size; + plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO); + if (plugin->server_stdin == NULL) + return GNUNET_SYSERR; - size = - sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) + - sizeof (struct ieee80211_frame) + ntohs (hdr->size) + - sizeof (struct AckSendQueue); + /* Start the server process */ - ack = GNUNET_malloc (size); - ack->message_id = msg_id; - ack->endpoint = endpoint; + if (plugin->testmode == 0) + { - size = - sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) + - sizeof (struct ieee80211_frame) + ntohs (hdr->size); +#if DEBUG_wlan + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, + "Starting gnunet-wlan-helper process cmd: %s %s %i\n", + filenamehw, plugin->interface, plugin->testmode); +#endif - msgheader = (struct GNUNET_MessageHeader *) &ack[1]; - ack->hdr = (struct GNUNET_MessageHeader *) &ack[1]; - msgheader->size = htons (size); - msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA); + if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_YES) + { + plugin->server_proc = + GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout, + filenamehw, filenamehw, plugin->interface, + NULL); + } + else if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_NO) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, + "gnunet-transport-wlan-helper is not suid, please change it or look at the doku\n"); + GNUNET_break (0); + } + else + { + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, + "gnunet-transport-wlan-helper not found, please look if it exists and is the $PATH variable!\n"); + GNUNET_break (0); + } - ack->radioHeader = (struct Radiotap_Send *) &msgheader[1]; - ack->ieeewlanheader = (struct ieee80211_frame *) &(ack->radioHeader)[1]; - msgheader2 = (struct GNUNET_MessageHeader *) &(ack->ieeewlanheader)[1]; - memcpy (msgheader2, hdr, ntohs (hdr->size)); + } + else if (plugin->testmode == 1) + { - GNUNET_CONTAINER_DLL_insert_tail (plugin->ack_send_queue_head, - plugin->ack_send_queue_tail, ack); +#if DEBUG_wlan + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, + "Starting gnunet-wlan-helper loopback 1 process cmd: %s %s %i\n", + filenameloopback, plugin->interface, plugin->testmode); +#endif -#if DEBUG_wlan_retransmission > 1 + if (GNUNET_OS_check_helper_binary (filenameloopback) != GNUNET_SYSERR) + { + plugin->server_proc = + GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout, + filenameloopback, filenameloopback, "1", + NULL); + } + else + { + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, + "gnunet-transport-wlan-helper-dummy not found, please look if it exists and is the $PATH variable!\n"); + GNUNET_break (0); + } + } + else if (plugin->testmode == 2) + { +#if DEBUG_wlan + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, + "Starting gnunet-wlan-helper loopback 2 process cmd: %s %s %i\n", + filenameloopback, plugin->interface, plugin->testmode); +#endif + if (GNUNET_OS_check_helper_binary (filenameloopback) != GNUNET_SYSERR) + { + plugin->server_proc = + GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout, + filenameloopback, filenameloopback, "2", + NULL); + } + else + { + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, + "gnunet-transport-wlan-helper-dummy not found, please look if it exists and is in the $PATH variable!\n"); + GNUNET_break (0); + } + } + if (plugin->server_proc == NULL) + { +#if DEBUG_wlan + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, + "Failed to start gnunet-wlan-helper process\n"); +#endif + return GNUNET_SYSERR; + } + + /* Close the write end of the read pipe */ + GNUNET_DISK_pipe_close_end (plugin->server_stdout, + GNUNET_DISK_PIPE_END_WRITE); + + /* Close the read end of the write pipe */ + GNUNET_DISK_pipe_close_end (plugin->server_stdin, GNUNET_DISK_PIPE_END_READ); + + plugin->server_stdout_handle = + GNUNET_DISK_pipe_handle (plugin->server_stdout, + GNUNET_DISK_PIPE_END_READ); + plugin->server_stdin_handle = + GNUNET_DISK_pipe_handle (plugin->server_stdin, + GNUNET_DISK_PIPE_END_WRITE); + + GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK); + +#if DEBUG_wlan GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, - "Adding ack with message id %u to send, AckSendQueue %p, endpoint %p\n", - msg_id, ack, endpoint); + "Adding server_read_task for the wlan-helper\n"); #endif - set_next_send (plugin); + plugin->server_read_task = + GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + plugin->server_stdout_handle, + &wlan_plugin_helper_read, plugin); + + return GNUNET_YES; } /** - * Function for the scheduler if a FragmentMessage times out - * @param cls pointer to the FragmentMessage - * @param tc pointer to the GNUNET_SCHEDULER_TaskContext - */ -static void + * Stops the gnunet-wlan-helper process. + * + * @param plugin the transport plugin + * @return GNUNET_YES if process was started, GNUNET_SYSERR on error + */ +static int +wlan_transport_stop_wlan_helper (struct Plugin *plugin) +{ +#if DEBUG_wlan + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, + "Stoping WLAN helper process\n"); +#endif + + if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task); + plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK; + } + if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (plugin->server_write_task); + plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; + } + if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (plugin->server_read_task); + plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK; + } + + GNUNET_DISK_pipe_close (plugin->server_stdout); + GNUNET_DISK_pipe_close (plugin->server_stdin); + GNUNET_OS_process_kill (plugin->server_proc, 9); + GNUNET_OS_process_close (plugin->server_proc); + + return GNUNET_YES; +} + +/** + * function for delayed restart of the helper process + * @param cls Finish_send struct if message should be finished + * @param tc TaskContext + */ +static void +delay_restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct Finish_send *finish = cls; + struct Plugin *plugin; + plugin = finish->plugin; + + plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; + if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) + { + GNUNET_free_non_null(finish->msgstart); + GNUNET_free (finish); + return; + } + + wlan_transport_start_wlan_helper(plugin); + + if (finish->size != 0) + { + plugin->server_write_task = + GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, + plugin->server_stdin_handle, + &finish_sending, finish); + } + else + { + set_next_send (plugin); + GNUNET_free_non_null(finish->msgstart); + GNUNET_free (finish); + } + +} + +/** + * Function to restart the helper + * @param plugin pointer to the global plugin struct + * @param finish pointer to the Finish_send struct to finish + */ +static void +restart_helper(struct Plugin *plugin, struct Finish_send *finish) +{ + static struct GNUNET_TIME_Relative next_try = {1000}; + GNUNET_assert(finish != NULL); + + wlan_transport_stop_wlan_helper(plugin); + plugin->server_write_task = GNUNET_SCHEDULER_add_delayed (next_try, &delay_restart_helper, finish); + GNUNET_TIME_relative_multiply(next_try, HELPER_RESTART_SCALING_FACTOR); + +} + +/** + * function to finish a sending if not all could have been writen befor + * @param cls pointer to the Finish_send struct + * @param tc TaskContext + */ +static void +finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct Finish_send *finish = cls; + struct Plugin *plugin; + ssize_t bytes; + + plugin = finish->plugin; + plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; + + if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) + { + GNUNET_free (finish->msgstart); + GNUNET_free (finish); + return; + } + bytes = + GNUNET_DISK_file_write (plugin->server_stdin_handle, finish->head_of_next_write, + finish->size); + + if (bytes != finish->size) + { + if (bytes != GNUNET_SYSERR) + { + finish->head_of_next_write += bytes; + finish->size -= bytes; + plugin->server_write_task = + GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, + plugin->server_stdin_handle, + &finish_sending, finish); + } + else + { + restart_helper(plugin, finish); + } + } + else + { + GNUNET_free (finish->msgstart); + GNUNET_free (finish); + set_next_send (plugin); + } +} + +/** + * function to send a hello beacon + * @param plugin pointer to the plugin struct + */ +static void +send_hello_beacon (struct Plugin *plugin) +{ + +#if DEBUG_wlan + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, + "Sending hello beacon\n"); +#endif + + uint16_t size; + ssize_t bytes; + uint16_t hello_size; + struct GNUNET_MessageHeader *msgheader; + struct ieee80211_frame *ieeewlanheader; + struct Radiotap_Send *radioHeader; + struct GNUNET_MessageHeader *msgheader2; + const struct GNUNET_MessageHeader *hello; + struct Finish_send * finish; + + GNUNET_assert (plugin != NULL); + + GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan hello beacons send"), 1, GNUNET_NO); + + hello = plugin->env->get_our_hello (); + hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello); + GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU); + size = + sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) + + sizeof (struct ieee80211_frame) + hello_size; + + msgheader = GNUNET_malloc (size); + msgheader->size = htons (size); + msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA); + + radioHeader = (struct Radiotap_Send *) &msgheader[1]; + getRadiotapHeader (plugin, NULL, radioHeader); + ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1]; + getWlanHeader (ieeewlanheader, &bc_all_mac, plugin, size); + + msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1]; + /*msgheader2->size = + htons (GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello) + + sizeof (struct GNUNET_MessageHeader)); + + msgheader2->type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);*/ + memcpy (msgheader2, hello, hello_size); + + bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, msgheader, size); + + if (bytes == GNUNET_SYSERR) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, + _ + ("Error writing to wlan healper. errno == %d, ERROR: %s\n"), + errno, strerror (errno)); + finish = GNUNET_malloc (sizeof (struct Finish_send)); + finish->plugin = plugin; + finish->head_of_next_write = NULL; + finish->size = 0; + finish->msgstart = NULL; + restart_helper(plugin, finish); + + } + else + { + GNUNET_assert (bytes == size); + set_next_send (plugin); + } + GNUNET_free (msgheader); + + set_next_beacon_time (plugin); +} + +/** + * function to add an ack to send it for a received fragment + * @param cls MacEndpoint this ack belongs to + * @param msg_id id of the message + * @param hdr pointer to the hdr where the ack is stored + * + */ + +static void +add_ack_for_send (void *cls, uint32_t msg_id, + const struct GNUNET_MessageHeader *hdr) +{ + + struct AckSendQueue *ack; + + GNUNET_assert (cls != NULL); + struct MacEndpoint *endpoint = cls; + struct Plugin *plugin = endpoint->plugin; + struct GNUNET_MessageHeader *msgheader; + struct GNUNET_MessageHeader *msgheader2; + uint16_t size; + + size = + sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) + + sizeof (struct ieee80211_frame) + ntohs (hdr->size) + + sizeof (struct AckSendQueue); + + ack = GNUNET_malloc (size); + ack->message_id = msg_id; + ack->endpoint = endpoint; + + size = + sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) + + sizeof (struct ieee80211_frame) + ntohs (hdr->size); + + msgheader = (struct GNUNET_MessageHeader *) &ack[1]; + ack->hdr = (struct GNUNET_MessageHeader *) &ack[1]; + msgheader->size = htons (size); + msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA); + + ack->radioHeader = (struct Radiotap_Send *) &msgheader[1]; + ack->ieeewlanheader = (struct ieee80211_frame *) &(ack->radioHeader)[1]; + msgheader2 = (struct GNUNET_MessageHeader *) &(ack->ieeewlanheader)[1]; + memcpy (msgheader2, hdr, ntohs (hdr->size)); + + GNUNET_CONTAINER_DLL_insert_tail (plugin->ack_send_queue_head, + plugin->ack_send_queue_tail, ack); + +#if DEBUG_wlan_retransmission > 1 + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, + "Adding ack with message id %u to send, AckSendQueue %p, endpoint %p\n", + msg_id, ack, endpoint); +#endif + + set_next_send (plugin); +} + +/** + * Function for the scheduler if a FragmentMessage times out + * @param cls pointer to the FragmentMessage + * @param tc pointer to the GNUNET_SCHEDULER_TaskContext + */ +static void fragmentmessage_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -1618,13 +1977,17 @@ check_fragment_queue (struct Plugin *plugin) /** * Function to send an ack, does not free the ack * @param plugin pointer to the plugin - * @param ack pointer to the ack to send */ static void -send_ack (struct Plugin *plugin, struct AckSendQueue *ack) +send_ack (struct Plugin *plugin) { ssize_t bytes; + struct AckSendQueue *ack; + struct Finish_send * finish; + + ack = plugin->ack_send_queue_head; + #if DEBUG_wlan GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, @@ -1649,52 +2012,19 @@ send_ack (struct Plugin *plugin, struct AckSendQueue *ack) _ ("Error writing to wlan healper. errno == %d, ERROR: %s\n"), errno, strerror (errno)); - - } - GNUNET_assert (bytes != GNUNET_SYSERR); - GNUNET_assert (bytes == ntohs (ack->hdr->size)); - set_next_send (plugin); -} - -/** - * function to finish a sending if not all could have been writen befor - * @param cls pointer to the Finish_send struct - * @param tc TaskContext - */ -static void -finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct Finish_send *finish = cls; - struct Plugin *plugin; - ssize_t bytes; - - plugin = finish->plugin; - plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; - - if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) - { - GNUNET_free (finish->msgstart); - GNUNET_free (finish); - return; - } - bytes = - GNUNET_DISK_file_write (plugin->server_stdin_handle, finish->msgheader, - finish->size); - GNUNET_assert (bytes != GNUNET_SYSERR); - - if (bytes != finish->size) - { - finish->msgheader = finish->msgheader + bytes; - finish->size = finish->size - bytes; - plugin->server_write_task = - GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, - plugin->server_stdin_handle, - &finish_sending, finish); + finish = GNUNET_malloc (sizeof (struct Finish_send)); + finish->plugin = plugin; + finish->head_of_next_write = NULL; + finish->size = 0; + finish->msgstart = NULL; + restart_helper(plugin, finish); } else { - GNUNET_free (finish->msgstart); - GNUNET_free (finish); + GNUNET_assert (bytes == ntohs (ack->hdr->size)); + GNUNET_CONTAINER_DLL_remove (plugin->ack_send_queue_head, + plugin->ack_send_queue_tail, ack); + GNUNET_free (ack); set_next_send (plugin); } } @@ -1719,16 +2049,11 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct FragmentMessage *fm; struct Finish_send *finish; struct FragmentMessage_queue *fmq; - struct AckSendQueue *ack; ssize_t bytes; if (plugin->ack_send_queue_head != NULL) { - ack = plugin->ack_send_queue_head; - GNUNET_CONTAINER_DLL_remove (plugin->ack_send_queue_head, - plugin->ack_send_queue_tail, ack); - send_ack (plugin, ack); - GNUNET_free (ack); + send_ack (plugin); return; } @@ -1736,6 +2061,7 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (GNUNET_TIME_absolute_get_remaining (plugin->beacon_time).rel_value == 0) { send_hello_beacon (plugin); + set_next_send(plugin); return; } @@ -1765,35 +2091,36 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, fm->frag, fm->size); - if (bytes == GNUNET_SYSERR) - { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, - _ - ("Error writing to wlan healper. errno == %d, ERROR: %s\n"), - errno, strerror (errno)); - //TODO START NEW WLAN HELPER - /* - * alle sessions beenden - * neu starten (alle 5 sec) - * alles bis dahin ablehnen - */ - } - //GNUNET_assert (bytes != GNUNET_SYSERR); + if (bytes != fm->size) { finish = GNUNET_malloc (sizeof (struct Finish_send)); finish->plugin = plugin; - finish->msgheader = fm->frag + bytes; - finish->size = fm->size - bytes; finish->msgstart = (struct GNUNET_MessageHeader *) fm->frag; - GNUNET_assert (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK); - plugin->server_write_task = - GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, - plugin->server_stdin_handle, - &finish_sending, finish); + if (bytes == GNUNET_SYSERR) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, + _ + ("Error writing to wlan healper. errno == %d, ERROR: %s\n"), + errno, strerror (errno)); + + finish->head_of_next_write = fm->frag; + finish->size = fm->size; + restart_helper(plugin, finish); + } + else + { + finish->head_of_next_write = fm->frag + bytes; + finish->size = fm->size - bytes; + plugin->server_write_task = + GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, + plugin->server_stdin_handle, + &finish_sending, finish); + } + fm->frag = NULL; } else @@ -1990,6 +2317,8 @@ free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint) GNUNET_CONTAINER_DLL_remove (plugin->mac_head, plugin->mac_tail, endpoint); if (endpoint->timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endpoint->timeout_task); + plugin->mac_count--; + GNUNET_STATISTICS_set(plugin->env->stats, _("# wlan mac endpoints"), plugin->mac_count, GNUNET_NO); GNUNET_free (endpoint); } @@ -2625,6 +2954,7 @@ create_macendpoint (struct Plugin *plugin, const struct MacAddress *addr) newend); plugin->mac_count++; + GNUNET_STATISTICS_set(plugin->env->stats, _("# wlan mac endpoints"), plugin->mac_count, GNUNET_NO); GNUNET_CONTAINER_DLL_insert_tail (plugin->mac_head, plugin->mac_tail, newend); #if DEBUG_wlan GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, @@ -2794,186 +3124,6 @@ wlan_process_helper (void *cls, void *client, } } -/** - * We have been notified that wlan-helper has written something to stdout. - * Handle the output, then reschedule this function to be called again once - * more is available. - * - * @param cls the plugin handle - * @param tc the scheduling context - */ -static void -wlan_plugin_helper_read (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct Plugin *plugin = cls; - - plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK; - - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - return; - - char mybuf[WLAN_MTU + sizeof (struct GNUNET_MessageHeader)]; - ssize_t bytes; - - bytes = - GNUNET_DISK_file_read (plugin->server_stdout_handle, mybuf, - sizeof (mybuf)); - if (bytes <= 0) - { -#if DEBUG_wlan - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, - _ - ("Finished reading from wlan-helper stdout with code: %d\n"), - bytes); -#endif - return; - } - GNUNET_SERVER_mst_receive (plugin->suid_tokenizer, NULL, mybuf, bytes, - GNUNET_NO, GNUNET_NO); - - GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK); - plugin->server_read_task = - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - plugin->server_stdout_handle, - &wlan_plugin_helper_read, plugin); -} - -/** - * Start the gnunet-wlan-helper process. - * - * @param plugin the transport plugin - * @param testmode should we use the dummy driver for testing? - * @return GNUNET_YES if process was started, GNUNET_SYSERR on error - */ -static int -wlan_transport_start_wlan_helper (struct Plugin *plugin, int testmode) -{ - const char *filenamehw = "gnunet-transport-wlan-helper"; - const char *filenameloopback = "gnunet-transport-wlan-helper-dummy"; - - plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); - if (plugin->server_stdout == NULL) - return GNUNET_SYSERR; - - plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO); - if (plugin->server_stdin == NULL) - return GNUNET_SYSERR; - - /* Start the server process */ - - if (testmode == 0) - { - -#if DEBUG_wlan - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, - "Starting gnunet-wlan-helper process cmd: %s %s %i\n", - filenamehw, plugin->interface, testmode); -#endif - - if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_YES) - { - plugin->server_proc = - GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout, - filenamehw, filenamehw, plugin->interface, - NULL); - } - else if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_NO) - { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, - "gnunet-transport-wlan-helper is not suid, please change it or look at the doku\n"); - GNUNET_break (0); - } - else - { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, - "gnunet-transport-wlan-helper not found, please look if it exists and is the $PATH variable!\n"); - GNUNET_break (0); - } - - } - else if (testmode == 1) - { - -#if DEBUG_wlan - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, - "Starting gnunet-wlan-helper loopback 1 process cmd: %s %s %i\n", - filenameloopback, plugin->interface, testmode); -#endif - - if (GNUNET_OS_check_helper_binary (filenameloopback) != GNUNET_SYSERR) - { - plugin->server_proc = - GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout, - filenameloopback, filenameloopback, "1", - NULL); - } - else - { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, - "gnunet-transport-wlan-helper-dummy not found, please look if it exists and is the $PATH variable!\n"); - GNUNET_break (0); - } - } - else if (testmode == 2) - { -#if DEBUG_wlan - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, - "Starting gnunet-wlan-helper loopback 2 process cmd: %s %s %i\n", - filenameloopback, plugin->interface, testmode); -#endif - if (GNUNET_OS_check_helper_binary (filenameloopback) != GNUNET_SYSERR) - { - plugin->server_proc = - GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout, - filenameloopback, filenameloopback, "2", - NULL); - } - else - { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, - "gnunet-transport-wlan-helper-dummy not found, please look if it exists and is in the $PATH variable!\n"); - GNUNET_break (0); - } - } - if (plugin->server_proc == NULL) - { -#if DEBUG_wlan - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, - "Failed to start gnunet-wlan-helper process\n"); -#endif - return GNUNET_SYSERR; - } - - /* Close the write end of the read pipe */ - GNUNET_DISK_pipe_close_end (plugin->server_stdout, - GNUNET_DISK_PIPE_END_WRITE); - - /* Close the read end of the write pipe */ - GNUNET_DISK_pipe_close_end (plugin->server_stdin, GNUNET_DISK_PIPE_END_READ); - - plugin->server_stdout_handle = - GNUNET_DISK_pipe_handle (plugin->server_stdout, - GNUNET_DISK_PIPE_END_READ); - plugin->server_stdin_handle = - GNUNET_DISK_pipe_handle (plugin->server_stdin, - GNUNET_DISK_PIPE_END_WRITE); - - GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK); - -#if DEBUG_wlan - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, - "Adding server_read_task for the wlan-helper\n"); -#endif - - plugin->server_read_task = - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - plugin->server_stdout_handle, - &wlan_plugin_helper_read, plugin); - - return GNUNET_YES; -} - /** * Exit point from the plugin. * @param cls pointer to the api struct @@ -2993,10 +3143,7 @@ libgnunet_plugin_transport_wlan_done (void *cls) "libgnunet_plugin_transport_wlan_done started\n"); #endif - GNUNET_DISK_pipe_close (plugin->server_stdout); - GNUNET_DISK_pipe_close (plugin->server_stdin); - GNUNET_OS_process_kill (plugin->server_proc, 9); - GNUNET_OS_process_close (plugin->server_proc); + wlan_transport_stop_wlan_helper(plugin); GNUNET_assert (cls != NULL); //free sessions @@ -3007,21 +3154,7 @@ libgnunet_plugin_transport_wlan_done (void *cls) endpoint = endpoint_next; } - if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task); - plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK; - } - if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (plugin->server_write_task); - plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; - } - if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (plugin->server_read_task); - plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK; - } + if (plugin->suid_tokenizer != NULL) GNUNET_SERVER_mst_destroy (plugin->suid_tokenizer); @@ -3048,7 +3181,6 @@ libgnunet_plugin_transport_wlan_init (void *cls) struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct Plugin *plugin; - static unsigned long long testmode = 0; GNUNET_assert (cls != NULL); @@ -3057,6 +3189,7 @@ libgnunet_plugin_transport_wlan_init (void *cls) plugin->pendingsessions = 0; GNUNET_STATISTICS_set(plugin->env->stats, _("# wlan pending sessions"), plugin->pendingsessions, GNUNET_NO); plugin->mac_count = 0; + GNUNET_STATISTICS_set(plugin->env->stats, _("# wlan mac endpoints"), plugin->mac_count, GNUNET_NO); plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK; plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK; @@ -3086,8 +3219,8 @@ libgnunet_plugin_transport_wlan_init (void *cls) { if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan", - "TESTMODE", &testmode)) - testmode = 0; //default value + "TESTMODE", &(plugin->testmode))) + plugin->testmode = 0; //default value } if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "INTERFACE")) @@ -3102,7 +3235,7 @@ libgnunet_plugin_transport_wlan_init (void *cls) } //start the plugin - wlan_transport_start_wlan_helper (plugin, testmode); + wlan_transport_start_wlan_helper (plugin); set_next_beacon_time (plugin); set_next_send(plugin); #if DEBUG_wlan -- 2.25.1