<commit_before>/**
 * \file vigenere_square.cpp
 * \brief vigenere_square implementation file.
 */

#include <sstream>
#include <valarray>
#include <exception>
#include <stdexcept>

#include "vigenere_square.hpp"
#include "stringutils.hpp"

vigenere_square::vigenere_square() {}

vigenere_square::vigenere_square(const std::string& i_alphabet) :
    alphabet(i_alphabet),
    table(std::vector<std::string>{alphabet.size()})
{
    if(!stringutils::is_all_unique(i_alphabet))
    {
        throw std::invalid_argument("Alphabet cannot contain duplicates.");
    }

    auto row_iter = table.begin();
    for(unsigned int i = 0; i < alphabet.size(); i++)
    {
        *row_iter++ = stringutils::shift(alphabet, -i);
    }
}

vigenere_square& vigenere_square::operator=(const vigenere_square& rhs)
{
    if(this == &rhs) return *this;

    this->alphabet = rhs.alphabet;
    this->table = rhs.table;

    this->cipher = rhs.cipher;
    this->key = rhs.key;
    this->plaintext = rhs.plaintext;

    return *this;
}

std::string vigenere_square::to_string() const
{
    std::stringstream ss;
    for(const auto& row : table)
    {
        ss << row << std::endl;
    }
    return ss.str();
}

void vigenere_square::print(std::ostream& os) const
{
    os << this->to_string();
}

int vigenere_square::find_keycolindex(char keychar)
{
    bool found = false;
    unsigned int i;

    for(i = 0; i < alphabet.size(); i++)
    {
        if(alphabet[i] == keychar)
        {
            found = true;
            break;
        }
    }

    if(found)
    {
        return i;
    }
    else
    {
        return -1;
    }
}

int vigenere_square::find_plainrowindex(int keycolindex, char plainchar)
{
    if(keycolindex < 0 || keycolindex >= static_cast<int>(alphabet.size()))
    {
        std::stringstream ss;
        ss << "keycolindex out of range [0," << alphabet.size() <<
              "[ " << "where keycolindex is " << keycolindex << ".";

        throw std::invalid_argument(ss.str());
    }

    return alphabet.find(plainchar);
}

std::string vigenere_square::encrypt(const std::string& str_plain,
                                     const std::string& key)
{

    std::string cipher;
    char keychar;
    int kci = 0;
    int pci = 0;
    int k = 0;

    for(const auto& plainchar : str_plain)
    {
        keychar = key[k];
        k = (k + 1) % key.size();
        kci = find_keycolindex(keychar);
        pci = find_plainrowindex(kci, plainchar);
        cipher += table[pci][kci];
    }

    return cipher;

    /*
    char keychar = key[0];
    int keyrowindex = find_keyrowindex(keychar);

    char plainchar = str_plain[0];
    int plaincharindex = find_plaincharindex(keyrowindex, plainchar);

    char cipherchar = table[0][plaincharindex];
    */
}

std::string vigenere_square::decrypt(const std::string& str_cipher,
                                     const std::string& key)
{
    return std::string{str_cipher};
}

void vigenere_square::set_cipher(const std::string& n_cipher)
{
    cipher = n_cipher;
}

void vigenere_square::set_key(const std::string& n_key)
{
    key = n_key;
}

void vigenere_square::set_plaintext(const std::string& n_plaintext)
{
    plaintext = n_plaintext;
}

std::string vigenere_square::get_cipher() const
{
    return cipher;
}

std::string vigenere_square::get_plaintext() const
{
    return plaintext;
}

std::string vigenere_square::get_key() const
{
    return key;
}

std::string vigenere_square::get_alphabet() const
{
    return alphabet;
}

std::ostream& operator<<(std::ostream& os, const vigenere_square& vsq)
{
    os << vsq.to_string();
    return os;
}
<commit_msg>removed unused include<commit_after>/**
 * \file vigenere_square.cpp
 * \brief vigenere_square implementation file.
 */

#include <sstream>
#include <exception>
#include <stdexcept>

#include "vigenere_square.hpp"
#include "stringutils.hpp"

vigenere_square::vigenere_square() {}

vigenere_square::vigenere_square(const std::string& i_alphabet) :
    alphabet(i_alphabet),
    table(std::vector<std::string>{alphabet.size()})
{
    if(!stringutils::is_all_unique(i_alphabet))
    {
        throw std::invalid_argument("Alphabet cannot contain duplicates.");
    }

    auto row_iter = table.begin();
    for(unsigned int i = 0; i < alphabet.size(); i++)
    {
        *row_iter++ = stringutils::shift(alphabet, -i);
    }
}

vigenere_square& vigenere_square::operator=(const vigenere_square& rhs)
{
    if(this == &rhs) return *this;

    this->alphabet = rhs.alphabet;
    this->table = rhs.table;

    this->cipher = rhs.cipher;
    this->key = rhs.key;
    this->plaintext = rhs.plaintext;

    return *this;
}

std::string vigenere_square::to_string() const
{
    std::stringstream ss;
    for(const auto& row : table)
    {
        ss << row << std::endl;
    }
    return ss.str();
}

void vigenere_square::print(std::ostream& os) const
{
    os << this->to_string();
}

int vigenere_square::find_keycolindex(char keychar)
{
    bool found = false;
    unsigned int i;

    for(i = 0; i < alphabet.size(); i++)
    {
        if(alphabet[i] == keychar)
        {
            found = true;
            break;
        }
    }

    if(found)
    {
        return i;
    }
    else
    {
        return -1;
    }
}

int vigenere_square::find_plainrowindex(int keycolindex, char plainchar)
{
    if(keycolindex < 0 || keycolindex >= static_cast<int>(alphabet.size()))
    {
        std::stringstream ss;
        ss << "keycolindex out of range [0," << alphabet.size() <<
              "[ " << "where keycolindex is " << keycolindex << ".";

        throw std::invalid_argument(ss.str());
    }

    return alphabet.find(plainchar);
}

std::string vigenere_square::encrypt(const std::string& str_plain,
                                     const std::string& key)
{

    std::string cipher;
    char keychar;
    int kci = 0;
    int pci = 0;
    int k = 0;

    for(const auto& plainchar : str_plain)
    {
        keychar = key[k];
        k = (k + 1) % key.size();
        kci = find_keycolindex(keychar);
        pci = find_plainrowindex(kci, plainchar);
        cipher += table[pci][kci];
    }

    return cipher;

    /*
    char keychar = key[0];
    int keyrowindex = find_keyrowindex(keychar);

    char plainchar = str_plain[0];
    int plaincharindex = find_plaincharindex(keyrowindex, plainchar);

    char cipherchar = table[0][plaincharindex];
    */
}

std::string vigenere_square::decrypt(const std::string& str_cipher,
                                     const std::string& key)
{
    return std::string{str_cipher};
}

void vigenere_square::set_cipher(const std::string& n_cipher)
{
    cipher = n_cipher;
}

void vigenere_square::set_key(const std::string& n_key)
{
    key = n_key;
}

void vigenere_square::set_plaintext(const std::string& n_plaintext)
{
    plaintext = n_plaintext;
}

std::string vigenere_square::get_cipher() const
{
    return cipher;
}

std::string vigenere_square::get_plaintext() const
{
    return plaintext;
}

std::string vigenere_square::get_key() const
{
    return key;
}

std::string vigenere_square::get_alphabet() const
{
    return alphabet;
}

std::ostream& operator<<(std::ostream& os, const vigenere_square& vsq)
{
    os << vsq.to_string();
    return os;
}
<|endoftext|>


<commit_before>// vrkit is (C) Copyright 2005-2007
//    by Allen Bierbaum, Aron Bierbuam, Patrick Hartling, and Daniel Shipton
//
// This file is part of vrkit.
//
// vrkit is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// vrkit 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 program.  If not, see <http://www.gnu.org/licenses/>.

#if defined(WIN32) || defined(WIN64)
#include <windows.h>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <string>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/exception.hpp>

namespace fs = boost::filesystem;

/**
 * Windows DLL entry point function. This ensures that the environment
 * variable \c VRKIT_BASE_DIR is set as soon as this DLL is attached to the
 * process. If it is not set, then it sets it based on an assumption about the
 * structure of a vrkit installation. More specifically, an assumption is made
 * that this DLL lives in the \c lib subdirectory of the vrkit installation.
 * Therefore, the root of the vrkit installation is the parent of the
 * directory containing this DLL.
 */
BOOL __stdcall DllMain(HINSTANCE module, DWORD reason, LPVOID reserved)
{
   switch (reason)
   {
      case DLL_PROCESS_ATTACH:
         {
#if defined(_MSC_VER) && _MSC_VER >= 1400
            char* env_dir(NULL);
            size_t len;
            _dupenv_s(&env_dir, &len, "VRKIT_BASE_DIR");
#else
            const char* env_dir = std::getenv("VRKIT_BASE_DIR");
#endif

            if ( NULL == env_dir )
            {
               char tmppath[1024];
               std::memset(tmppath, 0, sizeof(tmppath));
               GetModuleFileName(module, tmppath, sizeof(tmppath));

               try
               {
                  fs::path dll_path(tmppath, fs::native);
                  fs::path base_dir = dll_path.branch_path().branch_path();
#if defined(VRKIT_DEBUG) && ! defined(_DEBUG)
                  // The debug DLL linked against the release runtime is in
                  // <base_dir>\lib\debug.
                  base_dir = base_dir.branch_path();
#endif
                  const std::string base_dir_str =
                     base_dir.native_directory_string();
#if defined(_MSC_VER) && _MSC_VER >= 1400
                  _putenv_s("VRKIT_BASE_DIR", base_dir_str.c_str());
#else
                  std::ostringstream env_stream;
                  env_stream << "VRKIT_BASE_DIR=" << base_dir_str;
                  putenv(env_stream.str().c_str());
#endif
               }
               catch (fs::filesystem_error& ex)
               {
                  std::cerr << "Automatic assignment of VRKIT_BASE_DIR "
                            << "failed:\n" << ex.what() << std::endl;
               }
            }
#if defined(_MSC_VER) && _MSC_VER >= 1400
            else
            {
               std::free(env_dir);
            }
#endif
         }
         break;
      default:
         break;
   }

   return TRUE;
}

#else /* Non-windows or..Unix case. */
#include <dlfcn.h>
#include <string>

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>

#include <vpr/System.h>

#include <vrkit/Status.h>
#include <vrkit/Version.h>

namespace fs = boost::filesystem;

extern "C" void __attribute ((constructor)) vrkit_library_init()
{
   Dl_info info;
   info.dli_fname = 0;
   const int result =
      dladdr(reinterpret_cast<const void*>(&vrkit_library_init), &info);

   // NOTE: dladdr(3) really does return a non-zero value on success.
   if ( 0 != result )
   {
      fs::path vrkit_lib_file(info.dli_fname, fs::native);
      vrkit_lib_file = fs::system_complete(vrkit_lib_file);

      fs::path vrkit_lib_path = vrkit_lib_file.branch_path();

      //construct VRKIT_BASE_DIR, VRKIT_DATA_DIR, VRKIT_PLUGINS_DIR
      std::string vrkit_versioned_dir_name = "vrkit";
#ifdef VRKIT_USE_VERSIONING
      vrkit_versioned_dir_name.append("-");
      vrkit_versioned_dir_name.append(vrkit::getVersion());
#endif
      // Go from base/lib/(debug/release) down to base
      fs::path vrkit_base_dir = vrkit_lib_path.branch_path().branch_path();

      // Go from /base to base/lib/versioned_vrkit_dir/plugins
      fs::path vrkit_plugins_dir = vrkit_base_dir / "lib" /
                                      vrkit_versioned_dir_name / "plugins";
      // Go from /base to /base/share/versioned_vrkit_dir
      fs::path vrkit_data_dir = vrkit_base_dir / "share" /
                                   vrkit_versioned_dir_name;

      std::string vrkit_base_dir_env_var;
      vpr::System::getenv("VRKIT_BASE_DIR", vrkit_base_dir_env_var);

      if ( vrkit_base_dir_env_var.empty() )
      {
         vpr::System::setenv("VRKIT_BASE_DIR", vrkit_base_dir.string());
         VRKIT_STATUS << "VRKIT_BASE_DIR set to: " << vrkit_base_dir.string() << std::endl;
      }
      else
      {
         // VRKIT_BASE_DIR set...check if path will match up
      }

      std::string vrkit_data_dir_env_var;
      vpr::System::getenv("VRKIT_DATA_DIR", vrkit_data_dir_env_var);

      if ( vrkit_data_dir_env_var.empty() )
      {
         vpr::System::setenv("VRKIT_DATA_DIR", vrkit_data_dir.string());
         VRKIT_STATUS << "VRKIT_DATA_DIR set to: " << vrkit_data_dir.string() << std::endl;
      }
      else
      {
         // VRKIT_DATA_DIR set...check if path will match up
      }

      std::string vrkit_plugin_dir_env_var;
      vpr::System::getenv("VRKIT_PLUGINS_DIR", vrkit_plugin_dir_env_var);

      if ( vrkit_plugin_dir_env_var.empty() )
      {
         vpr::System::setenv("VRKIT_PLUGINS_DIR", vrkit_plugins_dir.string());
         VRKIT_STATUS << "VRKIT_PLUGINS_DIR set to: " << vrkit_plugins_dir.string() << std::endl;
      }
      else
      {
         // VRKIT_PLUGINS_DIR set...check if path will match up
      }
   }
}
#endif
<commit_msg>Handle the debug case.<commit_after>// vrkit is (C) Copyright 2005-2007
//    by Allen Bierbaum, Aron Bierbuam, Patrick Hartling, and Daniel Shipton
//
// This file is part of vrkit.
//
// vrkit is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// vrkit 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 program.  If not, see <http://www.gnu.org/licenses/>.

#if defined(WIN32) || defined(WIN64)
#include <windows.h>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <string>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/exception.hpp>

namespace fs = boost::filesystem;

/**
 * Windows DLL entry point function. This ensures that the environment
 * variable \c VRKIT_BASE_DIR is set as soon as this DLL is attached to the
 * process. If it is not set, then it sets it based on an assumption about the
 * structure of a vrkit installation. More specifically, an assumption is made
 * that this DLL lives in the \c lib subdirectory of the vrkit installation.
 * Therefore, the root of the vrkit installation is the parent of the
 * directory containing this DLL.
 */
BOOL __stdcall DllMain(HINSTANCE module, DWORD reason, LPVOID reserved)
{
   switch (reason)
   {
      case DLL_PROCESS_ATTACH:
         {
#if defined(_MSC_VER) && _MSC_VER >= 1400
            char* env_dir(NULL);
            size_t len;
            _dupenv_s(&env_dir, &len, "VRKIT_BASE_DIR");
#else
            const char* env_dir = std::getenv("VRKIT_BASE_DIR");
#endif

            if ( NULL == env_dir )
            {
               char tmppath[1024];
               std::memset(tmppath, 0, sizeof(tmppath));
               GetModuleFileName(module, tmppath, sizeof(tmppath));

               try
               {
                  fs::path dll_path(tmppath, fs::native);
                  fs::path base_dir = dll_path.branch_path().branch_path();
#if defined(VRKIT_DEBUG) && ! defined(_DEBUG)
                  // The debug DLL linked against the release runtime is in
                  // <base_dir>\lib\debug.
                  base_dir = base_dir.branch_path();
#endif
                  const std::string base_dir_str =
                     base_dir.native_directory_string();
#if defined(_MSC_VER) && _MSC_VER >= 1400
                  _putenv_s("VRKIT_BASE_DIR", base_dir_str.c_str());
#else
                  std::ostringstream env_stream;
                  env_stream << "VRKIT_BASE_DIR=" << base_dir_str;
                  putenv(env_stream.str().c_str());
#endif
               }
               catch (fs::filesystem_error& ex)
               {
                  std::cerr << "Automatic assignment of VRKIT_BASE_DIR "
                            << "failed:\n" << ex.what() << std::endl;
               }
            }
#if defined(_MSC_VER) && _MSC_VER >= 1400
            else
            {
               std::free(env_dir);
            }
#endif
         }
         break;
      default:
         break;
   }

   return TRUE;
}

#else /* Non-windows or..Unix case. */
#include <dlfcn.h>
#include <string>

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>

#include <vpr/System.h>

#include <vrkit/Status.h>
#include <vrkit/Version.h>

namespace fs = boost::filesystem;

extern "C" void __attribute ((constructor)) vrkit_library_init()
{
   Dl_info info;
   info.dli_fname = 0;
   const int result =
      dladdr(reinterpret_cast<const void*>(&vrkit_library_init), &info);

   // NOTE: dladdr(3) really does return a non-zero value on success.
   if ( 0 != result )
   {
      fs::path vrkit_lib_file(info.dli_fname, fs::native);
      vrkit_lib_file = fs::system_complete(vrkit_lib_file);

      fs::path vrkit_lib_path = vrkit_lib_file.branch_path();
#if defined(VRKIT_DEBUG)
      // The debug library is in <base_dir>/lib/debug.
      vrkit_lib_path = vrkit_lib_path.branch_path();
#endif

      //construct VRKIT_BASE_DIR, VRKIT_DATA_DIR, VRKIT_PLUGINS_DIR
      std::string vrkit_versioned_dir_name = "vrkit";
#ifdef VRKIT_USE_VERSIONING
      vrkit_versioned_dir_name.append("-");
      vrkit_versioned_dir_name.append(vrkit::getVersion());
#endif
      // Go from base/lib/(debug/release) down to base
      fs::path vrkit_base_dir = vrkit_lib_path.branch_path().branch_path();

      // Go from /base to base/lib/versioned_vrkit_dir/plugins
      fs::path vrkit_plugins_dir = vrkit_base_dir / "lib" /
                                      vrkit_versioned_dir_name / "plugins";
      // Go from /base to /base/share/versioned_vrkit_dir
      fs::path vrkit_data_dir = vrkit_base_dir / "share" /
                                   vrkit_versioned_dir_name;

      std::string vrkit_base_dir_env_var;
      vpr::System::getenv("VRKIT_BASE_DIR", vrkit_base_dir_env_var);

      if ( vrkit_base_dir_env_var.empty() )
      {
         vpr::System::setenv("VRKIT_BASE_DIR", vrkit_base_dir.string());
         VRKIT_STATUS << "VRKIT_BASE_DIR set to: " << vrkit_base_dir.string() << std::endl;
      }
      else
      {
         // VRKIT_BASE_DIR set...check if path will match up
      }

      std::string vrkit_data_dir_env_var;
      vpr::System::getenv("VRKIT_DATA_DIR", vrkit_data_dir_env_var);

      if ( vrkit_data_dir_env_var.empty() )
      {
         vpr::System::setenv("VRKIT_DATA_DIR", vrkit_data_dir.string());
         VRKIT_STATUS << "VRKIT_DATA_DIR set to: " << vrkit_data_dir.string() << std::endl;
      }
      else
      {
         // VRKIT_DATA_DIR set...check if path will match up
      }

      std::string vrkit_plugin_dir_env_var;
      vpr::System::getenv("VRKIT_PLUGINS_DIR", vrkit_plugin_dir_env_var);

      if ( vrkit_plugin_dir_env_var.empty() )
      {
         vpr::System::setenv("VRKIT_PLUGINS_DIR", vrkit_plugins_dir.string());
         VRKIT_STATUS << "VRKIT_PLUGINS_DIR set to: " << vrkit_plugins_dir.string() << std::endl;
      }
      else
      {
         // VRKIT_PLUGINS_DIR set...check if path will match up
      }
   }
}
#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla 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.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "vint-serialization.hh"
#include "core/future.hh"
#include "core/iostream.hh"
#include "sstables/exceptions.hh"
#include "sstables/progress_monitor.hh"
#include <seastar/core/byteorder.hh>
#include <seastar/util/variant_utils.hh>
#include <seastar/net/byteorder.hh>
#include "bytes.hh"

template<typename T>
static inline T consume_be(temporary_buffer<char>& p) {
    T i = read_be<T>(p.get());
    p.trim_front(sizeof(T));
    return i;
}

namespace data_consumer {
enum class proceed { no, yes };
using processing_result = boost::variant<proceed, skip_bytes>;

inline bool operator==(const processing_result& result, proceed value) {
    const proceed* p = boost::get<proceed>(&result);
    return (p != nullptr && *p == value);
}

inline bool operator!=(const processing_result& result, proceed value) {
    return !(result == value);
}

template <typename StateProcessor>
class continuous_data_consumer {
    using proceed = data_consumer::proceed;
    StateProcessor& state_processor() {
        return static_cast<StateProcessor&>(*this);
    };
protected:
    input_stream<char> _input;
    sstables::reader_position_tracker _stream_position;
    // remaining length of input to read (if <0, continue until end of file).
    uint64_t _remain;

    // state machine progress:
    enum class prestate {
        NONE,
        READING_U8,
        READING_U16,
        READING_U32,
        READING_U64,
        READING_BYTES,
        READING_UNSIGNED_VINT,
        READING_UNSIGNED_VINT_WITH_LEN,
    } _prestate = prestate::NONE;

    // state for non-NONE prestates
    uint32_t _pos;
    // state for READING_U8, READING_U16, READING_U32, READING_U64 prestate
    uint8_t  _u8;
    uint16_t _u16;
    uint32_t _u32;
    uint64_t _u64;
    union {
        char bytes[sizeof(uint64_t)];
        uint64_t uint64;
        uint32_t uint32;
        uint16_t uint16;
        uint8_t  uint8;
    } _read_int;
    // state for READING_BYTES prestate
    temporary_buffer<char> _read_bytes;
    temporary_buffer<char>* _read_bytes_where; // which temporary_buffer to set, _key or _val?

    enum class read_status { ready, waiting };
private:
    inline read_status read_partial_int(temporary_buffer<char>& data, prestate next_state) {
        std::copy(data.begin(), data.end(), _read_int.bytes);
        _pos = data.size();
        data.trim(0);
        _prestate = next_state;
        return read_status::waiting;
    }
protected:
    inline read_status read_8(temporary_buffer<char>& data) {
        if (data.size() >= sizeof(uint8_t)) {
            _u8 = consume_be<uint8_t>(data);
            return read_status::ready;
        } else {
            _pos = 0;
            _prestate = prestate::READING_U8;
            return read_status::waiting;
        }
    }
    // Read a 16-bit integer into _u16. If the whole thing is in the buffer
    // (this is the common case), do this immediately. Otherwise, remember
    // what we have in the buffer, and remember to continue later by using
    // a "prestate":
    inline read_status read_16(temporary_buffer<char>& data) {
        if (data.size() >= sizeof(uint16_t)) {
            _u16 = consume_be<uint16_t>(data);
            return read_status::ready;
        } else {
            return read_partial_int(data, prestate::READING_U16);
        }
    }
    inline read_status read_32(temporary_buffer<char>& data) {
        if (data.size() >= sizeof(uint32_t)) {
            _u32 = consume_be<uint32_t>(data);
            return read_status::ready;
        } else {
            return read_partial_int(data, prestate::READING_U32);
        }
    }
    inline read_status read_64(temporary_buffer<char>& data) {
        if (data.size() >= sizeof(uint64_t)) {
            _u64 = consume_be<uint64_t>(data);
            return read_status::ready;
        } else {
            return read_partial_int(data, prestate::READING_U64);
        }
    }
    inline read_status read_bytes(temporary_buffer<char>& data, uint32_t len, temporary_buffer<char>& where) {
        if (data.size() >=  len) {
            where = data.share(0, len);
            data.trim_front(len);
            return read_status::ready;
        } else {
            // copy what we have so far, read the rest later
            _read_bytes = temporary_buffer<char>(len);
            std::copy(data.begin(), data.end(),_read_bytes.get_write());
            _read_bytes_where = &where;
            _pos = data.size();
            data.trim(0);
            _prestate = prestate::READING_BYTES;
            return read_status::waiting;
        }
    }
    inline read_status read_unsigned_vint(temporary_buffer<char>& data) {
        if (data.empty()) {
            _prestate = prestate::READING_UNSIGNED_VINT;
            return read_status::waiting;
        } else {
            const vint_size_type len = unsigned_vint::serialized_size_from_first_byte(*data.begin());
            if (data.size() >= len) {
                _u64 = unsigned_vint::deserialize(
                        bytes_view(reinterpret_cast<bytes::value_type*>(data.get_write()), len)).value;
                data.trim_front(len);
                return read_status::ready;
            } else {
                _read_bytes = temporary_buffer<char>(len);
                std::copy(data.begin(), data.end(), _read_bytes.get_write());
                _pos = data.size();
                data.trim(0);
                _prestate = prestate::READING_UNSIGNED_VINT_WITH_LEN;
                return read_status::waiting;
            }
        }
    }

    inline void process_buffer(temporary_buffer<char>& data) {
        if (__builtin_expect((_prestate != prestate::NONE), 0)) {
            do_process_buffer(data);
        }
    }
private:
    // This is separated so that the compiler can inline "process_buffer". Because this chunk is too big,
    // it usually won't if this is part of the main function
    void do_process_buffer(temporary_buffer<char>& data) {
        // We're in the middle of reading a basic type, which crossed
        // an input buffer. Resume that read before continuing to
        // handle the current state:
        if (_prestate == prestate::READING_UNSIGNED_VINT) {
            if (read_unsigned_vint(data) == read_status::ready) {
                _prestate = prestate::NONE;
            }
        } else if (_prestate == prestate::READING_UNSIGNED_VINT_WITH_LEN) {
            const auto n = std::min(_read_bytes.size() - _pos, data.size());
            std::copy_n(data.begin(), n, _read_bytes.get_write() + _pos);
            data.trim_front(n);
            _pos += n;
            if (_pos == _read_bytes.size()) {
                _u64 = unsigned_vint::deserialize(
                        bytes_view(reinterpret_cast<bytes::value_type*>(_read_bytes.get_write()), _read_bytes.size())).value;
                _prestate = prestate::NONE;
            }
        } else if (_prestate == prestate::READING_BYTES) {
            auto n = std::min(_read_bytes.size() - _pos, data.size());
            std::copy(data.begin(), data.begin() + n,
                    _read_bytes.get_write() + _pos);
            data.trim_front(n);
            _pos += n;
            if (_pos == _read_bytes.size()) {
                *_read_bytes_where = std::move(_read_bytes);
                _prestate = prestate::NONE;
            }
        } else {
            // in the middle of reading an integer
            unsigned len;
            switch (_prestate) {
            case prestate::READING_U8:
                len = sizeof(uint8_t);
                break;
            case prestate::READING_U16:
                len = sizeof(uint16_t);
                break;
            case prestate::READING_U32:
                len = sizeof(uint32_t);
                break;
            case prestate::READING_U64:
                len = sizeof(uint64_t);
                break;
            default:
                throw sstables::malformed_sstable_exception("unknown prestate");
            }
            assert(_pos < len);
            auto n = std::min((size_t)(len - _pos), data.size());
            std::copy(data.begin(), data.begin() + n, _read_int.bytes + _pos);
            data.trim_front(n);
            _pos += n;
            if (_pos == len) {
                // done reading the integer, store it in _u8, _u16, _u32 or _u64:
                switch (_prestate) {
                case prestate::READING_U8:
                    _u8 = _read_int.uint8;
                    break;
                case prestate::READING_U16:
                    _u16 = net::ntoh(_read_int.uint16);
                    break;
                case prestate::READING_U32:
                    _u32 = net::ntoh(_read_int.uint32);
                    break;
                case prestate::READING_U64:
                    _u64 = net::ntoh(_read_int.uint64);
                    break;
                default:
                    throw sstables::malformed_sstable_exception(
                            "unknown prestate");
                }
                _prestate = prestate::NONE;
            }
        }
    }

    void verify_end_state() {
        state_processor().verify_end_state();
    }
public:
    continuous_data_consumer(input_stream<char>&& input, uint64_t start, uint64_t maxlen)
            : _input(std::move(input)), _stream_position(sstables::reader_position_tracker{start, maxlen}), _remain(maxlen) {}

    future<> consume_input() {
        return _input.consume(state_processor());
    }

    // some states do not consume input (its only exists to perform some
    // action when finishing to read a primitive type via a prestate, in
    // the rare case that a primitive type crossed a buffer). Such
    // non-consuming states need to run even if the data buffer is empty.
    bool non_consuming() {
        return state_processor().non_consuming();
    }

    using unconsumed_remainder = input_stream<char>::unconsumed_remainder;
    using consumption_result_type = consumption_result<char>;

    inline processing_result process(temporary_buffer<char>& data) {
        while (data || non_consuming()) {
            process_buffer(data);
            // If _prestate is set to something other than prestate::NONE
            // after process_buffer was called, it means that data wasn't
            // enough to complete the prestate. That can happen specially
            // when reading a large buf. Thefore, we need to ask caller
            // to read more data until prestate is completed.
            if (__builtin_expect((_prestate != prestate::NONE), 0)) {
                // assert that data was all consumed by process_buffer.
                assert(data.size() == 0);
                return proceed::yes;
            }
            auto ret = state_processor().process_state(data);
            if (__builtin_expect(ret != proceed::yes, 0)) {
                return ret;
            }
        }
        return proceed::yes;
    }

    // called by input_stream::consume():
    future<consumption_result_type>
    operator()(temporary_buffer<char> data) {
        if (data.size() >= _remain) {
            // We received more data than we actually care about, so process
            // the beginning of the buffer, and return the rest to the stream
            auto segment = data.share(0, _remain);
            auto ret = process(segment);
            data.trim_front(_remain - segment.size());
            auto len = _remain - segment.size();
            _remain -= len;
            _stream_position.position += len;
            if (_remain == 0 && ret == proceed::yes) {
                verify_end_state();
            }
            return make_ready_future<consumption_result_type>(stop_consuming<char>{std::move(data)});
        } else if (data.empty()) {
            // End of file
            verify_end_state();
            return make_ready_future<consumption_result_type>(stop_consuming<char>{std::move(data)});
        } else {
            // We can process the entire buffer (if the consumer wants to).
            auto orig_data_size = data.size();
            _stream_position.position += data.size();
            auto result = process(data);
            return visit(result, [this, &data, orig_data_size] (proceed value) {
                _remain -= orig_data_size - data.size();
                _stream_position.position -= data.size();
                if (value == proceed::yes) {
                    return make_ready_future<consumption_result_type>(continue_consuming{});
                } else {
                    return make_ready_future<consumption_result_type>(stop_consuming<char>{std::move(data)});
                }
            }, [this, &data, orig_data_size](skip_bytes skip) {
                // we only expect skip_bytes to be used if reader needs to skip beyond the provided buffer
                // otherwise it should just trim_front and proceed as usual
                assert(data.size() == 0);
                _remain -= orig_data_size;
                if (skip.get_value() >= _remain) {
                    _stream_position.position += _remain;
                    _remain = 0;
                    verify_end_state();
                    return make_ready_future<consumption_result_type>(stop_consuming<char>{std::move(data)});
                }
                _stream_position.position += skip.get_value();
                _remain -= skip.get_value();
                return make_ready_future<consumption_result_type>(std::move(skip));
            });
        }
    }

    future<> fast_forward_to(size_t begin, size_t end) {
        assert(begin >= _stream_position.position);
        auto n = begin - _stream_position.position;
        _stream_position.position = begin;

        assert(end >= _stream_position.position);
        _remain = end - _stream_position.position;

        _prestate = prestate::NONE;
        return _input.skip(n);
    }

    future<> skip_to(size_t begin) {
        return fast_forward_to(begin, _stream_position.position + _remain);
    }

    uint64_t position() const {
        return _stream_position.position;
    }

    const sstables::reader_position_tracker& reader_position() {
        return _stream_position;
    }

    bool eof() const {
        return _remain == 0;
    }

    future<> close() {
        return _input.close();
    }
};
}
<commit_msg>Add continuous_data_consumer::read_short_length_bytes<commit_after>/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla 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.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "vint-serialization.hh"
#include "core/future.hh"
#include "core/iostream.hh"
#include "sstables/exceptions.hh"
#include "sstables/progress_monitor.hh"
#include <seastar/core/byteorder.hh>
#include <seastar/util/variant_utils.hh>
#include <seastar/net/byteorder.hh>
#include "bytes.hh"

template<typename T>
static inline T consume_be(temporary_buffer<char>& p) {
    T i = read_be<T>(p.get());
    p.trim_front(sizeof(T));
    return i;
}

namespace data_consumer {
enum class proceed { no, yes };
using processing_result = boost::variant<proceed, skip_bytes>;

inline bool operator==(const processing_result& result, proceed value) {
    const proceed* p = boost::get<proceed>(&result);
    return (p != nullptr && *p == value);
}

inline bool operator!=(const processing_result& result, proceed value) {
    return !(result == value);
}

template <typename StateProcessor>
class continuous_data_consumer {
    using proceed = data_consumer::proceed;
    StateProcessor& state_processor() {
        return static_cast<StateProcessor&>(*this);
    };
protected:
    input_stream<char> _input;
    sstables::reader_position_tracker _stream_position;
    // remaining length of input to read (if <0, continue until end of file).
    uint64_t _remain;

    // state machine progress:
    enum class prestate {
        NONE,
        READING_U8,
        READING_U16,
        READING_U32,
        READING_U64,
        READING_BYTES,
        READING_U16_BYTES,
        READING_UNSIGNED_VINT,
        READING_UNSIGNED_VINT_WITH_LEN,
    } _prestate = prestate::NONE;

    // state for non-NONE prestates
    uint32_t _pos;
    // state for READING_U8, READING_U16, READING_U32, READING_U64 prestate
    uint8_t  _u8;
    uint16_t _u16;
    uint32_t _u32;
    uint64_t _u64;
    union {
        char bytes[sizeof(uint64_t)];
        uint64_t uint64;
        uint32_t uint32;
        uint16_t uint16;
        uint8_t  uint8;
    } _read_int;
    // state for READING_BYTES prestate
    temporary_buffer<char> _read_bytes;
    temporary_buffer<char>* _read_bytes_where; // which temporary_buffer to set, _key or _val?

    enum class read_status { ready, waiting };
private:
    inline read_status read_partial_int(temporary_buffer<char>& data, prestate next_state) {
        std::copy(data.begin(), data.end(), _read_int.bytes);
        _pos = data.size();
        data.trim(0);
        _prestate = next_state;
        return read_status::waiting;
    }
protected:
    inline read_status read_8(temporary_buffer<char>& data) {
        if (data.size() >= sizeof(uint8_t)) {
            _u8 = consume_be<uint8_t>(data);
            return read_status::ready;
        } else {
            _pos = 0;
            _prestate = prestate::READING_U8;
            return read_status::waiting;
        }
    }
    // Read a 16-bit integer into _u16. If the whole thing is in the buffer
    // (this is the common case), do this immediately. Otherwise, remember
    // what we have in the buffer, and remember to continue later by using
    // a "prestate":
    inline read_status read_16(temporary_buffer<char>& data) {
        if (data.size() >= sizeof(uint16_t)) {
            _u16 = consume_be<uint16_t>(data);
            return read_status::ready;
        } else {
            return read_partial_int(data, prestate::READING_U16);
        }
    }
    inline read_status read_32(temporary_buffer<char>& data) {
        if (data.size() >= sizeof(uint32_t)) {
            _u32 = consume_be<uint32_t>(data);
            return read_status::ready;
        } else {
            return read_partial_int(data, prestate::READING_U32);
        }
    }
    inline read_status read_64(temporary_buffer<char>& data) {
        if (data.size() >= sizeof(uint64_t)) {
            _u64 = consume_be<uint64_t>(data);
            return read_status::ready;
        } else {
            return read_partial_int(data, prestate::READING_U64);
        }
    }
    inline read_status read_bytes(temporary_buffer<char>& data, uint32_t len, temporary_buffer<char>& where) {
        if (data.size() >=  len) {
            where = data.share(0, len);
            data.trim_front(len);
            return read_status::ready;
        } else {
            // copy what we have so far, read the rest later
            _read_bytes = temporary_buffer<char>(len);
            std::copy(data.begin(), data.end(),_read_bytes.get_write());
            _read_bytes_where = &where;
            _pos = data.size();
            data.trim(0);
            _prestate = prestate::READING_BYTES;
            return read_status::waiting;
        }
    }
    inline read_status read_short_length_bytes(temporary_buffer<char>& data, temporary_buffer<char>& where) {
        if (data.size() >= sizeof(uint16_t)) {
            _u16 = consume_be<uint16_t>(data);
        } else {
            _read_bytes_where = &where;
            return read_partial_int(data, prestate::READING_U16_BYTES);
        }
        return read_bytes(data, uint32_t{_u16}, where);
    }
    inline read_status read_unsigned_vint(temporary_buffer<char>& data) {
        if (data.empty()) {
            _prestate = prestate::READING_UNSIGNED_VINT;
            return read_status::waiting;
        } else {
            const vint_size_type len = unsigned_vint::serialized_size_from_first_byte(*data.begin());
            if (data.size() >= len) {
                _u64 = unsigned_vint::deserialize(
                        bytes_view(reinterpret_cast<bytes::value_type*>(data.get_write()), len)).value;
                data.trim_front(len);
                return read_status::ready;
            } else {
                _read_bytes = temporary_buffer<char>(len);
                std::copy(data.begin(), data.end(), _read_bytes.get_write());
                _pos = data.size();
                data.trim(0);
                _prestate = prestate::READING_UNSIGNED_VINT_WITH_LEN;
                return read_status::waiting;
            }
        }
    }

    inline void process_buffer(temporary_buffer<char>& data) {
        if (__builtin_expect((_prestate != prestate::NONE), 0)) {
            do_process_buffer(data);
        }
    }
private:
    // This is separated so that the compiler can inline "process_buffer". Because this chunk is too big,
    // it usually won't if this is part of the main function
    void do_process_buffer(temporary_buffer<char>& data) {
        // We're in the middle of reading a basic type, which crossed
        // an input buffer. Resume that read before continuing to
        // handle the current state:
        if (_prestate == prestate::READING_UNSIGNED_VINT) {
            if (read_unsigned_vint(data) == read_status::ready) {
                _prestate = prestate::NONE;
            }
        } else if (_prestate == prestate::READING_UNSIGNED_VINT_WITH_LEN) {
            const auto n = std::min(_read_bytes.size() - _pos, data.size());
            std::copy_n(data.begin(), n, _read_bytes.get_write() + _pos);
            data.trim_front(n);
            _pos += n;
            if (_pos == _read_bytes.size()) {
                _u64 = unsigned_vint::deserialize(
                        bytes_view(reinterpret_cast<bytes::value_type*>(_read_bytes.get_write()), _read_bytes.size())).value;
                _prestate = prestate::NONE;
            }
        } else if (_prestate == prestate::READING_BYTES) {
            auto n = std::min(_read_bytes.size() - _pos, data.size());
            std::copy(data.begin(), data.begin() + n,
                    _read_bytes.get_write() + _pos);
            data.trim_front(n);
            _pos += n;
            if (_pos == _read_bytes.size()) {
                *_read_bytes_where = std::move(_read_bytes);
                _prestate = prestate::NONE;
            }
        } else {
            // in the middle of reading an integer
            unsigned len;
            switch (_prestate) {
            case prestate::READING_U8:
                len = sizeof(uint8_t);
                break;
            case prestate::READING_U16:
            case prestate::READING_U16_BYTES:
                len = sizeof(uint16_t);
                break;
            case prestate::READING_U32:
                len = sizeof(uint32_t);
                break;
            case prestate::READING_U64:
                len = sizeof(uint64_t);
                break;
            default:
                throw sstables::malformed_sstable_exception("unknown prestate");
            }
            assert(_pos < len);
            auto n = std::min((size_t)(len - _pos), data.size());
            std::copy(data.begin(), data.begin() + n, _read_int.bytes + _pos);
            data.trim_front(n);
            _pos += n;
            if (_pos == len) {
                // done reading the integer, store it in _u8, _u16, _u32 or _u64:
                switch (_prestate) {
                case prestate::READING_U8:
                    _u8 = _read_int.uint8;
                    break;
                case prestate::READING_U16:
                    _u16 = net::ntoh(_read_int.uint16);
                    break;
                case prestate::READING_U32:
                    _u32 = net::ntoh(_read_int.uint32);
                    break;
                case prestate::READING_U64:
                    _u64 = net::ntoh(_read_int.uint64);
                    break;
                case prestate::READING_U16_BYTES:
                    _u16 = net::ntoh(_read_int.uint16);
                    _prestate = prestate::NONE;
                    read_bytes(data, _u16, *_read_bytes_where);
                    return;
                default:
                    throw sstables::malformed_sstable_exception(
                            "unknown prestate");
                }
                _prestate = prestate::NONE;
            }
        }
    }

    void verify_end_state() {
        state_processor().verify_end_state();
    }
public:
    continuous_data_consumer(input_stream<char>&& input, uint64_t start, uint64_t maxlen)
            : _input(std::move(input)), _stream_position(sstables::reader_position_tracker{start, maxlen}), _remain(maxlen) {}

    future<> consume_input() {
        return _input.consume(state_processor());
    }

    // some states do not consume input (its only exists to perform some
    // action when finishing to read a primitive type via a prestate, in
    // the rare case that a primitive type crossed a buffer). Such
    // non-consuming states need to run even if the data buffer is empty.
    bool non_consuming() {
        return state_processor().non_consuming();
    }

    using unconsumed_remainder = input_stream<char>::unconsumed_remainder;
    using consumption_result_type = consumption_result<char>;

    inline processing_result process(temporary_buffer<char>& data) {
        while (data || non_consuming()) {
            process_buffer(data);
            // If _prestate is set to something other than prestate::NONE
            // after process_buffer was called, it means that data wasn't
            // enough to complete the prestate. That can happen specially
            // when reading a large buf. Thefore, we need to ask caller
            // to read more data until prestate is completed.
            if (__builtin_expect((_prestate != prestate::NONE), 0)) {
                // assert that data was all consumed by process_buffer.
                assert(data.size() == 0);
                return proceed::yes;
            }
            auto ret = state_processor().process_state(data);
            if (__builtin_expect(ret != proceed::yes, 0)) {
                return ret;
            }
        }
        return proceed::yes;
    }

    // called by input_stream::consume():
    future<consumption_result_type>
    operator()(temporary_buffer<char> data) {
        if (data.size() >= _remain) {
            // We received more data than we actually care about, so process
            // the beginning of the buffer, and return the rest to the stream
            auto segment = data.share(0, _remain);
            auto ret = process(segment);
            data.trim_front(_remain - segment.size());
            auto len = _remain - segment.size();
            _remain -= len;
            _stream_position.position += len;
            if (_remain == 0 && ret == proceed::yes) {
                verify_end_state();
            }
            return make_ready_future<consumption_result_type>(stop_consuming<char>{std::move(data)});
        } else if (data.empty()) {
            // End of file
            verify_end_state();
            return make_ready_future<consumption_result_type>(stop_consuming<char>{std::move(data)});
        } else {
            // We can process the entire buffer (if the consumer wants to).
            auto orig_data_size = data.size();
            _stream_position.position += data.size();
            auto result = process(data);
            return visit(result, [this, &data, orig_data_size] (proceed value) {
                _remain -= orig_data_size - data.size();
                _stream_position.position -= data.size();
                if (value == proceed::yes) {
                    return make_ready_future<consumption_result_type>(continue_consuming{});
                } else {
                    return make_ready_future<consumption_result_type>(stop_consuming<char>{std::move(data)});
                }
            }, [this, &data, orig_data_size](skip_bytes skip) {
                // we only expect skip_bytes to be used if reader needs to skip beyond the provided buffer
                // otherwise it should just trim_front and proceed as usual
                assert(data.size() == 0);
                _remain -= orig_data_size;
                if (skip.get_value() >= _remain) {
                    _stream_position.position += _remain;
                    _remain = 0;
                    verify_end_state();
                    return make_ready_future<consumption_result_type>(stop_consuming<char>{std::move(data)});
                }
                _stream_position.position += skip.get_value();
                _remain -= skip.get_value();
                return make_ready_future<consumption_result_type>(std::move(skip));
            });
        }
    }

    future<> fast_forward_to(size_t begin, size_t end) {
        assert(begin >= _stream_position.position);
        auto n = begin - _stream_position.position;
        _stream_position.position = begin;

        assert(end >= _stream_position.position);
        _remain = end - _stream_position.position;

        _prestate = prestate::NONE;
        return _input.skip(n);
    }

    future<> skip_to(size_t begin) {
        return fast_forward_to(begin, _stream_position.position + _remain);
    }

    uint64_t position() const {
        return _stream_position.position;
    }

    const sstables::reader_position_tracker& reader_position() {
        return _stream_position;
    }

    bool eof() const {
        return _remain == 0;
    }

    future<> close() {
        return _input.close();
    }
};
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#include "core/do_with.hh"
#include "cql_test_env.hh"
#include "cql3/query_processor.hh"
#include "cql3/query_options.hh"
#include "core/distributed.hh"
#include "core/shared_ptr.hh"
#include "utils/UUID_gen.hh"

class in_memory_cql_env : public cql_test_env {
public:
    static auto constexpr ks_name = "ks";
private:
    ::shared_ptr<distributed<database>> _db;
    ::shared_ptr<distributed<cql3::query_processor>> _qp;
    ::shared_ptr<service::storage_proxy> _proxy;
private:
    struct core_local_state {
        service::client_state client_state;

        core_local_state()
            : client_state(service::client_state::for_internal_calls()) {
            client_state.set_keyspace(ks_name);
        }

        future<> stop() {
            return make_ready_future<>();
        }
    };
    distributed<core_local_state> _core_local;
private:
    auto make_query_state() {
        return ::make_shared<service::query_state>(_core_local.local().client_state);
    }
public:
    in_memory_cql_env(
        ::shared_ptr<distributed<database>> db,
        ::shared_ptr<distributed<cql3::query_processor>> qp,
        ::shared_ptr<service::storage_proxy> proxy)
            : _db(db)
            , _qp(qp)
            , _proxy(proxy)
    { }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_cql(const sstring& text) override {
        auto qs = make_query_state();
        return _qp->local().process(text, *qs, cql3::query_options::DEFAULT).finally([qs] {});
    }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_cql(
        const sstring& text,
        std::unique_ptr<cql3::query_options> qo) override
    {
        auto qs = make_query_state();
        auto& lqo = *qo;
        return _qp->local().process(text, *qs, lqo).finally([qs, qo = std::move(qo)] {});
    }

    virtual future<bytes> prepare(sstring query) override {
        return _qp->invoke_on_all([query, this] (auto& local_qp) {
            auto qs = this->make_query_state();
            return local_qp.prepare(query, *qs).finally([qs] {}).discard_result();
        }).then([query, this] {
            return _qp->local().compute_id(query, ks_name);
        });
    }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_prepared(
        bytes id,
        std::vector<bytes_opt> values) override
    {
        auto prepared = _qp->local().get_prepared(id);
        assert(bool(prepared));
        auto stmt = prepared->statement;
        assert(stmt->get_bound_terms() == values.size());

        int32_t protocol_version = 3;
        auto options = ::make_shared<cql3::query_options>(db::consistency_level::ONE, std::experimental::nullopt, std::move(values), false,
                                                          cql3::query_options::specific_options::DEFAULT, protocol_version, serialization_format::use_32_bit());
        options->prepare(prepared->bound_names);

        auto qs = make_query_state();
        return _qp->local().process_statement(stmt, *qs, *options)
            .finally([options, qs] {});
    }

    virtual future<> create_table(std::function<schema(const sstring&)> schema_maker) override {
        auto id = utils::UUID_gen::get_time_UUID();
        return _db->invoke_on_all([schema_maker, id, this] (database& db) {
            auto cf_schema = make_lw_shared(schema_maker(ks_name));
            cf_schema->set_id(id);
            auto ksm = make_lw_shared<keyspace_metadata>(sstring{ks_name},
                    "org.apache.cassandra.locator.SimpleStrategy",
                    std::unordered_map<sstring, sstring>(),
                    false
                    );
            auto& ks = db.find_or_create_keyspace(ksm);
            auto cfg = ks.make_column_family_config(*cf_schema);
            db.add_column_family(column_family(std::move(cf_schema), std::move(cfg)));
        });
    }

    virtual future<> require_keyspace_exists(const sstring& ks_name) override {
        auto& db = _db->local();
        assert(db.has_keyspace(ks_name));
        return make_ready_future<>();
    }

    virtual future<> require_column_has_value(const sstring& table_name,
                                      std::vector<boost::any> pk,
                                      std::vector<boost::any> ck,
                                      const sstring& column_name,
                                      boost::any expected) override {
        auto& db = _db->local();
        auto& cf = db.find_column_family(ks_name, table_name);
        auto schema = cf.schema();
        auto pkey = partition_key::from_deeply_exploded(*schema, pk);
        auto dk = dht::global_partitioner().decorate_key(*schema, pkey);
        auto shard = db.shard_of(dk._token);
        return _db->invoke_on(shard, [pkey = std::move(pkey),
                                      ck = std::move(ck),
                                      ks_name = std::move(ks_name),
                                      column_name = std::move(column_name),
                                      expected = std::move(expected),
                                      table_name = std::move(table_name)] (database& db) {
          auto& cf = db.find_column_family(ks_name, table_name);
          auto schema = cf.schema();
          return cf.find_partition_slow(pkey).then([schema, ck, column_name, expected] (column_family::const_mutation_partition_ptr p) {
            assert(p != nullptr);
            auto row = p->find_row(clustering_key::from_deeply_exploded(*schema, ck));
            assert(row != nullptr);
            auto col_def = schema->get_column_definition(utf8_type->decompose(column_name));
            assert(col_def != nullptr);
            const atomic_cell_or_collection* cell = row->find_cell(col_def->id);
            if (!cell) {
                assert(((void)"column not set", 0));
            }
            bytes actual;
            if (!col_def->type->is_multi_cell()) {
                auto c = cell->as_atomic_cell();
                assert(c.is_live());
                actual = { c.value().begin(), c.value().end() };
            } else {
                auto c = cell->as_collection_mutation();
                auto type = dynamic_pointer_cast<const collection_type_impl>(col_def->type);
                actual = type->to_value(type->deserialize_mutation_form(c),
                                        serialization_format::internal());
            }
            assert(col_def->type->equal(actual, col_def->type->decompose(expected)));
          });
        });
    }

    virtual database& local_db() override {
        return _db->local();
    }

    future<> start() {
        return _core_local.start();
    }

    virtual future<> stop() override {
        return _core_local.stop().then([this] {
            return _qp->stop().then([this] {
                return _db->stop();
            });
        });
    }
};

future<::shared_ptr<cql_test_env>> make_env_for_test() {
    auto db = ::make_shared<distributed<database>>();
    return db->start().then([db] {
        auto proxy = ::make_shared<service::storage_proxy>(std::ref(*db));
        auto qp = ::make_shared<distributed<cql3::query_processor>>();
        return qp->start(std::ref(*proxy), std::ref(*db)).then([db, proxy, qp] {
            auto env = ::make_shared<in_memory_cql_env>(db, qp, proxy);
            return env->start().then([env] () -> ::shared_ptr<cql_test_env> {
                return env;
            });
        });
    });
}

future<> do_with_cql_env(std::function<future<>(cql_test_env&)> func) {
    return make_env_for_test().then([func = std::move(func)] (auto e) mutable {
        return do_with(std::move(func), [e] (auto& f) {
            return f(*e);
        }).finally([e] {
            return e->stop().finally([e] {});
        });
    });
}
<commit_msg>cql_test_env: Create keyspace for all test cases<commit_after>/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#include "core/do_with.hh"
#include "cql_test_env.hh"
#include "cql3/query_processor.hh"
#include "cql3/query_options.hh"
#include "core/distributed.hh"
#include "core/shared_ptr.hh"
#include "utils/UUID_gen.hh"

class in_memory_cql_env : public cql_test_env {
public:
    static auto constexpr ks_name = "ks";
private:
    ::shared_ptr<distributed<database>> _db;
    ::shared_ptr<distributed<cql3::query_processor>> _qp;
    ::shared_ptr<service::storage_proxy> _proxy;
private:
    struct core_local_state {
        service::client_state client_state;

        core_local_state()
            : client_state(service::client_state::for_internal_calls()) {
            client_state.set_keyspace(ks_name);
        }

        future<> stop() {
            return make_ready_future<>();
        }
    };
    distributed<core_local_state> _core_local;
private:
    auto make_query_state() {
        return ::make_shared<service::query_state>(_core_local.local().client_state);
    }
public:
    in_memory_cql_env(
        ::shared_ptr<distributed<database>> db,
        ::shared_ptr<distributed<cql3::query_processor>> qp,
        ::shared_ptr<service::storage_proxy> proxy)
            : _db(db)
            , _qp(qp)
            , _proxy(proxy)
    { }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_cql(const sstring& text) override {
        auto qs = make_query_state();
        return _qp->local().process(text, *qs, cql3::query_options::DEFAULT).finally([qs] {});
    }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_cql(
        const sstring& text,
        std::unique_ptr<cql3::query_options> qo) override
    {
        auto qs = make_query_state();
        auto& lqo = *qo;
        return _qp->local().process(text, *qs, lqo).finally([qs, qo = std::move(qo)] {});
    }

    virtual future<bytes> prepare(sstring query) override {
        return _qp->invoke_on_all([query, this] (auto& local_qp) {
            auto qs = this->make_query_state();
            return local_qp.prepare(query, *qs).finally([qs] {}).discard_result();
        }).then([query, this] {
            return _qp->local().compute_id(query, ks_name);
        });
    }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_prepared(
        bytes id,
        std::vector<bytes_opt> values) override
    {
        auto prepared = _qp->local().get_prepared(id);
        assert(bool(prepared));
        auto stmt = prepared->statement;
        assert(stmt->get_bound_terms() == values.size());

        int32_t protocol_version = 3;
        auto options = ::make_shared<cql3::query_options>(db::consistency_level::ONE, std::experimental::nullopt, std::move(values), false,
                                                          cql3::query_options::specific_options::DEFAULT, protocol_version, serialization_format::use_32_bit());
        options->prepare(prepared->bound_names);

        auto qs = make_query_state();
        return _qp->local().process_statement(stmt, *qs, *options)
            .finally([options, qs] {});
    }

    virtual future<> create_table(std::function<schema(const sstring&)> schema_maker) override {
        auto id = utils::UUID_gen::get_time_UUID();
        return _db->invoke_on_all([schema_maker, id, this] (database& db) {
            auto cf_schema = make_lw_shared(schema_maker(ks_name));
            cf_schema->set_id(id);
            auto& ks = db.find_keyspace(ks_name);
            auto cfg = ks.make_column_family_config(*cf_schema);
            db.add_column_family(column_family(std::move(cf_schema), std::move(cfg)));
        });
    }

    virtual future<> require_keyspace_exists(const sstring& ks_name) override {
        auto& db = _db->local();
        assert(db.has_keyspace(ks_name));
        return make_ready_future<>();
    }

    virtual future<> require_column_has_value(const sstring& table_name,
                                      std::vector<boost::any> pk,
                                      std::vector<boost::any> ck,
                                      const sstring& column_name,
                                      boost::any expected) override {
        auto& db = _db->local();
        auto& cf = db.find_column_family(ks_name, table_name);
        auto schema = cf.schema();
        auto pkey = partition_key::from_deeply_exploded(*schema, pk);
        auto dk = dht::global_partitioner().decorate_key(*schema, pkey);
        auto shard = db.shard_of(dk._token);
        return _db->invoke_on(shard, [pkey = std::move(pkey),
                                      ck = std::move(ck),
                                      ks_name = std::move(ks_name),
                                      column_name = std::move(column_name),
                                      expected = std::move(expected),
                                      table_name = std::move(table_name)] (database& db) {
          auto& cf = db.find_column_family(ks_name, table_name);
          auto schema = cf.schema();
          return cf.find_partition_slow(pkey).then([schema, ck, column_name, expected] (column_family::const_mutation_partition_ptr p) {
            assert(p != nullptr);
            auto row = p->find_row(clustering_key::from_deeply_exploded(*schema, ck));
            assert(row != nullptr);
            auto col_def = schema->get_column_definition(utf8_type->decompose(column_name));
            assert(col_def != nullptr);
            const atomic_cell_or_collection* cell = row->find_cell(col_def->id);
            if (!cell) {
                assert(((void)"column not set", 0));
            }
            bytes actual;
            if (!col_def->type->is_multi_cell()) {
                auto c = cell->as_atomic_cell();
                assert(c.is_live());
                actual = { c.value().begin(), c.value().end() };
            } else {
                auto c = cell->as_collection_mutation();
                auto type = dynamic_pointer_cast<const collection_type_impl>(col_def->type);
                actual = type->to_value(type->deserialize_mutation_form(c),
                                        serialization_format::internal());
            }
            assert(col_def->type->equal(actual, col_def->type->decompose(expected)));
          });
        });
    }

    virtual database& local_db() override {
        return _db->local();
    }

    future<> start() {
        return _core_local.start().then([this] () {
            return _db->invoke_on_all([this] (database& db) {
                auto ksm = make_lw_shared<keyspace_metadata>(sstring{ks_name},
                        "org.apache.cassandra.locator.SimpleStrategy",
                        std::unordered_map<sstring, sstring>(),
                        false
                        );
                db.find_or_create_keyspace(ksm);
                return make_ready_future<>();
            });
        });
    }

    virtual future<> stop() override {
        return _core_local.stop().then([this] {
            return _qp->stop().then([this] {
                return _db->stop();
            });
        });
    }
};

future<::shared_ptr<cql_test_env>> make_env_for_test() {
    auto db = ::make_shared<distributed<database>>();
    return db->start().then([db] {
        auto proxy = ::make_shared<service::storage_proxy>(std::ref(*db));
        auto qp = ::make_shared<distributed<cql3::query_processor>>();
        return qp->start(std::ref(*proxy), std::ref(*db)).then([db, proxy, qp] {
            auto env = ::make_shared<in_memory_cql_env>(db, qp, proxy);
            return env->start().then([env] () -> ::shared_ptr<cql_test_env> {
                return env;
            });
        });
    });
}

future<> do_with_cql_env(std::function<future<>(cql_test_env&)> func) {
    return make_env_for_test().then([func = std::move(func)] (auto e) mutable {
        return do_with(std::move(func), [e] (auto& f) {
            return f(*e);
        }).finally([e] {
            return e->stop().finally([e] {});
        });
    });
}
<|endoftext|>


<commit_before>#include "UT4WebAdmin.h"
#include "Base64.h"

#define UT4WA_PLUGIN_FOLDER "UT4WebAdmin"
#define UT4WA_WWW_FOLDER "www"

#define PAGE "<title>File not found</title>File not found"

UUT4WebAdmin::UUT4WebAdmin(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	daemon = nullptr;
	GameMode = nullptr;
}

void UUT4WebAdmin::Init()
{
	// Don't garbage collect me
	SetFlags(RF_MarkAsRootSet);

	if (WebHttpPort == 0)
	{
		WebHttpPort = 8080;
	}

	StartMicroHttp();
}

TSharedPtr<FJsonObject> GetGameInfoJSON()
{
	TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);;

	// Get a reference of any object using the UTBaseGameMode
	AUTBaseGameMode* BaseGameMode;
	BaseGameMode = Cast<AUTBaseGameMode>(GWorld->GetAuthGameMode());

	if (BaseGameMode) {

		// GameMode
		JsonObject->SetBoolField(TEXT("IsMatchInProgress"), BaseGameMode->IsMatchInProgress());
		JsonObject->SetBoolField(TEXT("HasMatchEnded"), BaseGameMode->HasMatchEnded());
		JsonObject->SetNumberField(TEXT("NumTravellingPlayers"), BaseGameMode->NumTravellingPlayers);
		JsonObject->SetStringField(TEXT("NetworkNumber"), BaseGameMode->GetNetworkNumber());
		JsonObject->SetStringField(TEXT("MatchState"), BaseGameMode->GetMatchState().ToString());

		// UTBaseGameMode
		JsonObject->SetStringField(TEXT("ServerInstanceID"), BaseGameMode->ServerInstanceID);
		JsonObject->SetStringField(TEXT("ServerInstanceGUID"), BaseGameMode->ServerInstanceGUID.ToString()); // The Unique ID for this game instance.
		JsonObject->SetStringField(TEXT("ContextGUID"), BaseGameMode->ContextGUID.ToString()); // ?
		JsonObject->SetStringField(TEXT("ServerPassword"), BaseGameMode->ServerPassword);
		JsonObject->SetStringField(TEXT("SpectatePassword"), BaseGameMode->SpectatePassword);
		JsonObject->SetBoolField(TEXT("bRequirePassword"), BaseGameMode->bRequirePassword);
		JsonObject->SetStringField(TEXT("DisplayName"), BaseGameMode->DisplayName.ToString());
		JsonObject->SetNumberField(TEXT("MinAllowedRank"), BaseGameMode->MinAllowedRank);
		JsonObject->SetNumberField(TEXT("MaxAllowedRank"), BaseGameMode->MaxAllowedRank);
		JsonObject->SetBoolField(TEXT("bTrainingGround"), BaseGameMode->bTrainingGround);
		JsonObject->SetNumberField(TEXT("NumPlayers"), BaseGameMode->GetNumPlayers());
		JsonObject->SetNumberField(TEXT("NumMatches"), BaseGameMode->GetNumMatches()); // 1 if dedi server else [0, .., X] range for hubs/lobbies
		JsonObject->SetNumberField(TEXT("CurrentPlaylistId"), BaseGameMode->CurrentPlaylistId); // no idea what this is about
		JsonObject->SetBoolField(TEXT("CurrentPlaylistId"), BaseGameMode->bPrivateMatch);
		JsonObject->SetStringField(TEXT("RankedLeagueName"), BaseGameMode->GetRankedLeagueName()); // always empty for the moment
		JsonObject->SetBoolField(TEXT("SupportsInstantReplay"), BaseGameMode->SupportsInstantReplay());
		JsonObject->SetBoolField(TEXT("bIsLANGame"), BaseGameMode->bIsLANGame);

		if (BaseGameMode->IsLobbyServer())
		{
			AUTLobbyGameMode* LobbyGameMode;
			LobbyGameMode = GWorld->GetAuthGameMode<AUTLobbyGameMode>();

			if (LobbyGameMode)
			{
				JsonObject->SetStringField(TEXT("ServType"), TEXT("dedis"));
				// TODO get instance data
			}
		}
	}

	return JsonObject;
}

int handle_game_info(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data,
	size_t *upload_data_size, void **con_cls)
{
	int ret;
	struct MHD_Response *response;

	if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) {

		TSharedPtr<FJsonObject> matchInfoJSON = GetGameInfoJSON();

		FString JsonText;
		TSharedRef< TJsonWriter<> > Writer = TJsonWriterFactory<>::Create(&JsonText);
		FJsonSerializer::Serialize(matchInfoJSON.ToSharedRef(), Writer);

		const char* jsonChar = TCHAR_TO_UTF8(*JsonText);

		response = MHD_create_response_from_buffer(strlen(jsonChar),
			(void*)jsonChar, MHD_RESPMEM_PERSISTENT);
		MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, "application/json");

		ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
		MHD_destroy_response(response);
	}

	return ret;
}

// Server files from root folder
const FString wwwStr = FPaths::GamePluginsDir() + UT4WA_PLUGIN_FOLDER + "/" + UT4WA_WWW_FOLDER + "/";

int handle_serve_file(void *cls,
	struct MHD_Connection *connection,
	const char *url,
	const char *method, // GET / POST / PUT ...
	const char *version, // HTML version 1.1
	const char *upload_data,
	size_t *upload_data_size, void **con_cls)
{
	struct MHD_Response *response;
	char *path = NULL;
	int ret;

	// redirect from http://myserver:port/ to http://myserver:port/index.html
	if (strcmp(url, "/") == 0) {
		path = "index.html";
	}

	if (NULL == path) {
		path = new char[strlen(&url[1]) + 1];
		strcpy(path, &url[1]);
	}

	const char *www = TCHAR_TO_ANSI(*wwwStr);

	// calculate the required buffer size (also accounting for the null terminator):
	int bufferSize = strlen(www) + strlen(path) + 1;

	// allocate enough memory for the concatenated string:
	char* concatString = new char[bufferSize];

	// copy strings one and two over to the new buffer:
	strcpy(concatString, www);
	strcat(concatString, path);

	FILE* f;
	f = fopen(concatString, "rb");

	if (f != NULL) {
		// Determine file size
		fseek(f, 0, SEEK_END);
		size_t size = ftell(f);
		char* where = new char[size];
		rewind(f);
		fread(where, sizeof(char), size, f);

		response = MHD_create_response_from_buffer(strlen(where),
			(void*)where, MHD_RESPMEM_PERSISTENT);

		fclose(f);
		ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
	}
	else {
		const char *notExist = "File not found !";
		response = MHD_create_response_from_buffer(strlen(notExist),
			(void*)notExist, MHD_RESPMEM_PERSISTENT);
		ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
	}

	MHD_destroy_response(response);
	return ret;
}

int answer_to_connection(void *cls,
	struct MHD_Connection *connection,
	const char *url,
	const char *method, // GET / POST / PUT ...
	const char *version, // HTML version 1.1
	const char *upload_data,
	size_t *upload_data_size, void **con_cls)
{
	// TODO handle POST methods in the future
	if ((0 != strcmp(method, MHD_HTTP_METHOD_GET)) &&
		(0 != strcmp(method, MHD_HTTP_METHOD_HEAD)))
		return MHD_NO;

	// TODO check user authentification

	if (strcmp(url, "/gameinfo") == 0) {
		// TODO GET JSON GAME INFO
		return handle_game_info(cls, connection, url, method, version, upload_data, upload_data_size, con_cls);
	}
	else {
		return handle_serve_file(cls, connection, url, method, version, upload_data, upload_data_size, con_cls);
	}
}

void UUT4WebAdmin::StartMicroHttp()
{
	// SSL not working yet need some more investigation
	if (WebHttpsEnabled) {

		if (NULL == *WebServerCertificateFile || NULL == *WebServerKeyFile) {
			UE_LOG(UT4WebAdmin, Warning, TEXT("Server key or certificate file is not set."));
			return;
		}

		// openssl req -days 365 -out server.pem -new -x509 -key server.key
		FILE* fcert_file = fopen(TCHAR_TO_ANSI(*WebServerCertificateFile), "r");

		// openssl genrsa -out server.key 1024
		FILE* fkey_file = fopen(TCHAR_TO_ANSI(*WebServerKeyFile), "r");

		if (NULL != fcert_file && NULL != fkey_file) {

			fseek(fcert_file, 0, SEEK_END);
			size_t size = ftell(fcert_file);
			char* cert_pem = new char[size];
			rewind(fcert_file);
			fread(cert_pem, sizeof(char), size, fcert_file);

			fseek(fkey_file, 0, SEEK_END);
			size_t size2 = ftell(fkey_file);
			char* key_pem = new char[size2];
			rewind(fkey_file);
			fread(key_pem, sizeof(char), size2, fkey_file);

			daemon = MHD_start_daemon(MHD_USE_AUTO | MHD_USE_SELECT_INTERNALLY | MHD_USE_TLS | MHD_USE_DEBUG, WebHttpPort, NULL, NULL,
				&answer_to_connection, NULL,
				MHD_OPTION_HTTPS_MEM_KEY, key_pem,
				MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
				MHD_OPTION_END);
		}

		if (NULL != fcert_file) {
			fclose(fcert_file);
		}

		if (NULL != fkey_file) {
			fclose(fkey_file);
		}
	}
	else {
		UE_LOG(UT4WebAdmin, Log, TEXT("Starting HTTP server without SSL"));
		daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, WebHttpPort, NULL, NULL,
			&answer_to_connection, NULL, MHD_OPTION_END);
	}

	if (daemon == NULL) {
		UE_LOG(UT4WebAdmin, Warning, TEXT(" * * * * * * * * * * * * * * * * * * * * * * *"));
		UE_LOG(UT4WebAdmin, Warning, TEXT(" UT4WebAdmin failed to start http(s) server !"));
		UE_LOG(UT4WebAdmin, Warning, TEXT(" * * * * * * * * * * * * * * * * * * * * * * *"));
	}
	else {
		UE_LOG(UT4WebAdmin, Log, TEXT(" * * * * * * * * * * * * * * * * * * * * * * *"));
		UE_LOG(UT4WebAdmin, Log, TEXT(" UT4WebAdmin started at port: %i "), WebHttpPort);
		UE_LOG(UT4WebAdmin, Log, TEXT(" * * * * * * * * * * * * * * * * * * * * * * *"));
	}
}

void UUT4WebAdmin::Stop()
{
	if (NULL != daemon) {
		MHD_stop_daemon(daemon);
	}
}

void UUT4WebAdmin::Tick(float DeltaTime)
{
	//poll(MGServer, 1);
	// TODO
}

TStatId UUT4WebAdmin::GetStatId() const
{
	RETURN_QUICK_DECLARE_CYCLE_STAT(UUT4WebAdmin, STATGROUP_Tickables);
}

<commit_msg>typo fix for gameinfo<commit_after>#include "UT4WebAdmin.h"
#include "Base64.h"

#define UT4WA_PLUGIN_FOLDER "UT4WebAdmin"
#define UT4WA_WWW_FOLDER "www"

#define PAGE "<title>File not found</title>File not found"

UUT4WebAdmin::UUT4WebAdmin(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	daemon = nullptr;
	GameMode = nullptr;
}

void UUT4WebAdmin::Init()
{
	// Don't garbage collect me
	SetFlags(RF_MarkAsRootSet);

	if (WebHttpPort == 0)
	{
		WebHttpPort = 8080;
	}

	StartMicroHttp();
}

TSharedPtr<FJsonObject> GetGameInfoJSON()
{
	TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);;

	// Get a reference of any object using the UTBaseGameMode
	AUTBaseGameMode* BaseGameMode;
	BaseGameMode = Cast<AUTBaseGameMode>(GWorld->GetAuthGameMode());

	if (BaseGameMode) {

		// GameMode
		JsonObject->SetBoolField(TEXT("IsMatchInProgress"), BaseGameMode->IsMatchInProgress());
		JsonObject->SetBoolField(TEXT("HasMatchEnded"), BaseGameMode->HasMatchEnded());
		JsonObject->SetNumberField(TEXT("NumTravellingPlayers"), BaseGameMode->NumTravellingPlayers);
		JsonObject->SetStringField(TEXT("NetworkNumber"), BaseGameMode->GetNetworkNumber());
		JsonObject->SetStringField(TEXT("MatchState"), BaseGameMode->GetMatchState().ToString());

		// UTBaseGameMode
		JsonObject->SetStringField(TEXT("ServerInstanceID"), BaseGameMode->ServerInstanceID);
		JsonObject->SetStringField(TEXT("ServerInstanceGUID"), BaseGameMode->ServerInstanceGUID.ToString()); // The Unique ID for this game instance.
		JsonObject->SetStringField(TEXT("ContextGUID"), BaseGameMode->ContextGUID.ToString()); // ?
		JsonObject->SetStringField(TEXT("ServerPassword"), BaseGameMode->ServerPassword);
		JsonObject->SetStringField(TEXT("SpectatePassword"), BaseGameMode->SpectatePassword);
		JsonObject->SetBoolField(TEXT("bRequirePassword"), BaseGameMode->bRequirePassword);
		JsonObject->SetStringField(TEXT("DisplayName"), BaseGameMode->DisplayName.ToString());
		JsonObject->SetNumberField(TEXT("MinAllowedRank"), BaseGameMode->MinAllowedRank);
		JsonObject->SetNumberField(TEXT("MaxAllowedRank"), BaseGameMode->MaxAllowedRank);
		JsonObject->SetBoolField(TEXT("bTrainingGround"), BaseGameMode->bTrainingGround);
		JsonObject->SetNumberField(TEXT("NumPlayers"), BaseGameMode->GetNumPlayers());
		JsonObject->SetNumberField(TEXT("NumMatches"), BaseGameMode->GetNumMatches()); // 1 if dedi server else [0, .., X] range for hubs/lobbies
		JsonObject->SetNumberField(TEXT("CurrentPlaylistId"), BaseGameMode->CurrentPlaylistId); // no idea what this is about
		JsonObject->SetBoolField(TEXT("bPrivateMatch"), BaseGameMode->bPrivateMatch);
		JsonObject->SetStringField(TEXT("RankedLeagueName"), BaseGameMode->GetRankedLeagueName()); // always empty for the moment
		JsonObject->SetBoolField(TEXT("SupportsInstantReplay"), BaseGameMode->SupportsInstantReplay());
		JsonObject->SetBoolField(TEXT("bIsLANGame"), BaseGameMode->bIsLANGame);

		if (BaseGameMode->IsLobbyServer())
		{
			AUTLobbyGameMode* LobbyGameMode;
			LobbyGameMode = GWorld->GetAuthGameMode<AUTLobbyGameMode>();

			if (LobbyGameMode)
			{
				JsonObject->SetStringField(TEXT("ServType"), TEXT("dedis"));
				// TODO get instance data
			}
		}
	}

	return JsonObject;
}

int handle_game_info(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data,
	size_t *upload_data_size, void **con_cls)
{
	int ret;
	struct MHD_Response *response;

	if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) {

		TSharedPtr<FJsonObject> matchInfoJSON = GetGameInfoJSON();

		FString JsonText;
		TSharedRef< TJsonWriter<> > Writer = TJsonWriterFactory<>::Create(&JsonText);
		FJsonSerializer::Serialize(matchInfoJSON.ToSharedRef(), Writer);

		const char* jsonChar = TCHAR_TO_UTF8(*JsonText);

		response = MHD_create_response_from_buffer(strlen(jsonChar),
			(void*)jsonChar, MHD_RESPMEM_PERSISTENT);
		MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, "application/json");

		ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
		MHD_destroy_response(response);
	}

	return ret;
}

// Server files from root folder
const FString wwwStr = FPaths::GamePluginsDir() + UT4WA_PLUGIN_FOLDER + "/" + UT4WA_WWW_FOLDER + "/";

int handle_serve_file(void *cls,
	struct MHD_Connection *connection,
	const char *url,
	const char *method, // GET / POST / PUT ...
	const char *version, // HTML version 1.1
	const char *upload_data,
	size_t *upload_data_size, void **con_cls)
{
	struct MHD_Response *response;
	char *path = NULL;
	int ret;

	// redirect from http://myserver:port/ to http://myserver:port/index.html
	if (strcmp(url, "/") == 0) {
		path = "index.html";
	}

	if (NULL == path) {
		path = new char[strlen(&url[1]) + 1];
		strcpy(path, &url[1]);
	}

	const char *www = TCHAR_TO_ANSI(*wwwStr);

	// calculate the required buffer size (also accounting for the null terminator):
	int bufferSize = strlen(www) + strlen(path) + 1;

	// allocate enough memory for the concatenated string:
	char* concatString = new char[bufferSize];

	// copy strings one and two over to the new buffer:
	strcpy(concatString, www);
	strcat(concatString, path);

	FILE* f;
	f = fopen(concatString, "rb");

	if (f != NULL) {
		// Determine file size
		fseek(f, 0, SEEK_END);
		size_t size = ftell(f);
		char* where = new char[size];
		rewind(f);
		fread(where, sizeof(char), size, f);

		response = MHD_create_response_from_buffer(strlen(where),
			(void*)where, MHD_RESPMEM_PERSISTENT);

		fclose(f);
		ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
	}
	else {
		const char *notExist = "File not found !";
		response = MHD_create_response_from_buffer(strlen(notExist),
			(void*)notExist, MHD_RESPMEM_PERSISTENT);
		ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
	}

	MHD_destroy_response(response);
	return ret;
}

int answer_to_connection(void *cls,
	struct MHD_Connection *connection,
	const char *url,
	const char *method, // GET / POST / PUT ...
	const char *version, // HTML version 1.1
	const char *upload_data,
	size_t *upload_data_size, void **con_cls)
{
	// TODO handle POST methods in the future
	if ((0 != strcmp(method, MHD_HTTP_METHOD_GET)) &&
		(0 != strcmp(method, MHD_HTTP_METHOD_HEAD)))
		return MHD_NO;

	// TODO check user authentification

	if (strcmp(url, "/gameinfo") == 0) {
		// TODO GET JSON GAME INFO
		return handle_game_info(cls, connection, url, method, version, upload_data, upload_data_size, con_cls);
	}
	else {
		return handle_serve_file(cls, connection, url, method, version, upload_data, upload_data_size, con_cls);
	}
}

void UUT4WebAdmin::StartMicroHttp()
{
	// SSL not working yet need some more investigation
	if (WebHttpsEnabled) {

		if (NULL == *WebServerCertificateFile || NULL == *WebServerKeyFile) {
			UE_LOG(UT4WebAdmin, Warning, TEXT("Server key or certificate file is not set."));
			return;
		}

		// openssl req -days 365 -out server.pem -new -x509 -key server.key
		FILE* fcert_file = fopen(TCHAR_TO_ANSI(*WebServerCertificateFile), "r");

		// openssl genrsa -out server.key 1024
		FILE* fkey_file = fopen(TCHAR_TO_ANSI(*WebServerKeyFile), "r");

		if (NULL != fcert_file && NULL != fkey_file) {

			fseek(fcert_file, 0, SEEK_END);
			size_t size = ftell(fcert_file);
			char* cert_pem = new char[size];
			rewind(fcert_file);
			fread(cert_pem, sizeof(char), size, fcert_file);

			fseek(fkey_file, 0, SEEK_END);
			size_t size2 = ftell(fkey_file);
			char* key_pem = new char[size2];
			rewind(fkey_file);
			fread(key_pem, sizeof(char), size2, fkey_file);

			daemon = MHD_start_daemon(MHD_USE_AUTO | MHD_USE_SELECT_INTERNALLY | MHD_USE_TLS | MHD_USE_DEBUG, WebHttpPort, NULL, NULL,
				&answer_to_connection, NULL,
				MHD_OPTION_HTTPS_MEM_KEY, key_pem,
				MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
				MHD_OPTION_END);
		}

		if (NULL != fcert_file) {
			fclose(fcert_file);
		}

		if (NULL != fkey_file) {
			fclose(fkey_file);
		}
	}
	else {
		UE_LOG(UT4WebAdmin, Log, TEXT("Starting HTTP server without SSL"));
		daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, WebHttpPort, NULL, NULL,
			&answer_to_connection, NULL, MHD_OPTION_END);
	}

	if (daemon == NULL) {
		UE_LOG(UT4WebAdmin, Warning, TEXT(" * * * * * * * * * * * * * * * * * * * * * * *"));
		UE_LOG(UT4WebAdmin, Warning, TEXT(" UT4WebAdmin failed to start http(s) server !"));
		UE_LOG(UT4WebAdmin, Warning, TEXT(" * * * * * * * * * * * * * * * * * * * * * * *"));
	}
	else {
		UE_LOG(UT4WebAdmin, Log, TEXT(" * * * * * * * * * * * * * * * * * * * * * * *"));
		UE_LOG(UT4WebAdmin, Log, TEXT(" UT4WebAdmin started at port: %i "), WebHttpPort);
		UE_LOG(UT4WebAdmin, Log, TEXT(" * * * * * * * * * * * * * * * * * * * * * * *"));
	}
}

void UUT4WebAdmin::Stop()
{
	if (NULL != daemon) {
		MHD_stop_daemon(daemon);
	}
}

void UUT4WebAdmin::Tick(float DeltaTime)
{
	//poll(MGServer, 1);
	// TODO
}

TStatId UUT4WebAdmin::GetStatId() const
{
	RETURN_QUICK_DECLARE_CYCLE_STAT(UUT4WebAdmin, STATGROUP_Tickables);
}

<|endoftext|>


<commit_before>#include "starlight_memory.h"

// Global memory stuff

void* MEM_CALL memory::slmalloc(size_t size) {
	return malloc(size);
}

void MEM_CALL memory::slfree(void* ptr) {
	return free(ptr);
}

void* MEM_CALL memory::slrealloc(void* ptr, size_t size) {
	return realloc(ptr, size);
}
<commit_msg>Wrap global new and delete<commit_after>#include "starlight_memory.h"

// Global memory stuff

void* MEM_CALL operator new(std::size_t n) throw()
{
	return memory::slmalloc(n);
}

void MEM_CALL operator delete(void * p) throw()
{
	return memory::slfree(p);
}

void* MEM_CALL memory::slmalloc(size_t size) {
	return malloc(size);
}

void MEM_CALL memory::slfree(void* ptr) {
	return free(ptr);
}

void* MEM_CALL memory::slrealloc(void* ptr, size_t size) {
	return realloc(ptr, size);
}
<|endoftext|>


<commit_before>// Filename: dxOcclusionQueryContext9.cxx
// Created by:  drose (04Jun07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "dxOcclusionQueryContext9.h"
#include "dxGraphicsStateGuardian9.h"
#include "pnotify.h"
#include "dcast.h"
#include "pStatTimer.h"

TypeHandle DXOcclusionQueryContext9::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function: GLOcclusionQueryContext::Destructor
//       Access: Public, Virtual
//  Description:
////////////////////////////////////////////////////////////////////
DXOcclusionQueryContext9::
~DXOcclusionQueryContext9() {
  _query->Release();
  _query = NULL;
}

////////////////////////////////////////////////////////////////////
//     Function: GLOcclusionQueryContext::is_answer_ready
//       Access: Public, Virtual
//  Description: Returns true if the query's answer is ready, false
//               otherwise.  If this returns false, the application
//               must continue to poll until it returns true.
//
//               It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
bool DXOcclusionQueryContext9::
is_answer_ready() const {
  DWORD result;
  HRESULT hr = _query->GetData(&result, sizeof(result), 0);
  return (hr != S_FALSE);
}

////////////////////////////////////////////////////////////////////
//     Function: GLOcclusionQueryContext::waiting_for_answer
//       Access: Public, Virtual
//  Description: Requests the graphics engine to expedite the pending
//               answer--the application is now waiting until the
//               answer is ready.
//
//               It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
void DXOcclusionQueryContext9::
waiting_for_answer() {
  DWORD result;
  PStatTimer timer(DXGraphicsStateGuardian9::_wait_occlusion_pcollector);
  HRESULT hr = _query->GetData(&result, sizeof(result), D3DGETDATA_FLUSH);
}

////////////////////////////////////////////////////////////////////
//     Function: GLOcclusionQueryContext::get_num_fragments
//       Access: Public, Virtual
//  Description: Returns the number of fragments (pixels) of the
//               specified geometry that passed the depth test.
//               If is_answer_ready() did not return true, this
//               function may block before it returns.
//
//               It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
int DXOcclusionQueryContext9::
get_num_fragments() const {
  DWORD result;
  HRESULT hr = _query->GetData(&result, sizeof(result), 0);
  if (hr == S_OK) {
    // The answer is ready now.
    return result;
  }

  {
    // The answer is not ready; this call will block.
    PStatTimer timer(DXGraphicsStateGuardian9::_wait_occlusion_pcollector);
    hr = _query->GetData(&result, sizeof(result), D3DGETDATA_FLUSH);
  }

  if (hr != S_OK) {
    // Some failure, e.g. devicelost.  Return a nonzero value as a
    // worst-case answer.
    return 1;
  }

  return result;
}
<commit_msg>wait for occlusion<commit_after>// Filename: dxOcclusionQueryContext9.cxx
// Created by:  drose (04Jun07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "dxOcclusionQueryContext9.h"
#include "dxGraphicsStateGuardian9.h"
#include "pnotify.h"
#include "dcast.h"
#include "pStatTimer.h"

TypeHandle DXOcclusionQueryContext9::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function: GLOcclusionQueryContext::Destructor
//       Access: Public, Virtual
//  Description:
////////////////////////////////////////////////////////////////////
DXOcclusionQueryContext9::
~DXOcclusionQueryContext9() {
  _query->Release();
  _query = NULL;
}

////////////////////////////////////////////////////////////////////
//     Function: GLOcclusionQueryContext::is_answer_ready
//       Access: Public, Virtual
//  Description: Returns true if the query's answer is ready, false
//               otherwise.  If this returns false, the application
//               must continue to poll until it returns true.
//
//               It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
bool DXOcclusionQueryContext9::
is_answer_ready() const {
  DWORD result;
  HRESULT hr = _query->GetData(&result, sizeof(result), 0);
  return (hr != S_FALSE);
}

////////////////////////////////////////////////////////////////////
//     Function: GLOcclusionQueryContext::waiting_for_answer
//       Access: Public, Virtual
//  Description: Requests the graphics engine to expedite the pending
//               answer--the application is now waiting until the
//               answer is ready.
//
//               It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
void DXOcclusionQueryContext9::
waiting_for_answer() {
  get_num_fragments();
}

////////////////////////////////////////////////////////////////////
//     Function: GLOcclusionQueryContext::get_num_fragments
//       Access: Public, Virtual
//  Description: Returns the number of fragments (pixels) of the
//               specified geometry that passed the depth test.
//               If is_answer_ready() did not return true, this
//               function may block before it returns.
//
//               It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
int DXOcclusionQueryContext9::
get_num_fragments() const {
  DWORD result;
  HRESULT hr = _query->GetData(&result, sizeof(result), 0);
  if (hr == S_OK) {
    // The answer is ready now.
    return result;
  }

  {
    // The answer is not ready; this call will block.
    PStatTimer timer(DXGraphicsStateGuardian9::_wait_occlusion_pcollector);
    while (hr == S_FALSE) {
      hr = _query->GetData(&result, sizeof(result), D3DGETDATA_FLUSH);
    }
  }

  if (FAILED(hr)) {
    // Some failure, e.g. devicelost.  Return a nonzero value as a
    // worst-case answer.
    dxgsg9_cat.info()
      << "occlusion query failed " << D3DERRORSTRING(hr);
    return 1;
  }

  return result;
}
<|endoftext|>