summaryrefslogtreecommitdiff
path: root/x11/ipc/server/ocopserver.cpp
authorzecke <zecke>2002-10-01 14:27:17 (UTC)
committer zecke <zecke>2002-10-01 14:27:17 (UTC)
commitbba0335bbea81519beafb7fec1979a0abbd8a7ea (patch) (side-by-side diff)
treeee334cf518c59582a36a3dd24238a05dfc3535a2 /x11/ipc/server/ocopserver.cpp
parentef8d0a15d706b0e230f052efcb1eab6f905a8737 (diff)
downloadopie-bba0335bbea81519beafb7fec1979a0abbd8a7ea.zip
opie-bba0335bbea81519beafb7fec1979a0abbd8a7ea.tar.gz
opie-bba0335bbea81519beafb7fec1979a0abbd8a7ea.tar.bz2
5th try
initial checkin of X11 Opie stuff it features an IPC Server the client is todo this will become the OPIE X11 department including alternative QPEApplication, QCOP replacement
Diffstat (limited to 'x11/ipc/server/ocopserver.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--x11/ipc/server/ocopserver.cpp383
1 files changed, 383 insertions, 0 deletions
diff --git a/x11/ipc/server/ocopserver.cpp b/x11/ipc/server/ocopserver.cpp
new file mode 100644
index 0000000..3df574b
--- a/dev/null
+++ b/x11/ipc/server/ocopserver.cpp
@@ -0,0 +1,383 @@
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <qcstring.h>
+#include <qtimer.h>
+
+#include "ocopserver.h"
+
+OCopServer::OCopServer()
+ : QObject()
+{
+ setName( "ocopserver");
+
+ /*
+ * init the server
+ */
+ init();
+ initSocket();
+}
+OCopServer::~OCopServer() {
+// socket notifiers should be deleted
+ close(m_serverfd );
+}
+void OCopServer::init() {
+ /*
+ * we set SIGPIPE to SIG_IGN
+ * to get EPIPE on reads ;)
+ */
+ qWarning("SIGPIPE to be ignored");
+ signal(SIGPIPE, SIG_IGN );
+
+ /*
+ * initialize some variables
+ */
+ m_server = 0l;
+ m_serverError = 0l;
+}
+
+/**
+ * here we will init our server
+ * socket and bind and do the listen
+ */
+void OCopServer::initSocket() {
+ /* get the home dir */
+ QCString home( getenv("HOME") );
+ QCString path( home + "/.opie.cop");
+
+ if ( ( m_serverfd = socket( PF_UNIX, SOCK_STREAM, 0 ) ) == -1 ) {
+ qWarning("failed to create server socket");
+ /* try again later */
+ QTimer::singleShot( 400, this, SLOT(initSocket() ) );
+ return;
+ }
+ qWarning( "unlinking file %s", path.data() );
+
+ /* unlink previous sockets */
+ unlink( path.data() );
+
+ struct sockaddr_un m_address;
+ memset(&m_address, 0, sizeof(m_address ) );
+ m_address.sun_family = AF_UNIX; /* unix domain socket */
+ strcpy(m_address.sun_path, path.data() );
+ m_adrlaenge = sizeof(m_address.sun_family) + strlen(m_address.sun_path );
+
+ /* cast to make it a (sockadr*) */
+ if (bind(m_serverfd, (struct sockaddr*)&m_address, m_adrlaenge ) == -1 ) {
+ qWarning("Server could not bind try again");
+ close(m_serverfd);
+ QTimer::singleShot(400, this, SLOT(initSocket() ) );
+ return;
+ }
+
+ /* tell the kernel that we're listening and accepting
+ * 5 pending connections */
+ if (listen(m_serverfd, 5) == -1 ) {
+ qWarning("could not listen");
+ close(m_serverfd );
+ QTimer::singleShot(400, this, SLOT(initSocket() ) );
+ return;
+ }
+
+ /*
+ * now we will create two QSocketNotifier
+ * which will us notify on reads
+ * and errors
+ * we do this because they integrate
+ * nicely into the QApplication eventloop
+ */
+ m_server = new QSocketNotifier(m_serverfd, QSocketNotifier::Read, this );
+ connect( m_server, SIGNAL(activated(int) ),
+ this, SLOT(newOnServer() ) );
+
+ m_serverError = new QSocketNotifier( m_serverfd, QSocketNotifier::Exception, this);
+ connect(m_serverError, SIGNAL(activated(int) ),
+ this, SLOT(errorOnServer() ) );
+
+ qWarning("done with registering");
+}
+/**
+ * we got the possibility to read
+ * on the server
+ * this is mostly due a connect
+ * on a client side
+ * we will accept it
+ * add it to our list
+ */
+void OCopServer::newOnServer() {
+ int fd = accept();
+ if ( fd < 0 )
+ return;
+
+ /*
+ * we got a successfull new connection
+ * be happy
+ * set SocketNotifier
+ * connect it
+ * and a OCOPClient
+ */
+ qWarning("Heureka new connection %d", fd );
+
+
+ registerClient( fd );
+}
+int OCopServer::accept() {
+ /*
+ * accept it
+ * the socket is currently blocking IIRC
+ */
+ return ::accept( m_serverfd, (struct sockaddr*)&m_address, &m_adrlaenge );
+}
+void OCopServer::newOnClient( int fd ) {
+ int bug[4096];
+ //qWarning("new stuff for client on fd %d", fd );
+ errno = 0;
+ OCOPHead head;
+ memset(&head, 0, sizeof(head) );
+ int rea = ::read(fd, &head, sizeof(head) );
+ //qWarning("read %d %d", rea, errno);
+ /*
+ * I should get EPIPE but nothing like this happens
+ * so if rea == 0 and we were signaled by the notifier
+ * we close it and drop the clients...
+ */
+ if ( rea <= 0 ) {
+ deregisterClient( fd );
+ return;
+ }
+ /*
+ * OCOPHead
+ */
+ qWarning("data %s %d", bug, rea );
+
+ /*
+ * Check the magic
+ * if chcked read till EOF if magic does not match
+ * otherwise do read
+ * channel
+ * func
+ * data into mem
+ * and then send the OCOPPacket
+ *
+ */
+ if (head.magic == 47 ) {
+ qWarning("magic match");
+ QCString channel( head.chlen+1 );
+ QCString func( head.funclen+1 );
+ QByteArray data ( head.datalen );
+
+ /*
+ * we do not check for errors
+ */
+ int s = read(fd, channel.data(), head.chlen );
+ s = read(fd, func.data(), head.funclen );
+ s = read(fd, data.data(), head.datalen );
+
+ /* debug output */
+ qWarning("channel %s %d", channel.data(), head.chlen );
+ qWarning("func %s %d", func.data(), head.funclen );
+ /* debug end */
+
+ /*
+ * now that we got the complete body
+ * we need to make a package
+ * and then we need to send it to clients
+ * making a package is done here
+ * dispatching it not
+ */
+ OCOPPacket packet( head.type, channel, func, data );
+ dispatch( packet, fd );
+
+ }else{
+ qWarning("magic does not match");
+ qWarning("magic %d", head.magic );
+ }
+}
+void OCopServer::registerClient( int fd ) {
+ if (m_clients.contains(fd) )
+ return;
+
+ QSocketNotifier* notify = new QSocketNotifier(fd, QSocketNotifier::Read, this );
+ connect(notify, SIGNAL(activated(int) ),
+ this, SLOT(newOnClient(int) ) );
+ OCOPClient client;
+ client.fd = fd;
+ client.notify = notify;
+ m_clients.insert( client.fd, client );
+ qWarning("clients are up to %d", m_clients.count() );
+};
+void OCopServer::deregisterClient(int fd ) {
+ QMap<int, OCOPClient>::Iterator it = m_clients.find( fd );
+ if (it != m_clients.end() ) {
+ OCOPClient client = (*it);
+ delete client.notify;
+ m_clients.remove(fd );
+ close(fd );
+ /*
+ * TIME_ME
+ *
+ * now delete from all channels
+ * go through all channels
+ * remove the fd from the list
+ * if count becomes 0 remove the channel
+ * otherwise replace QArray<int>
+ */
+ QMap<QCString, QValueList<int> >::Iterator it;
+ for ( it = m_channels.begin(); it != m_channels.end(); ++it ) {
+ /*
+ * The channel contains this fd
+ */
+ if ( it.data().contains( fd ) ) {
+ QValueList<int> array = it.data();
+
+ /*
+ * remove channel or just replace
+ */
+ if ( array.count() == 1 ) {
+ /* is the list now invalidatet? */
+ m_channels.remove( it );
+ }else{
+ array.remove( fd );
+ it = m_channels.replace( it.key(), array );
+ }
+ }
+ } // off all channels
+ }
+ qWarning("clients are now at %d", m_clients.count() );
+};
+/**
+ * this function will evaluate
+ * the package and then do the appropriate thins
+ */
+void OCopServer::dispatch( const OCOPPacket& packet, int sourceFD ) {
+ qWarning("packet.type() == %d", packet.type() );
+ switch( packet.type() ) {
+ case OCOPPacket::Register:
+ registerClient(sourceFD );
+ break;
+ case OCOPPacket::Unregister:
+ deregisterClient(sourceFD );
+ break;
+ case OCOPPacket::Call:
+ call( packet, sourceFD );
+ break;
+ /* not implemented */
+ case OCOPPacket::Method:
+ break;
+ /* nit implemented */
+ case OCOPPacket::Reply:
+ break;
+ case OCOPPacket::RegisterChannel:
+ addChannel( packet.channel() , sourceFD );
+ break;
+ case OCOPPacket::UnregisterChannel:
+ delChannel( packet.channel(), sourceFD );
+ break;
+ /* not implemented */
+ case OCOPPacket::Return:
+ break;
+ /* not implemented :( */
+ case OCOPPacket::Signal:
+ break;
+ case OCOPPacket::IsRegistered:
+ isRegistered( packet.channel(), sourceFD );
+ break;
+ };
+}
+void OCopServer::errorOnServer() {
+ /*
+ * something is wrong on the server socket?
+ * what should we do?
+ * FIXME
+ */
+}
+QStringList OCopServer::channels() {
+ QStringList list;
+ {
+ QMap<QCString, QValueList<int> >::Iterator it;
+ for (it = m_channels.begin(); it != m_channels.end(); ++it ) {
+ list << it.key();
+ };
+ }
+ return list;
+}
+bool OCopServer::isChannelRegistered( const QCString& chan ) const{
+ return m_channels.contains( chan );
+}
+void OCopServer::addChannel( const QCString& channel,
+ int fd ) {
+ QMap<QCString, QValueList<int> >::Iterator it;
+ it = m_channels.find( channel );
+
+ /* could be empty */
+ QValueList<int> list = it.data();
+ list.append( fd );
+ it = m_channels.replace( channel, list );
+};
+void OCopServer::delChannel( const QCString& channel,
+ int fd ) {
+ if (!m_channels.contains( channel ) )
+ return;
+
+ QMap<QCString, QValueList<int> >::Iterator it;
+ it = m_channels.find( channel );
+
+ if ( it.data().contains(fd) ) {
+
+ QValueList<int> ints = it.data();
+ if ( ints.count() == 1 )
+ m_channels.remove( it );
+ else{
+ QValueList<int> ints = it.data();
+ ints.remove( fd );
+ m_channels.replace( it.key(), ints );
+ }
+ }
+}
+void OCopServer::isRegistered( const QCString& channel, int fd) {
+ OCOPHead head;
+ QCString func(2);
+
+ memset(&head, 0, sizeof(head ) );
+ head.magic = 47;
+ head.type = OCOPPacket::IsRegistered;
+ head.chlen = channel.size();
+ head.funclen = func.size();
+ head.datalen = 0;
+
+ if ( isChannelRegistered( channel ) ) {
+ //is registered
+ func[0] = 1;
+ }else{
+ func[0] = 0;
+ }
+
+ /**
+ * write the head
+ * and then channel
+ * success/failure inside func
+ */
+ write(fd, &head, sizeof(head) );
+ write(fd, channel.data(), channel.size() );
+ write(fd, func.data(), func.size() );
+}
+QValueList<int> OCopServer::clients( const QCString& channel ) {
+ return m_channels[channel];
+}
+void OCopServer::call( const OCOPPacket& p, int fd ) {
+ QValueList<int> cli = clients( p.channel() );
+ QValueList<int>::Iterator it;
+
+ OCOPHead head = p.head();
+ for (it = cli.begin(); it != cli.end(); ++it ) {
+ write( (*it), &head, sizeof(head ) );
+ write( (*it), p.channel().data(), p.channel().size() );
+ write( (*it), p.header().data(), p.header().size() );
+ write( (*it), p.content().data(), p.content().size() );
+ };
+}