summaryrefslogtreecommitdiff
authorzecke <zecke>2002-10-01 18:04:40 (UTC)
committer zecke <zecke>2002-10-01 18:04:40 (UTC)
commitde95e9ad55685630512a8ee67d6e9214af1b1071 (patch) (side-by-side diff)
treea2f62044d8ba48aab1ca3f74376358f5aef352b3
parent1d9e6c252f74bfc8fcf6c80d8ce2a80cbd566d26 (diff)
downloadopie-de95e9ad55685630512a8ee67d6e9214af1b1071.zip
opie-de95e9ad55685630512a8ee67d6e9214af1b1071.tar.gz
opie-de95e9ad55685630512a8ee67d6e9214af1b1071.tar.bz2
The client should be working
it's complete but I never compiled it
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--x11/ipc/client/ocopclient.cpp129
-rw-r--r--x11/ipc/client/ocopclient.h56
-rw-r--r--x11/ipc/server/ocopserver.cpp1
3 files changed, 186 insertions, 0 deletions
diff --git a/x11/ipc/client/ocopclient.cpp b/x11/ipc/client/ocopclient.cpp
new file mode 100644
index 0000000..1c25271
--- a/dev/null
+++ b/x11/ipc/client/ocopclient.cpp
@@ -0,0 +1,129 @@
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+
+#include <qfile.h>
+#include <qtimer.h>
+
+#include "../common/ocoppacket.h"
+
+#include "ocopclient.h"
+
+OCOPClient::OCOPClient( const QString& path, QObject* obj )
+ : QObject( obj )
+{
+ init(QFile::encodeName(path) );
+}
+OCOPClient::~OCOPClient() {
+ close( m_socket );
+}
+void OCOPClient::init( const QCString& str ) {
+ struct sockaddr_un unix_adr;
+ if ( (m_socket = socket(PF_UNIX, SOCK_STREAM, 0) ) < 0 ) {
+ qWarning("could not socket");
+ QTimer::singleShot(400, this,SLOT(init() ) );
+ return;
+ }
+ memset(&unix_adr, 0, sizeof(unix_adr ) );
+ unix_adr.sun_family = AF_UNIX;
+ sprintf(unix_adr.sun_path,"%s/.opie.cop", getenv("HOME") );
+ int length = sizeof(unix_adr.sun_family) + strlen(unix_adr.sun_path);
+
+ if ( ::connect(m_socket, (struct sockaddr*)&unix_adr, length ) < 0 ) {
+ qWarning("could not connect %d", errno );
+ close( m_socket );
+ QTimer::singleShot(400, this, SLOT(init() ) );
+ return;
+ }
+ m_notify = new QSocketNotifier(m_socket, QSocketNotifier::Read, this );
+ connect( m_notify, SIGNAL(activated(int) ),
+ this, SLOT(newData() ) );
+}
+/**
+ * new data
+ * read the header check magic number
+ * and maybe read body
+ */
+void OCOPClient::newData() {
+ OCOPPacket pack = packet();
+ if ( pack.channel().isEmpty() )
+ return;
+
+ switch( pack.type() ) {
+ case OCOPPacket::Register:
+ case OCOPPacket::Unregister:
+ case OCOPPacket::Method:
+ case OCOPPacket::RegisterChannel:
+ case OCOPPacket::UnregisterChannel:
+ case OCOPPacket::Return:
+ case OCOPPacket::Signal:
+ /* is Registered should be handled sync */
+ case OCOPPacket::isRegistered:
+ break;
+ /* emit the signal */
+ case OCOPPacket::Call:
+ emit called( pack.channel(), pack.header(), pack.content() );
+ break;
+ }
+}
+OCOPPacket OCOPClient::packet() {
+ QCString chan;
+ QCString func;
+ QByteArray ar;
+ OCOPHead head;
+ memset(&head, 0, sizeof(head) );
+ read(m_socket, &head, sizeof(head) );
+ if ( head.magic == 47 ) {
+ read(m_socket, chan.data(), head.chlen );
+ read(m_socket, func.data(), head.funclen );
+ read(m_socket, ar.data(), head.datalen );
+ }
+ OCOPPacket pack(head.type, chan, func, data );
+ return pack;
+}
+/*
+ * we've blocking IO here on these sockets
+ * so we send and go on read
+ * this will be blocked
+ */
+bool OCOPClient::isRegistered( const QCString& chan ) {
+ /* should I disconnect the socket notfier? */
+ OCOPPacket packe(OCOPPacket::IsRegistered, chan );
+ OCOPHead head = packe.head();
+ write(m_socket, &head, sizeof(head) );
+
+ /* block */
+ OCOPPacket pack = packet();
+
+ /* connect here again */
+ if ( pack.channel() == chan ) {
+ QCString func = pack.header();
+ if (func[0] == 1 )
+ return;
+ }
+
+ return false;
+};
+void OCOPClient::send( const QCString& chan, const QCString& fu, const QByteArray& arr ) {
+ OCOPPacket pack(OCOPPacket::Call, chan, fu, arr );
+ call( pack );
+}
+void OCOPClient::addChannel(const QCString& channet) {
+ OCOPPacket pack(OCOPPacket::RegisterChannel, channel );
+ call( pack );
+}
+void OCOPClient::delChannel(const QCString& chan ) {
+ OCOPPacket pack(OCOPPacket::UnregisterChannel, channel );
+ call( pack );
+}
+void OCOPPacket::call( const OCOPPacket& pack ) {
+ OCOPHead head = pack.head();
+ write(m_socket, &head, sizeof(head) );
+ write(m_socket, pack.channel().data(), pack.channel().size() );
+ write(m_socket, pack.header().data(), pack.header().size() );
+ write(m_socket, pack.content().data(), pack.content().size() );
+}
diff --git a/x11/ipc/client/ocopclient.h b/x11/ipc/client/ocopclient.h
new file mode 100644
index 0000000..5300132
--- a/dev/null
+++ b/x11/ipc/client/ocopclient.h
@@ -0,0 +1,56 @@
+#ifndef OPIE_OCOP_CLIENT_H
+#define OPIE_OCOP_CLIENT_H
+
+
+#include <qobject.h>
+#include <qcstring.h>
+#include <qmap.h>
+#include <qsignal.h>
+#include <qstring.h>
+#include <qsocketnotifier.h>
+
+
+/**
+ * This is the OCOP client
+ * It currently only supports
+ * asking if a Channel is registered,
+ * calling and receiving calls
+ */
+class OCOPPacket;
+class OCOPClient : public QObject{
+ Q_OBJECT
+public:
+
+ /**
+ * Occasionally I decide to start a Server from here
+ */
+ OCOPClient(const QString& pathToServer = QString::null, QObject* obj = 0l);
+ ~OCOPClient();
+
+ bool isRegistered( const QCString& )const;
+ void send( const QCString& chan, const QCString&, const QByteArray& msg );
+
+ /**
+ * add a channel and does connect to a signal
+ * callback is the object
+ * slot is the SLOT()
+ */
+ void addChannel( const QCString& channel );
+ void delChannel( const QCString& channel );
+/* no direct signals due the design */
+signals:
+ void called(const QCString&, const QCString&, const QByteArray );
+private slots:
+ void init(const QCString& pa);
+ void newData();
+private:
+ OCOPPacket packet();
+ void call( const OCOPPacket& );
+
+ QSocketNotifier* m_notify;
+ int m_socket;
+private slots:
+
+};
+
+#endif
diff --git a/x11/ipc/server/ocopserver.cpp b/x11/ipc/server/ocopserver.cpp
index 3df574b..e76657e 100644
--- a/x11/ipc/server/ocopserver.cpp
+++ b/x11/ipc/server/ocopserver.cpp
@@ -1,383 +1,384 @@
#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 ) );
+ /* expl. shared! */
write( (*it), p.channel().data(), p.channel().size() );
write( (*it), p.header().data(), p.header().size() );
write( (*it), p.content().data(), p.content().size() );
};
}