1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11
12
13 #include <stdio.h>
14 #include <ctype.h>
15
16 #if defined(HAVE_SYS_TYPES_H)
17 #include <sys/types.h>
18 #endif
19
20 #if defined(windows) && defined(HAVE_WINSOCK_H)
21 #include <winsock.h>
22 #elif defined(HAVE_CYGWIN_SOCKET_H)
23 #include <cygwin/socket.h>
24 #elif defined(HAVE_SYS_SOCKET_H)
25 #include <sys/socket.h>
26 #endif
27
28 #if defined(HAVE_SYS_TIMEB_H)
29 #include <sys/timeb.h>
30 #endif
31
32 #if defined(HAVE_SYS_TIME_H)
33 #include <sys/time.h>
34 #endif
35
36 #if defined(HAVE_NETDB_H)
37 #include <netdb.h>
38 #endif
39
40 #include <errno.h>
41
42 #if defined(HAVE_STRING_H)
43 #include <string.h>
44 #endif
45
46 #if defined(HAVE_MALLOC_H)
47 #include <malloc.h>
48 #endif
49
50 #if defined(HAVE_SYS_SELECT_H)
51 #include <sys/select.h>
52 #endif
53
54 #if defined(HAVE_UNISTD_H)
55 #include <unistd.h>
56 #endif
57
58 #if defined(OS2) || defined(DXD_HAS_WINSOCKETS)
59 #if defined(HAVE_IO_H)
60 #include <io.h>
61 #endif
62 #define write(a,b,c) _dxl_os2_send(a,b,c,0)
63 #define read(a,b,c) _dxl_os2_recv(a,b,c,0)
64 #endif
65
66 #include "dxlP.h"
67
68 typedef int (*DXLPacketPredicate)(DXLConnection *, DXLEvent *, void *);
69
70 static int _dxl_ReadFromSocket(DXLConnection *conn);
71 static int _dxl_WaitForReadable(DXLConnection *conn);
72 static int _dxl_IsReadable(DXLConnection *conn);
73 static void PrintEvent(DXLEvent *e);
74
75 static DXLError DXLGetPacket(DXLConnection *, DXLPacketTypeEnum, int,
76 DXLEvent *, int,
77 DXLPacketPredicate, const void *);
78
79 #define STRLEN(A) (A ? strlen(A) : 0)
80
81 char *_DXLPacketTypes[] =
82 {
83 NULL,
84 "$int", /* PACK_INTERRUPT */
85 "$sys", /* PACK_SYSTEM */
86 "$ack", /* PACK_ACK */
87 "$mac", /* PACK_MACRODEF */
88 "$for", /* PACK_FOREGROUND */
89 "$bac", /* PACK_BACKGROUND */
90 "$err", /* PACK_ERROR */
91 "$mes", /* PACK_MESSAGE */
92 "$inf", /* PACK_INFO */
93 "$lin", /* PACK_LINQUIRY */
94 "$lre", /* PACK_LRESPONSE */
95 "$dat", /* PACK_LDATA */
96 "$sin", /* PACK_SINQUIRY */
97 "$sre", /* PACK_SRESPONSE */
98 "$dat", /* PACK_SDATA */
99 "$vin", /* PACK_VINQUIRY */
100 "$vre", /* PACK_VRESPONSE */
101 "$dat", /* PACK_VDATA */
102 "$com", /* PACK_COMPLETE */
103 "$imp", /* PACK_IMPORT */
104 "$imi", /* PACK_IMPORTINFO */
105 "$lnk" /* PACK_LINK */
106 };
107
108 int _DXLNumPackets = (sizeof(_DXLPacketTypes)/sizeof(_DXLPacketTypes[0]));
109
110 DXLEvent*
DXLNewEvent(int serialId,DXLPacketTypeEnum ptype,const char * msg)111 DXLNewEvent(int serialId, DXLPacketTypeEnum ptype, const char *msg)
112 {
113 int msgsize = 0;
114
115 DXLEvent *event = (DXLEvent*)malloc(sizeof(DXLEvent));
116 if (!event)
117 return NULL;
118
119 event->serial = serialId;
120 event->type = ptype;
121 if (msg) {
122 msgsize = strlen(msg) + 1;
123 if (msgsize > DXL_EVENT_BUF_SIZE)
124 event->contents = malloc(msgsize*sizeof(char));
125 else
126 event->contents = event->buffer;
127 strcpy(event->contents,msg);
128 } else {
129 event->contents = event->buffer;
130 event->buffer[0] = '\0';
131 }
132 event->contentsSize = msgsize;
133 event->next = NULL;
134 return event;
135 }
136
137 DXLError
DXLClearEvent(DXLEvent * event)138 DXLClearEvent(DXLEvent *event)
139 {
140 if (event->contents && event->contents != event->buffer)
141 free(event->contents);
142 event->next = NULL;
143 event->contentsSize = 0;
144 event->buffer[0] = '\0';
145 event->contents = event->buffer;
146 return OK;
147 }
148 DXLError
DXLFreeEvent(DXLEvent * event)149 DXLFreeEvent(DXLEvent *event)
150 {
151 if (DXLClearEvent(event))
152 free(event);
153 return OK;
154 }
155 DXLError
DXLCopyEvent(DXLEvent * dst,DXLEvent * src)156 DXLCopyEvent(DXLEvent *dst, DXLEvent *src)
157 {
158 if (src->contentsSize > DXL_EVENT_BUF_SIZE)
159 dst->contents = malloc(src->contentsSize);
160 else
161 dst->contents = dst->buffer;
162
163 dst->contentsSize = src->contentsSize;
164
165 memcpy(dst->contents, src->contents, src->contentsSize);
166
167 return OK;
168 }
169
170 DXLError
DXLSend(DXLConnection * conn,const char * string)171 DXLSend(DXLConnection *conn, const char *string)
172 {
173 DXLPacketTypeEnum ptype=PACK_FOREGROUND;
174
175 if (conn->dxuiConnected) {
176 if (conn->majorVersion <= 2)
177 ptype = PACK_FOREGROUND;
178 else
179 ptype = PACK_LINK;
180 return DXLSendPacket(conn, ptype, string) >= 0 ? OK : ERROR;
181 }
182 else if (conn->macroDef)
183 {
184 DXLSendUnpacketized(conn, string);
185 return OK;
186 }
187 else
188 {
189 ptype = PACK_FOREGROUND;
190 return DXLSendPacket(conn, ptype, string) >= 0 ? OK : ERROR;
191 }
192
193 }
194
195
196 #ifdef DEBUG_MESSAGES
197 static int first = 1;
198 static FILE *dbg = NULL;
199 #endif
200
201 int /* packet id that was sent, -1 on error */
DXLSendPacket(DXLConnection * conn,DXLPacketTypeEnum ptype,const char * string)202 DXLSendPacket(DXLConnection *conn, DXLPacketTypeEnum ptype, const char *string)
203 {
204 int l = STRLEN(string);
205 char *buffer = malloc(l + 50);
206 int packetId, sts = 0;
207 int written = 0;
208
209 if (!conn || conn->fd < 0 || (ptype > _DXLNumPackets) || (ptype <= 0))
210 return ERROR;
211
212 packetId = conn->id++;
213
214
215 if (ptype == PACK_MACRODEF)
216 l = SPRINTF(buffer,"|%d|%s|0|\n", packetId, _DXLPacketTypes[ptype]);
217 else if (ptype == PACK_INTERRUPT)
218 {
219 l = SPRINTF(buffer,"|%d|%s|1|0|\n", packetId, _DXLPacketTypes[ptype]);
220 }
221 else if (l == 0)
222 l = SPRINTF(buffer,"|%d|%s|0||\n", packetId, _DXLPacketTypes[ptype]);
223 else
224 l = SPRINTF(buffer,
225 "|%d|%s|%d|%s|\n", packetId, _DXLPacketTypes[ptype], l, string);
226
227 #ifdef DEBUG_MESSAGES
228 if (first)
229 {
230 first = 0;
231 dbg = fopen("debug", "w");
232 }
233 else
234 dbg = fopen("debug", "a");
235
236 fprintf(dbg, "--> %s", buffer);
237 fclose(dbg);
238 #endif
239
240 do {
241 if (_dxl_ReadFromSocket(conn) < 0)
242 {
243 sts = -1;
244 break;
245 }
246 if ((sts == 0) && conn->debugMessaging)
247 fprintf(stderr, "Sending -> %s\n",buffer);
248 sts = write(conn->fd, buffer + written, l);
249 l -= sts;
250 written += sts;
251 }
252 while (sts > 0 && l > 0);
253
254 free(buffer);
255 if (sts < 0) {
256 _dxl_InvalidateSocket(conn);
257 packetId = -1;
258 goto done;
259 } else if (ptype != PACK_MACRODEF && conn->synchronous) {
260 if (!DXLSync(conn)) {
261 packetId = -1;
262 goto done;
263 }
264 }
265
266 done:
267
268 return packetId;
269 }
270
271
272 int
DXLQuery(DXLConnection * conn,const char * string,const int length,char * result)273 DXLQuery(DXLConnection *conn, const char *string,
274 const int length, char *result)
275 {
276 int found;
277 int requestId;
278 DXLEvent event;
279 DXLPacketTypeEnum ptype;
280
281
282 if (conn->fd < 0)
283 goto error;
284
285
286 if (conn->dxuiConnected)
287 {
288 if (conn->majorVersion <= 2)
289 ptype = PACK_FOREGROUND;
290 else
291 ptype = PACK_LINK;
292 }
293 else
294 {
295 /*
296 * FIXME: This probably is not the correct code,
297 * but it serves as a marker.
298 */
299 ptype = PACK_FOREGROUND;
300
301 fprintf(stderr,"DXLQuery() not implemented for dexec connections\n");
302 goto error;
303 }
304
305 requestId = DXLSendPacket(conn,ptype,string);
306 if (requestId < 0)
307 goto error;
308
309 found = 0;
310 if (conn->dxuiConnected) {
311 if (DXLGetPacketId(conn, PACK_LRESPONSE, requestId, &event))
312 found = 1;
313 } else {
314 /* include "filename" causes completes to come back that match
315 * the zero'th sync
316 */
317 if (DXLGetPacketId(conn, PACK_COMPLETE, 0, &event))
318 found = 1;
319 }
320
321 if (!found)
322 {
323 _dxl_InvalidateSocket(conn);
324 DXLClearEvent(&event);
325 goto error;
326 }
327
328 strncpy(result, event.contents, length);
329
330 DXLClearEvent(&event);
331
332 return length;
333
334 error:
335 return -1;
336 }
337
RemoveEvent(DXLConnection * conn,DXLEvent * e)338 static void RemoveEvent(DXLConnection *conn, DXLEvent *e)
339 {
340 DXLEvent *event, *last_event = NULL;
341
342 for (event = conn->events; event ; event = event->next) {
343 if (event == e)
344 break;
345 last_event = event;
346 }
347
348 if (event == e) {
349 if (e == conn->events) {
350 /*
351 * First item on list
352 */
353 conn->events = e->next;
354 if (e == conn->lastEvent) /* ...and last item */
355 conn->lastEvent = NULL;
356 } else if (e == conn->lastEvent) {
357 /*
358 * Last item on list
359 */
360 conn->lastEvent = last_event;
361 last_event->next = NULL;
362 } else {
363 /*
364 * Middle item on list
365 */
366 last_event->next = e->next;
367 }
368 }
369
370 conn->nEvents--;
371 }
AppendEvent(DXLConnection * conn,DXLEvent * e)372 static void AppendEvent(DXLConnection *conn, DXLEvent *e)
373 {
374 if (conn->events == NULL) {
375 conn->events = e;
376 } else {
377 conn->lastEvent->next = e;
378 }
379 conn->lastEvent = e;
380 conn->nEvents++;
381 e->next = NULL; /* Just to be sure */
382
383 /*
384 * We've pulled an event off the socket and onto the local queue.
385 * If the event handler is dependent on a select() on the socket to
386 * determine that there's something to do, it won't find anything.
387 * So we install an idle-time event processor that will check for
388 * something to do when the system is otherwise idle.
389 */
390 _dxf_InstallIdleEventHandler(conn);
391 }
392
393
394 DXLError
DXLNextPacket(DXLConnection * conn,DXLEvent * event)395 DXLNextPacket(DXLConnection *conn, DXLEvent *event)
396 {
397 while(conn->nEvents == 0)
398 {
399 _dxl_WaitForReadable(conn);
400 if (_dxl_ReadFromSocket(conn) == 0)
401 return ERROR;
402 }
403
404 if (conn->events->type == PACK_ERROR)
405 _DXLError(conn, conn->events->contents);
406
407 DXLCopyEvent(event, conn->events);
408
409 RemoveEvent(conn, conn->events);
410 DXLFreeEvent(conn->events);
411
412 return OK;
413 }
414
415 int
DXLWaitForEvent(DXLConnection * conn)416 DXLWaitForEvent(DXLConnection *conn)
417 {
418 if(conn->nEvents == 0)
419 _dxl_WaitForReadable(conn);
420 return OK;
421 }
422
423
424
DXLDispatchEvent(DXLConnection * conn,DXLEvent * e)425 static void DXLDispatchEvent(DXLConnection *conn, DXLEvent *e)
426 {
427 RemoveEvent(conn,e);
428 if (conn->debugMessaging) {
429 fprintf(stderr, "Dispatching <- ");
430 PrintEvent(e);
431 }
432 _dxl_HandleMessage(conn, e->type, e->serial, e->contents);
433 }
434
435 DXLError
DXLProcessEventList(DXLConnection * conn)436 DXLProcessEventList(DXLConnection *conn)
437 {
438 DXLEvent *e;
439
440 while (_dxl_IsReadable(conn))
441 if (_dxl_ReadFromSocket(conn) == 0)
442 return ERROR;
443
444 while (NULL != (e = conn->events))
445 {
446 DXLDispatchEvent(conn,e);
447 DXLFreeEvent(e);
448 }
449
450 conn->nEvents = 0;
451
452 /*
453 * Now we have cleared all the input from both the socket and the
454 * input queue in conn, so we don't need an idle-time input check.
455 */
456 _dxf_ClearIdleEventHandler(conn);
457
458 return OK;
459 }
460
461
462 /*
463 * Starting with the given event, search the event list for the event
464 * matching the given type and requestId. If requestId is < 0 then we
465 * don't try and match the requestId. Further, if pp is not NULL then
466 * we also try and match the event with a call to (pp)(conn,event,arg).
467 *
468 */
469 static DXLEvent*
DXLFindEventInList(DXLConnection * conn,DXLEvent * event,DXLPacketTypeEnum type,int requestId,DXLPacketPredicate pp,const void * arg)470 DXLFindEventInList(DXLConnection *conn, DXLEvent *event,
471 DXLPacketTypeEnum type, int requestId,
472 DXLPacketPredicate pp, const void *arg)
473 {
474 DXLEvent *e;
475
476 for (e=event ; e ; ) {
477 if ((e->type == type) &&
478 ((requestId < 0) || (e->serial == requestId)) &&
479 (!pp || (pp)(conn,e,(char *)arg)))
480 break;
481 e = e->next;
482 }
483 return e;
484 }
485
486 /*
487 * Get the packet specified by the given packet type and the given id.
488 * If id is <= 0, then we don't try and match the ids with packets.
489 * If pp is not NULL, then we call it on the event (pp(conn,e,arg)),
490 * to see if it is a match.
491 * If we find an event with a match, given the above criteria, then
492 * we copy the event into the user structure .
493 */
494 static int
DXLCheckPacket(DXLConnection * conn,DXLPacketTypeEnum type,int requestId,DXLEvent * event,DXLPacketPredicate pp,const void * arg)495 DXLCheckPacket(DXLConnection *conn, DXLPacketTypeEnum type, int requestId,
496 DXLEvent *event, DXLPacketPredicate pp, const void *arg)
497 {
498 DXLEvent *e;
499
500 e = DXLFindEventInList(conn,conn->events,type,requestId, pp, arg);
501 if (e) {
502 DXLCopyEvent(event, e);
503 return 1;
504 }
505 return 0;
506 }
507 /*
508 * Get the packet specified by the given packet type and the given id.
509 * If id is <= 0, then we don't try and match the ids with packets.
510 * If pp is not NULL, then we call it on the event (pp(conn,e,arg)),
511 * to see if it is a match.
512 * If we find an event with a match, given the above criteria, then
513 * we copy the event into the user structure and if 'remove' is non-zero
514 * we remove the event from the event list.
515 */
516 static DXLError
DXLGetPacket(DXLConnection * conn,DXLPacketTypeEnum type,int requestId,DXLEvent * event,int remove,DXLPacketPredicate pp,const void * arg)517 DXLGetPacket(DXLConnection *conn, DXLPacketTypeEnum type, int requestId,
518 DXLEvent *event, int remove,
519 DXLPacketPredicate pp, const void *arg)
520 {
521 DXLEvent *e;
522
523 e = DXLFindEventInList(conn,conn->events,type,requestId, pp, arg);
524
525 while (!e)
526 {
527 e = conn->lastEvent;
528
529 if (! _dxl_WaitForReadable(conn))
530 return ERROR;
531
532 if (! _dxl_ReadFromSocket(conn))
533 return ERROR;
534
535 if (!e)
536 e = conn->events;
537 else
538 e = e->next;
539 #if 0
540 PrintEventList(e); fprintf(stderr, "\n");
541 #endif
542 e = DXLFindEventInList(conn,e,type,requestId, pp, arg);
543 }
544
545 DXLCopyEvent(event, e);
546
547 if (remove) {
548 RemoveEvent(conn, e);
549 DXLFreeEvent(e);
550 }
551
552 return OK;
553 }
554
MatchString(DXLConnection * conn,DXLEvent * e,void * arg)555 static int MatchString(DXLConnection *conn, DXLEvent *e, void *arg)
556 {
557 char *str = (char*)arg;
558
559 if (!str || strstr(e->contents,str))
560 return 1;
561 else
562 return 0;
563 }
564 /*
565 * Find and read until a packet with the given type, packet id, and string
566 * contained in the message is found. This may block on the socket.
567 * Return the found event in the given event, and remove the event
568 * from the event list.
569 */
570 DXLError
DXLGetPacketIdString(DXLConnection * conn,DXLPacketTypeEnum type,int requestId,const char * str,DXLEvent * event)571 DXLGetPacketIdString(DXLConnection *conn, DXLPacketTypeEnum type,
572 int requestId, const char *str, DXLEvent *event)
573 {
574 return DXLGetPacket(conn,type, requestId,event, 1, MatchString,str);
575 }
576 /*
577 * Find and read until a packet with the given type and string
578 * contained in the message is found. This may block on the socket.
579 * Return the found event in the given event, and remove the event
580 * from the event list.
581 */
582 DXLError
DXLGetPacketString(DXLConnection * conn,DXLPacketTypeEnum type,const char * str,DXLEvent * event)583 DXLGetPacketString(DXLConnection *conn, DXLPacketTypeEnum type,
584 const char *str, DXLEvent *event)
585 {
586 return DXLGetPacket(conn,type,-1,event, 1, MatchString,str);
587 }
588 /*
589 * Find a packet in the current event list with the given type and string
590 * contained in the message. Do not block on the socket.
591 * Return the found event in the given event, and do not remove the event
592 * from the event list. Return 0 if a matching packet was not found,
593 * otherwise non-zero.
594 */
595 int
DXLCheckPacketString(DXLConnection * conn,DXLPacketTypeEnum type,const char * str,DXLEvent * event)596 DXLCheckPacketString(DXLConnection *conn, DXLPacketTypeEnum type,
597 const char *str, DXLEvent *event)
598 {
599 return DXLCheckPacket(conn,type,-1,event, MatchString,str);
600 }
601 /*
602 * Find and read until a packet with the given type and string contained
603 * in the message is found.
604 * Return the found event in the given event, and do not remove the event
605 * from the event list.
606 */
607 DXLError
DXLWaitPacketString(DXLConnection * conn,DXLPacketTypeEnum type,const char * str,DXLEvent * event)608 DXLWaitPacketString(DXLConnection *conn, DXLPacketTypeEnum type,
609 const char *str, DXLEvent *event)
610 {
611 return DXLGetPacket(conn,type,-1,event, 0, MatchString,str);
612 }
613 /*
614 * Find and read until a packet with the given type and id is found.
615 * Return the found event in the given event, and remove the event
616 * from the event list.
617 */
618 DXLError
DXLGetPacketId(DXLConnection * conn,DXLPacketTypeEnum type,int id,DXLEvent * event)619 DXLGetPacketId(DXLConnection *conn, DXLPacketTypeEnum type, int id,
620 DXLEvent *event)
621 {
622 return DXLGetPacket(conn,type,id,event, 1, NULL,NULL);
623 }
624
625
626 DXLError
DXLPeekPacket(DXLConnection * conn,DXLEvent * event)627 DXLPeekPacket(DXLConnection *conn, DXLEvent *event)
628 {
629 if (conn->nEvents == 0)
630 _dxl_ReadFromSocket(conn);
631
632 if (conn->nEvents == 0)
633 return ERROR;
634
635 DXLCopyEvent(event, conn->events);
636
637 return OK;
638 }
639
640 static int
_dxl_IsReadable(DXLConnection * conn)641 _dxl_IsReadable(DXLConnection *conn)
642 {
643 #ifndef OS2
644 fd_set fds;
645 #endif
646 #ifdef hp700
647 int width = MAXFUPLIM;
648 #else
649 #ifdef aviion
650 int width = NOFILE;
651 #else
652 #ifdef solaris
653 int width = FD_SETSIZE;
654 #else
655 #ifdef DXD_HAS_WINSOCKETS
656 int width = FD_SETSIZE;
657 #else
658 #ifndef OS2
659 int width = getdtablesize();
660 #endif
661 #endif
662 #endif
663 #endif
664 #endif
665 int retval = 0;
666
667 struct timeval to;
668
669 if (conn->fd < 0)
670 return 0;
671
672 #if !defined(OS2) && !defined(DXD_HAS_WINSOCKETS)
673 FD_ZERO(&fds);
674 FD_SET(conn->fd, &fds);
675 to.tv_sec = 0;
676 to.tv_usec = 0;
677
678 /* this will restart select if it has been interrupted by a signal */
679 SELECT_INTR((conn->fd + 1), (SELECT_ARG_TYPE *)&fds, NULL, NULL, &to, retval);
680 #endif
681
682 #ifdef OS2
683 retval = select(&conn->fd, 1, 0, 0, 0);
684 #endif
685
686 #ifdef DXD_HAS_WINSOCKETS
687 to.tv_sec = 0;
688 to.tv_usec = 0;
689 FD_ZERO(&fds);
690 FD_SET(conn->fd, &fds);
691 retval = select(conn->fd, &fds, NULL, NULL, &to);
692 #endif
693
694 if (retval > 0) return TRUE;
695 if (retval == 0) return FALSE;
696
697 /* retval < 0 */
698 _dxl_InvalidateSocket (conn);
699 return FALSE;
700 }
701
702 int
DXLIsMessagePending(DXLConnection * conn)703 DXLIsMessagePending(DXLConnection *conn)
704 {
705 return (conn->nEvents > 0) || _dxl_IsReadable(conn);
706 }
707
708
709 static int
_dxl_WaitForReadable(DXLConnection * conn)710 _dxl_WaitForReadable(DXLConnection *conn)
711 {
712 int retval;
713 #ifndef OS2
714 fd_set fds;
715 #endif
716 #ifdef hp700
717 int width = MAXFUPLIM;
718 #else
719 #ifdef aviion
720 int width = NOFILE;
721 #else
722 #ifdef solaris
723 int width = FD_SETSIZE;
724 #else
725 #ifdef DXD_HAS_WINSOCKETS
726 int width = FD_SETSIZE;
727 #else
728 #ifndef OS2
729 int width = getdtablesize();
730 #endif
731 #endif
732 #endif
733 #endif
734 #endif
735
736 if (conn->fd < 0)
737 return 0;
738
739 #if !defined(OS2) && !defined(DXD_HAS_WINSOCKETS)
740 FD_ZERO(&fds);
741 FD_SET(conn->fd, &fds);
742
743 /* this will restart select if it was interrupted by a signal */
744 SELECT_INTR((conn->fd + 1), (SELECT_ARG_TYPE *)&fds, NULL, NULL, NULL, retval);
745 if(retval < 0)
746 goto error;
747 #endif
748
749 #ifdef OS2
750 if (select(&conn->fd, 1, 0, 0, -1)<0)
751 goto error;
752 #endif
753
754 #ifdef DXD_HAS_WINSOCKETS
755 FD_ZERO(&fds);
756 FD_SET(conn->fd, &fds);
757 width = select((conn->fd + 1), &fds, NULL, NULL, NULL);
758 if (width < 0)
759 goto error;
760
761 #endif
762 return 1;
763
764 error:
765 _dxl_InvalidateSocket(conn);
766 return 0;
767 }
768
769 #if 0
770 static int lock_me = 0;
771 #endif
772
773 static int
_dxl_ReadFromSocket(DXLConnection * conn)774 _dxl_ReadFromSocket(DXLConnection *conn)
775 {
776 int id, typei;
777 char type[8];
778 int nbytes;
779
780 char *start;
781 int nRemaining;
782
783 char *buffer;
784 char *msgbuf;
785 int bufSize = 4096;
786 int mbufSize = 4096;
787
788 if (conn->fd < 0)
789 return 0;
790
791 buffer = (char*) malloc(bufSize);
792 msgbuf = (char*) malloc(mbufSize);
793
794 while (_dxl_IsReadable(conn)) {
795 int nread;
796
797 nRemaining = conn->nLeftOver;
798
799 while( nRemaining+1025 > bufSize ){
800 char* tmp = buffer;
801 bufSize *= 2;
802 buffer = (char*) malloc( bufSize );
803 free(tmp);
804 }
805
806 if (nRemaining) {
807 memcpy (buffer, conn->leftOver, nRemaining);
808 nread = read(conn->fd, buffer+nRemaining, 1024);
809 } else {
810 nread = read(conn->fd, buffer, 1024);
811 }
812 if (nread <= 0)
813 goto error;
814 nRemaining+= nread;
815 buffer[nRemaining] = '\0';
816
817 start = buffer;
818 /*
819 * We used to check done here, but now we'll just keep reading
820 * from start until there isn't anything left to read.
821 */
822 while (1) {
823 int len, items;
824 DXLEvent *event;
825
826 int msgbytes_in_buffer;
827 int bytes_used;
828 short message_completed;
829
830 /*
831 * sscanf() leaves 'len' unset if the last '|' was not seen
832 */
833 len = -1;
834 items = sscanf(start, "|%d|%[^|]|%d|%n", &id, type, &nbytes, &len);
835 /*
836 * Perform 2 checks to see if we have enough bytes in the buffer
837 * to form a complete message. First check to see if the sscanf
838 * completed. Then check to see if the number of bytes resulting
839 * completes a message. In order to complete a message it has
840 * to get the trailing |\n.
841 */
842 if ((items != 3) || (len == -1)) {
843 message_completed = 0;
844 } else {
845 msgbytes_in_buffer = nRemaining - len;
846 if ((nbytes+2) > msgbytes_in_buffer) {
847 message_completed = 0;
848 } else {
849 message_completed = 1;
850 }
851 }
852 if (!message_completed) {
853 if (nRemaining >= conn->allocdLeftOver) {
854 free(conn->leftOver);
855 /* malloc 1.5 times nRemaining rounded to the nearest 16 */
856 conn->allocdLeftOver = 16 + ((nRemaining + (nRemaining>>1)) & (~15));
857 conn->leftOver = malloc(conn->allocdLeftOver);
858 if (!conn->leftOver)
859 goto error;
860 }
861
862
863 strncpy(conn->leftOver, start, nRemaining);
864 conn->nLeftOver = nRemaining;
865 break;
866 }
867
868 for (typei = 1; typei < _DXLNumPackets; typei++)
869 if (! strcmp(type, _DXLPacketTypes[typei]))
870 break;
871
872 if (typei == _DXLNumPackets) {
873 fprintf (stderr, "%s[%d] packet error\n", __FILE__,__LINE__);
874 goto error;
875 }
876
877 bytes_used = (len + nbytes + 2); /* 2 = "|\n" */
878
879 while( nbytes+2 > mbufSize ){
880 char* tmp = msgbuf;
881 mbufSize *= 2;
882 msgbuf = (char*) malloc( mbufSize );
883 free(tmp);
884 }
885
886 strncpy(msgbuf, start+len, nbytes + 2);
887 if (bytes_used > nRemaining)
888 goto error;
889
890 if (msgbuf[nbytes] != '|') {
891 fprintf (stderr, "%s[%d]packet error\n", __FILE__,__LINE__);
892 goto error;
893 }
894
895 nRemaining -= bytes_used;
896 start += bytes_used;
897
898 msgbuf[nbytes] = '\0';
899
900 event = DXLNewEvent(id, (DXLPacketTypeEnum) typei,msgbuf);
901 if (!event)
902 goto error;
903 if (conn->debugMessaging) {
904 fprintf(stderr, "Recving <- ");
905 PrintEvent(event);
906 }
907 AppendEvent(conn,event);
908 }
909 }
910
911 free(buffer);
912 free(msgbuf);
913
914 return 1;
915
916 error:
917
918 free(buffer);
919 free(msgbuf);
920
921 _dxl_InvalidateSocket(conn);
922 return 0;
923 }
924
DXLSendUnpacketized(DXLConnection * conn,const char * string)925 DXLError DXLSendUnpacketized(DXLConnection *conn, const char *string)
926 {
927 int length, r;
928 char *newString;
929
930 if (conn->fd < 0)
931 return ERROR;
932
933 length = STRLEN(string) + 1;
934 newString = malloc((length + 1) * sizeof(char));
935 strcpy(newString, string);
936 newString[length-1] = '\n';
937 newString[length] = '\0';
938
939 if (conn->debugMessaging)
940 fprintf(stderr, "Sending -> %s", newString);
941
942
943 #ifdef DEBUG_MESSAGES
944 if (first)
945 {
946 first = 0;
947 dbg = fopen("debug", "w");
948 }
949 else
950 dbg = fopen("debug", "a");
951
952 fprintf(dbg, "Unpacketized --> %s", newString);
953
954 fclose(dbg);
955 #endif
956
957 if (write(conn->fd, newString, length) != length)
958 r = ERROR;
959 else
960 r = OK;
961
962 free(newString);
963 return r;
964 }
965
DXLSendImmediate(DXLConnection * conn,const char * string)966 DXLError DXLSendImmediate(DXLConnection *conn, const char *string)
967 {
968 int length, r;
969 char *newString;
970
971 if (conn->fd < 0)
972 return ERROR;
973
974 length = STRLEN(string) + 1;
975 newString = malloc((length + 1) * sizeof(char));
976
977 strcpy(newString, "$");
978 strcat(newString, string);
979
980 r = DXLSendUnpacketized(conn,newString);
981
982 if (r == OK && conn->synchronous)
983 DXLSync(conn);
984
985 free(newString);
986
987 return r;
988 }
989
990 DXLError
DXLHandlePendingMessages(DXLConnection * conn)991 DXLHandlePendingMessages(DXLConnection *conn)
992 {
993
994 DXLProcessEventList(conn);
995 while (_dxl_IsReadable(conn))
996 {
997 _dxl_ReadFromSocket(conn);
998 DXLProcessEventList(conn);
999 }
1000
1001 return OK;
1002 }
PrintEvent(DXLEvent * e)1003 static void PrintEvent(DXLEvent *e)
1004 {
1005 fprintf(stderr, "id %d type %d %s\n", e->serial, e->type, e->contents);
1006 }
1007
DXLSetMessageDebugging(DXLConnection * conn,int on)1008 int DXLSetMessageDebugging(DXLConnection *conn, int on)
1009 {
1010 int oldval = conn->debugMessaging;
1011 conn->debugMessaging = on;
1012 return oldval;
1013 }
1014
1015 /* DW D Watson added to end of file */
1016
1017 DXLError
exDXLBeginMacroDefinition(DXLConnection * conn,const char * mhdr)1018 exDXLBeginMacroDefinition(DXLConnection *conn, const char *mhdr)
1019 {
1020 int sts = 0;
1021 DXLPacketTypeEnum ptype;
1022
1023 if (conn->dxuiConnected)
1024 {
1025 return ERROR;
1026 }
1027 else
1028 {
1029 conn->macroDef = TRUE;
1030 ptype = PACK_MACRODEF;
1031 sts = DXLSendPacket(conn,ptype,0);
1032 if (sts < 0)
1033 return ERROR;
1034 DXLSendUnpacketized(conn, mhdr);
1035 DXLSendUnpacketized(conn, "{\n");
1036
1037 }
1038 return OK;
1039
1040 }
1041
1042 DXLError
exDXLEndMacroDefinition(DXLConnection * conn)1043 exDXLEndMacroDefinition(DXLConnection *conn)
1044 {
1045 int sts = 0;
1046
1047 if (conn->dxuiConnected)
1048 {
1049 return ERROR;
1050 }
1051 else
1052 {
1053 if (!conn->macroDef) {
1054 fprintf(stderr,"exDXLEndMacroDefinition: not valid before exDXLBeginMacroDefinition()\n");
1055 return ERROR;
1056 } /* endif */
1057 conn->macroDef = FALSE;
1058 sts = DXLSendUnpacketized(conn,"}\n|\n");
1059 if (sts < 0)
1060 return ERROR;
1061
1062 }
1063
1064 if (conn->synchronous)
1065 if (!DXLSync(conn))
1066 return ERROR;
1067
1068 return OK;
1069 }
1070