Server.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // Copyright 2018, University of Freiburg,
  2. // Chair of Algorithms and Data Structures.
  3. // Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
  4. #ifndef ZLIB_CONST
  5. #define ZLIB_CONST
  6. #endif
  7. #include <fcntl.h>
  8. #include <netdb.h>
  9. #include <netinet/in.h>
  10. #include <netinet/tcp.h>
  11. #include <algorithm>
  12. #include <memory>
  13. #include <sstream>
  14. #include <stdexcept>
  15. #include <thread>
  16. #include <unordered_map>
  17. #ifdef ZLIB_FOUND
  18. #include <zlib.h>
  19. #endif
  20. #include <vector>
  21. #include "Server.h"
  22. #include "util/String.h"
  23. using util::http::Socket;
  24. using util::http::Queue;
  25. using util::http::Req;
  26. using util::http::HttpErr;
  27. using util::http::HttpServer;
  28. using util::http::HeaderState;
  29. // _____________________________________________________________________________
  30. Socket::Socket(int port) {
  31. int y = 1;
  32. _sock = socket(PF_INET, SOCK_STREAM, 0);
  33. if (_sock < 0)
  34. throw std::runtime_error(std::string("Could not create socket (") +
  35. std::strerror(errno) + ")");
  36. struct sockaddr_in addr;
  37. addr.sin_family = AF_INET;
  38. addr.sin_port = htons(port);
  39. addr.sin_addr.s_addr = INADDR_ANY;
  40. memset(&(addr.sin_zero), '\0', 8);
  41. setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(y));
  42. if (bind(_sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
  43. throw std::runtime_error(std::string("Could not bind to port ") +
  44. std::to_string(port) + " (" +
  45. std::strerror(errno) + ")");
  46. }
  47. }
  48. // _____________________________________________________________________________
  49. Socket::~Socket() { close(_sock); }
  50. // _____________________________________________________________________________
  51. int Socket::wait() {
  52. if (listen(_sock, BLOG) < 0)
  53. throw std::runtime_error(std::string("Cannot listen to socket (") +
  54. std::strerror(errno) + ")");
  55. sockaddr_in cli_addr;
  56. socklen_t clilen = sizeof(cli_addr);
  57. int sock = accept(_sock, reinterpret_cast<sockaddr*>(&cli_addr), &clilen);
  58. return sock;
  59. }
  60. // _____________________________________________________________________________
  61. void HttpServer::send(int sock, Answer* aw) {
  62. std::string enc = "identity";
  63. if (aw->gzip) aw->pl = compress(aw->pl, &enc);
  64. aw->params["Content-Encoding"] = enc;
  65. aw->params["Content-Length"] = std::to_string(aw->pl.size());
  66. std::stringstream ss;
  67. ss << "HTTP/1.1 " << aw->status << "\r\n";
  68. for (const auto& kv : aw->params)
  69. ss << kv.first << ": " << kv.second << "\r\n";
  70. ss << "\r\n" << aw->pl;
  71. std::string buff = ss.str();
  72. size_t writes = 0;
  73. while (writes != buff.size()) {
  74. int64_t out = write(sock, buff.c_str() + writes, buff.size() - writes);
  75. if (out < 0) {
  76. if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR) continue;
  77. throw std::runtime_error("Failed to write to socket");
  78. }
  79. writes += out;
  80. }
  81. }
  82. // _____________________________________________________________________________
  83. void HttpServer::handle() {
  84. int connection = -1;
  85. while ((connection = _jobs.get()) != -1) {
  86. Answer answ;
  87. try {
  88. Req req = getReq(connection);
  89. answ = _handler->handle(req, connection);
  90. answ.gzip = gzipSupport(req);
  91. } catch (const HttpErr& err) {
  92. answ = Answer(err.what(), err.what());
  93. } catch (...) {
  94. // catch everything to make sure the server continues running
  95. answ = Answer("500 Internal Server Error", "500 Internal Server Error");
  96. }
  97. send(connection, &answ);
  98. close(connection);
  99. }
  100. }
  101. // _____________________________________________________________________________
  102. bool HttpServer::gzipSupport(const Req& req) {
  103. bool accepts = false;
  104. // decide according to
  105. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
  106. for (const auto& kv : req.params) {
  107. if (kv.first == "Accept-Encoding") {
  108. for (const auto& encoding : split(kv.second, ',')) {
  109. std::vector<std::string> parts = split(encoding, ';');
  110. for (size_t i = 0; i < parts.size(); i++) {
  111. parts[i] = trim(parts[i]);
  112. }
  113. if (parts[0] == "*" && ((parts.size() == 1) || parts[1] != "q=0"))
  114. accepts = true;
  115. if (parts[0] == "gzip") accepts = true;
  116. if (parts.size() > 1 && parts[1] == "q=0") accepts = false;
  117. }
  118. }
  119. }
  120. return accepts;
  121. }
  122. // _____________________________________________________________________________
  123. Req HttpServer::getReq(int connection) {
  124. char buf[BSIZE + 1];
  125. size_t rcvd = 0;
  126. int64_t curRcvd = 0;
  127. HeaderState state = NONE;
  128. Req ret;
  129. char* tmp = 0;
  130. char* tmp2 = 0;
  131. char* brk = 0;
  132. while ((curRcvd = read(connection, buf + rcvd, BSIZE - rcvd))) {
  133. if (curRcvd < 0) {
  134. if (errno == EAGAIN || errno == EINTR) continue;
  135. throw HttpErr("500 Internal Server Error");
  136. }
  137. // parse request
  138. for (int i = 0; i < curRcvd; i++) {
  139. if (brk) break;
  140. char* c = buf + rcvd + i;
  141. switch (state) {
  142. case NONE:
  143. state = I_COM;
  144. tmp = c;
  145. continue;
  146. case I_VER:
  147. if (*c == '\n') {
  148. *c = 0;
  149. ret.ver = trim(tmp);
  150. state = A_KEY;
  151. }
  152. continue;
  153. case I_URL:
  154. if (*c == ' ') {
  155. *c = 0, ret.url = trim(tmp);
  156. tmp = c + 1;
  157. state = I_VER;
  158. } else if (*c == '\n') {
  159. *c = 0, ret.url = trim(tmp);
  160. state = A_KEY;
  161. }
  162. continue;
  163. case I_COM:
  164. if (*c == ' ') {
  165. *c = 0, ret.cmd = trim(tmp);
  166. tmp = c + 1;
  167. state = I_URL;
  168. } else if (*c == '\n') {
  169. *c = 0, ret.cmd = trim(tmp);
  170. state = A_KEY;
  171. }
  172. continue;
  173. case A_KEY:
  174. if (*c == '\r') *c = ' ';
  175. if (*c == '\n')
  176. brk = c + 1;
  177. else if (*c != ' ') {
  178. state = I_KEY;
  179. tmp = c;
  180. }
  181. continue;
  182. case I_KEY:
  183. if (*c == ':') {
  184. *c = 0;
  185. state = A_VAL;
  186. }
  187. continue;
  188. case A_VAL:
  189. if (*c != ' ') {
  190. state = I_VAL;
  191. tmp2 = c;
  192. }
  193. continue;
  194. case I_VAL:
  195. if (*c == '\r') *c = ' ';
  196. if (*c == '\n') {
  197. *c = 0;
  198. ret.params[tmp] = trim(tmp2);
  199. state = A_KEY;
  200. }
  201. continue;
  202. }
  203. }
  204. rcvd += curRcvd;
  205. // buffer is full
  206. if (rcvd == BSIZE) throw HttpErr("431 Request Header Fields Too Large");
  207. if (brk) break;
  208. }
  209. // POST payload
  210. if (ret.cmd == "POST") {
  211. size_t size = 0;
  212. if (ret.params.count("Content-Length"))
  213. size = atoi(ret.params["Content-Length"].c_str());
  214. if (size) {
  215. char* postBuf = new char[size + 1];
  216. postBuf[size] = 0;
  217. size_t rem = 0;
  218. // copy existing to new buffer
  219. if ((int)rcvd > brk - buf) {
  220. rem = std::min(size, rcvd - (brk - buf));
  221. memcpy(postBuf, brk, rem);
  222. }
  223. rcvd = 0;
  224. if (rem < size) {
  225. while ((curRcvd = read(connection, postBuf + rcvd + rem, size - rem))) {
  226. if (curRcvd == -1 && (errno == EAGAIN || errno == EINTR)) continue;
  227. if (curRcvd == -1) {
  228. postBuf[rcvd + 1] = 0;
  229. break;
  230. }
  231. rcvd += curRcvd;
  232. if (rcvd == size - rem) break;
  233. }
  234. }
  235. ret.payload = postBuf;
  236. delete[] postBuf;
  237. }
  238. }
  239. return ret;
  240. }
  241. // _____________________________________________________________________________
  242. std::string HttpServer::compress(const std::string& str, std::string* enc) {
  243. #ifdef ZLIB_FOUND
  244. // do not compress small payloads
  245. if (str.size() < 500) return str;
  246. std::string ret;
  247. // based on http://www.zlib.net/zlib_how.html
  248. z_stream defStr;
  249. defStr.zalloc = Z_NULL;
  250. defStr.zfree = Z_NULL;
  251. defStr.opaque = Z_NULL;
  252. defStr.avail_in = 0;
  253. defStr.next_in = Z_NULL;
  254. // fail silently with no compression at all
  255. if (deflateInit2(&defStr, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8,
  256. Z_DEFAULT_STRATEGY) != Z_OK)
  257. return str;
  258. defStr.next_in = reinterpret_cast<z_const Bytef*>(str.c_str());
  259. defStr.avail_in = static_cast<unsigned int>(str.size());
  260. size_t cSize = 0;
  261. do {
  262. if (ret.size() < (cSize + BSIZE_C)) ret.resize(cSize + BSIZE_C);
  263. defStr.avail_out = BSIZE_C;
  264. defStr.next_out = reinterpret_cast<Bytef*>(&ret[0] + cSize);
  265. deflate(&defStr, Z_FINISH);
  266. cSize += BSIZE_C - defStr.avail_out;
  267. } while (defStr.avail_out == 0);
  268. deflateEnd(&defStr);
  269. ret.resize(cSize);
  270. if (ret.size() > str.size()) return str;
  271. *enc = "gzip";
  272. return ret;
  273. #else
  274. return str;
  275. #endif
  276. }
  277. // _____________________________________________________________________________
  278. void HttpServer::run() {
  279. Socket socket(_port);
  280. std::vector<std::thread> thrds(_threads);
  281. for (auto& thr : thrds) thr = std::thread(&HttpServer::handle, this);
  282. while (1) _jobs.add(socket.wait());
  283. }
  284. // _____________________________________________________________________________
  285. void Queue::add(int c) {
  286. if (c < 0) return;
  287. {
  288. std::unique_lock<std::mutex> lock(_mut);
  289. _jobs.push(c);
  290. }
  291. _hasNew.notify_one();
  292. }
  293. // _____________________________________________________________________________
  294. int Queue::get() {
  295. std::unique_lock<std::mutex> lock(_mut);
  296. while (_jobs.empty()) _hasNew.wait(lock);
  297. int next = _jobs.front();
  298. _jobs.pop();
  299. return next;
  300. }