/*
 * ping6xlite
 *
 * auteurs	TBXteam
 * date		Decembre 2008
 *
 * commande de compilation : gcc ping6xlite.c -o ping6xlite -Wall -lxcast -lxcast_p -lxcast_pic
 *
 */

/* on inclut les librairies a tester : libxcast et libxcast_priv */
#include "libxcast.h"
#include "libxcast_priv.h"

/* fichiers necessaires a l'utilisation des adresses */
#include <netinet/in.h>
#include <netinet6/in6.h>

/* fichiers a inclure pour les sockets */
#include <net/if.h>

/* fichiers de librairie standard */
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>

/* nombre maximal de membres par groupe */
#define MAXMBRS 4

/* longueur maximale du paquet */
#define MAXPACKETLENGTH 32

/* port par defaut */
#define DEFAULT_PORT 2048

/* hop limit max desire */
#define HOP_LIMIT 32

int main(int argc, char** argv)
{
	int i;
	int nb_membre = argc - 1;

	/* verification de la coherence des parametres */
	if(argc < 2) {
		printf("Precisez au moins une adresse en parametre\n");
		exit(1);
	}

	struct addrinfo* adress[nb_membre];
	for(i=0 ; i<nb_membre ; i++)
		adress[i] = NULL;

	/* recuperation des infos des adresses */
	for(i=1 ; i<nb_membre+1 ; i++) {
		if(getaddrinfo(argv[i], NULL, NULL, &adress[i-1]) != 0) {
			printf("Adresse invalide ou erreur dans getaddrinfo\n");
			exit(1);
		}
	}

	/* =========== GESTION DU GROUPE =========== */

	/* creation du groupe et recuperation de son id */
	int gid = XcastCreateGroup(0, NULL, (unsigned short) MAXMBRS);	// pas de flags

	if(gid == XCAST_FAILURE) {	// on verifie si tout s'est bien passe, sinon on quitte
		printf("Erreur lors de la creation du groupe\n");
		exit(1);
	}

	/* =========== GESTION DU MEMBRE =========== */

	struct xcast_member* tab_membre[nb_membre];
	for(i=0 ; i<nb_membre ; i++)
		tab_membre[i] = NULL;

	/* pour chaque membre */
	for(i = 0 ; i < nb_membre ; i++) {
		((struct sockaddr_in6*)adress[i]->ai_addr)->sin6_port = DEFAULT_PORT;	// on associe un port

		tab_membre[i] = malloc(sizeof(struct xcast_member));	// on cree effectivement le membre

		tab_membre[i]->xm_dest = adress[i]->ai_addr;	// on lui associe l'adresse recuperee auparavant

		tab_membre[i]->xm_dscp = 0;	// remplissage de securite
	}

	/* on ajoute les membre dans le groupe */
	for(i=0 ; i<nb_membre ; i++) {
		if(XcastAddMember(gid, tab_membre[i]) == XCAST_FAILURE) {	// on verifie si tout s'est bien passe, sinon on quitte
			printf("Erreur lors de l'ajout du membre %d au groupe %d\n", i+1, gid);
			exit(1);
		}
	}

	/* verification de la creation automatique de nouveaux groupes quand  MAXMBRS est depasse */
	//struct xcast_grpentry* entry = XcastGetGroupEntry(gid);
	//printf("last de la grpentry : %d\n", entry->last);


	/* =========== ENVOI DU PAQUET =========== */

	int hlim = HOP_LIMIT;	// hop limit, arbitraire ici

	/* on definit le hop limit pour le groupe */
	if(XcastSetSockOpt(gid, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hlim, sizeof(int)) == XCAST_FAILURE) {
		printf("Erreur de definition du hop-limit\n");
		exit(1);
	}

	/* donnee a envoyer (de type char*) */
	char donnee[MAXPACKETLENGTH] = {"abcdefghijklmnopqrstuvwxyz"};

	/* envoi de la donnee */
	XcastSend(gid, (char*)donnee, MAXPACKETLENGTH);

	/* =========== LIBERATION MEMOIRE =========== */

	/* on supprime les membres du groupe */
	for(i=0 ; i<nb_membre ; i++)
		XcastDeleteMember(gid, tab_membre[i]);


	XcastDeleteGroup(gid);	// on efface le groupe

	/* liberation de la memoire des differentes structures */
	for(i=0 ; i<nb_membre ; i++) {
		free(adress[i]);
		free(tab_membre[i]);
	}

	printf("Success : data sent to group %d\n", gid);

	return 0;
}
