plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

event.c (1861B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <draw.h>
      4 #include <event.h>
      5 #include "plumb.h"
      6 
      7 typedef struct EQueue EQueue;
      8 
      9 struct EQueue
     10 {
     11 	int		id;
     12 	char		*buf;
     13 	int		nbuf;
     14 	EQueue	*next;
     15 };
     16 
     17 static	EQueue	*equeue;
     18 static	Lock		eqlock;
     19 
     20 static
     21 int
     22 partial(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 
     59 static
     60 void
     61 addpartial(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 
     82 static
     83 int
     84 plumbevent(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 
     99 int
    100 eplumb(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 }