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);
struct sockaddr_in clientname;
socklen_t incomingSockSize;
int i;
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: " +
std::string(strerror(errno)));
}
@@ -100,62 +99,65 @@ void bell::HTTPServer::listen() {
FD_ZERO(&activeFdSet);
FD_SET(sockfd, &activeFdSet);
for (;;) {
for (int maxfd = sockfd;;) {
/* Block until input arrives on one or more active sockets. */
readFdSet = activeFdSet;
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");
perror("select");
// exit(EXIT_FAILURE);
}
/* Service all the sockets with input pending. */
for (i = 0; i < FD_SETSIZE; ++i)
if (FD_ISSET(i, &readFdSet)) {
if (i == sockfd) {
/* Connection request on original socket. */
int newFd;
incomingSockSize = sizeof(clientname);
newFd = accept(sockfd, (struct sockaddr *)&clientname,
&incomingSockSize);
if (newFd < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
/* Service listening socket. */
if (FD_ISSET(sockfd, &readFdSet)) {
int newFd;
incomingSockSize = sizeof(clientname);
newFd = accept(sockfd, (struct sockaddr*)&clientname,
&incomingSockSize);
if (newFd < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
FD_SET(newFd, &activeFdSet);
FD_SET(newFd, &activeFdSet);
HTTPConnection conn = {.buffer = std::vector<uint8_t>(128),
.httpMethod = ""};
HTTPConnection conn = { .buffer = std::vector<uint8_t>(128),
.httpMethod = "" };
this->connections.insert({newFd, conn});
} else {
/* Data arriving on an already-connected socket. */
readFromClient(i);
}
}
this->connections.insert({ newFd, conn });
}
/* Service other sockets and update set & max */
maxfd = sockfd;
for (auto it = this->connections.cbegin();
it != this->connections.cend() /* not hoisted */;
/* no increment */) {
it != this->connections.cend() /* not hoisted */;
/* no increment */) {
int fd = (*it).first;
if ((*it).second.toBeClosed) {
close((*it).first);
FD_CLR((*it).first, &activeFdSet);
close(fd);
FD_CLR(fd, &activeFdSet);
this->connections.erase(
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;
}
}
}
}
void bell::HTTPServer::readFromClient(int 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) {
BELL_LOG(error, "http", "Error reading from client");
perror("recv");

View File

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