blob: 36a95d687f882f4cac738da882a22788bde65f01 [file] [log] [blame]
rsc3d7e9092003-10-14 02:35:00 +00001#include <u.h>
2#include <libc.h>
3#include <draw.h>
4#include <event.h>
5#include "plumb.h"
6
7typedef struct EQueue EQueue;
8
9struct EQueue
10{
11 int id;
12 char *buf;
13 int nbuf;
14 EQueue *next;
15};
16
17static EQueue *equeue;
18static Lock eqlock;
19
20static
21int
22partial(int id, Event *e, uchar *b, int n)
23{
24 EQueue *eq, *p;
25 int nmore;
26
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}
58
59static
60void
61addpartial(int id, char *b, int n)
62{
63 EQueue *eq;
64
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}
81
82static
83int
84plumbevent(int id, Event *e, uchar *b, int n)
85{
86 int nmore;
87
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}
98
99int
100eplumb(int key, char *port)
101{
102 int fd;
103
104 fd = plumbopen(port, OREAD|OCEXEC);
105 if(fd < 0)
106 return -1;
107 return estartfn(key, fd, 8192, plumbevent);
108}