summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore 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 @@
1#include <errno.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <unistd.h>
5#include <sys/socket.h>
6#include <sys/un.h>
7
8
9#include <qfile.h>
10#include <qtimer.h>
11
12#include "../common/ocoppacket.h"
13
14#include "ocopclient.h"
15
16OCOPClient::OCOPClient( const QString& path, QObject* obj )
17 : QObject( obj )
18{
19 init(QFile::encodeName(path) );
20}
21OCOPClient::~OCOPClient() {
22 close( m_socket );
23}
24void OCOPClient::init( const QCString& str ) {
25 struct sockaddr_un unix_adr;
26 if ( (m_socket = socket(PF_UNIX, SOCK_STREAM, 0) ) < 0 ) {
27 qWarning("could not socket");
28 QTimer::singleShot(400, this,SLOT(init() ) );
29 return;
30 }
31 memset(&unix_adr, 0, sizeof(unix_adr ) );
32 unix_adr.sun_family = AF_UNIX;
33 sprintf(unix_adr.sun_path,"%s/.opie.cop", getenv("HOME") );
34 int length = sizeof(unix_adr.sun_family) + strlen(unix_adr.sun_path);
35
36 if ( ::connect(m_socket, (struct sockaddr*)&unix_adr, length ) < 0 ) {
37 qWarning("could not connect %d", errno );
38 close( m_socket );
39 QTimer::singleShot(400, this, SLOT(init() ) );
40 return;
41 }
42 m_notify = new QSocketNotifier(m_socket, QSocketNotifier::Read, this );
43 connect( m_notify, SIGNAL(activated(int) ),
44 this, SLOT(newData() ) );
45}
46/**
47 * new data
48 * read the header check magic number
49 * and maybe read body
50 */
51void OCOPClient::newData() {
52 OCOPPacket pack = packet();
53 if ( pack.channel().isEmpty() )
54 return;
55
56 switch( pack.type() ) {
57 case OCOPPacket::Register:
58 case OCOPPacket::Unregister:
59 case OCOPPacket::Method:
60 case OCOPPacket::RegisterChannel:
61 case OCOPPacket::UnregisterChannel:
62 case OCOPPacket::Return:
63 case OCOPPacket::Signal:
64 /* is Registered should be handled sync */
65 case OCOPPacket::isRegistered:
66 break;
67 /* emit the signal */
68 case OCOPPacket::Call:
69 emit called( pack.channel(), pack.header(), pack.content() );
70 break;
71 }
72}
73OCOPPacket OCOPClient::packet() {
74 QCString chan;
75 QCString func;
76 QByteArray ar;
77 OCOPHead head;
78 memset(&head, 0, sizeof(head) );
79 read(m_socket, &head, sizeof(head) );
80 if ( head.magic == 47 ) {
81 read(m_socket, chan.data(), head.chlen );
82 read(m_socket, func.data(), head.funclen );
83 read(m_socket, ar.data(), head.datalen );
84 }
85 OCOPPacket pack(head.type, chan, func, data );
86 return pack;
87}
88/*
89 * we've blocking IO here on these sockets
90 * so we send and go on read
91 * this will be blocked
92 */
93bool OCOPClient::isRegistered( const QCString& chan ) {
94 /* should I disconnect the socket notfier? */
95 OCOPPacket packe(OCOPPacket::IsRegistered, chan );
96 OCOPHead head = packe.head();
97 write(m_socket, &head, sizeof(head) );
98
99 /* block */
100 OCOPPacket pack = packet();
101
102 /* connect here again */
103 if ( pack.channel() == chan ) {
104 QCString func = pack.header();
105 if (func[0] == 1 )
106 return;
107 }
108
109 return false;
110};
111void OCOPClient::send( const QCString& chan, const QCString& fu, const QByteArray& arr ) {
112 OCOPPacket pack(OCOPPacket::Call, chan, fu, arr );
113 call( pack );
114}
115void OCOPClient::addChannel(const QCString& channet) {
116 OCOPPacket pack(OCOPPacket::RegisterChannel, channel );
117 call( pack );
118}
119void OCOPClient::delChannel(const QCString& chan ) {
120 OCOPPacket pack(OCOPPacket::UnregisterChannel, channel );
121 call( pack );
122}
123void OCOPPacket::call( const OCOPPacket& pack ) {
124 OCOPHead head = pack.head();
125 write(m_socket, &head, sizeof(head) );
126 write(m_socket, pack.channel().data(), pack.channel().size() );
127 write(m_socket, pack.header().data(), pack.header().size() );
128 write(m_socket, pack.content().data(), pack.content().size() );
129}
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 @@
1#ifndef OPIE_OCOP_CLIENT_H
2#define OPIE_OCOP_CLIENT_H
3
4
5#include <qobject.h>
6#include <qcstring.h>
7#include <qmap.h>
8#include <qsignal.h>
9#include <qstring.h>
10#include <qsocketnotifier.h>
11
12
13/**
14 * This is the OCOP client
15 * It currently only supports
16 * asking if a Channel is registered,
17 * calling and receiving calls
18 */
19class OCOPPacket;
20class OCOPClient : public QObject{
21 Q_OBJECT
22public:
23
24 /**
25 * Occasionally I decide to start a Server from here
26 */
27 OCOPClient(const QString& pathToServer = QString::null, QObject* obj = 0l);
28 ~OCOPClient();
29
30 bool isRegistered( const QCString& )const;
31 void send( const QCString& chan, const QCString&, const QByteArray& msg );
32
33 /**
34 * add a channel and does connect to a signal
35 * callback is the object
36 * slot is the SLOT()
37 */
38 void addChannel( const QCString& channel );
39 void delChannel( const QCString& channel );
40/* no direct signals due the design */
41signals:
42 void called(const QCString&, const QCString&, const QByteArray );
43private slots:
44 void init(const QCString& pa);
45 void newData();
46private:
47 OCOPPacket packet();
48 void call( const OCOPPacket& );
49
50 QSocketNotifier* m_notify;
51 int m_socket;
52private slots:
53
54};
55
56#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
@@ -283,101 +283,102 @@ void OCopServer::dispatch( const OCOPPacket& packet, int sourceFD ) {
283 break; 283 break;
284 /* not implemented :( */ 284 /* not implemented :( */
285 case OCOPPacket::Signal: 285 case OCOPPacket::Signal:
286 break; 286 break;
287 case OCOPPacket::IsRegistered: 287 case OCOPPacket::IsRegistered:
288 isRegistered( packet.channel(), sourceFD ); 288 isRegistered( packet.channel(), sourceFD );
289 break; 289 break;
290 }; 290 };
291} 291}
292void OCopServer::errorOnServer() { 292void OCopServer::errorOnServer() {
293 /* 293 /*
294 * something is wrong on the server socket? 294 * something is wrong on the server socket?
295 * what should we do? 295 * what should we do?
296 * FIXME 296 * FIXME
297 */ 297 */
298} 298}
299QStringList OCopServer::channels() { 299QStringList OCopServer::channels() {
300 QStringList list; 300 QStringList list;
301 { 301 {
302 QMap<QCString, QValueList<int> >::Iterator it; 302 QMap<QCString, QValueList<int> >::Iterator it;
303 for (it = m_channels.begin(); it != m_channels.end(); ++it ) { 303 for (it = m_channels.begin(); it != m_channels.end(); ++it ) {
304 list << it.key(); 304 list << it.key();
305 }; 305 };
306 } 306 }
307 return list; 307 return list;
308} 308}
309bool OCopServer::isChannelRegistered( const QCString& chan ) const{ 309bool OCopServer::isChannelRegistered( const QCString& chan ) const{
310 return m_channels.contains( chan ); 310 return m_channels.contains( chan );
311} 311}
312void OCopServer::addChannel( const QCString& channel, 312void OCopServer::addChannel( const QCString& channel,
313 int fd ) { 313 int fd ) {
314 QMap<QCString, QValueList<int> >::Iterator it; 314 QMap<QCString, QValueList<int> >::Iterator it;
315 it = m_channels.find( channel ); 315 it = m_channels.find( channel );
316 316
317 /* could be empty */ 317 /* could be empty */
318 QValueList<int> list = it.data(); 318 QValueList<int> list = it.data();
319 list.append( fd ); 319 list.append( fd );
320 it = m_channels.replace( channel, list ); 320 it = m_channels.replace( channel, list );
321}; 321};
322void OCopServer::delChannel( const QCString& channel, 322void OCopServer::delChannel( const QCString& channel,
323 int fd ) { 323 int fd ) {
324 if (!m_channels.contains( channel ) ) 324 if (!m_channels.contains( channel ) )
325 return; 325 return;
326 326
327 QMap<QCString, QValueList<int> >::Iterator it; 327 QMap<QCString, QValueList<int> >::Iterator it;
328 it = m_channels.find( channel ); 328 it = m_channels.find( channel );
329 329
330 if ( it.data().contains(fd) ) { 330 if ( it.data().contains(fd) ) {
331 331
332 QValueList<int> ints = it.data(); 332 QValueList<int> ints = it.data();
333 if ( ints.count() == 1 ) 333 if ( ints.count() == 1 )
334 m_channels.remove( it ); 334 m_channels.remove( it );
335 else{ 335 else{
336 QValueList<int> ints = it.data(); 336 QValueList<int> ints = it.data();
337 ints.remove( fd ); 337 ints.remove( fd );
338 m_channels.replace( it.key(), ints ); 338 m_channels.replace( it.key(), ints );
339 } 339 }
340 } 340 }
341} 341}
342void OCopServer::isRegistered( const QCString& channel, int fd) { 342void OCopServer::isRegistered( const QCString& channel, int fd) {
343 OCOPHead head; 343 OCOPHead head;
344 QCString func(2); 344 QCString func(2);
345 345
346 memset(&head, 0, sizeof(head ) ); 346 memset(&head, 0, sizeof(head ) );
347 head.magic = 47; 347 head.magic = 47;
348 head.type = OCOPPacket::IsRegistered; 348 head.type = OCOPPacket::IsRegistered;
349 head.chlen = channel.size(); 349 head.chlen = channel.size();
350 head.funclen = func.size(); 350 head.funclen = func.size();
351 head.datalen = 0; 351 head.datalen = 0;
352 352
353 if ( isChannelRegistered( channel ) ) { 353 if ( isChannelRegistered( channel ) ) {
354 //is registered 354 //is registered
355 func[0] = 1; 355 func[0] = 1;
356 }else{ 356 }else{
357 func[0] = 0; 357 func[0] = 0;
358 } 358 }
359 359
360 /** 360 /**
361 * write the head 361 * write the head
362 * and then channel 362 * and then channel
363 * success/failure inside func 363 * success/failure inside func
364 */ 364 */
365 write(fd, &head, sizeof(head) ); 365 write(fd, &head, sizeof(head) );
366 write(fd, channel.data(), channel.size() ); 366 write(fd, channel.data(), channel.size() );
367 write(fd, func.data(), func.size() ); 367 write(fd, func.data(), func.size() );
368} 368}
369QValueList<int> OCopServer::clients( const QCString& channel ) { 369QValueList<int> OCopServer::clients( const QCString& channel ) {
370 return m_channels[channel]; 370 return m_channels[channel];
371} 371}
372void OCopServer::call( const OCOPPacket& p, int fd ) { 372void OCopServer::call( const OCOPPacket& p, int fd ) {
373 QValueList<int> cli = clients( p.channel() ); 373 QValueList<int> cli = clients( p.channel() );
374 QValueList<int>::Iterator it; 374 QValueList<int>::Iterator it;
375 375
376 OCOPHead head = p.head(); 376 OCOPHead head = p.head();
377 for (it = cli.begin(); it != cli.end(); ++it ) { 377 for (it = cli.begin(); it != cli.end(); ++it ) {
378 write( (*it), &head, sizeof(head ) ); 378 write( (*it), &head, sizeof(head ) );
379 /* expl. shared! */
379 write( (*it), p.channel().data(), p.channel().size() ); 380 write( (*it), p.channel().data(), p.channel().size() );
380 write( (*it), p.header().data(), p.header().size() ); 381 write( (*it), p.header().data(), p.header().size() );
381 write( (*it), p.content().data(), p.content().size() ); 382 write( (*it), p.content().data(), p.content().size() );
382 }; 383 };
383} 384}