ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

879 lines
22 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // See accompanying file COPYING.TXT file for licensing details.
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #define CPPCMS_SOURCE
  9. #include "cgi_api.h"
  10. #include "cgi_acceptor.h"
  11. #include <cppcms/service.h>
  12. #include "service_impl.h"
  13. #include "cppcms_error_category.h"
  14. #include <cppcms/json.h>
  15. #include <cppcms/cstdint.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <algorithm>
  19. #include <iostream>
  20. #include <stdio.h>
  21. #include <cppcms/config.h>
  22. #include <booster/aio/buffer.h>
  23. #include "binder.h"
  24. #include <utility>
  25. #include "cached_settings.h"
  26. #ifdef CPPCMS_WIN_NATIVE
  27. # ifndef NOMINMAX
  28. # define NOMINMAX
  29. # endif
  30. # include <winsock2.h>
  31. #else
  32. # include <arpa/inet.h>
  33. #endif
  34. namespace io = booster::aio;
  35. namespace cppcms {
  36. namespace impl {
  37. namespace cgi {
  38. template<typename API,typename Factory> class socket_acceptor;
  39. class fastcgi : public connection {
  40. public:
  41. fastcgi(cppcms::service &srv) :
  42. connection(srv),
  43. socket_(srv.impl().get_io_service()),
  44. header_(),
  45. full_header_(),
  46. eof_(),
  47. eof_callback_(false)
  48. {
  49. reset_all();
  50. int procs=srv.procs_no();
  51. if(procs < 1) procs=1;
  52. int threads=srv.threads_no();
  53. cuncurrency_hint_=srv.cached_settings().fastcgi.cuncurrency_hint;
  54. if(cuncurrency_hint_ < 0)
  55. cuncurrency_hint_ = procs*threads;
  56. }
  57. ~fastcgi()
  58. {
  59. if(socket_.native()!=io::invalid_socket) {
  60. booster::system::error_code e;
  61. socket_.shutdown(io::stream_socket::shut_rdwr,e);
  62. }
  63. }
  64. virtual void async_read_headers(handler const &h)
  65. {
  66. reset_all();
  67. async_read_record(mfunc_to_event_handler(&fastcgi::on_start_request,self(),h));
  68. }
  69. virtual void async_read_some(void *p,size_t s,io_handler const &h)
  70. {
  71. if(read_length_ == content_length_) {
  72. socket_.get_io_service().post(h,booster::system::error_code(errc::protocol_violation,cppcms_category),0);
  73. return;
  74. }
  75. if(body_ptr_ < body_.size()) {
  76. size_t rest=body_.size() - body_ptr_;
  77. if(s > rest)
  78. s=rest;
  79. memcpy(p,&body_[body_ptr_],s);
  80. body_ptr_ += s;
  81. read_length_ += s;
  82. if(body_ptr_ == body_.size()) {
  83. body_ptr_ = 0;
  84. body_.clear();
  85. }
  86. if(read_length_ >= content_length_) {
  87. async_read_record(mfunc_to_event_handler(
  88. &fastcgi::on_read_stdin_eof_expected,
  89. self(),
  90. h,
  91. s));
  92. return;
  93. }
  94. socket_.get_io_service().post(h,booster::system::error_code(),s);
  95. return;
  96. }
  97. else {
  98. async_read_record(mfunc_to_event_handler(
  99. &fastcgi::on_some_input_recieved,
  100. self(),
  101. h,std::make_pair(p,s)));
  102. return;
  103. }
  104. }
  105. virtual void on_async_write_start(){}
  106. virtual void on_async_write_progress(bool){}
  107. private:
  108. void on_some_input_recieved(booster::system::error_code const &e,io_handler const &h,std::pair<void *,size_t> in)
  109. {
  110. if(e) { h(e,0); return; }
  111. if( header_.type!=fcgi_stdin
  112. || header_.request_id!=request_id_
  113. || header_.content_length==0)
  114. {
  115. h(booster::system::error_code(errc::protocol_violation,cppcms_category),0);
  116. return;
  117. }
  118. async_read_some(in.first,in.second,h);
  119. }
  120. void on_read_stdin_eof_expected(booster::system::error_code const &e,io_handler const &h,size_t s)
  121. {
  122. if(e) { h(e,s); return; }
  123. if( header_.type!=fcgi_stdin
  124. || header_.request_id!=request_id_
  125. || header_.content_length!=0)
  126. {
  127. h(booster::system::error_code(errc::protocol_violation,cppcms_category),s);
  128. return;
  129. }
  130. h(booster::system::error_code(),s);
  131. }
  132. public:
  133. virtual booster::aio::const_buffer format_output(booster::aio::const_buffer const &in,bool completed,booster::system::error_code &)
  134. {
  135. booster::aio::const_buffer packet;
  136. booster::aio::const_buffer::entry const *chunks = in.get().first;
  137. //#define DEBUG_FASTCGI
  138. #ifdef DEBUG_FASTCGI
  139. {
  140. size_t n=in.get().second;
  141. printf("Format output of %d:\n",int(in.bytes_count()));
  142. for(size_t i=0;i<n;i++) {
  143. printf("[%.*s]",int(chunks[i].size),chunks[i].ptr);
  144. }
  145. if(completed) {
  146. printf("\nEOF\n");
  147. }
  148. else {
  149. printf("\n---\n");
  150. }
  151. }
  152. #endif
  153. size_t reminder = in.bytes_count();
  154. size_t in_size = reminder;
  155. size_t chunk_consumed = 0;
  156. while(reminder > 0) {
  157. static const char pad[8]={0,0,0,0,0,0,0,0};
  158. static const size_t max_packet_len = 65535;
  159. size_t chunk = 0;
  160. int pad_len = 0;
  161. if(reminder > max_packet_len) {
  162. chunk = max_packet_len;
  163. if(in_size > max_packet_len && reminder == in_size) {
  164. // prepare only once
  165. full_header_.version = fcgi_version_1;
  166. full_header_.type=fcgi_stdout;
  167. full_header_.request_id=request_id_;
  168. full_header_.content_length = max_packet_len;
  169. full_header_.padding_length = pad_len = 1;
  170. full_header_.to_net();
  171. }
  172. else {
  173. pad_len = 1;
  174. }
  175. packet += io::buffer(&full_header_,sizeof(full_header_));
  176. }
  177. else {
  178. chunk = reminder;
  179. memset(&header_,0,sizeof(header_));
  180. header_.version=fcgi_version_1;
  181. header_.type=fcgi_stdout;
  182. header_.request_id=request_id_;
  183. header_.content_length = reminder;
  184. header_.padding_length =pad_len = (8 - (reminder % 8)) % 8;
  185. header_.to_net();
  186. packet += io::buffer(&header_,sizeof(header_));
  187. }
  188. reminder -= chunk;
  189. while(chunk > 0) {
  190. size_t next_size = chunks->size - chunk_consumed;
  191. if(next_size > chunk)
  192. next_size = chunk;
  193. packet += io::buffer(chunks->ptr + chunk_consumed, next_size);
  194. chunk_consumed += next_size;
  195. chunk -= next_size;
  196. if(chunk_consumed == chunks->size) {
  197. chunks++;
  198. chunk_consumed = 0;
  199. }
  200. }
  201. packet += io::buffer(pad,pad_len);
  202. }
  203. if(completed) {
  204. prepare_eof();
  205. packet += io::buffer(&eof_,sizeof(eof_));
  206. }
  207. #ifdef DEBUG_FASTCGI
  208. std::pair<booster::aio::const_buffer::entry const *,size_t> cnk = packet.get();
  209. for(size_t i=0;i<cnk.second;i++) {
  210. std::cerr << "[ " << (void const *)(cnk.first[i].ptr) << " " << cnk.first[i].size << "]\n" << std::endl;
  211. }
  212. #endif
  213. return packet;
  214. }
  215. virtual booster::aio::stream_socket &socket() { return socket_; }
  216. virtual booster::aio::io_service &get_io_service()
  217. {
  218. return socket_.get_io_service();
  219. }
  220. virtual bool keep_alive()
  221. {
  222. bool ka_value = keep_alive_;
  223. reset_all();
  224. return ka_value;
  225. }
  226. void prepare_eof()
  227. {
  228. memset(&eof_,0,sizeof(eof_));
  229. for(unsigned i=0;i<2;i++) {
  230. eof_.headers_[i].version=fcgi_version_1;
  231. eof_.headers_[i].request_id=request_id_;
  232. }
  233. eof_.headers_[0].type=fcgi_stdout;
  234. eof_.headers_[1].type=fcgi_end_request;
  235. eof_.headers_[1].content_length=8;
  236. eof_.record_.protocol_status=fcgi_request_complete;
  237. eof_.headers_[0].to_net();
  238. eof_.headers_[1].to_net();
  239. eof_.record_.to_net();
  240. }
  241. virtual void do_eof()
  242. {
  243. if(eof_callback_)
  244. socket_.cancel();
  245. eof_callback_ = false;
  246. }
  247. struct io_handler_to_handler {
  248. callback h;
  249. io_handler_to_handler(callback const &c) : h(c) {}
  250. void operator()(booster::system::error_code const &,size_t)
  251. {
  252. h();
  253. }
  254. };
  255. struct io_handler_to_event_handler {
  256. handler h;
  257. io_handler_to_event_handler(handler const &c) : h(c) {}
  258. void operator()(booster::system::error_code const &e,size_t)
  259. {
  260. h(e);
  261. }
  262. };
  263. // This is not really correct because server may try
  264. // to multiplex or ask control... But meanwhile it is good enough
  265. virtual void async_read_eof(callback const &h)
  266. {
  267. eof_callback_ = true;
  268. static char a;
  269. async_read_from_socket(&a,1,io_handler_to_handler(h));
  270. }
  271. private:
  272. //
  273. //
  274. // defs
  275. //
  276. //
  277. struct fcgi_header {
  278. unsigned char version;
  279. unsigned char type;
  280. uint16_t request_id;
  281. uint16_t content_length;
  282. unsigned char padding_length;
  283. unsigned char reserved;
  284. void to_host() {
  285. request_id = ntohs(request_id);
  286. content_length = ntohs(content_length);
  287. }
  288. void to_net() {
  289. request_id = htons(request_id);
  290. content_length = htons(content_length);
  291. }
  292. };
  293. enum {
  294. fcgi_header_len = 8,
  295. fcgi_version_1 = 1,
  296. fcgi_begin_request = 1,
  297. fcgi_abort_request = 2,
  298. fcgi_end_request = 3,
  299. fcgi_params = 4,
  300. fcgi_stdin = 5,
  301. fcgi_stdout = 6,
  302. fcgi_stderr = 7,
  303. fcgi_data = 8,
  304. fcgi_get_values = 9,
  305. fcgi_get_values_result =10,
  306. fcgi_unknown_type =11,
  307. fcgi_maxtype =11,
  308. fcgi_null_request_id = 0
  309. };
  310. struct fcgi_request_body {
  311. uint16_t role;
  312. unsigned char flags;
  313. unsigned char reserved [5];
  314. void to_host() { role = ntohs(role); }
  315. void to_net() { role = htons(role); }
  316. };
  317. struct fcgi_begin_request_record {
  318. fcgi_header header;
  319. fcgi_request_body body;
  320. void to_host() { header.to_host(); body.to_host(); }
  321. void to_net() { header.to_net(); body.to_net(); }
  322. };
  323. enum {
  324. fcgi_keep_conn = 1
  325. };
  326. enum {
  327. fcgi_responder = 1,
  328. fcgi_authorizer = 2,
  329. fcgi_filter = 3
  330. };
  331. struct fcgi_end_request_body {
  332. uint32_t app_status;
  333. unsigned char protocol_status;
  334. unsigned char reserved[3];
  335. void to_host() { app_status = ntohl(app_status); }
  336. void to_net() { app_status = htonl(app_status); }
  337. };
  338. struct fcgi_end_request_record {
  339. fcgi_header header;
  340. fcgi_end_request_body body;
  341. void to_host() { header.to_host(); body.to_host(); }
  342. void to_net() { header.to_net(); body.to_net(); }
  343. };
  344. enum {
  345. fcgi_request_complete = 0,
  346. fcgi_cant_mpx_conn = 1,
  347. fcgi_overloaded = 2,
  348. fcgi_unknown_role = 3
  349. };
  350. struct fcgi_unknown_type_body {
  351. unsigned char type;
  352. unsigned char reserved[7];
  353. };
  354. struct fcgi_unknown_type_record {
  355. fcgi_header header;
  356. fcgi_unknown_type_body body;
  357. void to_host() { header.to_host();}
  358. void to_net() { header.to_net(); }
  359. };
  360. union fcgi_record {
  361. fcgi_header header;
  362. fcgi_begin_request_record begin ;
  363. fcgi_end_request_record end;
  364. fcgi_unknown_type_record unknown;
  365. };
  366. //
  367. //
  368. // end of defs
  369. //
  370. //
  371. //
  372. //
  373. void on_start_request(booster::system::error_code const &e,handler const &h)
  374. {
  375. if(e) {
  376. h(e);
  377. return;
  378. }
  379. if(header_.version!=fcgi_version_1)
  380. {
  381. h(booster::system::error_code(errc::protocol_violation,cppcms_category));
  382. return;
  383. }
  384. if(header_.type==fcgi_get_values) {
  385. header_.type = fcgi_get_values_result;
  386. std::vector<std::pair<std::string,std::string> > pairs;
  387. pairs.reserve(4);
  388. if(!parse_pairs(pairs)) {
  389. h(booster::system::error_code(errc::protocol_violation,cppcms_category));
  390. return;
  391. }
  392. body_.clear();
  393. std::locale l("C");
  394. std::ostringstream ss;
  395. ss.imbue(l);
  396. ss<<cuncurrency_hint_;
  397. for(unsigned i=0;i<pairs.size();i++) {
  398. std::string name=pairs[i].first;
  399. if(name=="FCGI_MAX_CONNS" || name=="FCGI_MAX_REQS")
  400. add_pair(name,ss.str());
  401. else if(name=="FCGI_MPXS_CONNS")
  402. add_pair(name,"0");
  403. }
  404. async_send_respnse(mfunc_to_event_handler(&fastcgi::on_params_response_sent,
  405. self(),
  406. h));
  407. }
  408. else if(header_.type!=fcgi_begin_request) {
  409. async_read_headers(h);
  410. return;
  411. }
  412. if(body_.size()!=sizeof(fcgi_request_body)) {
  413. h(booster::system::error_code(errc::protocol_violation,cppcms_category));
  414. return;
  415. }
  416. fcgi_request_body *body=reinterpret_cast<fcgi_request_body*>(&body_.front());
  417. body->to_host();
  418. keep_alive_=body->flags & fcgi_keep_conn;
  419. if(body->role!=fcgi_responder) {
  420. header_.type=fcgi_end_request;
  421. body_.assign(0,8);
  422. fcgi_end_request_body *body=reinterpret_cast<fcgi_end_request_body*>(&body_.front());
  423. body->protocol_status=fcgi_unknown_role;
  424. body->to_net();
  425. async_send_respnse(mfunc_to_event_handler(&fastcgi::on_params_response_sent,
  426. self(),
  427. h));
  428. return;
  429. }
  430. request_id_=header_.request_id;
  431. body_.clear();
  432. if(non_blocking_read_record()) {
  433. params_record_expected(booster::system::error_code(),h);
  434. }
  435. else {
  436. async_read_record(mfunc_to_event_handler(&fastcgi::params_record_expected,self(),h));
  437. }
  438. }
  439. uint32_t read_len(unsigned char const *&p,unsigned char const *e)
  440. {
  441. if (p<e && *p < 0x80) {
  442. return *p++;
  443. }
  444. else if(e-p >= 4) {
  445. uint32_t B3=*p++;
  446. uint32_t B2=*p++;
  447. uint32_t B1=*p++;
  448. uint32_t B0=*p++;
  449. uint32_t len = ((B3 & 0x7fU) << 24) + (B2 << 16) + (B1 << 8) + B0;
  450. return len;
  451. }
  452. else {
  453. return 0xFFFFFFFFu;
  454. }
  455. }
  456. bool parse_pairs()
  457. {
  458. unsigned char const *p=reinterpret_cast<unsigned char const *>(&body_.front());
  459. unsigned char const *e=p + body_.size();
  460. while(p<e) {
  461. uint32_t nlen=read_len(p,e);
  462. uint32_t vlen=read_len(p,e);
  463. if(nlen == 0xFFFFFFFFu || vlen == 0xFFFFFFFFu)
  464. return false;
  465. char *name=0;
  466. if(uint32_t(e - p) >= nlen) { // don't chage order -- prevent integer overflow
  467. name = pool_.add(reinterpret_cast<char const *>(p),nlen);
  468. p+=nlen;
  469. }
  470. else {
  471. return false;
  472. }
  473. char *value = 0;
  474. if(uint32_t(e - p) >= vlen) { // don't chage order -- prevent integer overflow
  475. value = pool_.add(reinterpret_cast<char const *>(p),vlen);
  476. p+=vlen;
  477. }
  478. else {
  479. return false;
  480. }
  481. env_.add(name,value);
  482. }
  483. return true;
  484. }
  485. bool parse_pairs(std::vector<std::pair<std::string,std::string> > &container)
  486. {
  487. unsigned char const *p=reinterpret_cast<unsigned char const *>(&body_.front());
  488. unsigned char const *e=p + body_.size();
  489. while(p<e) {
  490. uint32_t nlen=read_len(p,e);
  491. uint32_t vlen=read_len(p,e);
  492. if(nlen == 0xFFFFFFFFu || vlen == 0xFFFFFFFFu)
  493. return false;
  494. std::string name;
  495. if(uint32_t(e - p) >= nlen) { // don't chage order -- prevent integer overflow
  496. name.assign(reinterpret_cast<char const *>(p),nlen);
  497. p+=nlen;
  498. }
  499. else {
  500. return false;
  501. }
  502. std::string value;
  503. if(uint32_t(e - p) >= vlen) { // don't chage order -- prevent integer overflow
  504. value.assign(reinterpret_cast<char const *>(p),vlen);
  505. p+=vlen;
  506. }
  507. else {
  508. return false;
  509. }
  510. container.resize(container.size()+1);
  511. container.back().first.swap(name);
  512. container.back().second.swap(value);
  513. }
  514. return true;
  515. }
  516. void params_record_expected(booster::system::error_code const &e,handler const &h)
  517. {
  518. if(e) {
  519. h(e);
  520. return;
  521. }
  522. for(;;){
  523. if(header_.type!=fcgi_params || header_.request_id!=request_id_)
  524. h(booster::system::error_code(errc::protocol_violation,cppcms_category));
  525. if(header_.content_length!=0) { // eof
  526. if(body_.size() < 16384) {
  527. if(non_blocking_read_record()) {
  528. continue;
  529. }
  530. else {
  531. async_read_record(mfunc_to_event_handler(&fastcgi::params_record_expected,
  532. self(),
  533. h));
  534. }
  535. }
  536. else {
  537. h(booster::system::error_code(errc::protocol_violation,cppcms_category));
  538. }
  539. return;
  540. }
  541. break;
  542. }
  543. parse_pairs();
  544. body_.clear();
  545. char const *s_length = env_.get("CONTENT_LENGTH");
  546. if(!s_length || *s_length == 0 || (content_length_ = atoll(s_length)) <=0)
  547. content_length_=0;
  548. if(content_length_==0) {
  549. if(non_blocking_read_record()) {
  550. stdin_eof_expected(booster::system::error_code(),h);
  551. }
  552. else {
  553. async_read_record(mfunc_to_event_handler(
  554. &fastcgi::stdin_eof_expected,
  555. self(),
  556. h));
  557. }
  558. return;
  559. }
  560. h(booster::system::error_code());
  561. }
  562. void stdin_eof_expected(booster::system::error_code const &e,handler const &h)
  563. {
  564. if(e) { h(e); return; }
  565. if(header_.type!=fcgi_stdin || header_.content_length!=0) {
  566. h(booster::system::error_code(errc::protocol_violation,cppcms_category));
  567. return;
  568. }
  569. h(booster::system::error_code());
  570. }
  571. void on_params_response_sent(booster::system::error_code const &e,handler const &h)
  572. {
  573. if(e) { h(e); return; }
  574. async_read_headers(h);
  575. }
  576. // this is internal function for short messages
  577. void async_send_respnse(handler const &h)
  578. {
  579. header_.content_length=body_.size();
  580. if(body_.size() % 8 != 0) {
  581. header_.padding_length=8 - (body_.size() % 8);
  582. body_.resize(body_.size() + header_.padding_length);
  583. }
  584. io::const_buffer packet =
  585. io::buffer(&header_,sizeof(header_))
  586. + io::buffer(body_);
  587. header_.to_net();
  588. socket_.async_write(packet,io_handler_to_event_handler(h));
  589. }
  590. bool non_blocking_read_record()
  591. {
  592. fcgi_header hdr;
  593. if(!peek_bytes(&hdr,sizeof(hdr)))
  594. return false;
  595. hdr.to_host();
  596. size_t buffer_size = get_buffer_size();
  597. if(buffer_size < sizeof(hdr) + hdr.content_length + hdr.padding_length)
  598. return false;
  599. skip_bytes(sizeof(hdr));
  600. header_ = hdr;
  601. size_t cur_size=body_.size();
  602. size_t rec_size=header_.content_length+header_.padding_length;
  603. if(rec_size==0) {
  604. return true;
  605. }
  606. body_.resize(cur_size + rec_size);
  607. read_bytes(&body_[cur_size],rec_size);
  608. body_.resize(cur_size + header_.content_length);
  609. return true;
  610. }
  611. void async_read_record(handler const &h)
  612. {
  613. async_read_from_socket(&header_,sizeof(header_),
  614. mfunc_to_io_handler(
  615. &fastcgi::on_header_read,
  616. self(),
  617. h));
  618. }
  619. struct on_header_read_binder : public booster::callable<void(booster::system::error_code const &,size_t)> {
  620. handler h;
  621. booster::shared_ptr<fastcgi> self;
  622. on_header_read_binder(handler const &_h,booster::shared_ptr<fastcgi> const &s) : h(_h),self(s)
  623. {
  624. }
  625. virtual void operator()(booster::system::error_code const &e,size_t /*read*/)
  626. {
  627. self->on_body_read(e,h);
  628. }
  629. };
  630. void on_header_read(booster::system::error_code const &e,size_t /*unused read*/,handler const &h)
  631. {
  632. if(e) { h(e); return; }
  633. header_.to_host();
  634. size_t cur_size=body_.size();
  635. size_t rec_size=header_.content_length+header_.padding_length;
  636. if(rec_size==0) {
  637. h(booster::system::error_code());
  638. return;
  639. }
  640. body_.resize(cur_size + rec_size);
  641. std::auto_ptr<booster::callable<void(booster::system::error_code const &,size_t)> > cb;
  642. cb.reset(new on_header_read_binder(h,self()));
  643. async_read_from_socket(
  644. &body_[cur_size],rec_size,
  645. cb);
  646. }
  647. void on_body_read(booster::system::error_code const &e,handler const &h)
  648. {
  649. if(e) { h(e); return; }
  650. body_.resize(body_.size() - header_.padding_length);
  651. h(booster::system::error_code());
  652. }
  653. void add_value(std::string const &value)
  654. {
  655. if(value.size() <128) {
  656. body_.push_back(char(value.size()));
  657. }
  658. else {
  659. uint32_t size=value.size();
  660. size |= 0x80000000u;
  661. size=htonl(size);
  662. char *p=(char*)&size;
  663. body_.insert(body_.end(),p,p+sizeof(size));
  664. }
  665. }
  666. void add_pair(std::string const &name,std::string const &value)
  667. {
  668. add_value(name);
  669. add_value(value);
  670. body_.insert(body_.end(),name.begin(),name.end());
  671. body_.insert(body_.end(),value.begin(),value.end());
  672. }
  673. booster::shared_ptr<fastcgi> self()
  674. {
  675. return booster::static_pointer_cast<fastcgi>(shared_from_this());
  676. }
  677. friend class socket_acceptor<fastcgi>;
  678. io::stream_socket socket_;
  679. fcgi_header header_;
  680. fcgi_header full_header_;
  681. std::vector<char> body_;
  682. long long read_length_;
  683. long long content_length_;
  684. unsigned body_ptr_;
  685. int request_id_;
  686. bool keep_alive_;
  687. int cuncurrency_hint_;
  688. struct eof_str {
  689. fcgi_header headers_[2];
  690. fcgi_end_request_body record_;
  691. } eof_;
  692. std::vector<char> cache_;
  693. size_t cache_start_,cache_end_;
  694. bool eof_callback_;
  695. void reset_all()
  696. {
  697. memset(&header_,0,sizeof(header_));
  698. body_.clear();
  699. read_length_=content_length_=0;
  700. body_ptr_=0;
  701. request_id_=0;
  702. keep_alive_=false;
  703. env_.clear();
  704. pool_.clear();
  705. memset(&eof_,0,sizeof(eof_));
  706. if(cache_.empty()) {
  707. cache_start_ = 0;
  708. cache_end_ = 0;
  709. }
  710. }
  711. bool peek_bytes(void *ptr,size_t n)
  712. {
  713. if(cache_end_ - cache_start_ >= n) {
  714. memcpy(ptr,&cache_[cache_start_],n);
  715. return true;
  716. }
  717. return false;
  718. }
  719. size_t get_buffer_size()
  720. {
  721. return cache_end_ - cache_start_;
  722. }
  723. void skip_bytes(size_t n)
  724. {
  725. assert(cache_end_ - cache_start_ >= n);
  726. cache_start_ +=n;
  727. }
  728. void read_bytes(void *ptr,size_t n)
  729. {
  730. assert(cache_end_ - cache_start_ >=n);
  731. memcpy(ptr,&cache_[cache_start_],n);
  732. cache_start_+=n;
  733. }
  734. void async_read_from_socket(void *ptr,size_t n,booster::aio::io_handler const &cb)
  735. {
  736. if(cache_end_ - cache_start_ >=n) {
  737. memcpy(ptr,&cache_[cache_start_],n);
  738. cache_start_+=n;
  739. socket_.get_io_service().post(cb,booster::system::error_code(),n);
  740. return;
  741. }
  742. if(cache_start_ == cache_end_) {
  743. cache_start_ = cache_end_ = 0;
  744. }
  745. else if(cache_start_!=0) {
  746. memmove(&cache_[0],&cache_[cache_start_],cache_end_ - cache_start_);
  747. cache_end_ = cache_end_ - cache_start_;
  748. cache_start_ = 0;
  749. }
  750. size_t min_size = std::max(n,size_t(16384));
  751. if(cache_.size() < n) {
  752. cache_.resize(min_size,0);
  753. }
  754. socket_.async_read_some(
  755. booster::aio::buffer(&cache_[cache_end_],cache_.size() - cache_end_),
  756. mfunc_to_io_handler(
  757. &fastcgi::on_some_read_from_socket,
  758. self(),
  759. cb,
  760. std::make_pair(ptr,n)));
  761. }
  762. void on_some_read_from_socket( booster::system::error_code const &e,
  763. size_t read_size,
  764. booster::callback<void(booster::system::error_code const &e,size_t read)> const &cb,
  765. std::pair<void *,size_t> inp)
  766. {
  767. void *ptr = inp.first;
  768. size_t expected_read_size = inp.second;
  769. cache_end_ += read_size;
  770. if(e) {
  771. cb(e,0);
  772. return;
  773. }
  774. async_read_from_socket(ptr,expected_read_size,cb);
  775. }
  776. };
  777. std::auto_ptr<acceptor> fastcgi_api_tcp_socket_factory(cppcms::service &srv,std::string ip,int port,int backlog)
  778. {
  779. std::auto_ptr<acceptor> a(new socket_acceptor<fastcgi>(srv,ip,port,backlog));
  780. return a;
  781. }
  782. #if !defined(CPPCMS_WIN32)
  783. std::auto_ptr<acceptor> fastcgi_api_unix_socket_factory(cppcms::service &srv,std::string socket,int backlog)
  784. {
  785. std::auto_ptr<acceptor> a(new socket_acceptor<fastcgi>(srv,socket,backlog));
  786. return a;
  787. }
  788. std::auto_ptr<acceptor> fastcgi_api_unix_socket_factory(cppcms::service &srv,int backlog)
  789. {
  790. std::auto_ptr<acceptor> a(new socket_acceptor<fastcgi>(srv,backlog));
  791. return a;
  792. }
  793. #endif
  794. } // cgi
  795. } // impl
  796. } // cppcms