/*----------------------------------------------------------------------------- * tcpserver.cpp * Copyright (C) 2004, 2005 Akito Nozaki * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Original code came from cutestuff bytestream.h and cpp by Justin K. * Converted to use Tanoshi library stuff. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include NAMESPACE_TANOSHI { TcpServer::TcpServer(Object *parent) : Object(parent) { } TcpServer::~TcpServer() { } bool TcpServer::listen(const HostAddress &address, unsigned int port) { int fd = 0; _hostaddr = address; _port = port; if( (fd = socket(AF_INET, SOCK_STREAM, 0) ) == -1) { error(ErrSocket); return false; } int yes = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { error(ErrSocket); return false; } struct sockaddr_in srvaddr; srvaddr.sin_family = AF_INET; srvaddr.sin_addr.s_addr = htonl(_hostaddr.toIPv4Address()); srvaddr.sin_port = htons(_port); memset( &(srvaddr.sin_zero), 0, 8); // bind the information to the listener if(bind(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr)) == -1) { error(ErrBind); return false; } // start listening if(::listen(fd, 20) == -1) { error(ErrListening); return false; } _fd = fd; setFd(_fd); setEvents(POLLIN); addToEvent(); setSleep(-1); return true; } bool TcpServer::listen(unsigned int port) { listen(ntohl(INADDR_ANY), port); } void TcpServer::close() { ::close(_fd); _fd = 0; } bool TcpServer::isListening() { return (_fd != 0); } Socket *TcpServer::getPending() { Socket *temp = _pending.front(); _pending.pop(); return temp; } bool TcpServer::hasPending() { return (_pending.size() != 0); } bool TcpServer::event(Event *e) { if(e->id() != id()) return false; if(revents() & POLLIN) { sockaddr_in remoteaddr; int tempfd = 0; int addrlen = sizeof(struct sockaddr_in); if( ( tempfd = accept(_fd, (struct sockaddr *)&remoteaddr, (socklen_t *)&addrlen)) == -1) { error(ErrAccept); return true; } int flags = fcntl( tempfd, F_GETFL, 0 ); fcntl( tempfd, F_SETFL, flags | O_NONBLOCK ); Socket *temp = new Socket(this); temp->setSocket(tempfd); temp->setHostAddress(remoteaddr.sin_addr.s_addr); temp->setPort(ntohs(remoteaddr.sin_port)); _pending.push(temp); newConnection(); } return true; } }