gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r13169 - in gnunet/src: include transport


From: gnunet
Subject: [GNUnet-SVN] r13169 - in gnunet/src: include transport
Date: Tue, 5 Oct 2010 23:46:44 +0200

Author: brodski
Date: 2010-10-05 23:46:44 +0200 (Tue, 05 Oct 2010)
New Revision: 13169

Modified:
   gnunet/src/include/gnunet_protocols.h
   gnunet/src/transport/plugin_transport_wlan.c
Log:
Sending of data over wlan added; fragmentation added


Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h       2010-10-05 18:20:22 UTC (rev 
13168)
+++ gnunet/src/include/gnunet_protocols.h       2010-10-05 21:46:44 UTC (rev 
13169)
@@ -670,12 +670,17 @@
 
 /**
  * Type of messages for data over the wlan
- *
  */
 
 #define GNUNET_MESSAGE_TYPE_WLAN_DATA 198
 
 /**
+ * Fragment of a message
+ */
+
+#define GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT 199
+
+/**
  * Type of messages to query the local service-dns
  */
 #define GNUNET_MESSAGE_TYPE_LOCAL_QUERY_DNS 205

Modified: gnunet/src/transport/plugin_transport_wlan.c
===================================================================
--- gnunet/src/transport/plugin_transport_wlan.c        2010-10-05 18:20:22 UTC 
(rev 13168)
+++ gnunet/src/transport/plugin_transport_wlan.c        2010-10-05 21:46:44 UTC 
(rev 13169)
@@ -25,6 +25,7 @@
  */
 
 #include "platform.h"
+#include "gnunet_hello_lib.h"
 #include "gnunet_protocols.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_statistics_service.h"
@@ -40,6 +41,13 @@
  */
 #define WLAN_MTU 3000
 
+/**
+ * Time until retransmission of a fragment in ms
+ */
+
+#define FRAGMENT_TIMEOUT 1000
+
+
 #define DEBUG_wlan GNUNET_NO
 
 /**
@@ -147,6 +155,7 @@
 
 };
 
+//TODO doxigen
 
 struct Sessionqueue
 {
@@ -155,6 +164,15 @@
        struct Session * content;
 };
 
+//TODO doxigen
+
+struct FragmentQueue
+{
+       struct FragmentQueue * next;
+       struct FragmentQueue * prev;
+       int fragment_num;
+};
+
 /**
  * Session handle for connections.
  */
@@ -212,14 +230,14 @@
   struct GNUNET_TIME_Absolute last_activity;
 
   /**
-   * number of message, to distinguish between the messages
+   * current number for message incoming , to distinguish between the messages
    */
-  uint16_t message_num_in;
+  uint32_t message_id_in;
 
   /**
-   * number of message, to distinguish between the messages
+   * current number for message outgoing, to distinguish between the messages
    */
-  uint16_t message_num_out;
+  uint32_t message_id_out;
 
 
 };
@@ -264,14 +282,33 @@
   struct GNUNET_TIME_Absolute timeout;
 
   /**
+   * Timeout value for the pending fragments.
+   * Stores the time when the last msg fragment ack was received
+   */
+  struct GNUNET_TIME_Absolute last_ack;
+
+  /**
+   * Sorted queue with the acks received for fragments; head
+   */
+
+  struct FragmentQueue * head;
+
+  /**
+   * Sorted queue with the acks received for fragments; tail
+   */
+
+  struct FragmentQueue * tail;
+
+  /**
    * Size of the message
    */
   size_t message_size;
 
   /**
-   * pos in the message, for fragmentation/segmentation
+   * pos / next fragment number in the message, for fragmentation/segmentation,
+   * some acks can be missing but there is still time
    */
-  size_t message_pos;
+  uint32_t message_pos;
 };
 
 
@@ -345,18 +382,48 @@
 
 };
 
-enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 
};
+//enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 
8 };
 
 int getRadiotapHeader (struct RadiotapHeader * Header);
 int getWlanHeader (struct IeeeHeader * Header);
 static int wlan_plugin_address_suggested (void *cls,
                                   const void *addr,
                                   size_t addrlen);
+uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size);
+
 /**
+ * get the next message number, at the moment just a random one
+ *
+ */
+
+uint32_t
+get_next_message_id()
+{
+       // FIXME find good random generator
+       if (RAND_MAX < UINT32_MAX){
+               return (random() * random()) % UINT32_MAX;
+       } else {
+               return random() % UINT32_MAX;
+       }
+}
+
+/**
+ * start next message number generator
+ */
+
+void
+start_next_message_id()
+{
+       //FIXME not good
+       srand(GNUNET_TIME_absolute_get().value);
+}
+
+
+/**
  * get Session from address
  *
  */
-
+//TODO doxigen
 //TODO add other possibilities to find the right session (are there other?)
 static struct Session *
 get_Session (struct Plugin *plugin,
@@ -365,6 +432,8 @@
        struct Sessionqueue * queue = plugin->all_Sessions;
        struct Sessionqueue * lastitem = NULL;
 
+
+       //just look at all the session for the needed one
        while (queue != NULL){
                // content is never NULL
                GNUNET_assert (queue->content == NULL);
@@ -392,17 +461,18 @@
        queue->content = GNUNET_malloc (sizeof (struct Session));
        queue->content->plugin = plugin;
        memcpy(queue->content->addr, addr, 6);
+       queue->content->message_id_out = get_next_message_id();
 
-       //queue welcome
-       struct WelcomeMessage welcome;
+       //queue welcome message for new sessions, not realy needed
+       //struct WelcomeMessage welcome;
        struct PendingMessage *pm;
-       pm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct 
WelcomeMessage));
+       pm = GNUNET_malloc (sizeof (struct PendingMessage) + 
GNUNET_HELLO_size(* (plugin->env->our_hello)));
        pm->msg = (const char*) &pm[1];
-       pm->message_size = sizeof (struct WelcomeMessage);
-       welcome.header.size = htons (sizeof (struct WelcomeMessage));
-       welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
-       welcome.clientIdentity = *plugin->env->my_identity;
-       memcpy (&pm[1], &welcome, sizeof (welcome));
+       pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
+       //welcome.header.size = htons (GNUNET_HELLO_size(* 
(plugin->env->our_hello)));
+       //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
+       //welcome.clientIdentity = *plugin->env->my_identity;
+       memcpy (&pm[1], * plugin->env->our_hello, GNUNET_HELLO_size(* 
(plugin->env->our_hello)));
        pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
        GNUNET_CONTAINER_DLL_insert ((queue->content)->pending_messages_head,
                                           
(queue->content)->pending_messages_tail,
@@ -415,7 +485,7 @@
 /**
  * Queue the session to send data
  */
-
+//TODO doxigen
 static void
 queue_Session (struct Plugin *plugin,
                struct Session * session)
@@ -472,7 +542,13 @@
   struct IeeeHeader * wlanheader;
   struct RadiotapHeader * radioHeader;
   struct GNUNET_MessageHeader * msgheader;
+  struct FragmentationHeader fragheader;
   uint16_t size = 0;
+  const char * copystart = NULL;
+  uint16_t copysize = 0;
+  uint copyoffset = 0;
+  struct FragmentQueue * akt = NULL;
+  int exit = 0;
 
   queue = plugin->pending_Sessions;
 
@@ -487,16 +563,99 @@
 
   //check if msg is valid to send
   if (GNUNET_TIME_absolute_get_remaining(pm->timeout).value > 0){
-       // fixme split msg if to large
+       // split msg if to large
 
-       //increment one, this is a new message
-       session->message_num_out ++;
-       // fixme peer id is needed in each packet
-       size = pm->message_size + sizeof(struct RadiotapHeader)
-                                       + sizeof(struct IeeeHeader) + 
sizeof(struct GNUNET_MessageHeader)
-                                       + sizeof(struct FragmentationHeader);
+       if (pm->message_size > WLAN_MTU) {
+               size += sizeof(struct FragmentationHeader);
+               // check for retransmission
+               if (GNUNET_TIME_absolute_get_duration(pm->last_ack).value > 
FRAGMENT_TIMEOUT) {
+                       // TODO retransmit
+                       // be positive and try again later :-D
+                       pm->last_ack = GNUNET_TIME_absolute_get();
+                       // find first missing fragment
+                       exit = 0;
+                       akt = pm->head;
+                       pm->message_pos = 0;
+
+                       //test if ack was already received
+                       if (akt != NULL) {
+                               while (exit == 0){
+                                       //if fragment is present, take next
+                                       if (akt->fragment_num == 
pm->message_pos) {
+                                               pm->message_pos ++;
+                                       }
+                                       //next ack is bigger then the fragment 
number
+                                       //in case there is something like this: 
(acks) 1, 2, 5, 6, ...
+                                       //and we send 3 again, the next number 
should be 4
+                                       if (akt->fragment_num > 
pm->message_pos) {
+                                                                               
exit = 1;
+                                                                       }
+
+                                       akt = akt->next;
+                                       //test if this was the last ack
+                                       if (akt == NULL){
+                                               exit = 1;
+                                       }
+
+                               }
+                       }
+
+               }
+
+               copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * 
pm->message_pos;
+               fragheader.fragment_off_or_num = pm->message_pos;
+               fragheader.message_id = session->message_id_out;
+
+               // start should be smaller then the packet size
+               //TODO send some other data if everything was send but not all 
acks are present
+               GNUNET_assert(copyoffset < pm->message_size);
+               copystart = pm->msg + copyoffset;
+
+               //size of the fragment is either the MTU - overhead
+               //or the missing part of the message in case this is the last 
fragment
+               copysize = GNUNET_MIN(pm->message_size - copyoffset,
+                               WLAN_MTU - sizeof(struct FragmentationHeader));
+               fragheader.header.size = copysize;
+               fragheader.header.type = GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT;
+
+               //get the next missing fragment
+               exit = 0;
+               akt = pm->head;
+               pm->message_pos ++;
+
+               //test if ack was already received
+               if (akt != NULL) {
+                       while (exit == 0){
+                               //if fragment is present, take next
+                               if (akt->fragment_num == pm->message_pos) {
+                                       pm->message_pos ++;
+                               }
+                               //next ack is bigger then the fragment number
+                               //in case there is something like this: (acks) 
1, 2, 5, 6, ...
+                               //and we send 3 again, the next number should 
be 4
+                               if (akt->fragment_num > pm->message_pos) {
+                                                                       exit = 
1;
+                                                               }
+
+                               akt = akt->next;
+                               //test if this was the last ack
+                               if (akt == NULL){
+                                       exit = 1;
+                               }
+
+                       }
+               }
+
+       } else {
+               // there is no need to split
+               copystart = pm->msg;
+               copysize = pm->message_size;
+       }
+       size += copysize;
+       size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
+                       + sizeof(struct GNUNET_MessageHeader);
        msgheader = GNUNET_malloc(size);
-       msgheader->size = pm->message_size + sizeof(struct RadiotapHeader) + 
sizeof(struct IeeeHeader);
+       msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader));
        msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA;
 
        radioHeader = (struct RadiotapHeader*) &msgheader[1];
@@ -505,9 +664,23 @@
        wlanheader = (struct IeeeHeader *) &radioHeader[1];
        getWlanHeader(wlanheader);
 
+
+       //could be faster if content is just send and not copyed before
+       //fragmentheader is needed
+       if (pm->message_size > WLAN_MTU){
+               fragheader.message_crc = getcrc16(copystart, copysize);
+               memcpy(&wlanheader[1],&fragheader, sizeof(struct 
FragmentationHeader));
+               memcpy(&wlanheader[1] + sizeof(struct 
FragmentationHeader),copystart,copysize);
+       } else {
+               memcpy(&wlanheader[1],copystart,copysize);
+       }
+
        bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, 
size);
+
+
   } else {
          //remove message
+         //TODO free the queues (acks)
          GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
                                                                  
session->pending_messages_tail,
                                                                  pm);
@@ -531,6 +704,8 @@
 
 }
 
+
+
 /**
  * If we have pending messages, ask the server to
  * transmit them (schedule the respective tasks, etc.)
@@ -564,8 +739,39 @@
 }
 
 
+/**
+ * 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.
  *
@@ -607,7 +813,7 @@
 {
   struct Plugin * plugin = cls;
   struct PendingMessage * newmsg = NULL;
-
+  struct WlanHeader * wlanheader = NULL;
   //check if msglen > 0
   GNUNET_assert(msgbuf_size > 0);
 
@@ -631,15 +837,20 @@
   queue_Session(plugin, session);
 
   //queue message in session
-  newmsg = GNUNET_malloc(sizeof(struct PendingMessage) + msgbuf_size);
+  newmsg = GNUNET_malloc(sizeof(struct PendingMessage) + msgbuf_size + 
sizeof(struct WlanHeader));
   newmsg->msg = (const char*) &newmsg[1];
-  //copy msg to buffer, not fragmented / segmented yet
-  memcpy(&newmsg[1], msgbuf, msgbuf_size);
+  wlanheader = (struct WlanHeader *) &newmsg[1];
+  //copy msg to buffer, not fragmented / segmented yet, but with message header
+  wlanheader->header.size = msgbuf_size;
+  wlanheader->header.type = GNUNET_MESSAGE_TYPE_WLAN_DATA;
+  wlanheader->target = *target;
+  wlanheader->crc = 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->message_pos = 0;
-  newmsg->message_size = msgbuf_size;
+  newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
   newmsg->next = NULL;
 
   //check if queue is empty
@@ -688,7 +899,7 @@
                             const struct GNUNET_PeerIdentity *target)
 {
   // struct Plugin *plugin = cls;
-  // FIXME
+  // FIXME make something usefull :-D
 }
 
 
@@ -812,10 +1023,12 @@
 }
 
 
-#if 1
+
 /**
  * Function used for to process the data from the suid process
  */
+//TODO doxigen
+
 static void
 wlan_process_helper (void *cls,
                       void *client,
@@ -829,6 +1042,8 @@
   } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL){
     //TODO Control
     if (hdr->size == 6){
+      plugin->mac_address = GNUNET_malloc(6);
+      memcpy(plugin->mac_address, &hdr[1],6);
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying transport of address 
%s\n", wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
       plugin->env->notify_address (plugin->env->cls,
                                       "wlan",
@@ -922,9 +1137,6 @@
 
 
 
-#endif
-
-
 /**
  * Entry point for the plugin.
  *
@@ -966,6 +1178,8 @@
   api->check_address = &wlan_plugin_address_suggested;
   api->address_to_string = &wlan_plugin_address_to_string;
 
+  start_next_message_id();
+
   return api;
 }
 
@@ -973,6 +1187,7 @@
 /**
  * Exit point from the plugin.
  */
+//TODO doxigen
 void *
 gnunet_plugin_transport_wlan_done (void *cls)
 {
@@ -981,6 +1196,7 @@
 
   GNUNET_assert(cls !=NULL);
 
+  GNUNET_free_non_null(plugin->mac_address);
   GNUNET_free (plugin);
   GNUNET_free (api);
   return NULL;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]