<commit_before>/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  DataDifferential Utility Library
 *
 *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *      * Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *      * Redistributions in binary form must reproduce the above
 *  copyright notice, this list of conditions and the following disclaimer
 *  in the documentation and/or other materials provided with the
 *  distribution.
 *
 *      * The names of its contributors may not be used to endorse or
 *  promote products derived from this software without specific prior
 *  written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "gear_config.h"

#include "util/instance.hpp"

#include <cstdio>
#include <iostream>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <sstream>
#include <sys/socket.h>
#include <sys/types.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

namespace datadifferential {
namespace util {

Instance::Instance(const std::string& hostname_arg, const std::string& service_arg) :
  _host(hostname_arg),
  _service(service_arg),
  _sockfd(INVALID_SOCKET),
  _use_ssl(false),
  state(NOT_WRITING),
  _addrinfo(0),
  _addrinfo_next(0),
  _finish_fn(NULL),
  _operations(),
  _ctx_ssl(NULL),
  _ssl(NULL)
  {
  }

Instance::Instance(const std::string& hostname_arg, const in_port_t port_arg) :
  _host(hostname_arg),
  _sockfd(INVALID_SOCKET),
  _use_ssl(false),
  state(NOT_WRITING),
  _addrinfo(0),
  _addrinfo_next(0),
  _finish_fn(NULL),
  _operations(),
  _ctx_ssl(NULL),
  _ssl(NULL)
  {
    char tmp[BUFSIZ];
    snprintf(tmp, sizeof(tmp), "%u", static_cast<unsigned int>(port_arg));
    _service= tmp;
  }

Instance::~Instance()
{
  close_socket();
  free_addrinfo();
  for (Operation::vector::iterator iter= _operations.begin(); iter != _operations.end(); ++iter)
  {
    delete *iter;
  }
  _operations.clear();

  delete _finish_fn;

#if defined(HAVE_CYASSL) && HAVE_CYASSL
  if (_ssl)
  {
    CyaSSL_shutdown(_ssl);
    CyaSSL_free(_ssl);
  }
  if (_ctx_ssl)
  {
    CyaSSL_CTX_free(_ctx_ssl);
  }
  CyaSSL_Cleanup();
#endif
}

bool Instance::init_ssl()
{
#if defined(HAVE_CYASSL) && HAVE_CYASSL
  CyaSSL_Init();

  if ((_ctx_ssl= CyaSSL_CTX_new(CyaTLSv1_client_method())) == NULL)
  {
    _last_error= "CyaSSL_CTX_new error";
    return false;
  }

  if (CyaSSL_CTX_load_verify_locations(_ctx_ssl, ssl_ca_file(), 0) != SSL_SUCCESS)
  {
    std::stringstream message;
    message << "Error loading CA file " << ssl_ca_file();
    _last_error= message.str();
    return false;
  }

  if (CyaSSL_CTX_use_certificate_file(_ctx_ssl, ssl_certificate(), SSL_FILETYPE_PEM) != SSL_SUCCESS)
  {
    std::stringstream message;
    message << "Error loading certificate file " << ssl_certificate();
    _last_error= message.str();
    return false;
  }

  if (CyaSSL_CTX_use_PrivateKey_file(_ctx_ssl, ssl_key(), SSL_FILETYPE_PEM) != SSL_SUCCESS)
  {
    std::stringstream message;
    message << "Error loading private key file " << ssl_key();
    _last_error= message.str();
    return false;
  }
#endif // defined(HAVE_CYASSL) && HAVE_CYASSL
  return true;
}

bool Instance::run()
{
  if (_use_ssl)
  {
    if (not init_ssl())
    {
      return false;
    }
  }

  while (not _operations.empty())
  {
    Operation::vector::value_type operation= _operations.back();

    switch (state)
    {
    case NOT_WRITING:
      {
        free_addrinfo();

        struct addrinfo ai;
        memset(&ai, 0, sizeof(struct addrinfo));
        ai.ai_socktype= SOCK_STREAM;
        ai.ai_protocol= IPPROTO_TCP;

        int ret= getaddrinfo(_host.c_str(), _service.c_str(), &ai, &_addrinfo);
        if (ret)
        {
          std::stringstream message;
          message << "Failed to connect on " << _host.c_str() << ":" << _service.c_str() << " with "  << gai_strerror(ret);
          _last_error= message.str();
          return false;
        }
      }
      _addrinfo_next= _addrinfo;
      state= CONNECT;
      break;

    case NEXT_CONNECT_ADDRINFO:
      if (_addrinfo_next->ai_next == NULL)
      {
        std::stringstream message;
        message << "Error connecting to " << _host.c_str() << "." << std::endl;
        _last_error= message.str();
        return false;
      }
      _addrinfo_next= _addrinfo_next->ai_next;

    case CONNECT:
      close_socket();

      _sockfd= socket(_addrinfo_next->ai_family,
                      _addrinfo_next->ai_socktype,
                      _addrinfo_next->ai_protocol);
      if (_sockfd == INVALID_SOCKET)
      {
        perror("socket");
        continue;
      }

      if (connect(_sockfd, _addrinfo_next->ai_addr, _addrinfo_next->ai_addrlen) < 0)
      {
        switch(errno)
        {
        case EAGAIN:
        case EINTR:
          state= CONNECT;
          break;

        case EINPROGRESS:
          state= CONNECTING;
          break;

        case ECONNREFUSED:
        case ENETUNREACH:
        case ETIMEDOUT:
        default:
          state= NEXT_CONNECT_ADDRINFO;
          break;
        }
      }
      else
      {
        state= CONNECTING;
      }
      break;

    case CONNECTING:
      // Add logic for poll() for nonblocking.
      state= CONNECTED;
      break;

    case CONNECTED:
    case WRITING:
      {
        size_t packet_length= operation->size();
        const char *packet= operation->ptr();

#if defined(HAVE_CYASSL) && HAVE_CYASSL
        if (_ctx_ssl)
        {
          _ssl= CyaSSL_new(_ctx_ssl);
          if (_ssl == NULL)
          {
            _last_error= "CyaSSL_new() failed";
            return false;
          }

          int ssl_error;
          if ((ssl_error= CyaSSL_set_fd(_ssl, _sockfd)) != SSL_SUCCESS)
          {
            _last_error= "CyaSSL_set_fd() failed";
            return false;
          }
        }
#endif

        while(packet_length)
        {
          ssize_t write_size;
#if defined(HAVE_CYASSL) && HAVE_CYASSL
          if (_ssl)
          {
            write_size= CyaSSL_write(_ssl, (const void*)packet, int(packet_length));
            if (write_size < 0)
            {
              char errorString[80];
              CyaSSL_ERR_error_string(CyaSSL_get_error(_ssl, 0), errorString);
              _last_error= errorString;
              return false;
            }
          }
          else
#endif
          {
            write_size= send(_sockfd, packet, packet_length, 0);

            if (write_size < 0)
            {
              std::stringstream msg;
              msg << "Failed during send(" << strerror(errno) << ")";
              _last_error= msg.str();
              return false;
            }
          }

          packet_length-= static_cast<size_t>(write_size);
          packet+= static_cast<size_t>(write_size);
        }
      }
      state= READING;
      break;

    case READING:
      if (operation->has_response())
      {
        ssize_t read_length;

        do
        {
          char buffer[BUFSIZ];
#if defined(HAVE_CYASSL) && HAVE_CYASSL
          if (_ssl)
          {
            read_length= CyaSSL_read(_ssl, (void *)buffer, sizeof(buffer));
            if (read_length < 0)
            {
              char errorString[80];
              CyaSSL_ERR_error_string(CyaSSL_get_error(_ssl, 0), errorString);
              _last_error= errorString;
              return false;
            }
          }
          else
#endif
          {
            read_length= ::recv(_sockfd, buffer, sizeof(buffer), 0);
          }

          if (read_length < 0)
          {
            _last_error.clear();
            _last_error+= "Error occured while reading data from ";
            _last_error+= _host;
            return false;
          }
          else if (read_length == 0)
          {
            _last_error.clear();
            _last_error+= "Socket was shutdown while reading from ";
            _last_error+= _host;
            return false;
          }

          operation->push(buffer, static_cast<size_t>(read_length));

        } while (more_to_read());
      } // end has_response

      state= FINISHED;
      break;

    case FINISHED:
      std::string response;
      bool success= operation->response(response);
      if (_finish_fn)
      {
        if (not _finish_fn->call(success, response))
        {
          // Error was sent from _finish_fn
          return false;
        }
      }

      if (operation->reconnect())
      {
      }
      _operations.pop_back();
      delete operation;

      state= CONNECTED;
      break;
    } // end switch
  }

  return true;
} // end run()

bool Instance::more_to_read() const
{
  struct pollfd fds;
  fds.fd= _sockfd;
  fds.events = POLLIN;

  if (poll(&fds, 1, 5) < 1) // Default timeout is 5
  {
    return false;
  }

  return true;
}

void Instance::close_socket()
{
  if (_sockfd == INVALID_SOCKET)
  {
    return;
  }

  /* in case of death shutdown to avoid blocking at close() */
  if (shutdown(_sockfd, SHUT_RDWR) == SOCKET_ERROR && get_socket_errno() != ENOTCONN)
  {
    perror("shutdown");
  }
  else if (closesocket(_sockfd) == SOCKET_ERROR)
  {
    perror("close");
  }

  _sockfd= INVALID_SOCKET;
}

void Instance::free_addrinfo()
{
  if (_addrinfo == NULL)
  {
    return;
  }

  freeaddrinfo(_addrinfo);
  _addrinfo= NULL;
  _addrinfo_next= NULL;
}

} /* namespace util */
} /* namespace datadifferential */
<commit_msg>Fix for gearadmin multi-op<commit_after>/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  DataDifferential Utility Library
 *
 *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *      * Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *      * Redistributions in binary form must reproduce the above
 *  copyright notice, this list of conditions and the following disclaimer
 *  in the documentation and/or other materials provided with the
 *  distribution.
 *
 *      * The names of its contributors may not be used to endorse or
 *  promote products derived from this software without specific prior
 *  written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "gear_config.h"

#include "util/instance.hpp"

#include <cstdio>
#include <iostream>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <sstream>
#include <sys/socket.h>
#include <sys/types.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

namespace datadifferential {
namespace util {

Instance::Instance(const std::string& hostname_arg, const std::string& service_arg) :
  _host(hostname_arg),
  _service(service_arg),
  _sockfd(INVALID_SOCKET),
  _use_ssl(false),
  state(NOT_WRITING),
  _addrinfo(0),
  _addrinfo_next(0),
  _finish_fn(NULL),
  _operations(),
  _ctx_ssl(NULL),
  _ssl(NULL)
  {
  }

Instance::Instance(const std::string& hostname_arg, const in_port_t port_arg) :
  _host(hostname_arg),
  _sockfd(INVALID_SOCKET),
  _use_ssl(false),
  state(NOT_WRITING),
  _addrinfo(0),
  _addrinfo_next(0),
  _finish_fn(NULL),
  _operations(),
  _ctx_ssl(NULL),
  _ssl(NULL)
  {
    char tmp[BUFSIZ];
    snprintf(tmp, sizeof(tmp), "%u", static_cast<unsigned int>(port_arg));
    _service= tmp;
  }

Instance::~Instance()
{
  close_socket();
  free_addrinfo();
  for (Operation::vector::iterator iter= _operations.begin(); iter != _operations.end(); ++iter)
  {
    delete *iter;
  }
  _operations.clear();

  delete _finish_fn;

#if defined(HAVE_CYASSL) && HAVE_CYASSL
  if (_ssl)
  {
    CyaSSL_shutdown(_ssl);
    CyaSSL_free(_ssl);
  }
  if (_ctx_ssl)
  {
    CyaSSL_CTX_free(_ctx_ssl);
  }
  CyaSSL_Cleanup();
#endif
}

bool Instance::init_ssl()
{
#if defined(HAVE_CYASSL) && HAVE_CYASSL
  CyaSSL_Init();

  if ((_ctx_ssl= CyaSSL_CTX_new(CyaTLSv1_client_method())) == NULL)
  {
    _last_error= "CyaSSL_CTX_new error";
    return false;
  }

  if (CyaSSL_CTX_load_verify_locations(_ctx_ssl, ssl_ca_file(), 0) != SSL_SUCCESS)
  {
    std::stringstream message;
    message << "Error loading CA file " << ssl_ca_file();
    _last_error= message.str();
    return false;
  }

  if (CyaSSL_CTX_use_certificate_file(_ctx_ssl, ssl_certificate(), SSL_FILETYPE_PEM) != SSL_SUCCESS)
  {
    std::stringstream message;
    message << "Error loading certificate file " << ssl_certificate();
    _last_error= message.str();
    return false;
  }

  if (CyaSSL_CTX_use_PrivateKey_file(_ctx_ssl, ssl_key(), SSL_FILETYPE_PEM) != SSL_SUCCESS)
  {
    std::stringstream message;
    message << "Error loading private key file " << ssl_key();
    _last_error= message.str();
    return false;
  }
#endif // defined(HAVE_CYASSL) && HAVE_CYASSL
  return true;
}

bool Instance::run()
{
  if (_use_ssl)
  {
    if (not init_ssl())
    {
      return false;
    }
  }

  while (not _operations.empty())
  {
    Operation::vector::value_type operation= _operations.back();

    switch (state)
    {
    case NOT_WRITING:
      {
        free_addrinfo();

        struct addrinfo ai;
        memset(&ai, 0, sizeof(struct addrinfo));
        ai.ai_socktype= SOCK_STREAM;
        ai.ai_protocol= IPPROTO_TCP;

        int ret= getaddrinfo(_host.c_str(), _service.c_str(), &ai, &_addrinfo);
        if (ret)
        {
          std::stringstream message;
          message << "Failed to connect on " << _host.c_str() << ":" << _service.c_str() << " with "  << gai_strerror(ret);
          _last_error= message.str();
          return false;
        }
      }
      _addrinfo_next= _addrinfo;
      state= CONNECT;
      break;

    case NEXT_CONNECT_ADDRINFO:
      if (_addrinfo_next->ai_next == NULL)
      {
        std::stringstream message;
        message << "Error connecting to " << _host.c_str() << "." << std::endl;
        _last_error= message.str();
        return false;
      }
      _addrinfo_next= _addrinfo_next->ai_next;

    case CONNECT:
      close_socket();

      _sockfd= socket(_addrinfo_next->ai_family,
                      _addrinfo_next->ai_socktype,
                      _addrinfo_next->ai_protocol);
      if (_sockfd == INVALID_SOCKET)
      {
        perror("socket");
        continue;
      }

      if (connect(_sockfd, _addrinfo_next->ai_addr, _addrinfo_next->ai_addrlen) < 0)
      {
        switch(errno)
        {
        case EAGAIN:
        case EINTR:
          state= CONNECT;
          break;

        case EINPROGRESS:
          state= CONNECTING;
          break;

        case ECONNREFUSED:
        case ENETUNREACH:
        case ETIMEDOUT:
        default:
          state= NEXT_CONNECT_ADDRINFO;
          break;
        }
      }
      else
      {
        state= CONNECTING;
      }
      break;

    case CONNECTING:
      // Add logic for poll() for nonblocking.
      state= CONNECTED;
      break;

    case CONNECTED:
    case WRITING:
      {
        size_t packet_length= operation->size();
        const char *packet= operation->ptr();

#if defined(HAVE_CYASSL) && HAVE_CYASSL
        if (_ctx_ssl and not _ssl)
        {
          _ssl= CyaSSL_new(_ctx_ssl);
          if (_ssl == NULL)
          {
            _last_error= "CyaSSL_new() failed";
            return false;
          }

          int ssl_error;
          if ((ssl_error= CyaSSL_set_fd(_ssl, _sockfd)) != SSL_SUCCESS)
          {
            _last_error= "CyaSSL_set_fd() failed";
            return false;
          }
        }
#endif

        while(packet_length)
        {
          ssize_t write_size;
#if defined(HAVE_CYASSL) && HAVE_CYASSL
          if (_ssl)
          {
            write_size= CyaSSL_write(_ssl, (const void*)packet, int(packet_length));
            if (write_size < 0)
            {
              char errorString[80];
              CyaSSL_ERR_error_string(CyaSSL_get_error(_ssl, 0), errorString);
              _last_error= errorString;
              return false;
            }
          }
          else
#endif
          {
            write_size= send(_sockfd, packet, packet_length, 0);

            if (write_size < 0)
            {
              std::stringstream msg;
              msg << "Failed during send(" << strerror(errno) << ")";
              _last_error= msg.str();
              return false;
            }
          }

          packet_length-= static_cast<size_t>(write_size);
          packet+= static_cast<size_t>(write_size);
        }
      }
      state= READING;
      break;

    case READING:
      if (operation->has_response())
      {
        ssize_t read_length;

        do
        {
          char buffer[BUFSIZ];
#if defined(HAVE_CYASSL) && HAVE_CYASSL
          if (_ssl)
          {
            read_length= CyaSSL_read(_ssl, (void *)buffer, sizeof(buffer));
            if (read_length < 0)
            {
              char errorString[80];
              CyaSSL_ERR_error_string(CyaSSL_get_error(_ssl, 0), errorString);
              _last_error= errorString;
              return false;
            }
          }
          else
#endif
          {
            read_length= ::recv(_sockfd, buffer, sizeof(buffer), 0);
          }

          if (read_length < 0)
          {
            _last_error.clear();
            _last_error+= "Error occured while reading data from ";
            _last_error+= _host;
            return false;
          }
          else if (read_length == 0)
          {
            _last_error.clear();
            _last_error+= "Socket was shutdown while reading from ";
            _last_error+= _host;
            return false;
          }

          operation->push(buffer, static_cast<size_t>(read_length));

        } while (more_to_read());
      } // end has_response

      state= FINISHED;
      break;

    case FINISHED:
      std::string response;
      bool success= operation->response(response);
      if (_finish_fn)
      {
        if (not _finish_fn->call(success, response))
        {
          // Error was sent from _finish_fn
          return false;
        }
      }

      if (operation->reconnect())
      {
      }
      _operations.pop_back();
      delete operation;

      state= CONNECTED;
      break;
    } // end switch
  }

  return true;
} // end run()

bool Instance::more_to_read() const
{
  struct pollfd fds;
  fds.fd= _sockfd;
  fds.events = POLLIN;

  if (poll(&fds, 1, 5) < 1) // Default timeout is 5
  {
    return false;
  }

  return true;
}

void Instance::close_socket()
{
  if (_sockfd == INVALID_SOCKET)
  {
    return;
  }

  /* in case of death shutdown to avoid blocking at close() */
  if (shutdown(_sockfd, SHUT_RDWR) == SOCKET_ERROR && get_socket_errno() != ENOTCONN)
  {
    perror("shutdown");
  }
  else if (closesocket(_sockfd) == SOCKET_ERROR)
  {
    perror("close");
  }

  _sockfd= INVALID_SOCKET;
}

void Instance::free_addrinfo()
{
  if (_addrinfo == NULL)
  {
    return;
  }

  freeaddrinfo(_addrinfo);
  _addrinfo= NULL;
  _addrinfo_next= NULL;
}

} /* namespace util */
} /* namespace datadifferential */
<|endoftext|>


<commit_before>// Copyright (c) 2017-2019 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "cbtx.h"
#include "core_io.h"
#include "deterministicmns.h"
#include "simplifiedmns.h"
#include "specialtx.h"

#include "base58.h"
#include "chainparams.h"
#include "consensus/merkle.h"
#include "univalue.h"
#include "validation.h"

CSimplifiedMNListEntry::CSimplifiedMNListEntry(const CDeterministicMN& dmn) :
    proRegTxHash(dmn.proTxHash),
    confirmedHash(dmn.pdmnState->confirmedHash),
    service(dmn.pdmnState->addr),
    pubKeyOperator(dmn.pdmnState->pubKeyOperator),
    keyIDVoting(dmn.pdmnState->keyIDVoting),
    isValid(dmn.pdmnState->nPoSeBanHeight == -1)
{
}

uint256 CSimplifiedMNListEntry::CalcHash() const
{
    CHashWriter hw(SER_GETHASH, CLIENT_VERSION);
    hw << *this;
    return hw.GetHash();
}

std::string CSimplifiedMNListEntry::ToString() const
{
    return strprintf("CSimplifiedMNListEntry(proRegTxHash=%s, confirmedHash=%s, service=%s, pubKeyOperator=%s, votingAddress=%s, isValie=%d)",
        proRegTxHash.ToString(), confirmedHash.ToString(), service.ToString(false), pubKeyOperator.ToString(), CBitcoinAddress(keyIDVoting).ToString(), isValid);
}

void CSimplifiedMNListEntry::ToJson(UniValue& obj) const
{
    obj.clear();
    obj.setObject();
    obj.push_back(Pair("proRegTxHash", proRegTxHash.ToString()));
    obj.push_back(Pair("confirmedHash", confirmedHash.ToString()));
    obj.push_back(Pair("service", service.ToString(false)));
    obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString()));
    obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString()));
    obj.push_back(Pair("isValid", isValid));
}

CSimplifiedMNList::CSimplifiedMNList(const std::vector<CSimplifiedMNListEntry>& smlEntries)
{
    mnList = smlEntries;

    std::sort(mnList.begin(), mnList.end(), [&](const CSimplifiedMNListEntry& a, const CSimplifiedMNListEntry& b) {
        return a.proRegTxHash.Compare(b.proRegTxHash) < 0;
    });
}

CSimplifiedMNList::CSimplifiedMNList(const CDeterministicMNList& dmnList)
{
    mnList.reserve(dmnList.GetAllMNsCount());

    dmnList.ForEachMN(false, [this](const CDeterministicMNCPtr& dmn) {
        mnList.emplace_back(*dmn);
    });

    std::sort(mnList.begin(), mnList.end(), [&](const CSimplifiedMNListEntry& a, const CSimplifiedMNListEntry& b) {
        return a.proRegTxHash.Compare(b.proRegTxHash) < 0;
    });
}

uint256 CSimplifiedMNList::CalcMerkleRoot(bool* pmutated) const
{
    std::vector<uint256> leaves;
    leaves.reserve(mnList.size());
    for (const auto& e : mnList) {
        leaves.emplace_back(e.CalcHash());
    }
    return ComputeMerkleRoot(leaves, pmutated);
}

void CSimplifiedMNListDiff::ToJson(UniValue& obj) const
{
    obj.setObject();

    obj.push_back(Pair("baseBlockHash", baseBlockHash.ToString()));
    obj.push_back(Pair("blockHash", blockHash.ToString()));

    CDataStream ssCbTxMerkleTree(SER_NETWORK, PROTOCOL_VERSION);
    ssCbTxMerkleTree << cbTxMerkleTree;
    obj.push_back(Pair("cbTxMerkleTree", HexStr(ssCbTxMerkleTree.begin(), ssCbTxMerkleTree.end())));

    obj.push_back(Pair("cbTx", EncodeHexTx(*cbTx)));

    UniValue deletedMNsArr(UniValue::VARR);
    for (const auto& h : deletedMNs) {
        deletedMNsArr.push_back(h.ToString());
    }
    obj.push_back(Pair("deletedMNs", deletedMNsArr));

    UniValue mnListArr(UniValue::VARR);
    for (const auto& e : mnList) {
        UniValue eObj;
        e.ToJson(eObj);
        mnListArr.push_back(eObj);
    }
    obj.push_back(Pair("mnList", mnListArr));

    CCbTx cbTxPayload;
    if (GetTxPayload(*cbTx, cbTxPayload)) {
        obj.push_back(Pair("merkleRootMNList", cbTxPayload.merkleRootMNList.ToString()));
    }
}

bool BuildSimplifiedMNListDiff(const uint256& baseBlockHash, const uint256& blockHash, CSimplifiedMNListDiff& mnListDiffRet, std::string& errorRet)
{
    AssertLockHeld(cs_main);
    mnListDiffRet = CSimplifiedMNListDiff();

    BlockMap::iterator baseBlockIt = mapBlockIndex.begin();
    if (!baseBlockHash.IsNull()) {
        baseBlockIt = mapBlockIndex.find(baseBlockHash);
    }
    auto blockIt = mapBlockIndex.find(blockHash);
    if (baseBlockIt == mapBlockIndex.end()) {
        errorRet = strprintf("block %s not found", baseBlockHash.ToString());
        return false;
    }
    if (blockIt == mapBlockIndex.end()) {
        errorRet = strprintf("block %s not found", blockHash.ToString());
        return false;
    }

    if (!chainActive.Contains(baseBlockIt->second) || !chainActive.Contains(blockIt->second)) {
        errorRet = strprintf("block %s and %s are not in the same chain", baseBlockHash.ToString(), blockHash.ToString());
        return false;
    }
    if (baseBlockIt->second->nHeight > blockIt->second->nHeight) {
        errorRet = strprintf("base block %s is higher then block %s", baseBlockHash.ToString(), blockHash.ToString());
        return false;
    }

    LOCK(deterministicMNManager->cs);

    auto baseDmnList = deterministicMNManager->GetListForBlock(baseBlockHash);
    auto dmnList = deterministicMNManager->GetListForBlock(blockHash);
    mnListDiffRet = baseDmnList.BuildSimplifiedDiff(dmnList);

    // TODO store coinbase TX in CBlockIndex
    CBlock block;
    if (!ReadBlockFromDisk(block, blockIt->second, Params().GetConsensus())) {
        errorRet = strprintf("failed to read block %s from disk", blockHash.ToString());
        return false;
    }

    mnListDiffRet.cbTx = block.vtx[0];

    std::vector<uint256> vHashes;
    std::vector<bool> vMatch(block.vtx.size(), false);
    for (const auto& tx : block.vtx) {
        vHashes.emplace_back(tx->GetHash());
    }
    vMatch[0] = true; // only coinbase matches
    mnListDiffRet.cbTxMerkleTree = CPartialMerkleTree(vHashes, vMatch);

    return true;
}
<commit_msg>Fix incorrect usage of begin() when genesis block is requested in "protx diff" (#2699)<commit_after>// Copyright (c) 2017-2019 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "cbtx.h"
#include "core_io.h"
#include "deterministicmns.h"
#include "simplifiedmns.h"
#include "specialtx.h"

#include "base58.h"
#include "chainparams.h"
#include "consensus/merkle.h"
#include "univalue.h"
#include "validation.h"

CSimplifiedMNListEntry::CSimplifiedMNListEntry(const CDeterministicMN& dmn) :
    proRegTxHash(dmn.proTxHash),
    confirmedHash(dmn.pdmnState->confirmedHash),
    service(dmn.pdmnState->addr),
    pubKeyOperator(dmn.pdmnState->pubKeyOperator),
    keyIDVoting(dmn.pdmnState->keyIDVoting),
    isValid(dmn.pdmnState->nPoSeBanHeight == -1)
{
}

uint256 CSimplifiedMNListEntry::CalcHash() const
{
    CHashWriter hw(SER_GETHASH, CLIENT_VERSION);
    hw << *this;
    return hw.GetHash();
}

std::string CSimplifiedMNListEntry::ToString() const
{
    return strprintf("CSimplifiedMNListEntry(proRegTxHash=%s, confirmedHash=%s, service=%s, pubKeyOperator=%s, votingAddress=%s, isValie=%d)",
        proRegTxHash.ToString(), confirmedHash.ToString(), service.ToString(false), pubKeyOperator.ToString(), CBitcoinAddress(keyIDVoting).ToString(), isValid);
}

void CSimplifiedMNListEntry::ToJson(UniValue& obj) const
{
    obj.clear();
    obj.setObject();
    obj.push_back(Pair("proRegTxHash", proRegTxHash.ToString()));
    obj.push_back(Pair("confirmedHash", confirmedHash.ToString()));
    obj.push_back(Pair("service", service.ToString(false)));
    obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString()));
    obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString()));
    obj.push_back(Pair("isValid", isValid));
}

CSimplifiedMNList::CSimplifiedMNList(const std::vector<CSimplifiedMNListEntry>& smlEntries)
{
    mnList = smlEntries;

    std::sort(mnList.begin(), mnList.end(), [&](const CSimplifiedMNListEntry& a, const CSimplifiedMNListEntry& b) {
        return a.proRegTxHash.Compare(b.proRegTxHash) < 0;
    });
}

CSimplifiedMNList::CSimplifiedMNList(const CDeterministicMNList& dmnList)
{
    mnList.reserve(dmnList.GetAllMNsCount());

    dmnList.ForEachMN(false, [this](const CDeterministicMNCPtr& dmn) {
        mnList.emplace_back(*dmn);
    });

    std::sort(mnList.begin(), mnList.end(), [&](const CSimplifiedMNListEntry& a, const CSimplifiedMNListEntry& b) {
        return a.proRegTxHash.Compare(b.proRegTxHash) < 0;
    });
}

uint256 CSimplifiedMNList::CalcMerkleRoot(bool* pmutated) const
{
    std::vector<uint256> leaves;
    leaves.reserve(mnList.size());
    for (const auto& e : mnList) {
        leaves.emplace_back(e.CalcHash());
    }
    return ComputeMerkleRoot(leaves, pmutated);
}

void CSimplifiedMNListDiff::ToJson(UniValue& obj) const
{
    obj.setObject();

    obj.push_back(Pair("baseBlockHash", baseBlockHash.ToString()));
    obj.push_back(Pair("blockHash", blockHash.ToString()));

    CDataStream ssCbTxMerkleTree(SER_NETWORK, PROTOCOL_VERSION);
    ssCbTxMerkleTree << cbTxMerkleTree;
    obj.push_back(Pair("cbTxMerkleTree", HexStr(ssCbTxMerkleTree.begin(), ssCbTxMerkleTree.end())));

    obj.push_back(Pair("cbTx", EncodeHexTx(*cbTx)));

    UniValue deletedMNsArr(UniValue::VARR);
    for (const auto& h : deletedMNs) {
        deletedMNsArr.push_back(h.ToString());
    }
    obj.push_back(Pair("deletedMNs", deletedMNsArr));

    UniValue mnListArr(UniValue::VARR);
    for (const auto& e : mnList) {
        UniValue eObj;
        e.ToJson(eObj);
        mnListArr.push_back(eObj);
    }
    obj.push_back(Pair("mnList", mnListArr));

    CCbTx cbTxPayload;
    if (GetTxPayload(*cbTx, cbTxPayload)) {
        obj.push_back(Pair("merkleRootMNList", cbTxPayload.merkleRootMNList.ToString()));
    }
}

bool BuildSimplifiedMNListDiff(const uint256& baseBlockHash, const uint256& blockHash, CSimplifiedMNListDiff& mnListDiffRet, std::string& errorRet)
{
    AssertLockHeld(cs_main);
    mnListDiffRet = CSimplifiedMNListDiff();

    const CBlockIndex* baseBlockIndex = chainActive.Genesis();
    if (!baseBlockHash.IsNull()) {
        auto it = mapBlockIndex.find(baseBlockHash);
        if (it == mapBlockIndex.end()) {
            errorRet = strprintf("block %s not found", baseBlockHash.ToString());
            return false;
        }
        baseBlockIndex = it->second;
    }
    auto blockIt = mapBlockIndex.find(blockHash);
    if (blockIt == mapBlockIndex.end()) {
        errorRet = strprintf("block %s not found", blockHash.ToString());
        return false;
    }
    const CBlockIndex* blockIndex = blockIt->second;

    if (!chainActive.Contains(baseBlockIndex) || !chainActive.Contains(blockIndex)) {
        errorRet = strprintf("block %s and %s are not in the same chain", baseBlockHash.ToString(), blockHash.ToString());
        return false;
    }
    if (baseBlockIndex->nHeight > blockIndex->nHeight) {
        errorRet = strprintf("base block %s is higher then block %s", baseBlockHash.ToString(), blockHash.ToString());
        return false;
    }

    LOCK(deterministicMNManager->cs);

    auto baseDmnList = deterministicMNManager->GetListForBlock(baseBlockHash);
    auto dmnList = deterministicMNManager->GetListForBlock(blockHash);
    mnListDiffRet = baseDmnList.BuildSimplifiedDiff(dmnList);

    // TODO store coinbase TX in CBlockIndex
    CBlock block;
    if (!ReadBlockFromDisk(block, blockIndex, Params().GetConsensus())) {
        errorRet = strprintf("failed to read block %s from disk", blockHash.ToString());
        return false;
    }

    mnListDiffRet.cbTx = block.vtx[0];

    std::vector<uint256> vHashes;
    std::vector<bool> vMatch(block.vtx.size(), false);
    for (const auto& tx : block.vtx) {
        vHashes.emplace_back(tx->GetHash());
    }
    vMatch[0] = true; // only coinbase matches
    mnListDiffRet.cbTxMerkleTree = CPartialMerkleTree(vHashes, vMatch);

    return true;
}
<|endoftext|>


<commit_before>#include <glm/gtc/matrix_transform.hpp>
#include <GLFW/glfw3.h>
#include "camera.h"

static const float speed = 4.0f; // units per second
static const float mouseSpeedRad = 0.0005f;

Camera::Camera(GLFWwindow* window, const glm::vec3& startPosition, float startHorizontalAngleRad, float startVerticalAngleRad):
  window(window),
  position(startPosition),
  horizontalAngleRad(startHorizontalAngleRad),
  verticalAngleRad(startVerticalAngleRad) { }

void Camera::getViewMatrix(float deltaTimeMs, glm::mat4* pOutViewMatrix) {
  float deltaTimeSec = deltaTimeMs/1000.0f;

  int windowWidth, windowHeight;
  glfwGetWindowSize(window, &windowWidth, &windowHeight);

  double mouseX, mouseY;
  glfwGetCursorPos(window, &mouseX, &mouseY);

  horizontalAngleRad += mouseSpeedRad * static_cast<float>(windowWidth/2 - mouseX);
  verticalAngleRad += mouseSpeedRad * static_cast<float>(windowHeight/2 - mouseY);

  glfwSetCursorPos(window, windowWidth/2, windowHeight/2);

  glm::vec3 direction(
    cos(verticalAngleRad) * sin(horizontalAngleRad),
    sin(verticalAngleRad),
    cos(verticalAngleRad) * cos(horizontalAngleRad)
  );

  glm::vec3 right = glm::vec3(
    sin(horizontalAngleRad - 3.14f/2.0f),
    0,
    cos(horizontalAngleRad - 3.14f/2.0f)
  );

  glm::vec3 up = glm::cross(right, direction);

  if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
    position += direction * deltaTimeSec * speed;
  }

  if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
    position -= direction * deltaTimeSec * speed;
  }

  if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
    position -= right * deltaTimeSec * speed;
  }

  if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
    position += right * deltaTimeSec * speed;
  }

  *pOutViewMatrix = glm::lookAt(position, position + direction, up);
}<commit_msg>Minor changes<commit_after>#include <glm/gtc/matrix_transform.hpp>
#include <GLFW/glfw3.h>
#include "camera.h"

static const float speed = 4.0f; // units per second
static const float mouseSpeedRad = 0.0005f;

Camera::Camera(GLFWwindow* window, const glm::vec3& startPosition, float startHorizontalAngleRad, float startVerticalAngleRad):
  window(window),
  position(startPosition),
  horizontalAngleRad(startHorizontalAngleRad),
  verticalAngleRad(startVerticalAngleRad) { }

void Camera::getViewMatrix(float deltaTimeMs, glm::mat4* pOutViewMatrix) {
  float deltaTimeSec = deltaTimeMs/1000.0f;

  int windowWidth, windowHeight;
  glfwGetWindowSize(window, &windowWidth, &windowHeight);

  double mouseX, mouseY;
  glfwGetCursorPos(window, &mouseX, &mouseY);

  horizontalAngleRad += mouseSpeedRad * (windowWidth/2 - mouseX);
  verticalAngleRad += mouseSpeedRad * (windowHeight/2 - mouseY);

  glfwSetCursorPos(window, windowWidth/2, windowHeight/2);

  glm::vec3 direction(
    cos(verticalAngleRad) * sin(horizontalAngleRad),
    sin(verticalAngleRad),
    cos(verticalAngleRad) * cos(horizontalAngleRad)
  );

  glm::vec3 right = glm::vec3(
    sin(horizontalAngleRad - 3.14f/2.0f),
    0,
    cos(horizontalAngleRad - 3.14f/2.0f)
  );

  glm::vec3 up = glm::cross(right, direction);

  if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
    position += direction * deltaTimeSec * speed;
  }

  if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
    position -= direction * deltaTimeSec * speed;
  }

  if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
    position -= right * deltaTimeSec * speed;
  }

  if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
    position += right * deltaTimeSec * speed;
  }

  *pOutViewMatrix = glm::lookAt(position, position + direction, up);
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: inettbc.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: fs $ $Date: 2001-04-12 10:21:28 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SFX_INETTBC_HXX
#define _SFX_INETTBC_HXX

// includes *****************************************************************
#include <tools/string.hxx>
#include <tools/urlobj.hxx>

#ifndef _COMBOBOX_HXX //autogen
#include <vcl/combobox.hxx>
#endif

#define _SVSTDARR_STRINGSDTOR
#include <svtools/svstdarr.hxx>

struct SfxPickEntry_Impl;
class SfxURLBox : public ComboBox
{
friend class SfxMatchContext_Impl;
friend class SfxURLBox_Impl;
    Link                            aOpenHdl;
    String                          aBaseURL;
    INetProtocol                    eSmartProtocol;
    SfxMatchContext_Impl*           pCtx;
    SfxURLBox_Impl*                 pImp;
    BOOL                            bAutoCompleteMode;
    BOOL                            bOnlyDirectories;
    BOOL                            bModified;
    BOOL                            bTryAutoComplete: 1,
                                    bCtrlClick: 1,
                                    bHistoryDisabled : 1;

    BOOL                            ProcessKey( const KeyCode& rCode );
    void                            TryAutoComplete( BOOL bForward, BOOL bForce );
    void                            UpdatePicklistForSmartProtocol_Impl();
    DECL_LINK(                      AutoCompleteHdl_Impl, void* );

protected:
    virtual long                    Notify( NotifyEvent& rNEvt );
    virtual void                    Select();
    virtual void                    Modify();
    virtual BOOL                    QueryDrop( DropEvent &rEvt );
    virtual BOOL                    Drop( const DropEvent &rEvt );
    virtual long                    PreNotify( NotifyEvent& rNEvt );

public:
                                    SfxURLBox( Window* pParent, INetProtocol eSmart = INET_PROT_NOT_VALID );
                                    SfxURLBox( Window* pParent, const ResId& _rResId, INetProtocol eSmart = INET_PROT_NOT_VALID );
                                    ~SfxURLBox();

    void                            OpenURL( const String& rName, BOOL nMod ) const;
    void                            SetBaseURL( const String& rURL ) { aBaseURL = rURL; }
    const String&                   GetBaseURL() const { return aBaseURL; }
    void                            SetOpenHdl( const Link& rLink ) { aOpenHdl = rLink; }
    const Link&                     GetOpenHdl() const { return aOpenHdl; }
    void                            SetOnlyDirectories( BOOL bDir = TRUE );
    INetProtocol                    GetSmartProtocol() const { return eSmartProtocol; }
    void                            SetSmartProtocol( INetProtocol eProt );
    BOOL                            IsCtrlOpen()
                                    { return bCtrlClick; }
    String                          GetURL();
    void                            DisableHistory();
};

#if _SOLAR__PRIVATE

#include "tbxctrl.hxx"
class SfxURLToolBoxControl_Impl : public SfxToolBoxControl
{
private:
    SfxStatusForwarder      aURLForwarder;
    SfxURLBox*              GetURLBox() const;
    DECL_LINK(              OpenHdl, void* );
    DECL_LINK(              SelectHdl, void* );
public:

                            SFX_DECL_TOOLBOX_CONTROL();

                            SfxURLToolBoxControl_Impl( USHORT nId,
                                                    ToolBox& rBox,
                                                    SfxBindings& rBindings );

    virtual Window*         CreateItemWindow( Window* pParent );
    virtual void            StateChanged( USHORT nSID, SfxItemState eState,
                                  const SfxPoolItem* pState );
};

class SfxCancelToolBoxControl_Impl : public SfxToolBoxControl
{
public:

                            SFX_DECL_TOOLBOX_CONTROL();

                            SfxCancelToolBoxControl_Impl(
                                            USHORT nId,
                                            ToolBox& rBox,
                                            SfxBindings& rBindings );

    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
};

#endif

#endif

<commit_msg>TF_SVDATA<commit_after>/*************************************************************************
 *
 *  $RCSfile: inettbc.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: mba $ $Date: 2001-06-18 09:53:19 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SFX_INETTBC_HXX
#define _SFX_INETTBC_HXX

// includes *****************************************************************
#include <tools/string.hxx>
#include <tools/urlobj.hxx>

#ifndef _COMBOBOX_HXX //autogen
#include <vcl/combobox.hxx>
#endif

#define _SVSTDARR_STRINGSDTOR
#include <svtools/svstdarr.hxx>

struct SfxPickEntry_Impl;
class SfxURLBox : public ComboBox
{
friend class SfxMatchContext_Impl;
friend class SfxURLBox_Impl;
    Link                            aOpenHdl;
    String                          aBaseURL;
    INetProtocol                    eSmartProtocol;
    SfxMatchContext_Impl*           pCtx;
    SfxURLBox_Impl*                 pImp;
    BOOL                            bAutoCompleteMode;
    BOOL                            bOnlyDirectories;
    BOOL                            bModified;
    BOOL                            bTryAutoComplete: 1,
                                    bCtrlClick: 1,
                                    bHistoryDisabled : 1;

    BOOL                            ProcessKey( const KeyCode& rCode );
    void                            TryAutoComplete( BOOL bForward, BOOL bForce );
    void                            UpdatePicklistForSmartProtocol_Impl();
    DECL_LINK(                      AutoCompleteHdl_Impl, void* );

protected:
    virtual long                    Notify( NotifyEvent& rNEvt );
    virtual void                    Select();
    virtual void                    Modify();
#ifndef TF_SVDATA
    virtual BOOL                    QueryDrop( DropEvent &rEvt );
    virtual BOOL                    Drop( const DropEvent &rEvt );
#endif
    virtual long                    PreNotify( NotifyEvent& rNEvt );

public:
                                    SfxURLBox( Window* pParent, INetProtocol eSmart = INET_PROT_NOT_VALID );
                                    SfxURLBox( Window* pParent, const ResId& _rResId, INetProtocol eSmart = INET_PROT_NOT_VALID );
                                    ~SfxURLBox();

    void                            OpenURL( const String& rName, BOOL nMod ) const;
    void                            SetBaseURL( const String& rURL ) { aBaseURL = rURL; }
    const String&                   GetBaseURL() const { return aBaseURL; }
    void                            SetOpenHdl( const Link& rLink ) { aOpenHdl = rLink; }
    const Link&                     GetOpenHdl() const { return aOpenHdl; }
    void                            SetOnlyDirectories( BOOL bDir = TRUE );
    INetProtocol                    GetSmartProtocol() const { return eSmartProtocol; }
    void                            SetSmartProtocol( INetProtocol eProt );
    BOOL                            IsCtrlOpen()
                                    { return bCtrlClick; }
    String                          GetURL();
    void                            DisableHistory();
};

#if _SOLAR__PRIVATE

#include "tbxctrl.hxx"
class SfxURLToolBoxControl_Impl : public SfxToolBoxControl
{
private:
    SfxStatusForwarder      aURLForwarder;
    SfxURLBox*              GetURLBox() const;
    DECL_LINK(              OpenHdl, void* );
    DECL_LINK(              SelectHdl, void* );
public:

                            SFX_DECL_TOOLBOX_CONTROL();

                            SfxURLToolBoxControl_Impl( USHORT nId,
                                                    ToolBox& rBox,
                                                    SfxBindings& rBindings );

    virtual Window*         CreateItemWindow( Window* pParent );
    virtual void            StateChanged( USHORT nSID, SfxItemState eState,
                                  const SfxPoolItem* pState );
};

class SfxCancelToolBoxControl_Impl : public SfxToolBoxControl
{
public:

                            SFX_DECL_TOOLBOX_CONTROL();

                            SfxCancelToolBoxControl_Impl(
                                            USHORT nId,
                                            ToolBox& rBox,
                                            SfxBindings& rBindings );

    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
};

#endif

#endif

<|endoftext|>


<commit_before>/*
 Flexisip, a flexible SIP proxy server with media capabilities.
 Copyright (C) 2012  Belledonne Communications SARL.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as
 published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "forkmessagecontext.hh"
#include "registrardb.hh"
#include "common.hh"
#include <algorithm>
#include <sofia-sip/sip_status.h>
#include <sofia-sip/msg_types.h>
#include "xml/fthttp.hxx"

using namespace ::std;
using namespace fthttp;

static bool needsDelivery(int code){
	return code<200 || code==503 || code==408;
}

ForkMessageContext::ForkMessageContext(Agent *agent, const std::shared_ptr<RequestSipEvent> &event, shared_ptr<ForkContextConfig> cfg, ForkContextListener* listener) :
		ForkContext(agent, event,cfg,listener) {
	LOGD("New ForkMessageContext %p", this);
	mAcceptanceTimer=NULL;
	//start the acceptance timer immediately
	if (mCfg->mForkLate && mCfg->mDeliveryTimeout>30){
		mAcceptanceTimer=su_timer_create(su_root_task(mAgent->getRoot()), 0);
		su_timer_set_interval(mAcceptanceTimer, &ForkMessageContext::sOnAcceptanceTimer, this, (su_duration_t)mCfg->mUrgentTimeout*1000);
	}
	mDeliveredCount=0;
}

ForkMessageContext::~ForkMessageContext() {
	if (mAcceptanceTimer)
		su_timer_destroy(mAcceptanceTimer);
	LOGD("Destroy ForkMessageContext %p", this);
}

bool ForkMessageContext::shouldFinish() {
	return false; //the messaging fork context controls its termination.
}

void ForkMessageContext::checkFinished(){
	if (mIncoming==NULL && !mCfg->mForkLate){
		setFinished();
		return;
	}

	auto branches=getBranches();
	bool awaiting_responses=false;

	if (!mCfg->mForkLate){
		awaiting_responses=!allBranchesAnswered();
	}else{
		for(auto it=branches.begin();it!=branches.end();++it){
			if (needsDelivery((*it)->getStatus())) {
				awaiting_responses=true;
				break;
			}
		}
	}
	if (!awaiting_responses){
		shared_ptr<BranchInfo> br=findBestBranch(sUrgentCodes);
		if (br){
			forwardResponse(br);
		}
		setFinished();
	}
}

void ForkMessageContext::logDeliveryEvent(const std::shared_ptr<BranchInfo> &br, const shared_ptr<ResponseSipEvent> &event){
	sip_t *sip = event->getMsgSip()->getSip();
	auto log=make_shared<MessageLog>(MessageLog::Delivery,sip->sip_from,sip->sip_to,sip->sip_call_id);
	log->setDestination(br->mRequest->getMsgSip()->getSip()->sip_request->rq_url);
	log->setStatusCode(sip->sip_status->st_status,sip->sip_status->st_phrase);
	log->setCompleted();
	event->setEventLog(log);
	event->flushLog();
}

void ForkMessageContext::onResponse(const std::shared_ptr<BranchInfo> &br, const shared_ptr<ResponseSipEvent> &event) {
	sip_t *sip = event->getMsgSip()->getSip();
	int code=sip->sip_status->st_status;
	LOGD("ForkMessageContext::onResponse()");

	if (code > 100 && code < 300) {
		if (code>=200){
			mDeliveredCount++;
			if (mAcceptanceTimer) {
				if (mIncoming) logReceptionEvent(event); /*in the sender's log will appear the status code from the receiver*/
				su_timer_destroy(mAcceptanceTimer);
				mAcceptanceTimer=NULL;
			}
		}
		logDeliveryEvent(br,event);
		forwardResponse(br);
	}else logDeliveryEvent(br,event);
	checkFinished();
}

void ForkMessageContext::logReceptionEvent(const shared_ptr<ResponseSipEvent> &ev){
	sip_t *sip=ev->getMsgSip()->getSip();
	auto log=make_shared<MessageLog>(MessageLog::Reception,sip->sip_from,sip->sip_to,sip->sip_call_id);
	log->setStatusCode(sip->sip_status->st_status,sip->sip_status->st_phrase);
	log->setCompleted();
	ev->setEventLog(log);
	ev->flushLog();
}

/*we are called here if no good response has been received from any branch, in fork-late mode only */
void ForkMessageContext::acceptMessage(){
	if (mIncoming==NULL) return;

	/*in fork late mode, never answer a service unavailable*/
	shared_ptr<MsgSip> msgsip(mIncoming->createResponse(SIP_202_ACCEPTED));
	shared_ptr<ResponseSipEvent> ev(new ResponseSipEvent(dynamic_pointer_cast<OutgoingAgent>(mAgent->shared_from_this()), msgsip));
	forwardResponse(ev);
	logReceptionEvent(ev); /*in the sender's log will appear the 202 accepted from flexisip server*/
}

void ForkMessageContext::onAcceptanceTimer(){
	LOGD("ForkMessageContext::onAcceptanceTimer()");
	acceptMessage();
	su_timer_destroy(mAcceptanceTimer);
	mAcceptanceTimer=NULL;
}

void ForkMessageContext::sOnAcceptanceTimer(su_root_magic_t* magic, su_timer_t* t, su_timer_arg_t* arg){
	static_cast<ForkMessageContext*>(arg)->onAcceptanceTimer();
}

bool isMessageARCSFileTransferMessage(shared_ptr<RequestSipEvent> &ev) {
	sip_t* sip = ev->getSip();
	if (strncasecmp(sip->sip_request->rq_method_name, "MESSAGE", strlen(sip->sip_request->rq_method_name)) == 0) {
		if (sip->sip_content_type->c_type && strcasecmp (sip->sip_content_type->c_type, "application/vnd.gsma.rcs-ft-http+xml")==0) {
			return true;
		}
	}
	return false;
}

bool isConversionFromRcsToExternalBodyUrlNeeded(shared_ptr<ExtendedContact> &ec) {
	list<string> acceptHeaders = ec->mAcceptHeader;
	if (acceptHeaders.size() == 0) {
		return true;
	}

	for (auto it = acceptHeaders.begin(); it != acceptHeaders.end(); ++it) {
		string header = *it;
		if (header.compare("application/vnd.gsma.rcs-ft-http+xml") == 0) {
			return false;
		}
	}
	return true;
}

void ForkMessageContext::onNewBranch(const shared_ptr<BranchInfo> &br) {
	if (br->mUid.size()>0){
		/*check for a branch already existing with this uid, and eventually clean it*/
		shared_ptr<BranchInfo> tmp=findBranchByUid(br->mUid);
		if (tmp){
			removeBranch(tmp);
		}
	} else SLOGE << "No unique id found for contact";

	// Convert a RCS file transfer message to an external body url message if contact doesn't support it
	shared_ptr<RequestSipEvent> &ev = br->mRequest;
	if (ev && isMessageARCSFileTransferMessage(ev)) {
		shared_ptr<ExtendedContact> &ec = br->mContact;
		if (ec && isConversionFromRcsToExternalBodyUrlNeeded(ec)) {
			sip_t *sip = ev->getSip();
			sip_payload_t *payload = sip->sip_payload;

			std::unique_ptr<fthttp::File> file_transfer_infos = NULL;
			const char *file_url;

			try {
				istringstream data(payload->pl_data);
				file_transfer_infos = parseFile(data, xml_schema::Flags::dont_validate);
			} catch (const xml_schema::Exception& e) {
				SLOGE << "Can't parse the content of the message";
			}

			if (file_transfer_infos != NULL) {
				File::File_infoSequence &infos = file_transfer_infos->getFile_info();
				if (infos.size() >= 1) {
					for (File::File_infoConstIterator i (infos.begin()); i != infos.end(); ++i) {
						const File::File_infoType &info = (*i);
						const File_info::DataType &data = info.getData();
						const Data::UrlType &url = data.getUrl();
						file_url = url.c_str();
						break;
					}
				}
			}

			if (file_url) {
				//TODO
			}
		}
	}
}

bool ForkMessageContext::onNewRegister(const url_t *dest, const string &uid){
	bool already_have_transaction=!ForkContext::onNewRegister(dest,uid);
	if (already_have_transaction) return false;
	if (uid.size()>0){
		shared_ptr<BranchInfo> br=findBranchByUid(uid);
		if (br==NULL){
			//this is a new client instance or a client for which the message wasn't delivered yet. The message needs to be delivered.
			LOGD("ForkMessageContext::onNewRegister(): this is a new client instance.");
			return true;
		}else if (needsDelivery(br->getStatus())){
			//this is a new client instance or a client for which the message wasn't delivered yet. The message needs to be delivered.
			LOGD("ForkMessageContext::onNewRegister(): this client is reconnecting but was not delivered before.");
			return true;
		}
	}
	//in all other case we can accept a new transaction only if the message hasn't been delivered already.
	LOGD("Message has been delivered %i times.",mDeliveredCount);
	return mDeliveredCount==0;
}

<commit_msg>Fix crash when parser is destroyed<commit_after>/*
 Flexisip, a flexible SIP proxy server with media capabilities.
 Copyright (C) 2012  Belledonne Communications SARL.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as
 published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "forkmessagecontext.hh"
#include "registrardb.hh"
#include "common.hh"
#include <algorithm>
#include <sofia-sip/sip_status.h>
#include <sofia-sip/msg_types.h>
#include "xml/fthttp.hxx"
#include <xercesc/util/PlatformUtils.hpp>

using namespace ::std;
using namespace fthttp;

static bool needsDelivery(int code){
	return code<200 || code==503 || code==408;
}

ForkMessageContext::ForkMessageContext(Agent *agent, const std::shared_ptr<RequestSipEvent> &event, shared_ptr<ForkContextConfig> cfg, ForkContextListener* listener) :
		ForkContext(agent, event,cfg,listener) {
	LOGD("New ForkMessageContext %p", this);
	mAcceptanceTimer=NULL;
	//start the acceptance timer immediately
	if (mCfg->mForkLate && mCfg->mDeliveryTimeout>30){
		mAcceptanceTimer=su_timer_create(su_root_task(mAgent->getRoot()), 0);
		su_timer_set_interval(mAcceptanceTimer, &ForkMessageContext::sOnAcceptanceTimer, this, (su_duration_t)mCfg->mUrgentTimeout*1000);
	}
	mDeliveredCount=0;
}

ForkMessageContext::~ForkMessageContext() {
	if (mAcceptanceTimer)
		su_timer_destroy(mAcceptanceTimer);
	LOGD("Destroy ForkMessageContext %p", this);
}

bool ForkMessageContext::shouldFinish() {
	return false; //the messaging fork context controls its termination.
}

void ForkMessageContext::checkFinished(){
	if (mIncoming==NULL && !mCfg->mForkLate){
		setFinished();
		return;
	}

	auto branches=getBranches();
	bool awaiting_responses=false;

	if (!mCfg->mForkLate){
		awaiting_responses=!allBranchesAnswered();
	}else{
		for(auto it=branches.begin();it!=branches.end();++it){
			if (needsDelivery((*it)->getStatus())) {
				awaiting_responses=true;
				break;
			}
		}
	}
	if (!awaiting_responses){
		shared_ptr<BranchInfo> br=findBestBranch(sUrgentCodes);
		if (br){
			forwardResponse(br);
		}
		setFinished();
	}
}

void ForkMessageContext::logDeliveryEvent(const std::shared_ptr<BranchInfo> &br, const shared_ptr<ResponseSipEvent> &event){
	sip_t *sip = event->getMsgSip()->getSip();
	auto log=make_shared<MessageLog>(MessageLog::Delivery,sip->sip_from,sip->sip_to,sip->sip_call_id);
	log->setDestination(br->mRequest->getMsgSip()->getSip()->sip_request->rq_url);
	log->setStatusCode(sip->sip_status->st_status,sip->sip_status->st_phrase);
	log->setCompleted();
	event->setEventLog(log);
	event->flushLog();
}

void ForkMessageContext::onResponse(const std::shared_ptr<BranchInfo> &br, const shared_ptr<ResponseSipEvent> &event) {
	sip_t *sip = event->getMsgSip()->getSip();
	int code=sip->sip_status->st_status;
	LOGD("ForkMessageContext::onResponse()");

	if (code > 100 && code < 300) {
		if (code>=200){
			mDeliveredCount++;
			if (mAcceptanceTimer) {
				if (mIncoming) logReceptionEvent(event); /*in the sender's log will appear the status code from the receiver*/
				su_timer_destroy(mAcceptanceTimer);
				mAcceptanceTimer=NULL;
			}
		}
		logDeliveryEvent(br,event);
		forwardResponse(br);
	}else logDeliveryEvent(br,event);
	checkFinished();
}

void ForkMessageContext::logReceptionEvent(const shared_ptr<ResponseSipEvent> &ev){
	sip_t *sip=ev->getMsgSip()->getSip();
	auto log=make_shared<MessageLog>(MessageLog::Reception,sip->sip_from,sip->sip_to,sip->sip_call_id);
	log->setStatusCode(sip->sip_status->st_status,sip->sip_status->st_phrase);
	log->setCompleted();
	ev->setEventLog(log);
	ev->flushLog();
}

/*we are called here if no good response has been received from any branch, in fork-late mode only */
void ForkMessageContext::acceptMessage(){
	if (mIncoming==NULL) return;

	/*in fork late mode, never answer a service unavailable*/
	shared_ptr<MsgSip> msgsip(mIncoming->createResponse(SIP_202_ACCEPTED));
	shared_ptr<ResponseSipEvent> ev(new ResponseSipEvent(dynamic_pointer_cast<OutgoingAgent>(mAgent->shared_from_this()), msgsip));
	forwardResponse(ev);
	logReceptionEvent(ev); /*in the sender's log will appear the 202 accepted from flexisip server*/
}

void ForkMessageContext::onAcceptanceTimer(){
	LOGD("ForkMessageContext::onAcceptanceTimer()");
	acceptMessage();
	su_timer_destroy(mAcceptanceTimer);
	mAcceptanceTimer=NULL;
}

void ForkMessageContext::sOnAcceptanceTimer(su_root_magic_t* magic, su_timer_t* t, su_timer_arg_t* arg){
	static_cast<ForkMessageContext*>(arg)->onAcceptanceTimer();
}

bool isMessageARCSFileTransferMessage(shared_ptr<RequestSipEvent> &ev) {
	sip_t* sip = ev->getSip();
	if (strncasecmp(sip->sip_request->rq_method_name, "MESSAGE", strlen(sip->sip_request->rq_method_name)) == 0) {
		if (sip->sip_content_type->c_type && strcasecmp (sip->sip_content_type->c_type, "application/vnd.gsma.rcs-ft-http+xml")==0) {
			return true;
		}
	}
	return false;
}

bool isConversionFromRcsToExternalBodyUrlNeeded(shared_ptr<ExtendedContact> &ec) {
	list<string> acceptHeaders = ec->mAcceptHeader;
	if (acceptHeaders.size() == 0) {
		return true;
	}

	for (auto it = acceptHeaders.begin(); it != acceptHeaders.end(); ++it) {
		string header = *it;
		if (header.compare("application/vnd.gsma.rcs-ft-http+xml") == 0) {
			return false;
		}
	}
	return true;
}

void ForkMessageContext::onNewBranch(const shared_ptr<BranchInfo> &br) {
	if (br->mUid.size()>0){
		/*check for a branch already existing with this uid, and eventually clean it*/
		shared_ptr<BranchInfo> tmp=findBranchByUid(br->mUid);
		if (tmp){
			removeBranch(tmp);
		}
	} else SLOGE << "No unique id found for contact";

	// Convert a RCS file transfer message to an external body url message if contact doesn't support it
	shared_ptr<RequestSipEvent> &ev = br->mRequest;
	if (ev && isMessageARCSFileTransferMessage(ev)) {
		shared_ptr<ExtendedContact> &ec = br->mContact;
		xercesc::XMLPlatformUtils::Initialize();
		if (ec && isConversionFromRcsToExternalBodyUrlNeeded(ec)) {
			sip_t *sip = ev->getSip();
			sip_payload_t *payload = sip->sip_payload;

			std::unique_ptr<fthttp::File> file_transfer_infos = NULL;
			const char *file_url;

			try {
				istringstream data(payload->pl_data);
				file_transfer_infos = parseFile(data, xml_schema::Flags::dont_validate);
			} catch (const xml_schema::Exception& e) {
				SLOGE << "Can't parse the content of the message";
			}

			if (file_transfer_infos != NULL) {
				File::File_infoSequence &infos = file_transfer_infos->getFile_info();
				if (infos.size() >= 1) {
					for (File::File_infoConstIterator i (infos.begin()); i != infos.end(); ++i) {
						const File::File_infoType &info = (*i);
						const File_info::DataType &data = info.getData();
						const Data::UrlType &url = data.getUrl();
						file_url = url.c_str();
						break;
					}
				}
			}

			if (file_url) {
				//TODO
			}
		}
		xercesc::XMLPlatformUtils::Terminate();
	}
}

bool ForkMessageContext::onNewRegister(const url_t *dest, const string &uid){
	bool already_have_transaction=!ForkContext::onNewRegister(dest,uid);
	if (already_have_transaction) return false;
	if (uid.size()>0){
		shared_ptr<BranchInfo> br=findBranchByUid(uid);
		if (br==NULL){
			//this is a new client instance or a client for which the message wasn't delivered yet. The message needs to be delivered.
			LOGD("ForkMessageContext::onNewRegister(): this is a new client instance.");
			return true;
		}else if (needsDelivery(br->getStatus())){
			//this is a new client instance or a client for which the message wasn't delivered yet. The message needs to be delivered.
			LOGD("ForkMessageContext::onNewRegister(): this client is reconnecting but was not delivered before.");
			return true;
		}
	}
	//in all other case we can accept a new transaction only if the message hasn't been delivered already.
	LOGD("Message has been delivered %i times.",mDeliveredCount);
	return mDeliveredCount==0;
}

<|endoftext|>


<commit_before>#include "joystick.hpp"

Joystick::Joystick() {
	SDL_Init(SDL_INIT_JOYSTICK);
	int num_joysticks = SDL_NumJoysticks();

	// take first device that appears to be a joystick
	// and no strange vbox device for example...
	// ...which means more than 2 axes
	for (int i = 0; i < num_joysticks; i++) {
		SDL_Joystick *tmpStick = SDL_JoystickOpen(i);
		if (SDL_JoystickNumAxes(tmpStick) > 2) {
			m_joystick = tmpStick;
			m_name = SDL_JoystickName(i);

			break;
		}
	}

	SDL_JoystickEventState(SDL_ENABLE);
	SDL_JoystickEventState(SDL_QUERY);
}

Joystick::~Joystick() {

}

std::string Joystick::getName() {
	return m_name;
}

JoystickEvent Joystick::getEvent() {
	SDL_Event event;
	std::vector<bool>  buttons;
	std::vector<short> axis;

	SDL_JoystickUpdate();

	// get keys
	for (int i = 0; i < SDL_JoystickNumButtons(m_joystick); i++) {
		unsigned int n = SDL_JoystickGetButton(m_joystick, i);
		buttons.push_back((n == 1) ? true : false);
	}

	// get axis
	for (int i = 0; i < SDL_JoystickNumAxes(m_joystick); i++) {
		signed short a = SDL_JoystickGetAxis (m_joystick, i);
		axis.push_back(a);
	}

	return JoystickEvent(buttons, axis);
}
<commit_msg>Quit a little more gracefully if no joysticks were found<commit_after>#include "joystick.hpp"
#include <stdexcept>

Joystick::Joystick() {
	SDL_Init(SDL_INIT_JOYSTICK);
	int num_joysticks = SDL_NumJoysticks();
	if (num_joysticks < 1) {
		throw std::runtime_error("No joysticks found!");
	}

	// take first device that appears to be a joystick
	// and no strange vbox device for example...
	// ...which means more than 2 axes
	for (int i = 0; i < num_joysticks; i++) {
		SDL_Joystick *tmpStick = SDL_JoystickOpen(i);
		if (SDL_JoystickNumAxes(tmpStick) > 2) {
			m_joystick = tmpStick;
			m_name = SDL_JoystickName(i);

			break;
		}
	}

	SDL_JoystickEventState(SDL_ENABLE);
	SDL_JoystickEventState(SDL_QUERY);
}

Joystick::~Joystick() {

}

std::string Joystick::getName() {
	return m_name;
}

JoystickEvent Joystick::getEvent() {
	SDL_Event event;
	std::vector<bool>  buttons;
	std::vector<short> axis;

	SDL_JoystickUpdate();

	// get keys
	for (int i = 0; i < SDL_JoystickNumButtons(m_joystick); i++) {
		unsigned int n = SDL_JoystickGetButton(m_joystick, i);
		buttons.push_back((n == 1) ? true : false);
	}

	// get axis
	for (int i = 0; i < SDL_JoystickNumAxes(m_joystick); i++) {
		signed short a = SDL_JoystickGetAxis (m_joystick, i);
		axis.push_back(a);
	}

	return JoystickEvent(buttons, axis);
}
<|endoftext|>


<commit_before>#include "tileset.hpp"
#include "client/opengl.hpp"
#include "client/texturefile.hpp"
#include <stdlib.h>
using namespace LD22;

Tileset::Tileset()
{
    m_tile = TextureFile::open("sprite/tile.png");
    m_stick = TextureFile::open("sprite/stick.png");
    m_widget = TextureFile::open("sprite/widget.png");
}

Tileset::~Tileset()
{ }

void Tileset::drawTiles(const unsigned char t[TILE_HEIGHT][TILE_WIDTH],
                        int delta) const
{
    (void) delta;

    glPushMatrix();
    glScalef(32.0f, 32.0f, 1.0f);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    m_tile->bind();
    glBegin(GL_QUADS);
    for (int y = 0; y < TILE_HEIGHT; ++y) {
        for (int x = 0; x < TILE_WIDTH; ++x) {
            int i = t[y][x];
            if (!i)
                continue;
            int u = (i - 1) & 3, v = ((i - 1) >> 2) & 3;
            float u0 = u * 0.25f, u1 = u0 + 0.25f;
            float v1 = v * 0.25f, v0 = v1 - 0.25f;
            glTexCoord2f(u0, v0); glVertex2f(x, y);
            glTexCoord2f(u0, v1); glVertex2f(x, y + 1);
            glTexCoord2f(u1, v1); glVertex2f(x + 1, y + 1);
            glTexCoord2f(u1, v0); glVertex2f(x + 1, y);
        }
    }
    glEnd();
    glPopMatrix();
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
}

void Tileset::drawStick(int x, int y, int frame)
{
    int u = frame & 7, v = (frame / 8) & 3;
    bool flip = frame & 0x80;
    float x0 = x + STICK_WIDTH/2 - 32, x1 = x0 + 64;
    float y0 = y + STICK_WIDTH/2 - 32, y1 = y0 + 64;
    float u0 = u * 0.125f, u1 = u0 + 0.125f;
    float v1 = v * 0.25f, v0 = v1 + 0.25f;
    if (flip) {
        float t;
        t = u0;
        u0 = u1;
        u1 = t;
    }
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_DST_COLOR, GL_ZERO);
    m_stick->bind();
    glBegin(GL_QUADS);
    glTexCoord2f(u0, v0); glVertex2f(x0, y0);
    glTexCoord2f(u0, v1); glVertex2f(x0, y1);
    glTexCoord2f(u1, v1); glVertex2f(x1, y1);
    glTexCoord2f(u1, v0); glVertex2f(x1, y0);
    glEnd();
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
}

static const signed char WIDGET_INFO[Widget::MAX_WIDGET + 1][4] = {
    { 2, 2, -2, -2 },
    { 0, 2, 2, -2 },
    { 2, 2, 2, -2 },
    { 4, 2, -2, -2 },
    { 0, 3, 1, -1 },
    { 1, 3, 1, -1 },
    { 2, 3, 1, -1 },
    { 2, 4, 1, -1 },
    { 3, 4, 1, -2 }
};

void Tileset::drawWidget(int x, int y, int which)
{
    if (which < 0 || which > Widget::MAX_WIDGET)
        return;
    const signed char *ifo = WIDGET_INFO[which];
    float x0 = x, x1 = x0 + 64 * abs(ifo[2]);
    float y0 = y, y1 = y0 + 64 * abs(ifo[3]);
    float u0 = 0.25f * ifo[0], u1 = u0 + 0.25f * ifo[2];
    float v0 = 0.25f * ifo[1], v1 = v0 + 0.25f * ifo[3];
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    m_widget->bind();
    glBegin(GL_QUADS);
    glTexCoord2f(u0, v0); glVertex2f(x0, y0);
    glTexCoord2f(u0, v1); glVertex2f(x0, y1);
    glTexCoord2f(u1, v1); glVertex2f(x1, y1);
    glTexCoord2f(u1, v0); glVertex2f(x1, y0);
    glEnd();
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
}
<commit_msg>Fix stick drawing in Tileset code<commit_after>#include "tileset.hpp"
#include "client/opengl.hpp"
#include "client/texturefile.hpp"
#include <stdlib.h>
using namespace LD22;

Tileset::Tileset()
{
    m_tile = TextureFile::open("sprite/tile.png");
    m_stick = TextureFile::open("sprite/stick.png");
    m_widget = TextureFile::open("sprite/widget.png");
}

Tileset::~Tileset()
{ }

void Tileset::drawTiles(const unsigned char t[TILE_HEIGHT][TILE_WIDTH],
                        int delta) const
{
    (void) delta;

    glPushMatrix();
    glScalef(32.0f, 32.0f, 1.0f);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    m_tile->bind();
    glBegin(GL_QUADS);
    for (int y = 0; y < TILE_HEIGHT; ++y) {
        for (int x = 0; x < TILE_WIDTH; ++x) {
            int i = t[y][x];
            if (!i)
                continue;
            int u = (i - 1) & 3, v = ((i - 1) >> 2) & 3;
            float u0 = u * 0.25f, u1 = u0 + 0.25f;
            float v1 = v * 0.25f, v0 = v1 - 0.25f;
            glTexCoord2f(u0, v0); glVertex2f(x, y);
            glTexCoord2f(u0, v1); glVertex2f(x, y + 1);
            glTexCoord2f(u1, v1); glVertex2f(x + 1, y + 1);
            glTexCoord2f(u1, v0); glVertex2f(x + 1, y);
        }
    }
    glEnd();
    glPopMatrix();
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
}

void Tileset::drawStick(int x, int y, int frame)
{
    int u = frame & 7, v = (frame / 8) & 3;
    bool flip = frame & 0x80;
    float x0 = x + STICK_WIDTH/2 - 32, x1 = x0 + 64;
    float y0 = y + STICK_HEIGHT/2 - 32, y1 = y0 + 64;
    float u0 = u * 0.125f, u1 = u0 + 0.125f;
    float v1 = v * 0.25f, v0 = v1 + 0.25f;
    if (flip) {
        float t;
        t = u0;
        u0 = u1;
        u1 = t;
    }
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_DST_COLOR, GL_ZERO);
    m_stick->bind();
    glBegin(GL_QUADS);
    glTexCoord2f(u0, v0); glVertex2f(x0, y0);
    glTexCoord2f(u0, v1); glVertex2f(x0, y1);
    glTexCoord2f(u1, v1); glVertex2f(x1, y1);
    glTexCoord2f(u1, v0); glVertex2f(x1, y0);
    glEnd();
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
}

static const signed char WIDGET_INFO[Widget::MAX_WIDGET + 1][4] = {
    { 2, 2, -2, -2 },
    { 0, 2, 2, -2 },
    { 2, 2, 2, -2 },
    { 4, 2, -2, -2 },
    { 0, 3, 1, -1 },
    { 1, 3, 1, -1 },
    { 2, 3, 1, -1 },
    { 2, 4, 1, -1 },
    { 3, 4, 1, -2 }
};

void Tileset::drawWidget(int x, int y, int which)
{
    if (which < 0 || which > Widget::MAX_WIDGET)
        return;
    const signed char *ifo = WIDGET_INFO[which];
    float x0 = x, x1 = x0 + 64 * abs(ifo[2]);
    float y0 = y, y1 = y0 + 64 * abs(ifo[3]);
    float u0 = 0.25f * ifo[0], u1 = u0 + 0.25f * ifo[2];
    float v0 = 0.25f * ifo[1], v1 = v0 + 0.25f * ifo[3];
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    m_widget->bind();
    glBegin(GL_QUADS);
    glTexCoord2f(u0, v0); glVertex2f(x0, y0);
    glTexCoord2f(u0, v1); glVertex2f(x0, y1);
    glTexCoord2f(u1, v1); glVertex2f(x1, y1);
    glTexCoord2f(u1, v0); glVertex2f(x1, y0);
    glEnd();
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
}
<|endoftext|>


<commit_before>#include "../core/cpu.h"
#include "../core/mmu.h"
#include "../core/gpu.h"
#include "../video/sdl_renderer.h"

#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <chrono>
#include <thread>

#include <SDL2/SDL.h>

const int MILLIS_PER_FRAME = 1000 / 60;

int main(int argc, char* argv[]) {
    if (argc != 3) {
        std::cout << "Invalid arguments." << std::endl;
        exit(0);
    }

    std::string bios = argv[1];
    std::string rom = argv[2];

    SDLRenderer rend;
    SDL_Event event;

    GPU gpu(rend);
    MMU mmu(gpu, bios, rom);
    CPU cpu(mmu);

    time_t start_time = time(0);
    unsigned frames = 0;
    bool run = true;
    while (run) {
        int frame_cycles = 0;
        time_t frame_start_time = time(0);
        while (frame_cycles <= GPU::CYCLES_PER_FRAME) {
            int cycles = cpu.execute();
            gpu.step(cycles);
            frame_cycles += cycles;
        }

        ++frames;

        double frame_time = difftime(time(0), frame_start_time) * 1000;
        if (frame_time < MILLIS_PER_FRAME) {
            int time_to_sleep = static_cast<int>(MILLIS_PER_FRAME - frame_time);
            std::this_thread::sleep_for(std::chrono::milliseconds(time_to_sleep));
        }

        if (difftime(time(0), start_time) >= 1) {
            start_time = time(0);
            std::cout << std::dec << frames << std::endl;
            frames = 0;
        }

        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                run = false;
            }
        }
    }

    SDL_Quit();
}

<commit_msg>Improve FPS limiter<commit_after>#include "../core/cpu.h"
#include "../core/mmu.h"
#include "../core/gpu.h"
#include "../video/sdl_renderer.h"

#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <chrono>
#include <thread>

#include <SDL2/SDL.h>

const double MILLIS_PER_FRAME = 1000 / 60;

int main(int argc, char* argv[]) {
    using namespace std::chrono;

    if (argc != 3) {
        std::cout << "Invalid arguments." << std::endl;
        exit(0);
    }

    std::string bios = argv[1];
    std::string rom = argv[2];

    SDLRenderer rend;
    SDL_Event event;

    GPU gpu(rend);
    MMU mmu(gpu, bios, rom);
    CPU cpu(mmu);

    high_resolution_clock clock;
    auto start_time = clock.now();

    unsigned frames = 0;
    bool run = true;
    while (run) {
        int frame_cycles = 0;
        auto frame_start_time = clock.now();
        while (frame_cycles <= GPU::CYCLES_PER_FRAME) {
            int cycles = cpu.execute();
            gpu.step(cycles);
            frame_cycles += cycles;
        }

        ++frames;

        if (duration_cast<milliseconds>(clock.now() - start_time).count() >= 1000) {
            start_time = clock.now();
            std::cout << std::dec << frames << std::endl;
            frames = 0;
        }

        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                run = false;
            }
        }

        auto frame_time = duration_cast<milliseconds>(clock.now() - frame_start_time);

        if (frame_time.count() < MILLIS_PER_FRAME) {
            int time_to_sleep = MILLIS_PER_FRAME - frame_time.count();
            std::this_thread::sleep_for(milliseconds(time_to_sleep));
        }
    }

    SDL_Quit();
}

<|endoftext|>