/* Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "mcoputils.h" #include "unixserver.h" #include "socketconnection.h" #include "dispatcher.h" #include "debug.h" #define queue cqueue #include #undef queue #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace Arts; bool UnixServer::running() { return socketOk; } UnixServer::UnixServer(Dispatcher *dispatcher, const string& serverID) { this->dispatcher = dispatcher; socketOk = initSocket(serverID); if(socketOk) { IOManager *iom = dispatcher->ioManager(); iom->watchFD(theSocket,IOType::read|IOType::except,this); } } UnixServer::~UnixServer() { if(socketOk) { IOManager *iom = dispatcher->ioManager(); iom->remove(this,IOType::read|IOType::except); close(theSocket); unlink(xserverpath.c_str()); } } bool UnixServer::initSocket(const string& serverID) { struct sockaddr_un socket_addr; theSocket = socket(PF_UNIX,SOCK_STREAM,0); if(theSocket < 0) { arts_warning("MCOP UnixServer: can't create a socket"); return false; } if(fcntl(theSocket,F_SETFL,O_NONBLOCK)<0) { arts_warning("MCOP UnixServer: can't initialize non blocking I/O"); close(theSocket); return false; } int maxlen = sizeof(socket_addr.sun_path); string pathname = MCOPUtils::createFilePath(serverID); socket_addr.sun_family = AF_UNIX; strncpy(socket_addr.sun_path,pathname.c_str(),maxlen); socket_addr.sun_path[maxlen-1] = 0; xserverpath = socket_addr.sun_path; if ( bind( theSocket, (struct sockaddr *) &socket_addr, sizeof(struct sockaddr_un) ) < 0 ) { arts_warning("MCOP UnixServer: can't bind to file \"%s\"", pathname.c_str()); close(theSocket); return false; } if(listen(theSocket,16) < 0) { arts_warning("MCOP UnixServer: can't listen on the socket"); close(theSocket); return false; } return true; } string UnixServer::url() { return string("unix:") + xserverpath; } void UnixServer::notifyIO(int fd, int types) { assert(fd == theSocket); assert(socketOk); arts_debug("UnixManager: got notifyIO"); if(types & IOType::read) { int clientfd; struct sockaddr_un incoming; socklen_t size_in = sizeof(struct sockaddr_un); clientfd = accept(theSocket, (struct sockaddr*) &incoming, &size_in ); if(clientfd > 0) { // non blocking I/O int flags = fcntl (fd, F_GETFL, 0); assert (flags != -1); int nbl_result = fcntl (fd, F_SETFL, flags | O_NONBLOCK); assert(nbl_result >= 0); Dispatcher::the()->initiateConnection( new SocketConnection(clientfd)); } } arts_assert((types & IOType::write) == 0); arts_assert((types & IOType::except) == 0); }