in src/tcp-proxy.cpp [385:475]
IterationResult SessionArray::select_iteration()
{
fd_set set_r, set_w, set_e;
struct timeval tv = { 0, 10 };
int result = 0;
IterationResult retVal = IR::IDLE;
// KLUDGE:
base().sock[HOST] = base().sock[CLIENT] = INVALID_SOCKET;
// TODO: Do not add Sessions if there are too many
// TODO: round-robin select if there are many sessions
// Winsock fd_set is slow, maybe should iterate it myself later
FD_ZERO(&set_r);
SOCKET socketmax = listener;
for (intptr iSession = 1, count = std::min(30, (int)size()); iSession < count; ++iSession) {
Session &s = *operator[](iSession);
SOCKET sock;
forn (iSide, 2) {
if (INVALID_SOCKET != (sock = s.sock[iSide])) {
if (socketmax < sock) {
socketmax = sock;
}
FD_SET(sock, &set_r);
}
}
memset(s.chrwe, 0, sizeof(s.chrwe));
}
set_e = set_r;
set_w = set_r;
FD_SET(listener, &set_e);
FD_SET(listener, &set_r);
result = select((int)socketmax + 1, (fd_set *)&set_r, (fd_set *)&set_w, (fd_set *)&set_e, &tv);
switch (result) {
case 0:
return IR::IDLE; // Timeout
case -1:
err("select(): returned with error");
return IR::FAILURE;
}
if (FD_ISSET(listener, &set_e)) {
err("select(): error on listening socket: %d", socket_last_error());
return IR::FAILURE;
}
if (FD_ISSET(listener, &set_r)) {
retVal = IR::SUCCESS;
accept();
}
for (intptr iSession = 1, count = std::min(30, (int)size()); iSession < count; ++iSession) {
Session &s = *operator[](iSession);
SOCKET sock;
forn (iSide, 2) {
if (INVALID_SOCKET != (sock = s.sock[iSide])) {
s.chrwe[0][3] = (
(s.chrwe[iSide][2] = FD_ISSET(sock, &set_e)) |
(s.chrwe[iSide][1] = FD_ISSET(sock, &set_w)) |
(s.chrwe[iSide][0] = FD_ISSET(sock, &set_r))
);
}
}
}
for (intptr i = 1, count = std::min(30, (int)size()); i < count; ++i) {
Session &s = *operator[](i);
if (s.chrwe[0][3]) {
IterationResult ir = s.process();
if (ITERATION_FINISHED(ir)) {
//iprintf("deleting %s\n", s.name.c_str());
delete_at(i);
--count;
if (1 == size()) {
iprintf("All sessions finished\n\n");
nSessionsAccepted = 0;
}
retVal = IR::SUCCESS;
}
else if (IR::IDLE != ir) {
retVal = IR::SUCCESS;
}
}
}
return retVal;
}