/**
*
*  @File : exo_03s.cxx
*
*  @Authors : D. Mathieu
*             M. Laporte
*
*  @Date : 19/12/2000
*
*  @Version : V1.0
*
*  @Synopsis :
*
**/
#include <iostream>
#include <string>
#include <exception>
#include <cerrno>         // EINTR
#include <cstdlib>        // atoi()
#include <csignal>        // SIGURG, SIGALRM

#include <unistd.h>       // sleep(), alarm(), getpid()
#include <fcntl.h>        // F_SETOWN
#include <sys/socket.h>   // MSG_OOB
#include <netinet/in.h>   // ntohs()

#include "CExc.h"
#include "CExcFctSyst.h"
#include "nsSysteme.h"
#include "nsNet.h"

using namespace nsSysteme;
using namespace nsNet;

namespace
{
    volatile bool Continuer = true;
    unsigned Periode;
    unsigned MaxEvents;
    int      sdComm;
    unsigned Cpt;

    void DeroutUrg (int)
    {
        ::alarm (0);

        char Msg;

        Recv (sdComm, &Msg, 1, MSG_OOB);
        Send (sdComm, &Msg, 1, MSG_OOB);
        Cpt = 0;

        ::alarm (Periode);

    } // DeroutUrg()

    void DeroutAlrm (int)
    {
        Continuer = MaxEvents > ++Cpt;

        ::alarm (Periode);

    } // DeroutAlrm()

} // namespace anonyme

int std::ppal (int argc, char * argv []) throw (exception)
{
    if (3 != argc)
        throw nsBAO::CExc (string ("Usage : ") + argv [0] +
                           " <Periode> + <Nbre d'essais>");


    unsigned short NumPort = Getportbyname ("mathieu", "tcp");
    cout << "Numero de port = " << ::ntohs (NumPort) << endl;

    const int sd = ServeurSockInStream (NumPort);

    Periode   = ::atoi (argv [1]);
    MaxEvents = ::atoi (argv [2]);

    const char NonUrgent [] = "Non Urgent";

    Signal (SIGALRM, DeroutAlrm);
    Signal (SIGURG,  DeroutUrg);
    Cpt = 0;

    sdComm = ServeurAccept (sd);
    Fcntl (sdComm, F_SETOWN, ::getpid());
    ::alarm (Periode);

    for ( ; Continuer; )
    {
        Send (sdComm, NonUrgent, ::strlen (NonUrgent));

        // Il est nécessaire de réarmer la fonction sleep() avec le reste de
        //   temps non écoulé puisqu'elle est souvent interrompue par le
        //   signal SIGALRM

        for (unsigned Reste = 3; Reste = ::sleep (Reste); );
    }
    Close (sdComm);
    Close (sd);

    cerr << "Connexion perdue" << endl;

    return 0;

} // ppal()