<commit_before>/*
 * Copyright (c) 2013 Nicholas Corgan (n.corgan@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */

#include <fstream>
#include <sstream>
#include <stdio.h>

#include <boost/format.hpp>

#include <pkmnsim/base_move.hpp>
#include <pkmnsim/base_pkmn.hpp>
#include <pkmnsim/enums.hpp>
#include <pkmnsim/paths.hpp>
#include <pkmnsim/spec_pkmn.hpp>
#include <pkmnsim/database/queries.hpp>

#include "pokelib/data_tables.h"
#include "sqlitecpp/SQLiteCPP.h"
#include "trainer_gen4impl.hpp"

using namespace std;

namespace pkmnsim
{
    trainer_gen4impl::trainer_gen4impl(SQLite::Database *import_db): trainer()
    {
        SQLite::Database pkmnsim_db(get_database_path().c_str());

        SQLite::Statement trainer_info_query(*import_db, "SELECT * FROM trainer_info");
        trainer_info_query.executeStep();

        from_game = trainer_info_query.getColumn(1);
        trainer_name = trainer_info_query.getColumnStr(2);
        trainer_id = trainer_info_query.getColumnStr(3);
        int party_size = trainer_info_query.getColumn(4);
        money = trainer_info_query.getColumn(5);

        party.clear();

        for(unsigned int i = 0; i < party_size; i++)
        {
            //Grab values from export database necessary to create spec_pkmn
            SQLite::Statement party_query(*import_db, str(boost::format("SELECT * FROM party WHERE id=%d")
                                                                        % i).c_str()
                                         );
            party_query.executeStep();

            int pkmn_id = party_query.getColumn(1);
            int species_id = party_query.getColumn(2);
            string nickname = party_query.getColumn(3);
            int level = party_query.getColumn(4);
            int item_held_id = party_query.getColumn(5);
            int move1_id = party_query.getColumn(6);
            int move2_id = party_query.getColumn(7);
            int move3_id = party_query.getColumn(8);
            int move4_id = party_query.getColumn(9);
            int HP = party_query.getColumn(10);
            int ATK = party_query.getColumn(11);
            int DEF = party_query.getColumn(12);
            int SATK = party_query.getColumn(13);
            int SDEF = party_query.getColumn(14);
            int SPD = party_query.getColumn(15);
            int evHP = party_query.getColumn(16);
            int evATK = party_query.getColumn(17);
            int evDEF = party_query.getColumn(18);
            int evSATK = party_query.getColumn(19);
            int evSDEF = party_query.getColumn(20);
            int evSPD = party_query.getColumn(21);
            int ivHP = party_query.getColumn(22);
            int ivATK = party_query.getColumn(23);
            int ivDEF = party_query.getColumn(24);
            int ivSATK = party_query.getColumn(25);
            int ivSDEF = party_query.getColumn(26);
            int ivSPD = party_query.getColumn(27);

            string identifier, item_held, move1, move2, move3, move4;
            identifier = pkmnsim_db.execAndGetStr(str(boost::format(
                                                      "SELECT name FROM pokemon_species_names WHERE pokemon_species_id=%d AND local_language_id=9")
                                                      % species_id).c_str(), "name"
                                                 );
            if(item_held_id == -1) item_held = "None";
            else
            {
                item_held = pkmnsim_db.execAndGetStr(str(boost::format(
                                                         "SELECT name FROM item_names WHERE item_id=%d")
                                                         % item_held_id).c_str(), "name"
                                                    );
            }
            move1 = pkmnsim_db.execAndGetStr(str(boost::format(
                                                 "SELECT name FROM move_names WHERE move_id=%d AND local_language_id=9")
                                                 % move1_id).c_str(), "name"
                                            );
            if(move2_id == -1) move2 = "None";
            else
            {
                move2 = pkmnsim_db.execAndGetStr(str(boost::format(
                                                     "SELECT name FROM move_names WHERE move_id=%d AND local_language_id=9")
                                                     % move2_id).c_str(), "name"
                                                );
            }
            if(move3_id == -1) move3 = "None";
            else
            {
                move3 = pkmnsim_db.execAndGetStr(str(boost::format(
                                                     "SELECT name FROM move_names WHERE move_id=%d AND local_language_id=9")
                                                     % move3_id).c_str(), "name"
                                                );
            }
            if(move4_id == -1) move4 = "None";
            else
            {
                move4 = pkmnsim_db.execAndGetStr(str(boost::format(
                                                     "SELECT name FROM move_names WHERE move_id=%d AND local_language_id=9")
                                                     % move4_id).c_str(), "name"
                                                );
            }

            spec_pkmn::sptr s_pkmn = spec_pkmn::make(identifier, 3, level, move1, move2, move3, move4, true);

            //Manually set other values
            s_pkmn->nickname = nickname;
            s_pkmn->HP = HP;
            s_pkmn->ATK = ATK;
            s_pkmn->DEF = DEF;
            s_pkmn->SATK = SATK;
            s_pkmn->SDEF = SDEF;
            s_pkmn->SPD = SPD;
            s_pkmn->evHP = evHP;
            s_pkmn->evATK = evATK;
            s_pkmn->evDEF = evDEF;
            s_pkmn->evSATK = evSATK;
            s_pkmn->evSDEF = evSDEF;
            s_pkmn->evSPD = evSPD;
            s_pkmn->ivHP = ivHP;
            s_pkmn->ivATK = ivATK;
            s_pkmn->ivDEF = ivDEF;
            s_pkmn->ivSATK = ivSATK;
            s_pkmn->ivSDEF = ivSDEF;
            s_pkmn->ivSPD = ivSPD;

            party.push_back(s_pkmn);
        }
    }

    trainer_gen4impl::trainer_gen4impl(string filename, int game): trainer()
    {
        from_game = game;
        size_t size, save_size;

        //Read save file and get size
        FILE* save_file;
        save_file = fopen(filename.c_str(), "r");
        fseek(save_file, 0, SEEK_END);
        size = ftell(save_file);
        rewind(save_file);

        //Determine which size game file actually is
        if(size >= 0x80000) save_size = 0x80000;
        else if(size > 0x40000 and size < 0x80000) save_size = 0x40000;
        else
        {
            cerr << "File is too small to be a proper save file." << endl;
            exit(EXIT_FAILURE);
        }
        save = new PokeLib::Save(size);
        int result = fread(save->data, 1, save_size, save_file);
        if(result != save_size)
        {
            cerr << "Problem reading save file." << endl;
            exit(EXIT_FAILURE);
        }
        fclose(save_file);

        save->parseRawSave();

        party.clear();
        PokeLib::Party* pokelib_party = save->getParty();
        cout << "party size: " << (unsigned int)(pokelib_party->count()) << endl;
        cout << "Save type: " << save->getSaveType() << endl;
        //PokeLib::Pokemon pokelib_pkmn = pokelib_party->getPokemon(0);
        /*for(unsigned int i = 0; i < (unsigned int)(pokelib_party->count()); i++)
        {
            PokeLib::Pokemon pokelib_pkmn = pokelib_party->getPokemon(i);
            party.push_back(convert_to_spec_pkmn(pokelib_pkmn));
        }*/
    }

    void trainer_gen4impl::export_to_file(string filename)
    {
        //Create or open file
        ofstream ofile;
        ofile.open(filename.c_str());
        ofile.flush();
        ofile.close();

        SQLite::Database pkmnsim_db(get_database_path().c_str());
        SQLite::Database export_db(filename.c_str(), SQLITE_OPEN_READWRITE);
        string pkmnsim_db_query_string, export_db_query_string;

        export_db.exec("PRAGMA foreign_keys=OFF; BEGIN TRANSACTION;");
        export_db_query_string = "CREATE TABLE trainer_info (\n"
                                 "id INTEGER NOT NULL,\n"
                                 "from_game INTEGER NOT NULL,\n"
                                 "trainer_name VARCHAR(7) NOT NULL,\n"
                                 "trainer_id VARCHAR(5) NOT NULL,\n"
                                 "party_size INTEGER NOT NULL,\n"
                                 "money INTEGER NOT NULL,\n"
                                 "PRIMARY KEY(id));";
        export_db.exec(export_db_query_string.c_str());
        export_db.exec(str(boost::format("INSERT INTO \"trainer_info\" VALUES(0,'%s','%s','%s',%d,%d)")
                                         % from_game
                                         % trainer_name
                                         % trainer_id
                                         % party.size()
                                         % money).c_str()
                      );
        export_db_query_string = "CREATE TABLE party (\n"
                                 "id INTEGER NOT NULL,\n"
                                 "pkmn_id INTEGER NOT NULL,\n"
                                 "species_id INTEGER NOT NULL,\n"
                                 "nickname VARCHAR(10) NOT NULL,\n"
                                 "level INTEGER NOT NULL,\n"
                                 "item_held_id INTEGER NOT NULL,\n"
                                 "move1_id INTEGER NOT NULL,\n"
                                 "move2_id INTEGER NOT NULL,\n"
                                 "move3_id INTEGER NOT NULL,\n"
                                 "move4_id INTEGER NOT NULL,\n"
                                 "HP INTEGER NOT NULL,\n"
                                 "ATK INTEGER NOT NULL,\n"
                                 "DEF INTEGER NOT NULL,\n"
                                 "SATK INTEGER NOT NULL,\n"
                                 "SDEF INTEGER NOT NULL,\n"
                                 "SPD INTEGER NOT NULL,\n"
                                 "evHP INTEGER NOT NULL,\n"
                                 "evATK INTEGER NOT NULL,\n"
                                 "evDEF INTEGER NOT NULL,\n"
                                 "evSATK INTEGER NOT NULL,\n"
                                 "evSDEF INTEGER NOT NULL,\n"
                                 "evSPD INTEGER NOT NULL,\n"
                                 "ivHP INTEGER NOT NULL,\n"
                                 "ivATK INTEGER NOT NULL,\n"
                                 "ivDEF INTEGER NOT NULL,\n"
                                 "ivSATK INTEGER NOT NULL,\n"
                                 "ivSDEF INTEGER NOT NULL,\n"
                                 "ivSPD INTEGER NOT NULL,\n"
                                 "PRIMARY KEY(id));";
        export_db.exec(export_db_query_string.c_str());
        for(unsigned int i = 0; i < party.size(); i++)
        {
            dict<string, int> stats = party[i]->get_stats();
            dict<string, int> EVs = party[i]->get_EVs();
            dict<string, int> IVs = party[i]->get_IVs();
            vla<base_move::sptr> moves = party[i]->get_moves();

            //Intermediary variables for ID's
            int pkmn_id, species_id, item_held_id, move1_id, move2_id, move3_id, move4_id;

            pkmn_id = get_pkmn_id(party[i]->get_base_pkmn());
            species_id = get_species_id(party[i]->get_base_pkmn());
            if(party[i]->get_held_item() == "None" or party[i]->get_held_item() == "Nothing") item_held_id = -1;
            else
            {
                item_held_id = pkmnsim_db.execAndGet(str(boost::format("SELECT item_id FROM item_names WHERE name='%s';")
                                                                       % party[i]->get_held_item()).c_str()
                                                    );
            }
            move1_id = pkmnsim_db.execAndGet(str(boost::format("SELECT move_id FROM move_names WHERE name='%s';")
                                                               % moves[0]->get_name()).c_str()
                                                );
            if(moves[1]->get_name() == "Struggle") move2_id = -1;
            else
            {
                move2_id = pkmnsim_db.execAndGet(str(boost::format("SELECT move_id FROM move_names WHERE name='%s';")
                                                                   % moves[1]->get_name()).c_str()
                                                );
            }
            if(moves[2]->get_name() == "Struggle") move3_id = -1;
            else
            {
                move3_id = pkmnsim_db.execAndGet(str(boost::format("SELECT move_id FROM move_names WHERE name='%s';")
                                                                   % moves[2]->get_name()).c_str()
                                                );
            }
            if(moves[3]->get_name() == "Struggle") move4_id = -1;
            else
            {
                move4_id = pkmnsim_db.execAndGet(str(boost::format("SELECT move_id FROM move_names WHERE name='%s';")
                                                                   % moves[3]->get_name()).c_str()
                                                );
            }
            export_db.exec(str(boost::format("INSERT INTO party VALUES(%d,%d,%d,'%s',%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);")
                                             % i % pkmn_id % species_id % party[i]->get_nickname() % party[i]->get_level()
                                             % item_held_id % move1_id % move2_id % move3_id % move4_id
                                             % stats["HP"] % stats["ATK"] % stats["DEF"] % stats["SATK"] % stats["SDEF"] % stats["SPD"]
                                             % EVs["HP"] % EVs["ATK"] % EVs["DEF"] % EVs["SATK"] % EVs["SDEF"] % EVs["SPD"]
                                             % IVs["HP"] % IVs["ATK"] % IVs["DEF"] % IVs["SATK"] % IVs["SDEF"] % IVs["SPD"]).c_str()
                          );
        }
        export_db.exec("COMMIT;");
    }

    spec_pkmn::sptr trainer_gen4impl::convert_to_spec_pkmn(PokeLib::Pokemon pokelib_pkmn)
    {
        string identifier, move1, move2, move3, move4;
        int level;

        cout << "Inside convert_to_spec_pkmn" << endl;

        cout << "size: " << sizeof(pokelib_pkmn) << endl;
        /*identifier = PokeLib::species[int(pokelib_pkmn.pkm->pkm.species)];
        level = int(pokelib_pkmn.getLevel());

        move1 = to_database_format(PokeLib::movelist[int(pokelib_pkmn.pkm->pkm.move[0])]);
        move2 = to_database_format(PokeLib::movelist[int(pokelib_pkmn.pkm->pkm.move[1])]);
        move3 = to_database_format(PokeLib::movelist[int(pokelib_pkmn.pkm->pkm.move[2])]);
        move4 = to_database_format(PokeLib::movelist[int(pokelib_pkmn.pkm->pkm.move[3])]);

        spec_pkmn::sptr s_pkmn = spec_pkmn::make(identifier, 4, level, move1, move2, move3, move4, true);

        cout << s_pkmn->get_info() << endl << endl;*/
    }
}
<commit_msg>trainer_gen4impl: no segfaults when converting PokeLib::Pokemon to pkmnsim::spec_pkmn<commit_after>/*
 * Copyright (c) 2013 Nicholas Corgan (n.corgan@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */

#include <fstream>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>

#include <boost/format.hpp>

#include <pkmnsim/base_move.hpp>
#include <pkmnsim/base_pkmn.hpp>
#include <pkmnsim/enums.hpp>
#include <pkmnsim/paths.hpp>
#include <pkmnsim/spec_pkmn.hpp>
#include <pkmnsim/database/queries.hpp>

#include "pokelib/data_tables.h"
#include "sqlitecpp/SQLiteCPP.h"
#include "trainer_gen4impl.hpp"

using namespace std;

namespace pkmnsim
{
    trainer_gen4impl::trainer_gen4impl(SQLite::Database *import_db): trainer()
    {
        SQLite::Database pkmnsim_db(get_database_path().c_str());

        SQLite::Statement trainer_info_query(*import_db, "SELECT * FROM trainer_info");
        trainer_info_query.executeStep();

        from_game = trainer_info_query.getColumn(1);
        trainer_name = trainer_info_query.getColumnStr(2);
        trainer_id = trainer_info_query.getColumnStr(3);
        int party_size = trainer_info_query.getColumn(4);
        money = trainer_info_query.getColumn(5);

        party.clear();

        for(unsigned int i = 0; i < party_size; i++)
        {
            //Grab values from export database necessary to create spec_pkmn
            SQLite::Statement party_query(*import_db, str(boost::format("SELECT * FROM party WHERE id=%d")
                                                                        % i).c_str()
                                         );
            party_query.executeStep();

            int pkmn_id = party_query.getColumn(1);
            int species_id = party_query.getColumn(2);
            string nickname = party_query.getColumn(3);
            int level = party_query.getColumn(4);
            int item_held_id = party_query.getColumn(5);
            int move1_id = party_query.getColumn(6);
            int move2_id = party_query.getColumn(7);
            int move3_id = party_query.getColumn(8);
            int move4_id = party_query.getColumn(9);
            int HP = party_query.getColumn(10);
            int ATK = party_query.getColumn(11);
            int DEF = party_query.getColumn(12);
            int SATK = party_query.getColumn(13);
            int SDEF = party_query.getColumn(14);
            int SPD = party_query.getColumn(15);
            int evHP = party_query.getColumn(16);
            int evATK = party_query.getColumn(17);
            int evDEF = party_query.getColumn(18);
            int evSATK = party_query.getColumn(19);
            int evSDEF = party_query.getColumn(20);
            int evSPD = party_query.getColumn(21);
            int ivHP = party_query.getColumn(22);
            int ivATK = party_query.getColumn(23);
            int ivDEF = party_query.getColumn(24);
            int ivSATK = party_query.getColumn(25);
            int ivSDEF = party_query.getColumn(26);
            int ivSPD = party_query.getColumn(27);

            string identifier, item_held, move1, move2, move3, move4;
            identifier = pkmnsim_db.execAndGetStr(str(boost::format(
                                                      "SELECT name FROM pokemon_species_names WHERE pokemon_species_id=%d AND local_language_id=9")
                                                      % species_id).c_str(), "name"
                                                 );
            if(item_held_id == -1) item_held = "None";
            else
            {
                item_held = pkmnsim_db.execAndGetStr(str(boost::format(
                                                         "SELECT name FROM item_names WHERE item_id=%d")
                                                         % item_held_id).c_str(), "name"
                                                    );
            }
            move1 = pkmnsim_db.execAndGetStr(str(boost::format(
                                                 "SELECT name FROM move_names WHERE move_id=%d AND local_language_id=9")
                                                 % move1_id).c_str(), "name"
                                            );
            if(move2_id == -1) move2 = "None";
            else
            {
                move2 = pkmnsim_db.execAndGetStr(str(boost::format(
                                                     "SELECT name FROM move_names WHERE move_id=%d AND local_language_id=9")
                                                     % move2_id).c_str(), "name"
                                                );
            }
            if(move3_id == -1) move3 = "None";
            else
            {
                move3 = pkmnsim_db.execAndGetStr(str(boost::format(
                                                     "SELECT name FROM move_names WHERE move_id=%d AND local_language_id=9")
                                                     % move3_id).c_str(), "name"
                                                );
            }
            if(move4_id == -1) move4 = "None";
            else
            {
                move4 = pkmnsim_db.execAndGetStr(str(boost::format(
                                                     "SELECT name FROM move_names WHERE move_id=%d AND local_language_id=9")
                                                     % move4_id).c_str(), "name"
                                                );
            }

            spec_pkmn::sptr s_pkmn = spec_pkmn::make(identifier, 3, level, move1, move2, move3, move4, true);

            //Manually set other values
            s_pkmn->nickname = nickname;
            s_pkmn->HP = HP;
            s_pkmn->ATK = ATK;
            s_pkmn->DEF = DEF;
            s_pkmn->SATK = SATK;
            s_pkmn->SDEF = SDEF;
            s_pkmn->SPD = SPD;
            s_pkmn->evHP = evHP;
            s_pkmn->evATK = evATK;
            s_pkmn->evDEF = evDEF;
            s_pkmn->evSATK = evSATK;
            s_pkmn->evSDEF = evSDEF;
            s_pkmn->evSPD = evSPD;
            s_pkmn->ivHP = ivHP;
            s_pkmn->ivATK = ivATK;
            s_pkmn->ivDEF = ivDEF;
            s_pkmn->ivSATK = ivSATK;
            s_pkmn->ivSDEF = ivSDEF;
            s_pkmn->ivSPD = ivSPD;

            party.push_back(s_pkmn);
        }
    }

    trainer_gen4impl::trainer_gen4impl(string filename, int game): trainer()
    {
        from_game = game;
        size_t size, save_size;

        //Read save file and get size
        FILE* save_file;
        save_file = fopen(filename.c_str(), "rb");
        fseek(save_file, 0, SEEK_END);
        size = ftell(save_file);
        rewind(save_file);

        //Determine which size game file actually is
        if(size >= 0x80000) save_size = 0x80000;
        else if(size > 0x40000 and size < 0x80000) save_size = 0x40000;
        else
        {
            cerr << "File is too small to be a proper save file." << endl;
            exit(EXIT_FAILURE);
        }
        save = new PokeLib::Save(size);
        int result = fread(save->data, 1, save_size, save_file);
        if(result != save_size)
        {
            cerr << "Problem reading save file." << endl;
            exit(EXIT_FAILURE);
        }
        fclose(save_file);

        if(!save->parseRawSave()) cout << "Couldn't load file." << endl;

        party.clear();
        PokeLib::Party* pokelib_party = save->getParty();
        for(unsigned int i = 0; i < (unsigned int)(pokelib_party->count()); i++)
        {
            PokeLib::Pokemon pokelib_pkmn = pokelib_party->getPokemon(i+1);
            party.push_back(convert_to_spec_pkmn(pokelib_pkmn));
        }
    }

    void trainer_gen4impl::export_to_file(string filename)
    {
        //Create or open file
        ofstream ofile;
        ofile.open(filename.c_str());
        ofile.flush();
        ofile.close();

        SQLite::Database pkmnsim_db(get_database_path().c_str());
        SQLite::Database export_db(filename.c_str(), SQLITE_OPEN_READWRITE);
        string pkmnsim_db_query_string, export_db_query_string;

        export_db.exec("PRAGMA foreign_keys=OFF; BEGIN TRANSACTION;");
        export_db_query_string = "CREATE TABLE trainer_info (\n"
                                 "id INTEGER NOT NULL,\n"
                                 "from_game INTEGER NOT NULL,\n"
                                 "trainer_name VARCHAR(7) NOT NULL,\n"
                                 "trainer_id VARCHAR(5) NOT NULL,\n"
                                 "party_size INTEGER NOT NULL,\n"
                                 "money INTEGER NOT NULL,\n"
                                 "PRIMARY KEY(id));";
        export_db.exec(export_db_query_string.c_str());
        export_db.exec(str(boost::format("INSERT INTO \"trainer_info\" VALUES(0,'%s','%s','%s',%d,%d)")
                                         % from_game
                                         % trainer_name
                                         % trainer_id
                                         % party.size()
                                         % money).c_str()
                      );
        export_db_query_string = "CREATE TABLE party (\n"
                                 "id INTEGER NOT NULL,\n"
                                 "pkmn_id INTEGER NOT NULL,\n"
                                 "species_id INTEGER NOT NULL,\n"
                                 "nickname VARCHAR(10) NOT NULL,\n"
                                 "level INTEGER NOT NULL,\n"
                                 "item_held_id INTEGER NOT NULL,\n"
                                 "move1_id INTEGER NOT NULL,\n"
                                 "move2_id INTEGER NOT NULL,\n"
                                 "move3_id INTEGER NOT NULL,\n"
                                 "move4_id INTEGER NOT NULL,\n"
                                 "HP INTEGER NOT NULL,\n"
                                 "ATK INTEGER NOT NULL,\n"
                                 "DEF INTEGER NOT NULL,\n"
                                 "SATK INTEGER NOT NULL,\n"
                                 "SDEF INTEGER NOT NULL,\n"
                                 "SPD INTEGER NOT NULL,\n"
                                 "evHP INTEGER NOT NULL,\n"
                                 "evATK INTEGER NOT NULL,\n"
                                 "evDEF INTEGER NOT NULL,\n"
                                 "evSATK INTEGER NOT NULL,\n"
                                 "evSDEF INTEGER NOT NULL,\n"
                                 "evSPD INTEGER NOT NULL,\n"
                                 "ivHP INTEGER NOT NULL,\n"
                                 "ivATK INTEGER NOT NULL,\n"
                                 "ivDEF INTEGER NOT NULL,\n"
                                 "ivSATK INTEGER NOT NULL,\n"
                                 "ivSDEF INTEGER NOT NULL,\n"
                                 "ivSPD INTEGER NOT NULL,\n"
                                 "PRIMARY KEY(id));";
        export_db.exec(export_db_query_string.c_str());
        for(unsigned int i = 0; i < party.size(); i++)
        {
            dict<string, int> stats = party[i]->get_stats();
            dict<string, int> EVs = party[i]->get_EVs();
            dict<string, int> IVs = party[i]->get_IVs();
            vla<base_move::sptr> moves = party[i]->get_moves();

            //Intermediary variables for ID's
            int pkmn_id, species_id, item_held_id, move1_id, move2_id, move3_id, move4_id;

            pkmn_id = party[i]->get_base_pkmn()->get_pokemon_id();;
            species_id = party[i]->get_base_pkmn()->get_species_id();
            if(party[i]->get_held_item() == "None" or party[i]->get_held_item() == "Nothing") item_held_id = -1;
            else
            {
                item_held_id = pkmnsim_db.execAndGet(str(boost::format("SELECT item_id FROM item_names WHERE name='%s';")
                                                                       % party[i]->get_held_item()).c_str()
                                                    );
            }
            move1_id = pkmnsim_db.execAndGet(str(boost::format("SELECT move_id FROM move_names WHERE name='%s';")
                                                               % moves[0]->get_name()).c_str()
                                                );
            if(moves[1]->get_name() == "Struggle") move2_id = -1;
            else
            {
                move2_id = pkmnsim_db.execAndGet(str(boost::format("SELECT move_id FROM move_names WHERE name='%s';")
                                                                   % moves[1]->get_name()).c_str()
                                                );
            }
            if(moves[2]->get_name() == "Struggle") move3_id = -1;
            else
            {
                move3_id = pkmnsim_db.execAndGet(str(boost::format("SELECT move_id FROM move_names WHERE name='%s';")
                                                                   % moves[2]->get_name()).c_str()
                                                );
            }
            if(moves[3]->get_name() == "Struggle") move4_id = -1;
            else
            {
                move4_id = pkmnsim_db.execAndGet(str(boost::format("SELECT move_id FROM move_names WHERE name='%s';")
                                                                   % moves[3]->get_name()).c_str()
                                                );
            }
            export_db.exec(str(boost::format("INSERT INTO party VALUES(%d,%d,%d,'%s',%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);")
                                             % i % pkmn_id % species_id % party[i]->get_nickname() % party[i]->get_level()
                                             % item_held_id % move1_id % move2_id % move3_id % move4_id
                                             % stats["HP"] % stats["ATK"] % stats["DEF"] % stats["SATK"] % stats["SDEF"] % stats["SPD"]
                                             % EVs["HP"] % EVs["ATK"] % EVs["DEF"] % EVs["SATK"] % EVs["SDEF"] % EVs["SPD"]
                                             % IVs["HP"] % IVs["ATK"] % IVs["DEF"] % IVs["SATK"] % IVs["SDEF"] % IVs["SPD"]).c_str()
                          );
        }
        export_db.exec("COMMIT;");
    }

    spec_pkmn::sptr trainer_gen4impl::convert_to_spec_pkmn(PokeLib::Pokemon pokelib_pkmn)
    {
        string identifier, move1, move2, move3, move4;
        int level;

        cout << "Inside convert_to_spec_pkmn" << endl;
        identifier = PokeLib::species[int(pokelib_pkmn.pkm->pkm.species)];
        level = int(pokelib_pkmn.getLevel());

        move1 = database::to_database_format(PokeLib::movelist[int(pokelib_pkmn.pkm->pkm.move[0])]);
        move2 = database::to_database_format(PokeLib::movelist[int(pokelib_pkmn.pkm->pkm.move[1])]);
        move3 = database::to_database_format(PokeLib::movelist[int(pokelib_pkmn.pkm->pkm.move[2])]);
        move4 = database::to_database_format(PokeLib::movelist[int(pokelib_pkmn.pkm->pkm.move[3])]);

        spec_pkmn::sptr s_pkmn = spec_pkmn::make(identifier, 4, level, move1, move2, move3, move4, true);

        return s_pkmn;
    }
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <ctime>
#include <fstream>
#include <iostream>
#include <sstream>
#include <openssl/hmac.h>
#include <tw/authenticator.h>
#include <tw/base64.h>
#include <tw/oauth.h>
#include <utils.h>

static const std::string INSTRUCTIONS = "In order to allow LynxBot to use your "
"Twitter account, you must register it as a Twitter app. This is done by "
"signing into https://apps.twitter.com and clicking the \"Create New App\" "
"button. Give your app a unique name (e.g. lynxbot-TWITTERNAME), fill in the "
"rest of the form and agree to the Developer Agreement.\n\nOnce you submit the "
"form you will be redirected to your app's overview page. You can change the "
"access level to read only (LynxBot does not do any writing).\nNext, click the "
"Keys and Access Tokens tab. Under \"Your Access Token\", click Create my "
"access token to generate access tokens for LynxBot.\n\nYou will now see four "
"tokens on the page:\nConsumer Key\nConsumer Secret\nAccess Token\nAccess "
"Token Secret\nYou will need to enter them into this console.\n\nWARNING: "
"Your access tokens will be stored in plaintext.\n";

static void getString(std::string &target);

tw::Authenticator::Authenticator()
{
	m_configpath = utils::configdir() + utils::config("twitter");
	if (readKeys() == -1)
		interactiveSetup();
}

/* siggen: generate an oauth signature for a twitter api request */
void tw::Authenticator::siggen(const std::string &method, const std::string &URL,
		const param_vec &head_params, const param_vec &body_params)
{
	/* get ouath data */
	m_data.c_key = m_consumerkey;
	m_data.nonce = noncegen();
	m_data.sig_method = "HMAC-SHA1";
	m_data.timestamp = std::to_string(time(nullptr));
	m_data.token = m_token;
	m_data.version = "1.0";

	/* generate the base string */
	std::vector<std::string> enc_params;
	for (auto p : head_params)
		enc_params.push_back(pencode(p.first) + "=" + pencode(p.second));
	for (auto p : body_params)
		enc_params.push_back(pencode(p.first) + "=" + pencode(p.second));
	enc_params.push_back("oauth_consumer_key=" + m_data.c_key);
	enc_params.push_back("oauth_nonce=" + m_data.nonce);
	enc_params.push_back("oauth_signature_method=" + m_data.sig_method);
	enc_params.push_back("oauth_timestamp=" + m_data.timestamp);
	enc_params.push_back("oauth_token=" + m_data.token);
	enc_params.push_back("oauth_version=" + m_data.version);

	std::sort(enc_params.begin(), enc_params.end());

	std::string param_str;
	for (unsigned i = 0; i < enc_params.size(); ++i) {
		param_str += enc_params[i];
		if (i != enc_params.size() - 1)
			param_str += '&';
	}

	std::string base_str;
	base_str += method + "&";
	base_str += pencode(URL) + "&";
	base_str += pencode(param_str);

	/* get the signing key */
	std::string signing_key;
	signing_key += pencode(m_consumersecret) + "&";
	signing_key += pencode(m_tokensecret);

	unsigned char digest[1024];
	unsigned int digest_len;
	HMAC(EVP_sha1(), signing_key.c_str(), signing_key.length(),
			(unsigned char *)base_str.c_str(), base_str.length(),
			digest, &digest_len);
	std::cout << std::endl;

	m_data.sig = base64_enc((char *)digest, digest_len);
}

struct tw::Authenticator::oauth_data tw::Authenticator::authData()
{
	return m_data;
}

/* readKeys: read twitter keys from file (will be encrypted eventually) */
int tw::Authenticator::readKeys()
{
	std::ifstream reader(m_configpath);
	std::string line;
	int lnum = 0;

	if (!reader.is_open())
		return -1;
	while (std::getline(reader, line)) {
		switch (++lnum) {
		case 1:
			m_consumerkey = line;
			break;
		case 2:
			m_consumersecret = line;
			break;
		case 3:
			m_token = line;
			break;
		case 4:
			m_tokensecret = line;
			break;
		default:
			return 1;
		}
	}
	if (lnum != 4)
		return 1;

	return 0;
}

/* interactiveSetup: obtain access tokens from user */
void tw::Authenticator::interactiveSetup()
{
	char c = '\0';
	std::cout << m_configpath << " was not found." << std::endl;
	std::cout << "Would you like to set up LynxBot to use Twitter? (y/n) ";
	std::ofstream writer(m_configpath);

	while (c != 'y' && c != 'n')
		std::cin >> c;
	if (c == 'n')
		return;

	std::cout << INSTRUCTIONS << std::endl;
	std::cout << "Would you like to proceed? (y/n) ";

	c = '\0';
	while (c != 'y' && c != 'n')
		std::cin >> c;
	if (c == 'n')
		return;

	std::cout << "Enter your Consumer Key:" << std::endl;
	getString(m_consumerkey);
	std::cout << "Enter your Consumer Secret:" << std::endl;
	getString(m_consumersecret);
	std::cout << "Enter your Access Token:" << std::endl;
	getString(m_token);
	std::cout << "Enter your Access Token Secret:" << std::endl;
	getString(m_tokensecret);

	writer << m_consumerkey << std::endl << m_consumersecret << std::endl
		<< m_token << std::endl << m_tokensecret << std::endl;
	writer.close();

	std::cout << "Your tokens have been saved to " << m_configpath
		<< std::endl;
	std::cin.get();
}

/* getString: read a string from stdin */
static void getString(std::string &target)
{
	std::string line;
	while (true) {
		std::getline(std::cin, line);
		if (!line.empty()) break;
		std::cout << "Invalid string, try again:" << std::endl;
	}
	target = line;
}
<commit_msg>Remove trailing whitespace<commit_after>#include <algorithm>
#include <ctime>
#include <fstream>
#include <iostream>
#include <sstream>
#include <openssl/hmac.h>
#include <tw/authenticator.h>
#include <tw/base64.h>
#include <tw/oauth.h>
#include <utils.h>

static const std::string INSTRUCTIONS = "In order to allow LynxBot to use your "
"Twitter account, you must register it as a Twitter app. This is done by "
"signing into https://apps.twitter.com and clicking the \"Create New App\" "
"button. Give your app a unique name (e.g. lynxbot-TWITTERNAME), fill in the "
"rest of the form and agree to the Developer Agreement.\n\nOnce you submit the "
"form you will be redirected to your app's overview page. You can change the "
"access level to read only (LynxBot does not do any writing).\nNext, click the "
"Keys and Access Tokens tab. Under \"Your Access Token\", click Create my "
"access token to generate access tokens for LynxBot.\n\nYou will now see four "
"tokens on the page:\nConsumer Key\nConsumer Secret\nAccess Token\nAccess "
"Token Secret\nYou will need to enter them into this console.\n\nWARNING: "
"Your access tokens will be stored in plaintext.\n";

static void getString(std::string &target);

tw::Authenticator::Authenticator()
{
	m_configpath = utils::configdir() + utils::config("twitter");
	if (readKeys() == -1)
		interactiveSetup();
}

/* siggen: generate an oauth signature for a twitter api request */
void tw::Authenticator::siggen(const std::string &method, const std::string &URL,
		const param_vec &head_params, const param_vec &body_params)
{
	/* get ouath data */
	m_data.c_key = m_consumerkey;
	m_data.nonce = noncegen();
	m_data.sig_method = "HMAC-SHA1";
	m_data.timestamp = std::to_string(time(nullptr));
	m_data.token = m_token;
	m_data.version = "1.0";

	/* generate the base string */
	std::vector<std::string> enc_params;
	for (auto p : head_params)
		enc_params.push_back(pencode(p.first) + "=" + pencode(p.second));
	for (auto p : body_params)
		enc_params.push_back(pencode(p.first) + "=" + pencode(p.second));
	enc_params.push_back("oauth_consumer_key=" + m_data.c_key);
	enc_params.push_back("oauth_nonce=" + m_data.nonce);
	enc_params.push_back("oauth_signature_method=" + m_data.sig_method);
	enc_params.push_back("oauth_timestamp=" + m_data.timestamp);
	enc_params.push_back("oauth_token=" + m_data.token);
	enc_params.push_back("oauth_version=" + m_data.version);

	std::sort(enc_params.begin(), enc_params.end());

	std::string param_str;
	for (unsigned i = 0; i < enc_params.size(); ++i) {
		param_str += enc_params[i];
		if (i != enc_params.size() - 1)
			param_str += '&';
	}

	std::string base_str;
	base_str += method + "&";
	base_str += pencode(URL) + "&";
	base_str += pencode(param_str);

	/* get the signing key */
	std::string signing_key;
	signing_key += pencode(m_consumersecret) + "&";
	signing_key += pencode(m_tokensecret);

	unsigned char digest[1024];
	unsigned int digest_len;
	HMAC(EVP_sha1(), signing_key.c_str(), signing_key.length(),
			(unsigned char *)base_str.c_str(), base_str.length(),
			digest, &digest_len);
	std::cout << std::endl;

	m_data.sig = base64_enc((char *)digest, digest_len);
}

struct tw::Authenticator::oauth_data tw::Authenticator::authData()
{
	return m_data;
}

/* readKeys: read twitter keys from file (will be encrypted eventually) */
int tw::Authenticator::readKeys()
{
	std::ifstream reader(m_configpath);
	std::string line;
	int lnum = 0;

	if (!reader.is_open())
		return -1;
	while (std::getline(reader, line)) {
		switch (++lnum) {
		case 1:
			m_consumerkey = line;
			break;
		case 2:
			m_consumersecret = line;
			break;
		case 3:
			m_token = line;
			break;
		case 4:
			m_tokensecret = line;
			break;
		default:
			return 1;
		}
	}
	if (lnum != 4)
		return 1;

	return 0;
}

/* interactiveSetup: obtain access tokens from user */
void tw::Authenticator::interactiveSetup()
{
	char c = '\0';
	std::cout << m_configpath << " was not found." << std::endl;
	std::cout << "Would you like to set up LynxBot to use Twitter? (y/n) ";
	std::ofstream writer(m_configpath);

	while (c != 'y' && c != 'n')
		std::cin >> c;
	if (c == 'n')
		return;

	std::cout << INSTRUCTIONS << std::endl;
	std::cout << "Would you like to proceed? (y/n) ";

	c = '\0';
	while (c != 'y' && c != 'n')
		std::cin >> c;
	if (c == 'n')
		return;

	std::cout << "Enter your Consumer Key:" << std::endl;
	getString(m_consumerkey);
	std::cout << "Enter your Consumer Secret:" << std::endl;
	getString(m_consumersecret);
	std::cout << "Enter your Access Token:" << std::endl;
	getString(m_token);
	std::cout << "Enter your Access Token Secret:" << std::endl;
	getString(m_tokensecret);

	writer << m_consumerkey << std::endl << m_consumersecret << std::endl
		<< m_token << std::endl << m_tokensecret << std::endl;
	writer.close();

	std::cout << "Your tokens have been saved to " << m_configpath
		<< std::endl;
	std::cin.get();
}

/* getString: read a string from stdin */
static void getString(std::string &target)
{
	std::string line;
	while (true) {
		std::getline(std::cin, line);
		if (!line.empty()) break;
		std::cout << "Invalid string, try again:" << std::endl;
	}
	target = line;
}
<|endoftext|>


<commit_before>/**
 * @file
 */
#if ENABLE_LAZY_DEEP_CLONE
#include "libbirch/LazyContext.hpp"

#include "libbirch/SwapClone.hpp"
#include "libbirch/SwapContext.hpp"

libbirch::LazyAny* libbirch::LazyContext::get(LazyAny* o) {
  assert(o->isFrozen());
  LazyAny* prev = nullptr;
  LazyAny* next = o;
  l.write();
  do {
    prev = next;
    next = m.get(prev, prev);
  } while (next != prev && next->isFrozen());
  if (next->isFrozen()) {
    next = copy(next);
  }
  l.unwrite();
  return next;
}

libbirch::LazyAny* libbirch::LazyContext::pull(LazyAny* o) {
  assert(o->isFrozen());
  LazyAny* prev = nullptr;
  LazyAny* next = o;
  l.read();
  do {
    prev = next;
    next = m.get(prev, prev);
  } while (next != prev && next->isFrozen());
  l.unread();
  return next;
}

libbirch::LazyAny* libbirch::LazyContext::copy(LazyAny* o) {
  assert(o->isFrozen());
  SwapClone swapClone(true);
  SwapContext swapContext(this);
  auto cloned = o->clone_();
  if (!o->isSingle()) {
    cloned->memoize();
    frozen.store(false);  // no longer frozen, as will have new entry
    m.put(o, cloned);
  }
  return cloned;
}

void libbirch::LazyContext::freeze() {
  if (!frozen.exchange(true)) {
    l.read();
    m.freeze();
    l.unread();
  }
}

#endif
<commit_msg>Minor improvement to LazyContext to avoid reading atomic twice.<commit_after>/**
 * @file
 */
#if ENABLE_LAZY_DEEP_CLONE
#include "libbirch/LazyContext.hpp"

#include "libbirch/SwapClone.hpp"
#include "libbirch/SwapContext.hpp"

libbirch::LazyAny* libbirch::LazyContext::get(LazyAny* o) {
  assert(o->isFrozen());
  LazyAny* prev = nullptr;
  LazyAny* next = o;
  bool frozen = true;
  l.write();
  do {
    prev = next;
    next = m.get(prev);
    if (next) {
      frozen = next->isFrozen();
    }
  } while (frozen && next);
  if (!next) {
	  next = prev;
	}
  if (frozen) {
    next = copy(next);
  }
  l.unwrite();
  return next;
}

libbirch::LazyAny* libbirch::LazyContext::pull(LazyAny* o) {
  assert(o->isFrozen());
  LazyAny* prev = nullptr;
  LazyAny* next = o;
  bool frozen = true;
  l.read();
  do {
    prev = next;
    next = m.get(prev);
    if (next) {
      frozen = next->isFrozen();
    }
  } while (frozen && next);
  if (!next) {
	  next = prev;
	}
  l.unread();
  return next;
}

libbirch::LazyAny* libbirch::LazyContext::copy(LazyAny* o) {
  assert(o->isFrozen());
  SwapClone swapClone(true);
  SwapContext swapContext(this);
  auto cloned = o->clone_();
  if (!o->isSingle()) {
    cloned->memoize();
    frozen.store(false);  // no longer frozen, as will have new entry
    m.put(o, cloned);
  }
  return cloned;
}

void libbirch::LazyContext::freeze() {
  if (!frozen.exchange(true)) {
    l.read();
    m.freeze();
    l.unread();
  }
}

#endif
<|endoftext|>


<commit_before>#include <stdio.h>

#include "mem_tracker.h"
#include "concurrency.h"
#include "debugger.h"

atomic_number<size_t> alloc_objs;
atomic_number<size_t> alloc_bytes;

#ifdef ENABLE_MEM_TRACE

class print_mem_tracker_task: public debug_task
{
public:
	void run() {
		printf("alloc %ld objs and %ld bytes\n", alloc_objs.get(),
				alloc_bytes.get());
	}
};

void init_mem_tracker()
{
	printf("register mem_tracker to debug\n");
	debug.register_task(new print_mem_tracker_task());
}

void *operator new(size_t n) throw (std::bad_alloc)
{
	alloc_objs.inc(1);
	alloc_bytes.inc(n);
	void *p = malloc(n + sizeof(size_t));
	size_t *size = (size_t *) p;
	*size = n;

	return (void *) (size + 1);
}

void operator delete(void *p) throw ()
{
	alloc_objs.dec(1);
	size_t *size = (size_t *) (((char *) p) - sizeof(size_t));
	alloc_bytes.dec(*size);
	free(size);
}

void *operator new[](size_t n) throw (std::bad_alloc)
{
	alloc_objs.inc(1);
	alloc_bytes.inc(n);
	void *p = malloc(n + sizeof(size_t));
	size_t *size = (size_t *) p;
	*size = n;

	return (void *) (size + 1);
}

void operator delete[](void *p) throw ()
{
	alloc_objs.dec(1);
	size_t *size = (size_t *) (((char *) p) - sizeof(size_t));
	alloc_bytes.dec(*size);
	free(size);
}

#endif

size_t get_alloc_objs()
{
	return alloc_objs.get();
}

size_t get_alloc_bytes()
{
	return alloc_bytes.get();
}
<commit_msg>[SAFS]: mem_tracker needs to handle NULL pointers.<commit_after>#include <stdio.h>

#include "mem_tracker.h"
#include "concurrency.h"
#include "debugger.h"

atomic_number<size_t> alloc_objs;
atomic_number<size_t> alloc_bytes;

#ifdef ENABLE_MEM_TRACE

class print_mem_tracker_task: public debug_task
{
public:
	void run() {
		printf("alloc %ld objs and %ld bytes\n", alloc_objs.get(),
				alloc_bytes.get());
	}
};

void init_mem_tracker()
{
	printf("register mem_tracker to debug\n");
	debug.register_task(new print_mem_tracker_task());
}

void *operator new(size_t n) throw (std::bad_alloc)
{
	alloc_objs.inc(1);
	alloc_bytes.inc(n);
	void *p = malloc(n + sizeof(size_t));
	size_t *size = (size_t *) p;
	*size = n;

	return (void *) (size + 1);
}

void operator delete(void *p) throw ()
{
	if (p == NULL)
		return;

	alloc_objs.dec(1);
	size_t *size = (size_t *) (((char *) p) - sizeof(size_t));
	alloc_bytes.dec(*size);
	free(size);
}

void *operator new[](size_t n) throw (std::bad_alloc)
{
	alloc_objs.inc(1);
	alloc_bytes.inc(n);
	void *p = malloc(n + sizeof(size_t));
	size_t *size = (size_t *) p;
	*size = n;

	return (void *) (size + 1);
}

void operator delete[](void *p) throw ()
{
	if (p == NULL)
		return;

	alloc_objs.dec(1);
	size_t *size = (size_t *) (((char *) p) - sizeof(size_t));
	alloc_bytes.dec(*size);
	free(size);
}

#endif

size_t get_alloc_objs()
{
	return alloc_objs.get();
}

size_t get_alloc_bytes()
{
	return alloc_bytes.get();
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file BlockInfo.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include <libethcore/CommonEth.h>
#include "ProofOfWork.h"
#include "Exceptions.h"
#include "BlockInfo.h"
using namespace std;
using namespace dev;
using namespace dev::eth;

u256 dev::eth::c_genesisDifficulty = (u256)1 << 11;

BlockInfo::BlockInfo(): timestamp(Invalid256)
{
}

BlockInfo::BlockInfo(bytesConstRef _block, bool _checkNonce)
{
	populate(_block, _checkNonce);
}

void BlockInfo::setEmpty()
{
	parentHash = h256();
	sha3Uncles = EmptyListSHA3;
	coinbaseAddress = Address();
	stateRoot = EmptyTrie;
	transactionsRoot = EmptyTrie;
	receiptsRoot = EmptyTrie;
	logBloom = LogBloom();
	difficulty = 0;
	number = 0;
	gasLimit = 0;
	gasUsed = 0;
	timestamp = 0;
	extraData.clear();
	seedHash = h256();
	mixBytes = h256();
	nonce = Nonce();
	hash = headerHash(WithNonce);
}

BlockInfo BlockInfo::fromHeader(bytesConstRef _block)
{
	BlockInfo ret;
	ret.populateFromHeader(RLP(_block));
	return ret;
}

h256 BlockInfo::headerHash(IncludeNonce _n) const
{
	RLPStream s;
	streamRLP(s, _n);
	return sha3(s.out());
}

void BlockInfo::streamRLP(RLPStream& _s, IncludeNonce _n) const
{
	_s.appendList(_n == WithNonce ? 16 : 14)
		<< parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot << receiptsRoot << logBloom
		<< difficulty << number << gasLimit << gasUsed << timestamp << extraData << seedHash;
	if (_n == WithNonce)
		_s << mixBytes << nonce;
}

h256 BlockInfo::headerHash(bytesConstRef _block)
{
	return sha3(RLP(_block)[0].data());
}

void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
{
	hash = dev::sha3(_header.data());

	int field = 0;
	try
	{
		parentHash = _header[field = 0].toHash<h256>();
		sha3Uncles = _header[field = 1].toHash<h256>();
		coinbaseAddress = _header[field = 2].toHash<Address>();
		stateRoot = _header[field = 3].toHash<h256>();
		transactionsRoot = _header[field = 4].toHash<h256>();
		receiptsRoot = _header[field = 5].toHash<h256>();
		logBloom = _header[field = 6].toHash<LogBloom>();
		difficulty = _header[field = 7].toInt<u256>();
		number = _header[field = 8].toInt<u256>();
		gasLimit = _header[field = 9].toInt<u256>();
		gasUsed = _header[field = 10].toInt<u256>();
		timestamp = _header[field = 11].toInt<u256>();
		extraData = _header[field = 12].toBytes();
		seedHash = _header[field = 13].toHash<h256>();
		mixBytes = _header[field = 14].toHash<h256>();
		nonce = _header[field = 15].toHash<Nonce>();
	}

	catch (Exception const& _e)
	{
		_e << errinfo_name("invalid block header format") << BadFieldError(field, toHex(_header[field].data().toBytes()));
		throw;
	}

	// check it hashes according to proof of work or that it's the genesis block.
	if (_checkNonce && parentHash && !ProofOfWork::verify(*this))
		BOOST_THROW_EXCEPTION(InvalidBlockNonce(headerHash(WithoutNonce), nonce, difficulty));

	if (gasUsed > gasLimit)
		BOOST_THROW_EXCEPTION(TooMuchGasUsed());

	if (number && extraData.size() > 1024)
		BOOST_THROW_EXCEPTION(ExtraDataTooBig());
}

void BlockInfo::populate(bytesConstRef _block, bool _checkNonce)
{
	RLP root(_block);
	RLP header = root[0];

	if (!header.isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(0, header.data()) << errinfo_comment("block header needs to be a list"));
	populateFromHeader(header, _checkNonce);

	if (!root[1].isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(1, root[1].data()));
	if (!root[2].isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(2, root[2].data()));
}

void BlockInfo::verifyInternals(bytesConstRef _block) const
{
	RLP root(_block);

	u256 mgp = (u256)-1;

	OverlayDB db;
	GenericTrieDB<OverlayDB> t(&db);
	t.init();
	unsigned i = 0;
	for (auto const& tr: root[1])
	{
		bytes k = rlp(i);
		t.insert(&k, tr.data());
		u256 gasprice = tr[1].toInt<u256>();
		mgp = min(mgp, gasprice); // the minimum gas price is not used for anything //TODO delete?
		++i;
	}
	if (transactionsRoot != t.root())
		BOOST_THROW_EXCEPTION(InvalidTransactionsHash(t.root(), transactionsRoot));

	if (sha3Uncles != sha3(root[2].data()))
		BOOST_THROW_EXCEPTION(InvalidUnclesHash());
}

void BlockInfo::populateFromParent(BlockInfo const& _parent)
{
	stateRoot = _parent.stateRoot;
	parentHash = _parent.hash;
	number = _parent.number + 1;
	gasLimit = calculateGasLimit(_parent);
	gasUsed = 0;
	difficulty = calculateDifficulty(_parent);
	seedHash = number % 30 == 0 ? sha3(_parent.seedHash.asBytes() /*+ _parent.hash.asBytes()*/) : _parent.seedHash;
}

u256 BlockInfo::calculateGasLimit(BlockInfo const& _parent) const
{
	if (!parentHash)
		return 1000000;
	else
		return max<u256>(125000, (_parent.gasLimit * (1024 - 1) + (_parent.gasUsed * 6 / 5)) / 1024);
}

u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const
{
	if (!parentHash)
		return c_genesisDifficulty;
	else
		return max<u256>(2048, timestamp >= _parent.timestamp + (c_protocolVersion == 49 ? 5 : 8) ? _parent.difficulty - (_parent.difficulty / 2048) : (_parent.difficulty + (_parent.difficulty / 2048)));
}

template <class N> inline N diff(N const& _a, N const& _b) { return max(_a, _b) - min(_a, _b); }

void BlockInfo::verifyParent(BlockInfo const& _parent) const
{	// Check difficulty is correct given the two timestamps.
	if (difficulty != calculateDifficulty(_parent))
		BOOST_THROW_EXCEPTION(InvalidDifficulty());

	if (diff(gasLimit, _parent.gasLimit) <= _parent.gasLimit / 1024)
		BOOST_THROW_EXCEPTION(InvalidGasLimit(gasLimit, calculateGasLimit(_parent), diff(gasLimit, _parent.gasLimit), _parent.gasLimit / 1024));

	// Check timestamp is after previous timestamp.
	if (parentHash)
	{
		if (parentHash != _parent.hash)
			BOOST_THROW_EXCEPTION(InvalidParentHash());

		if (timestamp <= _parent.timestamp)
			BOOST_THROW_EXCEPTION(InvalidTimestamp());

		if (number != _parent.number + 1)
			BOOST_THROW_EXCEPTION(InvalidNumber());
	}
}
<commit_msg>fix blockGasLimit bug : 1024 -> 2048<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file BlockInfo.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include <libethcore/CommonEth.h>
#include "ProofOfWork.h"
#include "Exceptions.h"
#include "BlockInfo.h"
using namespace std;
using namespace dev;
using namespace dev::eth;

u256 dev::eth::c_genesisDifficulty = (u256)1 << 11;

BlockInfo::BlockInfo(): timestamp(Invalid256)
{
}

BlockInfo::BlockInfo(bytesConstRef _block, bool _checkNonce)
{
	populate(_block, _checkNonce);
}

void BlockInfo::setEmpty()
{
	parentHash = h256();
	sha3Uncles = EmptyListSHA3;
	coinbaseAddress = Address();
	stateRoot = EmptyTrie;
	transactionsRoot = EmptyTrie;
	receiptsRoot = EmptyTrie;
	logBloom = LogBloom();
	difficulty = 0;
	number = 0;
	gasLimit = 0;
	gasUsed = 0;
	timestamp = 0;
	extraData.clear();
	seedHash = h256();
	mixBytes = h256();
	nonce = Nonce();
	hash = headerHash(WithNonce);
}

BlockInfo BlockInfo::fromHeader(bytesConstRef _block)
{
	BlockInfo ret;
	ret.populateFromHeader(RLP(_block));
	return ret;
}

h256 BlockInfo::headerHash(IncludeNonce _n) const
{
	RLPStream s;
	streamRLP(s, _n);
	return sha3(s.out());
}

void BlockInfo::streamRLP(RLPStream& _s, IncludeNonce _n) const
{
	_s.appendList(_n == WithNonce ? 16 : 14)
		<< parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot << receiptsRoot << logBloom
		<< difficulty << number << gasLimit << gasUsed << timestamp << extraData << seedHash;
	if (_n == WithNonce)
		_s << mixBytes << nonce;
}

h256 BlockInfo::headerHash(bytesConstRef _block)
{
	return sha3(RLP(_block)[0].data());
}

void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
{
	hash = dev::sha3(_header.data());

	int field = 0;
	try
	{
		parentHash = _header[field = 0].toHash<h256>();
		sha3Uncles = _header[field = 1].toHash<h256>();
		coinbaseAddress = _header[field = 2].toHash<Address>();
		stateRoot = _header[field = 3].toHash<h256>();
		transactionsRoot = _header[field = 4].toHash<h256>();
		receiptsRoot = _header[field = 5].toHash<h256>();
		logBloom = _header[field = 6].toHash<LogBloom>();
		difficulty = _header[field = 7].toInt<u256>();
		number = _header[field = 8].toInt<u256>();
		gasLimit = _header[field = 9].toInt<u256>();
		gasUsed = _header[field = 10].toInt<u256>();
		timestamp = _header[field = 11].toInt<u256>();
		extraData = _header[field = 12].toBytes();
		seedHash = _header[field = 13].toHash<h256>();
		mixBytes = _header[field = 14].toHash<h256>();
		nonce = _header[field = 15].toHash<Nonce>();
	}

	catch (Exception const& _e)
	{
		_e << errinfo_name("invalid block header format") << BadFieldError(field, toHex(_header[field].data().toBytes()));
		throw;
	}

	// check it hashes according to proof of work or that it's the genesis block.
	if (_checkNonce && parentHash && !ProofOfWork::verify(*this))
		BOOST_THROW_EXCEPTION(InvalidBlockNonce(headerHash(WithoutNonce), nonce, difficulty));

	if (gasUsed > gasLimit)
		BOOST_THROW_EXCEPTION(TooMuchGasUsed());

	if (number && extraData.size() > 1024)
		BOOST_THROW_EXCEPTION(ExtraDataTooBig());
}

void BlockInfo::populate(bytesConstRef _block, bool _checkNonce)
{
	RLP root(_block);
	RLP header = root[0];

	if (!header.isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(0, header.data()) << errinfo_comment("block header needs to be a list"));
	populateFromHeader(header, _checkNonce);

	if (!root[1].isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(1, root[1].data()));
	if (!root[2].isList())
		BOOST_THROW_EXCEPTION(InvalidBlockFormat(2, root[2].data()));
}

void BlockInfo::verifyInternals(bytesConstRef _block) const
{
	RLP root(_block);

	u256 mgp = (u256)-1;

	OverlayDB db;
	GenericTrieDB<OverlayDB> t(&db);
	t.init();
	unsigned i = 0;
	for (auto const& tr: root[1])
	{
		bytes k = rlp(i);
		t.insert(&k, tr.data());
		u256 gasprice = tr[1].toInt<u256>();
		mgp = min(mgp, gasprice); // the minimum gas price is not used for anything //TODO delete?
		++i;
	}
	if (transactionsRoot != t.root())
		BOOST_THROW_EXCEPTION(InvalidTransactionsHash(t.root(), transactionsRoot));

	if (sha3Uncles != sha3(root[2].data()))
		BOOST_THROW_EXCEPTION(InvalidUnclesHash());
}

void BlockInfo::populateFromParent(BlockInfo const& _parent)
{
	stateRoot = _parent.stateRoot;
	parentHash = _parent.hash;
	number = _parent.number + 1;
	gasLimit = calculateGasLimit(_parent);
	gasUsed = 0;
	difficulty = calculateDifficulty(_parent);
	seedHash = number % 30 == 0 ? sha3(_parent.seedHash.asBytes() /*+ _parent.hash.asBytes()*/) : _parent.seedHash;
}

u256 BlockInfo::calculateGasLimit(BlockInfo const& _parent) const
{
	if (!parentHash)
		return 1000000;
	else
		return max<u256>(125000, (_parent.gasLimit * (1024 - 1) + (_parent.gasUsed * 6 / 5)) / 1024);
}

u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const
{
	if (!parentHash)
		return c_genesisDifficulty;
	else
		return max<u256>(2048, timestamp >= _parent.timestamp + (c_protocolVersion == 49 ? 5 : 8) ? _parent.difficulty - (_parent.difficulty / 2048) : (_parent.difficulty + (_parent.difficulty / 2048)));
}

template <class N> inline N diff(N const& _a, N const& _b) { return max(_a, _b) - min(_a, _b); }

void BlockInfo::verifyParent(BlockInfo const& _parent) const
{	// Check difficulty is correct given the two timestamps.
	if (difficulty != calculateDifficulty(_parent))
		BOOST_THROW_EXCEPTION(InvalidDifficulty());

	if (diff(gasLimit, _parent.gasLimit) <= _parent.gasLimit / 2048)
		BOOST_THROW_EXCEPTION(InvalidGasLimit(gasLimit, calculateGasLimit(_parent), diff(gasLimit, _parent.gasLimit), _parent.gasLimit / 2048));

	// Check timestamp is after previous timestamp.
	if (parentHash)
	{
		if (parentHash != _parent.hash)
			BOOST_THROW_EXCEPTION(InvalidParentHash());

		if (timestamp <= _parent.timestamp)
			BOOST_THROW_EXCEPTION(InvalidTimestamp());

		if (number != _parent.number + 1)
			BOOST_THROW_EXCEPTION(InvalidNumber());
	}
}
<|endoftext|>


<commit_before>/*
    $Id$
    This file is part of libkcal.
    Copyright (c) 2002 Klarlvdalens Datakonsult AB <info@klaralvdalens-datakonsult.se>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "calendarimap.h"
#include "calendarlocal.h"
// Just for some enums
#include "scheduler.h"

#include "journal.h"

#include <kdebug.h>
#include <kprocess.h>
#include <kapplication.h>
#include <kstandarddirs.h>
#include <kconfig.h>
#include <kinstance.h>
#include <kglobal.h>
#include <dcopclient.h>
#include <qfile.h>
#include <qdatastream.h>
#include <stdlib.h>

using namespace KCal;

CalendarIMAP::CalendarIMAP( const QString& organizerEmail ) : mTarget(0)
{
  mLocalCalendar = new CalendarLocal();
  mOrganizerEmail = organizerEmail;
}

CalendarIMAP::CalendarIMAP( const QString& organizerEmail, const QString& timeZoneId )
  : Calendar( timeZoneId ), mTarget(0)
{
  mLocalCalendar = new CalendarLocal( timeZoneId );
  mOrganizerEmail = organizerEmail;
}

CalendarIMAP::~CalendarIMAP()
{
  delete mLocalCalendar;
}

void CalendarIMAP::setTarget( QObject* target )
{
  if( mTarget ) {
    // Disconnect the old one
    disconnect( this, SIGNAL( signalNewOrUpdatedIncident( const QString&,
							  const QString&,
							  const QString&,
							  const QStringList&,
							  const QString& ) ) );
  }

  mTarget = target;

  QObject::connect( this,
		    SIGNAL( signalNewOrUpdatedIncident( const QString&,
							const QString&,
							const QString&,
							const QStringList&,
							const QString& ) ),
		    mTarget,
		    SLOT( slotNewOrUpdatedIncident( const QString&,
						    const QString&,
						    const QString&,
						    const QStringList&,
						    const QString& ) ) );
}

void CalendarIMAP::close()
{
  if( mLocalCalendar )
    mLocalCalendar->close();
}

void CalendarIMAP::addEvent( Event* aEvent )
{

  mLocalCalendar->addEvent( aEvent );

  // Tell mail client about the change
  sendNewOrUpdatedIncident( "Calendar", aEvent );

  setupAlarm();
}

void CalendarIMAP::deleteEvent( Event* aEvent )
{
  // Tell mail client about the deletion
  sendNewOrUpdatedIncident( "Calendar", aEvent, true );
  mLocalCalendar->deleteEvent( aEvent );

  setupAlarm();
}

Event* CalendarIMAP::event( const QString& uniqueStr )
{
  return mLocalCalendar->event( uniqueStr );
}

QPtrList<Event> CalendarIMAP::events()
{
  return mLocalCalendar->events();
}

QPtrList<Event> CalendarIMAP::rawEvents()
{
  return mLocalCalendar->rawEvents();
}

int CalendarIMAP::numEvents( const QDate& qd )
{
  return mLocalCalendar->numEvents( qd );
}

void CalendarIMAP::addTodo( Todo* aTodo )
{
  mLocalCalendar->addTodo( aTodo );

  // Tell mail client about the change
  sendNewOrUpdatedIncident( "Task", aTodo );

  setModified( true );

  setupAlarm();
}

void CalendarIMAP::deleteTodo( Todo* aTodo )
{
  // Tell mail client about the deletion
  sendNewOrUpdatedIncident( "Task", aTodo, true );

  mLocalCalendar->deleteTodo( aTodo );

  setModified( true );

  setupAlarm();
}

QPtrList<Todo> CalendarIMAP::todos()
{
  return mLocalCalendar->todos();
}

Todo* CalendarIMAP::todo( const QString& uid )
{
  return mLocalCalendar->todo( uid );
}

QPtrList<Todo> CalendarIMAP::todos( const QDate& date )
{
  return mLocalCalendar->todos( date );
}

QPtrList<Todo> CalendarIMAP::rawTodos() const
{
  return mLocalCalendar->rawTodos();
}

void CalendarIMAP::addJournal( Journal* journal )
{
  mLocalCalendar->addJournal( journal );

  setupAlarm();
}

Journal* CalendarIMAP::journal( const QDate& date )
{
  return mLocalCalendar->journal( date );
}

Journal* CalendarIMAP::journal( const QString& UID )
{
  return mLocalCalendar->journal( UID );
}

QPtrList<Journal> CalendarIMAP::journals()
{
  return mLocalCalendar->journals();
}

Alarm::List CalendarIMAP::alarms( const QDateTime &from,
                                  const QDateTime &to )
{
  return mLocalCalendar->alarms( from, to );
}

// after changes are made to an event, this should be called.
void CalendarIMAP::update( IncidenceBase *incidence )
{
  mLocalCalendar->update( incidence );
}

QPtrList<Event> CalendarIMAP::rawEventsForDate( const QDateTime &qdt )
{
  return mLocalCalendar->rawEventsForDate( qdt );
}

QPtrList<Event> CalendarIMAP::rawEventsForDate( const QDate &date,
                                                bool sorted )
{
  return mLocalCalendar->rawEventsForDate( date, sorted );
}

QPtrList<Event> CalendarIMAP::rawEvents( const QDate &start, const QDate &end,
                                         bool inclusive )
{
  return mLocalCalendar->rawEvents( start, end, inclusive );
}

/*!
  This method passes a new or updated event that has been created in
  KOrganizer to KMail for storage or sending to the recipients.
*/

void CalendarIMAP::sendNewOrUpdatedIncident( const QString& type,
                                             Incidence* incidence,
                                             bool eventDeleted )
{
  mFormat.setTimeZone( timeZoneId(), !isLocalTime() );

  // The method is always Request, never Refresh. At least, that's
  // what Outlook does.
  QString messageText( mFormat.createScheduleMessage(incidence,
						     eventDeleted ?
						     Scheduler::Cancel :
						     Scheduler::Request) );
  QString uid( incidence->uid() );
  if( eventDeleted )
    uid.prepend("DELETE ME:");

  QPtrList<Attendee> attendees = incidence->attendees();
  QStringList attendeeMailAddresses;
  for( Attendee* attendee = attendees.first(); attendee;
       attendee = attendees.next() ) {
    // Omit the organizer, so that we don't send an email to ourselves
    if( attendee->email() != mOrganizerEmail )
      attendeeMailAddresses.append( attendee->email() );
  }

  emit signalNewOrUpdatedIncident( type, messageText, uid,
				   attendeeMailAddresses,
				   incidence->summary() );
}

/*!
  Loads calendar data into the local calendar.
  PENDING(kalle) This needs to go back into KMail.
*/
bool CalendarIMAP::load( const QString& filename )
{
  return mLocalCalendar->load( filename );
}

/*!
  Saves the calendar data in the local calendar into a file.
*/

bool CalendarIMAP::save( const QString& filename, CalFormat* format )
{
  return mLocalCalendar->save( filename, format );
}

void CalendarIMAP::setupAlarm()
{
  static bool isInSetupAlarm = false;

  if( isInSetupAlarm )
    return;
  isInSetupAlarm = true;

  // Store the calendar in a file
  QString calFile = locateLocal( "appdata", "kmailalarms.ics" );

  if( save( calFile ) ) {
    DCOPClient* dcopClient = kapp->dcopClient();
    QByteArray params;
    QDataStream ds( params, IO_WriteOnly );

    QByteArray params2;
    QDataStream ds2( params2, IO_WriteOnly );
    ds2 << QCString( "korgac" ) << calFile;
    if( !dcopClient->send( "kalarmd", "ad", "reloadCal(QCString,QString)", params2 ) )
      kdDebug() << "Could not send reloadCal() DCOP call to kalarmd" << endl;
    else
      kdDebug() << "Send reloadCal() to kalarmd" << endl;
  }
  isInSetupAlarm = false;
}
<commit_msg>includemoc<commit_after>/*
    $Id$
    This file is part of libkcal.
    Copyright (c) 2002 Klarlvdalens Datakonsult AB <info@klaralvdalens-datakonsult.se>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "calendarimap.h"
#include "calendarimap.moc"

#include "calendarlocal.h"
// Just for some enums
#include "scheduler.h"

#include "journal.h"

#include <kdebug.h>
#include <kprocess.h>
#include <kapplication.h>
#include <kstandarddirs.h>
#include <kconfig.h>
#include <kinstance.h>
#include <kglobal.h>
#include <dcopclient.h>
#include <qfile.h>
#include <qdatastream.h>
#include <stdlib.h>

using namespace KCal;

CalendarIMAP::CalendarIMAP( const QString& organizerEmail ) : mTarget(0)
{
  mLocalCalendar = new CalendarLocal();
  mOrganizerEmail = organizerEmail;
}

CalendarIMAP::CalendarIMAP( const QString& organizerEmail, const QString& timeZoneId )
  : Calendar( timeZoneId ), mTarget(0)
{
  mLocalCalendar = new CalendarLocal( timeZoneId );
  mOrganizerEmail = organizerEmail;
}

CalendarIMAP::~CalendarIMAP()
{
  delete mLocalCalendar;
}

void CalendarIMAP::setTarget( QObject* target )
{
  if( mTarget ) {
    // Disconnect the old one
    disconnect( this, SIGNAL( signalNewOrUpdatedIncident( const QString&,
							  const QString&,
							  const QString&,
							  const QStringList&,
							  const QString& ) ) );
  }

  mTarget = target;

  QObject::connect( this,
		    SIGNAL( signalNewOrUpdatedIncident( const QString&,
							const QString&,
							const QString&,
							const QStringList&,
							const QString& ) ),
		    mTarget,
		    SLOT( slotNewOrUpdatedIncident( const QString&,
						    const QString&,
						    const QString&,
						    const QStringList&,
						    const QString& ) ) );
}

void CalendarIMAP::close()
{
  if( mLocalCalendar )
    mLocalCalendar->close();
}

void CalendarIMAP::addEvent( Event* aEvent )
{

  mLocalCalendar->addEvent( aEvent );

  // Tell mail client about the change
  sendNewOrUpdatedIncident( "Calendar", aEvent );

  setupAlarm();
}

void CalendarIMAP::deleteEvent( Event* aEvent )
{
  // Tell mail client about the deletion
  sendNewOrUpdatedIncident( "Calendar", aEvent, true );
  mLocalCalendar->deleteEvent( aEvent );

  setupAlarm();
}

Event* CalendarIMAP::event( const QString& uniqueStr )
{
  return mLocalCalendar->event( uniqueStr );
}

QPtrList<Event> CalendarIMAP::events()
{
  return mLocalCalendar->events();
}

QPtrList<Event> CalendarIMAP::rawEvents()
{
  return mLocalCalendar->rawEvents();
}

int CalendarIMAP::numEvents( const QDate& qd )
{
  return mLocalCalendar->numEvents( qd );
}

void CalendarIMAP::addTodo( Todo* aTodo )
{
  mLocalCalendar->addTodo( aTodo );

  // Tell mail client about the change
  sendNewOrUpdatedIncident( "Task", aTodo );

  setModified( true );

  setupAlarm();
}

void CalendarIMAP::deleteTodo( Todo* aTodo )
{
  // Tell mail client about the deletion
  sendNewOrUpdatedIncident( "Task", aTodo, true );

  mLocalCalendar->deleteTodo( aTodo );

  setModified( true );

  setupAlarm();
}

QPtrList<Todo> CalendarIMAP::todos()
{
  return mLocalCalendar->todos();
}

Todo* CalendarIMAP::todo( const QString& uid )
{
  return mLocalCalendar->todo( uid );
}

QPtrList<Todo> CalendarIMAP::todos( const QDate& date )
{
  return mLocalCalendar->todos( date );
}

QPtrList<Todo> CalendarIMAP::rawTodos() const
{
  return mLocalCalendar->rawTodos();
}

void CalendarIMAP::addJournal( Journal* journal )
{
  mLocalCalendar->addJournal( journal );

  setupAlarm();
}

Journal* CalendarIMAP::journal( const QDate& date )
{
  return mLocalCalendar->journal( date );
}

Journal* CalendarIMAP::journal( const QString& UID )
{
  return mLocalCalendar->journal( UID );
}

QPtrList<Journal> CalendarIMAP::journals()
{
  return mLocalCalendar->journals();
}

Alarm::List CalendarIMAP::alarms( const QDateTime &from,
                                  const QDateTime &to )
{
  return mLocalCalendar->alarms( from, to );
}

// after changes are made to an event, this should be called.
void CalendarIMAP::update( IncidenceBase *incidence )
{
  mLocalCalendar->update( incidence );
}

QPtrList<Event> CalendarIMAP::rawEventsForDate( const QDateTime &qdt )
{
  return mLocalCalendar->rawEventsForDate( qdt );
}

QPtrList<Event> CalendarIMAP::rawEventsForDate( const QDate &date,
                                                bool sorted )
{
  return mLocalCalendar->rawEventsForDate( date, sorted );
}

QPtrList<Event> CalendarIMAP::rawEvents( const QDate &start, const QDate &end,
                                         bool inclusive )
{
  return mLocalCalendar->rawEvents( start, end, inclusive );
}

/*!
  This method passes a new or updated event that has been created in
  KOrganizer to KMail for storage or sending to the recipients.
*/

void CalendarIMAP::sendNewOrUpdatedIncident( const QString& type,
                                             Incidence* incidence,
                                             bool eventDeleted )
{
  mFormat.setTimeZone( timeZoneId(), !isLocalTime() );

  // The method is always Request, never Refresh. At least, that's
  // what Outlook does.
  QString messageText( mFormat.createScheduleMessage(incidence,
						     eventDeleted ?
						     Scheduler::Cancel :
						     Scheduler::Request) );
  QString uid( incidence->uid() );
  if( eventDeleted )
    uid.prepend("DELETE ME:");

  QPtrList<Attendee> attendees = incidence->attendees();
  QStringList attendeeMailAddresses;
  for( Attendee* attendee = attendees.first(); attendee;
       attendee = attendees.next() ) {
    // Omit the organizer, so that we don't send an email to ourselves
    if( attendee->email() != mOrganizerEmail )
      attendeeMailAddresses.append( attendee->email() );
  }

  emit signalNewOrUpdatedIncident( type, messageText, uid,
				   attendeeMailAddresses,
				   incidence->summary() );
}

/*!
  Loads calendar data into the local calendar.
  PENDING(kalle) This needs to go back into KMail.
*/
bool CalendarIMAP::load( const QString& filename )
{
  return mLocalCalendar->load( filename );
}

/*!
  Saves the calendar data in the local calendar into a file.
*/

bool CalendarIMAP::save( const QString& filename, CalFormat* format )
{
  return mLocalCalendar->save( filename, format );
}

void CalendarIMAP::setupAlarm()
{
  static bool isInSetupAlarm = false;

  if( isInSetupAlarm )
    return;
  isInSetupAlarm = true;

  // Store the calendar in a file
  QString calFile = locateLocal( "appdata", "kmailalarms.ics" );

  if( save( calFile ) ) {
    DCOPClient* dcopClient = kapp->dcopClient();
    QByteArray params;
    QDataStream ds( params, IO_WriteOnly );

    QByteArray params2;
    QDataStream ds2( params2, IO_WriteOnly );
    ds2 << QCString( "korgac" ) << calFile;
    if( !dcopClient->send( "kalarmd", "ad", "reloadCal(QCString,QString)", params2 ) )
      kdDebug() << "Could not send reloadCal() DCOP call to kalarmd" << endl;
    else
      kdDebug() << "Send reloadCal() to kalarmd" << endl;
  }
  isInSetupAlarm = false;
}
<|endoftext|>


<commit_before>/*
 This file is part of cpp-ethereum.

 cpp-ethereum is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 */
/** @file RLPXHandshake.cpp
 * @author Alex Leverington <nessence@gmail.com>
 * @date 2015
 */

#include "Host.h"
#include "Session.h"
#include "Peer.h"
#include "RLPxHandshake.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace CryptoPP;

void RLPXHandshake::writeAuth()
{
	clog(NetConnect) << "p2p.connect.egress sending auth to " << m_socket->remoteEndpoint();
	m_auth.resize(Signature::size + h256::size + Public::size + h256::size + 1);
	bytesRef sig(&m_auth[0], Signature::size);
	bytesRef hepubk(&m_auth[Signature::size], h256::size);
	bytesRef pubk(&m_auth[Signature::size + h256::size], Public::size);
	bytesRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);

	// E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
	Secret staticShared;
	crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, staticShared);
	sign(m_ecdhe.seckey(), staticShared ^ m_nonce).ref().copyTo(sig);
	sha3(m_ecdhe.pubkey().ref(), hepubk);
	m_host->m_alias.pub().ref().copyTo(pubk);
	m_nonce.ref().copyTo(nonce);
	m_auth[m_auth.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_auth, m_authCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_authCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::writeAck()
{
	clog(NetConnect) << "p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint();
	m_ack.resize(Public::size + h256::size + 1);
	bytesRef epubk(&m_ack[0], Public::size);
	bytesRef nonce(&m_ack[Public::size], h256::size);
	m_ecdhe.pubkey().ref().copyTo(epubk);
	m_nonce.ref().copyTo(nonce);
	m_ack[m_ack.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_ack, m_ackCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_ackCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::readAuth()
{
	clog(NetConnect) << "p2p.connect.ingress recving auth from " << m_socket->remoteEndpoint();
	m_authCipher.resize(307);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_authCipher, 307), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_authCipher), m_auth))
		{
			bytesConstRef sig(&m_auth[0], Signature::size);
			bytesConstRef hepubk(&m_auth[Signature::size], h256::size);
			bytesConstRef pubk(&m_auth[Signature::size + h256::size], Public::size);
			bytesConstRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);
			pubk.copyTo(m_remote.ref());
			nonce.copyTo(m_remoteNonce.ref());

			Secret sharedSecret;
			crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, sharedSecret);
			m_remoteEphemeral = recover(*(Signature*)sig.data(), sharedSecret ^ m_remoteNonce);
			assert(sha3(m_remoteEphemeral) == *(h256*)hepubk.data());
			transition();
		}
		else
		{
			clog(NetConnect) << "p2p.connect.ingress recving auth decrypt failed for" << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::readAck()
{
	clog(NetConnect) << "p2p.connect.egress recving ack from " << m_socket->remoteEndpoint();
	m_ackCipher.resize(210);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_ackCipher, 210), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_ackCipher), m_ack))
		{
			bytesConstRef(&m_ack).cropped(0, Public::size).copyTo(m_remoteEphemeral.ref());
			bytesConstRef(&m_ack).cropped(Public::size, h256::size).copyTo(m_remoteNonce.ref());
			transition();
		}
		else
		{
			clog(NetConnect) << "p2p.connect.egress recving ack decrypt failed for " << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::error()
{
	clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)";
	m_socket->close();
	if (m_io != nullptr)
		delete m_io;
}

void RLPXHandshake::transition(boost::system::error_code _ech)
{
	if (_ech || m_nextState == Error || m_cancel)
		return error();

	auto self(shared_from_this());
	if (m_nextState == New)
	{
		m_nextState = AckAuth;
		if (m_originated)
			writeAuth();
		else
			readAuth();
	}
	else if (m_nextState == AckAuth)
	{
		m_nextState = WriteHello;
		if (m_originated)
			readAck();
		else
			writeAck();
	}
	else if (m_nextState == WriteHello)
	{
		m_nextState = ReadHello;
		clog(NetConnect) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "sending capabilities handshake";

		/// This pointer will be freed if there is an error otherwise
		/// it will be passed to Host which will take ownership.
		m_io = new RLPXFrameIO(*this);

		// old packet format
		// 5 arguments, HelloPacket
		RLPStream s;
		s.append((unsigned)0).appendList(5)
		<< dev::p2p::c_protocolVersion
		<< m_host->m_clientVersion
		<< m_host->caps()
		<< m_host->listenPort()
		<< m_host->id();
		bytes packet;
		s.swapOut(packet);
		m_io->writeSingleFramePacket(&packet, m_handshakeOutBuffer);
		ba::async_write(m_socket->ref(), ba::buffer(m_handshakeOutBuffer), [this, self](boost::system::error_code ec, std::size_t)
		{
			transition(ec);
		});
	}
	else if (m_nextState == ReadHello)
	{
		// Authenticate and decrypt initial hello frame with initial RLPXFrameIO
		// and request m_host to start session.
		m_nextState = StartSession;

		// read frame header
		m_handshakeInBuffer.resize(h256::size);
		ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, h256::size), [this, self](boost::system::error_code ec, std::size_t)
		{
			if (ec)
				transition(ec);
			else
			{
				/// authenticate and decrypt header
				if (!m_io->authAndDecryptHeader(bytesRef(m_handshakeInBuffer.data(), h256::size)))
				{
					m_nextState = Error;
					transition();
					return;
				}

				clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "recvd hello header";

				/// check frame size
				bytes& header = m_handshakeInBuffer;
				uint32_t frameSize = (uint32_t)(header[2]) | (uint32_t)(header[1])<<8 | (uint32_t)(header[0])<<16;
				if (frameSize > 1024)
				{
					// all future frames: 16777216
					clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame is too large" << frameSize;
					m_nextState = Error;
					transition();
					return;
				}

				/// rlp of header has protocol-type, sequence-id[, total-packet-size]
				bytes headerRLP(header.size() - 3 - h128::size);
				bytesConstRef(&header).cropped(3).copyTo(&headerRLP);

				/// read padded frame and mac
				m_handshakeInBuffer.resize(frameSize + ((16 - (frameSize % 16)) % 16) + h128::size);
				ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, m_handshakeInBuffer.size()), [this, self, headerRLP](boost::system::error_code ec, std::size_t)
				{
					if (ec)
						transition(ec);
					else
					{
						bytesRef frame(&m_handshakeInBuffer);
						if (!m_io->authAndDecryptFrame(frame))
						{
							clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: decrypt failed";
							m_nextState = Error;
							transition();
							return;
						}

						PacketType packetType = (PacketType)(frame[0] == 0x80 ? 0x0 : frame[0]);
						if (packetType != 0)
						{
							clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: invalid packet type";
							m_nextState = Error;
							transition();
							return;
						}

						clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: success. starting session.";
						RLP rlp(frame.cropped(1), RLP::ThrowOnFail | RLP::FailIfTooSmall);
						m_host->startPeerSession(m_remote, rlp, m_io, m_socket->remoteEndpoint());
					}
				});
			}
		});
	}

	m_idleTimer.expires_from_now(c_timeout);
	m_idleTimer.async_wait([this, self](boost::system::error_code const& _ec)
	{
		if (!_ec)
		{
			clog(NetWarn) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
			cancel();
		}
	});
}
<commit_msg>better handshake error logging, esp when remote disconnects<commit_after>/*
 This file is part of cpp-ethereum.

 cpp-ethereum is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 */
/** @file RLPXHandshake.cpp
 * @author Alex Leverington <nessence@gmail.com>
 * @date 2015
 */

#include "Host.h"
#include "Session.h"
#include "Peer.h"
#include "RLPxHandshake.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace CryptoPP;

void RLPXHandshake::writeAuth()
{
	clog(NetConnect) << "p2p.connect.egress sending auth to " << m_socket->remoteEndpoint();
	m_auth.resize(Signature::size + h256::size + Public::size + h256::size + 1);
	bytesRef sig(&m_auth[0], Signature::size);
	bytesRef hepubk(&m_auth[Signature::size], h256::size);
	bytesRef pubk(&m_auth[Signature::size + h256::size], Public::size);
	bytesRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);

	// E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
	Secret staticShared;
	crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, staticShared);
	sign(m_ecdhe.seckey(), staticShared ^ m_nonce).ref().copyTo(sig);
	sha3(m_ecdhe.pubkey().ref(), hepubk);
	m_host->m_alias.pub().ref().copyTo(pubk);
	m_nonce.ref().copyTo(nonce);
	m_auth[m_auth.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_auth, m_authCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_authCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::writeAck()
{
	clog(NetConnect) << "p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint();
	m_ack.resize(Public::size + h256::size + 1);
	bytesRef epubk(&m_ack[0], Public::size);
	bytesRef nonce(&m_ack[Public::size], h256::size);
	m_ecdhe.pubkey().ref().copyTo(epubk);
	m_nonce.ref().copyTo(nonce);
	m_ack[m_ack.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_ack, m_ackCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_ackCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::readAuth()
{
	clog(NetConnect) << "p2p.connect.ingress recving auth from " << m_socket->remoteEndpoint();
	m_authCipher.resize(307);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_authCipher, 307), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_authCipher), m_auth))
		{
			bytesConstRef sig(&m_auth[0], Signature::size);
			bytesConstRef hepubk(&m_auth[Signature::size], h256::size);
			bytesConstRef pubk(&m_auth[Signature::size + h256::size], Public::size);
			bytesConstRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);
			pubk.copyTo(m_remote.ref());
			nonce.copyTo(m_remoteNonce.ref());

			Secret sharedSecret;
			crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, sharedSecret);
			m_remoteEphemeral = recover(*(Signature*)sig.data(), sharedSecret ^ m_remoteNonce);
			assert(sha3(m_remoteEphemeral) == *(h256*)hepubk.data());
			transition();
		}
		else
		{
			clog(NetConnect) << "p2p.connect.ingress recving auth decrypt failed for" << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::readAck()
{
	clog(NetConnect) << "p2p.connect.egress recving ack from " << m_socket->remoteEndpoint();
	m_ackCipher.resize(210);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_ackCipher, 210), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_ackCipher), m_ack))
		{
			bytesConstRef(&m_ack).cropped(0, Public::size).copyTo(m_remoteEphemeral.ref());
			bytesConstRef(&m_ack).cropped(Public::size, h256::size).copyTo(m_remoteNonce.ref());
			transition();
		}
		else
		{
			clog(NetConnect) << "p2p.connect.egress recving ack decrypt failed for " << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::error()
{
	m_idleTimer.cancel();

	auto connected = m_socket->isConnected();
	if (connected && !m_socket->remoteEndpoint().address().is_unspecified())
		clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)";
	else
		clog(NetConnect) << "Handshake Failed (Connection reset by peer)";

	m_socket->close();
	if (m_io != nullptr)
		delete m_io;
}

void RLPXHandshake::transition(boost::system::error_code _ech)
{
	if (_ech || m_nextState == Error || m_cancel)
	{
		clog(NetConnect) << "Handshake Failed (I/O Error:" << _ech.message() << ")";
		return error();
	}

	auto self(shared_from_this());
	if (m_nextState == New)
	{
		m_nextState = AckAuth;
		if (m_originated)
			writeAuth();
		else
			readAuth();
	}
	else if (m_nextState == AckAuth)
	{
		m_nextState = WriteHello;
		if (m_originated)
			readAck();
		else
			writeAck();
	}
	else if (m_nextState == WriteHello)
	{
		m_nextState = ReadHello;
		clog(NetConnect) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "sending capabilities handshake";

		/// This pointer will be freed if there is an error otherwise
		/// it will be passed to Host which will take ownership.
		m_io = new RLPXFrameIO(*this);

		// old packet format
		// 5 arguments, HelloPacket
		RLPStream s;
		s.append((unsigned)0).appendList(5)
		<< dev::p2p::c_protocolVersion
		<< m_host->m_clientVersion
		<< m_host->caps()
		<< m_host->listenPort()
		<< m_host->id();
		bytes packet;
		s.swapOut(packet);
		m_io->writeSingleFramePacket(&packet, m_handshakeOutBuffer);
		ba::async_write(m_socket->ref(), ba::buffer(m_handshakeOutBuffer), [this, self](boost::system::error_code ec, std::size_t)
		{
			transition(ec);
		});
	}
	else if (m_nextState == ReadHello)
	{
		// Authenticate and decrypt initial hello frame with initial RLPXFrameIO
		// and request m_host to start session.
		m_nextState = StartSession;

		// read frame header
		m_handshakeInBuffer.resize(h256::size);
		ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, h256::size), [this, self](boost::system::error_code ec, std::size_t)
		{
			if (ec)
				transition(ec);
			else
			{
				/// authenticate and decrypt header
				if (!m_io->authAndDecryptHeader(bytesRef(m_handshakeInBuffer.data(), h256::size)))
				{
					m_nextState = Error;
					transition();
					return;
				}

				clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "recvd hello header";

				/// check frame size
				bytes& header = m_handshakeInBuffer;
				uint32_t frameSize = (uint32_t)(header[2]) | (uint32_t)(header[1])<<8 | (uint32_t)(header[0])<<16;
				if (frameSize > 1024)
				{
					// all future frames: 16777216
					clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame is too large" << frameSize;
					m_nextState = Error;
					transition();
					return;
				}

				/// rlp of header has protocol-type, sequence-id[, total-packet-size]
				bytes headerRLP(header.size() - 3 - h128::size);
				bytesConstRef(&header).cropped(3).copyTo(&headerRLP);

				/// read padded frame and mac
				m_handshakeInBuffer.resize(frameSize + ((16 - (frameSize % 16)) % 16) + h128::size);
				ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, m_handshakeInBuffer.size()), [this, self, headerRLP](boost::system::error_code ec, std::size_t)
				{
					if (ec)
						transition(ec);
					else
					{
						bytesRef frame(&m_handshakeInBuffer);
						if (!m_io->authAndDecryptFrame(frame))
						{
							clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: decrypt failed";
							m_nextState = Error;
							transition();
							return;
						}

						PacketType packetType = (PacketType)(frame[0] == 0x80 ? 0x0 : frame[0]);
						if (packetType != 0)
						{
							clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: invalid packet type";
							m_nextState = Error;
							transition();
							return;
						}

						clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: success. starting session.";
						RLP rlp(frame.cropped(1), RLP::ThrowOnFail | RLP::FailIfTooSmall);
						m_host->startPeerSession(m_remote, rlp, m_io, m_socket->remoteEndpoint());
					}
				});
			}
		});
	}

	m_idleTimer.expires_from_now(c_timeout);
	m_idleTimer.async_wait([this, self](boost::system::error_code const& _ec)
	{
		if (!_ec)
		{
			if (!m_socket->remoteEndpoint().address().is_unspecified())
				clog(NetWarn) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
			cancel();
		}
	});
}
<|endoftext|>