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

httpex.cpp

#include <QtCore>
#include <QtNetwork>
#include <QtDebug>

#include "httpex.h"

using namespace HttpEx;

Core::Core(QHttp *http, QObject *parent) : Interface(parent), _http(http)
{
  connect(_http,SIGNAL(authenticationRequired(const QString &,quint16,QAuthenticator *)),
          this,SIGNAL(authenticationRequired(const QString &,quint16,QAuthenticator *)));
  connect(_http,SIGNAL(dataReadProgress(int,int)),this,SIGNAL(dataReadProgress(int,int)));
  connect(_http,SIGNAL(dataSendProgress(int,int)),this,SIGNAL(dataSendProgress(int,int)));
  connect(_http,SIGNAL(done(bool)),this,SIGNAL(done(bool)));
  connect(_http,SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &,QAuthenticator *)),
          this,SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &,QAuthenticator *)));
  connect(_http,SIGNAL(readyRead(const QHttpResponseHeader &)),
          this,SIGNAL(readyRead(const QHttpResponseHeader &)));
  connect(_http,SIGNAL(requestFinished(int,bool)),this,SIGNAL(requestFinished(int,bool)));
  connect(_http,SIGNAL(requestStarted(int)),this,SIGNAL(requestStarted(int)));
  connect(_http,SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
          this,SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)));
  connect(_http,SIGNAL(stateChanged(int)),this,SIGNAL(stateChanged(int)));
}

Base::Base(Interface *interface) : Interface(interface), _interface(interface)
{
  connect(_interface,SIGNAL(authenticationRequired(const QString &,quint16,QAuthenticator *)),
          this,SIGNAL(authenticationRequired(const QString &,quint16,QAuthenticator *)));
  connect(_interface,SIGNAL(dataReadProgress(int,int)),this,SIGNAL(dataReadProgress(int,int)));
  connect(_interface,SIGNAL(dataSendProgress(int,int)),this,SIGNAL(dataSendProgress(int,int)));
  connect(_interface,SIGNAL(done(bool)),this,SIGNAL(done(bool)));
  connect(_interface,SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &,QAuthenticator *)),
          this,SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &,QAuthenticator *)));
  connect(_interface,SIGNAL(readyRead(const QHttpResponseHeader &)),
          this,SIGNAL(readyRead(const QHttpResponseHeader &)));
  connect(_interface,SIGNAL(requestFinished(int,bool)),this,SIGNAL(requestFinished(int,bool)));
  connect(_interface,SIGNAL(requestStarted(int)),this,SIGNAL(requestStarted(int)));
  connect(_interface,SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
          this,SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)));
  connect(_interface,SIGNAL(stateChanged(int)),this,SIGNAL(stateChanged(int)));
}

Log::Log(Interface *interface) : Base(interface)
{
  connectionModes[QHttp::ConnectionModeHttp] = "ConnectionModeHttp";
  connectionModes[QHttp::ConnectionModeHttps] = "ConnectionModeHttps";

  errors[QHttp::NoError] = "NoError";
  errors[QHttp::HostNotFound] = "HostNotFound";
  errors[QHttp::ConnectionRefused] = "ConnectionRefused";
  errors[QHttp::UnexpectedClose] = "UnexpectedClose";
  errors[QHttp::InvalidResponseHeader] = "InvalidResponseHeader";
  errors[QHttp::WrongContentLength] = "WrongContentLength";
  errors[QHttp::Aborted] = "Aborted";
  errors[QHttp::ProxyAuthenticationRequiredError] = "ProxyAuthenticationRequiredError";
  errors[QHttp::AuthenticationRequiredError] = "AuthenticationRequiredError";
  errors[QHttp::UnknownError] = "UnknownError";

  states[QHttp::Unconnected] = "Unconnected";
  states[QHttp::HostLookup] = "HostLookup";
  states[QHttp::Connecting] = "Connecting";
  states[QHttp::Sending] = "Sending";
  states[QHttp::Reading] = "Reading";
  states[QHttp::Connected] = "Connected";
  states[QHttp::Closing] = "Closing";

  connect(this,SIGNAL(authenticationRequired(const QString &,quint16,QAuthenticator *)),
          this,SLOT(authenticationRequiredSlot(const QString &,quint16,QAuthenticator *)));
  connect(this,SIGNAL(dataReadProgress(int,int)),this,SLOT(dataReadProgressSlot(int,int)));
  connect(this,SIGNAL(dataSendProgress(int,int)),this,SLOT(dataSendProgressSlot(int,int)));
  connect(this,SIGNAL(done(bool)),this,SLOT(doneSlot(bool)));
  connect(this,SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &,QAuthenticator *)),
          this,SLOT(proxyAuthenticationRequiredSlot(const QNetworkProxy &,QAuthenticator *)));
  connect(this,SIGNAL(readyRead(const QHttpResponseHeader &)),
          this,SLOT(readyReadSlot(const QHttpResponseHeader &)));
  connect(this,SIGNAL(requestFinished(int,bool)),this,SLOT(requestFinishedSlot(int,bool)));
  connect(this,SIGNAL(requestStarted(int)),this,SLOT(requestStartedSlot(int)));
  connect(this,SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
          this,SLOT(responseHeaderReceivedSlot(const QHttpResponseHeader &)));
  connect(this,SIGNAL(stateChanged(int)),this,SLOT(stateChangedSlot(int)));
}

void Log::clearPendingRequests()
{
  qWarning() << metaObject()->className() << "clearPendingRequests()";
  Base::clearPendingRequests();
}

int Log::close()
{
  int id = Base::close();

  qWarning() << metaObject()->className() << "close(), id =" << id;

  return id;
}

int Log::get(const QString &path, QIODevice *to)
{
  int id = Base::get(path,to);

  qWarning() << metaObject()->className() << "get(" << path << "," << to << "), id =" << id;

  return id;
}

int Log::head(const QString &path)
{
  int id = Base::head(path);

  qWarning() << metaObject()->className() << "head(" << path << "), id =" << id;

  return id;
}

int Log::post(const QString &path, QIODevice *data, QIODevice *to)
{
  int id = Base::post(path,data,to);

  qWarning() << metaObject()->className() << "post(" << path << "," << data << "," << to << "), id =" << id;

  return id;
}

int Log::post(const QString &path, const QByteArray &data, QIODevice *to)
{
  int id = Base::post(path,data,to);

  qWarning() << metaObject()->className() << "post(" << path << "," << data << "," << to << "), id =" << id;

  return id;
}

int Log::request(const QHttpRequestHeader &header, QIODevice *data, QIODevice *to)
{
  int id = Base::request(header,data,to);

  qWarning() << metaObject()->className() << "request(" << header.toString() << "," << data << "," << to << "), id =" << id;

  return id;
}

int Log::request(const QHttpRequestHeader &header, const QByteArray &data, QIODevice *to)
{
  int id = Base::request(header,data,to);

  qWarning() << metaObject()->className() << "request(" << header.toString() << "," << data << "," << to << "), id =" << id;

  return id;
}

int Log::setHost(const QString &hostName, quint16 port)
{
  int id = Base::setHost(hostName,port);

  qWarning() << metaObject()->className() << "setHost(" << hostName << "," << port << "), id =" << id;

  return id;
}

int Log::setHost(const QString &hostName, QHttp::ConnectionMode mode, quint16 port)
{
  int id = Base::setHost(hostName,mode,port);

  qWarning() << metaObject()->className() << "setHost(" << hostName << "," << connectionModes.value(mode) << "," << port << "), id =" << id;

  return id;
}

int Log::setProxy(const QString &host, int port, const QString &username, const QString &password)
{
  int id = Base::setProxy(host,port,username,password);

  qWarning() << metaObject()->className() << "setProxy(" << host << "," << port << "," << username << "," << password << "), id =" << id;

  return id;
}

int Log::setProxy(const QNetworkProxy &proxy)
{
  int id = Base::setProxy(proxy);

  qWarning() << metaObject()->className() << "setProxy(" << proxy.hostName() << "," << proxy.port() << "," << proxy.user() << "," << proxy.password() << "), id =" << id;

  return id;
}

int Log::setSocket(QTcpSocket *socket)
{
  int id = Base::setSocket(socket);

  qWarning() << metaObject()->className() << "setSocket(" << socket << "), id =" << id;

  return id;
}

int Log::setUser(const QString &userName, const QString &password)
{
  int id = Base::setUser(userName,password);

  qWarning() << metaObject()->className() << "setUser(" << userName << "," << password << "), id =" << id;

  return id;
}

void Log::abort()
{
  qWarning() << metaObject()->className() << "abort()" << "bytes available:" << bytesAvailable();
  Base::abort();
}

void Log::internalAbort()
{
  qWarning() << metaObject()->className() << "internalAbort()" << "bytes available:" << bytesAvailable();
  Base::internalAbort();
}

void Log::authenticationRequiredSlot(const QString &hostname, quint16 port, QAuthenticator *authenticator)
{
  qWarning() << "SIGNAL:" << metaObject()->className() << "authenticationRequired(" << hostname << "," << port << "," << authenticator << ")";
}

void Log::dataReadProgressSlot(int done, int total)
{
  qWarning() << "SIGNAL:" << metaObject()->className() << "dataReadProgress(" << done << "," << total << ")";
}

void Log::dataSendProgressSlot(int done, int total)
{
  qWarning() << "SIGNAL:" << metaObject()->className() << "dataSendProgress(" << done << "," << total << ")";
}

void Log::doneSlot(bool error)
{
  qWarning() << "SIGNAL:" << metaObject()->className() << "done(" << error << ")";
  if (error)
    qWarning() << "ERROR:" << errorString();
}

void Log::proxyAuthenticationRequiredSlot(const QNetworkProxy &proxy, QAuthenticator * /* authenticator */)
{
  qWarning() << "SIGNAL:" << metaObject()->className() << "proxyAuthenticationRequired(" << proxy.hostName() << "," << proxy.port() << ")";
}

void Log::readyReadSlot(const QHttpResponseHeader &resp)
{
  qWarning() << "SIGNAL:" << metaObject()->className() << "readyRead(" << resp.toString() << ")";
}

void Log::requestFinishedSlot(int id, bool error)
{
  qWarning() << "SIGNAL:" << metaObject()->className() << "requestFinished(" << id << "," << error << ")";
}

void Log::requestStartedSlot(int id)
{
  qWarning() << "SIGNAL:" << metaObject()->className() << "requestStarted(" << id << ")";
}

void Log::responseHeaderReceivedSlot(const QHttpResponseHeader &resp)
{
  qWarning() << "SIGNAL:" << metaObject()->className() << "responseHeaderReceived(" << resp.toString() << ")";
}

void Log::stateChangedSlot(int state)
{
  qWarning() << "SIGNAL:" << metaObject()->className() << "stateChanged(" << states.value(static_cast<QHttp::State> (state)) << ")";
}

Timeout::Timeout(Interface *interface) : Base(interface)
{
  timer = new QTimer(this);
  timer->setSingleShot(true);
  timer->setInterval(DEFAULT_TIMEOUT);

  connect(this,SIGNAL(stateChanged(int)),this,SLOT(evaluateState(int)));

  connect(this,SIGNAL(dataReadProgress(int,int)),timer,SLOT(start()));
  connect(this,SIGNAL(dataSendProgress(int,int)),timer,SLOT(start()));
  connect(this,SIGNAL(requestStarted(int)),timer,SLOT(start()));

  connect(this,SIGNAL(requestFinished(int,bool)),timer,SLOT(stop()));
  connect(this,SIGNAL(done(bool)),timer,SLOT(stop()));

  connect(timer,SIGNAL(timeout()),this,SLOT(processTimeout()));
  connect(timer,SIGNAL(timeout()),this,SLOT(internalAbort()));
}

void Timeout::setTimeout(int timeout)
{
  timer->setInterval(timeout);
}

int Timeout::timeout() const
{
  return timer->interval();
}

void Timeout::evaluateState(int state)
{
  switch (state)
  {
    case QHttp::Connected:
    case QHttp::Unconnected:
      timer->stop();
      break;

    case QHttp::HostLookup:
    case QHttp::Connecting:
    case QHttp::Sending:
    case QHttp::Closing:
    case QHttp::Reading:
      timer->start();
      break;

    default:
      break;
  }
}

void Timeout::processTimeout()
{
  qWarning() << "TIMEOUT:" << metaObject()->className();
}

Retry::Retry(Interface *interface) : Base(interface)
{
  _state = Idle;
  _tries = DEFAULT_TRIES;
  _aborted = false;

  connect(this,SIGNAL(dataReadProgress(int,int)),this,SLOT(updatePointers(int,int)));
  connect(this,SIGNAL(done(bool)),this,SLOT(processResult(bool)));
  connect(this,SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
          this,SLOT(saveCurrentRequest(const QHttpResponseHeader &)));
  connect(this,SIGNAL(requestStarted(int)),this,SLOT(initPointers()));
  connect(this,SIGNAL(stateChanged(int)),this,SLOT(evaluateNewState(int)));
}

int Retry::get(const QString &path, QIODevice *to)
{
  QHttpRequestHeader req("GET",path);

  req.addValue("Host",lastHostName);
  req.addValue("Connection","keep-alive");
  req.addValue("Accept-Ranges","bytes");
  req.addValue("Accept","*/*");

  switch (_state)
  {
    case Idle:
      _state = Init;
      lastDevice = to;
      _aborted = false;
      return _currentId = Base::request(req,0,to);

    case Init:
    case StoreRequest:
    case Downloading:
    case Closed:
      break;
  }

  return -1;
}

int Retry::post(const QString & /* path */, QIODevice * /* data */, QIODevice * /* to */)
{
  return -1;
}

int Retry::post(const QString & /* path */, const QByteArray & /* data */, QIODevice * /* to */)
{
  return -1;
}

int Retry::request(const QHttpRequestHeader &header, QIODevice *data, QIODevice *to)
{
  QHttpRequestHeader req = header;

  req.addValue("Accept-Ranges","bytes");

  switch (_state)
  {
    case Idle:
      _state = Init;
      lastDevice = to;
      _aborted = false;
      return _currentId = Base::request(req,data,to);

    case Init:
    case StoreRequest:
    case Closed:
      break;

    case Downloading:
      return _currentId = Base::request(header,data,to);
  }

  return -1;
}

int Retry::request(const QHttpRequestHeader &header, const QByteArray &data, QIODevice *to)
{
  QHttpRequestHeader req = header;

  req.addValue("Accept-Ranges","bytes");

  switch (_state)
  {
    case Idle:
      _state = Init;
      lastDevice = to;
      _aborted = false;
      return _currentId = Base::request(req,data,to);

    case Init:
    case StoreRequest:
    case Downloading:
    case Closed:
      break;
  }

  return -1;
}

int Retry::setHost(const QString &hostName, quint16 port)
{
  lastHostName = hostName;
  lastPort = port;
  lastConnectionMode = QHttp::ConnectionModeHttp;

  return Base::setHost(hostName,port);
}

int Retry::setHost(const QString &hostName, QHttp::ConnectionMode mode, quint16 port)
{
  lastHostName = hostName;
  lastPort = port;
  lastConnectionMode = mode;

  return Base::setHost(hostName,mode,port);
}

void Retry::initPointers()
{
  switch (_state)
  {
    case Init:
      if (_currentId == currentId())
      {
        _data.clear();
        _recoverable = false;
        _current = _total = _count = _nowAt = 0;
        lastRequest = QHttpRequestHeader();
        _state = StoreRequest;
      }
      break;

    case Idle:
    case StoreRequest:
    case Downloading:
    case Closed:
      break;
  }
}

void Retry::tryAgain()
{
  QHttpRequestHeader req = lastRequest;

  Base::setHost(lastHostName,lastConnectionMode,lastPort);

  if (_recoverable)
    req.setValue("Range",QString("bytes=%1-%2").arg(_current).arg(_total));
  else
  {
    _current = 0;
    _data.clear();
  }

  qWarning() << "TRY AGAIN:" << metaObject()->className() << req.toString();

  _nowAt = 0;
  request(req,0,lastDevice);
}

void Retry::saveCurrentRequest(const QHttpResponseHeader &resp)
{
  switch (_state)
  {
    case StoreRequest:
      lastRequest = currentRequest();
      _recoverable = resp.hasKey("Accept-Ranges") && resp.value("Accept-Ranges").compare("None",Qt::CaseInsensitive);
      if (resp.hasKey("Content-Length"))
        _data.reserve(resp.value("Content-Length").toInt());
      _state = Downloading;
      break;

    case Idle:
    case Init:
    case Downloading:
    case Closed:
      break;
  }
}

void Retry::updatePointers(int done, int total)
{
  switch (_state)
  {
    case Downloading:
      if (!_total)
        _total = total;

      _nowAt = done;

      if ((_current + done) > _total)
      {
        _current = 0;
        _data.clear();
      }

      emit progress(_count,_current + done,_total);
      break;

    case Idle:
    case Init:
    case StoreRequest:
    case Closed:
      break;
  }
}

void Retry::processResult(bool error)
{
  switch (_state)
  {
    case Downloading:
      _currentId = -1;
      _data += readAll();

      qWarning() << "PROCESS RESULT:" << metaObject()->className() << "count =" << _count << "tries =" << _tries
                 << "nowAt =" << _nowAt << "current =" << _current << "total =" << _total << "data.size=" << _data.size();

      if (error)
      {
        if ((++_count == _tries) || !_total || _aborted)
        {
          _state = Idle;
          emit completed(true,_data);
        }
        else
        {
          if (_nowAt)
            _current += _nowAt;
          _state = Closed;
        }
      }
      else
      {
        if (!_total)
        {
          _state = Idle;
          emit completed(false,_data);
        }
        else
        {
          _current += _nowAt;

          if (_current == _total)
          {
            _state = Idle;
            emit completed(false,_data);
          }
          else
          {
            if (++_count == _tries)
            {
              _state = Idle;
              emit completed(true,_data);
            }
            else
            {
              _state = Closed;
              if (state() == QHttp::Unconnected)
                emit stateChanged(QHttp::Unconnected);
            }
          }
        }
      }
      break;

    case StoreRequest:
      emit completed(true,_data);
      break;

    case Idle:
    case Init:
    case Closed:
      break;
  }
}

void Retry::evaluateNewState(int state)
{
  switch (state)
  {
    case QHttp::Unconnected:
      switch (_state)
      {
        case Idle:
        case Init:
        case StoreRequest:
        case Downloading:
          break;

        case Closed:
          if (!_aborted)
          {
            _state = Downloading;
            tryAgain();
          }
          break;
      }
      break;

    case QHttp::HostLookup:
    case QHttp::Connecting:
    case QHttp::Sending:
    case QHttp::Reading:
    case QHttp::Connected:
    case QHttp::Closing:
      break;
  }
}

void Retry::abort()
{
  _aborted = true;
  Base::abort();
}

Generated by  Doxygen 1.6.0   Back to index