smblisten.c 2.5 KB

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