Samchon Framework for CPP  1.0.0
WebServer.hpp
1 #pragma once
2 #include <samchon/API.hpp>
3 
4 #include <samchon/protocol/Server.hpp>
5 #include <samchon/protocol/WebClientDriver.hpp>
6 
7 #include <sstream>
8 #include <samchon/WeakString.hpp>
9 #include <samchon/library/StringUtil.hpp>
10 #include <samchon/protocol/WebSocketUtil.hpp>
11 
12 namespace samchon
13 {
14 namespace protocol
15 {
49  class WebServer
50  : public virtual Server
51  {
52  private:
53  typedef Server super;
54 
55  size_t sequence;
56 
57  public:
62  : super()
63  {
64  sequence = 0;
65  };
66  virtual ~WebServer() = default;
67 
68  private:
69  virtual void handle_connection(std::shared_ptr<boost::asio::ip::tcp::socket> socket) override
70  {
71  std::array<char, 1000> byte_array;
72  boost::system::error_code error;
73 
75  // LISTEN HEADER
77  size_t size = socket->read_some(boost::asio::buffer(byte_array), error);
78  if (error)
79  return;
80 
81  // HEADER FROM CLIENT
82  WeakString header(byte_array.data(), size);
83 
84  // KEY VALUES
85  WeakString path = header.between("", "\r\n").between(" /", " HTTP");
86  std::string session_id;
87  std::string cookie;
88 
89  WeakString encrypted_cert_key;
90 
91  // DECODE ENCRYPTED CERTIFICATION KEY
92  encrypted_cert_key = header.between("Sec-WebSocket-Key:", "\n").trim();
93 
94  if (encrypted_cert_key.find("\r") != std::string::npos)
95  encrypted_cert_key = encrypted_cert_key.between("", "\r");
96 
97  if (header.find("Set-Cookie: ") != std::string::npos)
98  {
99  cookie = header.between("Set-Cookie: ", "\r\n");
100 
101  size_t session_id_idx = header.find("SESSION_ID=");
102  if (session_id_idx == std::string::npos)
103  {
104  // ISSUE A NEW SESSION_ID AND ADD IT TO ORDINARY COOKIES
105  session_id = issue_session_id();
106  cookie += "; SESSION_ID=" + session_id;
107  }
108  else
109  {
110  // FETCH ORDINARY SESSION_ID
111  session_id = header.substr
112  (
113  session_id_idx + 11,
114  std::min
115  (
116  header.find(";", session_id_idx),
117  header.find("\r\n", session_id_idx)
118  )
119  );
120  }
121  }
122  else
123  {
124  // NO COOKIE EXISTS
125  session_id = issue_session_id();
126  cookie = "SESSION_ID=" + session_id;
127  }
128 
130  // SEND HEADER
132  // CONSTRUCT REPLY MESSAGE
133  std::string &reply_header = library::StringUtil::substitute
134  (
135  std::string("") +
136  "HTTP/1.1 101 Switching Protocols\r\n" +
137  "Upgrade: websocket\r\n" +
138  "Connection: Upgrade\r\n" +
139  "Set-Cookie: {1}\r\n" +
140  "Sec-WebSocket-Accept: {2}\r\n" +
141  "\r\n",
142 
143  cookie,
144  WebSocketUtil::encode_certification_key(encrypted_cert_key)
145  );
146 
147  // SEND
148  socket->write_some(boost::asio::buffer(reply_header), error);
149  if (error)
150  return;
151 
153  // ADD CLIENT
155  // CREATE DRIVER
156  std::shared_ptr<WebClientDriver> driver(new WebClientDriver(socket));
157  driver->session_id = session_id;
158  driver->path = path.str();
159 
160  // ADD CLIENT
161  addClient(driver);
162  };
163 
164  auto issue_session_id() -> std::string
165  {
166  static std::uniform_int_distribution<unsigned int> distribution(0, UINT32_MAX);
167  static std::random_device device;
168 
169  unsigned int port = _Acceptor->local_endpoint().port();
170  size_t uid = ++sequence;
171  long long linux_time = library::Date().toLinuxTime();
172  unsigned int rand = distribution(device);
173 
174  std::stringstream ss;
175  ss << std::hex << port;
176  ss << std::hex << uid;
177  ss << std::hex << linux_time;
178  ss << std::hex << rand;
179 
180  return ss.str();
181  };
182  };
183 };
184 };
virtual void addClient(std::shared_ptr< ClientDriver >)=0
static auto substitute(const std::string &format, const T &val, const _Args &...args) -> std::string
Substitutes "{n}" tokens within the specified string with the respective arguments passed in...
Definition: StringUtil.hpp:54
auto between(const WeakString &start={}, const WeakString &end={}) const -> WeakString
Generates a substring.
Definition: WeakString.hpp:475
auto find(const WeakString &delim, size_t startIndex=NULL) const -> size_t
Finds first occurence in string.
Definition: WeakString.hpp:273
Date (year, month, day in month)
Definition: Date.hpp:38
auto toLinuxTime() const -> long long
Converts the Date to linux_time.
Definition: Date.hpp:575
A string class only references characeters, reference only.
Definition: WeakString.hpp:35