smblisten.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "headers.h"
  10. static struct {
  11. int thread;
  12. QLock;
  13. char adir[NETPATHLEN];
  14. int acfd;
  15. char ldir[NETPATHLEN];
  16. int lcfd;
  17. SMBCIFSACCEPTFN *accept;
  18. } tcp = { -1 };
  19. typedef struct Session Session;
  20. enum { Connected, Dead };
  21. struct Session {
  22. SmbCifsSession;
  23. int thread;
  24. Session *next;
  25. int state;
  26. SMBCIFSWRITEFN *write;
  27. };
  28. static struct {
  29. QLock;
  30. Session *head;
  31. } sessions;
  32. typedef struct Listen Listen;
  33. static void
  34. deletesession(Session *s)
  35. {
  36. Session **sp;
  37. close(s->fd);
  38. qlock(&sessions);
  39. for (sp = &sessions.head; *sp && *sp != s; sp = &(*sp)->next)
  40. ;
  41. if (*sp)
  42. *sp = s->next;
  43. qunlock(&sessions);
  44. free(s);
  45. }
  46. static void
  47. tcpreader(void *a)
  48. {
  49. Session *s = a;
  50. uint8_t *buf;
  51. int buflen = smbglobals.maxreceive + 4;
  52. buf = nbemalloc(buflen);
  53. for (;;) {
  54. int n;
  55. uint8_t flags;
  56. uint16_t length;
  57. n = readn(s->fd, buf, 4);
  58. if (n != 4) {
  59. die:
  60. free(buf);
  61. if (s->state == Connected)
  62. (*s->write)(s, nil, -1);
  63. deletesession(s);
  64. return;
  65. }
  66. flags = buf[1];
  67. length = nhgets(buf + 2) | ((flags & 1) << 16);
  68. if (length > buflen - 4) {
  69. print("nbss: too much data (%u)\n", length);
  70. goto die;
  71. }
  72. n = readn(s->fd, buf + 4, length);
  73. if (n != length)
  74. goto die;
  75. if (s->state == Connected) {
  76. if ((*s->write)(s, buf + 4, length) != 0) {
  77. s->state = Dead;
  78. goto die;
  79. }
  80. }
  81. }
  82. }
  83. static Session *
  84. createsession(int fd)
  85. {
  86. Session *s;
  87. s = smbemalloc(sizeof(Session));
  88. s->fd = fd;
  89. s->state = Connected;
  90. qlock(&sessions);
  91. if (!(*tcp.accept)(s, &s->write)) {
  92. qunlock(&sessions);
  93. free(s);
  94. return nil;
  95. }
  96. s->thread = procrfork(tcpreader, s, 32768, RFNAMEG);
  97. if (s->thread < 0) {
  98. qunlock(&sessions);
  99. (*s->write)(s, nil, -1);
  100. free(s);
  101. return nil;
  102. }
  103. s->next = sessions.head;
  104. sessions.head = s;
  105. qunlock(&sessions);
  106. return s;
  107. }
  108. static void
  109. tcplistener(void *)
  110. {
  111. for (;;) {
  112. int dfd;
  113. char ldir[NETPATHLEN];
  114. int lcfd;
  115. //print("cifstcplistener: listening\n");
  116. lcfd = listen(tcp.adir, ldir);
  117. //print("cifstcplistener: contact\n");
  118. if (lcfd < 0) {
  119. die:
  120. qlock(&tcp);
  121. close(tcp.acfd);
  122. tcp.thread = -1;
  123. qunlock(&tcp);
  124. return;
  125. }
  126. dfd = accept(lcfd, ldir);
  127. close(lcfd);
  128. if (dfd < 0)
  129. goto die;
  130. if (createsession(dfd) == nil)
  131. close(dfd);
  132. }
  133. }
  134. int
  135. smblistencifs(SMBCIFSACCEPTFN *accept)
  136. {
  137. qlock(&tcp);
  138. if (tcp.thread < 0) {
  139. tcp.acfd = announce("tcp!*!cifs", tcp.adir);
  140. if (tcp.acfd < 0) {
  141. print("smblistentcp: can't announce: %r\n");
  142. qunlock(&tcp);
  143. return -1;
  144. }
  145. tcp.thread = proccreate(tcplistener, nil, 16384);
  146. }
  147. tcp.accept = accept;
  148. qunlock(&tcp);
  149. return 0;
  150. }