<commit_before>#include "DrawPolygonCMPT.h"
#include "EditPolylineWithCopyNodeOP.h"
#include "PolygonShape.h"
#include "DrawPencilPolygonCMPT.h"
#include "ColorMaterial.h"

#include <ee/SelectShapesOP.h>
#include <ee/MultiShapesImpl.h>
#include <ee/ShapeSelection.h>
#include <ee/EmptyVerifyVisitor.h>
#include <ee/FetchAllVisitor.h>
#include <ee/RGBColorSettingDlg.h>
#include <ee/HSLColorSettingDlg.h>
#include <ee/SymbolMgr.h>
#include <ee/panel_msg.h>
#include <ee/ImageSymbol.h>
#include <ee/Config.h>
#include <ee/SettingData.h>

namespace eshape
{

DrawPolygonCMPT::DrawPolygonCMPT(wxWindow* parent, const std::string& name, wxWindow* stage_wnd,
								 ee::EditPanelImpl* stage, ee::MultiShapesImpl* shapes_impl,
								 ee::PropertySettingPanel* property)
	: ee::OneFloatValueCMPT(parent, name, stage, "node capture", 5, 30, 10)
	, m_stage_wnd(stage_wnd)
	, m_shapes_impl(shapes_impl)
	, m_color(*wxBLACK)
{
	m_editop = NULL;
	// draw polygon with pen, node capture
	{
		ee::OneFloatValueCMPT* cmpt = new ee::OneFloatValueCMPT(this, "pen", stage, "node capture", 5, 30, 10);
		ee::EditOP* op = new EditPolylineOP<DrawPolygonOP, ee::SelectShapesOP>
			(stage_wnd, stage, shapes_impl, property, cmpt, /*cmpt*/this);
		cmpt->SetEditOP(op);
		AddChild(cmpt);
	}
	// draw polygon with pencil, simplify threshold
	{
		AddChild(new DrawPencilPolygonCMPT(this, "pencil", stage_wnd, stage, shapes_impl));
	}
}

void DrawPolygonCMPT::UpdateControlValue()
{
	bool empty;
	m_shapes_impl->GetShapeSelection()->Traverse(ee::EmptyVerifyVisitor(empty));
	m_btn_trigger->Enable(!empty);

	if (!empty) {
		std::vector<ee::Shape*> shapes;
		m_shapes_impl->GetShapeSelection()->Traverse(ee::FetchAllVisitor<ee::Shape>(shapes));
		PolygonShape* poly = dynamic_cast<PolygonShape*>(shapes[0]);
		if (poly) {
			const ColorMaterial* cm = dynamic_cast<const ColorMaterial*>(poly->GetMaterial());
			const s2::Color& col = cm->GetColor();
			m_color.Set(col.r, col.g, col.b);
			FillingButton();
		}
	}
}

wxSizer* DrawPolygonCMPT::InitLayout()
{
	wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

	sizer->Add(ee::OneFloatValueCMPT::InitLayout());

	sizer->AddSpacer(20);

	sizer->Add(InitChildrenLayout());

	sizer->AddSpacer(20);

	sizer->Add(InitPreviewButtonPanel());

	sizer->AddSpacer(10);

	m_btn_trigger = new wxButton(this, wxID_ANY, wxT(""));
	Connect(m_btn_trigger->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DrawPolygonCMPT::OnTriggerFillingColor));
	sizer->Add(m_btn_trigger);
	m_btn_trigger->Enable(false);

	return sizer;
}

wxSizer* DrawPolygonCMPT::InitPreviewButtonPanel()
{
	wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

	wxArrayString choices;
	choices.Add(wxT("ɫ"));
	choices.Add(wxT(""));
	m_filling_type_choice = new wxRadioBox(this, wxID_ANY, wxT("䷽ʽ"), wxDefaultPosition, wxDefaultSize, choices, 1, wxRA_SPECIFY_COLS);
	Connect(m_filling_type_choice->GetId(), wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(DrawPolygonCMPT::OnChangeFillingType));
	sizer->Add(m_filling_type_choice);

	sizer->AddSpacer(10);

	m_btn_review = new wxButton(this, wxID_ANY);
	Connect(m_btn_review->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DrawPolygonCMPT::OnSetColor));
	sizer->Add(m_btn_review);
	FillingButton();

	return sizer;
}

void DrawPolygonCMPT::OnSetColor(wxCommandEvent& event)
{
	switch (m_filling_type_choice->GetSelection())
	{
	case 0:
		if (ee::Config::Instance()->GetSettings().color_setting_dlg_type == ee::CSDT_HSL)
		{
 			// todo params between wxColor and s2::Color
 			s2::Color col;
 			col.r = m_color.Red();
 			col.g = m_color.Green();
 			col.b = m_color.Blue();
 			ee::HSLColorSettingDlg dlg(m_stage_wnd, NULL, col);
 			if (dlg.ShowModal() == wxID_OK) {
 				col = dlg.GetColor();
 				m_color.Set(col.r, col.g, col.b);
 			}
		}
		else
		{
			// todo params between wxColor and s2::Color
			s2::Color col;
			col.r = m_color.Red();
			col.g = m_color.Green();
			col.b = m_color.Blue();
			ee::RGBColorSettingDlg dlg(m_stage_wnd, NULL, col);
			if (dlg.ShowModal() == wxID_OK) {
				col = dlg.GetColor();
				m_color.Set(col.r, col.g, col.b);
			}
		}
		break;
	case 1:
		{
			wxFileDialog dlg(this, wxT("ѡ"), wxEmptyString, wxEmptyString, wxT("*.png;*.jpg"), wxFD_OPEN);
			if (dlg.ShowModal() == wxID_OK)
			{
				m_filepath = dlg.GetPath();
				m_bitmap.LoadFromFile(m_filepath);
			}
		}
		break;
	}
	FillingButton();
}

void DrawPolygonCMPT::OnChangeFillingType(wxCommandEvent& event)
{
	FillingButton();
}

void DrawPolygonCMPT::OnTriggerFillingColor(wxCommandEvent& event)
{
	std::vector<ee::Shape*> shapes;
	m_shapes_impl->GetShapeSelection()->Traverse(ee::FetchAllVisitor<ee::Shape>(shapes));

	for (size_t i = 0, n = shapes.size(); i < n; ++i)
	{
		PolygonShape* poly = dynamic_cast<PolygonShape*>(shapes[i]);
		switch (m_filling_type_choice->GetSelection())
		{
		case 0:
			poly->SetMaterialColor(s2::Color(m_color.Red(), m_color.Green(), m_color.Blue()));
			break;
		case 1:
			poly->SetMaterialTexture(static_cast<ee::ImageSymbol*>(ee::SymbolMgr::Instance()->FetchSymbol(m_filepath)));
			break;
		}
		ee::SetCanvasDirtySJ::Instance()->SetDirty();
	}
}

void DrawPolygonCMPT::FillingButton()
{
	switch (m_filling_type_choice->GetSelection())
	{
	case 0:
		{
			wxImage img(m_btn_review->GetSize().GetWidth(), m_btn_review->GetSize().GetHeight());
			img.SetRGB(wxRect(m_btn_review->GetSize()), m_color.Red(), m_color.Green(), m_color.Blue());
			wxBitmap bitmap(img);
			m_btn_review->SetBitmap(bitmap);
		}
		break;
	case 1:
		if (const wxBitmap* bmp = m_bitmap.GetLargeBmp()) {
			m_btn_review->SetBitmap(*bmp);
		}
		break;
	}
}

}<commit_msg>[FIXED] edit poly<commit_after>#include "DrawPolygonCMPT.h"
#include "EditPolylineWithCopyNodeOP.h"
#include "PolygonShape.h"
#include "DrawPencilPolygonCMPT.h"
#include "ColorMaterial.h"

#include <ee/SelectShapesOP.h>
#include <ee/MultiShapesImpl.h>
#include <ee/ShapeSelection.h>
#include <ee/EmptyVerifyVisitor.h>
#include <ee/FetchAllVisitor.h>
#include <ee/RGBColorSettingDlg.h>
#include <ee/HSLColorSettingDlg.h>
#include <ee/SymbolMgr.h>
#include <ee/panel_msg.h>
#include <ee/ImageSymbol.h>
#include <ee/Config.h>
#include <ee/SettingData.h>

namespace eshape
{

DrawPolygonCMPT::DrawPolygonCMPT(wxWindow* parent, const std::string& name, wxWindow* stage_wnd,
								 ee::EditPanelImpl* stage, ee::MultiShapesImpl* shapes_impl,
								 ee::PropertySettingPanel* property)
	: ee::OneFloatValueCMPT(parent, name, stage, "node capture", 5, 30, 10)
	, m_stage_wnd(stage_wnd)
	, m_shapes_impl(shapes_impl)
	, m_color(*wxBLACK)
{
	m_editop = NULL;
	// draw polygon with pen, node capture
	{
		ee::OneFloatValueCMPT* cmpt = new ee::OneFloatValueCMPT(this, "pen", stage, "node capture", 5, 30, 10);
		ee::EditOP* op = new EditPolylineOP<DrawPolygonOP, ee::SelectShapesOP>
			(stage_wnd, stage, shapes_impl, property, cmpt, /*cmpt*/this);
		cmpt->SetEditOP(op);
		AddChild(cmpt);
	}
	// draw polygon with pencil, simplify threshold
	{
		AddChild(new DrawPencilPolygonCMPT(this, "pencil", stage_wnd, stage, shapes_impl));
	}
}

void DrawPolygonCMPT::UpdateControlValue()
{
	bool empty;
	m_shapes_impl->GetShapeSelection()->Traverse(ee::EmptyVerifyVisitor(empty));
	m_btn_trigger->Enable(!empty);

	if (!empty) {
		std::vector<ee::Shape*> shapes;
		m_shapes_impl->GetShapeSelection()->Traverse(ee::FetchAllVisitor<ee::Shape>(shapes));
		PolygonShape* poly = dynamic_cast<PolygonShape*>(shapes[0]);
		if (poly) {
			const ColorMaterial* cm = dynamic_cast<const ColorMaterial*>(poly->GetMaterial());
			if (cm) {
				const s2::Color& col = cm->GetColor();
				m_color.Set(col.r, col.g, col.b);
				FillingButton();
			}
		}
	}
}

wxSizer* DrawPolygonCMPT::InitLayout()
{
	wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

	sizer->Add(ee::OneFloatValueCMPT::InitLayout());

	sizer->AddSpacer(20);

	sizer->Add(InitChildrenLayout());

	sizer->AddSpacer(20);

	sizer->Add(InitPreviewButtonPanel());

	sizer->AddSpacer(10);

	m_btn_trigger = new wxButton(this, wxID_ANY, wxT(""));
	Connect(m_btn_trigger->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DrawPolygonCMPT::OnTriggerFillingColor));
	sizer->Add(m_btn_trigger);
	m_btn_trigger->Enable(false);

	return sizer;
}

wxSizer* DrawPolygonCMPT::InitPreviewButtonPanel()
{
	wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

	wxArrayString choices;
	choices.Add(wxT("ɫ"));
	choices.Add(wxT(""));
	m_filling_type_choice = new wxRadioBox(this, wxID_ANY, wxT("䷽ʽ"), wxDefaultPosition, wxDefaultSize, choices, 1, wxRA_SPECIFY_COLS);
	Connect(m_filling_type_choice->GetId(), wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(DrawPolygonCMPT::OnChangeFillingType));
	sizer->Add(m_filling_type_choice);

	sizer->AddSpacer(10);

	m_btn_review = new wxButton(this, wxID_ANY);
	Connect(m_btn_review->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DrawPolygonCMPT::OnSetColor));
	sizer->Add(m_btn_review);
	FillingButton();

	return sizer;
}

void DrawPolygonCMPT::OnSetColor(wxCommandEvent& event)
{
	switch (m_filling_type_choice->GetSelection())
	{
	case 0:
		if (ee::Config::Instance()->GetSettings().color_setting_dlg_type == ee::CSDT_HSL)
		{
 			// todo params between wxColor and s2::Color
 			s2::Color col;
 			col.r = m_color.Red();
 			col.g = m_color.Green();
 			col.b = m_color.Blue();
 			ee::HSLColorSettingDlg dlg(m_stage_wnd, NULL, col);
 			if (dlg.ShowModal() == wxID_OK) {
 				col = dlg.GetColor();
 				m_color.Set(col.r, col.g, col.b);
 			}
		}
		else
		{
			// todo params between wxColor and s2::Color
			s2::Color col;
			col.r = m_color.Red();
			col.g = m_color.Green();
			col.b = m_color.Blue();
			ee::RGBColorSettingDlg dlg(m_stage_wnd, NULL, col);
			if (dlg.ShowModal() == wxID_OK) {
				col = dlg.GetColor();
				m_color.Set(col.r, col.g, col.b);
			}
		}
		break;
	case 1:
		{
			wxFileDialog dlg(this, wxT("ѡ"), wxEmptyString, wxEmptyString, wxT("*.png;*.jpg"), wxFD_OPEN);
			if (dlg.ShowModal() == wxID_OK)
			{
				m_filepath = dlg.GetPath();
				m_bitmap.LoadFromFile(m_filepath);
			}
		}
		break;
	}
	FillingButton();
}

void DrawPolygonCMPT::OnChangeFillingType(wxCommandEvent& event)
{
	FillingButton();
}

void DrawPolygonCMPT::OnTriggerFillingColor(wxCommandEvent& event)
{
	std::vector<ee::Shape*> shapes;
	m_shapes_impl->GetShapeSelection()->Traverse(ee::FetchAllVisitor<ee::Shape>(shapes));

	for (size_t i = 0, n = shapes.size(); i < n; ++i)
	{
		PolygonShape* poly = dynamic_cast<PolygonShape*>(shapes[i]);
		switch (m_filling_type_choice->GetSelection())
		{
		case 0:
			poly->SetMaterialColor(s2::Color(m_color.Red(), m_color.Green(), m_color.Blue()));
			break;
		case 1:
			poly->SetMaterialTexture(static_cast<ee::ImageSymbol*>(ee::SymbolMgr::Instance()->FetchSymbol(m_filepath)));
			break;
		}
		ee::SetCanvasDirtySJ::Instance()->SetDirty();
	}
}

void DrawPolygonCMPT::FillingButton()
{
	switch (m_filling_type_choice->GetSelection())
	{
	case 0:
		{
			wxImage img(m_btn_review->GetSize().GetWidth(), m_btn_review->GetSize().GetHeight());
			img.SetRGB(wxRect(m_btn_review->GetSize()), m_color.Red(), m_color.Green(), m_color.Blue());
			wxBitmap bitmap(img);
			m_btn_review->SetBitmap(bitmap);
		}
		break;
	case 1:
		if (const wxBitmap* bmp = m_bitmap.GetLargeBmp()) {
			m_btn_review->SetBitmap(*bmp);
		}
		break;
	}
}

}<|endoftext|>


<commit_before>/*******************************************************************************
 * c7a/api/bootstrap.hpp
 *
 * Part of Project c7a.
 *
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef C7A_API_BOOTSTRAP_HEADER
#define C7A_API_BOOTSTRAP_HEADER

#include <tuple>

#include <c7a/api/context.hpp>
#include <c7a/common/stats_timer.hpp>
#include <c7a/common/cmdline_parser.hpp>

namespace c7a {
namespace bootstrap {

std::tuple<int, size_t, std::vector<std::string> > ParseArgs(int argc, char* argv[]) {
    //replace with arbitrary compex implementation
    size_t my_rank;
    std::vector<std::string> endpoints;
    c7a::common::CmdlineParser clp;

    clp.SetVerboseProcess(false);

    unsigned int rank = 1;
    clp.AddUInt('r', "rank", "R", rank,
                "Rank of this worker");

    std::vector<std::string> addr;
    clp.AddParamStringlist("addresses", addr,
                           "List of all worker addresses.");

    if (!clp.Process(argc, argv)) {
        return std::make_tuple(-1, my_rank, endpoints);
    }

    for (auto address : addr) {
        if (address.find(":") == std::string::npos) {
            std::cerr << "Invalid address. No Portnumber detecable";
            return std::make_tuple(-1, my_rank, endpoints);
        }
    }

    if (argc > 2) {
        my_rank = rank;
        endpoints.assign(addr.begin(), addr.end());
    }
    else if (argc == 2) {
        std::cerr << "Wrong number of arguments. Must be 0 or > 1";
        return std::make_tuple(-1, my_rank, endpoints);
    }
    else {
        my_rank = 0;
        endpoints.push_back("127.0.0.1:1234");
    }
    return std::make_tuple(0, my_rank, endpoints);
}
}   //namespace bootstrap

//! Executes the given job startpoint with a context instance.
//! Startpoint may be called multiple times with concurrent threads and
//! different context instances.
//!
//! \returns result of word_count if bootstrapping was successfull, -1 otherwise.
static int Execute(int argc, char* argv[], std::function<int(Context&)> job_startpoint) {

    //!True if program time should be taken and printed

    static const bool debug = false;

    size_t my_rank;
    std::vector<std::string> endpoints;
    int result;
    std::tie(result, my_rank, endpoints) = bootstrap::ParseArgs(argc, argv);
    if (result != 0)
        return -1;

    if (my_rank >= endpoints.size()) {
        std::cerr << "endpoint list (" <<
            endpoints.size() <<
            " entries) does not include my rank (" <<
            my_rank << ")" << std::endl;
        return -1;
    }

    LOG << "executing " << argv[0] << " with rank " << my_rank << " and endpoints";
    for (const auto& ep : endpoints)
        LOG << ep << " ";

    Context ctx;
    LOG << "connecting to peers";
    ctx.job_manager().Connect(my_rank, net::Endpoint::ParseEndpointList(endpoints));
    LOG << "Starting job on Worker " << ctx.rank();
    auto overall_timer = ctx.get_stats().CreateTimer("job::overall", "", true);
    auto job_result = job_startpoint(ctx);
    overall_timer->Stop();
    LOG << "Worker " << ctx.rank() << " done!";
    return job_result;
}

static inline void
ExecuteThreads(const size_t & workers, const size_t & port_base,
               std::function<void(Context&)> job_startpoint) {

    std::vector<std::thread> threads(workers);
    std::vector<char**> arguments(workers);
    std::vector<std::vector<std::string> > strargs(workers);

    for (size_t i = 0; i < workers; i++) {

        arguments[i] = new char*[workers + 3];
        strargs[i].resize(workers + 3);

        for (size_t j = 0; j < workers; j++) {
            strargs[i][j + 3] += "127.0.0.1:";
            strargs[i][j + 3] += std::to_string(port_base + j);
            arguments[i][j + 3] = const_cast<char*>(strargs[i][j + 3].c_str());
        }

        strargs[i][0] = "local_c7a";
        arguments[i][0] = const_cast<char*>(strargs[i][0].c_str());
        strargs[i][1] = "-r";
        arguments[i][1] = const_cast<char*>(strargs[i][1].c_str());
        strargs[i][2] = std::to_string(i);
        arguments[i][2] = const_cast<char*>(strargs[i][2].c_str());

        std::function<int(Context&)> intReturningFunction = [job_startpoint](Context& ctx) {
            job_startpoint(ctx);
            return 1;
        };

        threads[i] = std::thread([=]() { Execute(workers + 3, arguments[i], intReturningFunction); });
    }

    for (size_t i = 0; i < workers; i++) {
      threads[i].join();
    }
}

} // namespace bootstrap

#endif // !C7A_API_BOOTSTRAP_HEADER

/******************************************************************************/
<commit_msg>fix typos<commit_after>/*******************************************************************************
 * c7a/api/bootstrap.hpp
 *
 * Part of Project c7a.
 *
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef C7A_API_BOOTSTRAP_HEADER
#define C7A_API_BOOTSTRAP_HEADER

#include <tuple>

#include <c7a/api/context.hpp>
#include <c7a/common/stats_timer.hpp>
#include <c7a/common/cmdline_parser.hpp>

namespace c7a {
namespace bootstrap {

std::tuple<int, size_t, std::vector<std::string> > ParseArgs(int argc, char* argv[]) {
    //replace with arbitrary complex implementation
    size_t my_rank;
    std::vector<std::string> endpoints;
    c7a::common::CmdlineParser clp;

    clp.SetVerboseProcess(false);

    unsigned int rank = 1;
    clp.AddUInt('r', "rank", "R", rank,
                "Rank of this worker");

    std::vector<std::string> addr;
    clp.AddParamStringlist("addresses", addr,
                           "List of all worker addresses.");

    if (!clp.Process(argc, argv)) {
        return std::make_tuple(-1, my_rank, endpoints);
    }

    for (auto address : addr) {
        if (address.find(":") == std::string::npos) {
            std::cerr << "Invalid address. No Portnumber detectable";
            return std::make_tuple(-1, my_rank, endpoints);
        }
    }

    if (argc > 2) {
        my_rank = rank;
        endpoints.assign(addr.begin(), addr.end());
    }
    else if (argc == 2) {
        std::cerr << "Wrong number of arguments. Must be 0 or > 1";
        return std::make_tuple(-1, my_rank, endpoints);
    }
    else {
        my_rank = 0;
        endpoints.push_back("127.0.0.1:1234");
    }
    return std::make_tuple(0, my_rank, endpoints);
}
}   //namespace bootstrap

//! Executes the given job startpoint with a context instance.
//! Startpoint may be called multiple times with concurrent threads and
//! different context instances.
//!
//! \returns result of word_count if bootstrapping was successfull, -1 otherwise.
static int Execute(int argc, char* argv[], std::function<int(Context&)> job_startpoint) {

    //!True if program time should be taken and printed

    static const bool debug = false;

    size_t my_rank;
    std::vector<std::string> endpoints;
    int result;
    std::tie(result, my_rank, endpoints) = bootstrap::ParseArgs(argc, argv);
    if (result != 0)
        return -1;

    if (my_rank >= endpoints.size()) {
        std::cerr << "endpoint list (" <<
            endpoints.size() <<
            " entries) does not include my rank (" <<
            my_rank << ")" << std::endl;
        return -1;
    }

    LOG << "executing " << argv[0] << " with rank " << my_rank << " and endpoints";
    for (const auto& ep : endpoints)
        LOG << ep << " ";

    Context ctx;
    LOG << "connecting to peers";
    ctx.job_manager().Connect(my_rank, net::Endpoint::ParseEndpointList(endpoints));
    LOG << "Starting job on Worker " << ctx.rank();
    auto overall_timer = ctx.get_stats().CreateTimer("job::overall", "", true);
    auto job_result = job_startpoint(ctx);
    overall_timer->Stop();
    LOG << "Worker " << ctx.rank() << " done!";
    return job_result;
}

static inline void
ExecuteThreads(const size_t & workers, const size_t & port_base,
               std::function<void(Context&)> job_startpoint) {

    std::vector<std::thread> threads(workers);
    std::vector<char**> arguments(workers);
    std::vector<std::vector<std::string> > strargs(workers);

    for (size_t i = 0; i < workers; i++) {

        arguments[i] = new char*[workers + 3];
        strargs[i].resize(workers + 3);

        for (size_t j = 0; j < workers; j++) {
            strargs[i][j + 3] += "127.0.0.1:";
            strargs[i][j + 3] += std::to_string(port_base + j);
            arguments[i][j + 3] = const_cast<char*>(strargs[i][j + 3].c_str());
        }

        strargs[i][0] = "local_c7a";
        arguments[i][0] = const_cast<char*>(strargs[i][0].c_str());
        strargs[i][1] = "-r";
        arguments[i][1] = const_cast<char*>(strargs[i][1].c_str());
        strargs[i][2] = std::to_string(i);
        arguments[i][2] = const_cast<char*>(strargs[i][2].c_str());

        std::function<int(Context&)> intReturningFunction = [job_startpoint](Context& ctx) {
            job_startpoint(ctx);
            return 1;
        };

        threads[i] = std::thread([=]() { Execute(workers + 3, arguments[i], intReturningFunction); });
    }

    for (size_t i = 0; i < workers; i++) {
      threads[i].join();
    }
}

} // namespace bootstrap

#endif // !C7A_API_BOOTSTRAP_HEADER

/******************************************************************************/
<|endoftext|>


<commit_before>#include "RdYarpImageManager.hpp"

//-- Initialize static members
rd::RdYarpImageManager * rd::RdYarpImageManager::uniqueInstance = NULL;
const std::string rd::RdYarpImageManager::id = "YARP";

bool rd::RdYarpImageManager::start()
{
    yarp::os::NetworkBase::initMinimum();

    imagePort.open(local_port_name.c_str());
    imagePort.useCallback(*this);

    if(! yarp::os::Network::connect( remote_port_name.c_str(), local_port_name.c_str(), "mjpeg" ) )
    {
        RD_WARNING("Could not connect to robot camera via mjpeg.\n");
		if (!yarp::os::Network::connect(remote_port_name.c_str(), local_port_name.c_str()))
		{
            RD_ERROR("Could not connect to robot camera.\n");
            RD_INFO("If you prefer a fake camera use the '--mockupImageManager' or '--yarpLocalImageManager' parameter to run robotDevastation.\n");
            return false;
		}
	}

    RD_SUCCESS("Connected to robot camera.\n");

    stopped = false;
    enabled = false;
    return true;

}

bool rd::RdYarpImageManager::stop()
{
    imagePort.disableCallback();
    imagePort.interrupt();
    imagePort.close();

    stopped = true;
    enabled = false;

    return true;
}

bool rd::RdYarpImageManager::isStopped()
{
    return stopped;
}

bool rd::RdYarpImageManager::setEnabled(bool enabled)
{
    this->enabled = enabled;
    return true;
}

bool rd::RdYarpImageManager::configure(std::string parameter, std::string value)
{
    if ( parameter.compare("remote_img_port") == 0 && value.compare("") != 0)
    {
        remote_port_name = value;
        return true;
    }
    else if ( parameter.compare("local_img_port") == 0 && value.compare("") != 0)
    {
        local_port_name = value;
        return true;
    }
    else
        return RdImageManager::configure(parameter, value);
}

rd::RdImage rd::RdYarpImageManager::getImage()
{
    semaphore.wait();
    RdImage return_image(image);
    semaphore.post();

    return return_image;
}

bool rd::RdYarpImageManager::RegisterManager()
{
    if (uniqueInstance == NULL)
    {
        uniqueInstance = new RdYarpImageManager();
    }

    return Register( uniqueInstance, id);
}

rd::RdYarpImageManager::~RdYarpImageManager()
{
    uniqueInstance = NULL;
}

void rd::RdYarpImageManager::onRead(rd::RdImage &image)
{
    semaphore.wait();
    this->image=image;
    semaphore.post();

    //-- Notify listeners
    if (enabled)
        for (int i = 0; i < listeners.size(); i++)
            listeners[i]->onImageArrived(this);
    else
    {
        RD_WARNING("YarpImageManager is disabled!\n");
    }
}

rd::RdYarpImageManager::RdYarpImageManager()
{
    stopped = true;
    enabled = false;
}
<commit_msg>RdYarpImageManager add extra check for yarp network<commit_after>#include "RdYarpImageManager.hpp"

//-- Initialize static members
rd::RdYarpImageManager * rd::RdYarpImageManager::uniqueInstance = NULL;
const std::string rd::RdYarpImageManager::id = "YARP";

bool rd::RdYarpImageManager::start()
{
    yarp::os::NetworkBase::initMinimum();

    if ( ! yarp::os::NetworkBase::checkNetwork() )
    {
        RD_ERROR("Found no yarp network (try running 'yarpserver &'', or '--mockupImageManager' or '--yarpLocalImageManager' for Fake robot camera). Bye!\n");
        return false;
    }

    imagePort.open(local_port_name.c_str());
    imagePort.useCallback(*this);

    if(! yarp::os::Network::connect( remote_port_name.c_str(), local_port_name.c_str(), "mjpeg" ) )
    {
        RD_WARNING("Could not connect to robot camera via mjpeg.\n");
		if (!yarp::os::Network::connect(remote_port_name.c_str(), local_port_name.c_str()))
		{
            RD_ERROR("Could not connect to robot camera.\n");
            RD_INFO("If you prefer a fake camera use the '--mockupImageManager' or '--yarpLocalImageManager' parameter to run robotDevastation.\n");
            return false;
		}
	}

    RD_SUCCESS("Connected to robot camera.\n");

    stopped = false;
    enabled = false;
    return true;

}

bool rd::RdYarpImageManager::stop()
{
    imagePort.disableCallback();
    imagePort.interrupt();
    imagePort.close();

    stopped = true;
    enabled = false;

    return true;
}

bool rd::RdYarpImageManager::isStopped()
{
    return stopped;
}

bool rd::RdYarpImageManager::setEnabled(bool enabled)
{
    this->enabled = enabled;
    return true;
}

bool rd::RdYarpImageManager::configure(std::string parameter, std::string value)
{
    if ( parameter.compare("remote_img_port") == 0 && value.compare("") != 0)
    {
        remote_port_name = value;
        return true;
    }
    else if ( parameter.compare("local_img_port") == 0 && value.compare("") != 0)
    {
        local_port_name = value;
        return true;
    }
    else
        return RdImageManager::configure(parameter, value);
}

rd::RdImage rd::RdYarpImageManager::getImage()
{
    semaphore.wait();
    RdImage return_image(image);
    semaphore.post();

    return return_image;
}

bool rd::RdYarpImageManager::RegisterManager()
{
    if (uniqueInstance == NULL)
    {
        uniqueInstance = new RdYarpImageManager();
    }

    return Register( uniqueInstance, id);
}

rd::RdYarpImageManager::~RdYarpImageManager()
{
    uniqueInstance = NULL;
}

void rd::RdYarpImageManager::onRead(rd::RdImage &image)
{
    semaphore.wait();
    this->image=image;
    semaphore.post();

    //-- Notify listeners
    if (enabled)
        for (int i = 0; i < listeners.size(); i++)
            listeners[i]->onImageArrived(this);
    else
    {
        RD_WARNING("YarpImageManager is disabled!\n");
    }
}

rd::RdYarpImageManager::RdYarpImageManager()
{
    stopped = true;
    enabled = false;
}
<|endoftext|>


<commit_before>
// Copyright (c) 2012 Nokia, Inc.
// Copyright (c) 2013-2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <string.h>
#include <poll.h>
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>

#include "portal.h"
#include "sock_utils.h"

#ifndef NO_CPP_PORTAL_CODE
PortalPoller *defaultPoller = new PortalPoller();
uint64_t poll_enter_time, poll_return_time; // for performance measurement

PortalPoller::PortalPoller()
  : portal_wrappers(0), portal_fds(0), numFds(0), inited(0), numWrappers(0), stopping(0)
{
    int rc = pipe(pipefd);
    sem_init(&sem_startup, 0, 0);
    pthread_mutex_init(&mutex, NULL);
    fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
    addFd(pipefd[0]);
}

int PortalPoller::unregisterInstance(Portal *portal)
{
  int i = 0;
  pthread_mutex_lock(&mutex);
  while(i < numWrappers){
    if(portal_wrappers[i]->pint.fpga_number == portal->pint.fpga_number) {
      fprintf(stderr, "PortalPoller::unregisterInstance %d %d\n", i, portal->pint.fpga_number);
      break;
    }
    i++;
  }

  while(i < numWrappers-1){
    portal_wrappers[i] = portal_wrappers[i+1];
    i++;
  }
  numWrappers--;
  i = 0;
  while(i < numFds){
    if(portal_fds[i].fd == portal->pint.fpga_fd)
      break;
    i++;
  }

  while(i < numFds-1){
    portal_fds[i] = portal_fds[i+1];
    i++;
  }
  numFds--;
  pthread_mutex_unlock(&mutex);
  return 0;
}

void PortalPoller::addFd(int fd)
{
    /* this internal function assumes mutex locked by caller.
     * since it can be called from addFdToPoller(), which was called under mutex lock
     * portalExec_event().
     */
    numFds++;
    portal_fds = (struct pollfd *)realloc(portal_fds, numFds*sizeof(struct pollfd));
    struct pollfd *pollfd = &portal_fds[numFds-1];
    memset(pollfd, 0, sizeof(struct pollfd));
    pollfd->fd = fd;
    pollfd->events = POLLIN;
}
int PortalPoller::registerInstance(Portal *portal)
{
    uint8_t ch = 0;
    int rc;
    pthread_mutex_lock(&mutex);
    rc = write(pipefd[1], &ch, 1); // get poll to return, so that it is no long using portal_fds (which gets realloc'ed)
    numWrappers++;
    fprintf(stderr, "Portal::registerInstance fpga%d fd %d clients %d\n", portal->pint.fpga_number, portal->pint.fpga_fd, portal->pint.client_fd_number);
    portal_wrappers = (Portal **)realloc(portal_wrappers, numWrappers*sizeof(Portal *));
    portal_wrappers[numWrappers-1] = portal;

    if (portal->pint.fpga_fd != -1)
        addFd(portal->pint.fpga_fd);
    for (int i = 0; i < portal->pint.client_fd_number; i++)
        addFd(portal->pint.client_fd[i]);
    portal->pint.item->enableint(&portal->pint, 1);
    pthread_mutex_unlock(&mutex);
    portalExec_start();
    return 0;
}

void* PortalPoller::portalExec_init(void)
{
    portalExec_timeout = -1; // no interrupt timeout
#ifdef XSIM
    portalExec_timeout = 100;
#endif
#ifdef BSIM
    portalExec_timeout = 100;
    if (global_sockfd != -1) {
        pthread_mutex_lock(&mutex);
        addFd(global_sockfd);
        pthread_mutex_unlock(&mutex);
    }
#endif
#if 0
    pthread_mutex_lock(&mutex);
    if (!numFds) {
        fprintf(stderr, "portalExec No fds open numFds=%d\n", numFds);
        return (void*)-ENODEV;
    }
    for (int i = 0; i < numWrappers; i++) {
      Portal *instance = portal_wrappers[i];
      //fprintf(stderr, "portalExec::enabling interrupts portal %d fpga%d\n", i, instance->pint.fpga_number);
      instance->pint.item->enableint(&instance->pint, 1);
    }
    pthread_mutex_unlock(&mutex);
#endif
    fprintf(stderr, "portalExec::about to enter loop, numFds=%d\n", numFds);
    return NULL;
}
void PortalPoller::portalExec_stop(void)
{
    uint8_t ch = 0;
    int rc;
    stopping = 1;
    rc = write(pipefd[1], &ch, 1);
}
void PortalPoller::portalExec_end(void)
{
    stopping = 1;
    printf("%s: don't disable interrupts when stopping\n", __FUNCTION__);
    return;
    pthread_mutex_lock(&mutex);
    for (int i = 0; i < numWrappers; i++) {
      Portal *instance = portal_wrappers[i];
      fprintf(stderr, "portalExec::disabling interrupts portal %d fpga%d\n", i, instance->pint.fpga_number);
      instance->pint.item->enableint(&instance->pint, 0);
    }
    pthread_mutex_unlock(&mutex);
}

void* PortalPoller::portalExec_poll(int timeout)
{
    long rc = 0;
    if (timeout != 0)
      rc = poll(portal_fds, numFds, timeout);
    if(rc < 0) {
      // return only in error case
      fprintf(stderr, "poll returned rc=%ld errno=%d:%s\n", rc, errno, strerror(errno));
    }
    return (void*)rc;
}

void* PortalPoller::portalExec_event(void)
{
    uint8_t ch;
    int rc;
    pthread_mutex_lock(&mutex);
    rc = read(pipefd[0], &ch, 1);
    for (int i = 0; i < numWrappers; i++) {
       if (!portal_wrappers)
           fprintf(stderr, "No portal_instances revents=%d\n", portal_fds[i].revents);
       Portal *instance = portal_wrappers[i];
       if (instance->pint.handler) {
           instance->pint.item->event(&instance->pint);
           // re-enable interrupt which was disabled by portal_isr
           instance->pint.item->enableint(&instance->pint, 1);
       }
    }
    pthread_mutex_unlock(&mutex);
    return NULL;
}
extern "C" void addFdToPoller(struct PortalPoller *poller, int fd)
{
    poller->addFd(fd);
}

void* PortalPoller::portalExec(void* __x)
{
    void *rc = portalExec_init();
    sem_post(&sem_startup);
    while (!rc && !stopping) {
        rc = portalExec_poll(portalExec_timeout);
        if ((long) rc >= 0)
            rc = portalExec_event();
    }
    portalExec_end();
    printf("[%s] thread ending\n", __FUNCTION__);
    return rc;
}

void* portalExec(void* __x)
{
  return defaultPoller->portalExec(__x);
}

void* portalExec_init(void)
{
  return defaultPoller->portalExec_init();
}

void* portalExec_poll(int timeout)
{
  return defaultPoller->portalExec_poll(timeout);
}

void* portalExec_event(void)
{
  return defaultPoller->portalExec_event();
}

void portalExec_end(void)
{
  defaultPoller->portalExec_end();
}

static void *pthread_worker(void *__x)
{
    ((PortalPoller *)__x)->portalExec(__x);
    return 0;
}
void PortalPoller::portalExec_start()
{
    pthread_t threaddata;
    pthread_mutex_lock(&mutex);
    if (inited) {
        pthread_mutex_unlock(&mutex);
        return;
    }
    inited = 1;
    pthread_mutex_unlock(&mutex);
    pthread_create(&threaddata, NULL, &pthread_worker, (void *)this);
    sem_wait(&sem_startup);
}
void portalExec_start()
{
    defaultPoller->portalExec_start();
}
void portalExec_stop()
{
    defaultPoller->portalExec_stop();
}

#endif // NO_CPP_PORTAL_CODE
<commit_msg>set timeout to 100, not sure zedboard interrupts working<commit_after>
// Copyright (c) 2012 Nokia, Inc.
// Copyright (c) 2013-2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <string.h>
#include <poll.h>
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>

#include "portal.h"
#include "sock_utils.h"

#ifndef NO_CPP_PORTAL_CODE
PortalPoller *defaultPoller = new PortalPoller();
uint64_t poll_enter_time, poll_return_time; // for performance measurement

PortalPoller::PortalPoller()
  : portal_wrappers(0), portal_fds(0), numFds(0), inited(0), numWrappers(0), stopping(0)
{
    int rc = pipe(pipefd);
    sem_init(&sem_startup, 0, 0);
    pthread_mutex_init(&mutex, NULL);
    fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
    addFd(pipefd[0]);
}

int PortalPoller::unregisterInstance(Portal *portal)
{
  int i = 0;
  pthread_mutex_lock(&mutex);
  while(i < numWrappers){
    if(portal_wrappers[i]->pint.fpga_number == portal->pint.fpga_number) {
      fprintf(stderr, "PortalPoller::unregisterInstance %d %d\n", i, portal->pint.fpga_number);
      break;
    }
    i++;
  }

  while(i < numWrappers-1){
    portal_wrappers[i] = portal_wrappers[i+1];
    i++;
  }
  numWrappers--;
  i = 0;
  while(i < numFds){
    if(portal_fds[i].fd == portal->pint.fpga_fd)
      break;
    i++;
  }

  while(i < numFds-1){
    portal_fds[i] = portal_fds[i+1];
    i++;
  }
  numFds--;
  pthread_mutex_unlock(&mutex);
  return 0;
}

void PortalPoller::addFd(int fd)
{
    /* this internal function assumes mutex locked by caller.
     * since it can be called from addFdToPoller(), which was called under mutex lock
     * portalExec_event().
     */
    numFds++;
    portal_fds = (struct pollfd *)realloc(portal_fds, numFds*sizeof(struct pollfd));
    struct pollfd *pollfd = &portal_fds[numFds-1];
    memset(pollfd, 0, sizeof(struct pollfd));
    pollfd->fd = fd;
    pollfd->events = POLLIN;
}
int PortalPoller::registerInstance(Portal *portal)
{
    uint8_t ch = 0;
    int rc;
    pthread_mutex_lock(&mutex);
    rc = write(pipefd[1], &ch, 1); // get poll to return, so that it is no long using portal_fds (which gets realloc'ed)
    numWrappers++;
    fprintf(stderr, "Portal::registerInstance fpga%d fd %d clients %d\n", portal->pint.fpga_number, portal->pint.fpga_fd, portal->pint.client_fd_number);
    portal_wrappers = (Portal **)realloc(portal_wrappers, numWrappers*sizeof(Portal *));
    portal_wrappers[numWrappers-1] = portal;

    if (portal->pint.fpga_fd != -1)
        addFd(portal->pint.fpga_fd);
    for (int i = 0; i < portal->pint.client_fd_number; i++)
        addFd(portal->pint.client_fd[i]);
    portal->pint.item->enableint(&portal->pint, 1);
    pthread_mutex_unlock(&mutex);
    portalExec_start();
    return 0;
}

void* PortalPoller::portalExec_init(void)
{
    portalExec_timeout = 100; // no interrupt timeout
#ifdef XSIM
    portalExec_timeout = 100;
#endif
#ifdef BSIM
    portalExec_timeout = 100;
    if (global_sockfd != -1) {
        pthread_mutex_lock(&mutex);
        addFd(global_sockfd);
        pthread_mutex_unlock(&mutex);
    }
#endif
#if 0
    pthread_mutex_lock(&mutex);
    if (!numFds) {
        fprintf(stderr, "portalExec No fds open numFds=%d\n", numFds);
        return (void*)-ENODEV;
    }
    for (int i = 0; i < numWrappers; i++) {
      Portal *instance = portal_wrappers[i];
      //fprintf(stderr, "portalExec::enabling interrupts portal %d fpga%d\n", i, instance->pint.fpga_number);
      instance->pint.item->enableint(&instance->pint, 1);
    }
    pthread_mutex_unlock(&mutex);
#endif
    fprintf(stderr, "portalExec::about to enter loop, numFds=%d\n", numFds);
    return NULL;
}
void PortalPoller::portalExec_stop(void)
{
    uint8_t ch = 0;
    int rc;
    stopping = 1;
    rc = write(pipefd[1], &ch, 1);
}
void PortalPoller::portalExec_end(void)
{
    stopping = 1;
    printf("%s: don't disable interrupts when stopping\n", __FUNCTION__);
    return;
    pthread_mutex_lock(&mutex);
    for (int i = 0; i < numWrappers; i++) {
      Portal *instance = portal_wrappers[i];
      fprintf(stderr, "portalExec::disabling interrupts portal %d fpga%d\n", i, instance->pint.fpga_number);
      instance->pint.item->enableint(&instance->pint, 0);
    }
    pthread_mutex_unlock(&mutex);
}

void* PortalPoller::portalExec_poll(int timeout)
{
    long rc = 0;
    if (timeout != 0)
      rc = poll(portal_fds, numFds, timeout);
    if(rc < 0) {
      // return only in error case
      fprintf(stderr, "poll returned rc=%ld errno=%d:%s\n", rc, errno, strerror(errno));
    }
    return (void*)rc;
}

void* PortalPoller::portalExec_event(void)
{
    uint8_t ch;
    int rc;
    pthread_mutex_lock(&mutex);
    rc = read(pipefd[0], &ch, 1);
    for (int i = 0; i < numWrappers; i++) {
       if (!portal_wrappers)
           fprintf(stderr, "No portal_instances revents=%d\n", portal_fds[i].revents);
       Portal *instance = portal_wrappers[i];
       if (instance->pint.handler) {
           instance->pint.item->event(&instance->pint);
           // re-enable interrupt which was disabled by portal_isr
           instance->pint.item->enableint(&instance->pint, 1);
       }
    }
    pthread_mutex_unlock(&mutex);
    return NULL;
}
extern "C" void addFdToPoller(struct PortalPoller *poller, int fd)
{
    poller->addFd(fd);
}

void* PortalPoller::portalExec(void* __x)
{
    void *rc = portalExec_init();
    sem_post(&sem_startup);
    while (!rc && !stopping) {
        rc = portalExec_poll(portalExec_timeout);
        if ((long) rc >= 0)
            rc = portalExec_event();
    }
    portalExec_end();
    printf("[%s] thread ending\n", __FUNCTION__);
    return rc;
}

void* portalExec(void* __x)
{
  return defaultPoller->portalExec(__x);
}

void* portalExec_init(void)
{
  return defaultPoller->portalExec_init();
}

void* portalExec_poll(int timeout)
{
  return defaultPoller->portalExec_poll(timeout);
}

void* portalExec_event(void)
{
  return defaultPoller->portalExec_event();
}

void portalExec_end(void)
{
  defaultPoller->portalExec_end();
}

static void *pthread_worker(void *__x)
{
    ((PortalPoller *)__x)->portalExec(__x);
    return 0;
}
void PortalPoller::portalExec_start()
{
    pthread_t threaddata;
    pthread_mutex_lock(&mutex);
    if (inited) {
        pthread_mutex_unlock(&mutex);
        return;
    }
    inited = 1;
    pthread_mutex_unlock(&mutex);
    pthread_create(&threaddata, NULL, &pthread_worker, (void *)this);
    sem_wait(&sem_startup);
}
void portalExec_start()
{
    defaultPoller->portalExec_start();
}
void portalExec_stop()
{
    defaultPoller->portalExec_stop();
}

#endif // NO_CPP_PORTAL_CODE
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/keygen_handler.h"

#include <Security/SecAsn1Coder.h>
#include <Security/SecAsn1Templates.h>
#include <Security/Security.h>

#include "base/base64.h"
#include "base/logging.h"
#include "base/scoped_cftyperef.h"

// These are in Security.framework but not declared in a public header.
extern const SecAsn1Template kSecAsn1AlgorithmIDTemplate[];
extern const SecAsn1Template kSecAsn1SubjectPublicKeyInfoTemplate[];

namespace net {

// Declarations of Netscape keygen cert structures for ASN.1 encoding:

struct PublicKeyAndChallenge {
  CSSM_X509_SUBJECT_PUBLIC_KEY_INFO spki;
  CSSM_DATA challenge_string;
};

// This is a copy of the built-in kSecAsn1IA5StringTemplate, but without the
// 'streamable' flag, which was causing bogus data to be written.
const SecAsn1Template kIA5StringTemplate[] = {
    { SEC_ASN1_IA5_STRING, 0, NULL, sizeof(CSSM_DATA) }
};

static const SecAsn1Template kPublicKeyAndChallengeTemplate[] = {
  {
    SEC_ASN1_SEQUENCE,
    0,
    NULL,
    sizeof(PublicKeyAndChallenge)
  },
  {
    SEC_ASN1_INLINE,
    offsetof(PublicKeyAndChallenge, spki),
    kSecAsn1SubjectPublicKeyInfoTemplate
  },
  {
    SEC_ASN1_INLINE,
    offsetof(PublicKeyAndChallenge, challenge_string),
    kIA5StringTemplate
  },
  {
    0
  }
};

struct SignedPublicKeyAndChallenge {
  PublicKeyAndChallenge pkac;
  CSSM_X509_ALGORITHM_IDENTIFIER signature_algorithm;
  CSSM_DATA signature;
};

static const SecAsn1Template kSignedPublicKeyAndChallengeTemplate[] = {
  {
    SEC_ASN1_SEQUENCE,
    0,
    NULL,
    sizeof(SignedPublicKeyAndChallenge)
  },
  {
    SEC_ASN1_INLINE,
    offsetof(SignedPublicKeyAndChallenge, pkac),
    kPublicKeyAndChallengeTemplate
  },
  {
    SEC_ASN1_INLINE,
    offsetof(SignedPublicKeyAndChallenge, signature_algorithm),
    kSecAsn1AlgorithmIDTemplate
  },
  {
    SEC_ASN1_BIT_STRING,
    offsetof(SignedPublicKeyAndChallenge, signature)
  },
  {
    0
  }
};

static OSStatus CreateRSAKeyPair(int size_in_bits,
                                 SecKeyRef* out_pub_key,
                                 SecKeyRef* out_priv_key);
static OSStatus SignData(CSSM_DATA data,
                         SecKeyRef private_key,
                         CSSM_DATA* signature);

std::string KeygenHandler::GenKeyAndSignChallenge() {
  std::string result;
  OSStatus err;
  SecKeyRef public_key = NULL;
  SecKeyRef private_key = NULL;
  SecAsn1CoderRef coder = NULL;
  CSSM_DATA signature = {0, NULL};

  {
    // Create the key-pair.
    err = CreateRSAKeyPair(key_size_in_bits_, &public_key, &private_key);
    if (err)
      goto failure;

    // Get the public key data (DER sequence of modulus, exponent).
    CFDataRef key_data = NULL;
    err = SecKeychainItemExport(public_key, kSecFormatBSAFE, 0, NULL,
                                &key_data);
    if (err)
      goto failure;
    scoped_cftyperef<CFDataRef> scoped_key_data(key_data);

    // Create an ASN.1 encoder.
    err = SecAsn1CoderCreate(&coder);
    if (err)
      goto failure;

    // Fill in and DER-encode the PublicKeyAndChallenge:
    SignedPublicKeyAndChallenge spkac;
    memset(&spkac, 0, sizeof(spkac));
    spkac.pkac.spki.algorithm.algorithm = CSSMOID_RSA;
    spkac.pkac.spki.subjectPublicKey.Length =
        CFDataGetLength(key_data) * 8;  // interpreted as a _bit_ count
    spkac.pkac.spki.subjectPublicKey.Data =
        const_cast<uint8_t*>(CFDataGetBytePtr(key_data));
    spkac.pkac.challenge_string.Length = challenge_.length();
    spkac.pkac.challenge_string.Data =
        reinterpret_cast<uint8_t*>(const_cast<char*>(challenge_.data()));

    CSSM_DATA encoded;
    err = SecAsn1EncodeItem(coder, &spkac.pkac,
                            kPublicKeyAndChallengeTemplate, &encoded);
    if (err)
      goto failure;

    // Compute a signature of the result:
    err = SignData(encoded, private_key, &signature);
    if (err)
      goto failure;
    spkac.signature.Data = signature.Data;
    spkac.signature.Length = signature.Length * 8;  // a _bit_ count
    spkac.signature_algorithm.algorithm = CSSMOID_MD5WithRSA;
    // TODO(snej): MD5 is weak. Can we use SHA1 instead?
    // See <https://bugzilla.mozilla.org/show_bug.cgi?id=549460>

    // DER-encode the entire SignedPublicKeyAndChallenge:
    err = SecAsn1EncodeItem(coder, &spkac,
                            kSignedPublicKeyAndChallengeTemplate, &encoded);
    if (err)
      goto failure;

    // Base64 encode the result.
    std::string input(reinterpret_cast<char*>(encoded.Data), encoded.Length);
    base::Base64Encode(input, &result);
  }

 failure:
  if (err) {
    LOG(ERROR) << "SSL Keygen failed! OSStatus = " << err;
  } else {
    LOG(INFO) << "SSL Keygen succeeded! Output is: " << result;
  }

  // Remove keys from keychain if asked to during unit testing:
  if (!stores_key_) {
    if (public_key)
      SecKeychainItemDelete(reinterpret_cast<SecKeychainItemRef>(public_key));
    if (private_key)
      SecKeychainItemDelete(reinterpret_cast<SecKeychainItemRef>(private_key));
  }

  // Clean up:
  free(signature.Data);
  if (coder)
    SecAsn1CoderRelease(coder);
  if (public_key)
    CFRelease(public_key);
  if (private_key)
    CFRelease(private_key);
  return result;
}

static OSStatus CreateRSAKeyPair(int size_in_bits,
                                 SecKeyRef* out_pub_key,
                                 SecKeyRef* out_priv_key) {
  OSStatus err;
  SecKeychainRef keychain;
  err = SecKeychainCopyDefault(&keychain);
  if (err)
    return err;
  scoped_cftyperef<SecKeychainRef> scoped_keychain(keychain);
  return SecKeyCreatePair(
      keychain,
      CSSM_ALGID_RSA,
      size_in_bits,
      0LL,
      // public key usage and attributes:
      CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP,
      CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT,
      // private key usage and attributes:
      CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN | CSSM_KEYUSE_UNWRAP,
      CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT |
          CSSM_KEYATTR_SENSITIVE,
      NULL,
      out_pub_key, out_priv_key);
}

static OSStatus CreateSignatureContext(SecKeyRef key,
                                       CSSM_ALGORITHMS algorithm,
                                       CSSM_CC_HANDLE* out_cc_handle) {
  OSStatus err;
  const CSSM_ACCESS_CREDENTIALS* credentials = NULL;
  err = SecKeyGetCredentials(key,
                             CSSM_ACL_AUTHORIZATION_SIGN,
                             kSecCredentialTypeDefault,
                             &credentials);
  if (err)
      return err;

  CSSM_CSP_HANDLE csp_handle = 0;
  err = SecKeyGetCSPHandle(key, &csp_handle);
  if (err)
    return err;

  const CSSM_KEY* cssm_key = NULL;
  err = SecKeyGetCSSMKey(key, &cssm_key);
  if (err)
    return err;

  return CSSM_CSP_CreateSignatureContext(csp_handle,
                                         algorithm,
                                         credentials,
                                         cssm_key,
                                         out_cc_handle);
}

static OSStatus SignData(CSSM_DATA data,
                         SecKeyRef private_key,
                         CSSM_DATA* signature) {
  CSSM_CC_HANDLE cc_handle;
  OSStatus err = CreateSignatureContext(private_key,
                                        CSSM_ALGID_MD5WithRSA,
                                        &cc_handle);
  if (err)
    return err;
  err = CSSM_SignData(cc_handle, &data, 1, CSSM_ALGID_NONE, signature);
  CSSM_DeleteContext(cc_handle);
  return err;
}

}  // namespace net
<commit_msg>Log readable versions of OS X keygen errors<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/keygen_handler.h"

#include <Security/SecAsn1Coder.h>
#include <Security/SecAsn1Templates.h>
#include <Security/Security.h>

#include "base/base64.h"
#include "base/crypto/cssm_init.h"
#include "base/logging.h"
#include "base/scoped_cftyperef.h"

// These are in Security.framework but not declared in a public header.
extern const SecAsn1Template kSecAsn1AlgorithmIDTemplate[];
extern const SecAsn1Template kSecAsn1SubjectPublicKeyInfoTemplate[];

namespace net {

// Declarations of Netscape keygen cert structures for ASN.1 encoding:

struct PublicKeyAndChallenge {
  CSSM_X509_SUBJECT_PUBLIC_KEY_INFO spki;
  CSSM_DATA challenge_string;
};

// This is a copy of the built-in kSecAsn1IA5StringTemplate, but without the
// 'streamable' flag, which was causing bogus data to be written.
const SecAsn1Template kIA5StringTemplate[] = {
    { SEC_ASN1_IA5_STRING, 0, NULL, sizeof(CSSM_DATA) }
};

static const SecAsn1Template kPublicKeyAndChallengeTemplate[] = {
  {
    SEC_ASN1_SEQUENCE,
    0,
    NULL,
    sizeof(PublicKeyAndChallenge)
  },
  {
    SEC_ASN1_INLINE,
    offsetof(PublicKeyAndChallenge, spki),
    kSecAsn1SubjectPublicKeyInfoTemplate
  },
  {
    SEC_ASN1_INLINE,
    offsetof(PublicKeyAndChallenge, challenge_string),
    kIA5StringTemplate
  },
  {
    0
  }
};

struct SignedPublicKeyAndChallenge {
  PublicKeyAndChallenge pkac;
  CSSM_X509_ALGORITHM_IDENTIFIER signature_algorithm;
  CSSM_DATA signature;
};

static const SecAsn1Template kSignedPublicKeyAndChallengeTemplate[] = {
  {
    SEC_ASN1_SEQUENCE,
    0,
    NULL,
    sizeof(SignedPublicKeyAndChallenge)
  },
  {
    SEC_ASN1_INLINE,
    offsetof(SignedPublicKeyAndChallenge, pkac),
    kPublicKeyAndChallengeTemplate
  },
  {
    SEC_ASN1_INLINE,
    offsetof(SignedPublicKeyAndChallenge, signature_algorithm),
    kSecAsn1AlgorithmIDTemplate
  },
  {
    SEC_ASN1_BIT_STRING,
    offsetof(SignedPublicKeyAndChallenge, signature)
  },
  {
    0
  }
};

static OSStatus CreateRSAKeyPair(int size_in_bits,
                                 SecKeyRef* out_pub_key,
                                 SecKeyRef* out_priv_key);
static OSStatus SignData(CSSM_DATA data,
                         SecKeyRef private_key,
                         CSSM_DATA* signature);

std::string KeygenHandler::GenKeyAndSignChallenge() {
  std::string result;
  OSStatus err;
  SecKeyRef public_key = NULL;
  SecKeyRef private_key = NULL;
  SecAsn1CoderRef coder = NULL;
  CSSM_DATA signature = {0, NULL};

  {
    // Create the key-pair.
    err = CreateRSAKeyPair(key_size_in_bits_, &public_key, &private_key);
    if (err)
      goto failure;

    // Get the public key data (DER sequence of modulus, exponent).
    CFDataRef key_data = NULL;
    err = SecKeychainItemExport(public_key, kSecFormatBSAFE, 0, NULL,
                                &key_data);
    if (err) {
      base::LogCSSMError("SecKeychainItemExpor", err);
      goto failure;
    }
    scoped_cftyperef<CFDataRef> scoped_key_data(key_data);

    // Create an ASN.1 encoder.
    err = SecAsn1CoderCreate(&coder);
    if (err) {
      base::LogCSSMError("SecAsn1CoderCreate", err);
      goto failure;
    }

    // Fill in and DER-encode the PublicKeyAndChallenge:
    SignedPublicKeyAndChallenge spkac;
    memset(&spkac, 0, sizeof(spkac));
    spkac.pkac.spki.algorithm.algorithm = CSSMOID_RSA;
    spkac.pkac.spki.subjectPublicKey.Length =
        CFDataGetLength(key_data) * 8;  // interpreted as a _bit_ count
    spkac.pkac.spki.subjectPublicKey.Data =
        const_cast<uint8_t*>(CFDataGetBytePtr(key_data));
    spkac.pkac.challenge_string.Length = challenge_.length();
    spkac.pkac.challenge_string.Data =
        reinterpret_cast<uint8_t*>(const_cast<char*>(challenge_.data()));

    CSSM_DATA encoded;
    err = SecAsn1EncodeItem(coder, &spkac.pkac,
                            kPublicKeyAndChallengeTemplate, &encoded);
    if (err) {
      base::LogCSSMError("SecAsn1EncodeItem", err);
      goto failure;
    }

    // Compute a signature of the result:
    err = SignData(encoded, private_key, &signature);
    if (err)
      goto failure;
    spkac.signature.Data = signature.Data;
    spkac.signature.Length = signature.Length * 8;  // a _bit_ count
    spkac.signature_algorithm.algorithm = CSSMOID_MD5WithRSA;
    // TODO(snej): MD5 is weak. Can we use SHA1 instead?
    // See <https://bugzilla.mozilla.org/show_bug.cgi?id=549460>

    // DER-encode the entire SignedPublicKeyAndChallenge:
    err = SecAsn1EncodeItem(coder, &spkac,
                            kSignedPublicKeyAndChallengeTemplate, &encoded);
    if (err) {
      base::LogCSSMError("SecAsn1EncodeItem", err);
      goto failure;
    }

    // Base64 encode the result.
    std::string input(reinterpret_cast<char*>(encoded.Data), encoded.Length);
    base::Base64Encode(input, &result);
  }

 failure:
  if (err) {
    LOG(ERROR) << "SSL Keygen failed! OSStatus = " << err;
  } else {
    LOG(INFO) << "SSL Keygen succeeded! Output is: " << result;
  }

  // Remove keys from keychain if asked to during unit testing:
  if (!stores_key_) {
    if (public_key)
      SecKeychainItemDelete(reinterpret_cast<SecKeychainItemRef>(public_key));
    if (private_key)
      SecKeychainItemDelete(reinterpret_cast<SecKeychainItemRef>(private_key));
  }

  // Clean up:
  free(signature.Data);
  if (coder)
    SecAsn1CoderRelease(coder);
  if (public_key)
    CFRelease(public_key);
  if (private_key)
    CFRelease(private_key);
  return result;
}

static OSStatus CreateRSAKeyPair(int size_in_bits,
                                 SecKeyRef* out_pub_key,
                                 SecKeyRef* out_priv_key) {
  OSStatus err;
  SecKeychainRef keychain;
  err = SecKeychainCopyDefault(&keychain);
  if (err) {
    base::LogCSSMError("SecKeychainCopyDefault", err);
    return err;
  }
  scoped_cftyperef<SecKeychainRef> scoped_keychain(keychain);
  err = SecKeyCreatePair(
      keychain,
      CSSM_ALGID_RSA,
      size_in_bits,
      0LL,
      // public key usage and attributes:
      CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP,
      CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT,
      // private key usage and attributes:
      CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN | CSSM_KEYUSE_UNWRAP,
      CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT |
          CSSM_KEYATTR_SENSITIVE,
      NULL,
      out_pub_key, out_priv_key);
  if (err)
    base::LogCSSMError("SecKeyCreatePair", err);
  return err;
}

static OSStatus CreateSignatureContext(SecKeyRef key,
                                       CSSM_ALGORITHMS algorithm,
                                       CSSM_CC_HANDLE* out_cc_handle) {
  OSStatus err;
  const CSSM_ACCESS_CREDENTIALS* credentials = NULL;
  err = SecKeyGetCredentials(key,
                             CSSM_ACL_AUTHORIZATION_SIGN,
                             kSecCredentialTypeDefault,
                             &credentials);
  if (err) {
    base::LogCSSMError("SecKeyGetCredentials", err);
    return err;
  }

  CSSM_CSP_HANDLE csp_handle = 0;
  err = SecKeyGetCSPHandle(key, &csp_handle);
  if (err) {
    base::LogCSSMError("SecKeyGetCSPHandle", err);
    return err;
  }

  const CSSM_KEY* cssm_key = NULL;
  err = SecKeyGetCSSMKey(key, &cssm_key);
  if (err) {
    base::LogCSSMError("SecKeyGetCSSMKey", err);
    return err;
  }

  err = CSSM_CSP_CreateSignatureContext(csp_handle,
                                        algorithm,
                                        credentials,
                                        cssm_key,
                                        out_cc_handle);
  if (err)
    base::LogCSSMError("CSSM_CSP_CreateSignatureContext", err);
  return err;
}

static OSStatus SignData(CSSM_DATA data,
                         SecKeyRef private_key,
                         CSSM_DATA* signature) {
  CSSM_CC_HANDLE cc_handle;
  OSStatus err = CreateSignatureContext(private_key,
                                        CSSM_ALGID_MD5WithRSA,
                                        &cc_handle);
  if (err) {
    base::LogCSSMError("CreateSignatureContext", err);
    return err;
  }
  err = CSSM_SignData(cc_handle, &data, 1, CSSM_ALGID_NONE, signature);
  if (err)
    base::LogCSSMError("CSSM_SignData", err);
  CSSM_DeleteContext(cc_handle);
  return err;
}

}  // namespace net
<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include <algorithm>
#include <ctime>

#include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/broadcast_socket.hpp" // for is_local et.al
#include "libtorrent/socket_io.hpp" // for hash_address

namespace libtorrent { namespace dht
{

// returns the distance between the two nodes
// using the kademlia XOR-metric
node_id distance(node_id const& n1, node_id const& n2)
{
	node_id ret;
	node_id::iterator k = ret.begin();
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, end(n1.end()); i != end; ++i, ++j, ++k)
	{
		*k = *i ^ *j;
	}
	return ret;
}

// returns true if: distance(n1, ref) < distance(n2, ref)
bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref)
{
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, k = ref.begin(), end(n1.end()); i != end; ++i, ++j, ++k)
	{
		boost::uint8_t lhs = (*i ^ *k);
		boost::uint8_t rhs = (*j ^ *k);
		if (lhs < rhs) return true;
		if (lhs > rhs) return false;
	}
	return false;
}

// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
// useful for finding out which bucket a node belongs to
int distance_exp(node_id const& n1, node_id const& n2)
{
	int byte = node_id::size - 1;
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, end(n1.end()); i != end; ++i, ++j, --byte)
	{
		TORRENT_ASSERT(byte >= 0);
		boost::uint8_t t = *i ^ *j;
		if (t == 0) continue;
		// we have found the first non-zero byte
		// return the bit-number of the first bit
		// that differs
		int bit = byte * 8;
		for (int b = 7; b >= 0; --b)
			if (t >= (1 << b)) return bit + b;
		return bit;
	}

	return 0;
}

struct static_ { static_() { std::srand((unsigned int)std::time(0)); } } static__;

node_id generate_id_impl(address const& ip, boost::uint32_t r)
{
	boost::uint32_t seed = r & 0x7;
	uint32_t modulus = 0x100;

	boost::uint8_t* p = 0;
	int num_octets = 0;
	int mod_shift = 0;

	address_v4::bytes_type b4;
#if TORRENT_USE_IPV6
	address_v6::bytes_type b6;
	if (ip.is_v6())
	{
		b6 = ip.to_v6().to_bytes();
		p = &b6[0];
		num_octets = 8;
		mod_shift = 3;
	}
	else
#endif
	{
		b4 = ip.to_v4().to_bytes();
		p = &b4[0];
		num_octets = 4;
		mod_shift = 6;
	}

	while (num_octets)
	{
		seed *= p[num_octets];
		seed &= (modulus-1);
		modulus <<= mod_shift;
		--num_octets;
	}

	seed = htonl(seed);

	node_id id = hasher((const char*)&seed, sizeof(seed)).final();

	for (int i = 4; i < 19; ++i) id[i] = rand();

	id[19] = r;

	return id;
}

node_id generate_random_id()
{
	char random[20];
	for (int i = 0; i < 20; ++i) random[i] = rand();
	return hasher(random, 20).final();
}

// verifies whether a node-id matches the IP it's used from
// returns true if the node-id is OK coming from this source
// and false otherwise.
bool verify_id(node_id const& nid, address const& source_ip)
{
	// no need to verify local IPs, they would be incorrect anyway
	if (is_local(source_ip)) return true;

	node_id h = generate_id_impl(source_ip, nid[19]);
	return memcmp(&nid[0], &h[0], 4) == 0;
}

node_id generate_id(address const& ip)
{
	return generate_id_impl(ip, rand());
}

} }  // namespace libtorrent::dht

<commit_msg>fix build error<commit_after>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include <algorithm>
#include <ctime>

#include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/broadcast_socket.hpp" // for is_local et.al
#include "libtorrent/socket_io.hpp" // for hash_address

namespace libtorrent { namespace dht
{

// returns the distance between the two nodes
// using the kademlia XOR-metric
node_id distance(node_id const& n1, node_id const& n2)
{
	node_id ret;
	node_id::iterator k = ret.begin();
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, end(n1.end()); i != end; ++i, ++j, ++k)
	{
		*k = *i ^ *j;
	}
	return ret;
}

// returns true if: distance(n1, ref) < distance(n2, ref)
bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref)
{
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, k = ref.begin(), end(n1.end()); i != end; ++i, ++j, ++k)
	{
		boost::uint8_t lhs = (*i ^ *k);
		boost::uint8_t rhs = (*j ^ *k);
		if (lhs < rhs) return true;
		if (lhs > rhs) return false;
	}
	return false;
}

// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
// useful for finding out which bucket a node belongs to
int distance_exp(node_id const& n1, node_id const& n2)
{
	int byte = node_id::size - 1;
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, end(n1.end()); i != end; ++i, ++j, --byte)
	{
		TORRENT_ASSERT(byte >= 0);
		boost::uint8_t t = *i ^ *j;
		if (t == 0) continue;
		// we have found the first non-zero byte
		// return the bit-number of the first bit
		// that differs
		int bit = byte * 8;
		for (int b = 7; b >= 0; --b)
			if (t >= (1 << b)) return bit + b;
		return bit;
	}

	return 0;
}

struct static_ { static_() { std::srand((unsigned int)std::time(0)); } } static__;

node_id generate_id_impl(address const& ip, boost::uint32_t r)
{
	boost::uint32_t seed = r & 0x7;
	boost::uint32_t modulus = 0x100;

	boost::uint8_t* p = 0;
	int num_octets = 0;
	int mod_shift = 0;

	address_v4::bytes_type b4;
#if TORRENT_USE_IPV6
	address_v6::bytes_type b6;
	if (ip.is_v6())
	{
		b6 = ip.to_v6().to_bytes();
		p = &b6[0];
		num_octets = 8;
		mod_shift = 3;
	}
	else
#endif
	{
		b4 = ip.to_v4().to_bytes();
		p = &b4[0];
		num_octets = 4;
		mod_shift = 6;
	}

	while (num_octets)
	{
		seed *= p[num_octets];
		seed &= (modulus-1);
		modulus <<= mod_shift;
		--num_octets;
	}

	seed = htonl(seed);

	node_id id = hasher((const char*)&seed, sizeof(seed)).final();

	for (int i = 4; i < 19; ++i) id[i] = rand();

	id[19] = r;

	return id;
}

node_id generate_random_id()
{
	char random[20];
	for (int i = 0; i < 20; ++i) random[i] = rand();
	return hasher(random, 20).final();
}

// verifies whether a node-id matches the IP it's used from
// returns true if the node-id is OK coming from this source
// and false otherwise.
bool verify_id(node_id const& nid, address const& source_ip)
{
	// no need to verify local IPs, they would be incorrect anyway
	if (is_local(source_ip)) return true;

	node_id h = generate_id_impl(source_ip, nid[19]);
	return memcmp(&nid[0], &h[0], 4) == 0;
}

node_id generate_id(address const& ip)
{
	return generate_id_impl(ip, rand());
}

} }  // namespace libtorrent::dht

<|endoftext|>


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

#ifndef _SVTOOLS_FSTATHELPER_HXX
#define _SVTOOLS_FSTATHELPER_HXX

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif

class UniString;
class Date;
class Time;

namespace FStatHelper {

/** Return the modified time and date stamp for this URL.

    @param URL  the asking URL

    @param pDate if unequal 0, the function set the date stamp

    @param pTime if unequal 0, the function set the time stamp

    @return     it was be able to get the date/time stamp
*/
sal_Bool GetModifiedDateTimeOfFile( const UniString& rURL,
                                    Date* pDate, Time* pTime );

/** Return if under the URL a document exist. This is only a wrapper for the
    UCB.IsContent.
*/
sal_Bool IsDocument( const UniString& rURL );

};

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

#ifndef _SVTOOLS_FSTATHELPER_HXX
#define _SVTOOLS_FSTATHELPER_HXX

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif

class UniString;
class Date;
class Time;

namespace FStatHelper {

/** Return the modified time and date stamp for this URL.

    @param URL  the asking URL

    @param pDate if unequal 0, the function set the date stamp

    @param pTime if unequal 0, the function set the time stamp

    @return     it was be able to get the date/time stamp
*/
sal_Bool GetModifiedDateTimeOfFile( const UniString& rURL,
                                    Date* pDate, Time* pTime );

/** Return if under the URL a document exist. This is only a wrapper for the
    UCB.IsContent.
*/
sal_Bool IsDocument( const UniString& rURL );

/** Return if under the URL a folder exist. This is only a wrapper for the
    UCB.isFolder.
*/
sal_Bool IsFolder( const UniString& rURL );

};

#endif
<|endoftext|>


<commit_before>/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include "kernel/formatter.h"
#include "kernel/context.h"

namespace lean {
/**
   \brief Very basic printer for expressions.
   It is mainly used when debugging code.
*/
struct print_expr_fn {
    std::ostream & m_out;

    std::ostream & out() { return m_out; }

    bool is_atomic(expr const & a) {
        return ::lean::is_atomic(a) || is_mlocal(a);
    }

    void print_child(expr const & a, context const & c) {
        if (is_atomic(a)) {
            print(a, c);
        } else {
            out() << "("; print(a, c); out() << ")";
        }
    }

    void print_macro(expr const & a, context const & c) {
        if (macro_num_args(a) > 0) out() << "(";
        macro_def(a).display(out());
        for (unsigned i = 0; i < macro_num_args(a); i++) {
            out() << " "; print(macro_arg(a, i), c);
        }
        if (macro_num_args(a) > 0) out() << ")";
    }

    void print_sort(expr const & a) {
        if (is_zero(sort_level(a))) {
            out() << "Bool";
        } else if (is_one(sort_level(a))) {
            out() << "Type";
        } else {
            out() << "Type.{" << sort_level(a) << "}";
        }
    }

    void print_app(expr const & e, context const & c) {
        expr const & f = app_fn(e);
        if (is_app(f))
            print(f, c);
        else
            print_child(f, c);
        out() << " ";
        print_child(app_arg(e), c);
    }

    void print_arrow_body(expr const & a, context const & c) {
        if (is_atomic(a) || is_arrow(a))
            return print(a, c);
        else
            return print_child(a, c);
    }

    void print_binder(char const * bname, expr const & e, context const & c) {
        out() << bname << " " << binder_name(e) << " : ";
        print_child(binder_domain(e), c);
        out() << ", ";
        print_child(binder_body(e), extend(c, binder_name(e), binder_domain(e)));
    }

    void print_const(expr const & a) {
        list<level> const & ls = const_level_params(a);
        out() << const_name(a);
        if (!is_nil(ls)) {
            out() << ".{";
            bool first = true;
            for (auto l : ls) {
                if (first) first = false; else out() << " ";
                out() << l;
            }
            out() << "}";
        }
    }

    void print(expr const & a, context const & c) {
        switch (a.kind()) {
        case expr_kind::Meta: case expr_kind::Local:
            out() << mlocal_name(a);
            break;
        case expr_kind::Var: {
            auto e = find(c, var_idx(a));
            if (e)
                out() << e->first << "#" << var_idx(a);
            else
                out() << "#" << var_idx(a);
            break;
        }
        case expr_kind::Constant:
            print_const(a);
            break;
        case expr_kind::App:
            print_app(a, c);
            break;
        case expr_kind::Lambda:
            print_binder("fun", a, c);
            break;
        case expr_kind::Pi:
            if (!is_arrow(a)) {
                print_binder("Pi", a, c);
            } else {
                print_child(binder_domain(a), c);
                out() << " -> ";
                print_arrow_body(binder_body(a), extend(c, binder_name(a), binder_domain(a)));
            }
            break;
        case expr_kind::Let:
            out() << "let " << let_name(a);
            out() << " : ";
            print(let_type(a), c);
            out() << " := ";
            print(let_value(a), c);
            out() << " in ";
            print_child(let_body(a), extend(c, let_name(a), let_value(a)));
            break;
        case expr_kind::Sort:
            print_sort(a);
            break;
        case expr_kind::Macro:
            print_macro(a, c);
            break;
        }
    }

    print_expr_fn(std::ostream & out):m_out(out) {}

    void operator()(expr const & e, context const & c) {
        print(e, c);
    }
};

std::ostream & operator<<(std::ostream & out, expr const & e) {
    print_expr_fn pr(out);
    pr(e, context());
    return out;
}

class simple_formatter_cell : public formatter_cell {
public:
    virtual format operator()(environment const &, expr const & e, options const &) {
        std::ostringstream s; s << e; return format(s.str());
    }
};
formatter mk_simple_formatter() {
    return mk_formatter(simple_formatter_cell());
}
void print(lean::expr const & a) { std::cout << a << std::endl; }
}
<commit_msg>feat(kernel/formatter): prefix metavars with '?' and local vars with '!' in the simple formatter<commit_after>/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include "kernel/formatter.h"
#include "kernel/context.h"

namespace lean {
/**
   \brief Very basic printer for expressions.
   It is mainly used when debugging code.
*/
struct print_expr_fn {
    std::ostream & m_out;

    std::ostream & out() { return m_out; }

    bool is_atomic(expr const & a) {
        return ::lean::is_atomic(a) || is_mlocal(a);
    }

    void print_child(expr const & a, context const & c) {
        if (is_atomic(a)) {
            print(a, c);
        } else {
            out() << "("; print(a, c); out() << ")";
        }
    }

    void print_macro(expr const & a, context const & c) {
        if (macro_num_args(a) > 0) out() << "(";
        macro_def(a).display(out());
        for (unsigned i = 0; i < macro_num_args(a); i++) {
            out() << " "; print(macro_arg(a, i), c);
        }
        if (macro_num_args(a) > 0) out() << ")";
    }

    void print_sort(expr const & a) {
        if (is_zero(sort_level(a))) {
            out() << "Bool";
        } else if (is_one(sort_level(a))) {
            out() << "Type";
        } else {
            out() << "Type.{" << sort_level(a) << "}";
        }
    }

    void print_app(expr const & e, context const & c) {
        expr const & f = app_fn(e);
        if (is_app(f))
            print(f, c);
        else
            print_child(f, c);
        out() << " ";
        print_child(app_arg(e), c);
    }

    void print_arrow_body(expr const & a, context const & c) {
        if (is_atomic(a) || is_arrow(a))
            return print(a, c);
        else
            return print_child(a, c);
    }

    void print_binder(char const * bname, expr const & e, context const & c) {
        out() << bname << " " << binder_name(e) << " : ";
        print_child(binder_domain(e), c);
        out() << ", ";
        print_child(binder_body(e), extend(c, binder_name(e), binder_domain(e)));
    }

    void print_const(expr const & a) {
        list<level> const & ls = const_level_params(a);
        out() << const_name(a);
        if (!is_nil(ls)) {
            out() << ".{";
            bool first = true;
            for (auto l : ls) {
                if (first) first = false; else out() << " ";
                out() << l;
            }
            out() << "}";
        }
    }

    void print(expr const & a, context const & c) {
        switch (a.kind()) {
        case expr_kind::Meta:
            out() << "?" << mlocal_name(a);
            break;
        case expr_kind::Local:
            out() << "!" << mlocal_name(a);
            break;
        case expr_kind::Var: {
            auto e = find(c, var_idx(a));
            if (e)
                out() << e->first << "#" << var_idx(a);
            else
                out() << "#" << var_idx(a);
            break;
        }
        case expr_kind::Constant:
            print_const(a);
            break;
        case expr_kind::App:
            print_app(a, c);
            break;
        case expr_kind::Lambda:
            print_binder("fun", a, c);
            break;
        case expr_kind::Pi:
            if (!is_arrow(a)) {
                print_binder("Pi", a, c);
            } else {
                print_child(binder_domain(a), c);
                out() << " -> ";
                print_arrow_body(binder_body(a), extend(c, binder_name(a), binder_domain(a)));
            }
            break;
        case expr_kind::Let:
            out() << "let " << let_name(a);
            out() << " : ";
            print(let_type(a), c);
            out() << " := ";
            print(let_value(a), c);
            out() << " in ";
            print_child(let_body(a), extend(c, let_name(a), let_value(a)));
            break;
        case expr_kind::Sort:
            print_sort(a);
            break;
        case expr_kind::Macro:
            print_macro(a, c);
            break;
        }
    }

    print_expr_fn(std::ostream & out):m_out(out) {}

    void operator()(expr const & e, context const & c) {
        print(e, c);
    }
};

std::ostream & operator<<(std::ostream & out, expr const & e) {
    print_expr_fn pr(out);
    pr(e, context());
    return out;
}

class simple_formatter_cell : public formatter_cell {
public:
    virtual format operator()(environment const &, expr const & e, options const &) {
        std::ostringstream s; s << e; return format(s.str());
    }
};
formatter mk_simple_formatter() {
    return mk_formatter(simple_formatter_cell());
}
void print(lean::expr const & a) { std::cout << a << std::endl; }
}
<|endoftext|>


<commit_before>#ifdef VERBOSE
#include "kernel.hpp"

namespace uart {

/**
 * The base port of the first serial interface.
 */
#define BASEPORT        0x3F8

void writeByte(unsigned int port, uint8_t value) {
//    print('>');
//    print(' ');
//    printHex(basePort + port);
//    print(',');
//    printHex(value);
//    newLine();
    asm(
        "outb   %%al, %%dx" : :
        "d"(BASEPORT + port), "a"(value)
    );
}

void writeWord(unsigned int port, uint16_t value) {
//    print('>');
//    print(' ');
//    printHex(basePort + port);
//    print(',');
//    printHex(value);
//    newLine();
    asm(
        "outw   %%ax, %%dx" : :
        "d"(BASEPORT + port), "a"(value)
    );
}

uint8_t readByte(unsigned int port) {
    uint8_t result;
    asm(
        "inb    %%dx, %%al" :
        "=a"(result) :
        "d"(BASEPORT + port)
    );
    return result;
}

}

#endif
<commit_msg>Removed stale code.<commit_after>#ifdef VERBOSE
#include "kernel.hpp"

namespace uart {

/**
 * The base port of the first serial interface.
 */
#define BASEPORT        0x3F8

void writeByte(unsigned int port, uint8_t value) {
    asm(
        "outb   %%al, %%dx" : :
        "d"(BASEPORT + port), "a"(value)
    );
}

void writeWord(unsigned int port, uint16_t value) {
    asm(
        "outw   %%ax, %%dx" : :
        "d"(BASEPORT + port), "a"(value)
    );
}

uint8_t readByte(unsigned int port) {
    uint8_t result;
    asm(
        "inb    %%dx, %%al" :
        "=a"(result) :
        "d"(BASEPORT + port)
    );
    return result;
}

}

#endif
<|endoftext|>