diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2025-03-22 05:53:08 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska@appnovation.com> | 2025-03-22 05:53:08 +0000 |
| commit | 9cd4e0d1902ebb196ebd53ed7ee88e6689d801b7 (patch) | |
| tree | ab44d569dce124541085629f6dbe0cc27b1da0fa /src/tipideed/stream.c | |
| parent | 53fdbac9da06a0dfb3f2821f7c7384001eea4f68 (diff) | |
| download | tipidee-9cd4e0d1902ebb196ebd53ed7ee88e6689d801b7.tar.gz | |
Add cgi streaming
WILDLY UNTESTED, don't use this commit, probably.
Also, autochunk hasn't been implemented yet.
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/tipideed/stream.c')
| -rw-r--r-- | src/tipideed/stream.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/tipideed/stream.c b/src/tipideed/stream.c new file mode 100644 index 0000000..7323c93 --- /dev/null +++ b/src/tipideed/stream.c @@ -0,0 +1,133 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> + +#ifdef SKALIBS_HASSPLICE + +#include <skalibs/nonposix.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdint.h> +#include <unistd.h> + +#include <skalibs/allreadwrite.h> +#include <skalibs/strerr.h> +#include <skalibs/tai.h> +#include <skalibs/djbunix.h> +#include <skalibs/unix-timed.h> + +#include "tipideed-internal.h" + +struct fixed_info_s +{ + int fd ; + size_t n ; +} ; + +static int fixed_getfd (void *b) +{ + struct fixed_info_s *si = b ; + return si->fd ; +} + +static ssize_t fixed_get (void *b) +{ + struct fixed_info_s *si = b ; + while (si->n) + { + ssize_t r = sanitize_read(splice(si->fd, 0, 1, 0, si->n, SPLICE_F_NONBLOCK)) ; + if (r == -1) break ; + if (!r) return 0 ; + si->n -= r ; + } + return si->n ? -1 : 1 ; +} + +void stream_fixed (int fd, size_t n, char const *fn) +{ + tain deadline ; + struct fixed_info_s si = { .fd = fd, .n = n } ; + tain_add_g(&deadline, tain_less(&g.writetto, &g.cgitto) ? &g.cgitto : &g.writetto) ; + if (timed_get_g(&si, &fixed_getfd, &fixed_get, &deadline) < 0) + strerr_diefu3sys(111, "splice from ", fn, " to stdout") ; +} + +void stream_infinite (int fd, char const *fn) +{ + ssize_t r ; + + /* only works when fd is a pipe, which is the case for cgi; fcgi/scgi will need refactoring */ + /* XXX: ignores timeouts, but this is just TOO GOOD to pass up */ + /* no really, it is just optimal in 99.9% of cases, it is WORTH IT */ + + while ((r = splice(fd, 0, 1, 0, 65536, SPLICE_F_MORE)) > 0) ; + + /* You WISH you had written that line of code */ + + if (r == -1) strerr_diefu3sys(111, "splice from ", fn, " to stdout") ; +} + +#else + +#include <sys/uio.h> +#include <unistd.h> +#include <stdint.h> + +#include <skalibs/uint64.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> + +#include "tipideed-internal.h" + +void stream_fixed (int fd, size_t n, char const *fn) +{ + tain deadline ; + struct iovec v[2] ; + size_t r ; + if (!n) goto flushit ; + fillit: + buffer_wpeek(buffer_1, v) ; + siovec_trunc(v, 2, n) ; + tain_add_g(&deadline, &g.cgitto) ; + r = timed_readv_g(fd, v, 2, &deadline) ; + if (r == -1) strerr_diefu2sys(111, "read from resource ", fn) ; + if (!r) strerr_dief3x(111, "resource ", fn, " provided less content than advertised in Content-Length") ; + buffer_wseek(buffer_1, r) ; + n -= r ; + flushit: + tain_add_g(&deadline, &g.writetto) ; + if (!buffer_timed_flush_g(buffer_1, &deadline)) + strerr_diefu1sys(111, "write to stdout") ; + if (n) goto fillit ; +} + +void stream_infinite (int fd, char const *fn) +{ + tain deadline ; + struct iovec v[2] ; + size_t r ; + for (;;) + { + buffer_wpeek(buffer_1, v) ; + tain_add_g(&deadline, &g.cgitto) ; + r = timed_readv_g(fd, v, 2, &deadline) ; + if (r == -1) strerr_diefu2sys(111, "read from resource ", fn) ; + if (!r) break ; + tain_add_g(&deadline, &g.writetto) ; + if (!buffer_timed_flush_g(buffer_1, &deadline)) + strerr_diefu1sys(111, "write to stdout") ; + } +} + +#endif + + +#include <skalibs/buffer.h> + +void stream_autochunk (buffer *b, char const *fn) +{ +} |
