xref: /plan9/sys/src/libplumb/event.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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