Code:
/********************************************************************
* SERVER.C
* ----------
*
* Objet :
* Moniteur serveur pour les échanges papiers SUPPORT
* Application client-serveur
* Client : Application sur poste de travail PTMF2 sous NT4
* Serveur: Application sur serveur UNIX NCR ou SUN
* Communication : socket TCP/IP
*
*--------------------------------------------------------------------
* V 1.3 02/07/2001
* Ajout edition des attestations
*
* V 2.1 08/10/2001
* Ajout gestion des variables
*
* V 2.5 02/07/2002
* Modification des lignes cmc7 des vignettes
* Fonctions d'affichage des statistiques
*
* V 2.5 07/11/2002
* Portage sur sun
*
* V 2.9 01/07/2004
* Portage sur sun, compilation laxf01
*
*********************************************************************/
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <netinet/in.h>
#define SUPPORT_SERVER_C
#include "main.h"
#include "server.h"
#include "fonction.h"
#include "transf.h"
static char ident[] = "@(#)"__FILE__","__DATE__","__TIME__"\0";
/*
* Fonction appelee lors de l'initialisation du pocessus
* maitre. Permet d'initialiser les variables dupliquees
* lors de la creation des processus de dialogue.
*/
#define DEBUG
int Processus_initialiser()
{
printf("\n%s\n%s\n%s\n\n",
"----------------------------------------------",
" (c) 2001-2002 DISF La Poste ",
"----------------------------------------------");
printf (" Module traitement serveur : %s %s\n\n", __DATE__, __TIME__);
gs_Pid = 0;
gs_SocketId = 0;
gs_SocketNum = 0;
memset (gs_Utilisateur, 0, SIZE_UTIL);
gs_Accept = FALSE;
return TRUE;
}
#define NETBUFF_TMP 1024
#define NETBUFF_MAX 65536
static char * _netbuff;
static char * _databuffin;
static char * _databuffout;
/*----------------------------------------------------------------
* Table de definition des messages
* - Nom de la requette
* - Version mini, Version maxi
* - Autorisee hors signature
* - Ouverture automatique des ports
* - Fonction, et parametre
*----------------------------------------------------------------*/
static struct msg_table _msg_table[] =
{
//
// Traitements directs par le service
//
{{'C', 'L', 'O', 'T'}, 0, 0xffff, TRUE, FALSE, _terminer, {0}},
{{'S', 'I', 'G', 'N'}, 0, 0xffff, TRUE, FALSE, _signature, {0}},
{{'E', 'T', 'A', 'P'}, 0, 0xffff, TRUE, FALSE, _test_etape, {0}},
{{'P', 'A', 'R', 'A'}, 0, 0xffff, TRUE, FALSE, _parametres, {0}},
{{'P', 'U', 'T', 'F'}, 0, 0xffff, FALSE, TRUE, _fichier_ecrit, {0}},
{{'G', 'E', 'T', 'F'}, 0, 0xffff, FALSE, TRUE, _fichier_lit, {0}},
{{'M', 'S', 'G', 'S'}, 0, 0xffff, FALSE, TRUE, _messages, {0}},
{{'V', 'A', 'R', 'S'}, 0, 0xffff, FALSE, TRUE, _variables, {0}},
//
// Traitements externes
//
// Transferts et procédures
{{'S', 'H', 'E', 'L'}, 0, 0xffff, FALSE, FALSE, _lanceprocedure, {0}},
{{'W', 'L', 'O', 'G'}, 0, 0xffff, FALSE, FALSE, _log, {0}},
{{'S', 'H', 'R', 'T'}, 0, 0xffff, FALSE, FALSE, _lanceprocedure_stdout, {0}},
{{'S', 'H', 'S', 'O'}, 0, 0xffff, FALSE, FALSE, _lanceprocedure_systemoutput, {0}},
{{'T', 'R', 'A', 'N'}, 0, 0xffff, FALSE, FALSE, _transfert, {0}},
{{0, 0, 0, 0}, 0, 0, 0, 0, NULL, {0}}
};
static int __fin = FALSE;
static int recvwait(int s, char * buf, int len, int flags)
{
#ifdef sun
int i = len;
char * ptr = buf;
while (i > 0)
{
int l;
if ((l = recv (s, ptr, i, flags)) < 0)
return -1;
if (l == 0)
return 0;
i -= l;
ptr += l;
}
return len;
#else
return recv(s, buf, len, flags | MSG_WAITALL);
#endif
}
int Processus_serveur (int sock_communication)
{
struct msg_header msgh;
struct msg_info msgi;
int m, i;
char * ptr;
/*
* Initialisation du processus utilisateur
*/
#ifdef DEBUG
trace ("Processus_serveur point 1");
#endif
__fin = FALSE;
_netbuff = (char *)malloc (NETBUFF_TMP);
_databuffin = (char *)malloc (NETBUFF_MAX);
_databuffout = (char *)malloc (NETBUFF_MAX);
if (_netbuff == NULL || _databuffin == NULL || _databuffout == NULL)
{
send (sock_communication, "ERRO", 4, 0);
send (sock_communication, "\n", 1, 0);
__fin = TRUE;
}
#ifdef DEBUG
trace ("Processus_serveur point 2");
#endif
if (!Crsf_Charger ())
{
send (sock_communication, "ERRO", 4, 0);
send (sock_communication, "\n", 1, 0);
__fin = TRUE;
}
#ifdef DEBUG
trace ("Processus_serveur point 3");
#endif
if (!Rejet_Charger ())
{
send (sock_communication, "ERRO", 4, 0);
send (sock_communication, "\n", 1, 0);
__fin = TRUE;
}
#ifdef DEBUG
trace ("Processus_serveur point 4");
#endif
if (!Parametres_Initialiser ())
{
send (sock_communication, "ERRO", 4, 0);
send (sock_communication, "\n", 1, 0);
__fin = TRUE;
}
/*
* Boucle de traitement des requettes
*/
#ifdef DEBUG
trace ("Processus_serveur point 5");
#endif
while (!__fin)
{
#ifdef DEBUG
trace ("Processus_serveur attente commande");
#endif
if (recvwait (sock_communication, (char *)(&msgh), sizeof (msgh), 0) <= 0)
{
if (errno == EINTR) __fin = TRUE;
else perror ("Erreur lecture des donnees");
__fin = TRUE;
break;
}
// Mise au format correct des donnees binaires
msgh.Version = ntohs (msgh.Version);
msgh.PortAller = ntohs (msgh.PortAller);
msgh.PortRetour = ntohs (msgh.PortRetour);
msgh.Longueur = ntohs (msgh.Longueur);
#ifdef DEBUG
trace ("Processus_serveur commande recue");
#endif
// Recherche si commande connue dans le tableau
for (m = 0; _msg_table[m].ReqName[0] != 0; m++)
{
if (memcmp (_msg_table[m].ReqName, msgh.ReqName, 4) != 0)
continue;
if (msgh.Version < _msg_table[m].MinVer || msgh.Version > _msg_table[m].MaxVer)
continue;
//
// Ok c'est trouve
// Lecture des donnees du message
//
i = msgh.Longueur;
ptr = _databuffin;
while (i > 0)
{
int l = (i > 512) ? 512 : i;
if (recvwait (sock_communication, ptr, l, 0) != l)
{
if (errno != EINTR) perror ("Erreur lecture des donnees");
__fin = TRUE;
break;
}
i -= l;
ptr += l;
}
msgi.header = msgh;
msgi.size_in = NETBUFF_MAX;
msgi.len_in = msgh.Longueur;
msgi.data_in = _databuffin;
msgi.size_out = NETBUFF_MAX;
msgi.len_out = 0;
msgi.data_out = _databuffout;
msgi.sok_in = 0;
msgi.sok_out = 0;
//
// Si besoin, ouverture des ports de communication additionels
//
if (_msg_table[m].Ouverture)
{
struct sockaddr_in sokdef;
#ifdef DEBUG
trace ("Ouverture des ports additionels");
#endif
if (msgh.PortAller != 0)
{
if ((msgi.sok_in = socket(PF_INET, SOCK_STREAM, 0)) == -1 )
{
perror("Erreur lors de la creation du socket");
sortie (-1);
}
//initialisation du serveur
sokdef.sin_family = AF_INET;
sokdef.sin_port = htons(msgh.PortAller);
sokdef.sin_addr.s_addr = gs_SaClient.sin_addr.s_addr;
if (connect (msgi.sok_in, (struct sockaddr *)&sokdef, sizeof (sokdef)) != 0)
{
perror("Erreur lors de la connexion du socket");
__fin = TRUE;
break;
}
#ifdef DEBUG
trace ("Connexion entree realisee");
#endif
}
if (msgh.PortRetour != 0)
{
if ((msgi.sok_out = socket(PF_INET, SOCK_STREAM, 0)) == -1 )
{
perror("Erreur lors de la creation du socket");
if (msgi.sok_in != 0)
close (msgi.sok_in);
sortie (-1);
}
//initialisation du serveur
sokdef.sin_family = AF_INET;
sokdef.sin_port = htons(msgh.PortRetour);
sokdef.sin_addr.s_addr = gs_SaClient.sin_addr.s_addr;
if (connect (msgi.sok_out, (struct sockaddr *)&sokdef, sizeof (sokdef)) != 0)
{
perror("Erreur lors de la connexion du socket");
if (msgi.sok_in != 0)
{
close (msgi.sok_in);
msgi.sok_in = 0;
}
__fin = TRUE;
break;
}
#ifdef DEBUG
trace ("Connexion sortie realisee\n");
#endif
}
}
//
// Si fonction disponible selon l'état de connexion
//
if (gs_Accept == 1 || _msg_table[m].Autori != FALSE)
{
//
// Appel de la fonction de traitement
//
if (_msg_table[m].fn_trait != NULL)
{
_msg_table[m].fn_trait (&msgi, _msg_table[m].Param);
}
}
else
{
printf ("Reception commande %4.4s(%d) interdite\n", msgh.ReqName, msgh.Version);
__fin = TRUE;
}
//
// Si besoin, fermeture des ports de communication additionels
//
if (_msg_table[m].Ouverture)
{
if (msgi.sok_in != 0)
{
shutdown (msgi.sok_in, 0);
close (msgi.sok_in);
msgi.sok_in = 0;
}
if (msgi.sok_out != 0)
{
shutdown (msgi.sok_out, 0);
close (msgi.sok_out);
msgi.sok_out = 0;
}
}
//
// Retour des donnees du message
//
msgh.PortAller = htons (msgh.PortAller);
msgh.PortRetour = htons (msgh.PortRetour);
msgh.Longueur = htons (msgi.len_out);
msgh.Version = htons (msgh.Version);
if (send (sock_communication, (char *)(&msgh), sizeof (msgh), 0) <= 0)
{
if (errno == EINTR) __fin = TRUE;
else perror ("Erreur envoi des donnees");
__fin = TRUE;
break;
}
i = msgi.len_out;
ptr = _databuffout;
while (i > 0)
{
int l = (i > 512) ? 512 : i;
if (send (sock_communication, ptr, l, 0) != l)
{
if (errno != EINTR) perror ("Erreur envoi des donnees");
__fin = TRUE;
break;
}
i -= l;
ptr += l;
}
break;
}
if (_msg_table[m].ReqName[0] == 0)
{
printf ("Reception commande %4.4s(%d) inconue\n", msgh.ReqName, msgh.Version);
send (sock_communication, "Commande inconnue, deconnexion\n", 31, 0);
__fin = TRUE;
}
}
send (sock_communication, "DISC", 4, 0);
send (sock_communication, "\n", 1, 0);
if (_netbuff != NULL)
free (_netbuff);
if (_databuffin != NULL)
free (_databuffin);
if (_databuffout != NULL)
free (_databuffout);
_netbuff = NULL;
_databuffin = NULL;
_databuffout = NULL;
#ifdef DEBUG
trace ("Processus_serveur point 99");
#endif
return 0;
}
void _terminer (struct msg_info * msg, union msg_param param)
{
__fin = TRUE;
}