- //cancel old task
- 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;
- }
-
- //check if some acks are in the queue
- if (plugin->ack_send_queue_head != NULL)
- {
- next_send = GNUNET_TIME_UNIT_ZERO;
- }
-
- //check if there are some fragments in the queue
- else if (plugin->sending_messages_head != NULL)
- {
- next_send = GNUNET_TIME_UNIT_ZERO;
- }
- else
- {
- next_send = GNUNET_TIME_absolute_get_remaining (plugin->beacon_time);
- }
-
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Next packet is send in: %u\n", next_send.rel_value);
-#endif
-
- if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
- {
- if (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,
- &do_transmit, plugin);
- }
- }
- else
- {
- if (plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK)
- {
- plugin->server_write_delay_task =
- GNUNET_SCHEDULER_add_delayed (next_send, &delay_fragment_task,
- plugin);
- }
- }
-}
-
-/**
- * Function to get the next queued Session, removes the session from the queue
- * @param plugin pointer to the plugin struct
- * @return pointer to the session found, returns NULL if there is now session in the queue
- */
-static struct Session *
-get_next_queue_session (struct Plugin *plugin)
-{
- struct Session *session;
- struct Sessionqueue *sessionqueue;
- struct Sessionqueue *sessionqueue_alt;
- struct PendingMessage *pm;
-
- sessionqueue = plugin->pending_Sessions_head;
-
- while (sessionqueue != NULL)
- {
- session = sessionqueue->content;
-
- GNUNET_assert (session != NULL);
- pm = session->pending_message_head;
-
- if (pm == NULL)
- {
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- "pending message is empty, should not happen. session %p\n",
- session);
-#endif
- sessionqueue_alt = sessionqueue;
- sessionqueue = sessionqueue->next;
- plugin->pendingsessions--;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
- plugin->pendingsessions, GNUNET_NO);
- GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
- plugin->pending_Sessions_tail,
- sessionqueue_alt);
-
- GNUNET_free (sessionqueue_alt);
- continue;
-
- }
-
- //check for message timeout
- if (GNUNET_TIME_absolute_get_remaining (pm->timeout).rel_value > 0)
- {
- //check if session has no message in the fragment queue
- if ((session->mac->fragment_messages_out_count <
- FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT) &&
- (session->fragment_messages_out_count <
- FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION))
- {
- plugin->pendingsessions--;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
- plugin->pendingsessions, GNUNET_NO);
- GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
- plugin->pending_Sessions_tail,
- sessionqueue);
- GNUNET_free (sessionqueue);
-
- return session;
- }
- else
- {
- sessionqueue = sessionqueue->next;
- }
- }
- else
- {
- GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
- session->pending_message_tail, pm);
-
- //call the cont func that it did not work
- if (pm->transmit_cont != NULL)
- pm->transmit_cont (pm->transmit_cont_cls, &(session->target),
- GNUNET_SYSERR);
- GNUNET_free (pm->msg);
- GNUNET_free (pm);
-
- if (session->pending_message_head == NULL)
- {
- sessionqueue_alt = sessionqueue;
- sessionqueue = sessionqueue->next;
- plugin->pendingsessions--;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
- plugin->pendingsessions, GNUNET_NO);
- GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
- plugin->pending_Sessions_tail,
- sessionqueue_alt);
-
- GNUNET_free (sessionqueue_alt);
- }
- }
-
- }
- return NULL;
-}
-
-/**
- * frees the space of a message in the fragment queue (send queue)
- * @param plugin the plugin struct
- * @param fm message to free
- */
-static void
-free_fragment_message (struct Plugin *plugin, struct FragmentMessage *fm)
-{
- struct Session *session = fm->session;
- struct MacEndpoint *endpoint = session->mac;
- struct FragmentMessage_queue *fmq;
- struct FragmentMessage_queue *fmq_next;
-
- fmq = plugin->sending_messages_head;
- while (fmq != NULL)
- {
- fmq_next = fmq->next;
- if (fmq->content == fm)
- {
- GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
- plugin->sending_messages_tail, fmq);
- GNUNET_free (fmq);
- }
- fmq = fmq_next;
- }
-
- (session->mac->fragment_messages_out_count)--;
- session->fragment_messages_out_count--;
- plugin->pending_Fragment_Messages--;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
- plugin->pending_Fragment_Messages, GNUNET_NO);
- GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
- endpoint->sending_messages_tail, fm);
- GNUNET_FRAGMENT_context_destroy (fm->fragcontext);
- if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (fm->timeout_task);
- fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- }
-
- GNUNET_free (fm);
-
- queue_session (plugin, session);
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Free pending fragment messages %p, session %p\n", fm,
- session);
-#endif
-}
-
-/**
- * function to fill the radiotap header
- * @param plugin pointer to the plugin struct
- * @param endpoint pointer to the endpoint
- * @param header pointer to the radiotap header
- * @return GNUNET_YES at success
- */
-static int
-getRadiotapHeader (struct Plugin *plugin, struct MacEndpoint *endpoint,
- struct Radiotap_Send *header)
-{
-
- if (endpoint != NULL)
- {
- header->rate = endpoint->rate;
- header->tx_power = endpoint->tx_power;
- header->antenna = endpoint->antenna;
- }
- else
- {
- header->rate = 255;
- header->tx_power = 0;
- header->antenna = 0;
- }
-
- return GNUNET_YES;
-}
-
-/**
- * function to generate the wlan hardware header for one packet
- * @param Header address to write the header to
- * @param to_mac_addr address of the recipient
- * @param plugin pointer to the plugin struct
- * @param size size of the whole packet, needed to calculate the time to send the packet
- * @return GNUNET_YES if there was no error
- */
-static int
-getWlanHeader (struct ieee80211_frame *Header,
- const struct MacAddress *to_mac_addr, struct Plugin *plugin,
- unsigned int size)
-{
- uint16_t *tmp16;
- const int rate = 11000000;
-
- Header->i_fc[0] = IEEE80211_FC0_TYPE_DATA;
- Header->i_fc[1] = 0x00;
- memcpy (&Header->i_addr3, &mac_bssid_gnunet, sizeof (mac_bssid_gnunet));
- memcpy (&Header->i_addr2, plugin->mac_address.mac,
- sizeof (plugin->mac_address));
- memcpy (&Header->i_addr1, to_mac_addr, sizeof (struct MacAddress));
-
- tmp16 = (uint16_t *) Header->i_dur;
- *tmp16 = (uint16_t) GNUNET_htole16 ((size * 1000000) / rate + 290);
- Header->llc[0] = WLAN_LLC_DSAP_FIELD;
- Header->llc[1] = WLAN_LLC_SSAP_FIELD;
-
- return GNUNET_YES;
-}
-
-
-/**
- * function to add a fragment of a message to send
- * @param cls FragmentMessage this message belongs to
- * @param hdr pointer to the start of the message
- */
-static void
-add_message_for_send (void *cls, const struct GNUNET_MessageHeader *hdr)
-{
-
- struct FragmentMessage *fm = cls;
- struct FragmentMessage_queue *fmqueue;
-
- GNUNET_assert (cls != NULL);
- GNUNET_assert (fm->frag == NULL);
- struct MacEndpoint *endpoint = fm->session->mac;
- struct Plugin *plugin = endpoint->plugin;
- struct GNUNET_MessageHeader *msgheader;
- struct GNUNET_MessageHeader *msgheader2;
- uint16_t size;
-
-#if DEBUG_wlan_retransmission > 1
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Adding fragment of message %p to send, session %p, endpoint %p, type %u\n",
- fm, fm->session, endpoint, hdr->type);
-#endif
-
- size =
- sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
- sizeof (struct ieee80211_frame) + ntohs (hdr->size);
- fm->frag = GNUNET_malloc (size);
- fm->size = size;
-
- msgheader = (struct GNUNET_MessageHeader *) fm->frag;
- msgheader->size = htons (size);
- msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
-
- fm->radioHeader = (struct Radiotap_Send *) &msgheader[1];
- fm->ieeewlanheader = (struct ieee80211_frame *) &fm->radioHeader[1];
- msgheader2 = (struct GNUNET_MessageHeader *) &fm->ieeewlanheader[1];
- memcpy (msgheader2, hdr, ntohs (hdr->size));
-
- fmqueue = GNUNET_malloc (sizeof (struct FragmentMessage_queue));
- fmqueue->content = fm;
-
- GNUNET_CONTAINER_DLL_insert_tail (plugin->sending_messages_head,
- plugin->sending_messages_tail, fmqueue);
- set_next_send (plugin);
-}
-
-
-/**
- * We have been notified that gnunet-helper-transport-wlan 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 gnunet-helper-transport-wlan 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-helper-transport-wlan process.
- *
- * @param plugin the transport plugin
- * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
- */
-static int
-wlan_transport_start_wlan_helper (struct Plugin *plugin)
-{
- const char *filenamehw = "gnunet-helper-transport-wlan";
- const char *filenameloopback = "gnunet-helper-transport-wlan-dummy";
- char *absolute_filename = NULL;
-
- if (plugin->helper_is_running == GNUNET_YES)
- {
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan_transport_start_wlan_helper not needed, helper already running!");
-#endif
- return GNUNET_YES;
- }
-
- plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, 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_YES, GNUNET_NO);
- if (plugin->server_stdin == NULL)
- return GNUNET_SYSERR;
-
- if ((plugin->testmode == 1) || (plugin->testmode == 2))
- {
- if (GNUNET_OS_check_helper_binary (filenameloopback) == GNUNET_YES)
- {
- absolute_filename = GNUNET_strdup (filenameloopback);
- }
- else
- {
- char cwd[FILENAME_MAX];
-
- GNUNET_assert (getcwd (cwd, sizeof (cwd)) != NULL);
-
- GNUNET_asprintf (&absolute_filename, "%s%s%s", cwd, DIR_SEPARATOR_STR,
- filenameloopback);
-
- if (GNUNET_DISK_file_test (filenameloopback) != GNUNET_YES)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- "Helper `%s' not found! %i\n", absolute_filename);
- GNUNET_break (0);
- }
- }
- }
-
- /* Start the server process */
-
- if (plugin->testmode == 0)
- {
-
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Starting gnunet-helper-transport-wlan process cmd: %s %s %i\n",
- filenamehw, plugin->interface, plugin->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-helper-transport-wlan 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-helper-transport-wlan not found, please look if it exists and is the $PATH variable!\n");
- GNUNET_break (0);
- }
-
- }
- else if (plugin->testmode == 1)
- {
-
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
- "Starting gnunet-helper-transport-wlan-dummy loopback 1 process cmd: %s %s %i\n",
- absolute_filename, plugin->interface, plugin->testmode);
-#endif
- plugin->server_proc =
- GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
- absolute_filename, absolute_filename, "1",
- NULL);
- if (plugin->server_proc == NULL)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- "`%s' not found, please look if it exists and is in the $PATH variable!\n",
- absolute_filename);
- GNUNET_break (0);
- }
- }
- else if (plugin->testmode == 2)
- {
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
- "Starting gnunet-helper-transport-wlan-dummy loopback 2 process cmd: %s %s %i\n",
- absolute_filename, plugin->interface, plugin->testmode);
-#endif
-
- plugin->server_proc =
- GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
- absolute_filename, absolute_filename, "2",
- NULL);
- if (plugin->server_proc == NULL)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- "`%s' not found, please look if it exists and is in the $PATH variable!\n",
- absolute_filename);
- GNUNET_break (0);
- }
- }
- if (absolute_filename != NULL)
- GNUNET_free (absolute_filename);
- if (plugin->server_proc == NULL)
- {
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Failed to start gnunet-helper-transport-wlan 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 gnunet-helper-transport-wlan\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);
-
- plugin->helper_is_running = GNUNET_YES;
- return GNUNET_YES;
-}
-
-/**
- * Stops the gnunet-helper-transport-wlan 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->helper_is_running == GNUNET_NO)
- {
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan_transport_stop_wlan_helper not needed, helper already stopped!");
-#endif
- return GNUNET_YES;
- }
-
- 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, SIGKILL);
- GNUNET_OS_process_wait (plugin->server_proc);
- GNUNET_OS_process_close (plugin->server_proc);
-
- plugin->helper_is_running = GNUNET_NO;
-
- 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 helper. 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);
-
- set_next_beacon_time (plugin);
-
- }
- else
- {
- GNUNET_assert (bytes == size);
- set_next_beacon_time (plugin);
- set_next_send (plugin);
- }
- GNUNET_free (msgheader);
-
-
-}
-
-/**
- * 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)
-{
- struct FragmentMessage *fm = cls;
-
- GNUNET_assert (fm != NULL);
- fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
- {
- return;
- }
- free_fragment_message (fm->session->mac->plugin, fm);
-}
-
-/**
- * Function to check if there is some space in the fragment queue
- * inserts a message if space is available
- * @param plugin the plugin struct
- */
-
-static void
-check_fragment_queue (struct Plugin *plugin)
-{
- struct Session *session;
- struct FragmentMessage *fm;
- struct GNUNET_PeerIdentity pid;
-
- struct PendingMessage *pm;
-
- if (plugin->pending_Fragment_Messages < FRAGMENT_QUEUE_SIZE)
- {
- session = get_next_queue_session (plugin);
- if (session != NULL)
- {
- pm = session->pending_message_head;
- GNUNET_assert (pm != NULL);
- GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
- session->pending_message_tail, pm);
- session->mac->fragment_messages_out_count++;
- session->fragment_messages_out_count++;
- plugin->pending_Fragment_Messages++;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
- plugin->pending_Fragment_Messages, GNUNET_NO);
-
- fm = GNUNET_malloc (sizeof (struct FragmentMessage));
- fm->session = session;
- fm->timeout.abs_value = pm->timeout.abs_value;
- fm->frag = NULL;
- fm->fragcontext =
- GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
- &plugin->tracker,
- GNUNET_TIME_UNIT_SECONDS,
- &(pm->msg->header),
- &add_message_for_send, fm);
- fm->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
- (fm->timeout), fragmentmessage_timeout,
- fm);
- GNUNET_CONTAINER_DLL_insert_tail (session->mac->sending_messages_head,
- session->mac->sending_messages_tail,
- fm);
-
- if (pm->transmit_cont != NULL)
- {
- pid = session->target;
- pm->transmit_cont (pm->transmit_cont_cls, &pid, GNUNET_OK);
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "called pm->transmit_cont for %p\n", session);
-#endif
- }
- else
- {
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "no pm->transmit_cont for %p\n", session);
-#endif
- }
- GNUNET_free (pm);
-
- if (session->pending_message_head != NULL)
- {
- //requeue session
- queue_session (plugin, session);
- }
-
- }
- }
-
- //check if timeout changed
- set_next_send (plugin);
-}
-
-/**
- * Function to send an ack, does not free the ack
- * @param plugin pointer to the plugin
- */
-static void
-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,
- "Sending ack for message_id %u for mac endpoint %p, size %u\n",
- ack->message_id, ack->endpoint,
- ntohs (ack->hdr->size) - sizeof (struct Radiotap_Send));
-#endif
-
- GNUNET_assert (plugin != NULL);
- GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks send"), 1,
- GNUNET_NO);
-
- getRadiotapHeader (plugin, ack->endpoint, ack->radioHeader);
- getWlanHeader (ack->ieeewlanheader, &ack->endpoint->addr, plugin,
- ntohs (ack->hdr->size));
-
- bytes =
- GNUNET_DISK_file_write (plugin->server_stdin_handle, ack->hdr,
- ntohs (ack->hdr->size));
- if (bytes == GNUNET_SYSERR)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- _
- ("Error writing to wlan helper. 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 == 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);
- }
-}
-
-/**
- * Function called when wlan helper is ready to get some data
- *
- * @param cls closure
- * @param tc GNUNET_SCHEDULER_TaskContext
- */
-static void
-do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct Plugin *plugin = cls;
-
- GNUNET_assert (plugin != NULL);
-
- plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
-
- struct Session *session;
- struct FragmentMessage *fm;
- struct Finish_send *finish;
- struct FragmentMessage_queue *fmq;
- ssize_t bytes;
-
- if (plugin->ack_send_queue_head != NULL)
- {
- send_ack (plugin);
- return;
- }
-
- //test if a "hello-beacon" has to be send
- if (GNUNET_TIME_absolute_get_remaining (plugin->beacon_time).rel_value == 0)
- {
- send_hello_beacon (plugin);
- return;
- }
-
- if (plugin->sending_messages_head != NULL)
- {
- GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan fragments send"), 1,
- GNUNET_NO);
-
- fmq = plugin->sending_messages_head;
- fm = fmq->content;
- GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
- plugin->sending_messages_tail, fmq);
- GNUNET_free (fmq);
-
- session = fm->session;
- GNUNET_assert (session != NULL);
-
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT for fragment message %p, size: %u\n",
- fm, fm->size);
-#endif
-
- getRadiotapHeader (plugin, session->mac, fm->radioHeader);
- getWlanHeader (fm->ieeewlanheader, &(fm->session->mac->addr), plugin,
- fm->size);
-
- bytes =
- GNUNET_DISK_file_write (plugin->server_stdin_handle, fm->frag,
- fm->size);
-
-
- if (bytes != fm->size)
- {
- finish = GNUNET_malloc (sizeof (struct Finish_send));
- finish->plugin = plugin;
- finish->msgstart = (struct GNUNET_MessageHeader *) fm->frag;
- GNUNET_assert (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
-
- if (bytes == GNUNET_SYSERR)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- _
- ("Error writing to wlan helper. 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
- {
- GNUNET_free (fm->frag);
- fm->frag = NULL;
- set_next_send (plugin);
- }
- GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
- return;
- }
-
-#if 1
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "do_transmit did nothing, should not happen!\n");
-#endif
- set_next_send (plugin);
-}
-
-/**
- * Another peer has suggested an address for this
- * peer and transport plugin. Check that this could be a valid
- * address. If so, consider adding it to the list
- * of addresses.
- *
- * @param cls closure
- * @param addr pointer to the address
- * @param addrlen length of addr
- * @return GNUNET_OK if this is a plausible address for this peer
- * and transport
- */
-static int
-wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
-{
- //struct Plugin *plugin = cls;
-
- /* check if the address is plausible; if so,
- * add it to our list! */
-
- GNUNET_assert (cls != NULL);
- //FIXME mitm is not checked
- //Mac Address has 6 bytes
- if (addrlen == 6)
- {
- /* TODO check for bad addresses like multicast, broadcast, etc */
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan_plugin_address_suggested got good address, size %u!\n",
- addrlen);
-#endif
- return GNUNET_OK;
- }
-#if DEBUG_wlan
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan_plugin_address_suggested got bad address, size %u!\n",
- addrlen);
-#endif
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Creates a new outbound session the transport service will use to send data to the
- * peer
- *
- * @param cls the plugin
- * @param address the address
- * @return the session or NULL of max connections exceeded
- */
-
-static struct Session *
-wlan_plugin_get_session (void *cls,
- const struct GNUNET_HELLO_Address *address)
-{
- struct Session * s = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "To be implemented\n");
- GNUNET_break (0);
- return s;
-}
-
-/**
- * Function that can be used by the transport service to transmit
- * a message using the plugin. Note that in the case of a
- * peer disconnecting, the continuation MUST be called
- * prior to the disconnect notification itself. This function
- * will be called with this peer's HELLO message to initiate
- * a fresh connection to another peer.
- *
- * @param cls closure
- * @param session which session must be used
- * @param msgbuf the message to transmit
- * @param msgbuf_size number of bytes in 'msgbuf'
- * @param priority how important is the message (most plugins will
- * ignore message priority and just FIFO)
- * @param to how long to wait at most for the transmission (does not
- * require plugins to discard the message after the timeout,
- * just advisory for the desired delay; most plugins will ignore
- * this as well)
- * @param cont continuation to call once the message has
- * been transmitted (or if the transport is ready
- * for the next transmission call; or if the
- * peer disconnected...); can be NULL
- * @param cont_cls closure for cont
- * @return number of bytes used (on the physical network, with overheads);
- * -1 on hard errors (i.e. address invalid); 0 is a legal value
- * and does NOT mean that the message was not transmitted (DV)
- */
-static ssize_t
-wlan_plugin_send (void *cls,
- struct Session *session,
- const char *msgbuf, size_t msgbuf_size,
- unsigned int priority,
- struct GNUNET_TIME_Relative to,
- GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
-{
- ssize_t sent = -1;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "To be implemented\n");
- GNUNET_break (0);
- return sent;
-}
-
-
-/**
- * Function that can be used by the transport service to transmit
- * a message using the plugin.
- *
- * @param cls closure
- * @param target who should receive this message
- * @param priority how important is the message
- * @param msgbuf the message to transmit
- * @param msgbuf_size number of bytes in 'msgbuf'
- * @param timeout when should we time out
- * @param session which session must be used (or NULL for "any")
- * @param addr the address to use (can be NULL if the plugin
- * is "on its own" (i.e. re-use existing TCP connection))
- * @param addrlen length of the address in bytes
- * @param force_address GNUNET_YES if the plugin MUST use the given address,
- * otherwise the plugin may use other addresses or
- * existing connections (if available)
- * @param cont continuation to call once the message has
- * been transmitted (or if the transport is ready
- * for the next transmission call; or if the
- * peer disconnected...)
- * @param cont_cls closure for cont
- * @return number of bytes used (on the physical network, with overheads);
- * -1 on hard errors (i.e. address invalid); 0 is a legal value
- * and does NOT mean that the message was not transmitted (DV)
- */
-static ssize_t
-wlan_plugin_send_old (void *cls, const struct GNUNET_PeerIdentity *target,
- const char *msgbuf, size_t msgbuf_size, unsigned int priority,
- struct GNUNET_TIME_Relative timeout, struct Session *session,
- const void *addr, size_t addrlen, int force_address,
- GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
-{
- struct Plugin *plugin = cls;
- struct PendingMessage *newmsg;
- struct WlanHeader *wlanheader;
-
- GNUNET_assert (plugin != NULL);
- //check if msglen > 0
- GNUNET_assert (msgbuf_size > 0);
-
- //get session if needed
- if (session == NULL)
- {
- if (wlan_plugin_address_suggested (plugin, addr, addrlen) == GNUNET_OK)
- {
- session = get_session (plugin, addr, target);
- }
- else
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- _("Wlan Address len %d is wrong\n"), addrlen);
- return -1;
- }
- }
-
- GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan messages queued"), 1,
- GNUNET_NO);
-
- //queue message:
-
- //queue message in session
- //test if there is no other message in the "queue"
- //FIXME: to many send requests
- if (session->pending_message_head != NULL)
- {
- newmsg = session->pending_message_head;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan_plugin_send: a pending message is already in the queue for this client\n remaining time to send this message is %u, queued fragment messages for this mac connection %u\n",
- GNUNET_TIME_absolute_get_remaining (newmsg->
- timeout).rel_value,
- session->mac->fragment_messages_out_count);
- }
-
- newmsg = GNUNET_malloc (sizeof (struct PendingMessage));
- newmsg->msg = GNUNET_malloc (msgbuf_size + sizeof (struct WlanHeader));
- wlanheader = newmsg->msg;
- //copy msg to buffer, not fragmented / segmented yet, but with message header
- wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader));
- wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA);
- memcpy (&(wlanheader->target), target, sizeof (struct GNUNET_PeerIdentity));
- memcpy (&(wlanheader->source), plugin->env->my_identity,
- sizeof (struct GNUNET_PeerIdentity));
- wlanheader->crc = 0;
- memcpy (&wlanheader[1], msgbuf, msgbuf_size);
- wlanheader->crc =
- htonl (GNUNET_CRYPTO_crc32_n
- ((char *) wlanheader, msgbuf_size + sizeof (struct WlanHeader)));
-
- newmsg->transmit_cont = cont;
- newmsg->transmit_cont_cls = cont_cls;
- newmsg->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-
- newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
-
- newmsg->message_size = msgbuf_size + sizeof (struct WlanHeader);
-
- GNUNET_CONTAINER_DLL_insert_tail (session->pending_message_head,
- session->pending_message_tail, newmsg);