<commit_before>/****************************************************************************
 *
 *   Copyright (C) 2015 Mark Charlebois. All rights reserved.
 *   Author: @author Mark Charlebois <charlebm#gmail.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/

/**
 * @file px4_posix_tasks.c
 * Implementation of existing task API for Linux
 */

#include <px4_log.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
#include <signal.h>
#include <fcntl.h>
#include <sched.h>
#include <unistd.h>
#include <string.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <string>

#include <px4_tasks.h>

#define MAX_CMD_LEN 100

#define PX4_MAX_TASKS 50
#define SHELL_TASK_ID (PX4_MAX_TASKS+1)

pthread_t _shell_task_id = 0;

struct task_entry
{
	pthread_t pid;
	std::string name;
	bool isused;
	task_entry() : isused(false) {}
};

static task_entry taskmap[PX4_MAX_TASKS];

typedef struct
{
	px4_main_t entry;
	int argc;
	char *argv[];
	// strings are allocated after the
} pthdata_t;

static void *entry_adapter ( void *ptr )
{
	pthdata_t *data;
	data = (pthdata_t *) ptr;

	data->entry(data->argc, data->argv);
	free(ptr);
	PX4_DEBUG("Before px4_task_exit");
	px4_task_exit(0);
	PX4_DEBUG("After px4_task_exit");

	return NULL;
}

void
px4_systemreset(bool to_bootloader)
{
	PX4_WARN("Called px4_system_reset");
	exit(0);
}

px4_task_t px4_task_spawn_cmd(const char *name, int scheduler, int priority, int stack_size, px4_main_t entry, char * const argv[])
{
	int rv;
	int argc = 0;
	int i;
	unsigned int len = 0;
	unsigned long offset;
	unsigned long structsize;
	char * p = (char *)argv;

        pthread_t task;
	pthread_attr_t attr;
	struct sched_param param;

	// Calculate argc
	while (p != (char *)0) {
		p = argv[argc];
		if (p == (char *)0)
			break;
		++argc;
		len += strlen(p)+1;
	}
        structsize = sizeof(pthdata_t)+(argc+1)*sizeof(char *);
	pthdata_t *taskdata;

	// not safe to pass stack data to the thread creation
	taskdata = (pthdata_t *)malloc(structsize+len);
	offset = ((unsigned long)taskdata)+structsize;

    	taskdata->entry = entry;
	taskdata->argc = argc;

	for (i=0; i<argc; i++) {
		printf("arg %d %s\n", i, argv[i]);
		taskdata->argv[i] = (char *)offset;
		strcpy((char *)offset, argv[i]);
		offset+=strlen(argv[i])+1;
	}
	// Must add NULL at end of argv
	taskdata->argv[argc] = (char *)0;

	rv = pthread_attr_init(&attr);
	if (rv != 0) {
		PX4_WARN("px4_task_spawn_cmd: failed to init thread attrs");
		return (rv < 0) ? rv : -rv;
	}
	rv = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
	if (rv != 0) {
		PX4_WARN("px4_task_spawn_cmd: failed to set inherit sched");
		return (rv < 0) ? rv : -rv;
	}
	rv = pthread_attr_setschedpolicy(&attr, scheduler);
	if (rv != 0) {
		PX4_WARN("px4_task_spawn_cmd: failed to set sched policy");
		return (rv < 0) ? rv : -rv;
	}

	param.sched_priority = priority;

	rv = pthread_attr_setschedparam(&attr, &param);
	if (rv != 0) {
		PX4_WARN("px4_task_spawn_cmd: failed to set sched param");
		return (rv < 0) ? rv : -rv;
	}

        rv = pthread_create (&task, &attr, &entry_adapter, (void *) taskdata);
	if (rv != 0) {

		if (rv == EPERM) {
			//printf("WARNING: NOT RUNING AS ROOT, UNABLE TO RUN REALTIME THREADS\n");
        		rv = pthread_create (&task, NULL, &entry_adapter, (void *) taskdata);
			if (rv != 0) {
				PX4_ERR("px4_task_spawn_cmd: failed to create thread %d %d\n", rv, errno);
				return (rv < 0) ? rv : -rv;
			}
		}
		else {
			return (rv < 0) ? rv : -rv;
		}
	}

	for (i=0; i<PX4_MAX_TASKS; ++i) {
		if (taskmap[i].isused == false) {
			taskmap[i].pid = task;
			taskmap[i].name = name;
			taskmap[i].isused = true;
			break;
		}
	}
	if (i>=PX4_MAX_TASKS) {
		return -ENOSPC;
	}
        return i;
}

int px4_task_delete(px4_task_t id)
{
	int rv = 0;
	pthread_t pid;
	PX4_WARN("Called px4_task_delete");

	if (id < PX4_MAX_TASKS && taskmap[id].isused)
		pid = taskmap[id].pid;
	else
		return -EINVAL;

	// If current thread then exit, otherwise cancel
        if (pthread_self() == pid) {
		taskmap[id].isused = false;
		pthread_exit(0);
	} else {
		rv = pthread_cancel(pid);
	}

	taskmap[id].isused = false;

	return rv;
}

void px4_task_exit(int ret)
{
	int i;
	pthread_t pid = pthread_self();

	// Get pthread ID from the opaque ID
	for (i=0; i<PX4_MAX_TASKS; ++i) {
		if (taskmap[i].pid == pid) {
			taskmap[i].isused = false;
			break;
		}
	}
	if (i>=PX4_MAX_TASKS)  {
		PX4_ERR("px4_task_exit: self task not found!");
	}
	else {
		PX4_DEBUG("px4_task_exit: %s", taskmap[i].name.c_str());
	}

	pthread_exit((void *)(unsigned long)ret);
}

int px4_task_kill(px4_task_t id, int sig)
{
	int rv = 0;
	pthread_t pid;
	PX4_DEBUG("Called px4_task_kill %d", sig);

	if (id < PX4_MAX_TASKS && taskmap[id].isused && taskmap[id].pid != 0)
		pid = taskmap[id].pid;
	else
		return -EINVAL;

	// If current thread then exit, otherwise cancel
	rv = pthread_kill(pid, sig);

	return rv;
}

void px4_show_tasks()
{
	int idx;
	int count = 0;

	PX4_INFO("Active Tasks:");
	for (idx=0; idx < PX4_MAX_TASKS; idx++)
	{
		if (taskmap[idx].isused) {
			PX4_INFO("   %-10s %lu", taskmap[idx].name.c_str(), taskmap[idx].pid);
			count++;
		}
	}
	if (count == 0)
		PX4_INFO("   No running tasks");

}

__BEGIN_DECLS

unsigned long px4_getpid()
{
	return (unsigned long)pthread_self();
}

const char *getprogname();
const char *getprogname()
{
        pthread_t pid = pthread_self();
	for (int i=0; i<PX4_MAX_TASKS; i++)
	{
		if (taskmap[i].isused && taskmap[i].pid == pid)
		{
			return taskmap[i].name.c_str();
		}
	}
	return "Unknown App";
}
__END_DECLS
<commit_msg>Posix tasks: Mark task creation<commit_after>/****************************************************************************
 *
 *   Copyright (C) 2015 Mark Charlebois. All rights reserved.
 *   Author: @author Mark Charlebois <charlebm#gmail.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/

/**
 * @file px4_posix_tasks.c
 * Implementation of existing task API for Linux
 */

#include <px4_log.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
#include <signal.h>
#include <fcntl.h>
#include <sched.h>
#include <unistd.h>
#include <string.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <string>

#include <px4_tasks.h>

#define MAX_CMD_LEN 100

#define PX4_MAX_TASKS 50
#define SHELL_TASK_ID (PX4_MAX_TASKS+1)

pthread_t _shell_task_id = 0;

struct task_entry
{
	pthread_t pid;
	std::string name;
	bool isused;
	task_entry() : isused(false) {}
};

static task_entry taskmap[PX4_MAX_TASKS];

typedef struct
{
	px4_main_t entry;
	int argc;
	char *argv[];
	// strings are allocated after the
} pthdata_t;

static void *entry_adapter ( void *ptr )
{
	pthdata_t *data;
	data = (pthdata_t *) ptr;

	data->entry(data->argc, data->argv);
	free(ptr);
	PX4_DEBUG("Before px4_task_exit");
	px4_task_exit(0);
	PX4_DEBUG("After px4_task_exit");

	return NULL;
}

void
px4_systemreset(bool to_bootloader)
{
	PX4_WARN("Called px4_system_reset");
	exit(0);
}

px4_task_t px4_task_spawn_cmd(const char *name, int scheduler, int priority, int stack_size, px4_main_t entry, char * const argv[])
{
	int rv;
	int argc = 0;
	int i;
	unsigned int len = 0;
	unsigned long offset;
	unsigned long structsize;
	char * p = (char *)argv;

        pthread_t task;
	pthread_attr_t attr;
	struct sched_param param;

	// Calculate argc
	while (p != (char *)0) {
		p = argv[argc];
		if (p == (char *)0)
			break;
		++argc;
		len += strlen(p)+1;
	}
        structsize = sizeof(pthdata_t)+(argc+1)*sizeof(char *);
	pthdata_t *taskdata;

	// not safe to pass stack data to the thread creation
	taskdata = (pthdata_t *)malloc(structsize+len);
	offset = ((unsigned long)taskdata)+structsize;

    	taskdata->entry = entry;
	taskdata->argc = argc;

	for (i=0; i<argc; i++) {
		printf("arg %d %s\n", i, argv[i]);
		taskdata->argv[i] = (char *)offset;
		strcpy((char *)offset, argv[i]);
		offset+=strlen(argv[i])+1;
	}
	// Must add NULL at end of argv
	taskdata->argv[argc] = (char *)0;

	PX4_WARN("starting task %s", name);

	rv = pthread_attr_init(&attr);
	if (rv != 0) {
		PX4_WARN("px4_task_spawn_cmd: failed to init thread attrs");
		return (rv < 0) ? rv : -rv;
	}
	rv = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
	if (rv != 0) {
		PX4_WARN("px4_task_spawn_cmd: failed to set inherit sched");
		return (rv < 0) ? rv : -rv;
	}
	rv = pthread_attr_setschedpolicy(&attr, scheduler);
	if (rv != 0) {
		PX4_WARN("px4_task_spawn_cmd: failed to set sched policy");
		return (rv < 0) ? rv : -rv;
	}

	param.sched_priority = priority;

	rv = pthread_attr_setschedparam(&attr, &param);
	if (rv != 0) {
		PX4_WARN("px4_task_spawn_cmd: failed to set sched param");
		return (rv < 0) ? rv : -rv;
	}

        rv = pthread_create (&task, &attr, &entry_adapter, (void *) taskdata);
	if (rv != 0) {

		if (rv == EPERM) {
			//printf("WARNING: NOT RUNING AS ROOT, UNABLE TO RUN REALTIME THREADS\n");
        		rv = pthread_create (&task, NULL, &entry_adapter, (void *) taskdata);
			if (rv != 0) {
				PX4_ERR("px4_task_spawn_cmd: failed to create thread %d %d\n", rv, errno);
				return (rv < 0) ? rv : -rv;
			}
		}
		else {
			return (rv < 0) ? rv : -rv;
		}
	}

	for (i=0; i<PX4_MAX_TASKS; ++i) {
		if (taskmap[i].isused == false) {
			taskmap[i].pid = task;
			taskmap[i].name = name;
			taskmap[i].isused = true;
			break;
		}
	}
	if (i>=PX4_MAX_TASKS) {
		return -ENOSPC;
	}
        return i;
}

int px4_task_delete(px4_task_t id)
{
	int rv = 0;
	pthread_t pid;
	PX4_WARN("Called px4_task_delete");

	if (id < PX4_MAX_TASKS && taskmap[id].isused)
		pid = taskmap[id].pid;
	else
		return -EINVAL;

	// If current thread then exit, otherwise cancel
        if (pthread_self() == pid) {
		taskmap[id].isused = false;
		pthread_exit(0);
	} else {
		rv = pthread_cancel(pid);
	}

	taskmap[id].isused = false;

	return rv;
}

void px4_task_exit(int ret)
{
	int i;
	pthread_t pid = pthread_self();

	// Get pthread ID from the opaque ID
	for (i=0; i<PX4_MAX_TASKS; ++i) {
		if (taskmap[i].pid == pid) {
			taskmap[i].isused = false;
			break;
		}
	}
	if (i>=PX4_MAX_TASKS)  {
		PX4_ERR("px4_task_exit: self task not found!");
	}
	else {
		PX4_DEBUG("px4_task_exit: %s", taskmap[i].name.c_str());
	}

	pthread_exit((void *)(unsigned long)ret);
}

int px4_task_kill(px4_task_t id, int sig)
{
	int rv = 0;
	pthread_t pid;
	PX4_DEBUG("Called px4_task_kill %d", sig);

	if (id < PX4_MAX_TASKS && taskmap[id].isused && taskmap[id].pid != 0)
		pid = taskmap[id].pid;
	else
		return -EINVAL;

	// If current thread then exit, otherwise cancel
	rv = pthread_kill(pid, sig);

	return rv;
}

void px4_show_tasks()
{
	int idx;
	int count = 0;

	PX4_INFO("Active Tasks:");
	for (idx=0; idx < PX4_MAX_TASKS; idx++)
	{
		if (taskmap[idx].isused) {
			PX4_INFO("   %-10s %lu", taskmap[idx].name.c_str(), taskmap[idx].pid);
			count++;
		}
	}
	if (count == 0)
		PX4_INFO("   No running tasks");

}

__BEGIN_DECLS

unsigned long px4_getpid()
{
	return (unsigned long)pthread_self();
}

const char *getprogname();
const char *getprogname()
{
        pthread_t pid = pthread_self();
	for (int i=0; i<PX4_MAX_TASKS; i++)
	{
		if (taskmap[i].isused && taskmap[i].pid == pid)
		{
			return taskmap[i].name.c_str();
		}
	}
	return "Unknown App";
}
__END_DECLS
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/

#include "projectwizardpage.h"
#include "ui_projectwizardpage.h"

#include <QtCore/QDebug>
#include <QtCore/QTextStream>

using namespace ProjectExplorer;
using namespace Internal;

ProjectWizardPage::ProjectWizardPage(QWidget *parent) :
    QWizardPage(parent),
    m_ui(new Ui::WizardPage)
{
    m_ui->setupUi(this);

    connect(m_ui->addToProjectCheckBox, SIGNAL(toggled(bool)),
            m_ui->projectComboBox, SLOT(setEnabled(bool)));
}

ProjectWizardPage::~ProjectWizardPage()
{
    delete m_ui;
}

void ProjectWizardPage::setProjects(const QStringList &l)
{
    m_ui->projectComboBox->clear();
    m_ui->projectComboBox->addItems(l);
}

void ProjectWizardPage::setAddToProjectEnabled(bool b)
{
    m_ui->projectLabel->setEnabled(b);
    m_ui->addToProjectLabel->setEnabled(b);
    m_ui->addToProjectCheckBox->setChecked(b);
    m_ui->addToProjectCheckBox->setEnabled(b);
    m_ui->projectComboBox->setEnabled(b);
}

int ProjectWizardPage::currentProjectIndex() const
{
    return m_ui->projectComboBox->currentIndex();
}

void ProjectWizardPage::setCurrentProjectIndex(int i)
{
    m_ui->projectComboBox->setCurrentIndex(i);
}

bool ProjectWizardPage::addToProject() const
{
    return m_ui->addToProjectCheckBox->isChecked();
}

bool ProjectWizardPage::addToVersionControl() const
{
    return m_ui->addToVersionControlCheckBox->isChecked();
}

void ProjectWizardPage::setAddToVersionControlEnabled(bool b)
{
    m_ui->addToVersionControlLabel->setEnabled(b);
    m_ui->addToVersionControlCheckBox->setChecked(b);
    m_ui->addToVersionControlCheckBox->setEnabled(b);
}

void ProjectWizardPage::changeEvent(QEvent *e)
{
    QWizardPage::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void ProjectWizardPage::setVCSDisplay(const QString &vcsName)
{
    m_ui->addToVersionControlLabel->setText(tr("Add to &VCS (%1)").arg(vcsName));
}

void ProjectWizardPage::setFilesDisplay(const QStringList &files)
{
    QString fileMessage;
    {
        QTextStream str(&fileMessage);
        str << "<qt>" << tr("Files to be added:");
        str << "
";
        const QStringList::const_iterator cend = files.constEnd();
        for (QStringList::const_iterator it = files.constBegin(); it != cend; ++it)
            str << *it << '\n';
        str << "
";
    }
    m_ui->filesLabel->setText(fileMessage);
}
<commit_msg>remove duplicate entries in File->New->Header, project combobox. also, sort that list<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/

#include "projectwizardpage.h"
#include "ui_projectwizardpage.h"

#include <QtCore/QDebug>
#include <QtCore/QTextStream>

using namespace ProjectExplorer;
using namespace Internal;

ProjectWizardPage::ProjectWizardPage(QWidget *parent) :
    QWizardPage(parent),
    m_ui(new Ui::WizardPage)
{
    m_ui->setupUi(this);

    connect(m_ui->addToProjectCheckBox, SIGNAL(toggled(bool)),
            m_ui->projectComboBox, SLOT(setEnabled(bool)));
}

ProjectWizardPage::~ProjectWizardPage()
{
    delete m_ui;
}

void ProjectWizardPage::setProjects(const QStringList &l)
{
    QStringList list = l;
    list.removeDuplicates();
    list.sort();
    m_ui->projectComboBox->clear();
    m_ui->projectComboBox->addItems(list);
}

void ProjectWizardPage::setAddToProjectEnabled(bool b)
{
    m_ui->projectLabel->setEnabled(b);
    m_ui->addToProjectLabel->setEnabled(b);
    m_ui->addToProjectCheckBox->setChecked(b);
    m_ui->addToProjectCheckBox->setEnabled(b);
    m_ui->projectComboBox->setEnabled(b);
}

int ProjectWizardPage::currentProjectIndex() const
{
    return m_ui->projectComboBox->currentIndex();
}

void ProjectWizardPage::setCurrentProjectIndex(int i)
{
    m_ui->projectComboBox->setCurrentIndex(i);
}

bool ProjectWizardPage::addToProject() const
{
    return m_ui->addToProjectCheckBox->isChecked();
}

bool ProjectWizardPage::addToVersionControl() const
{
    return m_ui->addToVersionControlCheckBox->isChecked();
}

void ProjectWizardPage::setAddToVersionControlEnabled(bool b)
{
    m_ui->addToVersionControlLabel->setEnabled(b);
    m_ui->addToVersionControlCheckBox->setChecked(b);
    m_ui->addToVersionControlCheckBox->setEnabled(b);
}

void ProjectWizardPage::changeEvent(QEvent *e)
{
    QWizardPage::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void ProjectWizardPage::setVCSDisplay(const QString &vcsName)
{
    m_ui->addToVersionControlLabel->setText(tr("Add to &VCS (%1)").arg(vcsName));
}

void ProjectWizardPage::setFilesDisplay(const QStringList &files)
{
    QString fileMessage;
    {
        QTextStream str(&fileMessage);
        str << "<qt>" << tr("Files to be added:");
        str << "
";
        const QStringList::const_iterator cend = files.constEnd();
        for (QStringList::const_iterator it = files.constBegin(); it != cend; ++it)
            str << *it << '\n';
        str << "
";
    }
    m_ui->filesLabel->setText(fileMessage);
}
<|endoftext|>


<commit_before>#include <libport/assert.hh>
#include <libport/exception.hh>
#include <libport/semaphore.hh>

namespace libport
{

# if defined WIN32 || defined LIBPORT_WIN32
  sem_t*
  sem_open (const char* name,
	    int oflag,
	    unsigned int /*mode_t*/ mode,
	    unsigned int value)
  {
    return 0; // Use sem_init instead.
  }

  int
  sem_init(sem_t* sem, int, int cnt)
  {
    *sem = CreateSemaphore(0, cnt, 100000, 0);
    if (!sem)
      errabort("CreateSemaphore");
    return sem ? 0 : -1;
  }

  int
  sem_post(sem_t* sem)
  {
    unsigned int result = ReleaseSemaphore(*sem, 1, 0);
    if (!result)
      errabort("ReleaseSemaphore");
    return result ? 0 : -1;
  }

  int
  sem_wait(sem_t* sem)
  {
    unsigned int result = WaitForSingleObject(*sem, INFINITE);
    if (result == WAIT_FAILED)
      errabort("WaitForSingleObject");
    return (result == WAIT_FAILED) ? -1 : 0;
  }

  int
  sem_destroy(sem_t* sem)
  {
    return CloseHandle(*sem) ? 0 : -1;
  }

  int
  sem_getvalue(sem_t* sem, int* v)
  {
    *v = 1; //TODO: implement
    // Maybe look at: http://www.codeguru.com/Cpp/W-P/win32/article.php/c1423
    return 0;
  }
#endif /* !WIN32 */

} // namespace libport

/* Darwin doesn't implement sem_init/sem_close (although the functions exists
 * and is defined, in fact it just returns ENOSYS). That's why need to use
 * named semaphores (with sem_open) instead.
 * See:
 * http://lists.apple.com/archives/darwin-development/2004/May/msg00077.html
 * http://www.google.com/search?as_q=sem_init&as_sitesearch=apple.com
 *
 * Semaphores created with sem_open must be closed with sem_close.
 * Semaphores created with sem_init must be closed with sem_destroy.
 */
# ifdef __APPLE__
#  include <fstream>
#  include <sstream>
# endif

# include <cerrno>

namespace libport
{

  Semaphore::Semaphore (int cnt)
  {
# ifdef __APPLE__
    static unsigned int counter = 0;
    std::stringstream s;
    s << "sema/" << getpid() << "/" << counter++;
    name_ = s.str();

    errno = 0;
    sem_ = sem_open(name_.c_str(), O_CREAT | O_EXCL, 0777, cnt);

    {
      // Save the semaphore name if we can, in order to provide the user
      // with a means to reclaim them.  Don't check for success, this is
      // best effort.
      std::ofstream o("/tmp/urbi-semaphores.log", std::ios_base::app);
      o << name_;
      if (errno)
        o << ": " << strerror(errno);
      o << std::endl;
    }

    if (sem_ == static_cast<sem_t*>(0))
      errabort("sem_open(" << name_ << ')');
# else
    sem_ = new sem_t;
    if (sem_init(sem_, 0, cnt))
    {
      destroy();
      errabort("sem_init(" << cnt << ')');
    }
# endif
  }

  Semaphore::~Semaphore ()
  {
    destroy();
  }

  void
  Semaphore::destroy()
  {
# ifdef __APPLE__
    // We *really* need to unlink the semaphores when we are done,
    // otherwise they leak, and at some point, ENOSPCE is the only
    // answer from the system.  I could not find a means to remove
    // them from the shell (ipcs shows nothing), so I had to reboot my
    // machine.
    //
    // So really, try to call the dtor in all the cases, including
    // aborts here.
    //
    // http://lists.apple.com/archives/darwin-dev/2005/Jun/msg00078.html
    int c = sem_close(sem_);
    int u = sem_unlink(name_.c_str());
    if (c)
      errabort("sem_close");
    if (u)
      errabort("sem_unlink");
# else
    if (sem_destroy(sem_))
      errabort("sem_destroy");
    delete sem_;
# endif
  }

  void
  Semaphore::operator++ ()
  {
    if (sem_post(sem_))
    {
      destroy();
      errabort("sem_post");
    }
  }

  void
  Semaphore::operator-- ()
  {
    int err;
    do
      {
	err = sem_wait(sem_);
      }
    while (err == -1 && errno == EINTR);
    if (err)
    {
      destroy();
      errabort("sem_wait");
    }
  }

  Semaphore::operator int ()
  {
    int res;
    if (sem_getvalue(sem_, &res))
    {
      destroy();
      errabort("sem_getvalue");
    }
    return res;
  }

} // namespace libport
<commit_msg>Use the right errno.<commit_after>#include <libport/assert.hh>
#include <libport/exception.hh>
#include <libport/semaphore.hh>

namespace libport
{

# if defined WIN32 || defined LIBPORT_WIN32
  sem_t*
  sem_open (const char* name,
	    int oflag,
	    unsigned int /*mode_t*/ mode,
	    unsigned int value)
  {
    return 0; // Use sem_init instead.
  }

  int
  sem_init(sem_t* sem, int, int cnt)
  {
    *sem = CreateSemaphore(0, cnt, 100000, 0);
    if (!sem)
      errabort("CreateSemaphore");
    return sem ? 0 : -1;
  }

  int
  sem_post(sem_t* sem)
  {
    unsigned int result = ReleaseSemaphore(*sem, 1, 0);
    if (!result)
      errabort("ReleaseSemaphore");
    return result ? 0 : -1;
  }

  int
  sem_wait(sem_t* sem)
  {
    unsigned int result = WaitForSingleObject(*sem, INFINITE);
    if (result == WAIT_FAILED)
      errabort("WaitForSingleObject");
    return (result == WAIT_FAILED) ? -1 : 0;
  }

  int
  sem_destroy(sem_t* sem)
  {
    return CloseHandle(*sem) ? 0 : -1;
  }

  int
  sem_getvalue(sem_t* sem, int* v)
  {
    *v = 1; //TODO: implement
    // Maybe look at: http://www.codeguru.com/Cpp/W-P/win32/article.php/c1423
    return 0;
  }
#endif /* !WIN32 */

} // namespace libport

/* Darwin doesn't implement sem_init/sem_close (although the functions exists
 * and is defined, in fact it just returns ENOSYS). That's why need to use
 * named semaphores (with sem_open) instead.
 * See:
 * http://lists.apple.com/archives/darwin-development/2004/May/msg00077.html
 * http://www.google.com/search?as_q=sem_init&as_sitesearch=apple.com
 *
 * Semaphores created with sem_open must be closed with sem_close.
 * Semaphores created with sem_init must be closed with sem_destroy.
 */
# ifdef __APPLE__
#  include <fstream>
#  include <sstream>
# endif

# include <cerrno>

namespace libport
{

  Semaphore::Semaphore (int cnt)
  {
# ifdef __APPLE__
    static unsigned int counter = 0;
    std::stringstream s;
    s << "sema/" << getpid() << "/" << counter++;
    name_ = s.str();

    errno = 0;
    sem_ = sem_open(name_.c_str(), O_CREAT | O_EXCL, 0777, cnt);

    {
      // Save the semaphore name if we can, in order to provide the user
      // with a means to reclaim them.  Don't check for success, this is
      // best effort.
      std::ofstream o("/tmp/urbi-semaphores.log", std::ios_base::app);
      o << name_;
      if (errno)
        o << ": " << strerror(errno);
      o << std::endl;
    }

    if (sem_ == static_cast<sem_t*>(0))
      errabort("sem_open(" << name_ << ')');
# else
    sem_ = new sem_t;
    if (sem_init(sem_, 0, cnt))
    {
      destroy();
      errabort("sem_init(" << cnt << ')');
    }
# endif
  }

  Semaphore::~Semaphore ()
  {
    destroy();
  }

  void
  Semaphore::destroy()
  {
# ifdef __APPLE__
    // We *really* need to unlink the semaphores when we are done,
    // otherwise they leak, and at some point, ENOSPCE is the only
    // answer from the system.  I could not find a means to remove
    // them from the shell (ipcs shows nothing), so I had to reboot my
    // machine.
    //
    // So really, try to call sem)unlink in all the cases, including
    // aborts here.
    //
    // http://lists.apple.com/archives/darwin-dev/2005/Jun/msg00078.html
    int c = sem_close(sem_);
    int close_errno = errno;
    int u = sem_unlink(name_.c_str());
    int unlink_errno = errno;
    if (c)
      {
	errno = close_errno;
	errabort("sem_close");
      }
    if (u)
      {
	errno = unlink_errno;
	errabort("sem_unlink");
      }
# else
    if (sem_destroy(sem_))
      errabort("sem_destroy");
    delete sem_;
# endif
  }

  void
  Semaphore::operator++ ()
  {
    if (sem_post(sem_))
    {
      destroy();
      errabort("sem_post");
    }
  }

  void
  Semaphore::operator-- ()
  {
    int err;
    do
      {
	err = sem_wait(sem_);
      }
    while (err == -1 && errno == EINTR);
    if (err)
    {
      destroy();
      errabort("sem_wait");
    }
  }

  Semaphore::operator int ()
  {
    int res;
    if (sem_getvalue(sem_, &res))
    {
      destroy();
      errabort("sem_getvalue");
    }
    return res;
  }

} // namespace libport
<|endoftext|>


<commit_before>/*
 * libjingle
 * Copyright 2014 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. 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.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

#if defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH)

#include "talk/session/media/externalhmac.h"

#include <stdlib.h>  // For malloc/free.

#ifdef SRTP_RELATIVE_PATH
#include "srtp.h"  // NOLINT
#else
#include "third_party/libsrtp/include/srtp.h"
#endif  // SRTP_RELATIVE_PATH

#include "talk/base/logging.h"

// The debug module for authentiation
debug_module_t mod_external_hmac = {
  0,                            // Debugging is off by default
  (char*)"external-hmac-sha-1"  // Printable name for module
};

extern auth_type_t external_hmac;

// Begin test case 0 */
uint8_t
external_hmac_test_case_0_key[20] = {
  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
  0x0b, 0x0b, 0x0b, 0x0b
};

uint8_t
external_hmac_test_case_0_data[8] = {
  0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65   // "Hi There"
};

uint8_t
external_hmac_fake_tag[10] = {
  0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd
};

auth_test_case_t
external_hmac_test_case_0 = {
  20,                                // Octets in key
  external_hmac_test_case_0_key,     // Key
  8,                                 // Octets in data
  external_hmac_test_case_0_data,    // Data
  10,                                // Octets in tag
  external_hmac_fake_tag,            // Tag
  NULL                               // Pointer to next testcase
};

err_status_t
external_hmac_alloc(auth_t** a, int key_len, int out_len) {
  uint8_t* pointer;

  // Check key length - note that we don't support keys larger
  // than 20 bytes yet
  if (key_len > 20)
    return err_status_bad_param;

  // Check output length - should be less than 20 bytes/
  if (out_len > 20)
    return err_status_bad_param;

  // Allocate memory for auth and hmac_ctx_t structures.
  pointer = reinterpret_cast<uint8_t*>(
      malloc(sizeof(external_hmac_ctx_t) + sizeof(auth_t)));
  if (pointer == NULL)
    return err_status_alloc_fail;

  // Set pointers
  *a = (auth_t *)pointer;
  (*a)->type = &external_hmac;
  (*a)->state = pointer + sizeof(auth_t);
  (*a)->out_len = out_len;
  (*a)->key_len = key_len;
  (*a)->prefix_len = 0;

  // Increment global count of all hmac uses.
  external_hmac.ref_count++;

  return err_status_ok;
}

err_status_t
external_hmac_dealloc(auth_t* a) {
  // Zeroize entire state
  memset((uint8_t *)a, sizeof(external_hmac_ctx_t) + sizeof(auth_t));

  // Free memory
  free(a);

  // Decrement global count of all hmac uses.
  external_hmac.ref_count--;

  return err_status_ok;
}

err_status_t
external_hmac_init(external_hmac_ctx_t* state,
                   const uint8_t* key, int key_len) {
  if (key_len > HMAC_KEY_LENGTH)
    return err_status_bad_param;

  memset(state->key, 0, key_len);
  memcpy(state->key, key, key_len);
  state->key_length = key_len;
  return err_status_ok;
}

err_status_t
external_hmac_start(external_hmac_ctx_t* state) {
  return err_status_ok;
}

err_status_t
external_hmac_update(external_hmac_ctx_t* state, const uint8_t* message,
                     int msg_octets) {
  return err_status_ok;
}

err_status_t
external_hmac_compute(external_hmac_ctx_t* state, const void* message,
                      int msg_octets, int tag_len, uint8_t* result) {
  memcpy(result, external_hmac_fake_tag, tag_len);
  return err_status_ok;
}

char external_hmac_description[] = "external hmac sha-1 authentication";

 // auth_type_t external_hmac is the hmac metaobject

auth_type_t
external_hmac  = {
  (auth_alloc_func)      external_hmac_alloc,
  (auth_dealloc_func)    external_hmac_dealloc,
  (auth_init_func)       external_hmac_init,
  (auth_compute_func)    external_hmac_compute,
  (auth_update_func)     external_hmac_update,
  (auth_start_func)      external_hmac_start,
  (char *)               external_hmac_description,
  (int)                  0,  /* instance count */
  (auth_test_case_t *)   &external_hmac_test_case_0,
  (debug_module_t *)     &mod_external_hmac,
  (auth_type_id_t)       EXTERNAL_HMAC_SHA1
};

err_status_t
external_crypto_init() {
  err_status_t status = crypto_kernel_replace_auth_type(
      &external_hmac, EXTERNAL_HMAC_SHA1);
  if (status) {
    LOG(LS_ERROR) << "Error in replacing default auth module, error: "
                  << status;
    return err_status_fail;
  }
  return err_status_ok;
}

#endif  // defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH)
<commit_msg>Fixing incorrect memset.<commit_after>/*
 * libjingle
 * Copyright 2014 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. 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.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

#if defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH)

#include "talk/session/media/externalhmac.h"

#include <stdlib.h>  // For malloc/free.

#ifdef SRTP_RELATIVE_PATH
#include "srtp.h"  // NOLINT
#else
#include "third_party/libsrtp/include/srtp.h"
#endif  // SRTP_RELATIVE_PATH

#include "talk/base/logging.h"

// The debug module for authentiation
debug_module_t mod_external_hmac = {
  0,                            // Debugging is off by default
  (char*)"external-hmac-sha-1"  // Printable name for module
};

extern auth_type_t external_hmac;

// Begin test case 0 */
uint8_t
external_hmac_test_case_0_key[20] = {
  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
  0x0b, 0x0b, 0x0b, 0x0b
};

uint8_t
external_hmac_test_case_0_data[8] = {
  0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65   // "Hi There"
};

uint8_t
external_hmac_fake_tag[10] = {
  0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd
};

auth_test_case_t
external_hmac_test_case_0 = {
  20,                                // Octets in key
  external_hmac_test_case_0_key,     // Key
  8,                                 // Octets in data
  external_hmac_test_case_0_data,    // Data
  10,                                // Octets in tag
  external_hmac_fake_tag,            // Tag
  NULL                               // Pointer to next testcase
};

err_status_t
external_hmac_alloc(auth_t** a, int key_len, int out_len) {
  uint8_t* pointer;

  // Check key length - note that we don't support keys larger
  // than 20 bytes yet
  if (key_len > 20)
    return err_status_bad_param;

  // Check output length - should be less than 20 bytes/
  if (out_len > 20)
    return err_status_bad_param;

  // Allocate memory for auth and hmac_ctx_t structures.
  pointer = reinterpret_cast<uint8_t*>(
      malloc(sizeof(external_hmac_ctx_t) + sizeof(auth_t)));
  if (pointer == NULL)
    return err_status_alloc_fail;

  // Set pointers
  *a = (auth_t *)pointer;
  (*a)->type = &external_hmac;
  (*a)->state = pointer + sizeof(auth_t);
  (*a)->out_len = out_len;
  (*a)->key_len = key_len;
  (*a)->prefix_len = 0;

  // Increment global count of all hmac uses.
  external_hmac.ref_count++;

  return err_status_ok;
}

err_status_t
external_hmac_dealloc(auth_t* a) {
  // Zeroize entire state
  memset((uint8_t *)a, 0, sizeof(external_hmac_ctx_t) + sizeof(auth_t));

  // Free memory
  free(a);

  // Decrement global count of all hmac uses.
  external_hmac.ref_count--;

  return err_status_ok;
}

err_status_t
external_hmac_init(external_hmac_ctx_t* state,
                   const uint8_t* key, int key_len) {
  if (key_len > HMAC_KEY_LENGTH)
    return err_status_bad_param;

  memset(state->key, 0, key_len);
  memcpy(state->key, key, key_len);
  state->key_length = key_len;
  return err_status_ok;
}

err_status_t
external_hmac_start(external_hmac_ctx_t* state) {
  return err_status_ok;
}

err_status_t
external_hmac_update(external_hmac_ctx_t* state, const uint8_t* message,
                     int msg_octets) {
  return err_status_ok;
}

err_status_t
external_hmac_compute(external_hmac_ctx_t* state, const void* message,
                      int msg_octets, int tag_len, uint8_t* result) {
  memcpy(result, external_hmac_fake_tag, tag_len);
  return err_status_ok;
}

char external_hmac_description[] = "external hmac sha-1 authentication";

 // auth_type_t external_hmac is the hmac metaobject

auth_type_t
external_hmac  = {
  (auth_alloc_func)      external_hmac_alloc,
  (auth_dealloc_func)    external_hmac_dealloc,
  (auth_init_func)       external_hmac_init,
  (auth_compute_func)    external_hmac_compute,
  (auth_update_func)     external_hmac_update,
  (auth_start_func)      external_hmac_start,
  (char *)               external_hmac_description,
  (int)                  0,  /* instance count */
  (auth_test_case_t *)   &external_hmac_test_case_0,
  (debug_module_t *)     &mod_external_hmac,
  (auth_type_id_t)       EXTERNAL_HMAC_SHA1
};

err_status_t
external_crypto_init() {
  err_status_t status = crypto_kernel_replace_auth_type(
      &external_hmac, EXTERNAL_HMAC_SHA1);
  if (status) {
    LOG(LS_ERROR) << "Error in replacing default auth module, error: "
                  << status;
    return err_status_fail;
  }
  return err_status_ok;
}

#endif  // defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH)
<|endoftext|>


<commit_before>#include <iostream>

#include "headings.h"
#include "libaps.h"
#include "constants.h"

#include <concol.h>

using namespace std;

int get_device_id() {
  cout << "Choose device ID [0]: ";
  string input = "";
  getline(cin, input);

  if (input.length() == 0) {
    return 0;
  }
  int device_id;
  stringstream mystream(input);

  mystream >> device_id;
  // cin.clear(); cin.ignore(INT_MAX, '\n');
  return device_id;
}

uint64_t get_mac_input() {
  cout << "New MAC address [blank to skip]: ";
  string input = "";
  getline(cin, input);

  if (input.length() == 0) {
    return 0;
  }
  stringstream mystream(input);
  uint64_t mac_addr;
  mystream >> std::hex >> mac_addr;

  cout << "Received " << hexn<12> << mac_addr << endl;
  return mac_addr;
}

string get_ip_input() {
  cout << "New IP address [blank to skip]: ";
  string input = "";
  getline(cin, input);
  return input;
}

int main (int argc, char* argv[])
{

  concol::concolinit();
  cout << concol::RED << "BBN AP2 Flash Test Executable" << concol::RESET << endl;

  int dbgLevel = 8;
  if (argc >= 2) {
    dbgLevel = atoi(argv[1]);
  }

  set_logging_level(dbgLevel);

  cout << concol::RED << "Attempting to initialize libaps" << concol::RESET << endl;

  init_nolog();

  int numDevices = get_numDevices();

  cout << concol::RED << numDevices << " APS device" << (numDevices > 1 ? "s": "")  << " found" << concol::RESET << endl;

  if (numDevices < 1)
  	return 0;

  cout << concol::RED << "Attempting to get serials" << concol::RESET << endl;

  const char ** serialBuffer = new const char*[numDevices];
  get_deviceSerials(serialBuffer);

  for (int cnt=0; cnt < numDevices; cnt++) {
  	cout << concol::RED << "Device " << cnt << " serial #: " << serialBuffer[cnt] << concol::RESET << endl;
  }

  string deviceSerial;

  if (numDevices == 1) {
    deviceSerial = string(serialBuffer[0]);
  } else {
    deviceSerial = string(serialBuffer[get_device_id()]);
  }

  cout << concol::RED << "Connecting to device serial #: " << deviceSerial << concol::RESET << endl;

  connect_APS(deviceSerial.c_str());

  double uptime = get_uptime(deviceSerial.c_str());

  cout << concol::RED << "Uptime for device " << deviceSerial << " is " << uptime << " seconds" << concol::RESET << endl;

  cout << "Programmed MAC and IP address at 0x00FF0000 are " << endl;
  cout << "MAC addr: " << hexn<12> << get_mac_addr(deviceSerial.c_str()) << endl;
  cout << "IP addr: " << get_ip_addr(deviceSerial.c_str()) << endl;

  // write a new MAC address
  uint64_t mac_addr = get_mac_input();
  if (mac_addr != 0) {
    cout << concol::RED << "Writing new MAC address" << concol::RESET << endl;
    set_mac_addr(deviceSerial.c_str(), mac_addr);
  }

  // write a new IP address
  string ip_addr = get_ip_input();
  if (ip_addr != "") {
    cout << concol::RED << "Writing new IP address" << concol::RESET << endl;
    set_ip_addr(deviceSerial.c_str(), ip_addr.c_str());
  }

  // read SPI setup sequence
  uint32_t setup[32];
  read_flash(deviceSerial.c_str(), 0x0, 32, setup);
  cout << "Programmed setup SPI sequence:" << endl;
  for (size_t ct=0; ct < 32; ct++) {
    cout << hexn<8> << setup[ct] << " ";
    if (ct % 4 == 3) cout << endl;
  }

  // write new SPI setup sequence
  // write_SPI_setup(deviceSerial.c_str());
  /*
  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  uint32_t buffer[4] = {0, 0, 0, 0};
  read_flash(deviceSerial.c_str(), 0x00FA0000, 4, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " << hexn<8> << buffer[1];
  cout << " " << hexn<8> << buffer[2] << " " << hexn<8> << buffer[3] << endl;

  cout << concol::RED << "Erasing/writing flash addr 0x00FA0000 (128 words)" << concol::RESET << endl;
  vector<uint32_t> testData;
  for (size_t ct=0; ct<128; ct++){
    testData.push_back(0x00FA0000 + static_cast<uint32_t>(ct));
  }
  write_flash(deviceSerial.c_str(), 0x00FA0000, testData.data(), testData.size());

  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  read_flash(deviceSerial.c_str(), 0x00FA0000, 4, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " << hexn<8> << buffer[1];
  cout << " " << hexn<8> << buffer[2] << " " << hexn<8> << buffer[3] << endl;

  cout << concol::RED << "Erasing/writing flash addr 0x00FA0000 (2 words)" << concol::RESET << endl;
  buffer[0] = 0xBADD1234;
  buffer[1] = 0x1234F00F;
  write_flash(deviceSerial.c_str(), 0x00FA0000, buffer, 2);

  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  read_flash(deviceSerial.c_str(), 0x00FA0000, 4, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " << hexn<8> << buffer[1];
  cout << " " << hexn<8> << buffer[2] << " " << hexn<8> << buffer[3] << endl;
  */

  disconnect_APS(deviceSerial.c_str());

  delete[] serialBuffer;

  cout << concol::RED << "Finished!" << concol::RESET << endl;

  return 0;
}
<commit_msg>Prompt for SPI programming.<commit_after>#include <iostream>

#include "headings.h"
#include "libaps.h"
#include "constants.h"

#include <concol.h>

using namespace std;

int get_device_id() {
  cout << "Choose device ID [0]: ";
  string input = "";
  getline(cin, input);

  if (input.length() == 0) {
    return 0;
  }
  int device_id;
  stringstream mystream(input);

  mystream >> device_id;
  return device_id;
}

uint64_t get_mac_input() {
  cout << "New MAC address [ENTER to skip]: ";
  string input = "";
  getline(cin, input);

  if (input.length() == 0) {
    return 0;
  }
  stringstream mystream(input);
  uint64_t mac_addr;
  mystream >> std::hex >> mac_addr;

  cout << "Received " << hexn<12> << mac_addr << endl;
  return mac_addr;
}

string get_ip_input() {
  cout << "New IP address [ENTER to skip]: ";
  string input = "";
  getline(cin, input);
  return input;
}

bool spi_prompt() {
  cout << "Do you want to program the SPI startup sequence? [y/N]: ";
  string input = "";
  getline(cin, input);
  if (input.length() == 0) {
    return false;
  }
  stringstream mystream(input);
  char response;
  mystream >> response;
  switch (response) {
    case 'y':
    case 'Y':
      return true;
      break;
    case 'n':
    case 'N':
    default:
      return false;
  }
}

int main (int argc, char* argv[])
{

  concol::concolinit();
  cout << concol::RED << "BBN AP2 Flash Test Executable" << concol::RESET << endl;

  int dbgLevel = 8;
  if (argc >= 2) {
    dbgLevel = atoi(argv[1]);
  }

  set_logging_level(dbgLevel);

  cout << concol::RED << "Attempting to initialize libaps" << concol::RESET << endl;

  init_nolog();

  int numDevices = get_numDevices();

  cout << concol::RED << numDevices << " APS device" << (numDevices > 1 ? "s": "")  << " found" << concol::RESET << endl;

  if (numDevices < 1)
  	return 0;

  cout << concol::RED << "Attempting to get serials" << concol::RESET << endl;

  const char ** serialBuffer = new const char*[numDevices];
  get_deviceSerials(serialBuffer);

  for (int cnt=0; cnt < numDevices; cnt++) {
  	cout << concol::RED << "Device " << cnt << " serial #: " << serialBuffer[cnt] << concol::RESET << endl;
  }

  string deviceSerial;

  if (numDevices == 1) {
    deviceSerial = string(serialBuffer[0]);
  } else {
    deviceSerial = string(serialBuffer[get_device_id()]);
  }

  cout << concol::RED << "Connecting to device serial #: " << deviceSerial << concol::RESET << endl;

  connect_APS(deviceSerial.c_str());

  double uptime = get_uptime(deviceSerial.c_str());

  cout << concol::RED << "Uptime for device " << deviceSerial << " is " << uptime << " seconds" << concol::RESET << endl;

  cout << "Programmed MAC and IP address at 0x00FF0000 are " << endl;
  cout << "MAC addr: " << hexn<12> << get_mac_addr(deviceSerial.c_str()) << endl;
  cout << "IP addr: " << get_ip_addr(deviceSerial.c_str()) << endl;

  // write a new MAC address
  uint64_t mac_addr = get_mac_input();
  if (mac_addr != 0) {
    cout << concol::RED << "Writing new MAC address" << concol::RESET << endl;
    set_mac_addr(deviceSerial.c_str(), mac_addr);
  }

  // write a new IP address
  string ip_addr = get_ip_input();
  if (ip_addr != "") {
    cout << concol::RED << "Writing new IP address" << concol::RESET << endl;
    set_ip_addr(deviceSerial.c_str(), ip_addr.c_str());
  }

  // read SPI setup sequence
  uint32_t setup[32];
  read_flash(deviceSerial.c_str(), 0x0, 32, setup);
  cout << "Programmed setup SPI sequence:" << endl;
  for (size_t ct=0; ct < 32; ct++) {
    cout << hexn<8> << setup[ct] << " ";
    if (ct % 4 == 3) cout << endl;
  }

  // write new SPI setup sequence
  if (spi_prompt()) {
    cout << concol::RED << "Writing SPI startup sequence" << concol::RESET << endl;
    write_SPI_setup(deviceSerial.c_str());
  }
  /*
  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  uint32_t buffer[4] = {0, 0, 0, 0};
  read_flash(deviceSerial.c_str(), 0x00FA0000, 4, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " << hexn<8> << buffer[1];
  cout << " " << hexn<8> << buffer[2] << " " << hexn<8> << buffer[3] << endl;

  cout << concol::RED << "Erasing/writing flash addr 0x00FA0000 (128 words)" << concol::RESET << endl;
  vector<uint32_t> testData;
  for (size_t ct=0; ct<128; ct++){
    testData.push_back(0x00FA0000 + static_cast<uint32_t>(ct));
  }
  write_flash(deviceSerial.c_str(), 0x00FA0000, testData.data(), testData.size());

  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  read_flash(deviceSerial.c_str(), 0x00FA0000, 4, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " << hexn<8> << buffer[1];
  cout << " " << hexn<8> << buffer[2] << " " << hexn<8> << buffer[3] << endl;

  cout << concol::RED << "Erasing/writing flash addr 0x00FA0000 (2 words)" << concol::RESET << endl;
  buffer[0] = 0xBADD1234;
  buffer[1] = 0x1234F00F;
  write_flash(deviceSerial.c_str(), 0x00FA0000, buffer, 2);

  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  read_flash(deviceSerial.c_str(), 0x00FA0000, 4, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " << hexn<8> << buffer[1];
  cout << " " << hexn<8> << buffer[2] << " " << hexn<8> << buffer[3] << endl;
  */

  disconnect_APS(deviceSerial.c_str());

  delete[] serialBuffer;

  cout << concol::RED << "Finished!" << concol::RESET << endl;

  return 0;
}
<|endoftext|>


<commit_before>#include "leveldb_common.hpp"

#include <bitcoin/block.hpp>
#include <bitcoin/transaction.hpp>
#include <bitcoin/address.hpp>
#include <bitcoin/satoshi_serialize.hpp>
#include <bitcoin/utility/assert.hpp>
#include <bitcoin/utility/logger.hpp>

namespace libbitcoin {

void leveldb_databases::write(leveldb_transaction_batch& batch)
{
    leveldb::WriteOptions options;
    // Begin commiting changes to database.
    block->Write(options, &batch.block);
    block_hash->Write(options, &batch.block_hash);
    tx->Write(options, &batch.tx);
    spend->Write(options, &batch.spend);
    credit->Write(options, &batch.credit);
    debit->Write(options, &batch.debit);
}

bool mark_spent_outputs(leveldb::WriteBatch& spend_batch,
    const output_point& previous_output, const input_point& spent_inpoint);
// Both functions return false only on database failure.
// They may or may not add an entry
bool add_debit(leveldb::WriteBatch& batch, const transaction_input_type& input);
bool add_credit(leveldb::WriteBatch& batch,
    const transaction_output_type& output, const output_point& outpoint,
    uint32_t block_depth);

leveldb_common::leveldb_common(leveldb_databases db)
  : db_(db)
{
}

uint32_t leveldb_common::find_last_block_depth()
{
    leveldb_iterator it(db_.block->NewIterator(leveldb::ReadOptions()));
    it->SeekToLast();
    if (!it->Valid() || !it->status().ok())
        return std::numeric_limits<uint32_t>::max();
    BITCOIN_ASSERT(it->key().size() == 4);
    return recreate_depth(it->key());
}

bool leveldb_common::fetch_spend(const output_point& spent_output,
    input_point& input_spend)
{
    data_chunk spent_key = create_spent_key(spent_output);
    std::string raw_spend;
    leveldb::Status status = db_.spend->Get(
        leveldb::ReadOptions(), slice(spent_key), &raw_spend);
    if (status.IsNotFound())
        return false;
    else if (!status.ok())
    {
        log_fatal(LOG_BLOCKCHAIN) << "fetch_spend: " << status.ToString();
        return false;
    }
    const data_chunk raw_spend_data(raw_spend.begin(), raw_spend.end());
    auto deserial = make_deserializer(
        raw_spend_data.begin(), raw_spend_data.end());
    input_spend.hash = deserial.read_hash();
    input_spend.index = deserial.read_4_bytes();
    return true;
}

bool leveldb_common::save_block(
    uint32_t depth, const block_type& serial_block)
{
    leveldb_transaction_batch batch;
    // Write block header + tx hashes
    data_chunk raw_block_data(
        80 + 4 + serial_block.transactions.size() * hash_digest_size);
    // Downcast to base header type so serializer selects that.
    auto header_end = satoshi_save(
        serial_block.header, raw_block_data.begin());
    BITCOIN_ASSERT(std::distance(raw_block_data.begin(), header_end) == 80);
    auto serial_hashes = make_serializer(header_end);
    // Write the number of transactions...
    serial_hashes.write_4_bytes(serial_block.transactions.size());
    // ... And now the tx themselves.
    for (uint32_t tx_index = 0;
        tx_index < serial_block.transactions.size(); ++tx_index)
    {
        const transaction_type& block_tx =
            serial_block.transactions[tx_index];
        const hash_digest& tx_hash = hash_transaction(block_tx);
        if (!save_transaction(batch, depth, tx_index, tx_hash, block_tx))
        {
            log_fatal(LOG_BLOCKCHAIN) << "Could not save transaction";
            return false;
        }
        serial_hashes.write_hash(tx_hash);
    }
    BITCOIN_ASSERT(
        std::distance(raw_block_data.begin(), serial_hashes.iterator()) ==
        80 + 4 + serial_block.transactions.size() * hash_digest_size);
    data_chunk raw_depth = uncast_type(depth);
    hash_digest block_hash = hash_block_header(serial_block.header);
    // Write block header
    batch.block.Put(slice(raw_depth), slice(raw_block_data));
    batch.block_hash.Put(slice_block_hash(block_hash), slice(raw_depth));
    // Execute batches.
    db_.write(batch);
    return true;
}

bool leveldb_common::save_transaction(leveldb_transaction_batch& batch,
    uint32_t block_depth, uint32_t tx_index,
    const hash_digest& tx_hash, const transaction_type& block_tx)
{
    if (duplicate_exists(tx_hash, block_depth, tx_index))
        return true;
    data_chunk tx_data(8 + satoshi_raw_size(block_tx));
    // Serialize tx.
    auto serial = make_serializer(tx_data.begin());
    serial.write_4_bytes(block_depth);
    serial.write_4_bytes(tx_index);
    // Actual tx data.
    auto end_iter = satoshi_save(block_tx, serial.iterator());
    BITCOIN_ASSERT(
        std::distance(tx_data.begin(), end_iter) ==
        8 + satoshi_raw_size(block_tx));
    // Save tx to leveldb
    batch.tx.Put(slice(tx_hash), slice(tx_data));
    // Add inputs to spends database.
    // Coinbase inputs do not spend anything.
    if (!is_coinbase(block_tx))
        for (uint32_t input_index = 0; input_index < block_tx.inputs.size();
            ++input_index)
        {
            const transaction_input_type& input =
                block_tx.inputs[input_index];
            const input_point inpoint{tx_hash, input_index};
            if (!mark_spent_outputs(batch.spend,
                    input.previous_output, inpoint))
                return false;
            if (!add_debit(batch.debit, input))
                return false;
        }
    // Save address -> output mappings.
    for (uint32_t output_index = 0; output_index < block_tx.outputs.size();
        ++output_index)
    {
        const transaction_output_type& output =
            block_tx.outputs[output_index];
        if (!add_credit(batch.credit,
                output, {tx_hash, output_index}, block_depth))
            return false;
    }
    return true;
}

bool leveldb_common::duplicate_exists(const hash_digest& tx_hash,
    uint32_t block_depth, uint32_t tx_index)
{
    leveldb_tx_info tx;
    if (!get_transaction(tx, tx_hash, false, false))
        return false;
    BITCOIN_ASSERT(block_depth == 91842 || block_depth == 91880);
    return true;
}

bool mark_spent_outputs(leveldb::WriteBatch& spend_batch,
    const output_point& previous_output, const input_point& spent_inpoint)
{
    data_chunk spent_key = create_spent_key(previous_output),
        spend_value = create_spent_key(spent_inpoint);
    spend_batch.Put(slice(spent_key), slice(spend_value));
    return true;
}

bool input_has_pubkey(const operation_stack& ops)
{
    return ops.size() == 2 &&
        ops[0].code == opcode::special &&
        ops[1].code == opcode::special;
}
bool extract_input_address(
    payment_address& address, const script& input_script)
{
    const operation_stack& ops = input_script.operations();
    if (!input_has_pubkey(ops))
        return false;
    BITCOIN_ASSERT(ops.size() == 2);
    const data_chunk& pubkey = ops[1].data;
    if (!set_public_key(address, pubkey))
        return false;
    return true;
}

bool add_debit(leveldb::WriteBatch& batch, const transaction_input_type& input)
{
    const output_point& outpoint = input.previous_output;
    payment_address address;
    // Not a Bitcoin address so skip this output.
    if (!extract_input_address(address, input.input_script))
        return true;
    data_chunk addr_key = create_address_key(address, outpoint);
    // outpoint, value, inpoint
    data_chunk row_info(36);
    auto serial = make_serializer(row_info.begin());
    // outpoint
    serial.write_hash(outpoint.hash);
    serial.write_4_bytes(outpoint.index);
    BITCOIN_ASSERT(
        std::distance(row_info.begin(), serial.iterator()) == 36);
    batch.Put(slice(addr_key), slice(row_info));
    return true;
}

bool add_credit(leveldb::WriteBatch& batch,
    const transaction_output_type& output, const output_point& outpoint,
    uint32_t block_depth)
{
    payment_address address;
    // Not a Bitcoin address so skip this output.
    if (!extract(address, output.output_script))
        return true;
    data_chunk addr_key = create_address_key(address, outpoint);
    // outpoint, value, inpoint
    data_chunk row_info(36 + 8 + 4);
    auto serial = make_serializer(row_info.begin());
    // outpoint
    serial.write_hash(outpoint.hash);
    serial.write_4_bytes(outpoint.index);
    // value
    serial.write_8_bytes(output.value);
    // block_depth
    // We add the block depth for reordering.
    serial.write_4_bytes(block_depth);
    BITCOIN_ASSERT(
        std::distance(row_info.begin(), serial.iterator()) == 36 + 8 + 4);
    batch.Put(slice(addr_key), slice(row_info));
    return true;
}

uint32_t leveldb_common::get_block_depth(const hash_digest& block_hash)
{
    std::string value;
    leveldb::Status status = db_.block_hash->Get(
        leveldb::ReadOptions(), slice_block_hash(block_hash), &value);
    if (status.IsNotFound())
        return std::numeric_limits<uint32_t>::max();
    else if (!status.ok())
    {
        log_fatal(LOG_BLOCKCHAIN) << "fetch_block_depth("
            << block_hash << "): " << status.ToString();
        return std::numeric_limits<uint32_t>::max();
    }
    return recreate_depth(value);
}

bool leveldb_common::get_block(leveldb_block_info& blk_info,
    uint32_t depth, bool read_header, bool read_tx_hashes)
{
    // First we try to read the bytes from the database.
    data_chunk raw_depth = uncast_type(depth);
    std::string value;
    leveldb::Status status = db_.block->Get(
        leveldb::ReadOptions(), slice(raw_depth), &value);
    if (status.IsNotFound())
        return false;
    else if (!status.ok())
    {
        log_fatal(LOG_BLOCKCHAIN) << "fetch_proto_block("
            << depth << "): " << status.ToString();
        return false;
    }
    return deserialize_block(blk_info, value, read_header, read_tx_hashes);
}
bool leveldb_common::deserialize_block(leveldb_block_info& blk_info,
    const std::string& raw_data, bool read_header, bool read_tx_hashes)
{
    // Read the header (if neccessary).
    // There is always at least one tx in a block.
    BITCOIN_ASSERT(raw_data.size() >= 80 + 4 + hash_digest_size);
    BITCOIN_ASSERT((raw_data.size() - 84) % hash_digest_size == 0);
    if (read_header)
        satoshi_load(raw_data.begin(), raw_data.begin() + 80, blk_info.header);
    if (!read_tx_hashes)
        return true;
    // Read the tx hashes for this block (if neccessary).
    auto deserial = make_deserializer(raw_data.begin() + 80, raw_data.end());
    uint32_t tx_count = deserial.read_4_bytes();
    for (size_t i = 0; i < tx_count; ++i)
    {
        const hash_digest& tx_hash = deserial.read_hash();
        blk_info.tx_hashes.push_back(tx_hash);
    }
    return true;
}

bool leveldb_common::get_transaction(leveldb_tx_info& tx_info,
    const hash_digest& tx_hash, bool read_parent, bool read_tx)
{
    // First we try to read the bytes from the database.
    std::string value;
    leveldb::Status status = db_.tx->Get(
        leveldb::ReadOptions(), slice(tx_hash), &value);
    if (status.IsNotFound())
        return false;
    else if (!status.ok())
    {
        log_fatal(LOG_BLOCKCHAIN) << "get_transaction("
            << tx_hash << "): " << status.ToString();
        return false;
    }
    // Read the parent block depth and our index in that block (if neccessary).
    BITCOIN_ASSERT(value.size() > 8);
    if (read_parent)
    {
        auto deserial = make_deserializer(value.begin(), value.begin() + 8);
        tx_info.depth = deserial.read_4_bytes();
        tx_info.index = deserial.read_4_bytes();
    }
    if (!read_tx)
        return true;
    // Read the actual transaction (if neccessary).
    try
    {
        BITCOIN_ASSERT(value.size() > 8);
        satoshi_load(value.begin() + 8, value.end(), tx_info.tx);
    }
    catch (end_of_stream)
    {
        return false;
    }
    BITCOIN_ASSERT(satoshi_raw_size(tx_info.tx) + 8 == value.size());
    BITCOIN_ASSERT(hash_transaction(tx_info.tx) == tx_hash);
    return true;
}

leveldb::Slice slice_block_hash(const hash_digest& block_hash)
{
    // Cut first 16 bytes of block hash
    BITCOIN_ASSERT(block_hash.size() == 32);
    return leveldb::Slice(
        reinterpret_cast<const char*>(block_hash.data() + 16), 16);
}

uint32_t addr_key_checksum(const output_point& outpoint)
{
    data_chunk chksum_data(hash_digest_size + 4);
    auto serial = make_serializer(chksum_data.begin());
    serial.write_hash(outpoint.hash);
    serial.write_4_bytes(outpoint.index);
    BITCOIN_ASSERT(
        std::distance(chksum_data.begin(), serial.iterator()) ==
        hash_digest_size + 4);
    return generate_sha256_checksum(chksum_data);
}
data_chunk create_address_key(
    const payment_address& address, const output_point& outpoint)
{
    data_chunk result(1 + short_hash_size + 4);
    auto serial = make_serializer(result.begin());
    serial.write_byte(address.version());
    serial.write_short_hash(address.hash());
    serial.write_4_bytes(addr_key_checksum(outpoint));
    BITCOIN_ASSERT(
        std::distance(result.begin(), serial.iterator()) ==
        1 + short_hash_size + 4);
    return result;
}

} // namespace libbitcoin

<commit_msg>bugfix: actually save inpoint in debit db (not previous outpoint)<commit_after>#include "leveldb_common.hpp"

#include <bitcoin/block.hpp>
#include <bitcoin/transaction.hpp>
#include <bitcoin/address.hpp>
#include <bitcoin/satoshi_serialize.hpp>
#include <bitcoin/utility/assert.hpp>
#include <bitcoin/utility/logger.hpp>

namespace libbitcoin {

void leveldb_databases::write(leveldb_transaction_batch& batch)
{
    leveldb::WriteOptions options;
    // Begin commiting changes to database.
    block->Write(options, &batch.block);
    block_hash->Write(options, &batch.block_hash);
    tx->Write(options, &batch.tx);
    spend->Write(options, &batch.spend);
    credit->Write(options, &batch.credit);
    debit->Write(options, &batch.debit);
}

bool mark_spent_outputs(leveldb::WriteBatch& spend_batch,
    const output_point& previous_output, const input_point& spent_inpoint);
// Both functions return false only on database failure.
// They may or may not add an entry
bool add_debit(leveldb::WriteBatch& batch,
    const transaction_input_type& input, const input_point& inpoint);
bool add_credit(leveldb::WriteBatch& batch,
    const transaction_output_type& output, const output_point& outpoint,
    uint32_t block_depth);

leveldb_common::leveldb_common(leveldb_databases db)
  : db_(db)
{
}

uint32_t leveldb_common::find_last_block_depth()
{
    leveldb_iterator it(db_.block->NewIterator(leveldb::ReadOptions()));
    it->SeekToLast();
    if (!it->Valid() || !it->status().ok())
        return std::numeric_limits<uint32_t>::max();
    BITCOIN_ASSERT(it->key().size() == 4);
    return recreate_depth(it->key());
}

bool leveldb_common::fetch_spend(const output_point& spent_output,
    input_point& input_spend)
{
    data_chunk spent_key = create_spent_key(spent_output);
    std::string raw_spend;
    leveldb::Status status = db_.spend->Get(
        leveldb::ReadOptions(), slice(spent_key), &raw_spend);
    if (status.IsNotFound())
        return false;
    else if (!status.ok())
    {
        log_fatal(LOG_BLOCKCHAIN) << "fetch_spend: " << status.ToString();
        return false;
    }
    const data_chunk raw_spend_data(raw_spend.begin(), raw_spend.end());
    auto deserial = make_deserializer(
        raw_spend_data.begin(), raw_spend_data.end());
    input_spend.hash = deserial.read_hash();
    input_spend.index = deserial.read_4_bytes();
    return true;
}

bool leveldb_common::save_block(
    uint32_t depth, const block_type& serial_block)
{
    leveldb_transaction_batch batch;
    // Write block header + tx hashes
    data_chunk raw_block_data(
        80 + 4 + serial_block.transactions.size() * hash_digest_size);
    // Downcast to base header type so serializer selects that.
    auto header_end = satoshi_save(
        serial_block.header, raw_block_data.begin());
    BITCOIN_ASSERT(std::distance(raw_block_data.begin(), header_end) == 80);
    auto serial_hashes = make_serializer(header_end);
    // Write the number of transactions...
    serial_hashes.write_4_bytes(serial_block.transactions.size());
    // ... And now the tx themselves.
    for (uint32_t tx_index = 0;
        tx_index < serial_block.transactions.size(); ++tx_index)
    {
        const transaction_type& block_tx =
            serial_block.transactions[tx_index];
        const hash_digest& tx_hash = hash_transaction(block_tx);
        if (!save_transaction(batch, depth, tx_index, tx_hash, block_tx))
        {
            log_fatal(LOG_BLOCKCHAIN) << "Could not save transaction";
            return false;
        }
        serial_hashes.write_hash(tx_hash);
    }
    BITCOIN_ASSERT(
        std::distance(raw_block_data.begin(), serial_hashes.iterator()) ==
        80 + 4 + serial_block.transactions.size() * hash_digest_size);
    data_chunk raw_depth = uncast_type(depth);
    hash_digest block_hash = hash_block_header(serial_block.header);
    // Write block header
    batch.block.Put(slice(raw_depth), slice(raw_block_data));
    batch.block_hash.Put(slice_block_hash(block_hash), slice(raw_depth));
    // Execute batches.
    db_.write(batch);
    return true;
}

bool leveldb_common::save_transaction(leveldb_transaction_batch& batch,
    uint32_t block_depth, uint32_t tx_index,
    const hash_digest& tx_hash, const transaction_type& block_tx)
{
    if (duplicate_exists(tx_hash, block_depth, tx_index))
        return true;
    data_chunk tx_data(8 + satoshi_raw_size(block_tx));
    // Serialize tx.
    auto serial = make_serializer(tx_data.begin());
    serial.write_4_bytes(block_depth);
    serial.write_4_bytes(tx_index);
    // Actual tx data.
    auto end_iter = satoshi_save(block_tx, serial.iterator());
    BITCOIN_ASSERT(
        std::distance(tx_data.begin(), end_iter) ==
        8 + satoshi_raw_size(block_tx));
    // Save tx to leveldb
    batch.tx.Put(slice(tx_hash), slice(tx_data));
    // Add inputs to spends database.
    // Coinbase inputs do not spend anything.
    if (!is_coinbase(block_tx))
        for (uint32_t input_index = 0; input_index < block_tx.inputs.size();
            ++input_index)
        {
            const transaction_input_type& input =
                block_tx.inputs[input_index];
            const input_point inpoint{tx_hash, input_index};
            if (!mark_spent_outputs(batch.spend,
                    input.previous_output, inpoint))
                return false;
            if (!add_debit(batch.debit, input, {tx_hash, input_index}))
                return false;
        }
    // Save address -> output mappings.
    for (uint32_t output_index = 0; output_index < block_tx.outputs.size();
        ++output_index)
    {
        const transaction_output_type& output =
            block_tx.outputs[output_index];
        if (!add_credit(batch.credit,
                output, {tx_hash, output_index}, block_depth))
            return false;
    }
    return true;
}

bool leveldb_common::duplicate_exists(const hash_digest& tx_hash,
    uint32_t block_depth, uint32_t tx_index)
{
    leveldb_tx_info tx;
    if (!get_transaction(tx, tx_hash, false, false))
        return false;
    BITCOIN_ASSERT(block_depth == 91842 || block_depth == 91880);
    return true;
}

bool mark_spent_outputs(leveldb::WriteBatch& spend_batch,
    const output_point& previous_output, const input_point& spent_inpoint)
{
    data_chunk spent_key = create_spent_key(previous_output),
        spend_value = create_spent_key(spent_inpoint);
    spend_batch.Put(slice(spent_key), slice(spend_value));
    return true;
}

bool input_has_pubkey(const operation_stack& ops)
{
    return ops.size() == 2 &&
        ops[0].code == opcode::special &&
        ops[1].code == opcode::special;
}
bool extract_input_address(
    payment_address& address, const script& input_script)
{
    const operation_stack& ops = input_script.operations();
    if (!input_has_pubkey(ops))
        return false;
    BITCOIN_ASSERT(ops.size() == 2);
    const data_chunk& pubkey = ops[1].data;
    if (!set_public_key(address, pubkey))
        return false;
    return true;
}

bool add_debit(leveldb::WriteBatch& batch,
    const transaction_input_type& input, const input_point& inpoint)
{
    payment_address address;
    // Not a Bitcoin address so skip this output.
    if (!extract_input_address(address, input.input_script))
        return true;
    data_chunk addr_key = create_address_key(address, input.previous_output);
    // inpoint
    data_chunk row_info(36);
    auto serial = make_serializer(row_info.begin());
    // inpoint
    serial.write_hash(inpoint.hash);
    serial.write_4_bytes(inpoint.index);
    BITCOIN_ASSERT(
        std::distance(row_info.begin(), serial.iterator()) == 36);
    batch.Put(slice(addr_key), slice(row_info));
    return true;
}

bool add_credit(leveldb::WriteBatch& batch,
    const transaction_output_type& output, const output_point& outpoint,
    uint32_t block_depth)
{
    payment_address address;
    // Not a Bitcoin address so skip this output.
    if (!extract(address, output.output_script))
        return true;
    data_chunk addr_key = create_address_key(address, outpoint);
    // outpoint, value, block_depth
    data_chunk row_info(36 + 8 + 4);
    auto serial = make_serializer(row_info.begin());
    // outpoint
    serial.write_hash(outpoint.hash);
    serial.write_4_bytes(outpoint.index);
    // value
    serial.write_8_bytes(output.value);
    // block_depth
    // We add the block depth for reordering.
    serial.write_4_bytes(block_depth);
    BITCOIN_ASSERT(
        std::distance(row_info.begin(), serial.iterator()) == 36 + 8 + 4);
    batch.Put(slice(addr_key), slice(row_info));
    return true;
}

uint32_t leveldb_common::get_block_depth(const hash_digest& block_hash)
{
    std::string value;
    leveldb::Status status = db_.block_hash->Get(
        leveldb::ReadOptions(), slice_block_hash(block_hash), &value);
    if (status.IsNotFound())
        return std::numeric_limits<uint32_t>::max();
    else if (!status.ok())
    {
        log_fatal(LOG_BLOCKCHAIN) << "fetch_block_depth("
            << block_hash << "): " << status.ToString();
        return std::numeric_limits<uint32_t>::max();
    }
    return recreate_depth(value);
}

bool leveldb_common::get_block(leveldb_block_info& blk_info,
    uint32_t depth, bool read_header, bool read_tx_hashes)
{
    // First we try to read the bytes from the database.
    data_chunk raw_depth = uncast_type(depth);
    std::string value;
    leveldb::Status status = db_.block->Get(
        leveldb::ReadOptions(), slice(raw_depth), &value);
    if (status.IsNotFound())
        return false;
    else if (!status.ok())
    {
        log_fatal(LOG_BLOCKCHAIN) << "fetch_proto_block("
            << depth << "): " << status.ToString();
        return false;
    }
    return deserialize_block(blk_info, value, read_header, read_tx_hashes);
}
bool leveldb_common::deserialize_block(leveldb_block_info& blk_info,
    const std::string& raw_data, bool read_header, bool read_tx_hashes)
{
    // Read the header (if neccessary).
    // There is always at least one tx in a block.
    BITCOIN_ASSERT(raw_data.size() >= 80 + 4 + hash_digest_size);
    BITCOIN_ASSERT((raw_data.size() - 84) % hash_digest_size == 0);
    if (read_header)
        satoshi_load(raw_data.begin(), raw_data.begin() + 80, blk_info.header);
    if (!read_tx_hashes)
        return true;
    // Read the tx hashes for this block (if neccessary).
    auto deserial = make_deserializer(raw_data.begin() + 80, raw_data.end());
    uint32_t tx_count = deserial.read_4_bytes();
    for (size_t i = 0; i < tx_count; ++i)
    {
        const hash_digest& tx_hash = deserial.read_hash();
        blk_info.tx_hashes.push_back(tx_hash);
    }
    return true;
}

bool leveldb_common::get_transaction(leveldb_tx_info& tx_info,
    const hash_digest& tx_hash, bool read_parent, bool read_tx)
{
    // First we try to read the bytes from the database.
    std::string value;
    leveldb::Status status = db_.tx->Get(
        leveldb::ReadOptions(), slice(tx_hash), &value);
    if (status.IsNotFound())
        return false;
    else if (!status.ok())
    {
        log_fatal(LOG_BLOCKCHAIN) << "get_transaction("
            << tx_hash << "): " << status.ToString();
        return false;
    }
    // Read the parent block depth and our index in that block (if neccessary).
    BITCOIN_ASSERT(value.size() > 8);
    if (read_parent)
    {
        auto deserial = make_deserializer(value.begin(), value.begin() + 8);
        tx_info.depth = deserial.read_4_bytes();
        tx_info.index = deserial.read_4_bytes();
    }
    if (!read_tx)
        return true;
    // Read the actual transaction (if neccessary).
    try
    {
        BITCOIN_ASSERT(value.size() > 8);
        satoshi_load(value.begin() + 8, value.end(), tx_info.tx);
    }
    catch (end_of_stream)
    {
        return false;
    }
    BITCOIN_ASSERT(satoshi_raw_size(tx_info.tx) + 8 == value.size());
    BITCOIN_ASSERT(hash_transaction(tx_info.tx) == tx_hash);
    return true;
}

leveldb::Slice slice_block_hash(const hash_digest& block_hash)
{
    // Cut first 16 bytes of block hash
    BITCOIN_ASSERT(block_hash.size() == 32);
    return leveldb::Slice(
        reinterpret_cast<const char*>(block_hash.data() + 16), 16);
}

uint32_t addr_key_checksum(const output_point& outpoint)
{
    data_chunk chksum_data(hash_digest_size + 4);
    auto serial = make_serializer(chksum_data.begin());
    serial.write_hash(outpoint.hash);
    serial.write_4_bytes(outpoint.index);
    BITCOIN_ASSERT(
        std::distance(chksum_data.begin(), serial.iterator()) ==
        hash_digest_size + 4);
    return generate_sha256_checksum(chksum_data);
}
data_chunk create_address_key(
    const payment_address& address, const output_point& outpoint)
{
    data_chunk result(1 + short_hash_size + 4);
    auto serial = make_serializer(result.begin());
    serial.write_byte(address.version());
    serial.write_short_hash(address.hash());
    serial.write_4_bytes(addr_key_checksum(outpoint));
    BITCOIN_ASSERT(
        std::distance(result.begin(), serial.iterator()) ==
        1 + short_hash_size + 4);
    return result;
}

} // namespace libbitcoin

<|endoftext|>


<commit_before>#pragma once
#include <cstdint>
#include <array>
#include "vm/memory.hpp"
#include "vm/interrupts.hpp"

namespace yagbe
{

	class gpu_base
	{
	public:
		gpu_base(memory &m, interrupts &i) : _m(m), _i(i) {}
		virtual ~gpu_base(){}

		enum class mode
		{
			horizontal_blank,
			vertical_blank,
			scanline_OAM,
			scanline_VRAM,
		};

		constexpr static std::array<int,4> mode_durations() { return{ 204, 456, 80, 172 }; }

		void step(uint32_t delta)
		{
			delta /= 4; //convert to m
			if (delta > 80)
				throw std::out_of_range("delta is too large");

			auto &current_mode_duration = mode_durations()[(int)_mode];
			_clock += delta;

			if (_clock < current_mode_duration)
				return;

			_clock -= current_mode_duration;

			auto call_ptr = mode_end_functions()[(int)_mode];
			mode new_mode = (this->*call_ptr)();

			if (_mode != new_mode)
			{
				_mode = new_mode;
				on_mode_changed();
			}

		}

		void reset()
		{
			_line = 0;
			_mode = mode::horizontal_blank;
			_clock = 0;
			on_mode_changed();
		}
	protected:
		void on_mode_changed()
		{
			uint8_t mode = (uint8_t)_mode;
			_m.io_register.STAT_mode_0bit = (mode & 0b01) != 0;
			_m.io_register.STAT_mode_1bit = (mode & 0b10) != 0;

			if (_mode == gpu_base::mode::horizontal_blank && _m.io_register.STAT_interrupt_mode00)
				_i.lcd_status();
			else if (_mode == gpu_base::mode::vertical_blank && _m.io_register.STAT_interrupt_mode01)
				_i.lcd_status();
			else if (_mode == gpu_base::mode::scanline_OAM && _m.io_register.STAT_interrupt_mode10)
				_i.lcd_status();
		}

		void set_line(int l)
		{
			_line = l;
			_m.io_register.LY = l;

			_m.io_register.STAT_ly_equals_lyc = l == _m.io_register.LYC;

			if (_m.io_register.STAT_interrupt_ly_equals_lyc)
				_i.lcd_status();

		}

		virtual void push_screen()
		{
			//push buffer to a renderer
		}

		virtual void render_scanline()
		{
			//render scanline to framebuffer
		}

		auto line()
		{
			return _line;
		}

	private:
		using function_pointer = gpu_base::mode (gpu_base::*)();

		mode end_horizontal_blank()
		{
			set_line(_line+1);
			if (_line == 143)
			{
				// Enter vblank
				_i.vblank();
				push_screen();
				return mode::vertical_blank;
			}
			return mode::scanline_OAM;
		}

		mode end_vertical_blank()
		{
			// Vblank (10 lines)
			set_line(_line + 1);
			if (_line > 153)
			{
				// Restart scanning modes
				set_line(0);
				return  mode::scanline_OAM;
			}
			return mode::vertical_blank;
		}

		mode end_scanline_OAM()
		{
			return mode::scanline_VRAM;
		}

		mode end_scanline_VRAM()
		{
			render_scanline();
			return mode::horizontal_blank;
		}

		constexpr static std::array<function_pointer, 4> mode_end_functions() { return{ &gpu_base::end_horizontal_blank, &gpu_base::end_vertical_blank, &gpu_base::end_scanline_OAM, &gpu_base::end_scanline_VRAM }; }

		int _line = 0;
		mode _mode = mode::horizontal_blank;
		uint32_t _clock = 0;
	protected:
		interrupts &_i;
		memory &_m;
	};
};<commit_msg>fixed lcd_status interrupt<commit_after>#pragma once
#include <cstdint>
#include <array>
#include "vm/memory.hpp"
#include "vm/interrupts.hpp"

namespace yagbe
{

	class gpu_base
	{
	public:
		gpu_base(memory &m, interrupts &i) : _m(m), _i(i) {}
		virtual ~gpu_base(){}

		enum class mode
		{
			horizontal_blank,
			vertical_blank,
			scanline_OAM,
			scanline_VRAM,
		};

		constexpr static std::array<int,4> mode_durations() { return{ 204, 456, 80, 172 }; }

		void step(uint32_t delta)
		{
			delta /= 4; //convert to m
			if (delta > 80)
				throw std::out_of_range("delta is too large");

			auto &current_mode_duration = mode_durations()[(int)_mode];
			_clock += delta;

			if (_clock < current_mode_duration)
				return;

			_clock -= current_mode_duration;

			auto call_ptr = mode_end_functions()[(int)_mode];
			mode new_mode = (this->*call_ptr)();

			if (_mode != new_mode)
			{
				_mode = new_mode;
				on_mode_changed();
			}

		}

		void reset()
		{
			_line = 0;
			_mode = mode::horizontal_blank;
			_clock = 0;
			on_mode_changed();
		}
	protected:
		void on_mode_changed()
		{
			uint8_t mode = (uint8_t)_mode;
			_m.io_register.STAT_mode_0bit = (mode & 0b01) != 0;
			_m.io_register.STAT_mode_1bit = (mode & 0b10) != 0;

			if (_mode == gpu_base::mode::horizontal_blank && _m.io_register.STAT_interrupt_mode00)
				_i.lcd_status();
			else if (_mode == gpu_base::mode::vertical_blank && _m.io_register.STAT_interrupt_mode01)
				_i.lcd_status();
			else if (_mode == gpu_base::mode::scanline_OAM && _m.io_register.STAT_interrupt_mode10)
				_i.lcd_status();
		}

		void set_line(int l)
		{
			_line = l;
			_m.io_register.LY = l;

			_m.io_register.STAT_ly_equals_lyc = l == _m.io_register.LYC;

			if (_m.io_register.STAT_interrupt_ly_equals_lyc && _m.io_register.STAT_ly_equals_lyc)
				_i.lcd_status();

		}

		virtual void push_screen()
		{
			//push buffer to a renderer
		}

		virtual void render_scanline()
		{
			//render scanline to framebuffer
		}

		auto line()
		{
			return _line;
		}

	private:
		using function_pointer = gpu_base::mode (gpu_base::*)();

		mode end_horizontal_blank()
		{
			set_line(_line+1);
			if (_line == 143)
			{
				// Enter vblank
				_i.vblank();
				push_screen();
				return mode::vertical_blank;
			}
			return mode::scanline_OAM;
		}

		mode end_vertical_blank()
		{
			// Vblank (10 lines)
			set_line(_line + 1);
			if (_line > 153)
			{
				// Restart scanning modes
				set_line(0);
				return  mode::scanline_OAM;
			}
			return mode::vertical_blank;
		}

		mode end_scanline_OAM()
		{
			return mode::scanline_VRAM;
		}

		mode end_scanline_VRAM()
		{
			render_scanline();
			return mode::horizontal_blank;
		}

		constexpr static std::array<function_pointer, 4> mode_end_functions() { return{ &gpu_base::end_horizontal_blank, &gpu_base::end_vertical_blank, &gpu_base::end_scanline_OAM, &gpu_base::end_scanline_VRAM }; }

		int _line = 0;
		mode _mode = mode::horizontal_blank;
		uint32_t _clock = 0;
	protected:
		interrupts &_i;
		memory &_m;
	};
};<|endoftext|>