#include <stdio.h>
#include <string.h>
#include "reseau.h"

time_t dt[MAXTAILLEFENETRE];
static int asource,adest;
static char *femission, *freception;

void prendre_de_la_couche_reseau(int *AS, int *AD, ttampon *T)
/* Lecture des données sur stdin, on quitte s'il n'y a plus rien à lire */
{
  if (fgets(T->info,MAXTAILLETAMPON,stdin)==NULL)
  {
    printf("Plus de donnees a envoyer\n");
    exit(0);
  }
  T->taille=strlen(T->info);
  *AS=asource;
  *AD=adest;
  return;
}

void construire_trame(int num, int AS, int AD, ttampon T, ttrame *Trame)
/* Construit la trame à partir du tampon, du numéro de séquence et des adresses,
   et insère le CRC */
{
  Trame->num=num;
  Trame->AS=AS;
  Trame->AD=AD;
  Trame->tampon=T;
  Trame->CRC=calcule_CRC(*Trame);
  return;
}

void envoyer_vers_couche_physique(ttrame Trame)
/* Envoie la trame sur le support physique */
{
  FILE *f;
  while ((f=fopen(femission,"ab"))==NULL);
  fwrite(&Trame,sizeof(ttrame),1,f);
  fclose(f);
  return;
}

void prendre_de_la_couche_physique(ttrame *Trame)
/* Récupère la trame sur le support physique */
{
  FILE *f, *temp;
  char auxnom[15]="tmp";
  ttrame aux;
  while ((f=fopen(freception,"rb"))==NULL);
  fread(Trame,sizeof(ttrame),1,f);
  strcat(auxnom,freception);
  temp=fopen(auxnom,"wb");
  while (fread(&aux,sizeof(ttrame),1,f)>0)
    fwrite(&aux,sizeof(ttrame),1,temp);
  fclose(f);
  fclose(temp);
  remove(freception);
  rename(auxnom,freception);
  return;
}

void recuperer_donnees(ttrame Trame, ttampon *T, int *num, int *AS, int *AD)
/* Extraire le tampon, le numéro de séquence et les adresses de la trame */
{
  *T=Trame.tampon;
  *num=Trame.num;
  *AS=Trame.AS;
  *AD=Trame.AD;
  return;
}

void envoyer_vers_couche_reseau(ttampon T, int AS, int AD)
/* Affichage des données sur stdout */
{
  int i;
  for (i=0; i<T.taille; i++)  printf("%c", T.info[i]);
  fflush(stdout);
  return;
}

void attendre(int signal)
/* Attend un ou des signaux */
{
  while (!signale(signal));
  return;
}

char signale(int signal)
/* Renvoie 1 si un des signaux passés en paramètre est émis
   SIGRECU  : une trame sans erreurs qui nous est destinée est arrivée
   SIGTEMPO : timeout
   SIGEMIS  : il reste des données à envoyer */
{
  int i;
  time_t aux;
  FILE *fic, *temp;
  ttrame Trame;
  char auxnom[15]="tmp";
  ttrame aux2;
  if (signal & SIGRECU)
    if ((fic=fopen(freception,"rb"))!=NULL)
    {
      if (fread(&Trame,sizeof(ttrame),1,fic)==1)
      {
        if ((Trame.AD==asource) && (calcule_CRC(Trame)==Trame.CRC)) return(1);
        else
        {
	  strcat(auxnom,freception);
	  temp=fopen(auxnom,"wb");
	  while (fread(&aux2,sizeof(ttrame),1,fic)>0)
	  fwrite(&aux2,sizeof(ttrame),1,temp);
	  fclose(fic);
	  fclose(temp);
	  remove(freception);
	  rename(auxnom,freception);
        }
      }
      fclose(fic);
    }
  if (signal & SIGTEMPO)
  {
    aux=time(NULL);
    for (i=0;i<MAXTAILLEFENETRE;i++)
      if ((dt[i]!=0) && (difftime(aux,dt[i])>=TIMEOUT)) return(1);
  }
  if (signal & SIGEMIS)
    if (!feof(stdin)) return(1);
  return(0);
}

char calcule_CRC(ttrame Trame)
/* Calcul du CRC de la trame, le CRC est ici un caractère de parité */
{
  int i;
  char resultat=0;
  char *p=(char *)&Trame;
  for (i=0; i<sizeof(ttrame)-sizeof(char); i++)
    resultat=(resultat & !*(p+i)) | (!resultat & *(p+i));
  return(resultat);
}

void tempo(int numseq)
/* Déclenche le temporisateur de la trame numseq */
{
  dt[numseq]=time(NULL);
  return;
}

void stoptempo(int numseq)
/* Stoppe le temporisateur de la trame numseq */
{
  dt[numseq]=0;
  return;
}

void initialise_couche_physique(char *emission, char *reception)
/* Initialise la couche physique, les paramètres sont les fichiers d'échange */
{
  femission=emission;
  freception=reception;
  remove(femission);
  remove(freception);
  return;
}

void initialise_couche_reseau(int source, int destination)
/* Initialise la couche réseau, les paramètres sont les adresses de la connection */
{
  asource=source;
  adest=destination;
  return;
}