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.
 
 
 
 
 
 

195 lines
4.9 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 <iostream>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <cppcms/config.h>
  18. #include <booster/aio/buffer.h>
  19. #include <string.h>
  20. #include "binder.h"
  21. namespace io = booster::aio;
  22. namespace cppcms {
  23. namespace impl {
  24. namespace cgi {
  25. template<typename API,typename Factory> class socket_acceptor;
  26. class scgi : public connection {
  27. public:
  28. scgi(cppcms::service &srv) :
  29. connection(srv),
  30. start_(0),
  31. end_(0),
  32. socket_(srv.impl().get_io_service()),
  33. eof_callback_(false)
  34. {
  35. }
  36. ~scgi()
  37. {
  38. if(socket_.native()!=io::invalid_socket) {
  39. booster::system::error_code e;
  40. socket_.shutdown(io::stream_socket::shut_rdwr,e);
  41. }
  42. }
  43. virtual void async_read_headers(handler const &h)
  44. {
  45. buffer_.resize(16);
  46. socket_.async_read(
  47. io::buffer(buffer_),
  48. mfunc_to_io_handler(
  49. &scgi::on_first_read,
  50. self(),
  51. h));
  52. }
  53. void on_first_read(booster::system::error_code const &e,size_t n,handler const &h)
  54. {
  55. if(e) {
  56. h(e);
  57. return;
  58. }
  59. sep_=std::find(buffer_.begin(),buffer_.begin()+n,':') - buffer_.begin();
  60. if(sep_ >= 16) {
  61. h(booster::system::error_code(errc::protocol_violation,cppcms_category));
  62. return;
  63. }
  64. buffer_[sep_]=0;
  65. int len=atoi(&buffer_.front());
  66. if(len < 0 || 16384 < len) {
  67. h(booster::system::error_code(errc::protocol_violation,cppcms_category));
  68. return;
  69. }
  70. size_t size=n;
  71. buffer_.resize(sep_ + 2 + len); // len of number + ':' + content + ','
  72. if(buffer_.size() <= size) {
  73. // It can't be so short so
  74. h(booster::system::error_code(errc::protocol_violation,cppcms_category));
  75. return;
  76. }
  77. socket_.async_read(
  78. io::buffer(&buffer_[size],buffer_.size() - size),
  79. mfunc_to_io_handler(
  80. &scgi::on_headers_chunk_read,
  81. self(),
  82. h));
  83. }
  84. void on_headers_chunk_read(booster::system::error_code const &e,size_t ,handler const &h)
  85. {
  86. if(e) { h(e); return; }
  87. if(buffer_.back()!=',') {
  88. buffer_.back() = 0;
  89. // make sure it is NUL terminated
  90. h(booster::system::error_code(errc::protocol_violation,cppcms_category));
  91. return;
  92. }
  93. char const *p=&buffer_[sep_ + 1];
  94. while(p < &buffer_.back()) {
  95. char *key=pool_.add(p);
  96. p+=strlen(p)+1;
  97. if(p>=&buffer_.back())
  98. break;
  99. char *value=pool_.add(p);
  100. p+=strlen(p)+1;
  101. env_.add(key,value);
  102. }
  103. buffer_.clear();
  104. h(booster::system::error_code());
  105. }
  106. virtual void on_async_write_start() {}
  107. virtual void on_async_write_progress(bool) {}
  108. virtual booster::aio::const_buffer format_output(booster::aio::const_buffer const &in,bool /*comleted*/,booster::system::error_code &/*e*/)
  109. {
  110. return in;
  111. }
  112. virtual void async_read_some(void *p,size_t s,io_handler const &h)
  113. {
  114. socket_.async_read_some(io::buffer(p,s),h);
  115. }
  116. virtual booster::aio::io_service &get_io_service()
  117. {
  118. return socket_.get_io_service();
  119. }
  120. virtual bool keep_alive()
  121. {
  122. return false;
  123. }
  124. virtual void do_eof()
  125. {
  126. if(eof_callback_)
  127. socket_.cancel();
  128. eof_callback_ = false;
  129. booster::system::error_code e;
  130. socket_.shutdown(io::stream_socket::shut_wr,e);
  131. socket_.close(e);
  132. }
  133. struct ignore_io {
  134. callback h;
  135. void operator()(booster::system::error_code const &,size_t) { h(); }
  136. };
  137. virtual void async_read_eof(callback const &h)
  138. {
  139. eof_callback_ = true;
  140. static char a;
  141. ignore_io cb = { h };
  142. socket_.async_read_some(io::buffer(&a,1),cb);
  143. }
  144. virtual booster::aio::stream_socket &socket() { return socket_; }
  145. private:
  146. size_t start_,end_,sep_;
  147. booster::shared_ptr<scgi> self()
  148. {
  149. return booster::static_pointer_cast<scgi>(shared_from_this());
  150. }
  151. friend class socket_acceptor<scgi>;
  152. io::stream_socket socket_;
  153. std::vector<char> buffer_;
  154. bool eof_callback_;
  155. };
  156. std::auto_ptr<acceptor> scgi_api_tcp_socket_factory(cppcms::service &srv,std::string ip,int port,int backlog)
  157. {
  158. std::auto_ptr<acceptor> a(new socket_acceptor<scgi>(srv,ip,port,backlog));
  159. return a;
  160. }
  161. #if !defined(CPPCMS_WIN32)
  162. std::auto_ptr<acceptor> scgi_api_unix_socket_factory(cppcms::service &srv,std::string socket,int backlog)
  163. {
  164. std::auto_ptr<acceptor> a(new socket_acceptor<scgi>(srv,socket,backlog));
  165. return a;
  166. }
  167. std::auto_ptr<acceptor> scgi_api_unix_socket_factory(cppcms::service &srv,int backlog)
  168. {
  169. std::auto_ptr<acceptor> a(new socket_acceptor<scgi>(srv,backlog));
  170. return a;
  171. }
  172. #endif
  173. } // cgi
  174. } // impl
  175. } // cppcms