------------------------------------------------------------------------------
                      Documentation sur les programmes pppoa
------------------------------------------------------------------------------

SOMMAIRE

* DESCRIPTION GENERALE DE LA FAMMILE PPPOA2/2M/3

* DESCRIPTION DE LA SERIE PPPOA2
  ** Deroulement d'une execution normale de pppoa2
  ** Gestion des erreurs de lecture/ecriture fatales
  ** Gestion des signaux
  ** Differences entre pppoa2 et pppoa2m (et genese de pppoa3)

*DESCRIPTION DE PPPOA3
  ** Changements entre pppoa3 et pppoa2
  ** Deroulement d'une execution normale
  ** Gestion des signaux
  

------------------------------------------------------------------------------

*DESCRIPTION GENERALE DE LA FAMILLE PPPOA2/2M/3

  Les FAI offrant un acces ADSL a sa clientele utilisent bien souvent le
protocole PPP over ATM. Sur Linux et BSD la couche PPP est directement
gérée par le noyau avec l'aide du programme ppp(d). Malheurresment ppp(d)
ne connait strictement rien a l'ATM et a l'USB. Il est donc impossible d'
utiliser directement ppp(d) pour communiquer avec votre modem (et donc votre
FAI).

  La famille de programme pppoa2/2m/3 resoud ce probleme en se placant entre
ppp(d) et le modem grace a l'utilisation de l'option pty des demons ppp(d).

Voici un schema resumant de facon simple le role de pppoax:


__________          __________                   _______
|        |--------->|        |----------------> /  ° °  \ 
| ppp(d) |   pty    | pppoax |   USB bus       |  Modem  |  ADSL line<----> FAI
|________|<---------|________|<---------------- \\     //   //
          ppp packets    ^       atm cells        \   /____//
                         |                         \_______/
                         |
               Gere l'en/decapsulation
               des données en frame aal5
               puis se charge de les envoyer
               /recevoir via le bus USB
               sous forme de cellules ATM


------------------------------------------------------------------------------

*DESCRIPTION DE LA SERIE DES PPPOA2

  La premiere solution que nous avons trouve pour gerer les flux d'entee/sortie
a été de creer un programme qui se fork en cours d'execution pour qu'une des
copies du programme s'occupe de la lecture et l'autre de l'ecriture sur le bus
USB.

  ** Deroulement d'une execution (normale) de pppoa2:

  1 - Le programme demarre et duplique ses descripteurs 0 (stdin) et 1 (stdout)
  2 - Ouverture du log
  3 - Duplication du descripteur du log en 0, 1, 2
      A partir de ce point plus rien n'apparait sur les consoles, tout printf
      se retouve loggué (car printf utilise stdout)
  4 - Mise en place de la discipline de ligne N_HDLC sur les descripteurs
      utilisés pour communiquer avec ppp(d)
  5 - Recherche du modem USB
  6 - Demande d'acces aux endpoints 0x07(lecture) et 0x87(ecriture)
  7 - Mise en place du signal handler pour gerer les divers signaux
      pouvant etre envoyés par ppp(d) (ou l'utilisateur)
  8 - Le programme se fork
      +Le fils rentre dans une boucle infinie ou il effectue toujours les memes
       taches : lecture des données envoyées par ppp(d), encapsulation aal5,
       hachage en cellules atm, envoi des cellules obtenues au modem
      +Le pere continue son execution
  9 - Maintenant le pere rentre lui aussi dans une boucle infinie ou il
      se charge de :
      recevoir les paquets atm du modem, reassembler les frames aal5, et
      envoyer les paquets ppp ainsi obtenus vers ppp(d)

  ** Gestion d'une erreur fatale de lecture/ecriture
  
    Voila, le programme est lancé et est censé communiquer "ad vidam eternam"
  Mais la vie n'est pas si parfaite et des erreurs peuvent avoir lieux. Voici
  ce qui se passe lorsqu'une telle injustice se produit :-)

    Le fils ou le pere sort de sa boucle infinie et lance le signal TERM sur
  l'autre. Et en s'assurant que les choses ne soient faites qu'une fois on
  relache les devices usb etc etc etc et on sort aussi proprement qu'on peut
  des programmes.
  Les 2 process sont theoriquement tués.

  ** Gestion des signaux
  
    pppoa2 n'est sensible qu'a SIGHUP sur les BSD, et SIGTERM sur Linux. Ceci
  est du au fait que ppp(d) utilise ces signaux pour signaler la fermeture du
  pty de communictaion a son esclave. Si un de ses signaux est recu par l'un
  des process pppoa2, il se charge de l'envoyer a l'autre.

  ** Qu'est ce qui change entre pppoa2 et pppoa2m

    pppoa2 est fonctionnel mais son design limité ne permettait aucune
  evolution de facon aisée. Le code n'était tout simplement pas assez modulaire
  et toute modification mineure a un endroit, entrainait des modifications tres
  importantes sur le reste. Le besoin s'est fait sentir de modulariser le code
  de facon a avoir d'un coté des sortes de libraries crc, atm, aal5 et de
  l'autre pppoa2 qui se servirait de ces librairies. Mais il n'a pas été
  possible de separer de pppoa2 la moindre parcelle de code pour parvenir a
  coder facilement ces librairies crc, atm, aal5.
    Le besoin d'un nouveau design s'est fait ressentir. On est donc reparti de
  zero pour recoder plus intelligemment pppoa2. Pour des raisons que
  j'evoquerai plus tard, ce pppoa2 réecrit s'est vu attribué le nom de pppoa3.
  Les librairies etaient pretes mais pppoa3 etait buggué. On a donc pensé qu'il
  serait bon de back porter les nouveautés apportées par les librairies dans
  le bon vieux pppoa2, qui lui etait epprouvé et fonctionnel. Pour ne pas
  rompre totalement avec pppoa2 on a decidé de faire cohabiter les 2 versions.
  C'est ainsi qu'on a donné a la version merged de pppoa2/3le nom  pppoa2m

  En resumant:
  pppoa2m = (pppoa2) - (le code deguelasse) + (nouvelles libs aal5/atm/crc)

    pppoa2m a l'avantage de voir integrer les dernieres modifications faites
  aux librairies atm/aal5 automatiquement et quelques nouveautés de pppoa3
  lorsque cela est possible (syteme de log par exemple)

NB:  Il est donc preferable d'utiliser pppoa2m a pppoa2

------------------------------------------------------------------------------

*DESCRIPTION DE PPPOA3

  Si vous avez tout lu jusqu'ici vous aurez donc compris que pppoa3 est le
successeur de pppoa2 dans la mesure ou il est le fruit d'un "redesign" de
pppoa2. Mais pour des raisons de compatibilités avec certains BSD qui ne
supportent pas les threads directement, on continue a faire cohabiter la
serie pppoa2 et le nouveau pppoa3 (sous Linux toutes les versions fonctionnent)
Bien entendu il est preferable d'utiliser pppoa2m a pppoa2)

  ** Changements par rapport a pppoa2 (pppoa2m reprenant pas mal de choses)

    1 - pppoa3 utilise des threads a la place de fork pour permettre
        la gestion de la lecture/ecriture de facon parallele
	Cela permet :
         - Temps de switch inférieur entre la lecture/ecriture
         - Utilisation de moins de memoire
         - Controle plus fin du scheduling des lectures/ecritures
	 - Meilleure gestion des signaux (car il'y a qu'un seul process)
    2 - Tout le code a été modularisé
    3 - Meilleure gestion ATM et AAL5 (ajout de certains CRC, verifications...)
    4 - Nouveau systeme de log (utilisation de syslog possible)

  ** Deroulement d'une execution normale

   Main thread 
   
   1 - Demarrage du programme
   2 - Mise en place de la discipline N_HDLC
   3 - Initialisation des attributs des threads
   4 - Initialisation de l'usb (detection et demande des endpoints 0x07, 0x87)
   5 - Mise en place d'un signal handler
   5 - Creation des E/S threads
   6 - arret en attendant qu'un semaphore soit posté
   7 - Le semaphore a été posté cela peut signifier 3 choses
         + Erreur de lecture fatale
         + Erreur d'ecriture fatale
         + Un signal a été saisi par le signal handler
   8 - Cleanup des ressources, abort des threads -> sortie

   E/S thread (cree a l'etape 5 du main thread)

   1 - Validation des abort
   2 - Blocage des signaux (ainsi seul le main thread s'en occupe)
   3 - Entree dans une boucle infinie de lecture/ecriture :
       encapsulation/decapsulation aal5, creation/recuperation des
       cellules atm
   4 - Si une erreur a eu lieu, postage du semaphore pour le signifier au
       main thread qui s'occupera de tout fermer correctement
   5 - quitter le thread

PS : le systeme de log n'est demarré qu'au premier mesage envoyé via la
     fonction report. C'est pour cela que la creation d'un log n'apparait
     pas dans ce résumé

  ** Gestion des signaux

    On l'aura compris, seul le main thread s'occupe des signaux. Lorsqu'un
  signal est traité, il l'est par le main thread. Dans le signal handler on
  poste le semaphore d'erreur de facon a reveiller le main thread qui se charge
  de quitter l'application proprement. L'atomicité de sem_post garantit le fait
  que le programme se termine bien au niveau du main thread.
