aboutsummaryrefslogtreecommitdiffstats
path: root/src/tipideed/stream.c
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2025-03-22 05:53:08 +0000
committerLaurent Bercot <ska@appnovation.com>2025-03-22 05:53:08 +0000
commit9cd4e0d1902ebb196ebd53ed7ee88e6689d801b7 (patch)
treeab44d569dce124541085629f6dbe0cc27b1da0fa /src/tipideed/stream.c
parent53fdbac9da06a0dfb3f2821f7c7384001eea4f68 (diff)
downloadtipidee-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.c133
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)
+{
+}