1. #include <cstdlib>
  2. #include <iostream>
  3. #include <boost/bind.hpp>
  4. #include <boost/smart_ptr.hpp>
  5. #include <boost/asio.hpp>
  6. #include <boost/thread.hpp>
  7. #include <boost/regex.hpp>
  8. #include <boost/lexical_cast.hpp>
  9. #include <string>
  10.  
  11. using boost::asio::ip::tcp;
  12. const int max_length = 1000000;
  13.  
  14. typedef boost::shared_ptr<tcp::socket> socket_ptr;
  15.  
  16. unsigned short analyze_user_request(std::string& user_request, short unsigned* ID, std::string* request_value)
  17. {
  18.   // function returns:
  19.   // 0: if user request is incorrect
  20.   // 1: if user requests "PUT" operation
  21.   // 2: if user requests "GET" operation
  22.   // Furthermore, if request is correct, its value (i.e. ID number and/or string) is saved to short unsigned and string values passed by pointers.
  23.  
  24.  boost::regex exp("^[[:space:]]*(PUT|GET)[[:space:]]+([[:digit:]]{1,2})(?:[[:space:]]+(.*))?$");
  25.  
  26.   boost::smatch what;
  27.   if (regex_match(user_request, what, exp, boost::match_extra))
  28.    {
  29.      short unsigned id_number = boost::lexical_cast<short unsigned>(what[2]);
  30.      
  31.      if (what[1] == "PUT")
  32.        {
  33.          boost::regex exp1("^[a-zA-Z0-9]+$");
  34.      std::string value = boost::lexical_cast<std::string>(what[3]);
  35.      if (value.length() > 4095)
  36.        return 0;
  37.      if (!regex_match(value, exp1))
  38.        return 0;
  39.      else
  40.        {
  41.           *request_value = value;
  42.           *ID = id_number;
  43.          return 1;
  44.            }
  45.        }
  46.    
  47.      if (what[1] == "GET")
  48.        {
  49.      *ID = id_number;
  50.          return 2;
  51.        }
  52.      
  53.    }
  54.  
  55.   if (!regex_match(user_request, what, exp, boost::match_extra))
  56.     return 0;
  57.    }
  58.  
  59.  
  60. class Session
  61. {
  62. public:
  63.   void handleRequest(socket_ptr sock)
  64. {
  65.   try
  66.   {
  67.     for (;;)
  68.     {
  69.       char data[max_length];
  70.  
  71.       boost::system::error_code error;
  72.       size_t length = sock->read_some(boost::asio::buffer(data), error);
  73.       if (error == boost::asio::error::eof)
  74.         break; // Connection closed cleanly by peer.
  75.       else if (error)
  76.         throw boost::system::system_error(error); // Some other error.
  77.       // convert buffer data to string for further procession
  78.       std::string line(boost::asio::buffers_begin(boost::asio::buffer(data)), boost::asio::buffers_begin(boost::asio::buffer(data)) + length);
  79.       std::string reply; // will be "QK", "INVALID", or "OK <value>"
  80.            unsigned short vID;
  81.      
  82.       unsigned short* ID = &vID;
  83.       std::string vrequest_value;
  84.       std::string* request_value = &vrequest_value;
  85.      
  86.       unsigned short output = analyze_user_request(line, ID, request_value);
  87.      
  88.       if (output == 1)
  89.     {
  90.     // PUT   
  91.       reply = "OK";
  92.       user_array[*ID] = *request_value;
  93.     }
  94.      
  95.         else if (output == 2)
  96.       {
  97.         // GET
  98.         reply = user_array[*ID];
  99.         if (reply == "")
  100.           reply = "EMPTY";
  101.       }
  102.      
  103.     else
  104.       reply = "INVALID";
  105.  
  106.             boost::system::error_code ignored_error;
  107.             size_t ans_len=reply.length();
  108.         boost::asio::write(*sock, boost::asio::buffer(reply));
  109.     }
  110.   }
  111.   catch (std::exception& e)
  112.   {
  113.     std::cerr << "Exception in thread: " << e.what() << "\n";
  114.   }
  115. }
  116.  
  117. private:
  118.   std::string user_array[100];
  119. };
  120.  
  121. typedef boost::shared_ptr<Session> SessionPtr;
  122.  
  123. void server(boost::asio::io_service& io_service, short port)
  124. {
  125.   tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
  126.   for (;;)
  127.   {
  128.     socket_ptr sock(new tcp::socket(io_service));
  129.     a.accept(*sock);
  130.     SessionPtr newSession(new Session());
  131.     boost::thread acceptThread(boost::bind(&Session::handleRequest, newSession, sock));
  132.   }
  133. }
  134.  
  135. int main(int argc, char* argv[])
  136. {
  137.   try
  138.   {
  139.     if (argc != 2)
  140.     {
  141.       std::cerr << "Usage: blocking_tcp_echo_server <port>\n";
  142.       return 1;
  143.     }
  144.  
  145.     boost::asio::io_service io_service;
  146.  
  147.     using namespace std; // For atoi.
  148.     server(io_service, atoi(argv[1]));
  149.   }
  150.   catch (std::exception& e)
  151.   {
  152.     std::cerr << "Exception: " << e.what() << "\n";
  153.   }
  154.  
  155.   return 0;
  156. }
  157.  
  158.