- * Funktion to check if all fragments where send and the acks received
- * frees the space if finished
- * @param plugin the plugin struct
- * @param fm the message to check
- */
-static void
-check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
-{
- //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
- unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
- - sizeof(struct FragmentationHeader)));
- uint64_t tmpfield = UINT64_MAX;
- tmpfield = tmpfield >> maxack;
-
- //#if DEBUG_wlan
- if (maxack != 63)
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Test bitfields %X and %X, maxack is %u, fm size %u\n",
- fm->ack_bitfield, tmpfield, maxack, fm->message_size);
- //#endif
-
- if (fm->ack_bitfield == tmpfield)
- {
-
- free_fragment_message(plugin, fm);
-
-#if DEBUG_wlan
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Finished sending and got all acks for a fragmented message\n");
-#endif
-
- check_next_fragment_timeout(plugin);
- check_fragment_queue(plugin);
-
- }
-}
-
-/**
- * Function to set the next fragment number
- * @param fm use this FragmentMessage
- */
-
-void
-set_next_message_fragment_pos(struct FragmentMessage * fm)
-{
-
- //check if retransmit is needed
- if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
- {
-
- // be positive and try again later :-D
- fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
- // find first missing fragment
-
- fm->message_pos = 0;
- }
-
- //test if ack 0 (or X) was already received
- while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
- {
- fm->message_pos++;
- }
-
-}
-
-void
-send_hello_beacon(struct Plugin * plugin)
-{
-
-#if DEBUG_wlan
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
-#endif
-
- uint16_t size = 0;
- ssize_t bytes;
- struct GNUNET_MessageHeader * msgheader = NULL;
- struct ieee80211_frame * ieeewlanheader = NULL;
- struct Radiotap_Send * radioHeader = NULL;
- struct GNUNET_MessageHeader * msgheader2 = NULL;
-
- GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
- *(plugin->env->our_hello)) <= WLAN_MTU);
- size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
- + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
- + GNUNET_HELLO_size(*(plugin->env->our_hello));
-
- 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);
-
- 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, GNUNET_HELLO_size(
- *(plugin->env->our_hello)));
-
- 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);
- check_next_fragment_timeout(plugin);
-}
-
-static void
-send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
-{
-
- uint16_t size = 0;
- ssize_t bytes;
- struct GNUNET_MessageHeader * msgheader = NULL;
- struct ieee80211_frame * ieeewlanheader = NULL;
- struct Radiotap_Send * radioHeader = NULL;
- struct FragmentationAckHeader * msgheader2 = NULL;
-
- GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
-
-#if DEBUG_wlan
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Sending ack for message_id %u with fragment field %u\n",
- ack->message_id, ack->fragments_field);
-#endif
-
- size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
- + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
- 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, ack->session, radioHeader);
- ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
- getWlanHeader(ieeewlanheader, ack->session->addr, plugin);
-
- msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
- msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
- msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
- msgheader2->message_id = htonl(ack->message_id);
- msgheader2->fragment_field = htonll(ack->fragments_field);
-
- 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);
- check_next_fragment_timeout(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 (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
- return;
-
- struct Session * session = NULL;
- struct FragmentMessage * fm = NULL;
- struct ieee80211_frame * ieeewlanheader = NULL;
- struct Radiotap_Send * radioHeader = NULL;
- struct GNUNET_MessageHeader * msgheader = NULL;
-
- struct FragmentationHeader fragheader;
- struct FragmentationHeader * fragheaderptr = NULL;
- struct Finish_send * finish = NULL;
- struct AckSendQueue * ack;
- uint16_t size = 0;
- ssize_t bytes;
- const char * copystart = NULL;
- uint16_t copysize = 0;
- uint copyoffset = 0;
-
- 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;
-
- }
-
- fm = plugin->pending_Fragment_Messages_head;
- if (fm != NULL)
- {
- session = fm->session;
- GNUNET_assert(session != NULL);
-
- // test if message timed out
- if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
- {
-#if DEBUG_wlan
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
-#endif
-
- check_fragment_queue(plugin);
- free_fragment_message(plugin, fm);
-
- }
- else
- {
-
- //if (fm->message_size > WLAN_MTU)
- // {
- size += sizeof(struct FragmentationHeader);
-
- set_next_message_fragment_pos(fm);
-
- copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
- * fm->message_pos;
-
-#if DEBUG_wlan
- GNUNET_log(
- GNUNET_ERROR_TYPE_DEBUG,
- "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
- fm->message_id_out, fm->message_pos, copysize
- + sizeof(struct FragmentationHeader), copyoffset,
- GNUNET_TIME_absolute_get_remaining(fm->timeout));
-#endif
-
- fragheader.fragment_off_or_num = htons(fm->message_pos);
- fragheader.message_id = htonl(fm->message_id_out);
- copystart = fm->msg + copyoffset;
- copysize = GNUNET_MIN(fm->message_size - copyoffset,
- WLAN_MTU - sizeof(struct FragmentationHeader));
-
- if (copyoffset >= fm->message_size)
- {
- GNUNET_log(
- GNUNET_ERROR_TYPE_ERROR,
- "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
- copyoffset, fm->message_size, WLAN_MTU
- - sizeof(struct FragmentationHeader), copysize,
- fm->message_pos);
- }
- GNUNET_assert(copyoffset < fm->message_size);
- //FIXME remove later
- GNUNET_assert(copystart < fm->msg + fm->message_size);
-
- fragheader.header.size = htons(copysize
- + sizeof(struct FragmentationHeader));
- fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
-
- /* }
- else
- {
- // there is no need to split
- copystart = fm->msg;
- copysize = fm->message_size;
- }*/
-
- size += copysize;
- size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
- + sizeof(struct GNUNET_MessageHeader);
- 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, session, radioHeader);
-
- ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
- getWlanHeader(ieeewlanheader, fm->session->addr, plugin);
-
- //could be faster if content is just send and not copyed before
- //fragmentheader is needed
- //if (fm->message_size > WLAN_MTU)
- // {
- fragheader.message_crc = htons(getcrc16(copystart, copysize));
- memcpy(&ieeewlanheader[1], &fragheader,
- sizeof(struct FragmentationHeader));
- fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
- memcpy(&fragheaderptr[1], copystart, copysize);
- /* }
- else
- {
- memcpy(&ieeewlanheader[1], copystart, copysize);
- }*/
-
- 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);
-
- if (bytes != size)
- {
- finish = GNUNET_malloc(sizeof( struct Finish_send));
- finish->plugin = plugin;
- finish->msgheader = (char *) msgheader + bytes;
- finish->size = size - bytes;
- finish->msgstart = msgheader;
-
- 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);
-
- }
- else
- {
- GNUNET_assert(bytes == size);
-
- GNUNET_free(msgheader);
- check_next_fragment_timeout(plugin);
- }
-
- //check if this was the last fragment of this message, if true then queue at the end of the list
- if (copysize + copyoffset >= fm->message_size)
- {
- GNUNET_assert(copysize + copyoffset == fm->message_size);
-
- GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
- plugin->pending_Fragment_Messages_tail, fm);
-
- GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
- plugin->pending_Fragment_Messages_tail, fm);
- // if fragments have opimized timeouts
- //sort_fragment_into_queue(plugin,fm);
-
- }
-
- }
- return;
- }
- GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
- "do_transmit did nothing, should not happen!\n");
-}
-
-static void
-finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct Finish_send * finish;
- struct Plugin * plugin;
- ssize_t bytes;
-
- finish = cls;
- plugin = finish->plugin;
-
- plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
-
- bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
- finish->msgheader, finish->size);
- GNUNET_assert(bytes != GNUNET_SYSERR);
-
- GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
- 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);
- check_next_fragment_timeout(plugin);
- }
-
-}
-
-int
-getRadiotapHeader(struct Plugin * plugin, struct Session * session,
- struct Radiotap_Send * header)
-{
-
- if (session != null){
- header->rate = session->rate;
- header->tx_power = session->tx_power;
- header->antenna = session->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
- * @return GNUNET_YES if there was no error
- */
-
-int
-getWlanHeader(struct ieee80211_frame * Header, const char * const to_mac_addr,
- struct Plugin * plugin)
-{
- 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(plugin->mac_address));
- 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)
-{
- //TODO calc some crc
- return 0;
-}
-
-/**
- * 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 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(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 = NULL;
- struct WlanHeader * wlanheader = 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);
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
- _("Wlan Address len %d is wrong\n"), addrlen);
- return -1;
- }
- }
-
- //TODO target "problem" not solved
- //if (session->target != NULL){
- // GNUNET_assert(session->target == *target);
- //} else {
- session->target = *target;
- //}
-
-
- //queue message:
-
- //queue message in session
- //test if there is no other message in the "queue"
- //FIXME: to many send requests
- //GNUNET_assert (session->pending_message == NULL);
- if (session->pending_message != NULL)
- {
- newmsg = session->pending_message;
- GNUNET_log(
- GNUNET_ERROR_TYPE_ERROR,
- "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 %u\n",
- GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
- session->fragment_messages_out_count);
- if (session->pending_message2 != NULL)
- {
- GNUNET_log(
- GNUNET_ERROR_TYPE_ERROR,
- "wlan_plugin_send: two pending messages are already in the queue for this client\n");
- return -1;
- }
- }
-
- newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
- (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
- wlanheader = (struct 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));
- wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
- memcpy(&wlanheader[1], msgbuf, msgbuf_size);
- 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);
-
- if (session->pending_message == NULL)
- {
- session->pending_message = newmsg;
- }
- else
- {
- session->pending_message2 = newmsg;
- }
-
-#if DEBUG_wlan
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "New message for %p with size (incl wlan header) %u added\n", session,
- newmsg->message_size);
-#endif
-
- //queue session
- queue_Session(plugin, session);
-
- check_fragment_queue(plugin);
- //FIXME not the correct size
- return msgbuf_size;
-
-}
-
-/**
- * function to get the first message in the fragement queue (out) of a session
- * @param session pointer to the session
- * @return pointer to the struct FragmentMessage
- */
-static struct FragmentMessage *
-get_fragment_message_from_session(struct Session * session)
-{
- struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
- while (fm != NULL)
- {
- if (fm->session == session)
- {
- return fm;
- }
- fm = fm->next;
- }
- return NULL;
-}
-
-/**
- * function to get the message in the fragement queue (out) of a session with a specific id
- * @param session pointer to the session
- * @param message_id id of the message
- * @return pointer to the struct FragmentMessage
- */
-static struct FragmentMessage *
-get_fragment_message_from_session_and_id(struct Session * session,
- uint32_t message_id)
-{
- struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
- while (fm != NULL)
- {
- if ((fm->session == session) && (fm->message_id_out == message_id))
- {
- return fm;
- }
- fm = fm->next;
- }
- return NULL;
-}
-
-/**
- * Function that can be used to force the plugin to disconnect
- * from the given peer and cancel all previous transmissions
- * (and their continuation).
- *
- * @param cls closure
- * @param target peer from which to disconnect
- */
-static void
-wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
-{
- struct Plugin *plugin = cls;
- struct Sessionqueue * queue = plugin->sessions;
- struct Sessionqueue * pendingsession = plugin->pending_Sessions;
- struct PendingMessage * pm = NULL;
- struct FragmentMessage * fm;
- struct Receive_Message_Queue * receive_queue;
-
- // just look at all the session for the needed one
- while (queue != NULL)
- {
- // content is never NULL
- GNUNET_assert (queue->content != NULL);
- if (memcmp(target, &(queue->content->target),
- sizeof(struct GNUNET_PeerIdentity)) == 0)
- {
- //session found
- //is this session pending for send
- while (pendingsession != NULL)
- {
- if (pendingsession->content == queue->content)
- {
- plugin->pendingsessions--;
- GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
- plugin->pending_Sessions_tail, pendingsession);
- GNUNET_free(pendingsession);
- break;
- }
- pendingsession = pendingsession->next;
- }
-
- //is something of this session in the fragment queue?
- fm = get_fragment_message_from_session(queue->content);
- while (fm != NULL)
- {
- free_fragment_message(plugin, fm);
- fm = get_fragment_message_from_session(queue->content);
- }
- check_next_fragment_timeout(plugin);
-
- //dispose all received fragments
- receive_queue = get_receive_message_from_session(plugin,
- queue->content);
- while (receive_queue != NULL)
- {
- free_receive_message(plugin, receive_queue);
- receive_queue = get_receive_message_from_session(plugin,
- queue->content);
- }
-
- // remove PendingMessage
- pm = queue->content->pending_message;
- if (pm != NULL)
- {
- GNUNET_free_non_null(pm->msg);
- GNUNET_free(pm);
- }
-
- GNUNET_free(queue->content);
- GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
- GNUNET_free(queue);
- plugin->session_count--;
-
- return;
- }
- // try next
- queue = queue->next;
- }
-}
-
-/**
- * Convert the transports address to a nice, human-readable
- * format.
- *
- * @param cls closure
- * @param type name of the transport that generated the address
- * @param addr one of the addresses of the host, NULL for the last address
- * the specific address format depends on the transport
- * @param addrlen length of the address
- * @param numeric should (IP) addresses be displayed in numeric form?
- * @param timeout after how long should we give up?
- * @param asc function to call on each string
- * @param asc_cls closure for asc
- */
-static void
-wlan_plugin_address_pretty_printer(void *cls, const char *type,
- const void *addr, size_t addrlen, int numeric,
- struct GNUNET_TIME_Relative timeout,
- GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
-{
- char ret[92];
- const unsigned char * input;
-
- //GNUNET_assert(cls !=NULL);
- if (addrlen != 6)
- {
- /* invalid address (MAC addresses have 6 bytes) */
- GNUNET_break (0);
- asc(asc_cls, NULL);
- return;
- }
- input = (const unsigned char*) addr;
- GNUNET_snprintf(ret, sizeof(ret),
- "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
- input[0], input[1], input[2], input[3], input[4], input[5]);
- asc(asc_cls, ret);
-}
-
-/**
- * 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;
-}
-
-/**
- * Function called for a quick conversion of the binary address to
- * a numeric address. Note that the caller must not free the
- * address and that the next call to this function is allowed
- * to override the address again.
- *
- * @param cls closure
- * @param addr binary address
- * @param addrlen length of the address
- * @return string representing the same address
- */
-static const char*
-wlan_plugin_address_to_string (void *cls,
- const void *addr,
- size_t addrlen)
-{
- static char ret[40];
- const struct MacAddress *mac;
-
- if (addrlen != sizeof (struct MacAddress))
- {
- GNUNET_break (0);
- return NULL;
- }
- mac = addr;
- GNUNET_snprintf(ret, sizeof(ret),
- "%s Mac-Address %X:%X:%X:%X:%X:%X",
- PROTOCOL_PREFIX,
- mac->mac[0], mac->mac[1],
- mac->mac[2], mac->mac[3],
- mac->mac[4], mac->mac[5]);
- return ret;
-}
-
-/**
- * function to check if bitfield is representation of fragments of the message
- * @param rec_message message to check
- */
-
-void
-check_message_fragment_bitfield(struct Receive_Message_Queue * rec_message)
-{
- uint64_t checkfragments = 0;
- struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
-
- while (rec_queue != NULL)
- {
- setBit((char*) &checkfragments, rec_queue->num);
- rec_queue = rec_queue->next;
-
- }
- GNUNET_assert(checkfragments == rec_message->received_fragments);
-}
-
-/**
- * Function to test if fragment number already exists in the fragments received
- *
- * @param rec_message message this fragment belongs to
- * @param fh Fragmentheader of the fragment
- * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
- */
-
-static const int
-is_double_msg(struct Receive_Message_Queue * rec_message,
- struct FragmentationHeader * fh)
-{
- //test if bitfield is okay
-#if DEBUG_wlan
- check_message_fragment_bitfield(rec_message);
-#endif
-
- return testBit((char *) &rec_message->received_fragments, ntohs(
- fh->fragment_off_or_num));
-
-}
-
-/**
- * Function to insert a fragment in a queue of a message
- * @param session session the fragment belongs to
- * @param rec_queue fragment to add
- */
-
-static void
-insert_fragment_in_queue(struct Receive_Message_Queue * rec_message,
- struct Receive_Fragment_Queue * rec_queue)
-{
- GNUNET_assert(rec_message != NULL);
- GNUNET_assert(rec_queue != NULL);
-
- struct Receive_Fragment_Queue * rec_queue2 = rec_message->frag_head;
- struct WlanHeader * wlanheader = NULL;
-
- //this is the first fragment of the message (fragment id 0)
- if (rec_queue->num == 0)
- {
- wlanheader = (struct WlanHeader *) rec_queue->msg;
- rec_message->rec_size = ntohs(wlanheader->header.size);
- }
-
- //sort into list
- while (rec_queue2 != NULL)
- {
- if (rec_queue2->num > rec_queue->num)
- {
- //next element number is grater than the current num
- GNUNET_CONTAINER_DLL_insert_before(rec_message->frag_head, rec_message->frag_tail, rec_queue2, rec_queue);
- setBit((char *) &rec_message->received_fragments, rec_queue->num);
- return;
- }
- rec_queue = rec_queue->next;
- }
- //no element has a grater number
- GNUNET_CONTAINER_DLL_insert_tail(rec_message->frag_head, rec_message->frag_tail, rec_queue);
-
- setBit((char *) &rec_message->received_fragments, rec_queue->num);
-}
-
-/**
- * Function to dispose the fragments received for a message and the message
- * @param plugin pointer to the plugin struct
- * @param rec_message pointer to the struct holding the message which should be freed
- */
-
-static void
-free_receive_message(struct Plugin* plugin,
- struct Receive_Message_Queue * rec_message)
-{
- GNUNET_assert(rec_message !=NULL);
- struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
- struct Receive_Fragment_Queue * rec_queue2;
-
- while (rec_queue != NULL)
- {
- rec_queue2 = rec_queue;
- rec_queue = rec_queue->next;
- GNUNET_free(rec_queue2);
- }
-
- GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rec_message);
-
- GNUNET_assert(plugin->pending_receive_messages > 0);
- GNUNET_assert(rec_message->session->fragment_messages_in_count > 0);
-
- plugin->pending_receive_messages--;
- rec_message->session->fragment_messages_in_count--;
- GNUNET_free(rec_message);
-}
-
-/**
- * Function to check if all fragments of a message have been received
- * @param plugin the plugin handle
- * @param session_light information of the message sender
- * @param session session the message belongs to
- * @param rec_message pointer to the message that should be checked
- */
-
-static void
-check_rec_finished_msg(struct Plugin* plugin,
- struct Session_light * session_light, struct Session * session,
- struct Receive_Message_Queue * rec_message)
-{
- GNUNET_assert(rec_message !=NULL);
-
- struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
- int packetsize = rec_message->rec_size;
- int sum = 0;
- int aktnum = 0;
- uint64_t bitfield = 0;
- char * msg;
-
- //check if first fragment is present
- if (packetsize == MESSAGE_LENGHT_UNKNOWN)
- {
- return;
- }
- // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
- else if (packetsize < sizeof(struct WlanHeader)
- + sizeof(struct GNUNET_MessageHeader))
- {
-#if DEBUG_wlan
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Message not big enough\n");
-#endif
- free_receive_message(plugin, rec_message);
- return;
- }
-
-#if DEBUG_wlan
- check_message_fragment_bitfield(rec_message);
-#endif
-
- bitfield = ~bitfield;
- bitfield = bitfield >> (63 - rec_message->frag_tail->num);
- if (rec_message->received_fragments == bitfield)
- {
-
- while (rec_queue != NULL)
- {
- sum += rec_queue->size;
- rec_queue = rec_queue->next;
- }
- //sum should always be smaller or equal of
- GNUNET_assert(sum <= packetsize);
- if (sum == packetsize)
- {
-
-#if DEBUG_wlan
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "check_rec_finished_msg: A message for %p is complete\n", session);
-#endif
-
- //TODO use mst
- //copy fragments together
- msg = GNUNET_malloc(packetsize);
- rec_queue = rec_message->frag_head;
- aktnum = 0;
- while (rec_queue != NULL)
- {
- //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
- memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
- aktnum += rec_queue->size;
- rec_queue = rec_queue->next;
- }
- free_receive_message(plugin, rec_message);
- //call wlan_process_helper to process the message
- wlan_data_massage_handler(plugin, session_light,
- (struct GNUNET_MessageHeader*) msg);
- //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
-
- GNUNET_free(msg);
- }
- }
-}
-
-static void
-process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
-{
-
- GNUNET_assert(client != NULL);
- GNUNET_assert(cls != NULL);
- struct Session * session = (struct Session *) client;
- struct Plugin * plugin = (struct Plugin *) cls;
-
- struct GNUNET_TRANSPORT_ATS_Information distance[2];
- distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
- distance[0].value = htonl(1);
- distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
- distance[1].value = htonl(0);
-
-#if DEBUG_wlan
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Calling plugin->env->receive for session %p; %s\n", session,
- wlan_plugin_address_to_string(NULL, session->addr, 6));
-#endif
-
- plugin->env->receive(plugin->env->cls, &(session->target), hdr,
- (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
- session->addr, sizeof(session->addr));
-}
-
-/**
- * handels the data after all fragments are put together
- * @param plugin
- * @param session_light
- * @param hdr pointer to the data
- */
-static void
-wlan_data_massage_handler(struct Plugin * plugin,
- struct Session_light * session_light,
- const struct GNUNET_MessageHeader * hdr)
-{
- struct WlanHeader * wlanheader = NULL;
- struct Session * session = NULL;
- const char * tempmsg = NULL;
- const struct GNUNET_MessageHeader * temp_hdr = NULL;
- struct GNUNET_PeerIdentity tmptarget;
-
- if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
- {
-
-#if DEBUG_wlan
- GNUNET_log(
- GNUNET_ERROR_TYPE_DEBUG,
- "Func wlan_data_massage_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
- ntohs(hdr->size));
-#endif
-
- if (ntohs(hdr->size) < sizeof(struct WlanHeader)
- + sizeof(struct GNUNET_MessageHeader))
- {
- //packet not big enought
- return;
- }
-
- GNUNET_assert(session_light != NULL);
- if (session_light->session == NULL)
- {
- session_light->session = search_session(plugin, session_light->addr);
- }
- session = session_light->session;
- wlanheader = (struct WlanHeader *) hdr;
-
- tempmsg = (char*) &wlanheader[1];
- temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
-
- if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
- wlanheader->crc))
- {
- //wrong crc, dispose message
- GNUNET_log(GNUNET_ERROR_TYPE_INFO,
- "Wlan message Header crc was wrong\n");
- return;
- }
-
- //if not in session list
- if (session == NULL)
- {
-#if DEBUG_wlan
- GNUNET_log(
- GNUNET_ERROR_TYPE_DEBUG,
- "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
- ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
- sizeof(struct WlanHeader));
-#endif
- //try if it is a hello message
- if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
- + sizeof(struct WlanHeader))
- {
- if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
- {
- if (GNUNET_HELLO_get_id(
- (const struct GNUNET_HELLO_Message *) temp_hdr,
- &tmptarget) == GNUNET_OK)
- {
- session = create_session(plugin, session_light->addr);
- session_light->session = session;
- memcpy(&session->target, &tmptarget,
- sizeof(struct GNUNET_PeerIdentity));
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
- "WLAN client not in session list and hello message not okay\n");
- return;
- }
-
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
- "WLAN client not in session list and not a hello message\n");
- return;
- }
- }
- else
- {
- GNUNET_log(
- GNUNET_ERROR_TYPE_WARNING,
- "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
- ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
- sizeof(struct WlanHeader));
- return;
- }
- }
-
- //"receive" the message
-
-
- GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
- (const char *) temp_hdr,
- ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
-
- return;
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
- "wlan_data_massage_handler got wrong message type\n");
- return;
- }
-}
-
-/**
- * function to add an ack to send it for a received fragment
- * @param plugin pointer to the global plugin structure
- * @param session pointer to the session this ack belongs to
- * @param bitfield bitfield to send
- * @param fh pointer to the fragmentation header which we would like to acknolage
- */
-
-void
-add_ack_for_send(struct Plugin * plugin, struct Session * session,
- uint64_t bitfield, struct FragmentationHeader * fh)
-{
- struct AckSendQueue * ack;
-
- GNUNET_assert(plugin != NULL);
- GNUNET_assert(session != NULL);
- GNUNET_assert(fh != NULL);
-
- ack = GNUNET_malloc(sizeof(struct AckSendQueue));
- ack->fragments_field = bitfield;
- ack->message_id = ntohl(fh->message_id);
- ack->session = session;
-
- GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
- plugin->ack_send_queue_tail, ack);
-
-}
-
-/**
- * function to get the receive message from the message id and the session
- * @param plugin pointer to the plugin struct
- * @param session session this fragment belongs to
- * @param message_id id of the message
- */
-
-struct Receive_Message_Queue *
-get_receive_message(struct Plugin * plugin, struct Session * session,
- uint32_t message_id)
-{
- struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
- while (rec_message != NULL)
- {
- if ((rec_message->message_id_in == message_id) && (rec_message->session
- == session))
- {
- return rec_message;
- }
- rec_message = rec_message->next;
- }
- return NULL;
-}
-
-/**
- * function to get the receive message of a session
- * @param plugin pointer to the plugin struct
- * @param session session this fragment belongs to
- */
-
-struct Receive_Message_Queue *
-get_receive_message_from_session(struct Plugin * plugin,
- struct Session * session)
-{
- struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
- while (rec_message != NULL)
- {
- if (rec_message->session == session)
- {
- return rec_message;
- }
- rec_message = rec_message->next;
- }
- return NULL;
-}
-
-/**
- * function to insert a received fragment into the right fragment queue of the right message
- * @param plugin pointer to the plugin struct
- * @param session_light pointer to the session_light struct of this message
- * @param session session this fragment belongs to
- * @param fh pointer to the header of the fragment
- * @return new fragment bitfield for the message
- */
-
-uint64_t
-insert_fragment_in_in_message_queue(struct Plugin * plugin,
- struct Session_light * session_light, struct Session * session,
- struct FragmentationHeader * fh)
-{
- struct Receive_Fragment_Queue * rec_queue = NULL;
- struct Receive_Message_Queue * rec_message;
- const char * tempmsg = (char*) &fh[1];
- uint64_t retval = 0;
-
- //TODO fragments do not timeout
- //check if message_id is right or it is a new msg
- GNUNET_assert(fh != NULL);
-
- rec_message = get_receive_message(plugin, session, ntohs(fh->message_id));
-
- if (rec_message == NULL)
- {
- if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
- {
-
- //new message incoming
- rec_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
- rec_message->message_id_in = ntohs(fh->message_id);
- rec_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
- rec_message->session = session;
- rec_message->timeout = GNUNET_TIME_absolute_add(
- GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
- rec_message->received_fragments = 0;
-
- GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rec_message);
-
- session->fragment_messages_in_count++;
- plugin->pending_receive_messages++;
-
-#if DEBUG_wlan
- GNUNET_log(
- GNUNET_ERROR_TYPE_DEBUG,
- "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
- rec_message->message_id_in, session->fragment_messages_in_count,
- plugin->pending_receive_messages);
-#endif
- }
- else
- {
-
- GNUNET_log(
- GNUNET_ERROR_TYPE_INFO,
- "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached\n");
- setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
- return retval;
- }
- }
-
- if (is_double_msg(rec_message, fh) != GNUNET_YES)
- {
-
- //report size
- rec_queue = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
- ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
- rec_queue->size = ntohs(fh->header.size)
- - sizeof(struct FragmentationHeader);
- rec_queue->num = ntohs(fh->fragment_off_or_num);
- rec_queue->msg = (char*) &(rec_queue[1]);
- //copy msg to buffer
- memcpy((char *) rec_queue->msg, tempmsg, rec_queue->size);
- insert_fragment_in_queue(rec_message, rec_queue);
- //save bitfield
- retval = rec_message->received_fragments;
-
-#if DEBUG_wlan
- GNUNET_log(
- GNUNET_ERROR_TYPE_DEBUG,
- "New fragment: size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
- rec_message->rec_size, rec_queue->size,
- rec_message->received_fragments, rec_message->message_id_in, session);
-#endif
-
- check_rec_finished_msg(plugin, session_light, session, rec_message);
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
- retval = rec_message->received_fragments;
-
- }
- return retval;
-
-}
-
-/**
- * Function used for to process the data received from the wlan interface