FreeWRL / FreeX3D 4.3.0
EAIEventsIn.c
1/*
2
3
4Handle incoming EAI (and java class) events with panache.
5
6*/
7
8/****************************************************************************
9 This file is part of the FreeWRL/FreeX3D Distribution.
10
11 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12
13 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25****************************************************************************/
26
27
28/************************************************************************/
29/* */
30/* Design notes: */
31/* FreeWRL is a server, the Java (or whatever) program is a client */
32/* */
33/* Commands come in, and get answered to, except for sendEvents; */
34/* for these there is no response (makes system faster) */
35/* */
36/* Nodes that are registered for listening to, send async */
37/* messages. */
38/* */
39/* very simple example: */
40/* move a transform; Java code: */
41/* */
42/* EventInMFNode addChildren; */
43/* EventInSFVec3f newpos; */
44/* try { root = browser.getNode("ROOT"); } */
45/* catch (InvalidNodeException e) { ... } */
46/* */
47/* newpos=(EventInSFVec3f)root.getEventIn("translation"); */
48/* val[0] = 1.0; val[1] = 1.0; val[2] = 1.0; */
49/* newpos.setValue(val); */
50/* */
51/* Three EAI commands sent: */
52/* 1) GetNode ROOT */
53/* returns a node identifier */
54/* 2) GetType (nodeID) translation */
55/* returns posn in memory, length, */
56/* and data type */
57/* */
58/* 3) SendEvent posn-in-memory, len, data */
59/* returns nothing - assumed to work. */
60/* */
61/************************************************************************/
62
63#include <config.h>
64#include <system.h>
65#include <display.h>
66#include <internal.h>
67
68#include <libFreeWRL.h>
69
70#include "../vrml_parser/Structs.h"
71#include "../main/headers.h"
72#include "../vrml_parser/CParseGeneral.h"
73#include "../vrml_parser/CParseLexer.h"
74#include "../vrml_parser/CParseParser.h"
75#include "../vrml_parser/CParse.h"
76#include "../world_script/JScript.h"
77#include "../world_script/CScripts.h"
78#include "../world_script/fieldGet.h"
79
80#include "../input/EAIHeaders.h"
81#include "../world_script/fieldSet.h"
82#include "../scenegraph/Viewer.h"
83#include "../opengl/OpenGL_Utils.h"
84#include "../scenegraph/RenderFuncs.h"
85#include "../opengl/OpenGL_Utils.h"
86#include "../opengl/Textures.h"
87#include "../x3d_parser/X3DParser.h"
88#include "../vrml_parser/CRoutes.h"
89
90#include "EAIHelpers.h"
91#include "EAIHeaders.h"
92
93#include <ctype.h> /* FIXME: config armor */
94
95#define EAI_BUFFER_CUR tg->EAICore.EAIbuffer[bufPtr]
96
97/* used for loadURL */
98//struct X3D_Anchor EAI_AnchorNode;
99//int waiting_for_anchor = FALSE;
100
101static void makeFIELDDEFret(int, int);
102static void handleRoute (char command, char *bufptr, int repno);
103static void handleGETNODE (char *bufptr, int repno);
104static void handleGETNODEPARENTS (char *bufptr, int repno);
105static void handleGETROUTES (char *bufptr, int repno);
106static void handleGETEAINODETYPE (char *bufptr, int repno);
107extern void dump_scene (FILE *fp, int level, struct X3D_Node* node); // in GeneratedCode.c
108
109
110/******************************************************************************
111*
112* EAI_core_commands should only be called from
113* fwl_EAI_handleBuffer(..) or
114*
115* there can be many commands waiting, so we loop through commands, and return
116* a status of EACH command
117*
118* a Command starts off with a sequential number, a space, then a letter indicating
119* the command, then the parameters of the command.
120*
121* the command names are #defined at the start of this file.
122*
123* some commands have sub commands (eg, get a value) to indicate data types,
124* (eg, EAI_SFFLOAT); these sub types are indicated with a lower case letter; again,
125* look to the top of this file for the #defines
126*
127*********************************************************************************/
128
129typedef struct pEAIEventsIn{
130int oldCount; //=0;
131int waiting_for_anchor; // = FALSE;
132struct X3D_Anchor EAI_AnchorNode;
134void *EAIEventsIn_constructor()
135{
136 void *v = MALLOC(void *,sizeof(struct pEAIEventsIn));
137 memset(v,0,sizeof(struct pEAIEventsIn));
138 return v;
139}
140void EAIEventsIn_init(struct tEAIEventsIn* t)
141{
142 //public
143 //struct X3D_Anchor EAI_AnchorNode; //null ok?
144
145 //private
146 t->prv = EAIEventsIn_constructor();
147 {
148 ppEAIEventsIn p = (ppEAIEventsIn)t->prv;
149 p->waiting_for_anchor = FALSE;
150 p->oldCount=0;
151 }
152}
153
154/*
155 * This code used to sit in the socket server, but
156 * the EAI buffer is no longer the same as the socket's buffer
157 * The EAI buffer may still need sharing and locking...
158 * Will leave that decision to the experts!!
159 */
160typedef struct pEAICore{
161 pthread_mutex_t eaibufferlock;// = PTHREAD_MUTEX_INITIALIZER;
162}* ppEAICore;
163
164void *EAICore_constructor()
165{
166 void *v = MALLOC(void *,sizeof(struct pEAICore));
167 memset(v,0,sizeof(struct pEAICore));
168 return v;
169}
170void EAICore_init(struct tEAICore* t){
171 //private
172 t->prv = EAICore_constructor();
173 {
174 ppEAICore p = (ppEAICore)t->prv;
175 pthread_mutex_init(&(p->eaibufferlock), NULL);
176 }
177 //public
178 t->EAIbufsize = EAIREADSIZE ;
179}
180
181struct X3D_Anchor* get_EAIEventsIn_AnchorNode()
182{
183 ppEAIEventsIn p = (ppEAIEventsIn)gglobal()->EAIEventsIn.prv;
184 return (struct X3D_Anchor*)&p->EAI_AnchorNode;
185}
186
187#if !defined(EXCLUDE_EAI)
188int fwl_EAI_allDone() {
189 int eaiverbose;
190 int bufPtr;
191 int stillToDo;
192 ttglobal tg = gglobal();
193 bufPtr = tg->EAICore.EAIbufpos;
194 stillToDo = (int)strlen((&EAI_BUFFER_CUR));
195 eaiverbose = tg->EAI_C_CommonFunctions.eaiverbose;
196 if (eaiverbose && stillToDo > 0) {
197 printf ("EAI_allDone still to do: strlen %d str :%s:\n",stillToDo, (&EAI_BUFFER_CUR));
198 }
199 return stillToDo;
200}
201
202char * fwl_EAI_handleRest() {
203 int eaiverbose;
204 int bufPtr;
205 int stillToDo;
206 struct tEAIHelpers *th;
207 ttglobal tg = gglobal();
208 bufPtr = tg->EAICore.EAIbufpos;
209 stillToDo = (int)strlen((&EAI_BUFFER_CUR));
210 eaiverbose = tg->EAI_C_CommonFunctions.eaiverbose;
211
212 if(NULL == tg->EAICore.EAIbuffer) {
213 printf("fwl_EAI_handleRest() did not have a buffer, WTF!!") ;
214 return NULL ;
215 }
216 if(stillToDo > 0) {
217 if(eaiverbose) {
218 printf("%s:%d fwl_EAI_handleRest: Buffer at %p , bufPtr=%d , still to do=%d str :%s:\n",\
219 __FILE__,__LINE__,tg->EAICore.EAIbuffer,bufPtr,(int)strlen((&EAI_BUFFER_CUR)), (&EAI_BUFFER_CUR));
220 }
221
222 EAI_core_commands() ;
223
224 th = &tg->EAIHelpers;
225 return th->outBuffer ;
226 } else {
227 return "";
228 }
229}
230
231char * EAI_handleBuffer(char *fromFront, bool useSockets) {
232 /* memcp from fromFront to &EAI_BUFFER_CUR */
233 int eaiverbose;
234 int len = (int)strlen(fromFront) ;
235 ttglobal tg = gglobal();
236 struct tEAIHelpers *th;
237 eaiverbose = tg->EAI_C_CommonFunctions.eaiverbose;
238
239 //we do not use sockets for data transfer and so we can ignore the 8192 packet size limit
240 //sent command is larger than bufsize
241 if(!useSockets)
242 {
243 //for memory economy we check if at some time we allocated a buffer bigger than READSIZE and we do not need it anymore
244 if(tg->EAICore.EAIbufsize > EAIREADSIZE && len < EAIREADSIZE)
245 {
246 if(eaiverbose) {
247 printf("EAI_handleBuffer() does not need that much space, so we clear at %p\n",tg->EAICore.EAIbuffer) ;
248 }
249
250 //cleaning the existing buffer the standard workflow will take care of recreating it
251 if(NULL != tg->EAICore.EAIbuffer)
252 {
253 FREE(tg->EAICore.EAIbuffer);
254 tg->EAICore.EAIbuffer = NULL;
255 }
256
257 //reset the buffer dimension request to default
258 tg->EAICore.EAIbufsize = EAIREADSIZE;
259 }
260 else if(len >= tg->EAICore.EAIbufsize) //if not, we check if we DO need a buffer bigger than READSIZE
261 {
262 if(eaiverbose) {
263 printf("EAI_handleBuffer() needs a larger buffer, so we clear one at %p\n",tg->EAICore.EAIbuffer) ;
264 }
265 //cleaning the existing buffer the standard workflow will take care of recreating it
266 if(NULL != tg->EAICore.EAIbuffer)
267 {
268 FREE(tg->EAICore.EAIbuffer);
269 tg->EAICore.EAIbuffer = NULL;
270 }
271
272 //set the buffer dimension request to len + space for the null terminator
273 tg->EAICore.EAIbufsize = len+1;
274 }
275 }
276
277
278 if(NULL == tg->EAICore.EAIbuffer) {
279 tg->EAICore.EAIbuffer = MALLOC(char *, tg->EAICore.EAIbufsize * sizeof (char));
280 if(eaiverbose) {
281 printf("fwl_EAI_handleBuffer() did not have a buffer, so create one at %p\n",tg->EAICore.EAIbuffer) ;
282 }
283 }
284 if(eaiverbose) {
285 printf("%s:%d fwl_EAI_handleBuffer: Buffer at %p is %d chars,",__FILE__,__LINE__,fromFront,len);
286 printf("Copy to buffer at %p\n", tg->EAICore.EAIbuffer);
287 }
288
289
290 if(!useSockets || len <= EAIREADSIZE) { //go for standard command processing if we are not using sockets or buffer dimension is lesser than packet limit
291 //JAS printf ("EAI_handleBuffer, %d\n",__LINE__);
292
293 tg->EAICore.EAIbuffer[len] = '\0';
294 memcpy(tg->EAICore.EAIbuffer, fromFront, len);
295
296 //int EAIbufcount; /* pointer into buffer*/
297 //int EAIbufpos;
298 tg->EAICore.EAIbufpos = 0;
299 tg->EAICore.EAIbufcount = 0;
300
301 EAI_core_commands() ;
302
303 th = &tg->EAIHelpers;
304 return th->outBuffer ;
305 } else { //or stop socket reading if buffer dimension is greater than the packet limit
306 //JAS printf ("EAI_handleBuffer, %d\n",__LINE__);
307 fwlio_RxTx_control(CHANNEL_EAI,RxTx_STOP) ;
308 return "";
309 }
310}
311
312
313char * fwl_EAI_handleBufferNoSKT(char *fromFront)
314{
315 return EAI_handleBuffer(fromFront, false);
316}
317
318char * fwl_EAI_handleBuffer(char *fromFront) {
319 return EAI_handleBuffer(fromFront, true);
320
322 //int eaiverbose;
323 //int len = (int)strlen(fromFront) ;
324 //ttglobal tg = gglobal();
325 //struct tEAIHelpers *th;
326 //eaiverbose = tg->EAI_C_CommonFunctions.eaiverbose;
327
328 //if(NULL == tg->EAICore.EAIbuffer) {
329 // tg->EAICore.EAIbuffer = MALLOC(char *, tg->EAICore.EAIbufsize * sizeof (char));
330 // if(eaiverbose) {
331 // printf("fwl_EAI_handleBuffer() did not have a buffer, so create one at %p\n",tg->EAICore.EAIbuffer) ;
332 // }
333 //}
334 //if(eaiverbose) {
335 // printf("%s:%d fwl_EAI_handleBuffer: Buffer at %p is %d chars,",__FILE__,__LINE__,fromFront,len);
336 // printf("Copy to buffer at %p\n", tg->EAICore.EAIbuffer);
337 //}
338
339 //if(len <= EAIREADSIZE) {
340 // tg->EAICore.EAIbuffer[len] = '\0';
341 // memcpy(tg->EAICore.EAIbuffer, fromFront, len);
342
343 // //int EAIbufcount; /* pointer into buffer*/
344 // //int EAIbufpos;
345 // tg->EAICore.EAIbufpos = 0;
346 // tg->EAICore.EAIbufcount = 0;
347
348 // EAI_core_commands() ;
349
350 // th = &tg->EAIHelpers;
351 // return th->outBuffer ;
352 //} else {
353 // fwlio_RxTx_control(CHANNEL_EAI,RxTx_STOP) ;
354 // return "";
355 //}
356}
357
358void EAI_core_commands () {
359 /* char buf[EAIREADSIZE];*/
360 char ctmp[EAIREADSIZE]; /* temporary character buffer*/
361 char dtmp[EAIREADSIZE]; /* temporary character buffer*/
362 struct X3D_Group *retGroup;
363
364 int count;
365 char command;
366 int bufPtr; /* where we are in the EAI input buffer */
367
368 int ra,rb,rd; /* temps*/
369 int rc;
370 int tmp_a, tmp_b, tmp_c;
371
372 int scripttype;
373 char *EOT; /* ptr to End of Text marker*/
374 int retint; /* used for getting retval for sscanf */
375
376 struct X3D_Node *boxptr;
377 int ctype;
378 int xxx;
379
380 char *dumpname ;
381 int dumpfsize ;
382 int dumpInt ;
383 FILE *dumpfd ;
384
385 int eaiverbose;
387 //ppEAICore ps;
388 struct tEAIHelpers *th;
389 ttglobal tg;
390
391 UNUSED(retint); // for compiler warnings
392
393 tg = gglobal();
394 p = (ppEAIEventsIn)tg->EAIEventsIn.prv;
395 eaiverbose = tg->EAI_C_CommonFunctions.eaiverbose;
396 th = &tg->EAIHelpers;
397 //ps = tg->EAICore.prv;
398
399 /* initialization */
400 bufPtr = tg->EAICore.EAIbufpos;
401
402 /* output buffer - start off with it this size */
403 th->outBufferLen = EAIREADSIZE;
404 th->outBuffer = MALLOC(char *, th->outBufferLen);
405 th->outBuffer[0] = 0;
406
407 if (EAI_BUFFER_CUR> 0) {
408 if (eaiverbose) {
409 printf ("EAI_core_commands: strlen %d str :%s:\n",(int)strlen((&EAI_BUFFER_CUR)), (&EAI_BUFFER_CUR));
410 }
411
412 /* step 1, get the command sequence number */
413 if (sscanf ((&EAI_BUFFER_CUR),"%d",&count) != 1) {
414 printf ("EAI_core_commands, expected a sequence number on command :%s:\n",(&EAI_BUFFER_CUR));
415 count = 0;
416 }
417 if (eaiverbose) {
418 printf ("EAI - seq number %d\n",count);
419 }
420
421 if (count != (p->oldCount+1)) {
422 printf ("COUNT MISMATCH, expected %d got %d\n",p->oldCount+1,count);
423 }
424 p->oldCount = count;
425
426
427 /* step 2, skip past the sequence number */
428 while (isdigit(EAI_BUFFER_CUR)) bufPtr++;
429 /* if (eaiverbose) {
430 printf("past sequence number, string:%s\n",(&EAI_BUFFER_CUR));
431 } */
432
433 while (EAI_BUFFER_CUR == ' ') bufPtr++;
434 /* if (eaiverbose) {
435 printf ("past the space, string:%s\n",(&EAI_BUFFER_CUR));
436 } */
437
438 /* step 3, get the command */
439
440 command = EAI_BUFFER_CUR;
441 if (eaiverbose)
442 printf ("EAI command %s (%c) strlen %d\n",eaiPrintCommand(command), command,(int)strlen(&EAI_BUFFER_CUR));
443
444 bufPtr++;
445
446 /* return is something like: $hand->print("RE\n$reqid\n1\n$id\n");*/
447 if (eaiverbose) {
448 printf ("\n... %d ",count);
449 }
450
451 switch (command) {
452 case DUMPSCENE: {
453 int throwAway;
454 int sendNameNotFile = 1 ;
455
456 UNUSED(throwAway); // for compiler warnings
457
458 dumpname = TEMPNAM(gglobal()->Mainloop.tmpFileLocation,"fwtmp");
459 dumpfd = fopen(dumpname,"w+");
460 dump_scene(dumpfd, 0, (struct X3D_Node*) rootNode());
461 fflush(dumpfd) ;
462 if (sendNameNotFile) {
463 fclose(dumpfd) ;
464 throwAway = sprintf (th->outBuffer,"RE\n%f\n%d\n%s",TickTime(),count,dumpname);
465 } else {
466 dumpfsize = (int) ftell(dumpfd) ;
467 fseek(dumpfd, 0L, SEEK_SET) ;
468
469 th->outBuffer = REALLOC(th->outBuffer,dumpfsize+200);
470 dumpInt = sprintf (th->outBuffer,"RE\n%f\n%d\n",TickTime(),count);
471 throwAway = (int) fread(th->outBuffer+dumpInt, dumpfsize, 1, dumpfd);
472 dumpInt += dumpfsize;
473
474 th->outBuffer[dumpInt] = '\0';
475 fclose(dumpfd) ;
476 unlink(dumpname) ;
477 }
478
479 break;
480 }
481 case GETRENDPROP: {
483 ttglobal tg = gglobal();
484 rdr_caps = (s_renderer_capabilities_t *)tg->display.rdr_caps;
485 sprintf (th->outBuffer,"RE\n%f\n%d\n%s %dx%d %d %s %d %f",TickTime(),count,
486 "SMOOTH", /* Shading */
487 rdr_caps->system_max_texture_size, rdr_caps->runtime_max_texture_size, /* Texture size */
488 rdr_caps->texture_units, /* texture units */
489 "FALSE", /* antialiased? */
490 tg->OpenGL_Utils.displayDepth, /* bit depth of display */
491 256.0 /* amount of memory left on card -
492 can not find this in OpenGL, so
493 just make it large... */
494 );
495 break;
496 }
497
498 case GETNAME: {
499 sprintf (th->outBuffer,"RE\n%f\n%d\n%s",TickTime(),count,BrowserName);
500 break;
501 }
502 case GETVERSION: {
503 sprintf (th->outBuffer,"RE\n%f\n%d\n%s",TickTime(),count,libFreeWRL_get_version());
504 break;
505 }
506 case GETENCODING: {
507 sprintf (th->outBuffer,"RE\n%f\n%d\n%d",TickTime(),count,tg->Mainloop.currentFileVersion);
508 break;
509 }
510 case GETCURSPEED: {
511 /* get the BrowserSpeed variable updated */
512 getCurrentSpeed();
513 sprintf (th->outBuffer,"RE\n%f\n%d\n%f",TickTime(),count,gglobal()->Mainloop.BrowserSpeed);
514 break;
515 }
516 case GETFRAMERATE: {
517 sprintf (th->outBuffer,"RE\n%f\n%d\n%f",TickTime(),count,gglobal()->Mainloop.BrowserFPS);
518 break;
519 }
520 case GETURL: {
521 sprintf (th->outBuffer,"RE\n%f\n%d\n%s",TickTime(),count,BrowserFullPath);
522 break;
523 }
524 case GETNODE: {
525 handleGETNODE(&EAI_BUFFER_CUR,count);
526 break;
527 }
528 case GETROUTES: {
529 handleGETROUTES(&EAI_BUFFER_CUR,count);
530 break;
531 }
532
533 case GETEAINODETYPE: {
534 handleGETEAINODETYPE(&EAI_BUFFER_CUR,count);
535 break;
536 }
537
538 case GETNODETYPE: {
539 int cNode;
540 retint = sscanf(&EAI_BUFFER_CUR,"%d",(&cNode));
541 if (eaiverbose) { printf ("\n"); } /* need to fix the dangling printf before the case statement */
542 if (cNode != 0) {
543 boxptr = getEAINodeFromTable(cNode,-1);
544 sprintf (th->outBuffer,"RE\n%f\n%d\n%d",TickTime(),count,getSAI_X3DNodeType (
545 boxptr->_nodeType));
546 } else {
547 sprintf (th->outBuffer,"RE\n%f\n%d\n-1",TickTime(),count);
548 }
549 /* printf ("GETNODETYPE, for node %s, returns %s\n",(&EAI_BUFFER_CUR),buf); */
550
551 break;
552 }
553
554 case GETFIELDTYPE: {
555 int xtmp;
556
557 /*format int seq# COMMAND int node# string fieldname string direction*/
558
559 retint=sscanf (&EAI_BUFFER_CUR,"%d %s %s",&xtmp, ctmp,dtmp);
560 if (eaiverbose) { printf ("\n"); } /* need to fix the dangling printf before the case statement */
561 if (eaiverbose) {
562 printf ("GETFIELDTYPE cptr %d %s %s\n",xtmp, ctmp, dtmp);
563 }
564
565 EAI_GetType (xtmp, ctmp, dtmp, &ra, &rb, &rc, &rd, &scripttype, &xxx);
566 sprintf (th->outBuffer,"RE\n%lf\n%d\n%d %d %d %c %d %s",TickTime(),count,(int)ra,(int)rb,(int)rc,(int)rd,
567 scripttype,stringKeywordType(xxx));
568 break;
569 }
570 case SENDEVENT: {
571 /*format int seq# COMMAND NODETYPE pointer offset data*/
572 setField_FromEAI (&EAI_BUFFER_CUR);
573 th->outBuffer[0] = 0;
574 if (eaiverbose) {
575 printf ("after SENDEVENT, strlen %d\n",(int)strlen(&EAI_BUFFER_CUR));
576 }
577 break;
578 }
579
580 case CREATEVU:
581 case CREATEXS:
582 case CREATEVS: {
583 /*format int seq# COMMAND vrml text string EOT*/
584
585 retGroup = createNewX3DNode(NODE_Group);
586 //JAS printf ("CREATEXS, created retGroup of %p\n",retGroup);
587
588 if (command == CREATEVS || command == CREATEXS) {
589 int topWaitLimit=16;
590 int currentWaitCount=0;
591
592 if (eaiverbose) {
593 if(command==CREATEVS) printf ("CREATEVS %s\n",&EAI_BUFFER_CUR);
594 if(command==CREATEXS) printf ("CREATEXS %s\n",&EAI_BUFFER_CUR);
595 }
596
597 EOT = strstr(&EAI_BUFFER_CUR,"\nEOT\n");
598/* if we do not have a string yet, we have to do this...
599This is a problem. We cannot create the VRML until we have a whole stanza
600which means we may have to block, because we cannot respond to the original request.
601
602However, nowadays we do not read any sockets directly....
603*/
604
605 while (EOT == NULL && topWaitLimit >= currentWaitCount) {
606 if(fwlio_RxTx_control(CHANNEL_EAI,RxTx_REFRESH) == 0) {
607 /* Nothing to be done, maybe not even running */
608 usleep(10000);
609 currentWaitCount++;
610 } else {
611 if(fwlio_RxTx_waitfor(CHANNEL_EAI,"\nEOT\n") != (char *)NULL) {
612 char *tempEAIdata = fwlio_RxTx_getbuffer(CHANNEL_EAI) ;
613 if(tempEAIdata != (char *)NULL) {
614 strcat(&EAI_BUFFER_CUR,tempEAIdata) ;
615 /* tg->EAICore.EAIbuffer = ....*/
616 FREE(tempEAIdata) ;
617 }
618 } else {
619 usleep(10000);
620 currentWaitCount++;
621 }
622 }
623 EOT = strstr(&EAI_BUFFER_CUR,"\nEOT\n");
624 }
625 if (topWaitLimit <= currentWaitCount) {
626 /* Abandon Ship */
627 sprintf (th->outBuffer,"RE\n%f\n%d\n-1",TickTime(),count);
628 } else {
629
630 *EOT = 0; /* take off the EOT marker*/
631 if(command==CREATEVS)
632 ra = EAI_CreateVrml("String",(&EAI_BUFFER_CUR),rootNode(),retGroup);
633 else //CREATEXS
634 ra = EAI_CreateX3d("String",(&EAI_BUFFER_CUR),rootNode(),retGroup);
635 /* finish this, note the pointer maths */
636 bufPtr = (int) (EOT+3-tg->EAICore.EAIbuffer);
637 }
638 } else {
639/* char *filename = MALLOC(char *,1000); */
640 char *mypath;
641
642 /* sanitize this string - remove leading and trailing garbage */
643 rb = 0;
644 while ((EAI_BUFFER_CUR!=0) && (EAI_BUFFER_CUR <= ' ')) bufPtr++;
645 while (EAI_BUFFER_CUR > ' ') { ctmp[rb] = EAI_BUFFER_CUR; rb ++; bufPtr++; }
646
647 /* ok, lets make a real name from this; maybe it is local to us? */
648 ctmp[rb] = 0;
649
650 /* get the current parent */
651 mypath = STRDUP(ctmp);
652 DEBUG_MSG("CREATEVU, mypath %s\n", mypath);
653
654 /* and strip off the file name, leaving any path */
655/* removeFilenameFromPath (mypath); */
656 /* printf ("CREATEVU, mypath sans file: %s\n",mypath); */
657
658 /* add the two together */
659/* makeAbsoluteFileName(filename,mypath,ctmp); */
660 /* printf ("CREATEVU, filename, %s\n",filename); */
661
662/* if (eaiverbose) { */
663/* printf ("CREATEVU %s\n",filename); */
664/* } */
665
666 ra = EAI_CreateVrml("URL", mypath, rootNode(), retGroup);
667/* FREE_IF_NZ(filename); */
668 FREE_IF_NZ(mypath);
669 }
670
671 //JAS printf ("CREATEXS ok, we are going to return the following number of nodes: %d\n",retGroup->children.n);
672 sprintf (th->outBuffer,"RE\n%f\n%d\n",TickTime(),count);
673 for (rb = 0; rb < retGroup->children.n; rb++) {
674 struct X3D_Node *node;
675 node = X3D_NODE(retGroup->children.p[rb]);
676 //printf ("CREATEXS, child %d is %p\n",rb,node);
677
678 sprintf (ctmp,"%d ", registerEAINodeForAccess(node));
679
680 outBufferCat(ctmp);
681
682 // now, ensure this ones parent is removed
683 remove_parent(node,X3D_NODE(retGroup));
684 }
685
686 //printf ("CREATEXS, marking for dispose, group %p\n",X3D_NODE(retGroup));
687 markForDispose(X3D_NODE(retGroup),FALSE);
688 break;
689 }
690
691 case SENDCHILD : {
692 struct X3D_Node *node;
693 char *address;
694
695 /*format int seq# COMMAND int node# ParentNode field ChildNode*/
696
697 retint=sscanf (&EAI_BUFFER_CUR,"%d %d %s %d",&ra,&rb,ctmp,&rc);
698
699 node = getEAINodeFromTable(ra,rb);
700 address = getEAIMemoryPointer (ra,rb);
701
702 if (eaiverbose) {
703 printf ("SENDCHILD Parent: %u ParentField: %u %s Child at: %d\n",(unsigned int) ra, (unsigned int)rb, ctmp, rc);
704 }
705
706 /* we actually let the end of eventloop code determine whether this is an add or
707 remove, or whatever - it will handle the addChildren and removeChildren well
708 so the add/remove/replace parameter of getMFNodetype is always 1 here */
709
710 getMFNodetype (getEAINodeFromTable(rc,-1),(struct Multi_Node *)address, node, 1);
711
712 /* tell the routing table that this node is updated - used for RegisterListeners */
713 MARK_EVENT(node,getEAIActualOffset(ra,rb));
714
715 sprintf (th->outBuffer,"RE\n%f\n%d\n0",TickTime(),count);
716 break;
717 }
718 case REGLISTENER: {
719 struct X3D_Node * node;
720 int offset;
721 int directionFlag = 0;
722
723 /*143024848 88 8 e 6*/
724 retint=sscanf (&EAI_BUFFER_CUR,"%d %d %c %d",&tmp_a,&tmp_b,ctmp,&tmp_c);
725printf ("REGLISTENER, calling getEAINodeFromTable(%d, %d)\n",tmp_a,tmp_b);
726 node = getEAINodeFromTable(tmp_a, tmp_b);
727printf ("REGLISTENER, calling getEAIActualOffset(%d, %d)\n",tmp_a,tmp_b);
728 offset = getEAIActualOffset(tmp_a, tmp_b);
729printf ("REGLISTENER, have node %p, offset %d (%s)\n",node,offset, stringNodeType(node->_nodeType));
730printf ("REGLISTENER, ctmp tells us that type is %c\n",ctmp[0]);
731
732 /* is this a script node? if so, get the actual string name in the table for this one */
733 if (node->_nodeType == NODE_Script) {
734 struct Shader_Script * sp;
735
736 /* we send along the script number, not the node pointer */
737 sp = (struct Shader_Script *) (X3D_SCRIPT(node)->__scriptObj);
738
739 /* some print statements here because this is a script node
740 printf ("ah! so noderef %d, node %u is script num %d\n",tmp_a,node,sp->num);
741 printf ("this is a script node in a REGLISTENER command! %d\n",tmp_b);
742 */
743
744 node = offsetPointer_deref(struct X3D_Node *,0,sp->num);
745 directionFlag = FROM_SCRIPT;
746 }
747
748 /* so, count = query id, tmp_a pointer, tmp_b, offset, ctmp[0] type, tmp_c, length*/
749 ctmp[1]=0;
750
751 if (eaiverbose)
752 printf ("REGISTERLISTENER from %p foffset %d fieldlen %d type %s \n",
753 node, offset ,tmp_c,ctmp);
754
755
756 /* put the address of the listener area in a string format for registering
757 the route - the route propagation will copy data to here */
758
759 /* set up the route from this variable to the handle Listener routine */
760 if (eaiverbose) printf ("going to register route for RegisterListener, have type %d\n",tmp_c);
761
762
763 // encode field type, node id, and field offset id here
764 struct EAI_Extra_Data *ed = MALLOC(struct EAI_Extra_Data *,sizeof(struct EAI_Extra_Data));
765 ed->field_type = mapEAItypeToFieldType(ctmp[0]);
766 ed->listener_id = count;
767 ed->field_id = tmp_b;
768 ed-> node_id = tmp_a;
769
770/*
771{
772 int field_id;
773 int node_id;
774 int field_type;
775 int listener_id;
776};
777*/
778
779printf ("registering, field_id %d, node_id %d, field_type %d, listener_id %d\n",ed->field_id, ed->node_id, ed->field_type, ed->listener_id);
780
781
782 CRoutes_Register (1,node, offset, NULL, 0, (int) tmp_c,(void *)
783 &EAIListener, directionFlag, ed);
784/*
785(mapEAItypeToFieldType(ctmp[0])<<24)
786 +(tmp_a<<8)
787 +tmp_b);
788*/
789
790 sprintf (th->outBuffer,"RE\n%f\n%d\n0",TickTime(),count);
791 break;
792 }
793
794 case UNREGLISTENER: {
795 struct X3D_Node * node;
796 void *vextra;
797 unsigned int iextra;
798 int offset;
799 int directionFlag = 0;
800
801 /*143024848 88 8 e 6*/
802 retint=sscanf (&EAI_BUFFER_CUR,"%d %d %c %d",&tmp_a,&tmp_b,ctmp,&tmp_c);
803 node = getEAINodeFromTable(tmp_a,tmp_b);
804 offset = getEAIActualOffset(tmp_a,tmp_b);
805
806 if (node->_nodeType == NODE_Script) {
807 struct Shader_Script * sp;
808
809 /* we send along the script number, not the node pointer */
810 sp = (struct Shader_Script *) (X3D_SCRIPT(node)->__scriptObj);
811
812 /* some print statements here because this is a script node
813 printf ("ah! so noderef %d, node %u is script num %d\n",tmp_a,node,sp->num);
814 printf ("this is a script node in a REGLISTENER command! %d\n",tmp_b);
815 */
816
817 node = offsetPointer_deref(struct X3D_Node *,0,sp->num);
818 directionFlag = FROM_SCRIPT;
819 }
820
821 /* so, count = query id, tmp_a pointer, tmp_b, offset, ctmp[0] type, tmp_c, length*/
822 ctmp[1]=0;
823
824 if (eaiverbose) printf ("UNREGISTERLISTENER from %p foffset %d fieldlen %d type %s \n",
825 node, offset ,tmp_c,ctmp);
826
827
828 /* put the address of the listener area in a string format for registering
829 the route - the route propagation will copy data to here */
830 /* set up the route from this variable to the handle Listener routine */
831 //dug9 I have no idea what extra is doing, Jun 29, 2018 I'm cleaning up compiler complaints
832 iextra = (count<<8)+mapEAItypeToFieldType(ctmp[0]);
833 //memset(vextra,0,sizeof(void*));
834 vextra = NULL;
835 memcpy(vextra,&iextra,4);
836 CRoutes_Register (0,node, offset, NULL, 0, (int) tmp_c,(void *)
837 &EAIListener, directionFlag, vextra ); /* encode id and type here*/
838
839 sprintf (th->outBuffer,"RE\n%f\n%d\n0",TickTime(),count);
840 break;
841 }
842
843 case GETVALUE: {
844 handleEAIGetValue(command, &EAI_BUFFER_CUR,count);
845 break;
846 }
847 case REPLACEWORLD: {
848 EAI_RW(&EAI_BUFFER_CUR);
849 sprintf (th->outBuffer,"RE\n%f\n%d\n0",TickTime(),count);
850 break;
851 }
852
853 case GETPROTODECL: {
854 sprintf (th->outBuffer,"RE\n%f\n%d\n%s",TickTime(),count,SAI_StrRetCommand ((char) command,&EAI_BUFFER_CUR));
855 break;
856 }
857 case REMPROTODECL:
858 case UPDPROTODECL:
859 case UPDNAMEDNODE:
860 case REMNAMEDNODE: {
861 if (eaiverbose) {
862 printf ("SV int ret command ..%s\n",&EAI_BUFFER_CUR);
863 }
864 sprintf (th->outBuffer,"RE\n%f\n%d\n%d",TickTime(),count,
865 SAI_IntRetCommand ((char) command,&EAI_BUFFER_CUR));
866 break;
867 }
868 case ADDROUTE:
869 case DELETEROUTE: {
870 handleRoute (command, &EAI_BUFFER_CUR,count);
871 break;
872 }
873
874 case STOPFREEWRL: {
875 if (!RUNNINGASPLUGIN) {
876 fwl_doQuit(__FILE__,__LINE__);
877 break;
878 }
879 }
880 case VIEWPOINT: {
881 /* do the viewpoints. Note the spaces in the strings */
882 if (!strncmp(&EAI_BUFFER_CUR, " NEXT",5)) fwl_Next_ViewPoint();
883 if (!strncmp(&EAI_BUFFER_CUR, " FIRST",6)) fwl_First_ViewPoint();
884 if (!strncmp(&EAI_BUFFER_CUR, " LAST",5)) fwl_Last_ViewPoint();
885 if (!strncmp(&EAI_BUFFER_CUR, " PREV",5)) fwl_Prev_ViewPoint();
886
887 sprintf (th->outBuffer,"RE\n%f\n%d\n0",TickTime(),count);
888 break;
889 }
890
891 case LOADURL: {
892 /* signal that we want to send the Anchor pass/fail to the EAI code */
893 p->waiting_for_anchor = TRUE;
894
895 /* make up the URL from what we currently know */
896 createLoadURL(&EAI_BUFFER_CUR);
897
898
899 /* prep the reply... */
900 sprintf (th->outBuffer,"RE\n%f\n%d\n",TickTime(),count);
901 /*
902 * Lots of pretending going on here....
903 *
904 * We prep (and send) the first portion of the reply
905 * but you will notice later on, we do not add an END_OF marker.
906 * So, then it is EAI_Anchor_Response() that sends the actual
907 * success/fail response with a END_OF marker.
908 *
909 * Therefore the client needs to be clever and glue the two-part
910 * reply back together again. This is easy in the socket code, but
911 * if you use functions, you need to be clever and wait for the
912 * async callback befor proceeding as if the request worked.
913 *
914 */
915
916 /* now tell the fwl_RenderSceneUpdateScene that BrowserAction is requested... */
917 setAnchorsAnchor( get_EAIEventsIn_AnchorNode()); //&tg->EAIEventsIn.EAI_AnchorNode;
918 tg->RenderFuncs.BrowserAction = TRUE;
919 break;
920 }
921
922 case CREATEPROTO:
923 case CREATENODE: {
924 /* sanitize this string - remove leading and trailing garbage */
925 rb = 0;
926 while ((EAI_BUFFER_CUR!=0) && (EAI_BUFFER_CUR <= ' ')) bufPtr++;
927 while (EAI_BUFFER_CUR > ' ') { ctmp[rb] = EAI_BUFFER_CUR; rb ++; bufPtr++; }
928
929 ctmp[rb] = 0;
930 if (eaiverbose) {
931 printf ("CREATENODE/PROTO %s\n",ctmp);
932 }
933
934 /* set up the beginnings of the return string... */
935 sprintf (th->outBuffer,"RE\n%f\n%d\n",TickTime(),count);
936
937 retGroup = createNewX3DNode(NODE_Group);
938 if (command == CREATENODE) {
939 if (eaiverbose) {
940 printf ("CREATENODE, %s is this a simple node? %d\n",ctmp,findFieldInNODES(ctmp));
941 }
942
943 ctype = findFieldInNODES(ctmp);
944 if (ctype > -1) {
945 /* yes, use C only to create this node */
946 sprintf (ctmp, "%ld",(long int) createNewX3DNode(ctype));
947 outBufferCat(ctmp);
948 /* set ra to 0 so that the sprintf below is not used */
949 ra = 0;
950 } else {
951 ra = EAI_CreateVrml("CREATENODE",ctmp,rootNode(),retGroup);
952 }
953 } else if (command == CREATEPROTO)
954 ra = EAI_CreateVrml("CREATEPROTO",ctmp,rootNode(),retGroup);
955 else
956 printf ("eai - huh????\n");
957
958
959 for (rb = 0; rb < retGroup->children.n; rb++) {
960 sprintf (ctmp,"%ld ", (long int) retGroup->children.p[rb]);
961 outBufferCat(ctmp);
962printf ("Possible EAI problem, children of container group should have this parent removed\n");
963
964 // now, ensure this ones parent is removed
965 //remove_parent(node,X3D_NODE(retGroup));
966 }
967 markForDispose(X3D_NODE(retGroup),FALSE);
968 break;
969 }
970
971 case GETFIELDDEFS: {
972 /* get a list of fields of this node */
973 sscanf (&EAI_BUFFER_CUR,"%d",&ra);
974 makeFIELDDEFret(ra,count);
975 break;
976 }
977
978 case GETNODEDEFNAME: {
979 /* return a def name for this node. */
980 sprintf (th->outBuffer,"RE\n%f\n%d\n%s",TickTime(),count,
981 SAI_StrRetCommand ((char) command,&EAI_BUFFER_CUR));
982
983 break;
984 }
985 case GETNODEPARENTS:
986 {
987 handleGETNODEPARENTS(&EAI_BUFFER_CUR,count);
988 break;
989 }
990
991 default: {
992 printf ("unhandled command :%c: %d\n",command,command);
993 outBufferCat( "unknown_EAI_command");
994 break;
995 }
996
997 }
998
999 /* skip to the next command */
1000 while (EAI_BUFFER_CUR >= ' ') bufPtr++;
1001 /* skip any new lines that may be there */
1002 while ((EAI_BUFFER_CUR == 10) || (EAI_BUFFER_CUR == 13)) bufPtr++;
1003
1004 if (eaiverbose) {
1005 printf ("end of command, remainder %d chars ",(int)strlen(&EAI_BUFFER_CUR));
1006#ifdef _MSC_VER
1007 printf ("and :%s: thread %lu\n",(&EAI_BUFFER_CUR),(unsigned long) pthread_self().p);
1008#else
1009 printf ("and :%s: thread %lu\n",(&EAI_BUFFER_CUR),(unsigned long) pthread_self());
1010#endif
1011
1012 }
1013 if (command == SENDEVENT ) {
1014 /* events don't send a reply as such so your code has to check for zerolength strings*/
1015 th->outBuffer[0] = 0;
1016 } else {
1017 /* send the response, but only a portion in the case of LOADURL */
1018 if (command != LOADURL) outBufferCat("\nRE_EOT"); /* Please read and digest the LOADURL case above */
1019 }
1020 }
1021 tg->EAICore.EAIbufpos = bufPtr;
1022eaiverbose=FALSE; //JAS
1023
1024 return ;
1025}
1026
1027static void handleGETROUTES (char *bufptr, int repno) {
1028 int numRoutes;
1029 int count;
1030 struct X3D_Node *fromNode;
1031 struct X3D_Node *toNode;
1032 int fromOffset;
1033 int toOffset;
1034 char ctmp[200];
1035 struct tEAIHelpers* th = &gglobal()->EAIHelpers;
1036
1037 sprintf (th->outBuffer,"RE\n%f\n%d\n",TickTime(),repno);
1038
1039 numRoutes = getRoutesCount();
1040
1041 if (numRoutes < 2) {
1042 outBufferCat("0");
1043 return;
1044 }
1045
1046 /* tell how many routes there are */
1047 sprintf (ctmp,"%d ",numRoutes-2);
1048 outBufferCat(ctmp);
1049
1050 /* remember, in the routing table, the first and last entres are invalid, so skip them */
1051 for (count = 1; count < (numRoutes-1); count++) {
1052 getSpecificRoute (count,&fromNode, &fromOffset, &toNode, &toOffset);
1053
1054 sprintf (ctmp, "%p %s %p %s ",fromNode,
1055 findFIELDNAMESfromNodeOffset(fromNode,fromOffset),
1056 toNode,
1057 findFIELDNAMESfromNodeOffset(toNode,toOffset)
1058 );
1059 outBufferCat(ctmp);
1060 /* printf ("route %d is:%s:\n",count,ctmp); */
1061 }
1062
1063 /* printf ("getRoutes returns %s\n",buf); */
1064}
1065
1066static void handleGETNODE (char *bufptr, int repno) {
1067 int retint;
1068 char ctmp[200];
1069 struct tEAIHelpers* th;
1070 int eaiverbose;
1071 ttglobal tg = gglobal();
1072 eaiverbose = tg->EAI_C_CommonFunctions.eaiverbose;
1073 th = &tg->EAIHelpers;
1074 /*format int seq# COMMAND string nodename*/
1075
1076 UNUSED(retint); // for compiler warnings
1077
1078 retint=sscanf (bufptr," %s",ctmp);
1079
1080 if (eaiverbose) {
1081 printf ("GETNODE %s\n",ctmp);
1082 }
1083
1084 /* is this the SAI asking for the root node? */
1085 if (strcmp(ctmp,SYSTEMROOTNODE)) {
1086 sprintf (th->outBuffer,"RE\n%f\n%d\n%d",TickTime(),repno, EAI_GetNode(ctmp));
1087 } else {
1088 /* yep i this is a call for the rootNode */
1089 sprintf (th->outBuffer,"RE\n%f\n%d\n%d",TickTime(),repno, EAI_GetRootNode());
1090 }
1091 if (eaiverbose) {
1092 printf ("GETNODE returns %s\n",th->outBuffer);
1093 }
1094}
1095
1096static void handleGETNODEPARENTS (char *bufptr, int repno)
1097{
1098 int nodeHandle;
1099 char parentAdr[10];
1100 char buffer[EAIREADSIZE];
1101 struct tEAIHelpers* th;
1102 int eaiverbose;
1103
1104 int* parentArray;
1105 int result;
1106 int index;
1107
1108 ttglobal tg = gglobal();
1109 eaiverbose = tg->EAI_C_CommonFunctions.eaiverbose;
1110 th = &tg->EAIHelpers;
1111
1112 nodeHandle = 0;
1113 parentArray = NULL;
1114 /*format int seq# COMMAND string nodename*/
1115
1116 sscanf(bufptr,"%d",&nodeHandle);
1117
1118 if (eaiverbose) {
1119 printf ("GETNODEPARENTS %d\n",nodeHandle);
1120 }
1121
1122 result = EAI_GetNodeParents(nodeHandle,&parentArray);
1123
1124 snprintf(buffer,EAIREADSIZE,"RE\n%f\n%d\n",TickTime(),repno);
1125
1126 if(result > 0)
1127 {
1128 for(index = 0; index < result; index++)
1129 {
1130 snprintf(parentAdr,10,"%d ",parentArray[index]);
1131 strncat(buffer,parentAdr,strlen(parentAdr));
1132 }
1133 }
1134 else
1135 {
1136 snprintf(parentAdr,10,"%d ",result);
1137 strncat(buffer,parentAdr,strlen(parentAdr));
1138 }
1139
1140 outBufferCat(buffer);
1141
1142 if (eaiverbose) {
1143 printf ("GETNODE returns %s\n",th->outBuffer);
1144 }
1145
1146 if(parentArray)
1147 free(parentArray);
1148}
1149
1150
1151/* get the actual node type, whether Group, IndexedFaceSet, etc, and its DEF name, if applicapable */
1152static void handleGETEAINODETYPE (char *bufptr, int repno) {
1153 int wlen;
1154 int nodeHandle;
1155 struct X3D_Node * myNode;
1156 char *cptr;
1157 char *myNT;
1158 struct tEAIHelpers *th = &gglobal()->EAIHelpers;
1159 /*format int seq# COMMAND string nodename*/
1160
1161 wlen=sscanf (bufptr," %d",&nodeHandle);
1162 if (wlen != 1) ConsoleMessage ("handleGETEAINODETYPE - expected to handle 1 number, got %d",wlen);
1163
1164 myNode = getEAINodeFromTable(nodeHandle,-1);
1165
1166 if (myNode == NULL) {
1167 printf ("Internal EAI error, node %d not found\n",nodeHandle);
1168 sprintf (th->outBuffer,"RE\n%f\n%d\n__UNDEFINED __UNDEFINED",TickTime(),repno);
1169 return;
1170 }
1171
1172 /* so, this is a valid node, lets find out if it is DEFined or whatever... */
1173 /* Get the Node type. If it is a PROTO, get the proto def name, if not, just get the X3D node name */
1174 //if ((myNode->_nodeType == NODE_Group) && (X3D_GROUP(myNode)->FreeWRL__protoDef != INT_ID_UNDEFINED)) {
1175 if (isProto(myNode)) {
1176 myNT = parser_getPROTONameFromNode(myNode);
1177 if (myNT == NULL) {
1178 myNT = "XML_PROTO"; /* add this if we need to parse XML proto getTypes */
1179 }
1180 } else {
1181 myNT = (char *) stringNodeType(myNode->_nodeType);
1182 }
1183
1184 /* Try to get X3D node name */
1185 #ifdef IPHONE
1186 cptr = NULL; /* no xml parsing for now in iphone */
1187 #else
1188 cptr = X3DParser_getNameFromNode(myNode);
1189 #endif
1190
1191 if (cptr != NULL) {
1192 sprintf (th->outBuffer,"RE\n%f\n%d\n%s %s",TickTime(),repno,myNT, cptr);
1193 return;
1194 }
1195
1196 /* Try to get VRML node name */
1197 cptr= parser_getNameFromNode(myNode);
1198 if (cptr != NULL) {
1199 /* Only one of these is right ..... */
1200 /* I think it is the first one, because we would have had to know the DEF name in the first place. */
1201 /* sprintf (th->outBuffer,"RE\n%f\n%d\n\\"%s\"",TickTime(),repno,myNT); */
1202 sprintf (th->outBuffer,"RE\n%f\n%d\n\"%s\" \"%s\"",TickTime(),repno,myNT, cptr);
1203 /* sprintf (th->outBuffer,"RE\n%f\n%d\n\"%s\"",TickTime(),repno, cptr); */
1204 return;
1205 }
1206
1207 /* no, this node is just undefined */
1208 sprintf (th->outBuffer,"RE\n%f\n%d\n%s __UNDEFINED",TickTime(),repno,myNT);
1209}
1210
1211
1212/* add or delete a route */
1213static void handleRoute (char command, char *bufptr, int repno) {
1214 struct X3D_Node *fromNode;
1215 struct X3D_Node *toNode;
1216 char fieldTemp[2000];
1217 int fromOffset, toOffset;
1218 int fromfieldType, fromfieldNode, fromretNode, fromretField, fromdataLen;
1219 int fromscripttype;
1220 int fromxxx;
1221 int tofieldNode, toretNode, toretField, todataLen, tofieldType;
1222 int toscripttype;
1223 int toxxx;
1224 char *x;
1225 int ftlen;
1226
1227 int rv;
1228 int eaiverbose;
1229 struct tEAIHelpers *th = &gglobal()->EAIHelpers;
1230 eaiverbose = gglobal()->EAI_C_CommonFunctions.eaiverbose;
1231 /* assume that all is ok right now */
1232 rv = TRUE;
1233
1234 /* get ready for the reply */
1235 sprintf (th->outBuffer,"RE\n%f\n%d\n",TickTime(),repno);
1236
1237 if (eaiverbose) printf ("handleRoute, string %s\n",bufptr);
1238
1239 /* ------- worry about the route from section -------- */
1240
1241 /* read in the fromNode pointer */
1242 while (*bufptr == ' ') bufptr++;
1243
1244 /* get the from Node */
1245 sscanf(bufptr, "%u", (unsigned int *)&fromfieldNode);
1246
1247 /* copy the from field into the "fieldTemp" array */
1248 x = fieldTemp; ftlen = 0;
1249
1250 /* skip to the beginning of the field name */
1251 while (*bufptr != ' ') bufptr++;
1252 while (*bufptr == ' ') bufptr++;
1253
1254 /* copy the field over */
1255 while ((*bufptr > ' ') && (ftlen <1000)) { *x = *bufptr; x++; bufptr++; ftlen++;}
1256 *x = '\0';
1257
1258 /* and, get the info for this one */
1259 EAI_GetType (fromfieldNode, fieldTemp, "outputOnly", &fromretNode, &fromretField, &fromdataLen, &fromfieldType, &fromscripttype, &fromxxx);
1260
1261
1262 /* skip past the first field, to get ready for the next one */
1263 while (*bufptr != ' ') bufptr++;
1264 while (*bufptr == ' ') bufptr++;
1265
1266 /* ------- now, the route to section -------- */
1267 /* get the to Node */
1268
1269 sscanf(bufptr, "%u", (unsigned int *)&tofieldNode);
1270
1271 /* copy the to field into the "fieldTemp" array */
1272 x = fieldTemp; ftlen = 0;
1273
1274 /* skip to the beginning of the field name */
1275 while (*bufptr != ' ') bufptr++;
1276 while (*bufptr == ' ') bufptr++;
1277
1278 /* copy the field over */
1279 while ((*bufptr > ' ') && (ftlen <1000)) { *x = *bufptr; x++; bufptr++; ftlen++;}
1280 *x = '\0';
1281
1282 /* and, get the info for this one */
1283 EAI_GetType (tofieldNode, fieldTemp, "inputOnly", &toretNode, &toretField, &todataLen, &tofieldType, &toscripttype, &toxxx);
1284
1285 if (eaiverbose) printf ("so, we are routing from %d:%d to %d:%d, fieldtypes %d:%d, datalen %d:%d\n",
1286 fromretNode, toretNode, fromretField,
1287 toretField, fromfieldType,tofieldType, fromdataLen,todataLen);
1288
1289 /* are both fieldtypes the same, and are both valid? */
1290 rv= ((fromfieldType==tofieldType) &&(fromfieldType != -1));
1291
1292 /* ------- if we are ok, call the routing code -------- */
1293 if (rv) {
1294 /* get the C node and field offset for the nodes now */
1295 fromNode = (struct X3D_Node*) getEAINodeFromTable(fromretNode,fromretField);
1296 toNode = (struct X3D_Node*) getEAINodeFromTable(toretNode,toretField);
1297 fromOffset = getEAIActualOffset((int)fromretNode,fromretField);
1298 toOffset = getEAIActualOffset(toretNode,toretField);
1299
1300 /* is this an add or delete route? */
1301 if (command == ADDROUTE) CRoutes_RegisterSimple(fromNode,fromOffset,toNode,toOffset,fromfieldType);
1302 else CRoutes_RemoveSimple(fromNode,fromOffset,toNode,toOffset,fromfieldType);
1303
1304 outBufferCat( "0");
1305 } else {
1306 outBufferCat( "1");
1307 }
1308}
1309
1310/* for a GetFieldTypes command for a node, we return a string giving the field types */
1311
1312static void makeFIELDDEFret(int myptr, int repno) {
1313 struct X3D_Node *boxptr;
1314 int myc;
1315 int *np;
1316 char myline[200];
1317 /* Used for heavy tracing with eaiverbose */
1318 char *tmpptr;
1319 int dtmp;
1320 char ctmp;
1321 char utilBuf[EAIREADSIZE];
1322 int errcount;
1323 ttglobal tg = gglobal();
1324 int eaiverbose;
1325 struct tEAIHelpers *th = &tg->EAIHelpers;
1326 eaiverbose = tg->EAI_C_CommonFunctions.eaiverbose;
1327
1328 memset(utilBuf,'\0',sizeof(utilBuf));
1329
1330 boxptr = getEAINodeFromTable(myptr,-1);
1331
1332 if (eaiverbose) {
1333 printf ("GETFIELDDEFS, node %u -> %p\n",(unsigned int)myptr, boxptr);
1334 }
1335
1336 if (boxptr == 0) {
1337 printf ("makeFIELDDEFret have null node here \n");
1338 sprintf (th->outBuffer,"RE\n%f\n%d\n0",TickTime(),repno);
1339 return;
1340 }
1341
1342 printf ("node type is %s\n",stringNodeType(boxptr->_nodeType));
1343
1344 /* Iterate over all the fields in the node */
1345 np = (int *) NODE_OFFSETS[boxptr->_nodeType];
1346 myc = 0;
1347 while (*np != -1) {
1348 /* is this a hidden field? */
1349 if (0 != strncmp(stringFieldType(np[0]), "_", 1) ) {
1350 if (eaiverbose) {
1351 ctmp = (char) mapFieldTypeToEAItype(np[2]) ;
1352 dtmp = mapEAItypeToFieldType(ctmp) ;
1353
1354 tmpptr = offsetPointer_deref (char *, boxptr,np[1]);
1355 printf("%s,%d ",__FILE__,__LINE__) ;
1356 printf("Field %d %s , ", myc, stringFieldType(np[0])) ;
1357 printf("offset=%d bytes , ", np[1]) ;
1358
1359 printf("field_type= %c (%d) , ", ctmp , dtmp) ;
1360 printf("Routing=%s , ", stringKeywordType(np[3])) ;
1361 printf("Spec=%d , ", np[4]) ;
1362
1363 errcount = UtilEAI_Convert_mem_to_ASCII (dtmp,tmpptr, utilBuf);
1364 if (0 == errcount) {
1365 printf ("\t\tValue = %s\n",utilBuf);
1366 } else {
1367 printf ("\t\tValue = indeterminate....\n");
1368 }
1369 }
1370 myc ++;
1371 }
1372 np += FIELDOFFSET_LENGTH;
1373 }
1374
1375 sprintf (th->outBuffer,"RE\n%f\n%d\n",TickTime(),repno);
1376
1377/* AFAIK Mon May 10 21:04:48 BST 2010 The EAI no longer passes a count, nor array markers ([]) */
1378/*
1379 sprintf (myline, "%d [",myc);
1380 outBufferCat( myline);
1381*/
1382
1383 /* now go through and get the name, type, keyword */
1384 np = (int *) NODE_OFFSETS[boxptr->_nodeType];
1385 while (*np != -1) {
1386 /* if (strcmp (FIELDNAMES[*np],"_") != 0) { */
1387 if (0 != strncmp(stringFieldType(np[0]), "_", 1) ) {
1388 /*
1389 sprintf (myline,"%s %c %s ",stringFieldType(np[0]), (char) mapFieldTypeToEAItype(np[2]),
1390 stringKeywordType(np[3]));
1391 */
1392 sprintf (myline,"\"%s\" ",stringFieldType(np[0])) ;
1393 outBufferCat( myline);
1394 }
1395 np += FIELDOFFSET_LENGTH;
1396 }
1397/*
1398 sprintf (myline, "]");
1399 outBufferCat( myline);
1400*/
1401}
1402
1403
1404#endif //EXCLUDE_EAI
1405
1406
1407
1408/* EAI, replaceWorld. */
1409void EAI_RW(char *str) {
1410 struct X3D_Node *newNode;
1411 int i;
1412
1413 /* clean the slate! keep EAI running, though */
1414 printf("EAI replace world, calling kill_oldWorld\n");
1415 kill_oldWorld(FALSE,TRUE,__FILE__,__LINE__);
1416
1417 /* go through the string, and send the nodes into the rootnode */
1418 /* first, remove the command, and get to the beginning of node */
1419 while ((*str != ' ') && (strlen(str) > 0)) str++;
1420 while (isspace(*str)) str++;
1421 while (strlen(str) > 0) {
1422 i = sscanf (str, "%u",(unsigned int *)&newNode);
1423
1424 if (i>0) {
1425 AddRemoveChildren (X3D_NODE(rootNode()),offsetPointer_deref(void*,rootNode(),offsetof (struct X3D_Group, children)),&newNode,1,1,__FILE__,__LINE__);
1426 }
1427 while (isdigit(*str)) str++;
1428 while (isspace(*str)) str++;
1429 }
1430}
1431
1432//#if !defined(EXCLUDE_EAI)
1433
1434void createLoadURL(char *bufptr) {
1435 #define strbrk " :loadURLStringBreak:"
1436 int count;
1437 char *spbrk;
1438 int retint; /* used to get retval from sscanf */
1439 ppEAIEventsIn p;
1440 UNUSED(retint); // for compiler warnings
1441
1442 p = (ppEAIEventsIn)gglobal()->EAIEventsIn.prv;
1443
1444 /* fill in Anchor parameters */
1445 p->EAI_AnchorNode.description = newASCIIString("From EAI");
1446
1447 /* fill in length fields from string */
1448 while (*bufptr==' ') bufptr++;
1449 retint=sscanf (bufptr,"%d",&p->EAI_AnchorNode.url.n);
1450 while (*bufptr>' ') bufptr++;
1451 while (*bufptr==' ') bufptr++;
1452 retint=sscanf (bufptr,"%d",&p->EAI_AnchorNode.parameter.n);
1453 while (*bufptr>' ') bufptr++;
1454 while (*bufptr==' ') bufptr++;
1455
1456 /* now, we should be at the strings. */
1457 bufptr--;
1458
1459 /* MALLOC the sizes required */
1460 if (p->EAI_AnchorNode.url.n > 0) p->EAI_AnchorNode.url.p = MALLOC(struct Uni_String **, p->EAI_AnchorNode.url.n * sizeof (struct Uni_String));
1461 if (p->EAI_AnchorNode.parameter.n > 0) p->EAI_AnchorNode.parameter.p = MALLOC(struct Uni_String **, p->EAI_AnchorNode.parameter.n * sizeof (struct Uni_String));
1462
1463 for (count=0; count<p->EAI_AnchorNode.url.n; count++) {
1464 bufptr += strlen(strbrk);
1465 /* printf ("scanning, at :%s:\n",bufptr); */
1466
1467 /* nullify the next "strbrk" */
1468 spbrk = strstr(bufptr,strbrk);
1469 if (spbrk!=NULL) *spbrk='\0';
1470
1471 p->EAI_AnchorNode.url.p[count] = newASCIIString(bufptr);
1472
1473 if (spbrk!=NULL) bufptr = spbrk;
1474 }
1475 for (count=0; count<p->EAI_AnchorNode.parameter.n; count++) {
1476 bufptr += strlen(strbrk);
1477 /* printf ("scanning, at :%s:\n",bufptr); */
1478
1479 /* nullify the next "strbrk" */
1480 spbrk = strstr(bufptr,strbrk);
1481 if (spbrk!=NULL) *spbrk='\0';
1482 if (p->EAI_AnchorNode.parameter.p != NULL)
1483 {
1484 p->EAI_AnchorNode.parameter.p[count] = newASCIIString(bufptr);
1485 }
1486 if (spbrk!=NULL) bufptr = spbrk;
1487 }
1488 /* EAI_AnchorNode.__parenturl = newASCIIString("./"); */
1489}
1490#if !defined(EXCLUDE_EAI)
1491
1492
1493/* if we have a LOADURL command (loadURL in java-speak) we call Anchor code to do this.
1494 here we tell the EAI code of the success/fail of an anchor call, IF the EAI is
1495 expecting such a call */
1496
1497void EAI_Anchor_Response (int resp) {
1498 char myline[1000];
1499 ppEAIEventsIn p;
1500 //ppEAICore ps;
1501 ttglobal tg = gglobal();
1502 p = (ppEAIEventsIn)tg->EAIEventsIn.prv;
1503 //ps = (ppEAICore)tg->EAICore.prv;
1504 if (p->waiting_for_anchor) {
1505 if (resp) strcpy (myline,"OK\nRE_EOT");
1506 else strcpy (myline,"FAIL\nRE_EOT");
1507 fwlio_RxTx_sendbuffer (__FILE__,__LINE__,CHANNEL_EAI,myline);
1508 }
1509 p->waiting_for_anchor = FALSE;
1510}
1511#else
1512void EAI_Anchor_Response (int resp) {
1513 char myline[1000];
1514 ppEAIEventsIn p;
1515 //ppEAICore ps;
1516 ttglobal tg = gglobal();
1517 p = (ppEAIEventsIn)tg->EAIEventsIn.prv;
1518 //ps = (ppEAICore)tg->EAICore.prv;
1519 p->waiting_for_anchor = FALSE;
1520}
1521#endif //EXCLUDE_EAI