fix potential cspot on socket timeout & optimize HTTP server - release

This commit is contained in:
philippe44
2022-09-24 23:11:20 -07:00
parent f84e856e68
commit f2b0c40848
2 changed files with 36 additions and 34 deletions

View File

@@ -80,9 +80,8 @@ void bell::HTTPServer::listen() {
socket(server->ai_family, server->ai_socktype, server->ai_protocol); socket(server->ai_family, server->ai_socktype, server->ai_protocol);
struct sockaddr_in clientname; struct sockaddr_in clientname;
socklen_t incomingSockSize; socklen_t incomingSockSize;
int i;
int yes = true; int yes = true;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) { if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*) &yes, sizeof(int)) < 0) {
throw std::runtime_error("setsockopt failed: " + throw std::runtime_error("setsockopt failed: " +
std::string(strerror(errno))); std::string(strerror(errno)));
} }
@@ -100,62 +99,65 @@ void bell::HTTPServer::listen() {
FD_ZERO(&activeFdSet); FD_ZERO(&activeFdSet);
FD_SET(sockfd, &activeFdSet); FD_SET(sockfd, &activeFdSet);
for (;;) { for (int maxfd = sockfd;;) {
/* Block until input arrives on one or more active sockets. */ /* Block until input arrives on one or more active sockets. */
readFdSet = activeFdSet; readFdSet = activeFdSet;
struct timeval tv = {0, 100000}; struct timeval tv = {0, 100000};
if (select(FD_SETSIZE, &readFdSet, NULL, NULL, &tv) < 0) { if (select(maxfd + 1, &readFdSet, NULL, NULL, &tv) < 0) {
BELL_LOG(error, "http", "Error in select"); BELL_LOG(error, "http", "Error in select");
perror("select"); perror("select");
// exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} }
/* Service all the sockets with input pending. */ /* Service listening socket. */
for (i = 0; i < FD_SETSIZE; ++i) if (FD_ISSET(sockfd, &readFdSet)) {
if (FD_ISSET(i, &readFdSet)) { int newFd;
if (i == sockfd) { incomingSockSize = sizeof(clientname);
/* Connection request on original socket. */ newFd = accept(sockfd, (struct sockaddr*)&clientname,
int newFd; &incomingSockSize);
incomingSockSize = sizeof(clientname); if (newFd < 0) {
newFd = accept(sockfd, (struct sockaddr *)&clientname, perror("accept");
&incomingSockSize); exit(EXIT_FAILURE);
if (newFd < 0) { }
perror("accept");
exit(EXIT_FAILURE);
}
FD_SET(newFd, &activeFdSet); FD_SET(newFd, &activeFdSet);
HTTPConnection conn = {.buffer = std::vector<uint8_t>(128), HTTPConnection conn = { .buffer = std::vector<uint8_t>(128),
.httpMethod = ""}; .httpMethod = "" };
this->connections.insert({newFd, conn}); this->connections.insert({ newFd, conn });
} else { }
/* Data arriving on an already-connected socket. */
readFromClient(i);
}
}
/* Service other sockets and update set & max */
maxfd = sockfd;
for (auto it = this->connections.cbegin(); for (auto it = this->connections.cbegin();
it != this->connections.cend() /* not hoisted */; it != this->connections.cend() /* not hoisted */;
/* no increment */) { /* no increment */) {
int fd = (*it).first;
if ((*it).second.toBeClosed) { if ((*it).second.toBeClosed) {
close((*it).first); close(fd);
FD_CLR((*it).first, &activeFdSet); FD_CLR(fd, &activeFdSet);
this->connections.erase( this->connections.erase(
it++); // or "it = m.erase(it)" since C++11 it++); // or "it = m.erase(it)" since C++11
} else { }
else {
if (fd != sockfd && FD_ISSET(fd, &readFdSet)) {
/* Data arriving on an already-connected socket. */
readFromClient(fd);
}
if (fd > maxfd) maxfd = fd;
++it; ++it;
} }
} }
} }
} }
void bell::HTTPServer::readFromClient(int clientFd) { void bell::HTTPServer::readFromClient(int clientFd) {
HTTPConnection &conn = this->connections[clientFd]; HTTPConnection &conn = this->connections[clientFd];
int nbytes = recv(clientFd, &conn.buffer[0], conn.buffer.size(), 0); int nbytes = recv(clientFd, (char*) &conn.buffer[0], conn.buffer.size(), 0);
if (nbytes < 0) { if (nbytes < 0) {
BELL_LOG(error, "http", "Error reading from client"); BELL_LOG(error, "http", "Error reading from client");
perror("recv"); perror("recv");

View File

@@ -126,7 +126,7 @@ std::vector<uint8_t> PlainConnection::readBlock(size_t size)
break; break;
default: default:
if (retries++ > 4) throw std::runtime_error("Error in read"); if (retries++ > 4) throw std::runtime_error("Error in read");
goto READ;
} }
} }
idx += n; idx += n;