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 }