eth_proto.c
author viric@llimona
Thu, 27 Sep 2007 00:25:54 +0200
changeset 58 2cf8c513d18f
parent 53 07500c5c53cb
child 60 18c24be2b1a6
permissions -rw-r--r--
added authors.

/*
    Terminal Mixer - multi-point multi-user access to terminal applications
    Copyright (C) 2007  LluĂ­s Batlle i Rossell

    Please find the license in the provided COPYING file.
*/
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>

#include "eth_linux.h"
#include "main.h"

static struct
{
    int socket;
    char partner[6];
    int partner_set;
    unsigned int seq_send;
    unsigned int seq_wait;
    unsigned int wrong_recv;
} edata;

enum Control{
    SEND,
    ACK,
    NAK
};

enum {
    MAXPACKET = 1000,
    HEAD = 9
};

static char eth_buffer[1000];

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)
{
    *((unsigned int *) data) = htonl(seq);
    data[4] = (unsigned char) c;
    *((unsigned int *)(data+5)) = htonl(size);
    return HEAD;
}

static int parse_head(unsigned char *data, unsigned int *seq, enum Control *c,
        int *size)
{
    *seq = ntohl( *((unsigned int*) data) );
    *c = data[4];
    if (size)
        *size = ntohl(*((unsigned int *)(data+5)));
    return HEAD;
}

void eth_proto_init()
{
    edata.socket = -1;
    edata.seq_send = 0;
    edata.seq_wait = 0;
    edata.partner_set = 0;
    if (command_line.c_param.server_address);
}

int eth_proto_open()
{
    edata.socket = eth_open(command_line.eth_device);
    if (edata.socket == -1)
        error("Cannot open device %s", command_line.eth_device);
    return edata.socket;
}

int eth_proto_recv(char *data, int size)
{
    int res;
    int seq;
    enum Control c;
    char partner[6];

    do {
            res = eth_recv(eth_buffer, sizeof(eth_buffer), partner);
            edata.partner_set = 1;
    } while(res < HEAD);
    parse_head(eth_buffer, &seq, &c, &res);
    /* We admit any first connection */
    if (seq == 0)
    {
      edata.seq_wait = 0;
      memcpy(edata.partner, partner, sizeof(edata.partner));
    }
    /*
    if (seq != edata.seq_wait)
    {
        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);
    eth_send(command_line.eth_device, edata.partner, eth_buffer, HEAD);
    */
    edata.seq_wait++;

    return res;
}

int eth_proto_send(const char *data, int size)
{
    int total = size;

    if (!edata.partner_set)
    {
        if (edata.seq_send == 0 && !command_line.is_server
                && command_line.c_param.server_address != 0)
        {
            eth_fill_mac(edata.partner, command_line.c_param.server_address);
            edata.partner_set = 1;
        }
        else
            return 0;
    }

    do {
        int once;
        int sent;
        int rseq;
        enum Control rc;

        once = min(sizeof(eth_buffer)-HEAD, size);

        make_head(eth_buffer, edata.seq_send, SEND, once);
        memcpy(eth_buffer+HEAD, data, once);
        sent = eth_send(command_line.eth_device, edata.partner,
                eth_buffer, once+HEAD);

        /*
        eth_recv(eth_buffer, HEAD, 0);
        parse_head(eth_buffer, &rseq, &rc, 0);
        if (rc != ACK || rseq != edata.seq_send)
            continue;
        */

        edata.seq_send++;
        size -= sent;
        data += sent;
    } while(size > 0);
    return total;
}

static void eth_fill_mac(unsigned char *mac, const char *str)
{
  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]);
  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]);
  }
  mac[0] = imac[0];
  mac[1] = imac[1];
  mac[2] = imac[2];
  mac[3] = imac[3];
  mac[4] = imac[4];
  mac[5] = imac[5];
}