Better ethernet protocol.
authorviric@llimona
Sun, 30 Sep 2007 18:34:48 +0200
changeset 60 18c24be2b1a6
parent 59 eac1d6b25a40
child 61 0b9daeb1cb1c
Better ethernet protocol.
client.c
eth_client.c
eth_proto.c
eth_server.c
main.h
signals.c
--- a/client.c	Thu Sep 27 00:26:46 2007 +0200
+++ b/client.c	Sun Sep 30 18:34:48 2007 +0200
@@ -51,9 +51,9 @@
         if (FD_ISSET(0, &read_set))
         {
             res = read(0, stream_buffer, stream_buffer_size);
+            net_send(stream_buffer, res);
             if (res == 0) /* EOF */
                 break;
-            net_send(stream_buffer, res);
         }
     } while (1);
 }
--- a/eth_client.c	Thu Sep 27 00:26:46 2007 +0200
+++ b/eth_client.c	Sun Sep 30 18:34:48 2007 +0200
@@ -43,6 +43,8 @@
         int res;
         int olen;
         res = eth_proto_recv(stream_buffer, stream_buffer_size);
+        if (res == -1)
+            return 0;
         if (res == 0) /* EOF */
         {
             filter_flush(client_fr, ostream_buffer, &olen);
--- a/eth_proto.c	Thu Sep 27 00:26:46 2007 +0200
+++ b/eth_proto.c	Sun Sep 30 18:34:48 2007 +0200
@@ -7,6 +7,7 @@
 #include <netinet/in.h>
 #include <string.h>
 #include <stdio.h>
+#include <errno.h>
 
 #include "eth_linux.h"
 #include "main.h"
@@ -19,17 +20,20 @@
     unsigned int seq_send;
     unsigned int seq_wait;
     unsigned int wrong_recv;
+    char tmp_eth_buffer[1000];
+    char tmp_eth_buffer_size;
+    char tmp_buffer_filled;
 } edata;
 
-enum Control{
+enum Control {
     SEND,
     ACK,
-    NAK
+    INIT
 };
 
 enum {
     MAXPACKET = 1000,
-    HEAD = 9
+    HEAD = 10
 };
 
 static char eth_buffer[1000];
@@ -37,21 +41,24 @@
 static void eth_fill_mac(unsigned char *mac, const char *str);
 
 static int make_head(unsigned char *data, unsigned int seq, enum Control c,
-        int size)
+        int size, unsigned char crc)
 {
     *((unsigned int *) data) = htonl(seq);
     data[4] = (unsigned char) c;
     *((unsigned int *)(data+5)) = htonl(size);
+    data[9] = crc;
     return HEAD;
 }
 
 static int parse_head(unsigned char *data, unsigned int *seq, enum Control *c,
-        int *size)
+        int *size, unsigned char *crc)
 {
     *seq = ntohl( *((unsigned int*) data) );
     *c = data[4];
     if (size)
         *size = ntohl(*((unsigned int *)(data+5)));
+    if (crc)
+        *crc = data[9];
     return HEAD;
 }
 
@@ -61,7 +68,7 @@
     edata.seq_send = 0;
     edata.seq_wait = 0;
     edata.partner_set = 0;
-    if (command_line.c_param.server_address);
+    edata.tmp_buffer_filled = 0;
 }
 
 int eth_proto_open()
@@ -69,49 +76,84 @@
     edata.socket = eth_open(command_line.eth_device);
     if (edata.socket == -1)
         error("Cannot open device %s", command_line.eth_device);
+
+    if ( !command_line.is_server)
+    {
+        eth_fill_mac(edata.partner, command_line.c_param.server_address);
+        edata.partner_set = 1;
+
+        make_head(eth_buffer, edata.seq_send, INIT, 0, 0);
+        eth_send(command_line.eth_device, edata.partner, eth_buffer, HEAD);
+        edata.seq_send++;
+    }
+
     return edata.socket;
 }
 
+static unsigned char get_crc(const char *data, int size)
+{
+    int i;
+    unsigned char crc = 0;
+    for (i=0; i < size; ++i, ++data)
+    {
+        crc ^= *data;
+    }
+    return crc;
+}
+
 int eth_proto_recv(char *data, int size)
 {
     int res;
     int seq;
     enum Control c;
     char partner[6];
+    unsigned char crc;
 
+    if (edata.tmp_buffer_filled)
+    {
+        int nbytes;
+        nbytes = min(size, edata.tmp_eth_buffer_size);
+        memcpy(data, edata.tmp_eth_buffer, nbytes);
+        return nbytes;
+    }
     do {
             res = eth_recv(eth_buffer, sizeof(eth_buffer), partner);
             edata.partner_set = 1;
     } while(res < HEAD);
-    parse_head(eth_buffer, &seq, &c, &res);
+    parse_head(eth_buffer, &seq, &c, &res, &crc);
     /* We admit any first connection */
-    if (seq == 0)
+    if (seq == 0 && c == INIT)
     {
-      edata.seq_wait = 0;
+      edata.seq_wait = 1; /* next of the just receive 0 */
       memcpy(edata.partner, partner, sizeof(edata.partner));
+      return -1; /* Nothing the parent should care about */
     }
-    /*
-    if (seq != edata.seq_wait)
+    if (seq != edata.seq_wait || c != SEND ||
+            crc != get_crc(eth_buffer + HEAD, res) )
     {
         edata.wrong_recv++;
         return -1;
     }
-    */
     /* res comes from parse_head. */
     memcpy(data, eth_buffer + HEAD, min(size, res));
 
-    /*
-    make_head(eth_buffer, seq, ACK, 0);
+    make_head(eth_buffer, seq, ACK, 0, 0);
     eth_send(command_line.eth_device, edata.partner, eth_buffer, HEAD);
-    */
     edata.seq_wait++;
 
-    return res;
+    if (res == 0 && c == SEND)
+    {
+        edata.partner_set = 0;
+        edata.seq_wait = 0;
+    }
+
+    return min(size, res);
 }
 
 int eth_proto_send(const char *data, int size)
 {
     int total = size;
+    int retries;
 
     if (!edata.partner_set)
     {
@@ -125,25 +167,57 @@
             return 0;
     }
 
+    retries = 3;
     do {
         int once;
         int sent;
         int rseq;
+        int res;
+        unsigned char crc;
         enum Control rc;
 
+        if (retries == 0)
+        {
+            edata.partner_set = 0;
+            return -1;
+        }
+
         once = min(sizeof(eth_buffer)-HEAD, size);
 
-        make_head(eth_buffer, edata.seq_send, SEND, once);
+        crc = get_crc(data, once);
+        make_head(eth_buffer, edata.seq_send, SEND, once, crc);
         memcpy(eth_buffer+HEAD, data, once);
         sent = eth_send(command_line.eth_device, edata.partner,
                 eth_buffer, once+HEAD);
+        sent -= HEAD;
+        if (sent < 0)
+            sent = 0;
 
-        /*
-        eth_recv(eth_buffer, HEAD, 0);
-        parse_head(eth_buffer, &rseq, &rc, 0);
-        if (rc != ACK || rseq != edata.seq_send)
+        program_timeout(2);
+        res = eth_recv(eth_buffer, HEAD, 0);
+        if (res == -1 && errno == EINTR)
+        {
+            unprogram_timeout();
+            retries--;
             continue;
-        */
+        }
+        unprogram_timeout();
+        retries = 3;
+
+        parse_head(eth_buffer, &rseq, &rc, 0, 0);
+        if (rc == SEND)
+        {
+            if (rseq != edata.seq_wait)
+                edata.wrong_recv++;
+            else if (edata.tmp_buffer_filled)
+            {
+                edata.seq_wait++;
+                memcpy(edata.tmp_eth_buffer, eth_buffer, res);
+                edata.tmp_buffer_filled = 1;
+            }
+        }
+        else if (rc != ACK || rseq != edata.seq_send)
+            continue;
 
         edata.seq_send++;
         size -= sent;
@@ -157,26 +231,12 @@
   int res;
   int imac[6];
   res = sscanf(str, "%x:%x:%x:%x:%x:%x",
-      &imac[0],
-      &imac[1],
-      &imac[2],
-      &imac[3],
-      &imac[4],
-      &imac[5]);
+      &imac[0], &imac[1], &imac[2], &imac[3], &imac[4], &imac[5]);
   if (res != 6)
   {
     error("Error parsing mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
-      imac[0],
-      imac[1],
-      imac[2],
-      imac[3],
-      imac[4],
-      imac[5]);
+      imac[0], imac[1], imac[2], imac[3], imac[4], imac[5]);
   }
-  mac[0] = imac[0];
-  mac[1] = imac[1];
-  mac[2] = imac[2];
-  mac[3] = imac[3];
-  mac[4] = imac[4];
-  mac[5] = imac[5];
+  mac[0] = imac[0];  mac[1] = imac[1];  mac[2] = imac[2];
+  mac[3] = imac[3];  mac[4] = imac[4];  mac[5] = imac[5];
 }
--- a/eth_server.c	Thu Sep 27 00:26:46 2007 +0200
+++ b/eth_server.c	Sun Sep 30 18:34:48 2007 +0200
@@ -41,7 +41,8 @@
 
         res = eth_proto_recv(stream_buffer, stream_buffer_size);
 
-        app_control_remote_send_to_stdin(stream_buffer, res);
+        if (res >= 0)
+            app_control_remote_send_to_stdin(stream_buffer, res);
     }
 }
 
--- a/main.h	Thu Sep 27 00:26:46 2007 +0200
+++ b/main.h	Sun Sep 30 18:34:48 2007 +0200
@@ -41,6 +41,8 @@
 
 /* signals.c */
 void install_signal_forwarders();
+void program_timeout(int secs);
+void unprogram_timeout();
 
 /* main.c */
 extern int app_stdin;
--- a/signals.c	Thu Sep 27 00:26:46 2007 +0200
+++ b/signals.c	Sun Sep 30 18:34:48 2007 +0200
@@ -6,12 +6,15 @@
 */
 #include <signal.h>
 #include <string.h>
+#include <unistd.h>
 #include <sys/types.h>
 
 #include "main.h"
 #include "handlers.h"
 
 static int child;
+static char old_alarm_handler_set;
+static struct sigaction old_alarm_handler;
 
 static void forward_signals_to_child_handler(int val)
 {
@@ -55,3 +58,40 @@
   act.sa_handler = update_window_size;
   sigaction(SIGWINCH, &act, 0);
 }
+
+static void alarm_handler(int x)
+{
+}
+
+void program_timeout(int secs)
+{
+  struct sigaction act;
+  struct sigaction *old;
+
+  /* Reset the mask */
+  memset(&act.sa_mask,0,sizeof(act.sa_mask));
+  act.sa_flags = 0;
+  act.sa_handler = alarm_handler;
+
+  if (old_alarm_handler_set)
+      old = 0;
+  else
+      old = &old_alarm_handler;
+
+  sigaction(SIGALRM, &act, old);
+
+  old_alarm_handler_set = 1;
+
+  alarm(secs);
+}
+
+void unprogram_timeout()
+{
+    alarm(0);
+
+    if (old_alarm_handler_set)
+    {
+        sigaction(SIGALRM, &old_alarm_handler, 0);
+        old_alarm_handler_set = 0;
+    }
+}