diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libplumb/event.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libplumb/event.c')
-rwxr-xr-x | sys/src/libplumb/event.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/sys/src/libplumb/event.c b/sys/src/libplumb/event.c new file mode 100755 index 000000000..36a95d687 --- /dev/null +++ b/sys/src/libplumb/event.c @@ -0,0 +1,108 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <event.h> +#include "plumb.h" + +typedef struct EQueue EQueue; + +struct EQueue +{ + int id; + char *buf; + int nbuf; + EQueue *next; +}; + +static EQueue *equeue; +static Lock eqlock; + +static +int +partial(int id, Event *e, uchar *b, int n) +{ + EQueue *eq, *p; + int nmore; + + lock(&eqlock); + for(eq = equeue; eq != nil; eq = eq->next) + if(eq->id == id) + break; + unlock(&eqlock); + if(eq == nil) + return 0; + /* partial message exists for this id */ + eq->buf = realloc(eq->buf, eq->nbuf+n); + if(eq->buf == nil) + drawerror(display, "eplumb: cannot allocate buffer"); + memmove(eq->buf+eq->nbuf, b, n); + eq->nbuf += n; + e->v = plumbunpackpartial((char*)eq->buf, eq->nbuf, &nmore); + if(nmore == 0){ /* no more to read in this message */ + lock(&eqlock); + if(eq == equeue) + equeue = eq->next; + else{ + for(p = equeue; p!=nil && p->next!=eq; p = p->next) + ; + if(p == nil) + drawerror(display, "eplumb: bad event queue"); + p->next = eq->next; + } + unlock(&eqlock); + free(eq->buf); + free(eq); + } + return 1; +} + +static +void +addpartial(int id, char *b, int n) +{ + EQueue *eq; + + eq = malloc(sizeof(EQueue)); + if(eq == nil) + return; + eq->id = id; + eq->nbuf = n; + eq->buf = malloc(n); + if(eq->buf == nil){ + free(eq); + return; + } + memmove(eq->buf, b, n); + lock(&eqlock); + eq->next = equeue; + equeue = eq; + unlock(&eqlock); +} + +static +int +plumbevent(int id, Event *e, uchar *b, int n) +{ + int nmore; + + if(partial(id, e, b, n) == 0){ + /* no partial message already waiting for this id */ + e->v = plumbunpackpartial((char*)b, n, &nmore); + if(nmore > 0) /* incomplete message */ + addpartial(id, (char*)b, n); + } + if(e->v == nil) + return 0; + return id; +} + +int +eplumb(int key, char *port) +{ + int fd; + + fd = plumbopen(port, OREAD|OCEXEC); + if(fd < 0) + return -1; + return estartfn(key, fd, 8192, plumbevent); +} |