You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
arts/mcop/unixserver.cc

153 lines
3.7 KiB

/*
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 <config.h>
#include "mcoputils.h"
#include "unixserver.h"
#include "socketconnection.h"
#include "dispatcher.h"
#include "debug.h"
#define queue cqueue
#include <arpa/inet.h>
#undef queue
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
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);
}