PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/vfcgi/ev/fcgi/Request.d

http://gool.googlecode.com/
D | 309 lines | 273 code | 26 blank | 10 comment | 36 complexity | 9366b16ac1fea5f3a376dbb2d365861d MD5 | raw file
  1. module vlib.ev.fcgi.Request ;
  2. import vlib.Types;
  3. private {
  4. extern(C){
  5. int fclose(int);
  6. }
  7. extern(Windows) {
  8. int connect(int, vAddr4*, int) ;
  9. int socket(int af, int type, int protocol);
  10. }
  11. }
  12. struct vFcgReq {
  13. alias typeof(*this) This ;
  14. alias typeof(this) pThis ;
  15. static void* _root ;
  16. static This[] _list ;
  17. static int _len = 4 ;
  18. static void Init() {
  19. expand(4) ;
  20. }
  21. static void expand(int i) {
  22. if( i < _len ) {
  23. return ;
  24. }
  25. _len = _len * 2 ;
  26. if( _len < i ) {
  27. _len = i ;
  28. }
  29. int size = This.sizeof * _len ;
  30. _root = GC.realloc (_root, size , GC.BlkAttr.NO_MOVE | GC.BlkAttr.NO_SCAN ) ;
  31. _list = cast(This[]) _root[0..size] ;
  32. assert(_list.length is _len ) ;
  33. }
  34. static void accept(ref Berkeley ssoc){
  35. pThis _this = null ;
  36. foreach(ref q; _list){
  37. if( !q._connected ){
  38. _this = &q ;
  39. break ;
  40. }
  41. }
  42. if( _this is null ) {
  43. int len = _list.length ;
  44. expand(len + 1 ) ;
  45. _this = &_list[len] ;
  46. }
  47. ssoc.accept(_this.si) ;
  48. _this.proxy ;
  49. log!(__FILE__,__LINE__)("start new req\n");
  50. }
  51. enum State {
  52. Closing ,
  53. Connecting ,
  54. Proxying ,
  55. }
  56. Berkeley si ;
  57. int si_fd ;
  58. Berkeley so ;
  59. int so_fd ;
  60. bool _connected ;
  61. vProcess* php ;
  62. ev_timer io_timer ;
  63. ev_io i_read, i_write ;
  64. ev_io o_read, o_write ;
  65. vBuffer ob , ib, oo = null ;
  66. State _state ;
  67. bool is_req_start ;
  68. void proxy() {
  69. _connected = true ;
  70. if( ob is null ) {
  71. ob = new vBuffer(1024, 1024);
  72. ib = new vBuffer(1024, 1024);
  73. oo = new vBuffer(1024, 1024);
  74. } else {
  75. ob.clear ;
  76. ib.clear ;
  77. oo.clear ;
  78. }
  79. so.open(AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP) ;
  80. si.blocking( false ) ;
  81. so.blocking( false ) ;
  82. si_fd = osf_open(cast(void*) si.handle) ;
  83. so_fd = osf_open(cast(void*) so.handle) ;
  84. static int php_i = 0 ;
  85. php = &vProcess.list [ php_i ++ % vProcess.list.length ] ;
  86. io_timer.data = this ;
  87. i_read.data = this ;
  88. i_write.data = this ;
  89. o_read.data = this ;
  90. o_write.data = this ;
  91. ev_timer_init(&io_timer, &On_Timer, 24, 24) ;
  92. ev_io_init(&i_read, &On_Req_Read, si_fd, EV_READ) ;
  93. ev_io_init(&i_write, &On_Req_Write, si_fd, EV_WRITE ) ;
  94. ev_io_init(&o_read, &On_Res_Read, so_fd, EV_READ) ;
  95. ev_io_init(&o_write, &On_Res_Write, so_fd, EV_WRITE ) ;
  96. // ev_io_set(&io_res, si_fd, EV_READ) ;
  97. int ret = connect(so.handle, &php._addr, php._addr.sizeof ) ;
  98. ev_timer_start(vLib.loop, &io_timer);
  99. ev_io_start(vLib.loop, &i_read);
  100. ev_io_start(vLib.loop, &o_write);
  101. _state = State.Connecting ;
  102. }
  103. void close() {
  104. ev_timer_stop(vLib.loop, &io_timer);
  105. ev_io_stop(vLib.loop, &i_read);
  106. ev_io_stop(vLib.loop, &i_write);
  107. ev_io_stop(vLib.loop, &o_read);
  108. ev_io_stop(vLib.loop, &o_write);
  109. osf_close(si_fd);
  110. osf_close(so_fd);
  111. so.detach ;
  112. si.detach ;
  113. _state = State.Closing ;
  114. _connected = false ;
  115. is_req_start = false ;
  116. }
  117. static extern(C) void On_Timer(ev_loop_t* loop, ev_timer* w, int ev) {
  118. pThis _this = cast(pThis) w.data ;
  119. if( _this._state is State.Connecting ) {
  120. // restart php
  121. }
  122. log!(__FILE__, __LINE__)("On_Timer");
  123. _this.php.reboot() ;
  124. _this.close() ;
  125. return ;
  126. }
  127. static extern(C) void On_Req_Read (ev_loop_t* loop, ev_io* w, int ev) {
  128. pThis _this = cast(pThis) w.data ;
  129. log!(__FILE__, __LINE__)("On_Req_Read start, len:{}", _this.ib.readable);
  130. bool is_first = true ;
  131. ubyte[512] tmp ;
  132. while( true ) {
  133. int i = _this.si.receive(tmp);
  134. if( i < 0 || i > tmp.length ) {
  135. log!(__FILE__, __LINE__)("read:{}:`{}`", i, _this.ib.readable );
  136. /*
  137. if( _this.is_req_start ) {
  138. _this.close() ;
  139. return ;
  140. }
  141. _this.is_req_start = true ;
  142. */
  143. break ;
  144. }
  145. if( is_first ) {
  146. is_first = false ;
  147. if( i is 0 ) {
  148. log!(__FILE__, __LINE__)("close, read:`{}`", i, _this.ib.readable );
  149. _this.close() ;
  150. return ;
  151. }
  152. }
  153. if( i is 0 ) {
  154. break ;
  155. }
  156. _this.ib(tmp[0..i]) ;
  157. }
  158. log!(__FILE__, __LINE__)("On_Req_Read end, len:{}", _this.ib.readable);
  159. if( _this.ib.readable ) {
  160. ev_io_start(vLib.loop, &_this.o_write) ;
  161. }
  162. ev_timer_stop(vLib.loop, &_this.io_timer);
  163. ev_timer_start(vLib.loop, &_this.io_timer);
  164. }
  165. static extern(C) void On_Req_Write(ev_loop_t* loop, ev_io* w, int ev) {
  166. pThis _this = cast(pThis) w.data ;
  167. log!(__FILE__, __LINE__)("On_Req_Write start, len:{}", _this.ob.readable );
  168. if( _this.ob.readable is 0 ) {
  169. ev_io_stop(vLib.loop, &_this.i_write) ;
  170. return ;
  171. }
  172. bool is_write = false ;
  173. ubyte[] _tmp = cast(ubyte[]) _this.ob.slice ;
  174. while(true) {
  175. int i = _this.si.send( _tmp ) ;
  176. if( i > _tmp.length || i < 0 ) {
  177. log!(__FILE__, __LINE__)("close");
  178. _this.php.reboot() ;
  179. _this.close() ;
  180. return ;
  181. }
  182. if( i is 0 ) {
  183. break ;
  184. }
  185. is_write = true ;
  186. if( i is _tmp.length ) {
  187. _tmp = _tmp[0..0] ;
  188. break ;
  189. }
  190. _tmp = _tmp[i..$] ;
  191. }
  192. log!(__FILE__, __LINE__)("On_Req_Write end:`{}:{}`", _this.ob.readable - _tmp.length, _tmp.length );
  193. _this.ob.clear;
  194. if( _tmp.length ) {
  195. _this.oo(_tmp);
  196. _this.ob( _this.oo.slice ) ;
  197. _this.oo.clear ;
  198. } else {
  199. ev_io_stop(vLib.loop, &_this.i_write) ;
  200. }
  201. if( is_write ) {
  202. ev_io_stop(vLib.loop, &_this.o_read) ;
  203. }
  204. ev_timer_stop(vLib.loop, &_this.io_timer);
  205. ev_timer_start(vLib.loop, &_this.io_timer);
  206. }
  207. static extern(C) void On_Res_Read (ev_loop_t* loop, ev_io* w, int ev) {
  208. pThis _this = cast(pThis) w.data ;
  209. log!(__FILE__, __LINE__)("On_Res_Read start, len:{}", _this.ob.readable);
  210. bool is_first = true ;
  211. ubyte[512] tmp ;
  212. while( true ) {
  213. int i = _this.so.receive(tmp);
  214. if( i < 0 || i > tmp.length ) {
  215. ev_io_stop(vLib.loop, &_this.o_read) ;
  216. //ev_io_start(vLib.loop, &_this.i_read) ;
  217. log!(__FILE__, __LINE__)("read:{}:{}", i, _this.ob.readable );
  218. break ;
  219. }
  220. if( is_first ) {
  221. is_first = false ;
  222. if( i is 0 ) {
  223. log!(__FILE__, __LINE__)("close");
  224. _this.php.reboot() ;
  225. _this.close() ;
  226. return ;
  227. }
  228. }
  229. if( i is 0 ) {
  230. break ;
  231. }
  232. _this.ob(tmp[0..i]) ;
  233. }
  234. log!(__FILE__, __LINE__)("On_Res_Read end, {}", _this.ob.readable );
  235. if( _this.ob.readable ) {
  236. ev_io_stop(vLib.loop, &_this.o_read) ;
  237. ev_io_start(vLib.loop, &_this.i_write) ;
  238. }
  239. ev_timer_stop(vLib.loop, &_this.io_timer);
  240. ev_timer_start(vLib.loop, &_this.io_timer);
  241. }
  242. static extern(C) void On_Res_Write(ev_loop_t* loop, ev_io* w, int ev) {
  243. pThis _this = cast(pThis) w.data ;
  244. log!(__FILE__, __LINE__)("On_Res_Write start, len:{}", _this.ib.readable);
  245. if( _this._state is State.Connecting ) {
  246. _this._state = State.Proxying ;
  247. }
  248. if( _this.ib.readable is 0 ) {
  249. ev_io_stop(vLib.loop, &_this.o_write) ;
  250. return ;
  251. }
  252. ubyte[] _tmp = cast(ubyte[]) _this.ib.slice ;
  253. while(true) {
  254. int i = _this.so.send( _tmp ) ;
  255. if( i > _tmp.length || i < 0 ) {
  256. log!(__FILE__, __LINE__)("close");
  257. _this.php.reboot() ;
  258. _this.close() ;
  259. return ;
  260. }
  261. if( i is _tmp.length ) {
  262. _tmp = _tmp[0..0] ;
  263. break ;
  264. }
  265. if( i is 0 || i is _tmp.length ) {
  266. break ;
  267. }
  268. _tmp = _tmp[i..$] ;
  269. }
  270. log!(__FILE__, __LINE__)("On_Res_Write end:`{}:{}`", _this.ib.readable - _tmp.length, _tmp.length );
  271. _this.ib.clear;
  272. if( _tmp.length ) {
  273. _this.oo(_tmp);
  274. _this.ib( _this.oo.slice ) ;
  275. _this.oo.clear ;
  276. } else {
  277. ev_io_stop(vLib.loop, &_this.o_write) ;
  278. ev_io_start(vLib.loop, &_this.o_read) ;
  279. }
  280. ev_timer_stop(vLib.loop, &_this.io_timer);
  281. ev_timer_start(vLib.loop, &_this.io_timer);
  282. }
  283. }