Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions includes/Server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Server {
TransferManager tm_;
Bot bot_;
void processTransferSocket_();
void
syncTransferPollFds_(); //before poll call we put listener/data fd in pollFds_
#endif

size_t numServerSockets_;
Expand Down
4 changes: 1 addition & 3 deletions srcs/bonus/TransferManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,7 @@ bool TransferManager::fileSize_(const std::string &path, off_t &size) const {
}

void TransferManager::setNonBlocking_(int fd) {
int flags = ::fcntl(fd, F_GETFL, 0);
if (flags != -1)
::fcntl(fd, F_SETFL, flags | O_NONBLOCK);
::fcntl(fd, F_SETFL, O_NONBLOCK);
}

#endif
52 changes: 41 additions & 11 deletions srcs/server/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,9 @@ void Server::processClientSockets_() {
++idx) {
pollfd &pfd = pollFds_.at(idx);
#ifdef BONUS
// Transfer listener/data fds are never registered in pollfds_, so this
// never fires today. Kept as future-proofing: if transfer_fd is ever added
// to pollfds_
if (tm_.ownsFd(pfd.fd))
// Transfer listener/data fds are in pollFds_ too (syncTransferPollFds_)
// but are not clients: processTransferSocket_ handles their revents.
if (!sockets_.checkSocketData(pfd.fd) || tm_.ownsFd(pfd.fd))
continue;
#endif

Expand Down Expand Up @@ -220,6 +219,10 @@ void Server::processClientSockets_() {
}

void Server::removeClientSocketPfd_(int const fd, std::string const &msg) {
if (!sockets_.checkSocketData(fd)) {
removePollFd_(fd);
return;
}
if (!sockets_.isServerSocket(fd)) {
if (!msg.empty()) {
Client *client = clients_.find(fd);
Expand Down Expand Up @@ -336,6 +339,7 @@ void Server::run() {
// so wake it up every 1000.
int timeout = 1000;
#ifdef BONUS
syncTransferPollFds_();
if (tm_.isActive())
timeout = 100;
#endif
Expand Down Expand Up @@ -388,6 +392,27 @@ Bot &Server::getBot() {
return bot_;
}

// Keeps the transfer listener/data fds inside the single poll() set:
// drops the ones the TransferManager already closed, adds the live ones.
void Server::syncTransferPollFds_() {
for (size_t i = numServerSockets_; i < pollFds_.size();) {
int const fd = pollFds_.at(i).fd;
if (!sockets_.checkSocketData(fd) && !tm_.ownsFd(fd))
pollFds_.erase(pollFds_.begin() + i);
else
++i;
}
if (!tm_.isActive())
return;
int const fds[2] = {tm_.getListenerFd(), tm_.current()->dataFd};
short const events[2] = {POLLIN, POLLOUT};
for (int i = 0; i < 2; ++i)
if (fds[i] != -1 &&
std::find_if(pollFds_.begin(), pollFds_.end(),
srvHelp::PfdHasFd(fds[i])) == pollFds_.end())
pollFds_.push_back(PollFd(fds[i], events[i]).pfd);
}

void Server::processTransferSocket_() {
if (!tm_.isActive())
return;
Expand All @@ -398,16 +423,22 @@ void Server::processTransferSocket_() {
int listener = tm_.getListenerFd();
if (listener == -1)
return;
int dataFd = tm_.getDataFd();
int dataFd = tm_.current()->dataFd;
struct pollfd pfds[2];
int n = 1;
pfds[0] = PollFd(listener, POLLIN).pfd;
if (dataFd != -1) {
pfds[1] = PollFd(dataFd, POLLOUT).pfd;
n = 2;
}
if (poll(pfds, n, 0) <= 0)
return;
for (int i = 0; i < n; ++i) { // revents from the main poll()
std::vector<pollfd>::iterator it = std::find_if(
pollFds_.begin(), pollFds_.end(), srvHelp::PfdHasFd(pfds[i].fd));
if (it == pollFds_.end())
pfds[i].revents = 0;
else
pfds[i].revents = it->revents;
}
if (pfds[0].revents & (POLLERR | POLLNVAL)) {
tm_.closeOffer();
return;
Expand All @@ -416,10 +447,9 @@ void Server::processTransferSocket_() {
dataFd = tm_.getDataFd();
if (dataFd < 0)
return;
pfds[1] = PollFd(dataFd, POLLOUT).pfd;
n = 2;
if (poll(pfds, n, 0) <= 0)
return;
// pfds[1] = PollFd(dataFd, POLLOUT).pfd;
// n = 2;
return; // the data fd joins the poll set on the next iteration
}
if (n != 2)
return;
Expand Down
Loading