/** * Check whether we need to call the callback, i.e. whether we * have connected or aborted and call the appropriate callback * for that. It's done this way to ease on the locking that * would otherwise be needed everywhere. */ /* static */ void TCPConnecter::CheckCallbacks() { for (TCPConnecter **iter = _tcp_connecters.Begin(); iter < _tcp_connecters.End(); /* nothing */) { TCPConnecter *cur = *iter; if ((cur->connected || cur->aborted) && cur->killed) { _tcp_connecters.Erase(iter); if (cur->sock != INVALID_SOCKET) closesocket(cur->sock); delete cur; continue; } if (cur->connected) { _tcp_connecters.Erase(iter); cur->OnConnect(cur->sock); delete cur; continue; } if (cur->aborted) { _tcp_connecters.Erase(iter); cur->OnFailure(); delete cur; continue; } iter++; } }
/* static */ void NetworkHTTPSocketHandler::HTTPReceive() { /* No connections, just bail out. */ if (_http_connections.Length() == 0) return; fd_set read_fd; struct timeval tv; FD_ZERO(&read_fd); for (NetworkHTTPSocketHandler **iter = _http_connections.Begin(); iter < _http_connections.End(); iter++) { FD_SET((*iter)->sock, &read_fd); } tv.tv_sec = tv.tv_usec = 0; // don't block at all. #if !defined(__MORPHOS__) && !defined(__AMIGA__) int n = select(FD_SETSIZE, &read_fd, NULL, NULL, &tv); #else int n = WaitSelect(FD_SETSIZE, &read_fd, NULL, NULL, &tv, NULL); #endif if (n == -1) return; for (NetworkHTTPSocketHandler **iter = _http_connections.Begin(); iter < _http_connections.End(); /* nothing */) { NetworkHTTPSocketHandler *cur = *iter; if (FD_ISSET(cur->sock, &read_fd)) { int ret = cur->Receive(); /* First send the failure. */ if (ret < 0) cur->callback->OnFailure(); if (ret <= 0) { /* Then... the connection can be closed */ cur->CloseConnection(); _http_connections.Erase(iter); delete cur; continue; } } iter++; } }