commit 5b302645b69e633643b7810d0de85cec0b54973d from: Omar Polo date: Thu Dec 21 22:52:16 2023 UTC http: add illimitate buffering commit - 1106be5093dfa29041632c36c853c52a0bce1ce7 commit + 5b302645b69e633643b7810d0de85cec0b54973d blob - /dev/null blob + f8ba6cc8e8a68459d60aa45a053f8643c8b14c5c (mode 644) --- /dev/null +++ http/buf.ha @@ -0,0 +1,87 @@ +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +use io; + +def chunksize = 1024; + +export type dynstream = struct { + vtable: io::stream, + dst: io::handle, + buf: []u8, + length: size, +}; + +const dynstream_vtable: io::vtable = io::vtable { + writer = &dynstream_write, + closer = &dynstream_close, + ... +}; + +fn new_dynstream(s: io::handle) dynstream = { + return dynstream { + vtable = &dynstream_vtable, + dst = s, + ... + }; +}; + +fn dynstream_resize(w: *dynstream, n: size) void = { + let cap = len(w.buf); + for (!(w.length + n < cap)) { + cap += chunksize; + }; + + if (cap == len(w.buf)) + return; + + let newbuf: []u8 = alloc([0...], cap); + newbuf[0..len(w.buf)] = w.buf; + free(w.buf); + w.buf = newbuf; +}; + +fn dynstream_write(s: *io::stream, buf: const []u8) (size | io::error) = { + let w = s: *dynstream; + + dynstream_resize(w, len(buf)); + + w.buf[w.length..(w.length+len(buf))] = buf; + w.length += len(buf); + + return len(buf); +}; + +fn dynstream_close(s: *io::stream) (void | io::error) = { + let w = s: *dynstream; + + free(w.buf); +}; + +fn dynstream_flush(w: *dynstream) (void | io::error) = { + let wrote = io::write(w.dst, w.buf[0..w.length])?; + + let n = w.length - wrote; + w.buf[0..n] = w.buf[wrote..w.length]; + w.length -= wrote; +}; blob - 1c1c4a2d51a1b79d5d0c93cda9e9ac92e396ea00 blob + dbc9022927b46e6928381adea2b116b4ba305efa --- http/reswriter.ha +++ http/reswriter.ha @@ -21,21 +21,17 @@ // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. -use bufio; use fmt; use io; use log; export type reswriter = struct { vtable: io::stream, - dst: bufio::stream, + dst: dynstream, hdrdone: bool, // done with the headers done: bool, // done with the response wrotedone: bool, // written the done chunk chunked: bool, // chunk the reply - - // XXX - buf: []u8, }; const reswriter_vtable: io::vtable = io::vtable { @@ -45,20 +41,11 @@ const reswriter_vtable: io::vtable = io::vtable { }; fn new_reswriter(s: io::handle) reswriter = { - let buf: []u8 = alloc([0...], 1024); - - // XXX using a bufio::stream means we can't append more than - // len(buf) data... - let w = reswriter { + return reswriter { vtable = &reswriter_vtable, - dst = bufio::init(s, [], buf), - buf = buf, + dst = new_dynstream(s), ... }; - - bufio::setflush(&w.dst, []); - - return w; }; fn reswriter_write(s: *io::stream, buf: const []u8) (size | io::error) = { @@ -91,14 +78,13 @@ fn reswriter_flush(res: *reswriter) (void | io::error) fmt::fprint(&res.dst, "0\r\n\r\n")?; res.wrotedone = true; }; - bufio::flush(&res.dst)?; + dynstream_flush(&res.dst)?; }; fn reswriter_close(s: *io::stream) (void | io::error) = { let w = s: *reswriter; io::close(&w.dst)?; - free(w.buf); }; export fn reply(