URI:
       tevent.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tevent.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 }