summaryrefslogtreecommitdiff
path: root/x11/ipc/client/ocopclient.cpp
blob: 608548132d253316fe9983c43f16fd4a3eaa2efd (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#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 ) {
        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) );
    write(m_socket, chan.data(), chan.size() );
    /* 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() );
}
void OCOPClient::startUP() {
    qWarning("Start me up");
    pid_t pi = fork();
    if ( pi == 0 ) {
        setsid();
        execlp("ocopserver", "ocopserver", NULL );
        _exit(1);
    }
}