summaryrefslogtreecommitdiffstats
path: root/ksysguard/gui/ksgrd/SensorAgent.cc
blob: 5fcb14a9ce564d8708702f3062c8d6767c08d6b0 (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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/*
    KSysGuard, the KDE System Guard
   
    Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of version 2 of the GNU General Public
    License as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

*/

#include <stdlib.h>

#include <kdebug.h>
#include <klocale.h>
#include <kpassdlg.h> 

#include "SensorClient.h"
#include "SensorManager.h"

#include "SensorAgent.h"

/**
  This can be used to debug communication problems with the daemon.
  Should be set to 0 in any production version.
*/
#define SA_TRACE 0

using namespace KSGRD;

SensorAgent::SensorAgent( SensorManager *sm )
  : mSensorManager( sm )
{
  /* SensorRequests migrate from the inputFIFO to the processingFIFO. So
   * we only have to delete them when they are removed from the
   * processingFIFO. */
  mInputFIFO.setAutoDelete( false );
  mProcessingFIFO.setAutoDelete( true );

  mDaemonOnLine = false;
  mTransmitting = false;
  mState = 0;
}

SensorAgent::~SensorAgent()
{
}

bool SensorAgent::sendRequest( const TQString &req, SensorClient *client, int id )
{
  /* The request is registered with the FIFO so that the answer can be
   * routed back to the requesting client. */
  mInputFIFO.prepend( new SensorRequest( req, client, id ) );

#if SA_TRACE
  kdDebug(1215) << "-> " << req << "(" << mInputFIFO.count() << "/"
                << mProcessingFIFO.count() << ")" << endl;
#endif
  executeCommand();

  return false;
}

void SensorAgent::processAnswer( const TQString &buffer )
{
#if SA_TRACE
  kdDebug(1215) << "<- " << buffer << endl;
#endif

  for ( uint i = 0; i < buffer.length(); i++ ) {
    if ( buffer[ i ] == '\033' ) {
      mState = ( mState + 1 ) & 1;
      if ( !mErrorBuffer.isEmpty() && mState == 0 ) {
        if ( mErrorBuffer == "RECONFIGURE\n" )
          emit reconfigure( this );
        else {
          /* We just received the end of an error message, so we
           * can display it. */
          SensorMgr->notify( i18n( "Message from %1:\n%2" )
                           .arg( mHostName )
                           .arg( mErrorBuffer ) );
        }
        mErrorBuffer = TQString::null;
      }
    } else if ( mState == 0 ) // receiving to answerBuffer
      mAnswerBuffer += buffer[ i ];
    else  // receiving to errorBuffer
      mErrorBuffer += buffer[ i ];
  }

  int end;
  // And now the real information
  while ( ( end = mAnswerBuffer.find( "\nksysguardd> " ) ) >= 0 ) {
#if SA_TRACE
    kdDebug(1215) << "<= " << mAnswerBuffer.left( end )
                  << "(" << mInputFIFO.count() << "/"
                  << mProcessingFIFO.count() << ")" << endl;
#endif
    if ( !mDaemonOnLine ) {
      /* First '\nksysguardd> ' signals that the daemon is
       * ready to serve requests now. */
      mDaemonOnLine = true;
#if SA_TRACE
      kdDebug(1215) << "Daemon now online!" << endl;
#endif
      mAnswerBuffer = TQString::null;
      break;
    }
	
    // remove pending request from FIFO
    SensorRequest* req = mProcessingFIFO.last();
    if ( !req ) {
      kdDebug(1215)	<< "ERROR: Received answer but have no pending "
                    << "request! : " << mAnswerBuffer.left( end ) << endl;
      mAnswerBuffer = TQString::null;
    } else {		
      if ( !req->client() ) {
        /* The client has disappeared before receiving the answer
         * to his request. */
      } else {
        if ( mAnswerBuffer.left( end ) == "UNKNOWN COMMAND" ) {
        /* Notify client that the sensor seems to be no longer
         * available. */
        req->client()->sensorLost( req->id() );
        } else {
        // Notify client of newly arrived answer.
          req->client()->answerReceived( req->id(), mAnswerBuffer.left( end ) );
        }
      }
      mProcessingFIFO.removeLast();
    }
    // chop off the processed part of the answer buffer
    mAnswerBuffer.remove( 0, end + strlen( "\nksysguardd> " ) );
  }

  executeCommand();
}

void SensorAgent::executeCommand()
{
  /* This function is called whenever there is a chance that we have a
   * command to pass to the daemon. But the command many only be send
   * if the daemon is online and there is no other command currently
   * being sent. */
  if ( mDaemonOnLine && txReady() && !mInputFIFO.isEmpty() ) {
    // take oldest request for input FIFO
    SensorRequest* req = mInputFIFO.last();
    mInputFIFO.removeLast();

#if SA_TRACE
    kdDebug(1215) << ">> " << req->request().ascii() << "(" << mInputFIFO.count()
                  << "/" << mProcessingFIFO.count() << ")" << endl;
#endif
    // send request to daemon
    TQString cmdWithNL = req->request() + "\n";
    if ( writeMsg( cmdWithNL.ascii(), cmdWithNL.length() ) )
      mTransmitting = true;
    else
      kdDebug(1215) << "SensorAgent::writeMsg() failed" << endl;

    // add request to processing FIFO
    mProcessingFIFO.prepend( req );
  }
}

void SensorAgent::disconnectClient( SensorClient *client )
{
  for ( SensorRequest *req = mInputFIFO.first(); req; req = mInputFIFO.next() )
    if ( req->client() == client )
      req->setClient( 0 );
  for ( SensorRequest *req = mProcessingFIFO.first(); req; req = mProcessingFIFO.next() )
    if ( req->client() == client )
      req->setClient( 0 );
}

SensorManager *SensorAgent::sensorManager()
{
  return mSensorManager;
}

void SensorAgent::setDaemonOnLine( bool value )
{
  mDaemonOnLine = value;
}

bool SensorAgent::daemonOnLine() const
{
  return mDaemonOnLine;
}

void SensorAgent::setTransmitting( bool value )
{
  mTransmitting = value;
}

bool SensorAgent::transmitting() const
{
  return mTransmitting;
}

void SensorAgent::setHostName( const TQString &hostName )
{
  mHostName = hostName;
}

const TQString &SensorAgent::hostName() const
{
  return mHostName;
}


SensorRequest::SensorRequest( const TQString &request, SensorClient *client, int id )
  : mRequest( request ), mClient( client ), mId( id )
{
}

SensorRequest::~SensorRequest()
{
}

void SensorRequest::setRequest( const TQString &request )
{
  mRequest = request;
}

TQString SensorRequest::request() const
{
  return mRequest;
}

void SensorRequest::setClient( SensorClient *client )
{
  mClient = client;
}

SensorClient *SensorRequest::client()
{
  return mClient;
}

void SensorRequest::setId( int id )
{
  mId = id;
}

int SensorRequest::id()
{
  return mId;
}

#include "SensorAgent.moc"