Initial revision
[scilab.git] / scilab_doc / comm / comm.tex
1 % Copyright INRIA
2
3 \documentclass[11pt]{article}
4
5 \textheight=23cm \textwidth=16cm
6 \topmargin=-1cm
7 \oddsidemargin=0pt \evensidemargin=0pt \marginparwidth=2cm
8
9 \newcommand{\func}[1]{\texttt{#1}}
10 \newcommand{\T}[1]{\texttt{#1}}
11
12 \title{Communication Toolbox}
13 \author{Claude Gomez}
14 \date{Manual Version 1.0 for Scilab 2.4}
15
16 \begin{document}
17
18 \maketitle
19
20 \small\textbf{
21 This is a beta version of the Communication Toolbox. It lacks security
22 problems when using remote communications (see~\ref{remote}). A good
23 error trapping is also under development, so you can ``block'' Scilab
24 when doing mistakes in the names of the linked applications.
25 }
26
27 \bigskip
28
29 GeCI is an interactive communication manager created in order to
30 manage remote executions of programs and allow exchanges of messages
31 between those programs. It offers the possibility to exploit numerous
32 machines on a network, as a virtual computer, by creating a
33 distributed group of independent softwares.
34
35 It has been originally developed in the CalICo Project (LaBRI-
36 Universit\'e Bordeaux I, France) by Nadine Rouillon.
37
38 In Scilab, GeCI manages communications between Scilab itself and other
39 applications (included Scilab itself). In fact, the \T{scilab}
40 command is a shell script which at last executes the command:
41
42 \begin{verbatim}
43 <Scilab directory>/bin/geci -local <Scilab directory>/bin/scilex
44 \end{verbatim}
45
46 where \verb|<Scilab directory>| is the main directory of Scilab.
47 We will use  \verb|<Scilab directory>| to denote this directory in
48 this manual.
49 This means that Scilab is ready to communicate with others
50 applications. In particular, this is the way Metanet Windows are
51 executed in the Metanet toolbox.
52
53 In section~\ref{functions}, we explain how to use the Scilab functions of the
54 Communication Toolbox and in section~\ref{internal} we describe the
55 way to make an application able to communicate with Scilab.
56
57 \section{Functions of the Communication Toolbox}\label{functions}
58
59 There are six functions in the Communication Toolbox to make
60 communications. They are 
61 \func{CreateLink}, \func{DestroyLink}, \func{ExecAppli},
62 \func{GetMsg}, \func{SendMsg} and \func{WaitMsg}. They are described
63 in the on-line manual. We are only going here to describe how to use
64 them for exchanging messages between two Scilab programs. You will find
65 in section~\ref{examples} how to communicate between Scilab and other
66 programs.
67
68 After executing Scilab, you can execute another Scilab on the same
69 computer from the first one and create a link to it and from it by
70 issuing the commands:
71  
72 \begin{verbatim}
73 -->h=unix_g("hostname");
74 -->ExecAppli(SCI+"/bin/scilex",h,"Scilab2")
75 -->CreateLink("SELF","Scilab2")
76 -->CreateLink("Scilab2","SELF")
77 \end{verbatim}
78
79 Each application linked to GeCI has a name. Two special names are defined,
80 \T{"SELF"} always stands for the name of the Scilab program where you
81 are and \T{"XGeCI"} stands for the first Scilab program.
82
83 Now, another Scilab named \T{Scilab2} appears and you can send a
84 message to it from the first Scilab:
85
86 \begin{verbatim}
87 -->SendMsg("Hi!","How are you?");
88 \end{verbatim}
89
90 And in \T{Scilab2}, you can get it:
91
92 \begin{verbatim}
93 -->[type,msg,apply] = GetMsg()
94  apply  =
95  
96  XGeCI   
97  msg  =
98  
99  How are you?   
100  type  =
101  
102  Hi!   
103 \end{verbatim}
104
105 You do not have to tell to which application you want to send the
106 message: you send it to all applications linked to you.
107
108 You can also send a message from \T{Scilab2} to first Scilab:
109
110 \begin{verbatim}
111 -->SendMsg("Answer","Fine and you?");
112 \end{verbatim}
113
114 and you get it in Scilab:
115
116 \begin{verbatim}
117 -->[type,msg,apply] = GetMsg()
118  apply  =
119  
120  Scilab2   
121  msg  =
122  
123  Fine and you?   
124  type  =
125  
126  Answer   
127 \end{verbatim}
128
129 You can even open a new Scilab, named \T{Scilab3} for instance, link it
130 to Scilab and/or \T{Scilab2} and exchange messages between them after
131 having created links. Use the \func{DestroyLink} function to destroy a
132 link.
133
134 Note that there is no notion of client and server. The server is the
135 GeCI program and all the applications which communicate are at the
136 same level. That means that the \func{CreateLink}, \func{DestroyLink}
137 and \func{ExecAppli} functions can be used in any Scilab instance.
138
139 \section{Creating applications to communicate with Scilab}\label{internal}
140
141 To communicate with Scilab, an application must have been prepared
142 for, by including a communication library in it. 
143 The way to do this is described in this section.
144
145 Suppose you have a C or fortran program and you want to add in it the
146 functionalities to communicate using GeCI. For this you need to add
147 new C functions in the code. For instance, you can create a new C file
148 which you are going to link with your existing C or fortran
149 program. You also need to link the program with the following library:
150
151 \begin{verbatim}
152 <Scilab directory>/libs/libcomm.a
153 \end{verbatim}
154
155 At the beginning of the C code, you must include the following header
156 files:
157  
158 \begin{verbatim}
159 #include "<Scilab directory>/routines/libcomm/libCalCom.h"
160 #include "<Scilab directory>/routines/libcomm/libCom.h"
161 \end{verbatim}
162
163 Then you define the messages known by the application, usually:
164
165 \begin{verbatim}
166 static void QuitAppli();
167 static void EndAppli();
168 static void ParseMessage();
169 static void MsgError();
170
171 static actions_messages tb_messages[]={
172     {ID_GeCI,MSG_QUITTER_APPLI,NBP_QUITTER_APPLI,QuitAppli},
173     {ID_GeCI,MSG_FIN_APPLI,NBP_FIN_APPLI,EndAppli},
174     {NULL,MSG_DISTRIB_LISTE_ELMNT,NBP_DISTRIB_LISTE_ELMNT,ParseMessage},
175     {NULL,NULL,0,MsgError}};
176 \end{verbatim}
177
178 All these functions have one argument of type \T{message}.
179
180 \T{QuitAppli} is executed when THIS application terminates.
181
182 \T{EndAppli} is executed when an application executed by THIS
183 application terminates.
184
185 \T{MsgError} is executed when there is an error in a message.
186
187 \T{ParseMessage} is executed to get the received messages.
188 For instance, you can write \T{ParseMessage} the following way:
189
190 \begin{verbatim}
191 static char *TheAppli;
192 static char *TheType;
193 static char *TheMsg;    
194
195 static void ParseMessage(message)
196 Message message;
197 {
198   int lappli, ltype, lmsg;
199
200   lappli = strlen(message.tableau[0]);
201   if ((TheAppli = (char *)malloc((unsigned)sizeof(char)*(lappli + 1)))
202       == NULL) {
203     return;
204   }
205   strcpy(TheAppli,message.tableau[0]);
206
207   ltype = strlen(message.tableau[3]);
208   if ((TheType = (char *)malloc((unsigned)sizeof(char)*(ltype + 1)))
209       == NULL) {
210     return;
211   }
212   strcpy(TheType,message.tableau[3]);
213
214   lmsg = strlen(message.tableau[4]);
215   if ((TheMsg = (char *)malloc((unsigned)sizeof(char)*(lmsg + 1)))
216       == NULL) {
217     return;
218   }
219   strcpy(TheMsg,message.tableau[4]);
220 }
221 \end{verbatim}
222
223 and you get:
224
225 \begin{itemize}
226 \item in \T{TheAppli} the name of the application which has sent the message
227 \item in \T{TheType} the type of the message (an ASCII string)
228 \item in \T{TheMsg} the message (an ASCII string)
229 \end{itemize}
230
231 Then you must initialize the communications. 
232
233 For this, the main function of the 
234 application must understand the arguments \T{-pipes <pipe1> <pipe2>} which
235 are automatically given by GeCI when executing it by:
236
237 \begin{verbatim}
238 geci -local <my application>
239 \end{verbatim}
240
241 A simple way to do this is to use the \T{find} function:
242 \begin{verbatim}
243 static int find(s,n,t)
244 char *s;
245 int n;
246 char **t;
247 {
248   int i;
249   for (i=0; i<n; i++)
250     if (!strcmp(s,t[i])) return(i);
251   return(-1);
252 }
253
254 int main(argc, argv)
255 unsigned int argc;
256 char **argv;
257 {
258   int igeci;
259   int p1, p2;
260   igeci = find("-pipes",argc,argv);
261   if (igeci == -1) exit(1);
262
263   p1 = atoi(argv[igeci+1]); p2 = atoi(argv[igeci+2]);
264 \end{verbatim}
265
266 And you initialize the communications:
267
268 \begin{verbatim}
269   init_messages(tb_messages,p1,p2);
270 \end{verbatim}
271
272 Then it is possible to use the functions of GeCI. For this, you have
273 to send messages to GeCI.
274
275 \begin{itemize}
276 \item You can execute an application from your program:
277
278 \begin{verbatim} 
279   envoyer_message_parametres_var(ID_GeCI,
280                                  MSG_LANCER_APPLI,
281                                  <appli>,
282                                  <host>,
283                                  <path appli>,
284                                  INS_ID_PIPES,
285                                  NULL);
286 \end{verbatim}
287
288 where \T{<appli>} is the name you give to the application you execute,
289 \T{<host>}
290 is the name of the host where you want to execute the application and 
291 \T{<path appli>} is the path of the program of the application on the
292 host. If you want to execute an application locally on the same host,
293 you give the name of your host. You can also execute the application
294 on a remote host on Internet, see \ref{remote}.
295
296 Every application has a name. The name of your program has also a name
297 given automatically. When you have to use it (to link applications for
298 instance), you can get it by \T{identificateur\_appli()}.
299
300 \item To create a (directed) link from the application named \T{<appli1>} to
301 the application named \T{<appli2>}:
302
303 \begin{verbatim} 
304   envoyer_message_parametres_var(ID_GeCI,
305                                  MSG_CREER_LIAISON, 
306                                  <appli1>,
307                                  <appli2>,
308                                  NULL);
309 \end{verbatim}
310
311 Then you are able to send messages from \T{<appli1>} to \T{<appli2>}.
312
313 Note that the two applications must have been executed first by the
314 preceding message.
315
316 \item To destroy a link from \T{<appli1>} to \T{<appli2>}:
317
318 \begin{verbatim} 
319   envoyer_message_parametres_var(ID_GeCI,
320                                  MSG_DETRUIRE_LIAISON, 
321                                  <appli1>,
322                                  <appli2>,
323                                  NULL);
324 \end{verbatim}
325
326 \item To send a message to all linked applications:
327
328 \begin{verbatim} 
329   envoyer_message_parametres_var(ID_GeCI,
330                                  MSG_POSTER_LISTE_ELMNT,
331                                  <type>,
332                                  <msg>,
333                                  NULL);
334 \end{verbatim}
335
336 where \T{<type>} is a string corresponding to the type of the message
337 and \T{<msg>} is the string corresponding to the message.
338
339 Note that before being able to exchange messages, applications must
340 have been linked.
341
342 \item To get a message in an asynchronous way:
343
344 \begin{verbatim}
345   scanner_messages();
346 \end{verbatim}
347  
348 \item To wait for a message from \T{<appli>} in a synchronous way:
349 \begin{verbatim}
350
351   attendre_reponse(<appli>,
352                    MSG_DISTRIB_LISTE_ELMNT,
353                    NBP_DISTRIB_LISTE_ELMNT);
354 \end{verbatim}
355 \end{itemize}
356
357 \subsection{Communication between remote hosts}\label{remote}
358
359 \emph{\textbf{
360 CAUTION: With this beta version of the Communication Toolbox, nothing
361 has been done for adressing possibly security holes and problems when
362 using the \T{gecid} daemon and remote \T{geci} programs. So use them
363 very carefully.
364 }}
365
366 \medskip
367
368 With GeCI you can also have communications between programs on remote
369 hosts.
370
371 Suppose you are on host \T{h1}, have a local application \T{a1} and
372 you want to execute an application \T{a2} on host \T{h2} and open a
373 communication between \T{a1} and \T{a2}.
374
375 First, you must have a \T{geci} program on both hosts. Second you must
376 have a daemon, called \T{gecid}, on the remote host. The C source code
377 of this daemon is given in the \T{geci} directory of Scilab
378 distribution.
379
380 You have to give the good path of \T{geci} program in the source code
381 of program \T{gecid} in variable \T{GECI}.
382
383 Then, you first start the daemon \T{gecid} on host \T{h2}. 
384 After, you execute application \T{a1}, Scilab for instance, on host
385 \T{h1} and use GeCI functions to execute application \T{a2} on host \T{h2}:
386 you have to give the complete Internet name of host \T{h2} in these
387 functions.
388
389 If application \T{a2} is another Scilab, do not forget to give the
390 good \T{-display} argument to the \T{scilex} command.
391
392 In fact the \T{gecid} daemon will wait for a socket connection on port
393 2001 and then start \T{geci} on host \T{h2}.
394
395 \subsection{Examples}\label{examples}
396
397 You will find below two complete C programs as examples.
398
399 The first program opens Scilab,
400 wait for messages and print them. We call the file of this program 
401 \T{alpha.c}
402 and we suppose that the main directory of Scilab, 
403 \verb|<Scilab directory>| is \T{/usr/local/lib/scilab-2.4}.
404
405 Compile this program with:
406  
407 \begin{verbatim}
408 cc -o alpha alpha.c /usr/local/lib/scilab-2.4/libs/libcomm.a
409 \end{verbatim}
410
411 and execute it with (if shell is csh):
412
413 \begin{verbatim}
414 setenv SCI /usr/local/lib/scilab-2.4
415 /usr/local/lib/scilab-2.4/bin/geci -local alpha
416 \end{verbatim} 
417
418 Then a new Scilab is executed and you can execute in it commands of the form
419 \T{SendMsg("Hi","How are you?")}. On the console you must see:
420 \begin{verbatim}
421 Message received from Scilab
422     type: Hi
423     message: How are you?
424 \end{verbatim}
425
426 "alpha.c" is given below and in the directory \T{docs/comm} of Scilab
427 distribution.
428
429 \begin{verbatim}
430 /***************************************************************************/
431 #include <stdio.h>
432 #include <string.h>
433
434 /* Communications headers */
435 #include "/usr/local/lib/scilab-2.4/routines/libcomm/libCalCom.h"
436 #include "/usr/local/lib/scilab-2.4/routines/libcomm/libCom.h"
437
438 static void QuitAppli();  
439 static void EndAppli();
440 static void ParseMessage();
441 static void MsgError();
442
443 /* Known messages */
444 static actions_messages tb_messages[]={
445   {ID_GeCI,MSG_QUITTER_APPLI,NBP_QUITTER_APPLI,QuitAppli},
446   {ID_GeCI,MSG_FIN_APPLI,NBP_FIN_APPLI,EndAppli},
447   {NULL,MSG_DISTRIB_LISTE_ELMNT,NBP_DISTRIB_LISTE_ELMNT,ParseMessage},
448   {NULL,NULL,0,MsgError}};
449
450 static void QuitAppli(message)
451      Message message;
452 {  
453   printf("Quit application\n");
454   exit(0);
455 }
456
457 static void EndAppli(message) 
458      Message message;
459 {
460   printf("End application\n");
461 }
462
463 static void MsgError(message)
464      Message message;
465 {
466   printf("Bad received message\n");
467 }
468
469 static char *TheAppli;
470 static char *TheType;
471 static char *TheMsg;
472
473 /* ParseMessage is executed when a message is received */
474 static void ParseMessage(message)
475      Message message;
476 {
477   int lappli, ltype, lmsg;
478
479   lappli = strlen(message.tableau[0]);
480   if ((TheAppli = (char *)malloc((unsigned)sizeof(char)*(lappli + 1)))
481       == NULL) {
482     return;
483   }
484   strcpy(TheAppli,message.tableau[0]);
485
486   ltype = strlen(message.tableau[3]);
487   if ((TheType = (char *)malloc((unsigned)sizeof(char)*(ltype + 1)))
488       == NULL) {
489     return;
490   }
491   strcpy(TheType,message.tableau[3]);
492
493   lmsg = strlen(message.tableau[4]);
494   if ((TheMsg = (char *)malloc((unsigned)sizeof(char)*(lmsg + 1)))
495       == NULL) {
496     return;
497   }
498   strcpy(TheMsg,message.tableau[4]);
499 }
500
501 static int find(s,n,t)
502      char *s;
503      int n;
504      char **t;
505 {
506   int i;
507   for (i=0; i<n; i++)
508     if (!strcmp(s,t[i])) return(i);
509   return(-1);
510 }
511
512 int main(argc, argv)
513      unsigned int argc;
514      char **argv;
515 {
516   int igeci;
517   int p1, p2;
518   char myhost[128];
519   /* Scilab application to execute */
520   char *scilex = "/usr/local/lib/scilab-2.4/bin/scilex";
521
522   igeci = find("-pipes",argc,argv);
523   if (igeci == -1) exit(1);
524
525   p1 = atoi(argv[igeci+1]); p2 = atoi(argv[igeci+2]);
526
527   /* Intialization of communications */
528   init_messages(tb_messages,p1,p2);
529
530   /* Get the name of my computer */
531   gethostname(myhost,128);
532
533   /* Execute Scilab with name "Scilab" on my local host */
534   envoyer_message_parametres_var(ID_GeCI,
535                                  MSG_LANCER_APPLI,
536                                  "Scilab",
537                                  myhost,
538                                  scilex,
539                                  INS_ID_PIPES,
540                                  NULL);
541
542   /* Link THIS application with "Scilab" */
543   envoyer_message_parametres_var(ID_GeCI,
544                                  MSG_CREER_LIAISON, 
545                                  identificateur_appli(),
546                                  "Scilab",NULL);
547   
548   /* Link "Scilab" with THIS application  */
549   envoyer_message_parametres_var(ID_GeCI,
550                                  MSG_CREER_LIAISON, 
551                                  "Scilab",
552                                  identificateur_appli(),NULL);
553
554   /* Loop waiting for messages */
555   while (1) {
556     scanner_messages();
557     if (TheType != NULL) {
558       printf("Message received from %s\n",TheAppli);
559       printf("    type: %s\n",TheType);
560       printf("    message: %s\n",TheMsg);
561       TheAppli = NULL; TheType = NULL; TheMsg = NULL;
562     }
563   }
564 }
565 /***************************************************************************/
566 \end{verbatim} 
567
568 \bigskip
569  
570 The second program has everything to communicate with another
571 application linked to GeCI, Scilab for instance.
572 It waits for messages and print them. We call the file of this program 
573 \T{beta.c}
574 and we suppose that the main directory of Scilab, 
575 \verb|<Scilab directory>| is \T{/usr/local/lib/scilab-2.4}.
576
577 Compile this program with:
578  
579 \begin{verbatim}
580 cc -o beta beta.c /usr/local/lib/scilab-2.4/libs/libcomm.a
581 \end{verbatim}
582
583 Then, being in the directory where \T{beta} lies, execute Scilab and
584 issue the following Scilab command:
585 \begin{verbatim}
586 // get host name of my computer
587 h=unix_g("hostname")
588 // execute program beta from Scilab and give it "Beta" as a name
589 ExecAppli("beta",h,"Beta")
590 // create a link from Scilab to 
591 CreateLink("SELF","Beta")
592 // send a message to "Beta"
593 SendMsg("Hi","How are you?")
594 \end{verbatim}
595
596 On the console you must seen (written by \T{beta}):
597 \begin{verbatim}
598 Message received from Scilab
599     type: Hi
600     message: How are you?
601 \end{verbatim}
602
603 "beta.c" is given below and in the directory \T{docs/comm} of Scilab
604 distribution.
605
606 \begin{verbatim}
607 /***************************************************************************/
608 #include <stdio.h>
609 #include <string.h>
610
611 /* Communications headers */
612 #include "/usr/local/lib/scilab-2.4/routines/libcomm/libCalCom.h"
613 #include "/usr/local/lib/scilab-2.4/routines/libcomm/libCom.h"
614
615 static void QuitAppli();  
616 static void EndAppli();
617 static void ParseMessage();
618 static void MsgError();
619
620 /* Known messages */
621 static actions_messages tb_messages[]={
622   {ID_GeCI,MSG_QUITTER_APPLI,NBP_QUITTER_APPLI,QuitAppli},
623   {ID_GeCI,MSG_FIN_APPLI,NBP_FIN_APPLI,EndAppli},
624   {NULL,MSG_DISTRIB_LISTE_ELMNT,NBP_DISTRIB_LISTE_ELMNT,ParseMessage},
625   {NULL,NULL,0,MsgError}};
626
627 static void QuitAppli(message)
628      Message message;
629 {  
630   printf("Quit application\n");
631   exit(0);
632 }
633
634 static void EndAppli(message) 
635      Message message;
636 {
637   printf("End application\n");
638 }
639
640 static void MsgError(message)
641      Message message;
642 {
643     printf("Bad received message\n");
644 }
645
646 static char *TheAppli;
647 static char *TheType;
648 static char *TheMsg;
649
650 /* ParseMessage is executed when a message is received */
651 static void ParseMessage(message)
652      Message message;
653 {
654   int lappli, ltype, lmsg;
655
656   lappli = strlen(message.tableau[0]);
657   if ((TheAppli = (char *)malloc((unsigned)sizeof(char)*(lappli + 1)))
658       == NULL) {
659     return;
660   }
661   strcpy(TheAppli,message.tableau[0]);
662
663   ltype = strlen(message.tableau[3]);
664   if ((TheType = (char *)malloc((unsigned)sizeof(char)*(ltype + 1)))
665       == NULL) {
666     return;
667   }
668   strcpy(TheType,message.tableau[3]);
669
670   lmsg = strlen(message.tableau[4]);
671   if ((TheMsg = (char *)malloc((unsigned)sizeof(char)*(lmsg + 1)))
672       == NULL) {
673     return;
674   }
675   strcpy(TheMsg,message.tableau[4]);
676 }
677
678 static int find(s,n,t)
679      char *s;
680      int n;
681      char **t;
682 {
683   int i;
684   for (i=0; i<n; i++)
685     if (!strcmp(s,t[i])) return(i);
686   return(-1);
687 }
688
689 int main(argc, argv)
690      unsigned int argc;
691      char **argv;
692 {
693   int igeci;
694   int p1, p2;
695
696   igeci = find("-pipes",argc,argv);
697   if (igeci == -1) exit(1);
698
699   p1 = atoi(argv[igeci+1]); p2 = atoi(argv[igeci+2]);
700
701   /* Intialization of communications */
702   init_messages(tb_messages,p1,p2);
703
704   /* Loop waiting for messages */
705   while (1) {
706     scanner_messages();
707     if (TheType != NULL) {
708       printf("Message received from %s\n",TheAppli);
709       printf("    type: %s\n",TheType);
710       printf("    message: %s\n",TheMsg);
711       TheAppli = NULL; TheType = NULL; TheMsg = NULL;
712     }
713   }
714 }
715 /***************************************************************************/
716 \end{verbatim}
717 \newpage
718 \tableofcontents
719
720 \end{document}