stream.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. // Copyright © 2018-2019 Ariadne Devos
  3. /* s2 -- process HTTP input */
  4. #include "fd.h"
  5. #include "worker.h"
  6. #include <sHT/resource.h>
  7. #include <sHT/scheduling.h>
  8. #include <sHT/stream.h>
  9. #include <sHT/test.h>
  10. #include <errno.h>
  11. #include <stddef.h>
  12. #include <sys/epoll.h>
  13. #include <sys/socket.h>
  14. #define sHTTPd_DONE sHT_STREAM_USER1
  15. __attribute__((nonnull (1, 2)))
  16. static void
  17. sHTTPd_close_connection(struct sHT_worker *worker, struct sHT_task_stream *task)
  18. {
  19. sHT_close(task->stream.fd);
  20. sHT_free(worker->free_streams, task);
  21. }
  22. void
  23. sHT_socket_task(struct sHT_worker *worker, struct sHT_task_stream *task)
  24. {
  25. if (!sHT_and_any(task->task.epollflags, EPOLLIN | EPOLLOUT))
  26. return;
  27. /* @var{sHT_socket_mayread} and @var{sHT_socket_maywrite} don't
  28. leak information to the compiler, so no @var{sHT_test_hidden}
  29. magic is required. Their values may also speculatively be wrong,
  30. but it is merely advisory, improving performance by skipping
  31. code. */
  32. /* Read request headers */
  33. if (sHT_socket_mayread(task))
  34. sHT_socket_readsome_tcp(worker, task);
  35. /* Output headers, output response */
  36. if (sHT_socket_maywrite(task))
  37. sHT_socket_sendsome_tcp(worker, task);
  38. /* TODO: do HTTP */
  39. /* A graceful shutdown */
  40. if (sHT_zero_p(task->stream.to_write.length))
  41. /* The file descriptor remains intact, so no Spectre issues */
  42. shutdown(task->stream.fd, SHUT_WR);
  43. if (sHT_and_any(task->stream.flags, sHT_STREAM_RESET_GRACEFUL | sHT_STREAM_RESET_BLUNT | sHT_STREAM_WRITE_EOF | sHTTPd_DONE))
  44. sHTTPd_close_connection(worker, task);
  45. if (sHT_and_any(task->task.flags, sHT_TASK_SCHEDULE)) {
  46. task->task.flags &= ~sHT_TASK_SCHEDULE;
  47. sHT_qadd_try(&worker->todo.queue, &task->task);
  48. }
  49. }