/tools/vfcgi/ev/fcgi/Request.d
D | 309 lines | 273 code | 26 blank | 10 comment | 36 complexity | 9366b16ac1fea5f3a376dbb2d365861d MD5 | raw file
- module vlib.ev.fcgi.Request ;
-
- import vlib.Types;
-
- private {
- extern(C){
- int fclose(int);
- }
- extern(Windows) {
- int connect(int, vAddr4*, int) ;
- int socket(int af, int type, int protocol);
- }
- }
-
- struct vFcgReq {
- alias typeof(*this) This ;
- alias typeof(this) pThis ;
-
- static void* _root ;
- static This[] _list ;
- static int _len = 4 ;
- static void Init() {
- expand(4) ;
- }
-
- static void expand(int i) {
- if( i < _len ) {
- return ;
- }
- _len = _len * 2 ;
- if( _len < i ) {
- _len = i ;
- }
- int size = This.sizeof * _len ;
- _root = GC.realloc (_root, size , GC.BlkAttr.NO_MOVE | GC.BlkAttr.NO_SCAN ) ;
- _list = cast(This[]) _root[0..size] ;
- assert(_list.length is _len ) ;
- }
-
- static void accept(ref Berkeley ssoc){
- pThis _this = null ;
- foreach(ref q; _list){
- if( !q._connected ){
- _this = &q ;
- break ;
- }
- }
- if( _this is null ) {
- int len = _list.length ;
- expand(len + 1 ) ;
- _this = &_list[len] ;
- }
- ssoc.accept(_this.si) ;
- _this.proxy ;
- log!(__FILE__,__LINE__)("start new req\n");
- }
-
- enum State {
- Closing ,
- Connecting ,
- Proxying ,
- }
-
- Berkeley si ;
- int si_fd ;
- Berkeley so ;
- int so_fd ;
- bool _connected ;
- vProcess* php ;
- ev_timer io_timer ;
- ev_io i_read, i_write ;
- ev_io o_read, o_write ;
- vBuffer ob , ib, oo = null ;
- State _state ;
- bool is_req_start ;
-
- void proxy() {
- _connected = true ;
- if( ob is null ) {
- ob = new vBuffer(1024, 1024);
- ib = new vBuffer(1024, 1024);
- oo = new vBuffer(1024, 1024);
- } else {
- ob.clear ;
- ib.clear ;
- oo.clear ;
- }
- so.open(AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP) ;
- si.blocking( false ) ;
- so.blocking( false ) ;
-
- si_fd = osf_open(cast(void*) si.handle) ;
- so_fd = osf_open(cast(void*) so.handle) ;
-
- static int php_i = 0 ;
- php = &vProcess.list [ php_i ++ % vProcess.list.length ] ;
-
- io_timer.data = this ;
- i_read.data = this ;
- i_write.data = this ;
- o_read.data = this ;
- o_write.data = this ;
-
- ev_timer_init(&io_timer, &On_Timer, 24, 24) ;
- ev_io_init(&i_read, &On_Req_Read, si_fd, EV_READ) ;
- ev_io_init(&i_write, &On_Req_Write, si_fd, EV_WRITE ) ;
-
- ev_io_init(&o_read, &On_Res_Read, so_fd, EV_READ) ;
- ev_io_init(&o_write, &On_Res_Write, so_fd, EV_WRITE ) ;
-
- // ev_io_set(&io_res, si_fd, EV_READ) ;
-
- int ret = connect(so.handle, &php._addr, php._addr.sizeof ) ;
- ev_timer_start(vLib.loop, &io_timer);
- ev_io_start(vLib.loop, &i_read);
- ev_io_start(vLib.loop, &o_write);
- _state = State.Connecting ;
- }
-
- void close() {
- ev_timer_stop(vLib.loop, &io_timer);
-
- ev_io_stop(vLib.loop, &i_read);
- ev_io_stop(vLib.loop, &i_write);
- ev_io_stop(vLib.loop, &o_read);
- ev_io_stop(vLib.loop, &o_write);
-
- osf_close(si_fd);
- osf_close(so_fd);
- so.detach ;
- si.detach ;
- _state = State.Closing ;
- _connected = false ;
- is_req_start = false ;
- }
-
-
- static extern(C) void On_Timer(ev_loop_t* loop, ev_timer* w, int ev) {
- pThis _this = cast(pThis) w.data ;
- if( _this._state is State.Connecting ) {
- // restart php
- }
- log!(__FILE__, __LINE__)("On_Timer");
- _this.php.reboot() ;
- _this.close() ;
- return ;
- }
-
- static extern(C) void On_Req_Read (ev_loop_t* loop, ev_io* w, int ev) {
- pThis _this = cast(pThis) w.data ;
- log!(__FILE__, __LINE__)("On_Req_Read start, len:{}", _this.ib.readable);
- bool is_first = true ;
- ubyte[512] tmp ;
- while( true ) {
- int i = _this.si.receive(tmp);
- if( i < 0 || i > tmp.length ) {
- log!(__FILE__, __LINE__)("read:{}:`{}`", i, _this.ib.readable );
- /*
- if( _this.is_req_start ) {
- _this.close() ;
- return ;
- }
- _this.is_req_start = true ;
- */
- break ;
- }
- if( is_first ) {
- is_first = false ;
- if( i is 0 ) {
- log!(__FILE__, __LINE__)("close, read:`{}`", i, _this.ib.readable );
- _this.close() ;
- return ;
- }
- }
- if( i is 0 ) {
- break ;
- }
- _this.ib(tmp[0..i]) ;
- }
- log!(__FILE__, __LINE__)("On_Req_Read end, len:{}", _this.ib.readable);
- if( _this.ib.readable ) {
- ev_io_start(vLib.loop, &_this.o_write) ;
- }
- ev_timer_stop(vLib.loop, &_this.io_timer);
- ev_timer_start(vLib.loop, &_this.io_timer);
- }
-
- static extern(C) void On_Req_Write(ev_loop_t* loop, ev_io* w, int ev) {
- pThis _this = cast(pThis) w.data ;
- log!(__FILE__, __LINE__)("On_Req_Write start, len:{}", _this.ob.readable );
- if( _this.ob.readable is 0 ) {
- ev_io_stop(vLib.loop, &_this.i_write) ;
- return ;
- }
- bool is_write = false ;
- ubyte[] _tmp = cast(ubyte[]) _this.ob.slice ;
- while(true) {
- int i = _this.si.send( _tmp ) ;
- if( i > _tmp.length || i < 0 ) {
- log!(__FILE__, __LINE__)("close");
- _this.php.reboot() ;
- _this.close() ;
- return ;
- }
- if( i is 0 ) {
- break ;
- }
- is_write = true ;
- if( i is _tmp.length ) {
- _tmp = _tmp[0..0] ;
- break ;
- }
- _tmp = _tmp[i..$] ;
- }
- log!(__FILE__, __LINE__)("On_Req_Write end:`{}:{}`", _this.ob.readable - _tmp.length, _tmp.length );
- _this.ob.clear;
- if( _tmp.length ) {
- _this.oo(_tmp);
- _this.ob( _this.oo.slice ) ;
- _this.oo.clear ;
- } else {
- ev_io_stop(vLib.loop, &_this.i_write) ;
- }
- if( is_write ) {
- ev_io_stop(vLib.loop, &_this.o_read) ;
- }
- ev_timer_stop(vLib.loop, &_this.io_timer);
- ev_timer_start(vLib.loop, &_this.io_timer);
- }
-
- static extern(C) void On_Res_Read (ev_loop_t* loop, ev_io* w, int ev) {
- pThis _this = cast(pThis) w.data ;
- log!(__FILE__, __LINE__)("On_Res_Read start, len:{}", _this.ob.readable);
- bool is_first = true ;
- ubyte[512] tmp ;
- while( true ) {
- int i = _this.so.receive(tmp);
- if( i < 0 || i > tmp.length ) {
- ev_io_stop(vLib.loop, &_this.o_read) ;
- //ev_io_start(vLib.loop, &_this.i_read) ;
- log!(__FILE__, __LINE__)("read:{}:{}", i, _this.ob.readable );
- break ;
- }
- if( is_first ) {
- is_first = false ;
- if( i is 0 ) {
- log!(__FILE__, __LINE__)("close");
- _this.php.reboot() ;
- _this.close() ;
- return ;
- }
- }
- if( i is 0 ) {
- break ;
- }
- _this.ob(tmp[0..i]) ;
- }
- log!(__FILE__, __LINE__)("On_Res_Read end, {}", _this.ob.readable );
- if( _this.ob.readable ) {
- ev_io_stop(vLib.loop, &_this.o_read) ;
- ev_io_start(vLib.loop, &_this.i_write) ;
- }
- ev_timer_stop(vLib.loop, &_this.io_timer);
- ev_timer_start(vLib.loop, &_this.io_timer);
- }
-
- static extern(C) void On_Res_Write(ev_loop_t* loop, ev_io* w, int ev) {
- pThis _this = cast(pThis) w.data ;
- log!(__FILE__, __LINE__)("On_Res_Write start, len:{}", _this.ib.readable);
- if( _this._state is State.Connecting ) {
- _this._state = State.Proxying ;
- }
- if( _this.ib.readable is 0 ) {
- ev_io_stop(vLib.loop, &_this.o_write) ;
- return ;
- }
- ubyte[] _tmp = cast(ubyte[]) _this.ib.slice ;
- while(true) {
- int i = _this.so.send( _tmp ) ;
- if( i > _tmp.length || i < 0 ) {
- log!(__FILE__, __LINE__)("close");
- _this.php.reboot() ;
- _this.close() ;
- return ;
- }
- if( i is _tmp.length ) {
- _tmp = _tmp[0..0] ;
- break ;
- }
- if( i is 0 || i is _tmp.length ) {
- break ;
- }
- _tmp = _tmp[i..$] ;
- }
- log!(__FILE__, __LINE__)("On_Res_Write end:`{}:{}`", _this.ib.readable - _tmp.length, _tmp.length );
- _this.ib.clear;
- if( _tmp.length ) {
- _this.oo(_tmp);
- _this.ib( _this.oo.slice ) ;
- _this.oo.clear ;
- } else {
- ev_io_stop(vLib.loop, &_this.o_write) ;
- ev_io_start(vLib.loop, &_this.o_read) ;
- }
-
- ev_timer_stop(vLib.loop, &_this.io_timer);
- ev_timer_start(vLib.loop, &_this.io_timer);
- }
- }