event.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <event.h>
  5. #include "plumb.h"
  6. typedef struct EQueue EQueue;
  7. struct EQueue
  8. {
  9. int id;
  10. char *buf;
  11. int nbuf;
  12. EQueue *next;
  13. };
  14. static EQueue *equeue;
  15. static Lock eqlock;
  16. static
  17. int
  18. partial(int id, Event *e, uchar *b, int n)
  19. {
  20. EQueue *eq, *p;
  21. int nmore;
  22. lock(&eqlock);
  23. for(eq = equeue; eq != nil; eq = eq->next)
  24. if(eq->id == id)
  25. break;
  26. unlock(&eqlock);
  27. if(eq == nil)
  28. return 0;
  29. /* partial message exists for this id */
  30. eq->buf = realloc(eq->buf, eq->nbuf+n);
  31. if(eq->buf == nil)
  32. drawerror(display, "eplumb: cannot allocate buffer");
  33. memmove(eq->buf+eq->nbuf, b, n);
  34. eq->nbuf += n;
  35. e->v = plumbunpackpartial((char*)eq->buf, eq->nbuf, &nmore);
  36. if(nmore == 0){ /* no more to read in this message */
  37. lock(&eqlock);
  38. if(eq == equeue)
  39. equeue = eq->next;
  40. else{
  41. for(p = equeue; p!=nil && p->next!=eq; p = p->next)
  42. ;
  43. if(p == nil)
  44. drawerror(display, "eplumb: bad event queue");
  45. p->next = eq->next;
  46. }
  47. unlock(&eqlock);
  48. free(eq->buf);
  49. free(eq);
  50. }
  51. return 1;
  52. }
  53. static
  54. void
  55. addpartial(int id, char *b, int n)
  56. {
  57. EQueue *eq;
  58. eq = malloc(sizeof(EQueue));
  59. if(eq == nil)
  60. return;
  61. eq->id = id;
  62. eq->nbuf = n;
  63. eq->buf = malloc(n);
  64. if(eq->buf == nil){
  65. free(eq);
  66. return;
  67. }
  68. memmove(eq->buf, b, n);
  69. lock(&eqlock);
  70. eq->next = equeue;
  71. equeue = eq;
  72. unlock(&eqlock);
  73. }
  74. static
  75. int
  76. plumbevent(int id, Event *e, uchar *b, int n)
  77. {
  78. int nmore;
  79. if(partial(id, e, b, n) == 0){
  80. /* no partial message already waiting for this id */
  81. e->v = plumbunpackpartial((char*)b, n, &nmore);
  82. if(nmore > 0) /* incomplete message */
  83. addpartial(id, (char*)b, n);
  84. }
  85. if(e->v == nil)
  86. return 0;
  87. return id;
  88. }
  89. int
  90. eplumb(int key, char *port)
  91. {
  92. int fd;
  93. fd = plumbopen(port, OREAD|OCEXEC);
  94. if(fd < 0)
  95. return -1;
  96. return estartfn(key, fd, 8192, plumbevent);
  97. }