Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <event.h>
5 #include "plumb.h"
7 typedef struct EQueue EQueue;
9 struct EQueue
10 {
11 int id;
12 char *buf;
13 int nbuf;
14 EQueue *next;
15 };
17 static EQueue *equeue;
18 static Lock eqlock;
20 static
21 int
22 partial(int id, Event *e, uchar *b, int n)
23 {
24 EQueue *eq, *p;
25 int nmore;
27 lock(&eqlock);
28 for(eq = equeue; eq != nil; eq = eq->next)
29 if(eq->id == id)
30 break;
31 unlock(&eqlock);
32 if(eq == nil)
33 return 0;
34 /* partial message exists for this id */
35 eq->buf = realloc(eq->buf, eq->nbuf+n);
36 if(eq->buf == nil)
37 drawerror(display, "eplumb: cannot allocate buffer");
38 memmove(eq->buf+eq->nbuf, b, n);
39 eq->nbuf += n;
40 e->v = plumbunpackpartial((char*)eq->buf, eq->nbuf, &nmore);
41 if(nmore == 0){ /* no more to read in this message */
42 lock(&eqlock);
43 if(eq == equeue)
44 equeue = eq->next;
45 else{
46 for(p = equeue; p!=nil && p->next!=eq; p = p->next)
47 ;
48 if(p == nil)
49 drawerror(display, "eplumb: bad event queue");
50 p->next = eq->next;
51 }
52 unlock(&eqlock);
53 free(eq->buf);
54 free(eq);
55 }
56 return 1;
57 }
59 static
60 void
61 addpartial(int id, char *b, int n)
62 {
63 EQueue *eq;
65 eq = malloc(sizeof(EQueue));
66 if(eq == nil)
67 return;
68 eq->id = id;
69 eq->nbuf = n;
70 eq->buf = malloc(n);
71 if(eq->buf == nil){
72 free(eq);
73 return;
74 }
75 memmove(eq->buf, b, n);
76 lock(&eqlock);
77 eq->next = equeue;
78 equeue = eq;
79 unlock(&eqlock);
80 }
82 static
83 int
84 plumbevent(int id, Event *e, uchar *b, int n)
85 {
86 int nmore;
88 if(partial(id, e, b, n) == 0){
89 /* no partial message already waiting for this id */
90 e->v = plumbunpackpartial((char*)b, n, &nmore);
91 if(nmore > 0) /* incomplete message */
92 addpartial(id, (char*)b, n);
93 }
94 if(e->v == nil)
95 return 0;
96 return id;
97 }
99 int
100 eplumb(int key, char *port)
102 int fd;
104 fd = plumbopen(port, OREAD|OCEXEC);
105 if(fd < 0)
106 return -1;
107 return estartfn(key, fd, 8192, plumbevent);