ClientConnection.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. //
  2. // Created by xcbosa on 2023/1/28.
  3. //
  4. #include "ClientConnection.h"
  5. #include "../processor/processor.h"
  6. using namespace std;
  7. using namespace xc::processor;
  8. namespace xc {
  9. namespace httpserver {
  10. ClientConnection::ClientConnection(int sockFd, struct sockaddr_in address) {
  11. this->sockFd = sockFd;
  12. this->address = address;
  13. this->clRead = nullptr;
  14. this->clWrite = nullptr;
  15. this->requestBuff = nullptr;
  16. }
  17. void ClientConnection::workAndDestroy() {
  18. thread(&ClientConnection::workLoop, this).detach();
  19. }
  20. void ClientConnection::workLoop() {
  21. ::FILE *clRead = fdopen(this->sockFd, "r");
  22. ::FILE *clWrite = fdopen(dup(this->sockFd), "w");
  23. struct timeval timeout = { conf::clientSocketTimeoutSeconds, 0 };
  24. if (setsockopt(this->sockFd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) {
  25. cleanUpAndDestroy();
  26. return;
  27. }
  28. this->clRead = clRead;
  29. this->clWrite = clWrite;
  30. char *requestBuff = (char *)::calloc(1, urlRequestBuffSize);
  31. this->requestBuff = requestBuff;
  32. ::fgets(requestBuff, urlRequestBuffSize, clRead);
  33. if (::strstr(requestBuff, "HTTP/") == NULL) {
  34. conf::errorPage400.writeTo(clWrite);
  35. cleanUpAndDestroy();
  36. return;
  37. }
  38. string method, url;
  39. char *ptr, *p;
  40. ptr = strtok_r(requestBuff, " ", &p);
  41. if (ptr != nullptr) {
  42. method = string(ptr);
  43. ptr = strtok_r(p, " ", &p);
  44. if (ptr != nullptr) {
  45. url = string(ptr);
  46. }
  47. }
  48. if (method == "GET" || method == "POST") {
  49. map<string, string> headers;
  50. ostringstream body;
  51. while (bzero(requestBuff, urlRequestBuffSize), ::fgets(requestBuff, urlRequestBuffSize, clRead)) {
  52. string line(requestBuff);
  53. replace_all(line, "\r\n", "");
  54. trim(line);
  55. if (line.length() == 0) {
  56. break; // TODO: POST Body not read.
  57. }
  58. auto lineParts = split(line, ":");
  59. for (auto &it : lineParts) {
  60. trim(it);
  61. }
  62. if (lineParts.size() == 2) {
  63. headers[lineParts[0]] = lineParts[1];
  64. }
  65. }
  66. RequestData requestData(url, method, headers, body.str());
  67. cout << "[HTTPServer] Received " << method << " Request URL = " << url << endl;
  68. if (url.find("..") != string::npos) {
  69. conf::errorPage400.writeTo(clWrite);
  70. cleanUpAndDestroy();
  71. return;
  72. }
  73. RequestProcessTask *task = new RequestProcessTask(requestData);
  74. processor::enqueueTask(task);
  75. ::time_t start, now;
  76. ::time(&start);
  77. while (true) {
  78. usleep(1000 * 10);
  79. if (task->isFinish()) {
  80. ResponseData *taskResponse = task->getResponse();
  81. taskResponse->writeTo(clWrite);
  82. // taskResponse->writeTo(stdout);
  83. delete taskResponse;
  84. break;
  85. }
  86. ::time(&now);
  87. if (::difftime(now, start) > conf::taskProcessTimeoutSeconds) {
  88. cout << "[HTTPServer-Warn] Task failed because time out" << endl;
  89. conf::errorPageTimeout.writeTo(clWrite);
  90. processor::deleteTask(task);
  91. task->setHttpDiscarded(true);
  92. break;
  93. }
  94. }
  95. cleanUpAndDestroy();
  96. return;
  97. } else {
  98. conf::ErrorView view(400, "");
  99. view.setMessage("未知的协议 " + method);
  100. TemplateResponseData({ view }).writeTo(clWrite);
  101. cleanUpAndDestroy();
  102. return;
  103. }
  104. }
  105. void ClientConnection::cleanUpAndDestroy() {
  106. if (this->clRead) {
  107. ::fclose(this->clRead);
  108. this->clRead = nullptr;
  109. }
  110. if (this->clWrite) {
  111. ::fclose(this->clWrite);
  112. this->clWrite = nullptr;
  113. }
  114. if (this->requestBuff) {
  115. ::free(this->requestBuff);
  116. this->requestBuff = nullptr;
  117. }
  118. ::close(this->sockFd);
  119. delete this;
  120. }
  121. } // xc
  122. } // httpserver