/* ***********************IMPORTANT *********************************************
 *  Copyright (C) 2004-2007 Thierry Lagarde <tlagarde@users.sourceforge.net>
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License.
 *
 *
 *                      ********************
 *
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *
 *                      ********************
 *
 *
 * You are highly encouraged to send your changes to <tlagarde@users.sourceforge.net>
 * for possible incorporation into the main distribution.
 * By sending these changes to <tlagarde@users.sourceforge.net>,
 * it is assumed that you are offering <tlagarde@users.sourceforge.net>
 * the unlimited, non-exclusive right to reuse, modify, and relicense the code.
 *
 *
 *                      ********************
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **************************************************************************************/
#include <gtk/gtk.h>
#ifdef         __SCRIPT_ENABLE
#include <sys/msg.h>
#endif



#include "Communication.h"
#include "Commun.h"
#include "../Reseau.h"
#include "../Debug.h"
#include "Initialisation_Com.h"
#include "../Equipement.h"
#include "../Equipement_Port.h"
#include "../Script.h"
#include "../Interface/Root_Interface.h"
#include "../Nessus.h"
#include "../Snmp.h"
#include "../Interface/Wizard_Interface_Add_Network.h"
#include "../Interface/Demarrage_Interface.h"
#include "../Interface/New_Update_Interface.h"
#include "../Animation.h"
#include "../Declaration_Constante.h"
#include "../Contribution.h"
#include "../Interface/Maemo.h"
#include "../Macro.h"
#include "../Log.h"

struct Struct_Modele_Communication Liste_Communication[] = {
	{AGENT_VERSION, &Reception_Version_Agent,"AGENT_VERSION",sizeof(struct struct_Agent_Version)},
	{AJOUT_PORT, NULL,"AJOUT_PORT",0},
	{AJOUT_SIGNATURE, NULL,"AJOUT_SIGNATURE",0},
	{RESTAURATION_MACHINE, NULL,"RESTAURATION_MACHINE",0},
	{AJOUT_RESEAU_PRIVEE, NULL,"AJOUT_RESEAU_PRIVEE",0},
	{DEMANDE_LISTE_INTERFACE, NULL,"DEMANDE_LISTE_INTERFACE",0},
	{NOUVELLE_INTERFACE, &Recuperation_Nouvelle_Interface,"NOUVELLE_INTERFACE",sizeof(struct struct_Nouvelle_Interface)},
	{FIN_LISTE_INTERFACE, &Recuperation_Liste_Interface_Fini,"FIN_LISTE_INTERFACE",sizeof(struct struct_Fin_Liste_Interface)},
	{DEMARRAGE_AGENT, NULL,"DEMARRAGE_AGENT",0},
	{DEMANDE_ARRET_AGENT, NULL,"DEMANDE_ARRET_AGENT",0},
	{RETOUR_MESSAGE, &Recuperation_Message_Agent,"RETOUR_MESSAGE",sizeof(struct struct_Retour_Message)},
	{RETOUR_ERREUR_CRITIQUE, &Recuperation_Retour_Critique_Agent,"RETOUR_ERREUR_CRITIQUE",sizeof(struct struct_Retour_Erreur_Critique)},
	{INFO_AGENT, &Retour_Info,"INFO_AGENT",sizeof(struct struct_Info_Agent)},
	{NOUVEAU_EQUIPEMENT, &Recuperation_Nouveau_Equipement,"NOUVEAU_EQUIPEMENT",sizeof(struct struct_Nouveau_Equipement)},
	{DEMANDE_NESSUS, NULL,"DEMANDE_NESSUS",0},
	{DEMARRAGE_NESSUS, &Demarrage_Nessus,"DEMARRAGE_NESSUS",sizeof(struct struct_Demarrage_Nessus)},
	{RETOUR_NESSUS_INFO, &Nouvelle_Info_Nessus,"RETOUR_NESSUS_INFO",sizeof(struct struct_Retour_Nessus_Info)},
	{RETOUR_NESSUS_DONNEE, &Nouvelle_Donnee_Nessus,"RETOUR_NESSUS_DONNEE",sizeof(struct struct_Retour_Nessus_Donnee)},
	{RETOUR_NESSUS_FIN, &Fin_Nessus,"RETOUR_NESSUS_FIN",sizeof(struct struct_Retour_Nessus_Fin)},
	{DEMANDE_RAFRAICHIR_ETAT_EQUIMEMENT, NULL,"DEMANDE_RAFRAICHIR_ETAT_EQUIMEMENT",0},
	{RETOUR_RAFRAICHIR_ETAT_EQUIMEMENT, &Retour_Modification_Etat_Equipement,"RETOUR_RAFRAICHIR_ETAT_EQUIMEMENT",sizeof(struct struct_Retour_Rachaichir_Etat_Equipement)},
	{DEMANDE_RAFRAICHIR_LISTE_PORTS, NULL,"DEMANDE_RAFRAICHIR_LISTE_PORTS",0},
	{RETOUR_RAFRAICHIR_LISTE_PORTS, &Retour_Modification_Etat_Port,"RETOUR_RAFRAICHIR_LISTE_PORTS",sizeof(struct struct_Retour_Rachaichir_Liste_Ports)},
	{DEMANDE_RAFRAICHIR_ENREGISTREMENT_SAMBA, NULL,"DEMANDE_RAFRAICHIR_ENREGISTREMENT_SAMBA",0},
	{RETOUR_RAFRAICHIR_ENREGISTREMENT_SAMBA, NULL,"RETOUR_RAFRAICHIR_ENREGISTREMENT_SAMBA",0},
	{DEMANDE_RAFRAICHIR_SIGNATURE, NULL,"DEMANDE_RAFRAICHIR_SIGNATURE",0},
	{RETOUR_RAFRAICHIR_SIGNATURE, NULL,"RETOUR_RAFRAICHIR_SIGNATURE",0},
	{DEMANDE_NOTIFICATION_WARNING_ETAT_EQUIPEMENT, NULL,"DEMANDE_NOTIFICATION_WARNING_ETAT_EQUIPEMENT",0},
	{DEMANDE_NOTIFICATION_WARNING_ETAT_PORT, NULL,"DEMANDE_NOTIFICATION_WARNING_ETAT_PORT",0},
	{DEMANDE_NOTIFICATION_CRITIQUE_ETAT_EQUIPEMENT, NULL,"DEMANDE_NOTIFICATION_CRITIQUE_ETAT_EQUIPEMENT",0},
	{DEMANDE_NOTIFICATION_CRITIQUE_ETAT_PORT, NULL,"DEMANDE_NOTIFICATION_CRITIQUE_ETAT_PORT",0},
	{RETOUR_NOTIFICATION_CHANGEMENT_ETAT_EQUIPEMENT, &Retour_Notification_Equipement,"RETOUR_NOTIFICATION_CHANGEMENT_ETAT_EQUIPEMENT",sizeof(struct struct_Retour_Notification_Changement_Etat_Equipement)},
	{RETOUR_NOTIFICATION_CHANGEMENT_ETAT_PORT, &Retour_Notification_Port,"RETOUR_NOTIFICATION_CHANGEMENT_ETAT_PORT",sizeof(struct struct_Retour_Notification_Changement_Etat_Port)},
	{ANNULATION_NOTIFICATION_ETAT_EQUIPEMENT, NULL,"ANNULATION_NOTIFICATION_ETAT_EQUIPEMENT",0},
	{ANNULATION_NOTIFICATION_ETAT_PORT, NULL,"ANNULATION_NOTIFICATION_ETAT_PORT",0},
	{ACTIVE_ALERTE_INTRUS, NULL,"ACTIVE_ALERTE_INTRUS",0},
	{DESACTIVE_ALERTE_INTRUS, NULL,"DESACTIVE_ALERTE_INTRUS",0},
	{ALERTE_INTRUS, &Retour_Alerte_Intrusion,"ALERTE_INTRUS",sizeof(struct struct_Alerte_Intrus)},
	{DEMANDE_MODIFIE_NIVEAU_DEBUG, NULL,"DEMANDE_MODIFIE_NIVEAU_DEBUG",0},
	{RETOUR_LISTE_SNMP, &Recuperation_Liste_Snmp,"RETOUR_LISTE_SNMP",sizeof(struct struct_Retour_Liste_SNMP)},
	{DEMANDE_LANCEMENT_SCRIPT, NULL,"DEMANDE_LANCEMENT_SCRIPT",0},
	{RETOUR_SCRIPT, &Retour_Script,"RETOUR_SCRIPT",sizeof(struct struct_Retour_Script)},
	{RETOUR_SCRIPT_TERMINER, &Retour_Script_Terminer,"RETOUR_SCRIPT_TERMINER",sizeof(struct struct_Retour_Script_Terminer)},
	{DEMANDE_RAFRAICHIR_EQUIPEMENT, NULL,"DEMANDE_RAFRAICHIR_EQUIPEMENT",0},
	{RETOUR_RAFRAICHIR_EQUIPEMENT, &Retour_Rafraichir_Equipement,"RETOUR_RAFRAICHIR_EQUIPEMENT",sizeof(struct struct_Retour_Rafraichir_Equipement)},
	{IP_RETROUVER, &Equipement_Ip_Retrouver,"IP_RETROUVER",sizeof(struct struct_Ip_Retrouver )},
	{IP_PERDU, &Equipement_Ip_Perdu,"IP_PERDU",sizeof(struct struct_Ip_Perdu)},
	{IP_MODIFIER, &Equipement_Ip_Modifier,"IP_MODIFIER",sizeof(struct struct_Ip_Modifier)},
	{DEMANDE_LISTE_SNMP, NULL,"DEMANDE_LISTE_SNMP",0},
	{DEL_GLIST_SNMP, &Retour_Efface_Liste_Snmp,"DEL_GLIST_SNMP",sizeof(struct struct_Del_Glist_SNMP)},
	{DEMANDE_LISTE_SNMP_ALL, NULL,"DEMANDE_LISTE_SNMP_ALL",0},
	{DEMANDE_WAKE_UP, NULL ,"DEMANDE_WAKE_UP",0},
	{DEMANDE_LOG_EQUIPEMENT, NULL ,"DEMANDE_LOG_EQUIPEMENT",0},
	{RETOUR_LOG_EQUIPEMENT, &Recuperation_Log_Equipement ,"RETOUR_LOG_EQUIPEMENT",sizeof(struct struct_Retour_Log_Equipement)},
	{RETOUR_RAFRAICHIR_NOM_UTILISATEUR, &Retour_Rafraichir_Nom_Utilisateur ,"RETOUR_RAFRAICHIR_NOM_UTILISATEUR",sizeof(struct struct_Retour_Rafraichir_Nom_Utilisateur)},
	{AFFICHE_NOUVEAU_EQUIPEMENT, &Affiche_Nouveau_Equipement ,"AFFICHE_NOUVEAU_EQUIPEMENT",sizeof(struct struct_Retour_Affiche_Nouveau_Equipement)},
	{DEMANDE_SNMP_SCALAIRE, NULL,"DEMANDE_SNMP_SCALAIRE",0},
	{RETOUR_SNMP_SCALAIRE, &Retour_Liste_Snmp_Scalaire,"DEMANDE_LISTE_SCALAIRE",sizeof(struct struct_Retour_SNMP_Scalaire)}	
};


void Log_Reception_Transmission(struct Struct_Liste_Reseau *Reseau,gchar *Texte_Log){
	if (Reseau!=NULL)
		Log(Reseau->Log_Recv,Texte_Log);
	MYFREE(Texte_Log);
}


void Recuperation_Nb_Octet_Recu (gint Nb_Octet, struct Struct_Liste_Reseau *Reseau)
{
	if (Reseau != NULL)
		Reseau->Octet_Recu_Agent = Reseau->Octet_Recu_Agent + Nb_Octet;
}

gboolean Rachaichi_Info_Transfert_Entre_Agent (void)
{
	gchar    *Text = NULL;

	if (Reseau_Selectionner != NULL) {
		if (Reseau_Selectionner->Octet_Recu_Agent > 1024)
			Text = g_strdup_printf ("R : %.1f Ko/s", (((double) Reseau_Selectionner->Octet_Recu_Agent) / 1024));
		else
			Text = g_strdup_printf ("R : %d o/s", Reseau_Selectionner->Octet_Recu_Agent);
		gtk_label_set_text (GTK_LABEL (label_Inter_AutoScan_Reception), Text);
		MYFREE (Text);

		if (Reseau_Selectionner->Octet_Envoyer_Agent > 1024)
			Text = g_strdup_printf ("S : %.1f Ko/s", (((double) Reseau_Selectionner->Octet_Envoyer_Agent) / 1024));
		else
			Text = g_strdup_printf ("S : %d o/s", Reseau_Selectionner->Octet_Envoyer_Agent);
		gtk_label_set_text (GTK_LABEL (label_Inter_AutoScan_Emission), Text);
		MYFREE (Text);
		Reseau_Selectionner->Octet_Recu_Agent = 0;
		Reseau_Selectionner->Octet_Envoyer_Agent = 0;
		
		if (Reseau_Selectionner->Compteur_Activite_Agent>10)
			gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progressbar), "Agent : Failed");
		Reseau_Selectionner->Compteur_Activite_Agent++;
	}
	return TRUE;
}


gboolean Donnee_Socket(int socket,struct Struct_Liste_Reseau *Reseau){
	fd_set fd_read,fd_write;
	socklen_t lon; 
    struct timeval tv;
	int retval,valopt;
	



	FD_ZERO(&fd_read);
	FD_SET(socket, &fd_read);
	FD_ZERO(&fd_write);
	FD_SET(socket, &fd_write);

   	tv.tv_sec = 1;
    tv.tv_usec = 0;
 	retval = select(socket + 1,&fd_read, &fd_write, NULL, &tv);
    if (retval==2){
	
    	lon = sizeof(int); 
    	if (getsockopt(socket, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
#ifdef __DEBUG_COM
			Log_Reception_Transmission(Reseau,g_strdup_printf("Error in getsockopt() %d - %s\n", errno, strerror(errno)));
#endif
			debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Error in getsockopt() %d - %s\n", errno, strerror(errno)); 
        	return FALSE;
		} 
		if (valopt) { 
#ifdef __DEBUG_COM
			Log_Reception_Transmission(Reseau,g_strdup_printf("Error in delayed connection() %d - %s", valopt, strerror(valopt)));
#endif
			debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Error in delayed connection() %d - %s",valopt, strerror(valopt)); 
			return FALSE;
		} 
#ifdef __DEBUG_COM
			Log_Reception_Transmission(Reseau,g_strdup_printf(" Reception Donnée...\n"));
#endif
		return TRUE;
	}
    else {
#ifdef __DEBUG_COM
		Log_Reception_Transmission(Reseau,g_strdup_printf("Pas de données depuis 1 secondes  retval=%d",retval));
#endif
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Pas de données depuis 1 secondes  retval=%d",retval);
		sleep(1);
	}
	return FALSE;
	
	
/*	struct pollfd fds;
	int       resultat;

	bzero (&fds, sizeof fds);
	fds.events = POLLIN;
	fds.fd = socket;	
	if ((resultat = poll (&fds, 1, 1000)) > 0) {
		if ((fds.revents & POLLERR) == POLLERR) {
			debug_printf (INTERFACE,D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Condition d'erreur");
			return FALSE;
		}
		if ((fds.revents & POLLHUP) == POLLHUP) {
			debug_printf (INTERFACE,D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Déconnexion");
			return FALSE;
		}
		return TRUE;
	}
	else {
		if (resultat != 0)
			debug_printf (INTERFACE,D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s", strerror (errno));
		return FALSE;
	}*/
}

gboolean Communication_Reception_Donnee_Boucle (void)
{
	struct struct_Info Donnee;	
	struct struct_Info_Entete Entete;
	struct Struct_Liste_Reseau *Reseau = NULL;
	guint     Nb_Objet_Liste, i, Tentative;
	gint      Taille_Donnee_Recue,Taille_Donnee_Recue_Part,Ckecksum;
	gchar     Donnee_Brut[TAILLE_MAX_DONNEE_BRUT],*pEntete = NULL;
	
	if (Nouvelle_Version_Telechargable){
		gtk_widget_show (button_Message_Root);
		gtk_widget_show (label_Message_Root);
		Nouvelle_Version_Telechargable = FALSE;
	}
	if (Connecter_Agent){
	
		Taille_Donnee_Recue = 0;
		pEntete = &Entete; 
		do {  
		
			Taille_Donnee_Recue = recvfrom (Socket_Agent_Init, &Entete, sizeof (struct struct_Info_Entete), 0, NULL, 0);
			if (Taille_Donnee_Recue > 0){
			
				Tentative = 0;
				while ((sizeof (struct struct_Info_Entete)!=Taille_Donnee_Recue)&&(Tentative!=10)){
					Tentative++;
					if (!Donnee_Socket(Socket_Agent_Init,NULL)) 
						debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "No data : (Tentative : %d)", Tentative);
					Taille_Donnee_Recue_Part = recvfrom (Socket_Agent_Init, &pEntete[Taille_Donnee_Recue], sizeof (struct struct_Info_Entete)-Taille_Donnee_Recue, 0, NULL, 0);
					if (Taille_Donnee_Recue_Part == -1){
						debug_printf (INTERFACE,D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Taille_Donnee_Recue_Part == -1   %s  Socket (%d)", strerror (errno),Socket_Agent_Init);
						if (!(errno == EINTR || errno == EAGAIN))
							debug_printf (INTERFACE,D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s Socket (%d)", strerror (errno),Socket_Agent_Init);
						usleep(400000);
					}
					else {
						if (Taille_Donnee_Recue_Part==0)
							debug_printf (INTERFACE,D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Taille_Donnee_Recue_Part == 0   %s  Socket (%d)", strerror (errno),Socket_Agent_Init);
						Taille_Donnee_Recue = Taille_Donnee_Recue + Taille_Donnee_Recue_Part;
					}
				}
			
				if (sizeof (struct struct_Info_Entete) != Taille_Donnee_Recue)
					debug_printf (INTERFACE,D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[%s]  [%d]!=[%d]", Liste_Communication[Entete.ID_Info].Debug,sizeof (struct struct_Info_Entete), Taille_Donnee_Recue);
			
				if (Entete.Taille_Donnee != Liste_Communication[Entete.ID_Info].Taille_Structure)
					debug_printf (INTERFACE,D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[%s]  [%d]!=[%d]", Liste_Communication[Entete.ID_Info].Debug,Liste_Communication[Entete.ID_Info].Taille_Structure, Entete.Taille_Donnee);
				if (Entete.Taille_Donnee > TAILLE_MAX_DONNEE_BRUT)
					debug_printf (INTERFACE,D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[%s]  Taille:[%d]", Liste_Communication[Entete.ID_Info].Debug, Entete.Taille_Donnee);
			
				Tentative = 0;
				Taille_Donnee_Recue = 0; 
				do{
					Tentative++;
					if (!Donnee_Socket(Socket_Agent_Init,NULL))
						debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "No data : (Tentative : %d)", Tentative);
					Taille_Donnee_Recue_Part = recvfrom (Socket_Agent_Init, &Donnee_Brut[Taille_Donnee_Recue], Entete.Taille_Donnee-Taille_Donnee_Recue, 0, NULL, 0);
					if (Taille_Donnee_Recue_Part == -1){
						debug_printf (D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Taille_Donnee_Recue_Part == -1   %s  Socket (%d)", strerror (errno),Socket_Agent_Init);
						if (!(errno == EINTR || errno == EAGAIN))
							debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s  Socket (%d)", strerror (errno),Socket_Agent_Init);
						usleep(400000);
					}
					else {
						if (Taille_Donnee_Recue_Part==0)
							debug_printf (D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Taille_Donnee_Recue_Part == 0   %s  Socket (%d)", strerror (errno),Socket_Agent_Init);
						Taille_Donnee_Recue = Taille_Donnee_Recue + Taille_Donnee_Recue_Part;
					}				
				}while ((Entete.Taille_Donnee!=Taille_Donnee_Recue)&&(Tentative!=10));
			
				if ((Taille_Donnee_Recue == -1)||(Taille_Donnee_Recue == 0))
					debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[%s]", strerror (errno));
				if (Entete.Taille_Donnee!=Taille_Donnee_Recue)
					debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Entete.Taille_Donnee!=Taille_Donnee_Recue [%d!=%d] Tentative(%d)", Entete.Taille_Donnee,Taille_Donnee_Recue,Tentative);
			
				Ckecksum = Calculer_Ckecksum(Donnee_Brut,Taille_Donnee_Recue);
				if (Ckecksum!=Entete.Ckecksum)
					debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Ckecksum!=Entete.Ckecksum [%08X!=%08X]    Nb Tentative : (%d)  Taille_Donnee(%d)  TailleRecu(%d)", Ckecksum, Entete.Ckecksum,Tentative,Entete.Taille_Donnee,Taille_Donnee_Recue);
			
				if (Liste_Communication[Entete.ID_Info].Gestion_Communication != NULL)
					(*Liste_Communication[Entete.ID_Info].Gestion_Communication) ((gpointer *) &Donnee_Brut);
				else
					debug_printf (INTERFACE, D_WARN_USER, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Reception Message sans action defini   [%s] Taille=[%d]", Liste_Communication[Entete.ID_Info].Debug,Taille_Donnee_Recue);
			}
		}
		while (Taille_Donnee_Recue>0);
	}
	

	Taille_Donnee_Recue = 0;
	Nb_Objet_Liste = g_list_length (GList_Liste_Reseau);
	pEntete = &Entete; 
	for (i = 0; i < Nb_Objet_Liste; i++) {
		do {
			Reseau = g_list_nth_data (GList_Liste_Reseau, i);
		
			Taille_Donnee_Recue = recvfrom (Reseau->Socket_Agent, &Entete, sizeof (struct struct_Info_Entete), 0, NULL, 0);
			if (Taille_Donnee_Recue>0){
			
				Tentative = 0;
				while ((sizeof (struct struct_Info_Entete)!=Taille_Donnee_Recue)&&(Tentative!=10)){
					Tentative++;
					if (!Donnee_Socket(Reseau->Socket_Agent,Reseau)) 
						debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "No data : (Tentative : %d)", Tentative);
					Taille_Donnee_Recue_Part = recvfrom (Reseau->Socket_Agent, &pEntete[Taille_Donnee_Recue], sizeof (struct struct_Info_Entete)-Taille_Donnee_Recue, 0, NULL, 0);
					if (Taille_Donnee_Recue_Part == -1){
#ifdef __DEBUG_COM
						Log_Reception_Transmission(Reseau,g_strdup_printf("[%s] Tentative(%d) Taille_Donnee_Recue_Part == -1   %s  Socket (%d)\n",Liste_Communication[Entete.ID_Info].Debug, Tentative, strerror (errno),Reseau->Socket_Agent));
#endif						
						debug_printf (INTERFACE,D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Taille_Donnee_Recue_Part == -1   %s  Socket (%d)", strerror (errno),Reseau->Socket_Agent);
						if (!(errno == EINTR || errno == EAGAIN))
							debug_printf (INTERFACE,D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s Socket (%d)", strerror (errno),Reseau->Socket_Agent);
						usleep(400000);
					}
					else {
						if (Taille_Donnee_Recue_Part==0)
							debug_printf (INTERFACE,D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Taille_Donnee_Recue_Part == 0   %s  Socket (%d)", strerror (errno),Reseau->Socket_Agent);
						Taille_Donnee_Recue = Taille_Donnee_Recue + Taille_Donnee_Recue_Part;
					}
				}
				if (Liste_Communication[Entete.ID_Info].ID_Communication!=INFO_AGENT){
#ifdef __DEBUG_COM					
					Log_Reception_Transmission(Reseau,g_strdup_printf("[%s] %d\n",Liste_Communication[Entete.ID_Info].Debug,Entete.Taille_Donnee));
#endif	
				}
			
				if (sizeof (struct struct_Info_Entete) != Taille_Donnee_Recue)
					debug_printf (INTERFACE,D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[%s]  [%d]!=[%d]", Liste_Communication[Entete.ID_Info].Debug, sizeof (struct struct_Info_Entete), Taille_Donnee_Recue);
			
				if (Entete.Taille_Donnee != Liste_Communication[Entete.ID_Info].Taille_Structure)
					debug_printf (INTERFACE,D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[%s]  [%d]!=[%d]",  Liste_Communication[Entete.ID_Info].Debug,Liste_Communication[Entete.ID_Info].Taille_Structure, Entete.Taille_Donnee);
				if (Entete.Taille_Donnee > TAILLE_MAX_DONNEE_BRUT)
					debug_printf (INTERFACE,D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[%s]  Taille:[%d]", Liste_Communication[Entete.ID_Info].Debug, Entete.Taille_Donnee);
			
				Tentative = 0;
				Taille_Donnee_Recue = 0;
				do{
					Tentative++;
					if (!Donnee_Socket(Reseau->Socket_Agent,Reseau))
						debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "No data : (Tentative : %d)", Tentative);
					Taille_Donnee_Recue_Part = recvfrom (Reseau->Socket_Agent, &Donnee_Brut[Taille_Donnee_Recue], Entete.Taille_Donnee-Taille_Donnee_Recue, 0, NULL, 0);
					if (Taille_Donnee_Recue_Part == -1){
#ifdef __DEBUG_COM		
						Log_Reception_Transmission(Reseau,g_strdup_printf("[%s] Tentative(%d) Taille_Donnee_Recue_Part == -1   %s  Socket (%d)\n",Liste_Communication[Entete.ID_Info].Debug, Tentative, strerror (errno),Reseau->Socket_Agent));
#endif	
						debug_printf (D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Taille_Donnee_Recue_Part == -1   %s  Socket (%d)", strerror (errno),Reseau->Socket_Agent);
						if (!(errno == EINTR || errno == EAGAIN))
							debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s  Socket (%d)", strerror (errno),Reseau->Socket_Agent);
						usleep(400000);
					}
					else {
						if (Taille_Donnee_Recue_Part==0)
							debug_printf (D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Taille_Donnee_Recue_Part == 0   %s  Socket (%d)", strerror (errno),Reseau->Socket_Agent);
						Taille_Donnee_Recue = Taille_Donnee_Recue + Taille_Donnee_Recue_Part;
					}			
				}while ((Entete.Taille_Donnee!=Taille_Donnee_Recue)&&(Tentative!=10));
			
				if ((Taille_Donnee_Recue == -1)||(Taille_Donnee_Recue == 0))
					debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[%s] Taille Recupere Entete : (%d)", strerror (errno),Taille_Donnee_Recue);
				if (Entete.Taille_Donnee!=Taille_Donnee_Recue)
						debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Entete.Taille_Donnee!=Taille_Donnee_Recue [%d!=%d]   Réseau:[%s]  [%s] Tentative(%d)", Entete.Taille_Donnee,Taille_Donnee_Recue, Reseau->Nom_Reseau,Liste_Communication[Entete.ID_Info].Debug,Tentative);
			
				Ckecksum = Calculer_Ckecksum(Donnee_Brut,Taille_Donnee_Recue);
				if (Ckecksum!=Entete.Ckecksum)
					debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[%s] Ckecksum!=Entete.Ckecksum [%08X!=%08X]    Nb Tentative : (%d)  Taille_Donnee(%d)  TailleRecu(%d)", Liste_Communication[Entete.ID_Info].Debug,Ckecksum, Entete.Ckecksum,Tentative,Entete.Taille_Donnee,Taille_Donnee_Recue);
				if (Liste_Communication[Entete.ID_Info].ID_Communication!=INFO_AGENT){
#ifdef __DEBUG_COM					
					Log_Reception_Transmission(Reseau,g_strdup_printf("[%s] Ckecksum %08X\n",Liste_Communication[Entete.ID_Info].Debug,Ckecksum));
#endif	
				}
			
			
				if (Liste_Communication[Entete.ID_Info].Gestion_Communication != NULL)
					(*Liste_Communication[Entete.ID_Info].Gestion_Communication) ((gpointer *) &Donnee_Brut);
				else
					debug_printf (INTERFACE, D_WARN_USER, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Reception Message sans action defini   [%s] Taille=[%d]", Liste_Communication[Entete.ID_Info].Debug,Taille_Donnee_Recue);
			
			}
		}
		while (Taille_Donnee_Recue>0);
	}

#ifdef         __SCRIPT_ENABLE

	do {
		bzero (&Donnee, sizeof (struct struct_Info));
		if ((Taille_Donnee_Recue = msgrcv (File_Info, (void *) &Donnee, sizeof (struct struct_Info) - sizeof (long), Mon_Pid, IPC_NOWAIT)) > -1) {
			if (Liste_Communication[Donnee.ID_Info].Gestion_Communication != NULL)
				(*Liste_Communication[Donnee.ID_Info].Gestion_Communication) ((gpointer *) & Donnee.Donnee);
			else
				debug_printf (INTERFACE, D_WARN_USER, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Reception Message sans action defini    %d", Donnee.ID_Info);
		}
	}
	while (Taille_Donnee_Recue != -1);
#endif
	return TRUE;
}


void Communication_Initialisation (void)
{
#ifdef         __SCRIPT_ENABLE
	Mon_Pid = getpid ();
	debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "AutoScan : pid(%d)", Mon_Pid);

	if (msgctl (msgget (KEY_FILE, 0), IPC_RMID, NULL) == -1)
		debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "File KEY_FILE");

	if ((File_Info = msgget (KEY_FILE, IPC_CREAT | 0777)) == -1)
		debug_printf (INTERFACE, D_WARN_USER, __FILE__, __PRETTY_FUNCTION__, __LINE__, "msgget  : %s", strerror (errno));
#endif
}



/* 
*             Communication TCP
*
*/

/*int waiting_service (int sock, int event)
{
	struct pollfd fds;
	int       resultat;

	bzero (&fds, sizeof fds);
	fds.events = event;
	fds.fd = sock;	
	debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "waiting_service : (%d)", sock);
	if ((resultat = poll (&fds, 1, 1000)) > 0) {
		if ((fds.revents & POLLERR) == POLLERR) {
			debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "waiting_service Socket error : (%d)", sock);
			return ERREUR_SOCK;
		}
		if ((fds.revents & POLLHUP) == POLLHUP) {
			debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "waiting_service Socket error : (%d)", sock);
			return ERREUR_SOCK;
		}
		debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "waiting_service : (%d) pret", sock);
		return DONNEE_PRET;
	}
	else {
		if (resultat != 0) {
			debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s", strerror (errno));
		}
		debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "waiting_service : (%d) Attendre", sock);
		return ATTENDRE;
	}
	return DONNEE_PRET; 

}*/


/*gboolean attendre_Sock (int sock)
{
	int       temp;
	int       result;

	temp = 5;
	while ((result = waiting_service (sock, POLLOUT)) == ATTENDRE) {
		printf (".%d\n", temp);
		temp--;
		if (temp == 0) {
			debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Timeout dans Attendre_donnee");
			return FALSE;
		}
	}
	if (result == ERREUR_SOCK)
		return FALSE;
	return TRUE;
}
*/

int connection_Serveur (char *serveur, struct hostent *host, int port, int sock)
{
	struct sockaddr_in SocketAddr;
	memset (&SocketAddr, 0, sizeof (struct sockaddr_in));
	memcpy (&SocketAddr.sin_addr.s_addr, host->h_addr, host->h_length);
	SocketAddr.sin_family = AF_INET;
	SocketAddr.sin_port = htons (port);
	/*
	Plante sous 64 bits
	debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[I] Connection au serveur [%s] en cours   (%s)\n", serveur,inet_ntoa (SocketAddr.sin_addr));*/
	if (connect (sock, (struct sockaddr *) &SocketAddr, sizeof (struct sockaddr)) < 0) {
		debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "connect : [%s] socket (%d)", strerror (errno),sock);
		if (errno != EINPROGRESS) {
			debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s", strerror (errno));
			return FALSE;
		}
		return FALSE;
	
	}
	debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Connection au serveur : %s:%i", serveur, port);
	return TRUE;
}


#define SOCKET_NON_BLOQUANT 1
#define SOCKET_BLOQUANT 0

void set_NonBlock (int sock,int block){
	int       flags;
	if ((flags = fcntl (sock, F_GETFL)) == -1)
		debug_printf (INTERFACE,D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s", strerror (errno));
	if (fcntl (sock, F_SETFL, flags | O_NONBLOCK) == -1)
		debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s", strerror (errno));
}


int Initialisation_TCP_Agent (gchar *Nom_Serveur_Agent,gint Num_Port)
{
	#define TIME_OUT_CONNECT 6
	#define TENTATIVE_CONNECT_AGENT 2
	struct hostent *host = NULL;
	int       NbOctet, TimeOut, Tentative_Connect_Agent;
	int       Socket_Agent;
	gboolean  Connection_Accepter;
	gchar     *Text = NULL;
	gchar	  Entete[30];
	fd_set fd_read,fd_write;
	socklen_t lon; 
    struct timeval tv;
	int retval,valopt;
/*	struct pollfd fd_write;
	int       res;*/

	debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "[%s](%d)",Nom_Serveur_Agent,Num_Port);

	
		sleep(2);
	Socket_Agent_Init = -1;
	if ((host = gethostbyname (Nom_Serveur_Agent)) == NULL) {
		return -1;
	}
	Socket_Agent = socket (AF_INET, SOCK_STREAM, 0);
	ERROR_if (Socket_Agent == -1);

	Tentative_Connect_Agent = 0;
	Connection_Accepter = FALSE;
		
#ifndef         __WINDOWS_ENABLE
	set_NonBlock(Socket_Agent,SOCKET_NON_BLOQUANT);

		if (!connection_Serveur (Nom_Serveur_Agent, host, Num_Port, Socket_Agent)){
		
			TimeOut = 0;
			do {
				Text = g_strdup_printf ("Connecting (%s)(%d)   please wait (%d)", Nom_Serveur_Agent,Tentative_Connect_Agent,TIME_OUT_CONNECT-TimeOut);
				if (AutoRestore){
#ifndef         __MAEMO
					gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progressbar_Demarrage), Text);
#else
					gtk_progress_bar_set_text_maemo(banner_maemo_Demarrage, Text);
#endif
				}
				else
					gtk_label_set_text(label_Localisation_Connecting, Text);
				MYFREE (Text);
			
				refresh();
			
			
			
				FD_ZERO(&fd_read);
				FD_SET(Socket_Agent, &fd_read);
				FD_ZERO(&fd_write);
				FD_SET(Socket_Agent, &fd_write);
			
   				tv.tv_sec = 1;
    			tv.tv_usec = 0;
 				retval = select(Socket_Agent + 1,&fd_read, &fd_write, NULL, &tv);
    			if (retval==2){
				
              		lon = sizeof(int); 
              		if (getsockopt(Socket_Agent, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
						debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Error in getsockopt() %d - %s\n", errno, strerror(errno)); 
              			return -1;
					} 
					if (valopt) { 
                 		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__,  "Error in delayed connection() %d - %s", valopt, strerror(valopt)); 
	               		Text = g_strdup_printf ("[FAILED] Connecting (%s)  (%s)", Nom_Serveur_Agent, strerror(valopt));
						if (!AutoRestore)
							gtk_label_set_text(label_Localisation_Connecting, Text);
						refresh();
						MYFREE (Text);
						debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Impossible de se connecter à l agent");
						return -1;
					} 
	        		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Ecriture+Lecture maintenant  = %d",retval);
					Connection_Accepter = TRUE;
				}
    			else {
	        		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Pas de données depuis 1 secondes  retval=%d",retval);
					sleep(1);
				}
			

				
				/*bzero (&fd_write, sizeof fd_write);
				fd_write.events = POLLOUT;	
				fd_write.fd = Socket_Agent;	
				if ((res = poll (&fd_write, 1, 1000)) > 0) {
					debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__,"poll() res=%d  revents=0x%x  POLLHUP=0x%x POLLERR=0x%x POLLIN=0x%x  POLLOUT=0x%x",res, fd_write.revents,  fd_write.revents & POLLHUP,fd_write.revents & POLLERR, fd_write.revents & POLLIN, fd_write.revents & POLLOUT);
					if (!(fd_write.revents  & POLLOUT)){
						debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Socket pret en ecriture\n");
						Connection_Accepter = TRUE;
					}
				}
				else {
					if (res != 0) 
						debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Socket error : (%d)  [%s]", Socket_Agent,strerror (errno));
					debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Pas de données depuis 1 secondes\n");
				}
				debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Tentative Connection Agent : TimeOut n°[%d]", TimeOut);
				sleep(1);*/
				TimeOut++;
			} while ((!Connection_Accepter) && (TimeOut <= TIME_OUT_CONNECT));
		}
		else 
			Connection_Accepter = TRUE;


/*	do {
		Text = g_strdup_printf ("Connecting (%s)   please wait (%d)", Nom_Serveur_Agent, TENTATIVE_CONNECT_AGENT-Tentative_Connect_Agent);
		if (AutoRestore){
#ifndef         __MAEMO 
			gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progressbar_Demarrage), Text);
#else 
			gtk_progress_bar_set_text_maemo(banner_maemo_Demarrage, Text);	 
#endif 
		}
		else
			gtk_label_set_text(label_Localisation_Connecting, Text);

		refresh();
		MYFREE (Text);
		debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Tentative Connection Agent : tentative n°[%d]", Tentative_Connect_Agent);
		if (connection_Serveur (Nom_Serveur_Agent, host, Num_Port, Socket_Agent) == FALSE) {
			sleep (1);
		}
		else
			Connection_Accepter = TRUE;
		Tentative_Connect_Agent++;
	} while ((!Connection_Accepter) && (Tentative_Connect_Agent <= TENTATIVE_CONNECT_AGENT));
*/
#else  	
	set_NonBlock(Socket_Agent,SOCKET_NON_BLOQUANT);
	do {
		if (!connection_Serveur (Nom_Serveur_Agent, host, Num_Port, Socket_Agent)){
		
			TimeOut = 0;
			do {
				Text = g_strdup_printf ("Connecting (%s)(%d)   please wait (%d)", Nom_Serveur_Agent,Tentative_Connect_Agent,TIME_OUT_CONNECT-TimeOut);
				if (AutoRestore){
					gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progressbar_Demarrage), Text);
				}
				else
					gtk_label_set_text(label_Localisation_Connecting, Text);
				refresh();
				MYFREE (Text);
				FD_ZERO(&ensemble);
				FD_SET(Socket_Agent, &ensemble);
			
   				tv.tv_sec = 1;
    			tv.tv_usec = 0;
 				retval = select(Socket_Agent + 1, &ensemble, NULL, NULL, &tv);
    			if (retval){
	        		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Données disponibles maintenant\n");
					Connection_Accepter = TRUE;
				}
    			else
	        		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Pas de données depuis 1 secondes\n");
				debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Tentative Connection Agent : TimeOut n°[%d]", TimeOut);
				TimeOut++;
			} while ((!Connection_Accepter) && (TimeOut <= TIME_OUT_CONNECT));
		}
		Tentative_Connect_Agent++;
	} while ((!Connection_Accepter) && (Tentative_Connect_Agent <= TENTATIVE_CONNECT_AGENT));
#endif
	
	if (!Connection_Accepter) {
		Text = g_strdup_printf ("[FAILED] Connecting (%s)", Nom_Serveur_Agent);
		if (!AutoRestore)
			gtk_label_set_text(label_Localisation_Connecting, Text);
		refresh();
		MYFREE (Text);
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Impossible de se connecter à l agent");
		close (Socket_Agent);
		return -1;
	}
	
	debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Connecter a [%s] Socket :(%d)",Nom_Serveur_Agent,Socket_Agent);
	
	NbOctet = recvfrom (Socket_Agent, &Entete, sizeof (Entete), 0, NULL, 0);
	if (NbOctet==-1)
    	 debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "read  %s", strerror (errno));
	debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Récuperation de l'entete de l'agent : [%s](%d)",Entete, NbOctet);
	
	if ((strcmp (Entete, VERSION_AGENT) != 0)){
		Text = g_strdup_printf ("[FAILED] Version check (%s)", Entete);
		if (!AutoRestore)
			gtk_label_set_text(label_Localisation_Connecting, Text);
		refresh();
		MYFREE (Text);
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Agent incompatible");
		close (Socket_Agent);
		return -1;		
	}
	NbOctet = send (Socket_Agent, VERSION_AUTOSCAN, sizeof (VERSION_AUTOSCAN), 0);
	if (NbOctet < 0)
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "send  : %s", strerror (errno));
	

	Socket_Agent_Init = Socket_Agent;
	Connecter_Agent = TRUE;
	debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Connection opérationnel -- Connection Bloquante");
	return Socket_Agent;
}
