ClientConnection.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. isHeader = false;
  78. lastLineIsEmpty = true;
  79. if (lastLineEmptyAndZero) {
  80. break;
  81. } else {
  82. lastLineEmptyAndZero = false;
  83. }
  84. if (method == "GET") {
  85. break;
  86. }
  87. continue;
  88. }
  89. if (lineBuff[0] == '0') {
  90. if (lastLineIsEmpty) {
  91. lastLineEmptyAndZero = true;
  92. lastLineIsEmpty = false;
  93. }
  94. }
  95. if (isHeader) {
  96. char *headerValue;
  97. char *headerName = strtok_r(lineBuff, ":", &headerValue);
  98. if (headerName != nullptr && headerValue != nullptr) {
  99. string name(headerName);
  100. string value(headerValue);
  101. headers[name] = value;
  102. }
  103. } else {
  104. body << lineBuff << endl;
  105. }
  106. }
  107. RequestData requestData(url, method, headers, body.str());
  108. cout << "[HTTPServer] Received " << method << " Request URL = " << url << endl;
  109. if (url.find("..") != string::npos) {
  110. conf::errorPage400.writeTo(clWrite);
  111. cleanUpAndDestroy();
  112. return;
  113. }
  114. RequestProcessTask *task = new RequestProcessTask(requestData);
  115. processor::enqueueTask(task);
  116. ::time_t start, now;
  117. ::time(&start);
  118. while (true) {
  119. usleep(1000 * 10);
  120. if (task->isFinish()) {
  121. ResponseData *taskResponse = task->getResponse();
  122. taskResponse->writeTo(clWrite);
  123. delete taskResponse;
  124. break;
  125. }
  126. ::time(&now);
  127. if (::difftime(now, start) > conf::taskProcessTimeoutSeconds) {
  128. cout << "[HTTPServer-Warn] Task failed because time out" << endl;
  129. conf::errorPageTimeout.writeTo(clWrite);
  130. processor::deleteTask(task);
  131. task->setHttpDiscarded(true);
  132. break;
  133. }
  134. }
  135. cleanUpAndDestroy();
  136. return;
  137. } else {
  138. conf::errorPage.applyReplacements(400, {
  139. Replacement("errorCode", "400"),
  140. Replacement("errorMessage", "未知的协议 " + method)
  141. }).writeTo(clWrite);
  142. cleanUpAndDestroy();
  143. return;
  144. }
  145. }
  146. void ClientConnection::cleanUpAndDestroy() {
  147. if (this->clRead) {
  148. ::fclose(this->clRead);
  149. this->clRead = nullptr;
  150. }
  151. if (this->clWrite) {
  152. ::fclose(this->clWrite);
  153. this->clWrite = nullptr;
  154. }
  155. if (this->requestBuff) {
  156. ::free(this->requestBuff);
  157. this->requestBuff = nullptr;
  158. }
  159. ::close(this->sockFd);
  160. delete this;
  161. }
  162. } // xc
  163. } // httpserver