+static void
+set_next_send (struct Plugin *const plugin)
+{
+ struct GNUNET_TIME_Relative next_send;
+
+ //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, sizeof (mac_bssid));
+ 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) htole16 ((size * 1000000) / rate + 290);
+ Header->llc[0] = WLAN_LLC_DSAP_FIELD;
+ Header->llc[1] = WLAN_LLC_SSAP_FIELD;
+
+#if DEBUG_wlan_ip_udp_packets_on_air > 1
+ uint crc = 0;
+ uint16_t *x;
+ int count;
+
+ Header->ip.ip_dst.s_addr = *((uint32_t *) & to_mac_addr->mac[2]);
+ Header->ip.ip_src.s_addr = *((uint32_t *) & plugin->mac_address.mac[2]);
+ Header->ip.ip_v = 4;
+ Header->ip.ip_hl = 5;
+ Header->ip.ip_p = 17;
+ Header->ip.ip_ttl = 1;
+ Header->ip.ip_len = htons (size + 8);
+ Header->ip.ip_sum = 0;
+ x = (uint16_t *) & Header->ip;
+ count = sizeof (struct iph);
+ while (count > 1)
+ {
+ /* This is the inner loop */
+ crc += (unsigned short) *x++;
+ count -= 2;
+ }
+ /* Add left-over byte, if any */
+ if (count > 0)
+ crc += *(unsigned char *) x;
+ crc = (crc & 0xffff) + (crc >> 16);
+ Header->ip.ip_sum = htons (~(unsigned short) crc);
+ Header->udp.len = htons (size - sizeof (struct ieee80211_frame));
+
+#endif
+
+ return GNUNET_YES;
+}
+
+/**
+ * 32bit CRC
+ *
+ * @param msgbuf pointer tor the data
+ * @param msgbuf_size size of the data
+ *
+ * @return 32bit crc value
+ */
+
+uint32_t
+getcrc32 (const char *msgbuf, size_t msgbuf_size)
+{
+
+ return GNUNET_CRYPTO_crc32_n (msgbuf, msgbuf_size);;
+}
+
+/**
+ * 16bit CRC
+ *
+ * @param msgbuf pointer tor the data
+ * @param msgbuf_size size of the data
+ *
+ * @return 16bit crc value
+ */
+
+uint16_t
+getcrc16 (const char *msgbuf, size_t msgbuf_size)
+{
+ //TODO calc some crc
+ return 0;
+}
+
+/**
+ * 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
+ */
+
+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 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
+ * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
+ */
+static int
+wlan_transport_start_wlan_helper (struct Plugin *plugin)