ClientConnection.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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 *)::malloc(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. bool isHeader = true;
  52. bool lastLineIsEmpty = false;
  53. bool lastLineEmptyAndZero = false;
  54. while (::fgets(requestBuff, urlRequestBuffSize, clRead)) {
  55. int len = ::strlen(requestBuff);
  56. char *lineBuff = (char *) ::malloc(len + 1), *pLineBuff = lineBuff;
  57. bool leftHasContext = false;
  58. for (int i = 0; i < len; i++) {
  59. if (requestBuff[i] == '\r' || requestBuff[i] == '\n') continue;
  60. if (requestBuff[i] == ' ' || requestBuff[i] == '\t') {
  61. if (leftHasContext) {
  62. *pLineBuff++ = requestBuff[i];
  63. }
  64. } else {
  65. leftHasContext = true;
  66. *pLineBuff++ = requestBuff[i];
  67. }
  68. }
  69. if (leftHasContext) {
  70. pLineBuff--;
  71. while (pLineBuff >= lineBuff && (*pLineBuff == ' ' || *pLineBuff == '\t')) {
  72. *pLineBuff = 0; // 从右往左,删掉右边的空白符
  73. pLineBuff--;
  74. }
  75. }
  76. if (::strlen(lineBuff) == 0) {
  77. // TODO: Fix Linux POST Method
  78. // isHeader = false;
  79. // lastLineIsEmpty = true;
  80. // if (lastLineEmptyAndZero) {
  81. // break;
  82. // } else {
  83. // lastLineEmptyAndZero = false;
  84. // }
  85. // if (method == "GET") {
  86. break;
  87. // }
  88. continue;
  89. }
  90. if (lineBuff[0] == '0') {
  91. if (lastLineIsEmpty) {
  92. lastLineEmptyAndZero = true;
  93. lastLineIsEmpty = false;
  94. }
  95. }
  96. if (isHeader) {
  97. char *headerValue;
  98. char *headerName = strtok_r(lineBuff, ":", &headerValue);
  99. if (headerName != nullptr && headerValue != nullptr) {
  100. string name(headerName);
  101. string value(headerValue);
  102. headers[name] = value;
  103. }
  104. } else {
  105. body << lineBuff << endl;
  106. }
  107. }
  108. RequestData requestData(url, method, headers, body.str());
  109. cout << "[HTTPServer] Received " << method << " Request URL = " << url << endl;
  110. if (url.find("..") != string::npos) {
  111. conf::errorPage400.writeTo(clWrite);
  112. cleanUpAndDestroy();
  113. return;
  114. }
  115. RequestProcessTask *task = new RequestProcessTask(requestData);
  116. processor::enqueueTask(task);
  117. ::time_t start, now;
  118. ::time(&start);
  119. while (true) {
  120. usleep(1000 * 10);
  121. if (task->isFinish()) {
  122. ResponseData *taskResponse = task->getResponse();
  123. taskResponse->writeTo(clWrite);
  124. // taskResponse->writeTo(stdout);
  125. delete taskResponse;
  126. break;
  127. }
  128. ::time(&now);
  129. if (::difftime(now, start) > conf::taskProcessTimeoutSeconds) {
  130. cout << "[HTTPServer-Warn] Task failed because time out" << endl;
  131. conf::errorPageTimeout.writeTo(clWrite);
  132. processor::deleteTask(task);
  133. task->setHttpDiscarded(true);
  134. break;
  135. }
  136. }
  137. cleanUpAndDestroy();
  138. return;
  139. } else {
  140. conf::ErrorView view(400, "");
  141. view.setMessage("未知的协议 " + method);
  142. TemplateResponseData({ view }).writeTo(clWrite);
  143. cleanUpAndDestroy();
  144. return;
  145. }
  146. }
  147. void ClientConnection::cleanUpAndDestroy() {
  148. if (this->clRead) {
  149. ::fclose(this->clRead);
  150. this->clRead = nullptr;
  151. }
  152. if (this->clWrite) {
  153. ::fclose(this->clWrite);
  154. this->clWrite = nullptr;
  155. }
  156. if (this->requestBuff) {
  157. ::free(this->requestBuff);
  158. this->requestBuff = nullptr;
  159. }
  160. ::close(this->sockFd);
  161. delete this;
  162. }
  163. } // xc
  164. } // httpserver