/tools/vfcgi2/ev/fcgi/Request.d
D | 407 lines | 164 code | 17 blank | 226 comment | 16 complexity | 562debb7aa3713df47ec85677587dbe0 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 Mutex _mux ;
- static void Init() {
- _mux = new Mutex ;
- 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){
- _mux.lock();
- scope(exit) _mux.unlock() ;
- pThis _this = null ;
- foreach(ref q; _list){
- if( !q._running ){
- _this = &q ;
- break ;
- }
- }
- if( _this is null ) {
- int len = _list.length ;
- expand(len + 1 ) ;
- _this = &_list[len] ;
- }
- _this.Setup ;
- _this._running = true ;
- ssoc.accept(_this.si) ;
- assert( _this._res !is null);
- _this._res.start() ;
- }
-
- enum State {
- None ,
- Connecting ,
- Proxying ,
- Closing ,
- }
- enum Errno {
- None ,
- Connect ,
- Res_Read,
- Res_Write,
- Req_Read,
- Req_Write,
- }
-
- Thread _req, _res ;
- Semaphore _sem = null ;
- bool _running ;
- Berkeley si ;
- Berkeley so ;
- vProcess* php ;
- State _state ;
- Errno _errno ;
-
- void Setup() {
- if( _sem !is null ) {
- return ;
- }
- _req = new Thread(&Req_Loop) ;
- _res = new Thread(&Res_Loop) ;
- _sem = new Semaphore ;
- }
-
- void Free(){
- so.detach ;
- si.detach ;
- _mux.lock();
- scope(exit) _mux.unlock() ;
- _running = false ;
- }
-
- void Req_Loop(){
- scope(exit){
- log!(__FILE__, __LINE__)("exit Req_Loop :{:x}", cast(void*)Thread.getThis) ;
- }
-
- log!(__FILE__, __LINE__)("connected , start req proxy:{:x}", cast(void*)Thread.getThis) ;
- Thread.sleep(.1);
- ubyte[512] tmp ;
-
- while(true){
- int i = so.receive(tmp) ;
- if( i <= 0 || i > tmp.length ) {
- _errno = Errno.Res_Read ;
- log!(__FILE__, __LINE__)("Res_Read: {}", i ) ;
- return ;
- }
- ubyte[] _tmp = tmp[0..i];
- while( _tmp.length ) {
- int j = si.send( _tmp) ;
- if( j < 0 || j > _tmp.length ) {
- _errno = Errno.Req_Write ;
- log!(__FILE__, __LINE__)("Req_Write: {}", j ) ;
- return ;
- }
- if( j is _tmp.length ) {
- break ;
- }
- _tmp = _tmp[ j .. $] ;
- }
- }
- }
-
- void Res_Loop(){
- scope(exit){
- Free;
- log!(__FILE__, __LINE__)("exit Res_Loop :{:x}", cast(void*)Thread.getThis) ;
- }
- _errno = Errno.None ;
- _state = State.Connecting ;
- so.open(AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP) ;
- vProcess.find(php);
- int ret = connect(so.handle, &php._addr, php._addr.sizeof );
- if( ret !is 0 ) {
- log!(__FILE__, __LINE__)(" connect error :{}", ret) ;
- _state = State.Closing ;
- _errno = Errno.Connect ;
- Free;
- return ;
- }
- log!(__FILE__, __LINE__)("connected , start res proxy, {:x},", cast(void*)Thread.getThis) ;
-
- ubyte[512] tmp ;
- while(true) {
- int i = si.receive(tmp) ;
- if( i <= 0 || i > tmp.length ) {
- _errno = Errno.Req_Read ;
- log!(__FILE__, __LINE__)("Req_Read: {}", i ) ;
- return ;
- }
- ubyte[] _tmp = tmp[0..i];
- while( _tmp.length ) {
- int j = so.send( _tmp) ;
- if( j < 0 || j > _tmp.length ) {
- _errno = Errno.Res_Write ;
- log!(__FILE__, __LINE__)("Res_Write: {}", j ) ;
- return ;
- }
- if( j is _tmp.length ) {
- break ;
- }
- _tmp = _tmp[ j .. $] ;
- }
-
- }
- }
-
- /*
- 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, 6, 6) ;
- 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 ;
- }
-
-
- 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 ;
- 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 );
- 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 ;
- 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);
- }
- */
- }