summaryrefslogtreecommitdiff
path: root/x11/ipc/client/ocopclient.cpp
blob: 43e426c10b39dab85bf5d20c87dfe04dec34e8f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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&  ) {
    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() const{
    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, 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{
    /* 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 true;
    }

    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& 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() );
}