accept.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /* shttpd - accept HTTP connections
  2. Copyright (C) 2018 Ariadne Devos
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. #include "worker.h"
  14. #include "fd.h"
  15. #include <sHT/bugs.h>
  16. #include <sHT/compiler.h>
  17. #include <sHT/nospec.h>
  18. #include <sHT/resource.h>
  19. #include <sHT/stream.h>
  20. #include <sHT/accept.h>
  21. #include <string.h>
  22. /* TODO: configuration, errno handling in task/accept.c, task/sockrw.c */
  23. static const char test_message[] =
  24. "HTTP/1.1 200 OK\r\n"
  25. "Server: sHTTPd\r\n"
  26. "Connection: Close\r\n"
  27. "Content-Type: text/plain\r\n"
  28. "Content-Language: en\r\n"
  29. "\r\n"
  30. "Hello!";
  31. struct sHT_task_stream *
  32. sHT_accept_subtask(struct sHT_worker *worker, struct sHT_task_accept *task)
  33. {
  34. /* TODO: allow different settings for different TCP ports */
  35. return sHT_alloc(worker->free_streams);
  36. }
  37. void
  38. sHT_accept_abort(struct sHT_worker *worker, struct sHT_task_accept *task, struct sHT_task_stream *subtask)
  39. {
  40. sHT_free(worker->free_streams, subtask);
  41. }
  42. void
  43. sHT_accept_logic(struct sHT_worker *worker, struct sHT_task_accept *task, struct sHT_task_stream *subtask)
  44. {
  45. _Bool oops = sHT_init_stream(worker->papers, &subtask->stream);
  46. if (sHT_unlikely(sHT_test_hidden(oops, oops))) {
  47. /* XXX Spectre: what if this branch is ignored?
  48. Then a NULL paper might be written to,
  49. might be problematic. */
  50. sHT_close(subtask->stream.fd);
  51. sHT_free(worker->free_streams, subtask);
  52. return;
  53. }
  54. /* TODO: consider patching the kernel to allow 'reservation' of
  55. epoll events. TODO: reconsider this previous TODO. */
  56. oops = sHT_install_edge_trigger(worker->watches, subtask->stream.fd, &subtask->task);
  57. if (sHT_unlikely(sHT_test_hidden(oops, oops))) {
  58. /* Spectre: a speculatively missing watch isn't problematic.
  59. For a teeny while,
  60. the task won't run although it should be. */
  61. sHT_free_stream(worker->papers, &subtask->stream);
  62. sHT_close(subtask->stream.fd);
  63. sHT_free(worker->free_streams, subtask);
  64. return;
  65. }
  66. sHT_assert(subtask->stream.to_write.offset == 0);
  67. sHT_assert(subtask->stream.to_write.length == 0);
  68. sHT_assert(sizeof(test_message) <= sHT_PAPER_SIZE);
  69. memcpy(subtask->stream.to_write.first, test_message, sizeof(test_message));
  70. sHT_init_task(&subtask->task);
  71. subtask->task.epollflags |= EPOLLIN | EPOLLOUT;
  72. subtask->stream.to_write.length = sizeof(test_message);
  73. }