+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
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Adding fragment of message %p to send, session %p, endpoint %p\n", fm,
+ fm->session, endpoint);
+#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);
+}
+
+/**
+ * function to send a hallo beacon
+ * @param plugin pointer to the plugin struct
+ */
+static void
+send_hello_beacon(struct Plugin * plugin)
+{
+
+#if DEBUG_wlan
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
+#endif
+
+ uint16_t size;
+ ssize_t bytes;
+ uint16_t hallo_size;
+ struct GNUNET_MessageHeader * msgheader;
+ struct ieee80211_frame * ieeewlanheader;
+ struct Radiotap_Send * radioHeader;
+ struct GNUNET_MessageHeader * msgheader2;
+
+ hallo_size = GNUNET_HELLO_size(*(plugin->env->our_hello));
+ GNUNET_assert(sizeof(struct WlanHeader) + hallo_size <= WLAN_MTU);
+ size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
+ + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
+ + hallo_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(*(plugin->env->our_hello))
+ + sizeof(struct GNUNET_MessageHeader));
+
+ msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
+ memcpy(&msgheader2[1], *plugin->env->our_hello, hallo_size);
+
+ bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
+
+ if (bytes == GNUNET_SYSERR)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
+ errno, strerror(errno));
+
+ }
+ GNUNET_assert(bytes != GNUNET_SYSERR);
+ GNUNET_assert(bytes == size);
+ GNUNET_free(msgheader);
+
+ set_next_beacon_time(plugin);
+ set_next_send(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
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Adding ack with message id %u to send, AckSendQueue %p, endpoint %p\n",
+ msg_id, ack, endpoint);
+#endif
+
+ set_next_send(plugin);
+}
+
+/**
+ * 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_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_assert(pm != NULL);
+
+ 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);
+ 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(GNUNET_ERROR_TYPE_DEBUG,
+ "called pm->transmit_cont for %p\n", session);
+#endif
+ }
+ else
+ {
+#if DEBUG_wlan
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "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
+ * @param ack pointer to the ack to send
+ */
+static void
+send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
+{
+
+ ssize_t bytes;
+
+#if DEBUG_wlan
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "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
+
+ 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(GNUNET_ERROR_TYPE_ERROR,
+ _("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);
+ }
+ else
+ {
+ GNUNET_free(finish->msgstart);
+ GNUNET_free(finish);
+ 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;
+
+ 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;
+ 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);
+ 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)
+ {
+ 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(
+ GNUNET_ERROR_TYPE_DEBUG,
+ "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 == GNUNET_SYSERR)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
+ errno, strerror(errno));
+
+ }
+ 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);
+ fm->frag = NULL;
+ }
+ else
+ {
+ GNUNET_free(fm->frag);
+ fm->frag = NULL;
+ set_next_send(plugin);
+ }
+ GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
+ return;
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
+ "do_transmit did nothing, should not happen!\n");
+}
+
+/**
+ * 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 */
+ return GNUNET_OK;
+ }
+
+ return GNUNET_SYSERR;