--- 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];
}