Logo Search packages:      
Sourcecode: kboincspy version File versions  Download package

kbsrpcmonitor.cpp

/***************************************************************************
 *   Copyright (C) 2004 by Roberto Virga                                   *
 *   rvirga@users.sf.net                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <qtimer.h>

#include <klocale.h>

#include <kbsboincmonitor.h>

#include <boincdata.h>

#include "kbsrpcmonitor.h"

KBSRPCMonitor::KBSRPCMonitor(const QString &host, KBSBOINCMonitor *parent, const char *name)
             : QObject(parent, name),
               m_runMode(RunAuto), m_networkMode(ConnectAlways), m_seqno(-1),
               m_host(host),
               m_socket(new QSocket(this)), m_status(Disconnected),
               m_interval(0), m_port(0)
{
  connect(m_socket, SIGNAL(connected()), this, SLOT(slotConnected()));
  connect(m_socket, SIGNAL(connectionClosed()), this, SLOT(slotConnectionClosed()));
  connect(m_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
  connect(m_socket, SIGNAL(error(int)), this, SLOT(slotError(int)));
}

bool KBSRPCMonitor::canRPC() const
{
  return(!m_msgs.msg.isEmpty());
}

int KBSRPCMonitor::interval() const
{
  return m_interval;
}

void KBSRPCMonitor::setInterval(int interval)
{
  if(interval > 0 && interval < 100) interval = 100;
  
  if(interval == m_interval) return;
  
  if(interval > 0)
  {
    m_interval = interval;
    m_timer = startTimer(interval);
    fetchData();
  }
  else if(interval < 0)
  {
    m_interval = 0;
    killTimer(m_timer);
  }

  emit intervalChanged(interval);
}

QString KBSRPCMonitor::host() const
{
  return m_host;
}

void KBSRPCMonitor::setHost(const QString &host)
{
  if(host == m_host) return;
  
  m_host = host;
  
  if(m_status > Disconnected) {
    m_socket->close();
    m_status = Disconnected;
  }
}

unsigned KBSRPCMonitor::port() const
{
  return m_port;
}

void KBSRPCMonitor::setPort(unsigned port)
{
  if(port == m_port) return;
  
  m_port = port;
  
  if(m_status > Disconnected) {
    m_socket->close();
    m_status = Disconnected;
  }
}
BOINCRunMode KBSRPCMonitor::runMode() const
{
  return m_runMode;
}

void KBSRPCMonitor::setRunMode(BOINCRunMode mode)
{
  QDomDocument command;
  
  QDomElement set_run_mode = command.createElement("set_run_mode");
  command.appendChild(set_run_mode);
  
  QString tag;
  switch(mode) {
    case RunAlways:
      tag = "always";
      break;
    case RunNever:
      tag = "never";
      break;    
    default:
      tag = "auto";
      break;
  }
  set_run_mode.appendChild(command.createElement(tag));
  
  sendCommand(command.toString());
}

BOINCNetworkMode KBSRPCMonitor::networkMode() const
{
  return m_networkMode;
}

void KBSRPCMonitor::setNetworkMode(BOINCNetworkMode mode)
{
  QDomDocument command;
  
  QDomElement set_network_mode = command.createElement("set_network_mode");
  command.appendChild(set_network_mode);
  
  QString tag;
  switch(mode) {
    case ConnectNever:
      tag = "never";
      break;    
    default:
      tag = "always";
      break;
  }
  set_network_mode.appendChild(command.createElement(tag));
  
  sendCommand(command.toString());
}

const BOINCMsgs *KBSRPCMonitor::messages() const
{
  return &m_msgs;
}

const BOINCFileTransfers *KBSRPCMonitor::fileTransfers() const
{
  return &m_fileTransfers;
}

void KBSRPCMonitor::setProxyInfo(const BOINCProxyInfo &info)
{
  QDomDocument command;
  
  QDomElement set_proxy_info = command.createElement("set_proxy_info");
  command.appendChild(set_proxy_info);
  
  QDomElement socks_proxy_server_name = command.createElement("socks_proxy_server_name");
  set_proxy_info.appendChild(socks_proxy_server_name);
  socks_proxy_server_name.appendChild(command.createTextNode(info.socks.server.name));
  
  QDomElement socks_proxy_server_port = command.createElement("socks_proxy_server_port");
  set_proxy_info.appendChild(socks_proxy_server_port);
  socks_proxy_server_port.appendChild(command.createTextNode(QString::number(info.socks.server.port)));
  
  QDomElement http_proxy_server_name = command.createElement("http_proxy_server_name");
  set_proxy_info.appendChild(http_proxy_server_name);
  http_proxy_server_name.appendChild(command.createTextNode(info.http.server.name));
  
  QDomElement http_proxy_server_port = command.createElement("http_proxy_server_port");
  set_proxy_info.appendChild(http_proxy_server_port);
  http_proxy_server_port.appendChild(command.createTextNode(QString::number(info.http.server.port)));
  
  QDomElement socks_proxy_user_name = command.createElement("socks_proxy_user_name");
  set_proxy_info.appendChild(socks_proxy_user_name);
  socks_proxy_user_name.appendChild(command.createTextNode(info.socks.user.name));
  
  QDomElement socks_proxy_user_passwd = command.createElement("socks_proxy_user_passwd");
  set_proxy_info.appendChild(socks_proxy_user_passwd);
  socks_proxy_user_passwd.appendChild(command.createTextNode(info.socks.user.passwd));
  
  QDomElement http_proxy_user_name = command.createElement("http_proxy_user_name");
  set_proxy_info.appendChild(http_proxy_user_name);
  http_proxy_user_name.appendChild(command.createTextNode(info.http.user.name));
  
  QDomElement http_proxy_user_passwd = command.createElement("http_proxy_user_passwd");
  set_proxy_info.appendChild(http_proxy_user_passwd);
  http_proxy_user_passwd.appendChild(command.createTextNode(info.http.user.passwd));
  
  sendCommand(command.toString());
}

void KBSRPCMonitor::attachProject(const KURL &url, const QString &id)
{
  QDomDocument command;
  
  QDomElement project_attach = command.createElement("project_attach");
  command.appendChild(project_attach);
  
  QDomElement project_url = command.createElement("project_url");
  project_attach.appendChild(project_url);
  project_url.appendChild(command.createTextNode(url.prettyURL(+1)));
  
  QDomElement authenticator = command.createElement("authenticator");
  project_attach.appendChild(authenticator);
  authenticator.appendChild(command.createTextNode(id));
  
  sendCommand(command.toString());
}

void KBSRPCMonitor::detachProject(const KURL &url)
{
  projectCommand("project_detach", url);
}

void KBSRPCMonitor::resetProject(const KURL &url)
{
  projectCommand("project_reset", url);
}

void KBSRPCMonitor::updateProject(const KURL &url)
{
  projectCommand("project_update", url);
}

void KBSRPCMonitor::suspendProject(const KURL &url, bool suspend)
{
  projectCommand(suspend ? "project_suspend" : "project_resume", url);
}

void KBSRPCMonitor::extinguishProject(const KURL &url, bool extinguish)
{
  projectCommand(extinguish ? "project_nomorework" : "project_allowmorework", url);
}

void KBSRPCMonitor::abortResult(const KURL &url, const QString &result)
{
  resultCommand("abort_result", url, result);
}

void KBSRPCMonitor::suspendResult(const KURL &url, const QString &result, bool suspend)
{
  resultCommand(suspend ? "suspend_result" : "resume_result", url, result);
}

void KBSRPCMonitor::showGraphics(const KURL &url, const QString &result)
{
  QDomDocument command;
  
  QDomElement result_show_graphics = command.createElement("result_show_graphics");
  command.appendChild(result_show_graphics);
  
  QDomElement project_url = command.createElement("project_url");
  result_show_graphics.appendChild(project_url);
  project_url.appendChild(command.createTextNode(url.prettyURL(+1)));
  
  QDomElement result_name = command.createElement("result_name");
  result_show_graphics.appendChild(result_name);
  result_name.appendChild(command.createTextNode(result));
  
  sendCommand(command.toString());
}

void KBSRPCMonitor::abortFileTransfer(const KURL &url, const QString &name)
{
  fileTransferCommand("abort_file_transfer", url, name);
}

void KBSRPCMonitor::retryFileTransfer(const KURL &url, const QString &name)
{
  fileTransferCommand("retry_file_transfer", url, name);
}

void KBSRPCMonitor::sendCommand(const QString &command)
{
  if(m_queue.contains(command)) return;
  m_queue << command;
  
  sendQueued();
  fetchData();
}

KBSBOINCMonitor *KBSRPCMonitor::monitor()
{
  return static_cast<KBSBOINCMonitor*>(parent());
}

void KBSRPCMonitor::projectCommand(const QString &tag, const KURL &url)
{
  QDomDocument command;
  
  QDomElement root = command.createElement(tag);
  command.appendChild(root);
  
  QDomElement project_url = command.createElement("project_url");
  root.appendChild(project_url);
  project_url.appendChild(command.createTextNode(url.prettyURL(+1)));
  
  sendCommand(command.toString());
  QTimer::singleShot(1500, monitor(), SLOT(checkFiles()));
}

void KBSRPCMonitor::resultCommand(const QString &tag, const KURL &url, const QString &result)
{
  QDomDocument command;
  
  QDomElement root = command.createElement(tag);
  command.appendChild(root);
  
  QDomElement project_url = command.createElement("project_url");
  root.appendChild(project_url);
  project_url.appendChild(command.createTextNode(url.prettyURL(+1)));
  
  QDomElement name = command.createElement("name");
  root.appendChild(name);
  name.appendChild(command.createTextNode(result));
  
  sendCommand(command.toString());
  QTimer::singleShot(1500, monitor(), SLOT(checkFiles()));
}

void KBSRPCMonitor::fileTransferCommand(const QString &tag, const KURL &url, const QString &name)
{
  QDomDocument command;
  
  QDomElement root = command.createElement(tag);
  command.appendChild(root);
  
  QDomElement project_url = command.createElement("project_url");
  root.appendChild(project_url);
  project_url.appendChild(command.createTextNode(url.prettyURL(+1)));
  
  QDomElement filename = command.createElement("filename");
  root.appendChild(filename);
  filename.appendChild(command.createTextNode(name));
  
  sendCommand(command.toString());
}

void KBSRPCMonitor::fetchData()
{
  if(Disconnected == m_status) startConnection();
  
  fetchRunMode();
  fetchNetworkMode();
  fetchMessages();
  fetchFileTransfers();
}

void KBSRPCMonitor::timerEvent(QTimerEvent *e)
{
  if(e->timerId() != m_timer || 0 == m_port) return;
  
  fetchData();
}
  
void KBSRPCMonitor::fetchRunMode()
{
  QDomDocument command;
  
  command.appendChild(command.createElement("get_run_mode"));
  
  sendCommand(command.toString());
}

void KBSRPCMonitor::fetchNetworkMode()
{
  QDomDocument command;
  
  QDomElement get_network_mode = command.createElement("get_network_mode");
  command.appendChild(get_network_mode);
  get_network_mode.appendChild(command.createTextNode(""));
  
  sendCommand(command.toString());
}

void KBSRPCMonitor::fetchMessages()
{
  QDomDocument command;
  
  QDomElement get_messages = command.createElement("get_messages");
  command.appendChild(get_messages);
  
  QDomElement nmessages = command.createElement("nmessages");
  get_messages.appendChild(nmessages);
  nmessages.appendChild(command.createTextNode(QString::number(32767)));
  
  if(m_seqno >= 0) {
    QDomElement seqno = command.createElement("seqno");
    get_messages.appendChild(seqno);
    seqno.appendChild(command.createTextNode(QString::number(m_seqno)));
  }  
  
  sendCommand(command.toString());
}

void KBSRPCMonitor::fetchFileTransfers()
{
  QDomDocument command;
  
  QDomElement get_file_transfers = command.createElement("get_file_transfers");
  command.appendChild(get_file_transfers);
  get_file_transfers.appendChild(command.createTextNode(""));
  
  sendCommand(command.toString());
}

void KBSRPCMonitor::massageFileTransfers(BOINCFileTransfers &fileTransfers)
{
  const BOINCClientState *state = monitor()->state();
  if(NULL == state) return;
  
  QMap<QString,BOINCFileTransfer>::iterator transfer;
  for(transfer = fileTransfers.file_transfer.begin();
      transfer != fileTransfers.file_transfer.end(); ++transfer)
    if((*transfer).project_name.isEmpty())
    {
      const QString project = parseProjectName((*transfer).project_url);
      if(project.isEmpty()) continue;
      
      if(state->project.contains(project))
        (*transfer).project_name = state->project[project].project_name;
    }
}

void KBSRPCMonitor::startConnection()
{
  if(Disconnected != m_status) return;
  
  m_status = Connecting;
  
  m_socket->connectToHost(m_host, m_port);
}

void KBSRPCMonitor::sendQueued()
{
  if(Idle != m_status) return;
  
  if(m_queue.isEmpty()) return;
  QString command = m_queue.first();
  m_queue.remove(command);

  m_status = Active;
    
  QTextStream stream(m_socket);
  stream << command << "\n";
  m_socket->flush();
}

void KBSRPCMonitor::slotConnected()
{
  m_status = Idle;
  
  sendQueued();
}

void KBSRPCMonitor::slotConnectionClosed()
{
  Status status = m_status;
  m_status = Disconnected;
  
  m_queue.clear();
  m_output = QString::null;
  
  m_socket->close();
  
  if(!m_msgs.msg.isEmpty())
  {
    m_msgs.msg.clear();
    m_seqno = -1;
    
    emit updated();
    emit messagesUpdated();
  
    if(status >= Idle)
      emit error(i18n("Lost RPC connection"));
  }
}

void KBSRPCMonitor::slotReadyRead()
{
  if(Active != m_status) return;
  
  int len;
  char buffer[1024+1];
  
  while((len = m_socket->readBlock(buffer, 1024)) > 0) {
    buffer[len] = '\0';
    m_output.append(buffer);
  }
  
  if(len < 0) {
    slotError(len);
    return;
  }
  
  if(!m_output.contains('\003')) return;
  
  m_output.remove('\003');
  
  QDomDocument doc;
  if(doc.setContent(m_output))
  {
    QDomNodeList list;
    
    if((list = doc.elementsByTagName("run_mode")).count() > 0)
    {
      QDomElement node = list.item(0).toElement();
      BOINCRunMode runMode = RunAuto;
      
      if(node.elementsByTagName("always").count() > 0)
        runMode = RunAlways;
      else if(node.elementsByTagName("never").count() > 0)
        runMode = RunNever;
      
      if(m_runMode != runMode) {
        m_runMode = runMode;
        emit runModeUpdated();
      }
    }
    else if((list = doc.elementsByTagName("network_mode")).count() > 0)
    {
      QDomElement node = list.item(0).toElement();
      BOINCNetworkMode networkMode = ConnectAlways;
      
      if(node.elementsByTagName("never").count() > 0)
        networkMode = ConnectNever;
      
      if(m_networkMode != networkMode) {
        m_networkMode = networkMode;
        emit networkModeUpdated();
      }
    }
    else if((list = doc.elementsByTagName("msg")).count() > 0)
    {
      const unsigned count = m_msgs.msg.count();
      
      for(unsigned i = 0; i < list.count(); ++i)
      {
        BOINCMsg msg;
        if(msg.parse(list.item(i).toElement())) {
          if(int(msg.seqno) > m_seqno) m_seqno = msg.seqno;
          if(msg.project.isEmpty()) msg.project = "BOINC";
          m_msgs.msg << msg;
        }
      }

      if(m_msgs.msg.count() > count)
      {
        qHeapSort(m_msgs.msg);
        if(0 == count) emit updated();
        emit messagesUpdated();
      }
    }
    else if((list = doc.elementsByTagName("file_transfers")).count() > 0)
    {
      BOINCFileTransfers fileTransfers;
      
      if(fileTransfers.parse(list.item(0).toElement())
         && !(m_fileTransfers.file_transfer.isEmpty()
              && fileTransfers.file_transfer.isEmpty()))
      {
        massageFileTransfers(fileTransfers);
        m_fileTransfers = fileTransfers;
        emit fileTransfersUpdated();
      }
    }
    else if((list = doc.elementsByTagName("error")).count() > 0)
    {
      QDomElement node = list.item(0).toElement();
      emit error(i18n("Client replied \"%1\"").arg(node.text()));
    }
   else if(doc.elementsByTagName("unrecognized").count() > 0)
      emit error(i18n("Unrecognized RPC command"));
  }
  else
    emit error(i18n("Invalid RPC response"));
  
  m_status = Idle;
  
  m_output = QString::null;
  
  sendQueued();
}

void KBSRPCMonitor::slotError(int num)
{
  Status status = m_status;
  m_status = Disconnected;
  
  m_queue.clear();
  m_output = QString::null;
  
  m_socket->close();
  
  if(!m_msgs.msg.isEmpty())
  {
    m_msgs.msg.clear();
    m_seqno = -1;
    
    emit updated();
    emit messagesUpdated();
  }
  
  if(status >= Idle)
    emit error(i18n("Lost RPC connection (error %1)").arg(num));
}

#include "kbsrpcmonitor.moc"

Generated by  Doxygen 1.6.0   Back to index