relay.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * uhttpd - Tiny single-threaded httpd
  3. *
  4. * Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org>
  5. * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for any
  8. * purpose with or without fee is hereby granted, provided that the above
  9. * copyright notice and this permission notice appear in all copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  12. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  14. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. #include <signal.h>
  20. #include "uhttpd.h"
  21. void uh_relay_free(struct relay *r)
  22. {
  23. if (!r->cl)
  24. return;
  25. if (r->proc.pending)
  26. kill(r->proc.pid, SIGKILL);
  27. uloop_timeout_cancel(&r->timeout);
  28. uloop_process_delete(&r->proc);
  29. ustream_free(&r->sfd.stream);
  30. close(r->sfd.fd.fd);
  31. r->cl = NULL;
  32. }
  33. void uh_relay_close(struct relay *r, int ret)
  34. {
  35. struct ustream *us = &r->sfd.stream;
  36. if (!us->notify_read)
  37. return;
  38. us->notify_read = NULL;
  39. us->notify_write = NULL;
  40. us->notify_state = NULL;
  41. if (r->close)
  42. r->close(r, ret);
  43. }
  44. static void relay_error(struct relay *r)
  45. {
  46. struct ustream *s = &r->sfd.stream;
  47. int len;
  48. r->error = true;
  49. s->eof = true;
  50. ustream_get_read_buf(s, &len);
  51. if (len)
  52. ustream_consume(s, len);
  53. ustream_state_change(s);
  54. }
  55. static void relay_process_headers(struct relay *r)
  56. {
  57. struct ustream *s = &r->sfd.stream;
  58. char *buf, *newline;
  59. int len;
  60. if (!r->header_cb)
  61. return;
  62. while (r->header_cb) {
  63. int line_len;
  64. char *val;
  65. buf = ustream_get_read_buf(s, &len);
  66. if (!buf || !len)
  67. break;
  68. newline = strchr(buf, '\n');
  69. if (!newline)
  70. break;
  71. line_len = newline + 1 - buf;
  72. if (newline > buf && newline[-1] == '\r')
  73. newline--;
  74. *newline = 0;
  75. if (newline == buf) {
  76. r->header_cb = NULL;
  77. if (r->header_end)
  78. r->header_end(r);
  79. ustream_consume(s, line_len);
  80. break;
  81. }
  82. val = uh_split_header(buf);
  83. if (!val) {
  84. relay_error(r);
  85. return;
  86. }
  87. r->header_cb(r, buf, val);
  88. ustream_consume(s, line_len);
  89. }
  90. }
  91. static void relay_read_cb(struct ustream *s, int bytes)
  92. {
  93. struct relay *r = container_of(s, struct relay, sfd.stream);
  94. struct client *cl = r->cl;
  95. struct ustream *us = cl->us;
  96. char *buf;
  97. int len;
  98. if (r->process_done)
  99. uloop_timeout_set(&r->timeout, 1);
  100. if (!r->error)
  101. relay_process_headers(r);
  102. if (r->header_cb) {
  103. /*
  104. * if eof, ensure that remaining data is discarded, so the
  105. * state change cb will tear down the stream
  106. */
  107. if (s->eof)
  108. relay_error(r);
  109. return;
  110. }
  111. if (!s->eof && ustream_pending_data(us, true)) {
  112. ustream_set_read_blocked(s, true);
  113. return;
  114. }
  115. buf = ustream_get_read_buf(s, &len);
  116. if (!buf || !len)
  117. return;
  118. if (!r->skip_data)
  119. uh_chunk_write(cl, buf, len);
  120. ustream_consume(s, len);
  121. }
  122. static void relay_close_if_done(struct uloop_timeout *timeout)
  123. {
  124. struct relay *r = container_of(timeout, struct relay, timeout);
  125. struct ustream *s = &r->sfd.stream;
  126. while (ustream_poll(&r->sfd.stream));
  127. if (!(r->process_done || s->eof) || (ustream_pending_data(s, false) && !r->header_cb))
  128. return;
  129. uh_relay_close(r, r->ret);
  130. }
  131. static void relay_state_cb(struct ustream *s)
  132. {
  133. struct relay *r = container_of(s, struct relay, sfd.stream);
  134. if (r->process_done)
  135. uloop_timeout_set(&r->timeout, 1);
  136. }
  137. static void relay_proc_cb(struct uloop_process *proc, int ret)
  138. {
  139. struct relay *r = container_of(proc, struct relay, proc);
  140. r->process_done = true;
  141. r->ret = ret;
  142. uloop_timeout_set(&r->timeout, 1);
  143. }
  144. void uh_relay_kill(struct client *cl, struct relay *r)
  145. {
  146. struct ustream *us = &r->sfd.stream;
  147. kill(r->proc.pid, SIGKILL);
  148. us->eof = true;
  149. ustream_state_change(us);
  150. }
  151. void uh_relay_open(struct client *cl, struct relay *r, int fd, int pid)
  152. {
  153. struct ustream *us = &r->sfd.stream;
  154. r->cl = cl;
  155. us->notify_read = relay_read_cb;
  156. us->notify_state = relay_state_cb;
  157. us->string_data = true;
  158. ustream_fd_init(&r->sfd, fd);
  159. r->proc.pid = pid;
  160. r->proc.cb = relay_proc_cb;
  161. uloop_process_add(&r->proc);
  162. r->timeout.cb = relay_close_if_done;
  163. }