#include "mchat.h" /* fonctions reseau */ int init_reseaux(void) { sdw = init_socket(&sock_w , port , dest , WRITE); sdr = init_socket(&sock_r , port , dest , READ); len_r = sizeof(sock_r); len_w = sizeof(sock_w); imr.imr_multiaddr.s_addr = htonl(inet_addr(dest)); imr.imr_interface.s_addr = htonl(INADDR_ANY); /* pour avoir un retour du paquet envoye (couche3) pour une valeur=1 */ /* sinon pas de retour direct valeur=0*/ loop = 1 - loop; /* 0 = disable, 1 = enable */ setsockopt(sdr, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); /*pour joindre un groupe multicast*/ if (setsockopt(sdr, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &imr, sizeof(struct ip_mreq)) < 0) { perror("setsockopt - IP_ADD_MEMBERSHIP"); exit(1); } /* portee du multicast*/ setsockopt(sdw, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); return(sdr); } void sock_read(Widget widget,XtPointer client_data,XtPointer call_data) { char buf[1024]; /* taille maxi autorisee */ int cnt=-1; /* reception de datagrammes*/ while (cnt<=0) { cnt = recvfrom(sdr, buf, sizeof(buf), 0, (struct sockaddr *) &sock_r, &len_r); } /* traiter la partie utile */ traiter_message(buf,cnt); } void sock_write(char* buf,int n) { /*emission en mode multicast*/ strcat(buf,"\0"); n++; if (sendto(sdw, buf, n, 0, (struct sockaddr *) &sock_w, len_w)<0) { perror("Probleme avec sendto"); printf("%d,%s,\n",n,buf); exit(1); } } int init_socket(struct sockaddr_in * sock,int port,char * group,int sens) { int nsock; int one = 1; /* creation des socket */ if ((nsock = socket(PF_INET, SOCK_DGRAM, 0))< 0) { perror("Probleme de creation de socket"); exit(1); } /* initialisation a proprement parler*/ if (sens==WRITE) { memset(sock, 0, sizeof(*sock)); sock->sin_family = AF_INET; sock->sin_port = htons(port); sock->sin_addr.s_addr = htonl(inet_addr(group)); } else { memset(sock, 0, sizeof(*sock)); sock->sin_family = AF_INET; sock->sin_port = htons(port); sock->sin_addr.s_addr = htonl(inet_addr(group)); sock->sin_addr.s_addr = htonl(INADDR_ANY); if (setsockopt(nsock, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) < 0) { perror("setsockopt - REUSEADDR"); exit(1); } if (bind(nsock, (struct sockaddr *) sock, sizeof(*sock))<0) { if (errno == EADDRNOTAVAIL) { sock->sin_addr.s_addr = htonl(INADDR_ANY); if (bind(nsock, (struct sockaddr *) sock, sizeof(*sock)) < 0) { perror("bind"); fprintf(stderr, "errno = %d\n", errno); exit(2); } } } } return(nsock); } void quit_res(void) { /* pour quitter le groupe multicast*/ if(setsockopt(sdr, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &imr, sizeof(struct ip_mreq))<0) { perror("Probleme pour quitter multicast"); exit(1); } } extern char *optarg; extern int optind, opterr, optopt; void usage(char * progn) { fprintf(stderr, "Usage: %s [-vd] [-S \"session-name\"] [-M \"media-name\"] [-t ttl] dest/port\n", progn); exit(1); } void options(int argc, char ** argv) { int c; char *s; int awaiting_dest_port = 0; while ((c = getopt(argc, argv, "hdvt:S:M:")) != EOF) { switch(c) { case 'S': sess_name = optarg; awaiting_dest_port = 1; break; case 'M': media = optarg; awaiting_dest_port = 1; break; case 't': ttl = atoi(optarg); awaiting_dest_port = 1; break; case 'd': debug = 1; break; case 'h': default : usage(argv[0]); } } if (awaiting_dest_port) { if (optind == argc) usage(argv[0]); dest = argv[optind]; s = strchr(dest, '/'); if (*s) { *s = '\0'; port = atoi(s+1); } if (debug) printf("dest/port: %s/%d, ttl=%d\n", dest, port, ttl); } } /*********************************************************/ /* MAIN DU PROGRAMME : WIDGETS + GENERAL */ /*********************************************************/ void main(int argc, char *argv[]) { Widget toplevel,form, frame, frame2, frame3, title, manager, text, button, menubar,cascade,shell; XtAppContext app; Arg args[15]; register int i; /* La fenetre se decompose en quatre parties : - une barre de menu - une zone texte permettant de naviguer parmi les messages recus - une zone texte selectionnable permettant de choisir son destinataire - une zone texte editable afin de pouvoir taper le texte a envoyer */ toplevel = XtAppInitialize(&app, "Mcast", NULL, 0, &argc, argv, fallbackResources, NULL, 0); dest = GROUP; port = PORT; ttl = TTL; options(argc, argv); form = XmCreateForm(toplevel, "form", NULL, 0); /*******************************************************/ /* PREMIERE PARTIE : barre de menu */ /*******************************************************/ i=0; XtSetArg (args[i], XmNleftAttachment, XmATTACH_FORM); i++; XtSetArg (args[i], XmNrightAttachment, XmATTACH_FORM); i++; menubar = XmCreateMenuBar(form, "menubar", args, i); i=0; XtSetArg (args[i], XmNshadowThickness,0); i++; cascade = XmCreateCascadeButton(menubar, "Quit", args, i); XtAddCallback(cascade, XmNactivateCallback, quit, NULL); XtManageChild(cascade); i=0; XtSetArg (args[i], XmNshadowThickness,0); i++; cascade = XmCreateCascadeButton(menubar, " Echo ", args, i); XtAddCallback(cascade, XmNactivateCallback, echo_switch, NULL); XtManageChild(cascade); i=0; XtSetArg (args[i], XmNshadowThickness,0); i++; cascade = XmCreateCascadeButton(menubar, " Who ", args, i); XtAddCallback(cascade, XmNactivateCallback, refresh_callback, NULL); XtManageChild(cascade); i=0; XtSetArg (args[i], XmNshadowThickness,0); i++; cascade = XmCreateCascadeButton(menubar, "Help", args, i); i=0; XtSetArg (args[i],XmNmessageString, XmStringCreateLocalized("Functionnalities of MCHAT v2.0 - 1 - Echo allow people to receive or not their own messages - 2 - Who ask all participants to declare themselves - 3 - Receivers can be chosen through the right menu ") ); i++; shell = XmCreateTemplateDialog (menubar,"help", args,i); XtAddCallback(cascade, XmNactivateCallback, help_callback, shell); XtManageChild(cascade); XtManageChild(menubar); /*******************************************************/ /* DEUXIEME PARTIE : zone texte non editable */ /*******************************************************/ i = 0; XtSetArg (args[i], XmNmarginWidth, 4); i++; XtSetArg (args[i], XmNmarginHeight, 5); i++; XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++; XtSetArg(args[i], XmNtopWidget, menubar); i++; XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++; XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++; frame = XmCreateFrame (form, "frame", args, i); i = 0; XtSetArg (args[i], XmNchildType, XmFRAME_TITLE_CHILD); i++; XtSetArg (args[i], XmNchildVerticalAlignment, XmALIGNMENT_CENTER); i++; XtSetArg (args[i], XmNchildVerticalAlignment, XmALIGNMENT_CENTER); i++; title = XmCreateLabel (frame, "Received messages", args, i); XtManageChild (title); i = 0; XtSetArg (args[i], XmNchildType, XmFRAME_WORKAREA_CHILD); i++; XtSetArg (args[i], XmNfractionBase, 1); i++; XtSetArg (args[i], XmNverticalSpacing, 2); i++; XtSetArg (args[i], XmNhorizontalSpacing, 4); i++; manager = XmCreateForm(frame, "form", args, i); i = 0; XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM); i++; XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++; XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++; XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++; /* arguments specifiques hors position */ XtSetArg (args[i], XmNspacing, 1); i++; XtSetArg (args[i], XmNscrollingPolicy, XmAUTOMATIC); i++; XtSetArg (args[i], XmNscrollHorizontal, False); i++; XtSetArg (args[i], XmNeditMode, XmMULTI_LINE_EDIT); i++; XtSetArg (args[i], XmNrows, 4); i++; XtSetArg (args[i], XmNwordWrap, True); i++; XtSetArg (args[i], XmNeditable, False); i++; XtSetArg (args[i], XmNcursorPositionVisible, False); i++; message_list = XmCreateScrolledText (manager, "message", args, i); XtManageChild (message_list); XtManageChild (manager); XtManageChild (frame); /*******************************************************/ /* TROISIEME PARTIE : zone de texte selectionnable */ /*******************************************************/ i = 0; XtSetArg (args[i], XmNmarginWidth, 4); i++; XtSetArg (args[i], XmNmarginHeight, 5); i++; XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++; XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++; XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++; XtSetArg(args[i], XmNtopWidget, frame); i++; frame2 = XmCreateFrame (form, "frame", args, i); i = 0; XtSetArg (args[i], XmNchildType, XmFRAME_TITLE_CHILD); i++; XtSetArg (args[i], XmNchildVerticalAlignment, XmALIGNMENT_CENTER); i++; title = XmCreateLabel (frame2, "Connected users and targets", args, i); XtManageChild (title); i = 0; XtSetArg (args[i], XmNchildType, XmFRAME_WORKAREA_CHILD); i++; XtSetArg (args[i], XmNvisibleItemCount , 4); i++; users_list = XmCreateScrolledList (frame2, "users_list", args, i); XtManageChild (users_list); XtManageChild (frame2); /*******************************************************/ /* QUATRIEME PARTIE : texte editable + pushbutton */ /*******************************************************/ i = 0; XtSetArg (args[i], XmNmarginWidth, 4); i++; XtSetArg (args[i], XmNmarginHeight, 5); i++; XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++; XtSetArg(args[i], XmNtopWidget, frame2); i++; XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++; XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++; XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++; frame3 = XmCreateFrame (form, "frame", args,i); i = 0; XtSetArg (args[i], XmNchildType, XmFRAME_TITLE_CHILD); i++; XtSetArg (args[i], XmNchildVerticalAlignment, XmALIGNMENT_CENTER); i++; title = XmCreateLabel (frame3, "Send message", args, i); XtManageChild (title); i = 0; XtSetArg (args[i], XmNchildType, XmFRAME_WORKAREA_CHILD); i++; XtSetArg (args[i], XmNfractionBase, 100); i++; XtSetArg (args[i], XmNverticalSpacing, 4); i++; XtSetArg (args[i], XmNhorizontalSpacing, 5); i++; manager = XmCreateForm(frame3, "form", args, i); i = 0; XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++; XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++; XtSetArg (args[i], XmNspacing, 1); i++; XtSetArg (args[i], XmNscrollingPolicy, XmAUTOMATIC); i++; XtSetArg (args[i], XmNscrollHorizontal, False); i++; XtSetArg (args[i], XmNeditMode, XmMULTI_LINE_EDIT); i++; XtSetArg (args[i], XmNmaxLength, 255); i++; XtSetArg (args[i], XmNrows, 2); i++; XtSetArg (args[i], XmNcolumns, 80); i++; XtSetArg (args[i], XmNwordWrap, True); i++; text = XmCreateScrolledText (manager, "message", args, i); i = 0; XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++; XtSetArg(args[i], XmNbottomAttachment, XmATTACH_POSITION); i++; XtSetArg(args[i], XmNbottomPosition, 80); i++; XtSetArg(args[i], XmNmarginHeight, 6); i++; XtSetArg(args[i], XmNmarginWidth, 10); i++; button = XmCreatePushButton (manager, "Send", args, i); XtAddCallback (button, XmNactivateCallback,send_callback, text); XtVaSetValues (XtParent (text), XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, button, NULL); XtManageChild (text); XtManageChild (button); XtManageChild (manager); XtManageChild (frame3); XtManageChild(form); XtRealizeWidget(toplevel); /* initialisation des parametres du programme*/ init_declarations(); /* rajout d'un masque de reseau */ XtAppAddInput(app,init_reseaux(), (XtPointer) XtInputReadMask,(XtInputCallbackProc) sock_read, NULL); XtAppMainLoop(app); } /*************************************************************/ /* FONCTIONS ANNEXES */ /*************************************************************/ void init_declarations(void) { char host[256]; int i; /* creation de l'identificateur local */ if (cuserid(nickname)==NULL) perror("impossible de trouver le login\n"); gethostname(host, sizeof(host)); /* creation de myid */ strcpy(myid,nickname); strcat(myid,"@"); strcat(myid,host); /* remplir les premiers champs */ for (i=0;i 9500) strcpy(history_message,&history_message[500]); strncpy(tmp,msg,l); tmp[l]='\0'; strcat(tmp," : "); strcat(tmp,&msg[l]); strcat(tmp,"\n"); strcat(tmp,history_message); strcpy(history_message,tmp); XmTextSetString(message_list,history_message); } void rajouter_user(char * nom) { int i=0; int n=-1; while(n<0) { if (i > MAX_USER) { fprintf(stderr,"depassement capacite !!!"); exit(3); } if (users_list_used[i]==0) n=i; i++; } users_list_used[n]=1; strcpy(user_id[n],nom); XmListAddItem (users_list, XmStringCreateLocalized (nom) ,n+1); } void enlever_user(char * nom) { int i=0; int n=-1; while(n<0) { if (strcmp(user_id[i],nom)==0) n=i; i++; } users_list_used[n]=0; strcpy(user_id[n],""); XmListDeleteItem (users_list, XmStringCreateLocalized (nom)); } /***************************************************************/ /* CALLBACKS ASSOCIES AU PROGRAMME */ /***************************************************************/ /* callback pour donner le minimum d'aide */ void help_callback (Widget w, XtPointer client_data, XtPointer call_data) { Widget win = (Widget) client_data; XtManageChild(win); } /* callback pour le refresh des participants */ void refresh_callback (Widget w, XtPointer client_data, XtPointer call_data) { char buf[5]; register int i; XmListDeleteAllItems (users_list); for (i=0;i