1584Salexander.borisov@nginx.com 2584Salexander.borisov@nginx.com /* 3584Salexander.borisov@nginx.com * Copyright (C) Alexander Borisov 4584Salexander.borisov@nginx.com * Copyright (C) NGINX, Inc. 5584Salexander.borisov@nginx.com */ 6584Salexander.borisov@nginx.com 7584Salexander.borisov@nginx.com #include <ruby/nxt_ruby.h> 8743Smax.romanov@nginx.com #include <nxt_unit.h> 9584Salexander.borisov@nginx.com 10584Salexander.borisov@nginx.com 111687Smax.romanov@nginx.com static VALUE nxt_ruby_stream_io_new(VALUE class, VALUE arg); 12584Salexander.borisov@nginx.com static VALUE nxt_ruby_stream_io_initialize(int argc, VALUE *argv, VALUE self); 131337Smax.romanov@nginx.com static VALUE nxt_ruby_stream_io_gets(VALUE obj); 141337Smax.romanov@nginx.com static VALUE nxt_ruby_stream_io_each(VALUE obj); 15584Salexander.borisov@nginx.com static VALUE nxt_ruby_stream_io_read(VALUE obj, VALUE args); 161337Smax.romanov@nginx.com static VALUE nxt_ruby_stream_io_rewind(VALUE obj); 17584Salexander.borisov@nginx.com static VALUE nxt_ruby_stream_io_puts(VALUE obj, VALUE args); 18584Salexander.borisov@nginx.com static VALUE nxt_ruby_stream_io_write(VALUE obj, VALUE args); 191687Smax.romanov@nginx.com nxt_inline long nxt_ruby_stream_io_s_write(nxt_ruby_ctx_t *rctx, VALUE val); 201337Smax.romanov@nginx.com static VALUE nxt_ruby_stream_io_flush(VALUE obj); 21*2093Sz.hong@f5.com static VALUE nxt_ruby_stream_io_close(VALUE obj); 22584Salexander.borisov@nginx.com 23584Salexander.borisov@nginx.com 24584Salexander.borisov@nginx.com VALUE 25584Salexander.borisov@nginx.com nxt_ruby_stream_io_input_init(void) 26584Salexander.borisov@nginx.com { 27584Salexander.borisov@nginx.com VALUE stream_io; 28584Salexander.borisov@nginx.com 291870So.canty@f5.com stream_io = rb_define_class("NGINX_Unit_Stream_IO_Read", rb_cObject); 301870So.canty@f5.com 311870So.canty@f5.com rb_undef_alloc_func(stream_io); 32584Salexander.borisov@nginx.com 33584Salexander.borisov@nginx.com rb_gc_register_address(&stream_io); 34584Salexander.borisov@nginx.com 35584Salexander.borisov@nginx.com rb_define_singleton_method(stream_io, "new", nxt_ruby_stream_io_new, 1); 361235Sigor@sysoev.ru rb_define_method(stream_io, "initialize", 371235Sigor@sysoev.ru nxt_ruby_stream_io_initialize, -1); 38584Salexander.borisov@nginx.com rb_define_method(stream_io, "gets", nxt_ruby_stream_io_gets, 0); 39584Salexander.borisov@nginx.com rb_define_method(stream_io, "each", nxt_ruby_stream_io_each, 0); 40584Salexander.borisov@nginx.com rb_define_method(stream_io, "read", nxt_ruby_stream_io_read, -2); 41584Salexander.borisov@nginx.com rb_define_method(stream_io, "rewind", nxt_ruby_stream_io_rewind, 0); 42*2093Sz.hong@f5.com rb_define_method(stream_io, "close", nxt_ruby_stream_io_close, 0); 43584Salexander.borisov@nginx.com 44584Salexander.borisov@nginx.com return stream_io; 45584Salexander.borisov@nginx.com } 46584Salexander.borisov@nginx.com 47584Salexander.borisov@nginx.com 48584Salexander.borisov@nginx.com VALUE 49584Salexander.borisov@nginx.com nxt_ruby_stream_io_error_init(void) 50584Salexander.borisov@nginx.com { 51584Salexander.borisov@nginx.com VALUE stream_io; 52584Salexander.borisov@nginx.com 531870So.canty@f5.com stream_io = rb_define_class("NGINX_Unit_Stream_IO_Error", rb_cObject); 541870So.canty@f5.com 551870So.canty@f5.com rb_undef_alloc_func(stream_io); 56584Salexander.borisov@nginx.com 57584Salexander.borisov@nginx.com rb_gc_register_address(&stream_io); 58584Salexander.borisov@nginx.com 59584Salexander.borisov@nginx.com rb_define_singleton_method(stream_io, "new", nxt_ruby_stream_io_new, 1); 601235Sigor@sysoev.ru rb_define_method(stream_io, "initialize", 611235Sigor@sysoev.ru nxt_ruby_stream_io_initialize, -1); 62584Salexander.borisov@nginx.com rb_define_method(stream_io, "puts", nxt_ruby_stream_io_puts, -2); 63584Salexander.borisov@nginx.com rb_define_method(stream_io, "write", nxt_ruby_stream_io_write, -2); 64584Salexander.borisov@nginx.com rb_define_method(stream_io, "flush", nxt_ruby_stream_io_flush, 0); 65*2093Sz.hong@f5.com rb_define_method(stream_io, "close", nxt_ruby_stream_io_close, 0); 66584Salexander.borisov@nginx.com 67584Salexander.borisov@nginx.com return stream_io; 68584Salexander.borisov@nginx.com } 69584Salexander.borisov@nginx.com 70584Salexander.borisov@nginx.com 71584Salexander.borisov@nginx.com static VALUE 721687Smax.romanov@nginx.com nxt_ruby_stream_io_new(VALUE class, VALUE arg) 73584Salexander.borisov@nginx.com { 741687Smax.romanov@nginx.com VALUE self; 75584Salexander.borisov@nginx.com 761687Smax.romanov@nginx.com self = Data_Wrap_Struct(class, 0, 0, (void *) (uintptr_t) arg); 77584Salexander.borisov@nginx.com 78584Salexander.borisov@nginx.com rb_obj_call_init(self, 0, NULL); 79584Salexander.borisov@nginx.com 80584Salexander.borisov@nginx.com return self; 81584Salexander.borisov@nginx.com } 82584Salexander.borisov@nginx.com 83584Salexander.borisov@nginx.com 84584Salexander.borisov@nginx.com static VALUE 85584Salexander.borisov@nginx.com nxt_ruby_stream_io_initialize(int argc, VALUE *argv, VALUE self) 86584Salexander.borisov@nginx.com { 87584Salexander.borisov@nginx.com return self; 88584Salexander.borisov@nginx.com } 89584Salexander.borisov@nginx.com 90584Salexander.borisov@nginx.com 91584Salexander.borisov@nginx.com static VALUE 921337Smax.romanov@nginx.com nxt_ruby_stream_io_gets(VALUE obj) 93584Salexander.borisov@nginx.com { 94743Smax.romanov@nginx.com VALUE buf; 951398Smax.romanov@nginx.com ssize_t res; 961687Smax.romanov@nginx.com nxt_ruby_ctx_t *rctx; 97743Smax.romanov@nginx.com nxt_unit_request_info_t *req; 98584Salexander.borisov@nginx.com 991687Smax.romanov@nginx.com Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); 1001687Smax.romanov@nginx.com req = rctx->req; 101743Smax.romanov@nginx.com 102743Smax.romanov@nginx.com if (req->content_length == 0) { 103584Salexander.borisov@nginx.com return Qnil; 104584Salexander.borisov@nginx.com } 105584Salexander.borisov@nginx.com 1061398Smax.romanov@nginx.com res = nxt_unit_request_readline_size(req, SSIZE_MAX); 1071398Smax.romanov@nginx.com if (nxt_slow_path(res < 0)) { 108584Salexander.borisov@nginx.com return Qnil; 109584Salexander.borisov@nginx.com } 110584Salexander.borisov@nginx.com 1111398Smax.romanov@nginx.com buf = rb_str_buf_new(res); 112743Smax.romanov@nginx.com 1131398Smax.romanov@nginx.com if (nxt_slow_path(buf == Qnil)) { 1141398Smax.romanov@nginx.com return Qnil; 1151398Smax.romanov@nginx.com } 1161398Smax.romanov@nginx.com 1171398Smax.romanov@nginx.com res = nxt_unit_request_read(req, RSTRING_PTR(buf), res); 1181398Smax.romanov@nginx.com 1191398Smax.romanov@nginx.com rb_str_set_len(buf, res); 120584Salexander.borisov@nginx.com 121584Salexander.borisov@nginx.com return buf; 122584Salexander.borisov@nginx.com } 123584Salexander.borisov@nginx.com 124584Salexander.borisov@nginx.com 125584Salexander.borisov@nginx.com static VALUE 1261337Smax.romanov@nginx.com nxt_ruby_stream_io_each(VALUE obj) 127584Salexander.borisov@nginx.com { 128584Salexander.borisov@nginx.com VALUE chunk; 129584Salexander.borisov@nginx.com 130584Salexander.borisov@nginx.com if (rb_block_given_p() == 0) { 131584Salexander.borisov@nginx.com rb_raise(rb_eArgError, "Expected block on rack.input 'each' method"); 132584Salexander.borisov@nginx.com } 133584Salexander.borisov@nginx.com 134584Salexander.borisov@nginx.com for ( ;; ) { 1351337Smax.romanov@nginx.com chunk = nxt_ruby_stream_io_gets(obj); 136584Salexander.borisov@nginx.com 137584Salexander.borisov@nginx.com if (chunk == Qnil) { 138584Salexander.borisov@nginx.com return Qnil; 139584Salexander.borisov@nginx.com } 140584Salexander.borisov@nginx.com 141584Salexander.borisov@nginx.com rb_yield(chunk); 142584Salexander.borisov@nginx.com } 143584Salexander.borisov@nginx.com 144584Salexander.borisov@nginx.com return Qnil; 145584Salexander.borisov@nginx.com } 146584Salexander.borisov@nginx.com 147584Salexander.borisov@nginx.com 148584Salexander.borisov@nginx.com static VALUE 149584Salexander.borisov@nginx.com nxt_ruby_stream_io_read(VALUE obj, VALUE args) 150584Salexander.borisov@nginx.com { 1511687Smax.romanov@nginx.com VALUE buf; 1521687Smax.romanov@nginx.com long copy_size, u_size; 1531687Smax.romanov@nginx.com nxt_ruby_ctx_t *rctx; 154584Salexander.borisov@nginx.com 1551687Smax.romanov@nginx.com Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); 156584Salexander.borisov@nginx.com 1571687Smax.romanov@nginx.com copy_size = rctx->req->content_length; 158584Salexander.borisov@nginx.com 159584Salexander.borisov@nginx.com if (RARRAY_LEN(args) > 0 && TYPE(RARRAY_PTR(args)[0]) == T_FIXNUM) { 160584Salexander.borisov@nginx.com u_size = NUM2LONG(RARRAY_PTR(args)[0]); 161584Salexander.borisov@nginx.com 162584Salexander.borisov@nginx.com if (u_size < 0 || copy_size == 0) { 163584Salexander.borisov@nginx.com return Qnil; 164584Salexander.borisov@nginx.com } 165584Salexander.borisov@nginx.com 166584Salexander.borisov@nginx.com if (copy_size > u_size) { 167584Salexander.borisov@nginx.com copy_size = u_size; 168584Salexander.borisov@nginx.com } 169584Salexander.borisov@nginx.com } 170584Salexander.borisov@nginx.com 171584Salexander.borisov@nginx.com if (copy_size == 0) { 172584Salexander.borisov@nginx.com return rb_str_new_cstr(""); 173584Salexander.borisov@nginx.com } 174584Salexander.borisov@nginx.com 175584Salexander.borisov@nginx.com buf = rb_str_buf_new(copy_size); 176584Salexander.borisov@nginx.com 177584Salexander.borisov@nginx.com if (nxt_slow_path(buf == Qnil)) { 178584Salexander.borisov@nginx.com return Qnil; 179584Salexander.borisov@nginx.com } 180584Salexander.borisov@nginx.com 1811687Smax.romanov@nginx.com copy_size = nxt_unit_request_read(rctx->req, RSTRING_PTR(buf), copy_size); 182584Salexander.borisov@nginx.com 183584Salexander.borisov@nginx.com if (RARRAY_LEN(args) > 1 && TYPE(RARRAY_PTR(args)[1]) == T_STRING) { 184584Salexander.borisov@nginx.com 185584Salexander.borisov@nginx.com rb_str_set_len(RARRAY_PTR(args)[1], 0); 186584Salexander.borisov@nginx.com rb_str_cat(RARRAY_PTR(args)[1], RSTRING_PTR(buf), copy_size); 187584Salexander.borisov@nginx.com } 188584Salexander.borisov@nginx.com 189743Smax.romanov@nginx.com rb_str_set_len(buf, copy_size); 190584Salexander.borisov@nginx.com 191584Salexander.borisov@nginx.com return buf; 192584Salexander.borisov@nginx.com } 193584Salexander.borisov@nginx.com 194584Salexander.borisov@nginx.com 195584Salexander.borisov@nginx.com static VALUE 1961337Smax.romanov@nginx.com nxt_ruby_stream_io_rewind(VALUE obj) 197584Salexander.borisov@nginx.com { 198584Salexander.borisov@nginx.com return Qnil; 199584Salexander.borisov@nginx.com } 200584Salexander.borisov@nginx.com 201584Salexander.borisov@nginx.com 202584Salexander.borisov@nginx.com static VALUE 203584Salexander.borisov@nginx.com nxt_ruby_stream_io_puts(VALUE obj, VALUE args) 204584Salexander.borisov@nginx.com { 2051687Smax.romanov@nginx.com nxt_ruby_ctx_t *rctx; 206584Salexander.borisov@nginx.com 207584Salexander.borisov@nginx.com if (RARRAY_LEN(args) != 1) { 208584Salexander.borisov@nginx.com return Qnil; 209584Salexander.borisov@nginx.com } 210584Salexander.borisov@nginx.com 2111687Smax.romanov@nginx.com Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); 212584Salexander.borisov@nginx.com 2131687Smax.romanov@nginx.com nxt_ruby_stream_io_s_write(rctx, RARRAY_PTR(args)[0]); 214584Salexander.borisov@nginx.com 215584Salexander.borisov@nginx.com return Qnil; 216584Salexander.borisov@nginx.com } 217584Salexander.borisov@nginx.com 218584Salexander.borisov@nginx.com 219584Salexander.borisov@nginx.com static VALUE 220584Salexander.borisov@nginx.com nxt_ruby_stream_io_write(VALUE obj, VALUE args) 221584Salexander.borisov@nginx.com { 2221687Smax.romanov@nginx.com long len; 2231687Smax.romanov@nginx.com nxt_ruby_ctx_t *rctx; 224584Salexander.borisov@nginx.com 225584Salexander.borisov@nginx.com if (RARRAY_LEN(args) != 1) { 226584Salexander.borisov@nginx.com return Qnil; 227584Salexander.borisov@nginx.com } 228584Salexander.borisov@nginx.com 2291687Smax.romanov@nginx.com Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); 230584Salexander.borisov@nginx.com 2311687Smax.romanov@nginx.com len = nxt_ruby_stream_io_s_write(rctx, RARRAY_PTR(args)[0]); 232584Salexander.borisov@nginx.com 233584Salexander.borisov@nginx.com return LONG2FIX(len); 234584Salexander.borisov@nginx.com } 235584Salexander.borisov@nginx.com 236584Salexander.borisov@nginx.com 237584Salexander.borisov@nginx.com nxt_inline long 2381687Smax.romanov@nginx.com nxt_ruby_stream_io_s_write(nxt_ruby_ctx_t *rctx, VALUE val) 239584Salexander.borisov@nginx.com { 240584Salexander.borisov@nginx.com if (nxt_slow_path(val == Qnil)) { 241584Salexander.borisov@nginx.com return 0; 242584Salexander.borisov@nginx.com } 243584Salexander.borisov@nginx.com 244584Salexander.borisov@nginx.com if (TYPE(val) != T_STRING) { 245584Salexander.borisov@nginx.com val = rb_funcall(val, rb_intern("to_s"), 0); 246584Salexander.borisov@nginx.com 247584Salexander.borisov@nginx.com if (TYPE(val) != T_STRING) { 248584Salexander.borisov@nginx.com return 0; 249584Salexander.borisov@nginx.com } 250584Salexander.borisov@nginx.com } 251584Salexander.borisov@nginx.com 2521687Smax.romanov@nginx.com nxt_unit_req_error(rctx->req, "Ruby: %s", RSTRING_PTR(val)); 253584Salexander.borisov@nginx.com 254584Salexander.borisov@nginx.com return RSTRING_LEN(val); 255584Salexander.borisov@nginx.com } 256584Salexander.borisov@nginx.com 257584Salexander.borisov@nginx.com 258584Salexander.borisov@nginx.com static VALUE 2591337Smax.romanov@nginx.com nxt_ruby_stream_io_flush(VALUE obj) 260584Salexander.borisov@nginx.com { 261584Salexander.borisov@nginx.com return Qnil; 262584Salexander.borisov@nginx.com } 263*2093Sz.hong@f5.com 264*2093Sz.hong@f5.com 265*2093Sz.hong@f5.com static VALUE 266*2093Sz.hong@f5.com nxt_ruby_stream_io_close(VALUE obj) 267*2093Sz.hong@f5.com { 268*2093Sz.hong@f5.com return Qnil; 269*2093Sz.hong@f5.com } 270