2
KSysGuard, the KDE System Guard
4
Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
6
This program is free software; you can redistribute it and/or
7
modify it under the terms of the GNU General Public
8
License version 2 or at your option version 3 as published by
9
the Free Software Foundation.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27
#include "SensorClient.h"
28
#include "SensorManager.h"
30
#include "SensorAgent.h"
33
This can be used to debug communication problems with the daemon.
34
Should be set to 0 in any production version.
38
using namespace KSGRD;
40
SensorAgent::SensorAgent( SensorManager *sm ) : QObject(sm)
43
mDaemonOnLine = false;
46
SensorAgent::~SensorAgent()
48
for(int i = mInputFIFO.size()-1; i >= 0; --i)
49
delete mInputFIFO.takeAt(i);
50
for(int i = mProcessingFIFO.size()-1; i >= 0; --i)
51
delete mProcessingFIFO.takeAt(i);
54
void SensorAgent::sendRequest( const QString &req, SensorClient *client, int id )
56
SensorRequest *sensorreq = 0;
57
for(int i =0; i < mInputFIFO.size(); ++i) {
58
sensorreq = mInputFIFO.at(i);
59
if(id == sensorreq->id() && client == sensorreq->client() && req == sensorreq->request()) {
61
return; //don't bother to resend the same request if we already have it in our queue to send
64
for(int i =0; i < mProcessingFIFO.size(); ++i) {
65
sensorreq = mProcessingFIFO.at(i);
66
if(id == sensorreq->id() && client == sensorreq->client() && req == sensorreq->request())
67
return; //don't bother to resend the same request if we have already sent the request to client and just waiting for an answer
70
/* The request is registered with the FIFO so that the answer can be
71
* routed back to the requesting client. */
72
mInputFIFO.enqueue( new SensorRequest( req, client, id ) );
75
kDebug(1215) << "-> " << req << "(" << mInputFIFO.count() << "/"
76
<< mProcessingFIFO.count() << ")" << endl;
81
void SensorAgent::processAnswer( const char *buf, int buflen )
83
//It is possible for an answer/error message to be split across multiple processAnswer calls. This makes our life more difficult
84
//We have to keep track of the state we are in. Any characters that we have not parsed yet we put in
86
QByteArray buffer = QByteArray::fromRawData(buf, buflen);
87
if(!mLeftOverBuffer.isEmpty()) {
88
buffer = mLeftOverBuffer + buffer; //If we have data left over from a previous processAnswer, then we have to prepend this on
89
mLeftOverBuffer.clear();
93
kDebug(1215) << "<- " << QString::fromUtf8(buffer, buffer.size());
95
int startOfAnswer = 0; //This can become >= buffer.size(), so check before using!
96
for ( int i = 0; i < buffer.size(); ++i ) {
97
if ( buffer.at(i) == '\033' ) { // 033 in octal is the escape character. The signifies the start of an error
100
while(++i < buffer.size()) {
101
if(buffer.at(i) == '\033') {
102
QString error = QString::fromUtf8(buffer.constData() + startOfError+1, i-startOfError-1);
103
if ( error.startsWith(QLatin1String("RECONFIGURE")) ) {
104
emit reconfigure( this );
107
/* We just received the end of an error message, so we
109
SensorMgr->notify( i18nc( "%1 is a host name", "Message from %1:\n%2",
118
buffer.remove(startOfError, i-startOfError+1);
119
i = startOfAnswer - 1;
122
//We have not found the end of the escape string. Try checking in the next packet
123
mLeftOverBuffer = QByteArray(buffer.constData()+startOfAnswer, buffer.size()-startOfAnswer);
128
//The spec was supposed to be that it returned "\nksysguardd> " but some seem to forget the space, so we have to compensate. Sigh
129
if( (i==startOfAnswer && buffer.size() -i >= (signed)(sizeof("ksysguardd>" ))-1 && qstrncmp(buffer.constData()+i, "ksysguardd>", sizeof("ksysguardd>" )-1) == 0) ||
130
(buffer.size() -i >= (signed)(sizeof("\nksysguardd>"))-1 && qstrncmp(buffer.constData()+i, "\nksysguardd>", sizeof("\nksysguardd>")-1) == 0)) {
132
QByteArray answer(buffer.constData()+startOfAnswer, i-startOfAnswer);
133
if(!answer.isEmpty())
134
mAnswerBuffer << answer;
136
kDebug(1215) << "<= " << mAnswerBuffer
137
<< "(" << mInputFIFO.count() << "/"
138
<< mProcessingFIFO.count() << ")" << endl;
140
if(buffer.at(i) == '\n')
142
i += sizeof("ksysguardd>") -2; //Move i on to the next answer (if any). -2 because sizeof adds one for \0 and the for loop will increment by 1 also
143
if(i+1 < buffer.size() && buffer.at(i+1) == ' ') i++;
146
//We have found the end of one reply
147
if ( !mDaemonOnLine ) {
148
/* First '\nksysguardd> ' signals that the daemon is
149
* ready to serve requests now. */
150
mDaemonOnLine = true;
152
kDebug(1215) << "Daemon now online!";
154
mAnswerBuffer.clear();
158
//Deal with the answer we have now read in
160
// remove pending request from FIFO
161
if ( mProcessingFIFO.isEmpty() ) {
162
kDebug(1215) << "ERROR: Received answer but have no pending "
163
<< "request!" << endl;
164
mAnswerBuffer.clear();
168
SensorRequest *req = mProcessingFIFO.dequeue();
169
// we are now responsible for the memory of req - we must delete it!
170
if ( !req->client() ) {
171
/* The client has disappeared before receiving the answer
174
mAnswerBuffer.clear();
178
if(!mAnswerBuffer.isEmpty() && mAnswerBuffer[0] == "UNKNOWN COMMAND") {
179
/* Notify client that the sensor seems to be no longer available. */
180
kDebug(1215) << "Received UNKNOWN COMMAND for: " << req->request();
181
req->client()->sensorLost( req->id() );
183
// Notify client of newly arrived answer.
184
req->client()->answerReceived( req->id(), mAnswerBuffer );
187
mAnswerBuffer.clear();
188
} else if(buffer.at(i) == '\n'){
189
mAnswerBuffer << QByteArray(buffer.constData()+startOfAnswer, i-startOfAnswer);
194
mLeftOverBuffer += QByteArray(buffer.constData()+startOfAnswer, buffer.size()-startOfAnswer);
198
void SensorAgent::executeCommand()
200
/* This function is called whenever there is a chance that we have a
201
* command to pass to the daemon. But the command may only be sent
202
* if the daemon is online and there is no other command currently
204
if ( mDaemonOnLine && !mInputFIFO.isEmpty() ) {
205
SensorRequest *req = mInputFIFO.dequeue();
208
kDebug(1215) << ">> " << req->request().toAscii() << "(" << mInputFIFO.count()
209
<< "/" << mProcessingFIFO.count() << ")" << endl;
211
// send request to daemon
212
QString cmdWithNL = req->request() + '\n';
213
if ( !writeMsg( cmdWithNL.toLatin1(), cmdWithNL.length() ) )
214
kDebug(1215) << "SensorAgent::writeMsg() failed";
216
// add request to processing FIFO.
217
// Note that this means that mProcessingFIFO is now responsible for managing the memory for it.
218
mProcessingFIFO.enqueue( req );
222
void SensorAgent::disconnectClient( SensorClient *client )
224
for (int i = 0; i < mInputFIFO.size(); ++i)
225
if ( mInputFIFO[i]->client() == client )
226
mInputFIFO[i]->setClient(0);
227
for (int i = 0; i < mProcessingFIFO.size(); ++i)
228
if ( mProcessingFIFO[i]->client() == client )
229
mProcessingFIFO[i]->setClient( 0 );
233
SensorManager *SensorAgent::sensorManager()
235
return mSensorManager;
238
void SensorAgent::setDaemonOnLine( bool value )
240
mDaemonOnLine = value;
243
bool SensorAgent::daemonOnLine() const
245
return mDaemonOnLine;
248
void SensorAgent::setHostName( const QString &hostName )
250
mHostName = hostName;
253
QString SensorAgent::hostName() const
258
QString SensorAgent::reasonForOffline() const
260
return mReasonForOffline;
263
void SensorAgent::setReasonForOffline(const QString &reasonForOffline)
265
mReasonForOffline = reasonForOffline;
268
SensorRequest::SensorRequest( const QString &request, SensorClient *client, int id )
269
: mRequest( request ), mClient( client ), mId( id )
273
SensorRequest::~SensorRequest()
277
void SensorRequest::setRequest( const QString &request )
282
QString SensorRequest::request() const
287
void SensorRequest::setClient( SensorClient *client )
292
SensorClient *SensorRequest::client()
297
void SensorRequest::setId( int id )
302
int SensorRequest::id()
307
#include "SensorAgent.moc"