summaryrefslogtreecommitdiff
path: root/x11/ipc
authorzecke <zecke>2003-02-05 08:54:58 (UTC)
committer zecke <zecke>2003-02-05 08:54:58 (UTC)
commitbbb3690f12191763a407e6a0edd521113b3c25ac (patch) (side-by-side diff)
tree39f90d71c7f085f5722382db4a5577bbda2e1618 /x11/ipc
parent97b96e141fca844317e59ca5b99c1bf5fa52b1f0 (diff)
downloadopie-bbb3690f12191763a407e6a0edd521113b3c25ac.zip
opie-bbb3690f12191763a407e6a0edd521113b3c25ac.tar.gz
opie-bbb3690f12191763a407e6a0edd521113b3c25ac.tar.bz2
Fix the IPC server and client
registering channel is done locally with refcounts if the channel is already registered globally Fix some sizes to allow proper communication..
Diffstat (limited to 'x11/ipc') (more/less context) (show whitespace changes)
-rw-r--r--x11/ipc/client/ocopclient.cpp8
-rw-r--r--x11/ipc/server/ocopserver.cpp9
2 files changed, 14 insertions, 3 deletions
diff --git a/x11/ipc/client/ocopclient.cpp b/x11/ipc/client/ocopclient.cpp
index 6085481..91827e7 100644
--- a/x11/ipc/client/ocopclient.cpp
+++ b/x11/ipc/client/ocopclient.cpp
@@ -1,159 +1,167 @@
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <qfile.h>
#include <qtimer.h>
#include "../common/ocoppacket.h"
#include "ocopclient.h"
OCOPClient* OCOPClient::m_self = 0;
OCOPClient* OCOPClient::self() {
if (!m_self ) {
m_self = new OCOPClient();
}
return m_self;
}
OCOPClient::OCOPClient( const QString& path, QObject* obj )
: QObject( obj )
{
m_tries = 0;
init(QFile::encodeName(path) );
}
OCOPClient::~OCOPClient() {
delete m_notify;
close( m_socket );
}
void OCOPClient::init() {
// failed start ther server NOW!!!
startUP();
QCString str;
init(str );
}
void OCOPClient::init( const QCString& ) {
m_tries++;
struct sockaddr_un unix_adr;
if ( (m_socket = socket(PF_UNIX, SOCK_STREAM, 0) ) < 0 ) {
qWarning("could not socket");
if ( m_tries < 8 )
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 );
if ( m_tries < 8 )
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() const{
QCString chan;
QCString func;
QByteArray ar;
OCOPHead head;
memset(&head, 0, sizeof(head) );
read(m_socket, &head, sizeof(head) );
if ( head.magic == 47 ) {
+ qWarning("Client:Magic Match");
+ chan = QCString( head.chlen+1);
+ func = QCString( head.funclen+1 );
+ ar = QByteArray( head.datalen);
read(m_socket, chan.data(), head.chlen );
read(m_socket, func.data(), head.funclen );
read(m_socket, ar.data(), head.datalen );
+ qWarning("Client:%d %s",head.chlen,chan.data() );
}
OCOPPacket pack(head.type, chan, func, ar );
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 ) const{
+ qWarning("OCopClient::isRegistered %s", chan.data() );
/* should I disconnect the socket notfier? */
OCOPPacket packe(OCOPPacket::IsRegistered, chan );
OCOPHead head = packe.head();
write(m_socket, &head, sizeof(head) );
write(m_socket, chan.data(), chan.size() );
/* block */
OCOPPacket pack = packet();
+ qWarning("unblock %s %s", pack.channel().data(), chan.data() );
/* connect here again */
if ( pack.channel() == chan ) {
QCString func = pack.header();
if (func[0] == 1 )
return true;
}
return false;
};
void OCOPClient::send( const QCString& chan, const QCString& fu, const QByteArray& arr ) {
+ qWarning("ClientSending %s %s", chan.data(), fu.data() );
OCOPPacket pack(OCOPPacket::Call, chan, fu, arr );
call( pack );
}
void OCOPClient::addChannel(const QCString& channel) {
OCOPPacket pack(OCOPPacket::RegisterChannel, channel );
call( pack );
}
void OCOPClient::delChannel(const QCString& chan ) {
OCOPPacket pack(OCOPPacket::UnregisterChannel, chan );
call( pack );
}
void OCOPClient::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() );
}
void OCOPClient::startUP() {
qWarning("Start me up");
pid_t pi = fork();
if ( pi == 0 ) {
setsid();
execlp("ocopserver", "ocopserver", NULL );
_exit(1);
}
}
diff --git a/x11/ipc/server/ocopserver.cpp b/x11/ipc/server/ocopserver.cpp
index 0f818b7..ee5ea18 100644
--- a/x11/ipc/server/ocopserver.cpp
+++ b/x11/ipc/server/ocopserver.cpp
@@ -42,369 +42,372 @@ void OCopServer::init() {
}
/**
* 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 ) {
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 );
+ QByteArray data ( head.datalen+1 );
/*
* we do not check for errors
*/
// qWarning("read ");
int s = read(fd, channel.data(), head.chlen );
s = read(fd, func.data(), head.funclen );
s = read(fd, data.data(), head.datalen );
// qWarning("read");
/* 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() ) {
/*
* 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 it2;
repeatIt:
for ( it2 = m_channels.begin(); it2 != m_channels.end(); ++it2 ) {
/*
* The channel contains this fd
*/
qWarning("Channel %s %d", it2.key().data(), it2.data().count() );
if ( it2.data().contains( fd ) ) {
qWarning("contains");
QValueList<int> array = it2.data();
/*
* remove channel or just replace
*/
if ( array.count() == 1 || array.count() == 0) {
qWarning("Invalidate!");
/* is the list now invalidatet? */
m_channels.remove( it2 );
/* That is the first go to of my life
* but Iterator remove( Iterator )
* does not exist
* it2 = --it2;
* does not work reliable too
* so the only way is to reiterate :(
*/
goto repeatIt;
}else{
qWarning("removing count %d %d",fd, array.count() );
QValueList<int>::Iterator it3 = array.find( fd );
it3 = array.remove( it3 );
QCString key = it2.key().copy();
it2 = m_channels.replace( key, array );
}
}
} // off all channels
OCOPClient client = it.data();
delete client.notify;
m_clients.remove(fd );
close(fd );
}
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:
- qWarning("IsRegistered");
+ qWarning("Server:IsRegistered %s", packet.channel().data() );
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 );
if ( it != m_channels.end() ) {
/* could be empty */
QValueList<int> list = it.data();
list.append( fd );
qWarning("count is now in addChannel %d %s", list.count(), channel.data() );
it = m_channels.replace( channel, list );
}else {
QValueList<int> ints;
ints.append( fd );
m_channels.insert( channel, ints );
}
};
void OCopServer::delChannel( const QCString& channel,
int fd ) {
qWarning("remove %s, %d", channel.data(), 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( channel );
else{
QValueList<int> ints = it.data();
QValueList<int>::Iterator rem = ints.find( fd );
rem = ints.remove( rem );
QCString str = it.key().copy();
m_channels.replace( str, ints );
}
qWarning(" channel count is now %d", ints.count() );
}
}
void OCopServer::isRegistered( const QCString& channel, int fd) {
-// qWarning("isRegistered");
+ qWarning("Server:isRegistered %s", channel.data() );
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;
+ qWarning("Server:Channel is Registered %d", head.chlen);
}else{
func[0] = 0;
+ qWarning("Server:Channel is NotRegistered");
}
/**
* 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 ) {
QValueList<int> cli = clients( p.channel() );
QValueList<int>::Iterator it;
OCOPHead head = p.head();
for (it = cli.begin(); it != cli.end(); ++it ) {
+ qWarning("Server:calling %d %s %s", (*it), p.channel().data(), p.header().data() );
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() );
};
}