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