123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- //
- // Created by xcbosa on 2023/1/28.
- //
- #include "ClientConnection.h"
- #include "../processor/processor.h"
- using namespace std;
- using namespace xc::processor;
- namespace xc {
- namespace httpserver {
- ClientConnection::ClientConnection(int sockFd, struct sockaddr_in address) {
- this->sockFd = sockFd;
- this->address = address;
- this->clRead = nullptr;
- this->clWrite = nullptr;
- this->requestBuff = nullptr;
- }
- void ClientConnection::workAndDestroy() {
- thread(&ClientConnection::workLoop, this).detach();
- }
- void ClientConnection::workLoop() {
- ::FILE *clRead = fdopen(this->sockFd, "r");
- ::FILE *clWrite = fdopen(dup(this->sockFd), "w");
- struct timeval timeout = { conf::clientSocketTimeoutSeconds, 0 };
- if (setsockopt(this->sockFd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) {
- cleanUpAndDestroy();
- return;
- }
- this->clRead = clRead;
- this->clWrite = clWrite;
- char *requestBuff = (char *)::calloc(1, urlRequestBuffSize);
- this->requestBuff = requestBuff;
- ::fgets(requestBuff, urlRequestBuffSize, clRead);
- if (::strstr(requestBuff, "HTTP/") == NULL) {
- conf::errorPage400.writeTo(clWrite);
- cleanUpAndDestroy();
- return;
- }
- string method, url;
- char *ptr, *p;
- ptr = strtok_r(requestBuff, " ", &p);
- if (ptr != nullptr) {
- method = string(ptr);
- ptr = strtok_r(p, " ", &p);
- if (ptr != nullptr) {
- url = string(ptr);
- }
- }
- if (method == "GET" || method == "POST") {
- map<string, string> headers;
- ostringstream body;
- while (bzero(requestBuff, urlRequestBuffSize), ::fgets(requestBuff, urlRequestBuffSize, clRead)) {
- string line(requestBuff);
- replace_all(line, "\r\n", "");
- trim(line);
- if (line.length() == 0) {
- break; // TODO: POST Body not read.
- }
- auto lineParts = split(line, ":");
- for (auto &it : lineParts) {
- trim(it);
- }
- if (lineParts.size() == 2) {
- headers[lineParts[0]] = lineParts[1];
- }
- }
- RequestData requestData(url, method, headers, body.str());
- cout << "[HTTPServer] Received " << method << " Request URL = " << url << endl;
- if (url.find("..") != string::npos) {
- conf::errorPage400.writeTo(clWrite);
- cleanUpAndDestroy();
- return;
- }
- RequestProcessTask *task = new RequestProcessTask(requestData);
- processor::enqueueTask(task);
- ::time_t start, now;
- ::time(&start);
- while (true) {
- usleep(1000 * 10);
- if (task->isFinish()) {
- ResponseData *taskResponse = task->getResponse();
- taskResponse->writeTo(clWrite);
- // taskResponse->writeTo(stdout);
- delete taskResponse;
- break;
- }
- ::time(&now);
- if (::difftime(now, start) > conf::taskProcessTimeoutSeconds) {
- cout << "[HTTPServer-Warn] Task failed because time out" << endl;
- conf::errorPageTimeout.writeTo(clWrite);
- processor::deleteTask(task);
- task->setHttpDiscarded(true);
- break;
- }
- }
- cleanUpAndDestroy();
- return;
- } else {
- conf::ErrorView view(400, "");
- view.setMessage("未知的协议 " + method);
- TemplateResponseData({ view }).writeTo(clWrite);
- cleanUpAndDestroy();
- return;
- }
- }
- void ClientConnection::cleanUpAndDestroy() {
- if (this->clRead) {
- ::fclose(this->clRead);
- this->clRead = nullptr;
- }
- if (this->clWrite) {
- ::fclose(this->clWrite);
- this->clWrite = nullptr;
- }
- if (this->requestBuff) {
- ::free(this->requestBuff);
- this->requestBuff = nullptr;
- }
- ::close(this->sockFd);
- delete this;
- }
- } // xc
- } // httpserver
|