//------------------------------------------------------------------------------ // Delete a socket/port connection from this UM. // ioSock (in) - socket/port connection to be deleted //------------------------------------------------------------------------------ void UmModuleIPs::delSocketConn( const IOSocket& ioSock ) { boost::mutex::scoped_lock lock( fUmModuleMutex ); for (unsigned int i=0; i<fUmIPSocketConns.size(); ++i) { sockaddr sa = ioSock.sa(); const sockaddr_in* sinp = reinterpret_cast<const sockaddr_in*>(&sa); if (fUmIPSocketConns[i]->ipAddress() == sinp->sin_addr.s_addr) { #ifdef MOD_CONN_DEBUG std::ostringstream oss; oss << "UM " << fUmModuleName << "; deleting connection "<< ioSock.toString() << std::endl; std::cout << oss.str(); #endif fUmIPSocketConns[i]->delSocketConn ( ioSock ); //..If we just deleted the last connection for this IP, then ad- // vance fNextUmIPSocketIdx to an IP address having connections. if (fUmIPSocketConns[i]->count() == 0) { advanceToNextIP(); } break; } } }
//------------------------------------------------------------------------------ // Get the next socket/port connection belonging to the same UM as ios. // The selected socket/port connection will be returned in outIos. It can // then be used for sending the next response message back to the applicable // UM module. // ios (in) - socket/port connection where a UM request originated from // outIos (out) - socket/port connection to use in sending the // corresponding response // writelock (out) - mutex lock to be used when writing to outIos // return - bool indicating if socket/port connection was assigned to // outIos //------------------------------------------------------------------------------ bool UmSocketSelector::nextIOSocket( const IOSocket& ios, SP_UM_IOSOCK& outIos, SP_UM_MUTEX& writeLock ) { sockaddr sa = ios.sa(); const sockaddr_in* sinp = reinterpret_cast<const sockaddr_in*>(&sa); IpAddressUmMap_t::iterator mapIter = fIpAddressUmMap.find ( sinp->sin_addr.s_addr ); if ( mapIter != fIpAddressUmMap.end() ) { unsigned int umIdx = mapIter->second; if (fUmModuleIPs[umIdx]->nextIOSocket( outIos, writeLock )) { #ifdef SEL_CONN_DEBUG std::ostringstream oss; oss << "UM " << fUmModuleIPs[umIdx]->moduleName() << "; in: " << ios.toString() << "; selected out: " << outIos->toString() << std::endl; std::cout << oss.str(); #endif return true; } } //..This should not happen. Application is asking for next socket/port for // a connection not in our UM module list. return false; }
//------------------------------------------------------------------------------ // Delete the specified socket/port from the connection list for the IP address // referenced by this UmIPSocketConns object. // ioSock (in) - socket/port connection to be deleted // // Not normally a good thing to be using a std::vector if we are going to be // deleting elements in the middle of the collection. Very inefficient. // But this method won't be called often, and we are only dealing with a small // collection. Plus we want to use a vector over a list, so that nextIOSocket() // can benefit from quick random access. //------------------------------------------------------------------------------ void UmIPSocketConns::delSocketConn( const IOSocket& ioSock ) { for (unsigned int i=0; i<fIOSockets.size(); ++i) { sockaddr sa1 = fIOSockets[i].fSock->sa(); const sockaddr_in* sinp1 = reinterpret_cast<const sockaddr_in*>(&sa1); sockaddr sa2 = ioSock.sa(); const sockaddr_in* sinp2 = reinterpret_cast<const sockaddr_in*>(&sa2); if (sinp1->sin_port == sinp2->sin_port) { fIOSockets.erase ( fIOSockets.begin() + i ); //..Adjust fNextIOSocketIdx // 1a. decrement if fNextIOSocketIdx is after deleted connection // 1b. reset to start of vector if we deleted the last connection // 2. reset fNextIOSocketIdx to -1 if we have no more connections if (fIOSockets.size() > 0) { if (fNextIOSocketIdx > static_cast<int>(i)) fNextIOSocketIdx--; if ( fNextIOSocketIdx >= static_cast<int>(fIOSockets.size()) ) fNextIOSocketIdx = 0; } else { fNextIOSocketIdx = NEXT_IOSOCKET_UNASSIGNED; } break; } } }
//------------------------------------------------------------------------------ // Delete a socket/port connection from the UM for which it belongs. // ioSock (in) - socket/port connection to be deleted //------------------------------------------------------------------------------ void UmSocketSelector::delConnection( const IOSocket& ios ) { sockaddr sa = ios.sa(); const sockaddr_in* sinp = reinterpret_cast<const sockaddr_in*>(&sa); IpAddressUmMap_t::iterator mapIter = fIpAddressUmMap.find ( sinp->sin_addr.s_addr ); if ( mapIter != fIpAddressUmMap.end() ) { unsigned int umIdx = mapIter->second; fUmModuleIPs[umIdx]->delSocketConn( ios ); } }
/* this was cut & pasted from InetStreamSocket; * is there a clean way to wrap ISS::accept()? */ const IOSocket CompressedInetStreamSocket::accept(const struct timespec* timeout) { int clientfd; long msecs = 0; struct pollfd pfd[1]; pfd[0].fd = socketParms().sd(); pfd[0].events = POLLIN; if (timeout != 0) { msecs = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000; if (poll(pfd, 1, msecs) != 1 || (pfd[0].revents & POLLIN) == 0 || pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) return IOSocket(new CompressedInetStreamSocket()); } struct sockaddr sa; socklen_t sl = sizeof(sa); int e; do { clientfd = ::accept(socketParms().sd(), &sa, &sl); e = errno; } while (clientfd < 0 && (e == EINTR || #ifdef ERESTART e == ERESTART || #endif #ifdef ECONNABORTED e == ECONNABORTED || #endif false)); if (clientfd < 0) { string msg = "CompressedInetStreamSocket::accept: accept() error: "; scoped_array<char> buf(new char[80]); #if STRERROR_R_CHAR_P const char* p; if ((p = strerror_r(e, buf.get(), 80)) != 0) msg += p; #else int p; if ((p = strerror_r(e, buf.get(), 80)) == 0) msg += buf.get(); #endif throw runtime_error(msg); } if (fSyncProto) { /* send a byte to artificially synchronize with connect() on the remote */ char b = 'A'; int ret; ret = ::send(clientfd, &b, 1, 0); e = errno; if (ret < 0) { ostringstream os; char blah[80]; #if STRERROR_R_CHAR_P const char* p; if ((p = strerror_r(e, blah, 80)) != 0) os << "CompressedInetStreamSocket::accept sync: " << p; #else int p; if ((p = strerror_r(e, blah, 80)) == 0) os << "CompressedInetStreamSocket::accept sync: " << blah; #endif ::close(clientfd); throw runtime_error(os.str()); } else if (ret == 0) { ::close(clientfd); throw runtime_error("CompressedInetStreamSocket::accept sync: got unexpected error code"); } } CompressedInetStreamSocket* ciss = new CompressedInetStreamSocket(); IOSocket ios; sockaddr_in* sin = (sockaddr_in*) &sa; if ((sin->sin_addr.s_addr == fSa.sin_addr.s_addr) || sin->sin_addr.s_addr == inet_addr("127.0.0.1")) ciss->useCompression = false; ios.setSocketImpl(ciss); SocketParms sp; sp = ios.socketParms(); sp.sd(clientfd); ios.socketParms(sp); ios.sa(&sa); return ios; }
void MasterDBRMNode::run() { ByteStream msg; IOSocket *s; boost::thread *reader; CLEAR_ALARM while (!die) { s = new IOSocket(); #ifdef BRM_VERBOSE cerr << "DBRM Controller waiting..." << endl; #endif serverLock.lock(); if (dbrmServer != NULL) try { *s = dbrmServer->accept(&MSG_TIMEOUT); } catch (runtime_error &e) { cerr << e.what() << " continuing...\n"; serverLock.unlock(); delete s; continue; } serverLock.unlock(); if (reloadCmd) { if (s->isOpen()) s->close(); delete s; reload(); continue; } if (die || !s->isOpen()) { if (s->isOpen()) s->close(); delete s; continue; } #ifdef BRM_VERBOSE cerr << "DBRM Controller: got a connection..." << endl; #endif mutex.lock(); activeSessions.push_back(s); params = new ThreadParams(); #ifdef BRM_VERBOSE cerr << "DBRM Controller: starting another thread" << endl; #endif mutex2.lock(); try { reader = new boost::thread(MsgProcessor(this)); } catch (boost::thread_resource_error&) { log("DBRM Controller: WARNING!! Got thread resource error! Increase system stack size or decrease the # of active sessions."); #ifdef BRM_VERBOSE cerr << "DBRM Controller: WARNING!! Got thread resource error! Increase system stack size or decrease the # of active sessions.\n"; #endif activeSessions.pop_back(); sendError(s, ERR_NETWORK); sleep(1); // don't close right away to avoid broken pipe on the client s->close(); delete s; delete params; mutex2.unlock(); mutex.unlock(); continue; } params->t = reader; params->sock = s; mutex2.unlock(); #ifdef __FreeBSD__ mutex.unlock(); #endif } serverLock.lock(); delete dbrmServer; dbrmServer = NULL; serverLock.unlock(); }