TMultiplexingServer::~TMultiplexingServer() { if (listenSocket > 0) TF_CLOSE(listenSocket); if (epollFd > 0) TF_CLOSE(epollFd); }
TActionForkProcess::~TActionForkProcess() { if (httpSocket) delete httpSocket; if (TActionContext::socketDesc > 0) TF_CLOSE(TActionContext::socketDesc); currentActionContext = 0; }
TActionThread::~TActionThread() { if (httpSocket) delete httpSocket; if (TActionContext::socketDesc > 0) TF_CLOSE(TActionContext::socketDesc); threadCounter.fetchAndAddOrdered(-1); }
void TMultiplexingServer::epollClose(int fd) { tf_epoll_ctl(epollFd, EPOLL_CTL_DEL, fd, NULL); TF_CLOSE(fd); recvBuffers.remove(fd); QQueue<THttpSendBuffer*> que = sendBuffers.take(fd); for (QListIterator<THttpSendBuffer*> it(que); it.hasNext(); ) { delete it.next(); } pendingRequests.removeAll(fd); }
TActionContext::~TActionContext() { if (httpSocket) delete httpSocket; if (socketDesc > 0) TF_CLOSE(socketDesc); // Releases all database sessions TActionContext::releaseDatabases(); for (QListIterator<TTemporaryFile *> i(tempFiles); i.hasNext(); ) { delete i.next(); } for (QStringListIterator i(autoRemoveFiles); i.hasNext(); ) { QFile(i.next()).remove(); } }
void TMultiplexingServer::run() { // Listen socket quint16 port = Tf::app()->appSettings().value("ListenPort").toUInt(); int sock = TApplicationServerBase::nativeListen(QHostAddress::Any, port); if (sock > 0) { tSystemDebug("listen successfully. port:%d", port); } else { tSystemError("Failed to set socket descriptor: %d", sock); TApplicationServerBase::nativeClose(sock); return; } listenSocket = sock; setSocketOption(listenSocket); maxWorkers = Tf::app()->maxNumberOfServers(10); tSystemDebug("MaxWorkers: %d", maxWorkers); // Get send buffer size and recv buffer size int res, sendBufSize, recvBufSize; socklen_t optlen = sizeof(int); res = getsockopt(listenSocket, SOL_SOCKET, SO_SNDBUF, &sendBufSize, &optlen); if (res < 0) tSystemDebug("SO_SNDBUF: %d", sendBufSize); res = getsockopt(listenSocket, SOL_SOCKET, SO_RCVBUF, &recvBufSize, &optlen); if (res < 0) tSystemDebug("SO_RCVBUF: %d", recvBufSize); const int MaxEvents = 128; struct epoll_event events[MaxEvents]; sendBufSize *= 0.8; char *sndbuffer = new char[sendBufSize]; char *rcvbuffer = new char[recvBufSize]; // Create epoll epollFd = epoll_create(1); if (epollFd < 0) { tSystemError("Failed epoll_create()"); goto socket_error; } if (epollAdd(listenSocket, EPOLLIN) < 0) { tSystemError("Failed epoll_ctl()"); goto epoll_error; } for (;;) { // Get send-request getSendRequest(); // Check pending requests while (!pendingRequests.isEmpty() && (int)threadCounter < maxWorkers) { int fd = pendingRequests.takeFirst(); THttpBuffer &recvbuf = recvBuffers[fd]; emitIncomingRequest(fd, recvbuf); } // Poll Sending/Receiving/Incoming int timeout = ((int)threadCounter > 0) ? 1 : 100; int nfd = tf_epoll_wait(epollFd, events, MaxEvents, timeout); int err = errno; if (nfd < 0) { tSystemError("Failed epoll_wait() : errno:%d", err); break; } for (int i = 0; i < nfd; ++i) { if (events[i].data.fd == listenSocket) { if (!pendingRequests.isEmpty()) continue; // Incoming connection struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); int clt = ::accept(events[i].data.fd, (sockaddr *)&addr, &addrlen); if (clt < 0) { tSystemWarn("Failed accept"); continue; } setNonBlocking(clt); if (epollAdd(clt, EPOLLIN) == 0) { THttpBuffer &recvbuf = recvBuffers[clt]; recvbuf.clear(); recvbuf.setClientAddress(QHostAddress((sockaddr *)&addr)); } } else { int cltfd = events[i].data.fd; if ( (events[i].events & EPOLLIN) ) { // Receive data int len = ::recv(cltfd, rcvbuffer, recvBufSize, 0); err = errno; if (len > 0) { // Read successfully THttpBuffer &recvbuf = recvBuffers[cltfd]; recvbuf.write(rcvbuffer, len); if (recvbuf.canReadHttpRequest()) { // Incoming a request if ((int)threadCounter >= maxWorkers) { pendingRequests << cltfd; } else { emitIncomingRequest(cltfd, recvbuf); } } } else { if (len < 0 && err != ECONNRESET) { tSystemError("Failed recv : errno:%d", err); } // Disconnect epollClose(cltfd); continue; } } if ( (events[i].events & EPOLLOUT) ) { // Send data THttpSendBuffer *sendbuf = sendBuffers[cltfd].first(); if (!sendbuf) { tSystemError("Not found send-buffer"); epollClose(cltfd); continue; } int len = sendbuf->read(sndbuffer, sendBufSize); int sentlen = ::send(cltfd, sndbuffer, len, 0); err = errno; TAccessLogger &logger = sendbuf->accessLogger(); if (sentlen <= 0) { if (err != ECONNRESET) { tSystemError("Failed send : errno:%d", err); } // Access log logger.setResponseBytes(-1); logger.write(); epollClose(cltfd); continue; } else { logger.setResponseBytes(logger.responseBytes() + sentlen); if (len > sentlen) { tSystemDebug("sendbuf prepend: len:%d", len - sentlen); sendbuf->prepend(sndbuffer + sentlen, len - sentlen); } if (sendbuf->atEnd()) { logger.write(); // Writes access log sendbuf->release(); QQueue<THttpSendBuffer*> &que = sendBuffers[cltfd]; delete que.dequeue(); // delete send-buffer obj // Prepare recv if (que.isEmpty()) epollModify(cltfd, EPOLLIN); } } } } } // Check stop flag if (stopped) { if (listenSocket > 0) { // Close the listen-socket epollClose(listenSocket); listenSocket = 0; } if (!recvBuffers.isEmpty()) { for (QMapIterator<int, THttpBuffer> it(recvBuffers); it.hasNext(); ) { it.next(); epollClose(it.key()); } } if (recvBuffers.isEmpty() && sendBuffers.isEmpty()) { break; } } } epoll_error: TF_CLOSE(epollFd); epollFd = 0; socket_error: if (listenSocket > 0) TF_CLOSE(listenSocket); listenSocket = 0; delete sndbuffer; delete rcvbuffer; }
void TApplicationServer::nativeClose(int socket) { if (socket > 0) TF_CLOSE(socket); }