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.
 
 
 
 
 
 

141 lines
3.1 KiB

  1. #ifndef CPPCMS_HTP_CONNECTION_SCGI_H
  2. #define CPPCMS_HTP_CONNECTION_SCGI_H
  3. #include "http_connection.h"
  4. #include "asio_config.h"
  5. namespace cppcms { namespace http {
  6. template<typename Socket>
  7. class scgi_connection : public connection {
  8. aio::streambuf buf_;
  9. std::vector<char> data_;
  10. std::map<std::string,std::string> env_;
  11. Socket socket_;
  12. void on_done(error_code const &e,boost::fuction<void(bool>) callback)
  13. {
  14. callback(bool(e));
  15. }
  16. int check_size(aio::buffer &buf)
  17. {
  18. std::istream s(&buf);
  19. size_t n;
  20. s>>n;
  21. if(s.failbit())
  22. return -1;
  23. return n;
  24. }
  25. bool parse_env(std::vector<char> const &s)
  26. {
  27. if(s.back()!=',')
  28. return false;
  29. std::vector<char>::const_iterator b,e,p;
  30. b=s.begin(); e=s.begin()+s.size()-1;
  31. while(b!=e) {
  32. p=std::find(b,e,0);
  33. if(p==e)
  34. return false;
  35. std::string key(b,p);
  36. b=p+1;
  37. p=std::find(b,e,0);
  38. if(p==e)
  39. return false;
  40. std::string val(b,p);
  41. b=p+1;
  42. env_.insert(std::make_pair(key,val));
  43. }
  44. if(env_.find("CONTENT_LENGTH")==env_.end())
  45. return false;
  46. return true;
  47. }
  48. public:
  49. virtual bool keep_alive() { return false; }
  50. virtual size_t read(void *buffer,size_t s)
  51. {
  52. return aio::read(socket_,aio::buffer(buffer,s));
  53. }
  54. virtual size_t write(void const *buffer,size_t s)
  55. {
  56. return aio::write(socket_,aio::buffer(buffer,s));
  57. }
  58. virtual bool prepare()
  59. {
  60. try {
  61. aio::read_until(socket_,buf_,':');
  62. int n=check_size(buf);
  63. if(n<0)
  64. return false;
  65. data_.resize(n+1,0);
  66. if(aio::read(socket_,aio::buffer(data))!=n+1)
  67. return false;
  68. if(!parse_env(data))
  69. return false;
  70. }
  71. catch(std::exception const &e) {
  72. return false;
  73. }
  74. return true;
  75. }
  76. virtual aio::io_service &io_service()
  77. {
  78. return socket_.io_service();
  79. }
  80. virtual void async_read(void *buffer,size_t s,boost::function<void(bool)> c)
  81. {
  82. aio::async_read(socket_,aio::buffer(buffer,s),
  83. boost::bind(&scgi_connection<Socket>::on_done,shared_from_this(),aio::placeholders::error,c));
  84. }
  85. virtual void async_write(void const *buffer,size_t s,boost::function<void(bool)> c)
  86. {
  87. aio::async_write(socket_,aio::buffer(buffer,s),
  88. boost::bind(&scgi_connection<Socket>::on_done,shared_from_this(),aio::placeholders::error,c));
  89. }
  90. virtual void async_prepare(boost::function<void(bool)> c)
  91. {
  92. aio::async_read_until(socket_,buf_,':',
  93. boost::bind(&scgi_connection<Socket>::on_net_read,shared_from_this(),aio::placeholders::error,c));
  94. }
  95. private:
  96. void on_net_read(error_code const &e,boost::function<void(bool)> c)
  97. {
  98. if(e) {
  99. c(false);
  100. return;
  101. }
  102. int n=check_size(buf);
  103. if(n<0) {
  104. c(false) ;
  105. return;
  106. }
  107. data_.resize(n+1,0);
  108. aio::async_read(socket_,aio::buffer(data_),
  109. boost::bind(&scgi_connection<Socket>::on_env_read,aio::placeholders::error,c));
  110. }
  111. void on_env_read(error_code const &e,boost::function<void(bool)>)
  112. {
  113. if(e) {
  114. c(false);
  115. return;
  116. }
  117. if(!parse_env(data)) {
  118. c(false);
  119. return;
  120. }
  121. c(true);
  122. }
  123. public:
  124. virtual std::string getenv(std::string const &key)
  125. {
  126. std::map<std::string,std::string>::iterator p;
  127. p=env_.find(key);
  128. if(p==env_.end())
  129. return std::string();
  130. return p->second;
  131. }
  132. }; // connection_scgi
  133. } }
  134. #endif