<commit_before>//! Copyright (c) 2013 ASMlover. 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 ofconditions 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 materialsprovided with the
//!    distribution.
//!
//! 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 HOLDER 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 "common.h"
#include "socket.h"
#include "conn_mgr.h"

ConnectorMgr::ConnectorMgr(void)
{
}

ConnectorMgr::~ConnectorMgr(void)
{
}

void
ConnectorMgr::Insert(int fd, int ev)
{
  Socket* s = new Socket();
  if (NULL == s) {
    LOG_ERR("new Socket error ...\n");
    return;
  }
  s->Attach(fd);

  LockerGuard<SpinLock> guard(spinlock_);
  std::map<int, std::pair<int, Socket*> >::iterator it;
  it = connectors_.find(fd);
  if (it == connectors_.end())
    connectors_[fd] = std::make_pair<int, Socket*>(ev, s);
}

void
ConnectorMgr::Remove(int fd)
{
  LockerGuard<SpinLock> guard(spinlock_);
  std::map<int, std::pair<int, Socket*> >::iterator it;
  it = connectors_.find(fd);
  if (it != connectors_.end()) {
    it->second.second->Close();
    delete it->second.second;
    connectors_.erase(it);
  }
}

void
ConnectorMgr::AddEvent(int fd, int ev)
{
  LockerGuard<SpinLock> guard(spinlock_);
  std::map<int, std::pair<int, Socket*> >::iterator it;
  it = connectors_.find(fd);
  if (it != connectors_.end())
    it->second.first |= ev;
}

void
ConnectorMgr::DelEvent(int fd, int ev)
{
  LockerGuard<SpinLock> guard(spinlock_);
  std::map<int, std::pair<int, Socket*> >::iterator it;
  it = connectors_.find(fd);
  if (it != connectors_.end())
    it->second.first &= ~ev;
}

Socket*
ConnectorMgr::GetConnector(int fd)
{
  Socket* s = NULL;

  {
    LockerGuard<SpinLock> guard(spinlock_);
    std::map<int, std::pair<int, Socket*> >::iterator it;
    it = connectors_.find(fd);
    if (it != connectors_.end())
      s = it->second.second;
  }

  return s;
}

void
ConnectorMgr::InitSelectSets(fd_set* rset, fd_set* wset)
{
  FD_ZERO(rset);
  FD_ZERO(wset);

  LockerGuard<SpinLock> guard(spinlock_);
  std::map<int, std::pair<int, Socket*> >::iterator it;
  for (it = connectors_.begin(); it != connectors_.end(); ++it) {
    FD_SET(it->first, rset);
    FD_SET(it->first, wset);
  }
}
<commit_msg>fixed bug of Connector Manager module<commit_after>//! Copyright (c) 2013 ASMlover. 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 ofconditions 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 materialsprovided with the
//!    distribution.
//!
//! 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 HOLDER 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 "common.h"
#include "socket.h"
#include "conn_mgr.h"
#include "event_handler.h"

ConnectorMgr::ConnectorMgr(void)
{
}

ConnectorMgr::~ConnectorMgr(void)
{
}

void
ConnectorMgr::Insert(int fd, int ev)
{
  Socket* s = new Socket();
  if (NULL == s) {
    LOG_ERR("new Socket error ...\n");
    return;
  }
  s->Attach(fd);

  LockerGuard<SpinLock> guard(spinlock_);
  std::map<int, std::pair<int, Socket*> >::iterator it;
  it = connectors_.find(fd);
  if (it == connectors_.end())
    connectors_[fd] = std::make_pair<int, Socket*>(ev, s);
}

void
ConnectorMgr::Remove(int fd)
{
  LockerGuard<SpinLock> guard(spinlock_);
  std::map<int, std::pair<int, Socket*> >::iterator it;
  it = connectors_.find(fd);
  if (it != connectors_.end()) {
    it->second.second->Close();
    delete it->second.second;
    connectors_.erase(it);
  }
}

void
ConnectorMgr::AddEvent(int fd, int ev)
{
  LockerGuard<SpinLock> guard(spinlock_);
  std::map<int, std::pair<int, Socket*> >::iterator it;
  it = connectors_.find(fd);
  if (it != connectors_.end())
    it->second.first |= ev;
}

void
ConnectorMgr::DelEvent(int fd, int ev)
{
  LockerGuard<SpinLock> guard(spinlock_);
  std::map<int, std::pair<int, Socket*> >::iterator it;
  it = connectors_.find(fd);
  if (it != connectors_.end())
    it->second.first &= ~ev;
}

Socket*
ConnectorMgr::GetConnector(int fd)
{
  Socket* s = NULL;

  {
    LockerGuard<SpinLock> guard(spinlock_);
    std::map<int, std::pair<int, Socket*> >::iterator it;
    it = connectors_.find(fd);
    if (it != connectors_.end())
      s = it->second.second;
  }

  return s;
}

void
ConnectorMgr::InitSelectSets(fd_set* rset, fd_set* wset)
{
  FD_ZERO(rset);
  FD_ZERO(wset);

  LockerGuard<SpinLock> guard(spinlock_);
  std::map<int, std::pair<int, Socket*> >::iterator it;
  for (it = connectors_.begin(); it != connectors_.end();) {
    if (INVALID_SOCKET == it->second.second->fd()) {
      it = connectors_.erase(it);
    }
    else {
      if (it->second.first & EventHandler::kEventTypeRead)
        FD_SET(it->first, rset);

      if (it->second.first & EventHandler::kEventTypeWrite)
        FD_SET(it->first, wset);
    }
  }
}
<|endoftext|>


<commit_before>// *****************************************************************************************************************************
// array_list.hpp
// Array List Template Class
// Self-resizing dynamic array
// Author(s): Cory Douthat
// Copyright (c) 2020 Cory Douthat, All Rights Reserved.
// *****************************************************************************************************************************

#ifndef ARRAY_LIST_HPP_
#define ARRAY_LIST_HPP_

#include <cstdlib>

template <typename T>
class ArrayList
{
private:
	T* data;
	unsigned int count;
	unsigned int size;
public:
	// CONSTRUCTORS AND DESTRUCTOR
	ArrayList() : data(nullptr), count(0), size(0) {}			// Constructor: default
	ArrayList(unsigned int c) : ArrayList() { allocate(c); }	// Constructor: w/ allocation
	ArrayList(const ArrayList<T>& copy) : ArrayList() { *this = copy; }	// Constructor: copy
	~ArrayList() { free(); }									// Destructor

	// OPERATORS
	const ArrayList<T>& operator =(const ArrayList<T> &b);	// Operator =
	T& operator [](unsigned int i) { return data[i]; }			// Operator []
	const T& operator [](unsigned int i)const { return data[i]; }	// Operator [] (const)

	// CHECK FUNCTIONS
	bool isEmpty()const { return count == 0; }					// Empty check
	unsigned int getCount()const { return count; }				// Count
	unsigned int getSize()const { return size; }				// Size

	// DATA CONTROL FUNCTIONS
	bool updateCount(unsigned int new_count);					// Update list count
	bool addOneCount() { return updateCount(count + 1); }		// Add one to count (and re-allocate if necessary)
	bool allocate(unsigned int new_size);						// Re-allocate to new size

	bool set(unsigned int index, const T& item);				// Set value at index
	bool setAll(const T& item);									// Set value of all

	bool insert(unsigned int index, const T& item);				// Insert item at index
	unsigned int insertSorted(const T& item, bool order, bool dup);	// Insert item into sorted list

	void copyData(const ArrayList<T>& b);						// Copy data, only allocate if needed

	unsigned int push(const T& item) { return insert(count, item); }	// Push item on end
	bool pop() { return remove(count - 1); }					// Pop/remove end item

	bool remove(unsigned int index);							// Remove item at index

	void clear() { count = 0; }									// Clear list
	void free();												// Clear and de-allocate memory

	// READ FUNCTIONS
	T& get(unsigned int index) { return (*this)[index]; }		// Get reference to item at index
	T& getLast() { return (*this)[count - 1]; }					// Get reference to end item
};

// Operator =
template <typename T>
const ArrayList<T>& ArrayList<T>::operator =(const ArrayList<T>& b)
{
	clear();

	allocate(b.size());

	if (!(b.isEmpty()))
	{
		count = b.count;
		memcpy(data, b.data, count * sizeof(T));
	}

	return *this;
}

// Update list count
template <typename T>
bool ArrayList<T>::updateCount(unsigned int new_count)
{
	if (new_count > count)
	{
		allocate(new_count);	// Allocate more memory if needed
		count = new_count;
		return true;
	}
	else
		return false;
}

// Re-allocate to new size
template <typename T>
bool ArrayList<T>::allocate(unsigned int new_size)
{
	if (new_size <= size)
		return false;
	else
	{
		T* temp;
		unsigned int remainder;

		// Re-size
		if (new_size <= 100)
			new_size = 100;
		else if (new_size <= 200)
			new_size = 200;
		else if (new_size <= 500)
			new_size = 500;
		else if (new_size <= 1000)
			new_size = 1000;
		else
		{
			remainder = new_size % 1000;

			if (remainder > 0)
				new_size += 1000 - remainder;
		}

		// Copy data to new memory location
		if (count > 0)
		{
			temp = data;
			data = new T[new_size];
			memcpy(data, temp, count * sizeof(T));
			if (std::is_class<T>::value)	// Is T a class?
				memset(temp, 0, count * sizeof(T));	// Prevent delete from calling class destructors
			delete[] temp;
		}
		else
			data = new T[new_size];

		size = new_size;

		return true;
	}
}

// Set value at index
template <typename T>
bool ArrayList<T>::set(unsigned int index, const T& item)
{
	if (index >= count)
		return false;
	else
	{
		data[index] = item;
		return true;
	}
}

// Set value of all
template <typename T>
bool ArrayList<T>::setAll(const T& item)
{
	if (count == 0)
		return false;
	else
	{
		memset(data, item, count * sizeof(T));
		return true;
	}
}

// Insert item at index
// Push other items up the list
template <typename T>
bool ArrayList<T>::insert(unsigned int index, const T& item)
{
	// Highest insert allowed is right after last item
	if (index > count)
		return false;

	if (count == 0)
	{
		// Empty
		addOneCount();

		data[0] = item;

		return true;
	}
	else
	{
		addOneCount();

		// Move items up
		for (unsigned int i = count - 2; i >= index; i--)
		{
			data[i] = data[i - 1];
		}

		data[index] = item;

		return true;
	}
}

// Insert item into sorted list
// List must be pre-sorted (TODO: add bool sorted variable)
template <typename T>
unsigned int ArrayList<T>::insertSorted(const T& item, bool order, bool dup)
{
	if (isEmpty())
		insert(0, item);
	else
	{
		// Check if should be inserted at beginning
		if ((dup && data[0] == item) || (!order && data[0] > item) || (order && data[0] < item))
		{
			insert(0, item);
			return 0;
		}

		for (unsigned int i = 0; i < count - 1; i++)
		{
			// Ascending
			if (!order)
			{
				if (data[i + 1] > item && (data[i] < item || dup))
				{
					// Insert between i and i+1
					insert(i + 1, item);
					return i + 1;
				}
			}
			// Descending
			else
			{
				if (data[i + 1] < item && (data[i] > item || dup))
				{
					// Insert between i and i+1
					insert(i + 1, item);
					return i + 1;
				}
			}
		}

		// End of list
		i = count - 1;
		if (dup || data[i] != item)
		{
			insert(count, item);
			return count;
		}
	}
}

// Copy data, only allocate if needed
template <typename T>
void ArrayList<T>::copyData(const ArrayList<T>& b)
{
	clear();

	if (b.count > size)
		allocate(b.getSize());

	if (!(b.isEmpty()))
	{
		count = b.count;
		memcpy(data, b.data, count * sizeof(T));
	}
}

// Remove item at index
template <typename T>
bool ArrayList<T>::remove(unsigned int index)
{
	if (index => count)
		return false;	// Invalid index
	else
	{
		for (unsigned int i = index; i < count - 1; i++)
		{
			data[i] = data[i + 1];
		}

		count--;
	}
}

// Clear and de-allocate memory
template <typename T>
void ArrayList<T>::free()
{
	clear();

	delete[] data;
}

#endif
<commit_msg>Fix compile issue with previously unused ArrayList::remove() function<commit_after>// *****************************************************************************************************************************
// array_list.hpp
// Array List Template Class
// Self-resizing dynamic array
// Author(s): Cory Douthat
// Copyright (c) 2020 Cory Douthat, All Rights Reserved.
// *****************************************************************************************************************************

#ifndef ARRAY_LIST_HPP_
#define ARRAY_LIST_HPP_

#include <cstdlib>

template <typename T>
class ArrayList
{
private:
	T* data;
	unsigned int count;
	unsigned int size;
public:
	// CONSTRUCTORS AND DESTRUCTOR
	ArrayList() : data(nullptr), count(0), size(0) {}			// Constructor: default
	ArrayList(unsigned int c) : ArrayList() { allocate(c); }	// Constructor: w/ allocation
	ArrayList(const ArrayList<T>& copy) : ArrayList() { *this = copy; }	// Constructor: copy
	~ArrayList() { free(); }									// Destructor

	// OPERATORS
	const ArrayList<T>& operator =(const ArrayList<T> &b);	// Operator =
	T& operator [](unsigned int i) { return data[i]; }			// Operator []
	const T& operator [](unsigned int i)const { return data[i]; }	// Operator [] (const)

	// CHECK FUNCTIONS
	bool isEmpty()const { return count == 0; }					// Empty check
	unsigned int getCount()const { return count; }				// Count
	unsigned int getSize()const { return size; }				// Size

	// DATA CONTROL FUNCTIONS
	bool updateCount(unsigned int new_count);					// Update list count
	bool addOneCount() { return updateCount(count + 1); }		// Add one to count (and re-allocate if necessary)
	bool allocate(unsigned int new_size);						// Re-allocate to new size

	bool set(unsigned int index, const T& item);				// Set value at index
	bool setAll(const T& item);									// Set value of all

	bool insert(unsigned int index, const T& item);				// Insert item at index
	unsigned int insertSorted(const T& item, bool order, bool dup);	// Insert item into sorted list

	void copyData(const ArrayList<T>& b);						// Copy data, only allocate if needed

	unsigned int push(const T& item) { return insert(count, item); }	// Push item on end
	bool pop() { return remove(count - 1); }					// Pop/remove end item

	bool remove(unsigned int index);							// Remove item at index

	void clear() { count = 0; }									// Clear list
	void free();												// Clear and de-allocate memory

	// READ FUNCTIONS
	T& get(unsigned int index) { return (*this)[index]; }		// Get reference to item at index
	T& getLast() { return (*this)[count - 1]; }					// Get reference to end item
};

// Operator =
template <typename T>
const ArrayList<T>& ArrayList<T>::operator =(const ArrayList<T>& b)
{
	clear();

	allocate(b.size());

	if (!(b.isEmpty()))
	{
		count = b.count;
		memcpy(data, b.data, count * sizeof(T));
	}

	return *this;
}

// Update list count
template <typename T>
bool ArrayList<T>::updateCount(unsigned int new_count)
{
	if (new_count > count)
	{
		allocate(new_count);	// Allocate more memory if needed
		count = new_count;
		return true;
	}
	else
		return false;
}

// Re-allocate to new size
template <typename T>
bool ArrayList<T>::allocate(unsigned int new_size)
{
	if (new_size <= size)
		return false;
	else
	{
		T* temp;
		unsigned int remainder;

		// Re-size
		if (new_size <= 100)
			new_size = 100;
		else if (new_size <= 200)
			new_size = 200;
		else if (new_size <= 500)
			new_size = 500;
		else if (new_size <= 1000)
			new_size = 1000;
		else
		{
			remainder = new_size % 1000;

			if (remainder > 0)
				new_size += 1000 - remainder;
		}

		// Copy data to new memory location
		if (count > 0)
		{
			temp = data;
			data = new T[new_size];
			memcpy(data, temp, count * sizeof(T));
			if (std::is_class<T>::value)	// Is T a class?
				memset(temp, 0, count * sizeof(T));	// Prevent delete from calling class destructors
			delete[] temp;
		}
		else
			data = new T[new_size];

		size = new_size;

		return true;
	}
}

// Set value at index
template <typename T>
bool ArrayList<T>::set(unsigned int index, const T& item)
{
	if (index >= count)
		return false;
	else
	{
		data[index] = item;
		return true;
	}
}

// Set value of all
template <typename T>
bool ArrayList<T>::setAll(const T& item)
{
	if (count == 0)
		return false;
	else
	{
		memset(data, item, count * sizeof(T));
		return true;
	}
}

// Insert item at index
// Push other items up the list
template <typename T>
bool ArrayList<T>::insert(unsigned int index, const T& item)
{
	// Highest insert allowed is right after last item
	if (index > count)
		return false;

	if (count == 0)
	{
		// Empty
		addOneCount();

		data[0] = item;

		return true;
	}
	else
	{
		addOneCount();

		// Move items up
		for (unsigned int i = count - 2; i >= index; i--)
		{
			data[i] = data[i - 1];
		}

		data[index] = item;

		return true;
	}
}

// Insert item into sorted list
// List must be pre-sorted (TODO: add bool sorted variable)
template <typename T>
unsigned int ArrayList<T>::insertSorted(const T& item, bool order, bool dup)
{
	if (isEmpty())
		insert(0, item);
	else
	{
		// Check if should be inserted at beginning
		if ((dup && data[0] == item) || (!order && data[0] > item) || (order && data[0] < item))
		{
			insert(0, item);
			return 0;
		}

		for (unsigned int i = 0; i < count - 1; i++)
		{
			// Ascending
			if (!order)
			{
				if (data[i + 1] > item && (data[i] < item || dup))
				{
					// Insert between i and i+1
					insert(i + 1, item);
					return i + 1;
				}
			}
			// Descending
			else
			{
				if (data[i + 1] < item && (data[i] > item || dup))
				{
					// Insert between i and i+1
					insert(i + 1, item);
					return i + 1;
				}
			}
		}

		// End of list
		i = count - 1;
		if (dup || data[i] != item)
		{
			insert(count, item);
			return count;
		}
	}
}

// Copy data, only allocate if needed
template <typename T>
void ArrayList<T>::copyData(const ArrayList<T>& b)
{
	clear();

	if (b.count > size)
		allocate(b.getSize());

	if (!(b.isEmpty()))
	{
		count = b.count;
		memcpy(data, b.data, count * sizeof(T));
	}
}

// Remove item at index
template <typename T>
bool ArrayList<T>::remove(unsigned int index)
{
	if (index >= count)
		return false;	// Invalid index
	else
	{
		for (unsigned int i = index; i < count - 1; i++)
		{
			data[i] = data[i + 1];
		}

		count--;
	}
}

// Clear and de-allocate memory
template <typename T>
void ArrayList<T>::free()
{
	clear();

	delete[] data;
}

#endif
<|endoftext|>


<commit_before>#include "unit_tests.h"
#include "crc_t.h"

//------------- tests for CRC_t methods -------------

int test_crc_t_name(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t  crc;

    if( crc.name != "CRC-32" )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_name_2(struct test_info_t  *test_info)
{

    TEST_INIT;

    const char* name = "some_name";

    CRC_t crc(name);

    if( crc.name != name )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_bits(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 0, 0, true, true, 0);

    if( crc.get_bits() != 1 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_poly(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 123, 0, true, true, 0);

    if( crc.get_poly() != 123 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_init(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 0, 1234, true, true, 0);

    if( crc.get_init() != 1234 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_xor_out(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 0, 0, true, true, 1000);

    if( crc.get_xor_out() != 1000 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_ref_in(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 0, 0, true, true, 0);

    if( crc.get_ref_in() != true )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_ref_out(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 0, 0, true, true, 0);

    if( crc.get_ref_out() != true )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_set_bits(struct test_info_t  *test_info)
{

    TEST_INIT;

    int i, res;

    CRC_t crc(1, 0, 0, true, true, 0);

    if( crc.get_bits() != 1 )
        return TEST_BROKEN;

    if( crc.set_bits(0) != -1 )
         return TEST_BROKEN;

    // 1..64
    for( i = 1; i <= 64; ++i)
    {
        res = crc.set_bits(i);
        if( res != 0 )
             return TEST_BROKEN;

        if( crc.get_bits() != i )
            return TEST_BROKEN;
    }

    //more 64
    for( i = 65; i <= 256; ++i)
    {
        if( crc.set_bits(i) != -1 )
             return TEST_BROKEN;
    }

    return TEST_PASSED;
}

//------------- tests for Calculate CRC  -------------

//width=3 poly=0x3 init=0x7 refin=true refout=true xorout=0x0 check=0x6 name="CRC-3/ROHC"
int test_crc3(struct test_info_t  *test_info)
{

    TEST_INIT;

    uint8_t crc;

    CRC_t ucrc(3, 0x3, 0x7, true, true, 0x0);

    crc = ucrc.get_crc("123456789", 9);
    if( crc != 0x6 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc4(struct test_info_t  *test_info)
{

    TEST_INIT;

    uint8_t crc;

    CRC_t ucrc(4, 0x3, 0x0, false, false, 0x0);

    crc = ucrc.get_crc("123456789", 9);
    if( crc != 0xE )
        return TEST_BROKEN;

    return TEST_PASSED;
}

//width=4 poly=0x3 init=0x0 refin=true refout=true xorout=0x0 check=0x7 name="CRC-4/ITU"
int test_crc4_2(struct test_info_t  *test_info)
{

    TEST_INIT;

    uint8_t crc;

    CRC_t ucrc(4, 0x3, 0x0, true, true, 0x0);

    crc = ucrc.get_crc("123456789", 9);
    if( crc != 0x7 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

//width=5 poly=0x09 init=0x09 refin=false refout=false xorout=0x00 check=0x00 name="CRC-5/EPC"
int test_crc5(struct test_info_t  *test_info)
{

    TEST_INIT;

    uint8_t crc;

    CRC_t ucrc(5, 0x09, 0x09, false, false, 0x0);

    crc = ucrc.get_crc("123456789", 9);
    if( crc != 0x0 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

ptest_func tests[] =
{

    //CRC_t methods
    test_crc_t_name,
    test_crc_t_name_2,

    test_crc_t_get_bits,
    test_crc_t_get_poly,
    test_crc_t_get_init,
    test_crc_t_get_xor_out,
    test_crc_t_get_ref_in,
    test_crc_t_get_ref_out,

    test_crc_t_set_bits,

    //CRC
    test_crc3,

    test_crc4,
    test_crc4_2,

    test_crc5,

};

int main(void)
{

    RUN_TESTS(tests);

    return 0;
}
<commit_msg>add test to calculate the CRC-5/ITU<commit_after>#include "unit_tests.h"
#include "crc_t.h"

//------------- tests for CRC_t methods -------------

int test_crc_t_name(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t  crc;

    if( crc.name != "CRC-32" )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_name_2(struct test_info_t  *test_info)
{

    TEST_INIT;

    const char* name = "some_name";

    CRC_t crc(name);

    if( crc.name != name )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_bits(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 0, 0, true, true, 0);

    if( crc.get_bits() != 1 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_poly(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 123, 0, true, true, 0);

    if( crc.get_poly() != 123 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_init(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 0, 1234, true, true, 0);

    if( crc.get_init() != 1234 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_xor_out(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 0, 0, true, true, 1000);

    if( crc.get_xor_out() != 1000 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_ref_in(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 0, 0, true, true, 0);

    if( crc.get_ref_in() != true )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_get_ref_out(struct test_info_t  *test_info)
{

    TEST_INIT;

    CRC_t crc(1, 0, 0, true, true, 0);

    if( crc.get_ref_out() != true )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc_t_set_bits(struct test_info_t  *test_info)
{

    TEST_INIT;

    int i, res;

    CRC_t crc(1, 0, 0, true, true, 0);

    if( crc.get_bits() != 1 )
        return TEST_BROKEN;

    if( crc.set_bits(0) != -1 )
         return TEST_BROKEN;

    // 1..64
    for( i = 1; i <= 64; ++i)
    {
        res = crc.set_bits(i);
        if( res != 0 )
             return TEST_BROKEN;

        if( crc.get_bits() != i )
            return TEST_BROKEN;
    }

    //more 64
    for( i = 65; i <= 256; ++i)
    {
        if( crc.set_bits(i) != -1 )
             return TEST_BROKEN;
    }

    return TEST_PASSED;
}

//------------- tests for Calculate CRC  -------------

//width=3 poly=0x3 init=0x7 refin=true refout=true xorout=0x0 check=0x6 name="CRC-3/ROHC"
int test_crc3(struct test_info_t  *test_info)
{

    TEST_INIT;

    uint8_t crc;

    CRC_t ucrc(3, 0x3, 0x7, true, true, 0x0);

    crc = ucrc.get_crc("123456789", 9);
    if( crc != 0x6 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

int test_crc4(struct test_info_t  *test_info)
{

    TEST_INIT;

    uint8_t crc;

    CRC_t ucrc(4, 0x3, 0x0, false, false, 0x0);

    crc = ucrc.get_crc("123456789", 9);
    if( crc != 0xE )
        return TEST_BROKEN;

    return TEST_PASSED;
}

//width=4 poly=0x3 init=0x0 refin=true refout=true xorout=0x0 check=0x7 name="CRC-4/ITU"
int test_crc4_2(struct test_info_t  *test_info)
{

    TEST_INIT;

    uint8_t crc;

    CRC_t ucrc(4, 0x3, 0x0, true, true, 0x0);

    crc = ucrc.get_crc("123456789", 9);
    if( crc != 0x7 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

//width=5 poly=0x09 init=0x09 refin=false refout=false xorout=0x00 check=0x00 name="CRC-5/EPC"
int test_crc5(struct test_info_t  *test_info)
{

    TEST_INIT;

    uint8_t crc;

    CRC_t ucrc(5, 0x09, 0x09, false, false, 0x0);

    crc = ucrc.get_crc("123456789", 9);
    if( crc != 0x0 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

//width=5 poly=0x15 init=0x00 refin=true refout=true xorout=0x00 check=0x07 name="CRC-5/ITU"
int test_crc5_2(struct test_info_t  *test_info)
{

    TEST_INIT;

    uint8_t crc;

    CRC_t ucrc(5, 0x15, 0x00, true, true, 0x0);

    crc = ucrc.get_crc("123456789", 9);
    if( crc != 0x07 )
        return TEST_BROKEN;

    return TEST_PASSED;
}

ptest_func tests[] =
{

    //CRC_t methods
    test_crc_t_name,
    test_crc_t_name_2,

    test_crc_t_get_bits,
    test_crc_t_get_poly,
    test_crc_t_get_init,
    test_crc_t_get_xor_out,
    test_crc_t_get_ref_in,
    test_crc_t_get_ref_out,

    test_crc_t_set_bits,

    //CRC
    test_crc3,

    test_crc4,
    test_crc4_2,

    test_crc5,
    test_crc5_2,

};

int main(void)
{

    RUN_TESTS(tests);

    return 0;
}
<|endoftext|>


<commit_before>#include "etl/assert.h"

namespace etl {

void assertion_failed(char const *, int, char const *, char const *) {
  while (true);
}

}  // namespace etl
<commit_msg>assert_loop: name parameters for GDB.<commit_after>#include "etl/assert.h"

namespace etl {

void assertion_failed(char const * file,
                      int line,
                      char const * function,
                      char const * expression) {
  // Parameters are named to help GDB display them.
  while (true);
}

}  // namespace etl
<|endoftext|>


<commit_before>// Copyright (c) 2009 hp-FEM group at the University of Nevada, Reno (UNR).
// Distributed under the terms of the BSD license (see the LICENSE
// file for the exact terms).
// Email: hermes1d@googlegroups.com, home page: http://hpfem.org/

#include "matrix.h"

#include "python_api.h"

void solve_linear_system_numpy(Matrix *mat, double *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr().todense()");
    p->exec("from numpy.linalg import solve");
    p->exec("x = solve(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}

void solve_linear_system_numpy(Matrix *mat, cplx *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_complex_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr().todense()");
    p->exec("from numpy.linalg import solve");
    p->exec("x = solve(A, rhs)");
    cplx *x;
    int n;
    numpy2c_double_complex_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(cplx));
    delete p;
}

void solve_linear_system_scipy_umfpack(Matrix *mat, double *res)
{
    CSCMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSCMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csc()");
    p->exec("from scipy.sparse.linalg import spsolve");
    p->exec("x = spsolve(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}

void solve_linear_system_scipy_umfpack(Matrix *mat, cplx *res)
{
    CSCMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSCMatrix(&M));
    p->push("rhs", c2numpy_double_complex_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csc()");
    p->exec("from scipy.sparse.linalg import spsolve");
    p->exec("x = spsolve(A, rhs)");
    cplx *x;
    int n;
    numpy2c_double_complex_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(cplx));
    delete p;
}

void solve_linear_system_scipy_cg(Matrix *mat, double *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr()");
    p->exec("from scipy.sparse.linalg import cg");
    p->exec("x, res = cg(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}

void solve_linear_system_scipy_gmres(Matrix *mat, double *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr()");
    p->exec("from scipy.sparse.linalg import gmres");
    p->exec("x, res = gmres(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}
<commit_msg>Fix the SciPy DeprecationWarning<commit_after>// Copyright (c) 2009 hp-FEM group at the University of Nevada, Reno (UNR).
// Distributed under the terms of the BSD license (see the LICENSE
// file for the exact terms).
// Email: hermes1d@googlegroups.com, home page: http://hpfem.org/

#include "matrix.h"

#include "python_api.h"

void solve_linear_system_numpy(Matrix *mat, double *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr().todense()");
    p->exec("from numpy.linalg import solve");
    p->exec("x = solve(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}

void solve_linear_system_numpy(Matrix *mat, cplx *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_complex_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr().todense()");
    p->exec("from numpy.linalg import solve");
    p->exec("x = solve(A, rhs)");
    cplx *x;
    int n;
    numpy2c_double_complex_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(cplx));
    delete p;
}

void solve_linear_system_scipy_umfpack(Matrix *mat, double *res)
{
    CSCMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSCMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csc()");
    p->exec("from scipy.sparse.linalg import spsolve");
    // Turn off warnings in spsolve (only there)
    p->exec("import warnings");
    p->exec("with warnings.catch_warnings():\n"
            "    warnings.simplefilter('ignore')\n"
            "    x = spsolve(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}

void solve_linear_system_scipy_umfpack(Matrix *mat, cplx *res)
{
    CSCMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSCMatrix(&M));
    p->push("rhs", c2numpy_double_complex_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csc()");
    p->exec("from scipy.sparse.linalg import spsolve");
    p->exec("x = spsolve(A, rhs)");
    cplx *x;
    int n;
    numpy2c_double_complex_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(cplx));
    delete p;
}

void solve_linear_system_scipy_cg(Matrix *mat, double *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr()");
    p->exec("from scipy.sparse.linalg import cg");
    p->exec("x, res = cg(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}

void solve_linear_system_scipy_gmres(Matrix *mat, double *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr()");
    p->exec("from scipy.sparse.linalg import gmres");
    p->exec("x, res = gmres(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <list>
#include <thread>

#include <boost/asio.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/read.hpp>
using namespace::boost::asio;

#define DUMP_VAR(x) std::cout << __func__ << #x << "=<" << x <<">" << std::endl;

std::list<std::string> gCarCommand;

std::mutex mtx;
std::condition_variable cv;

void push_command(const std::string &cmd)
{
   std::unique_lock<std::mutex> lock(mtx);
   if("init"==cmd) {
      gCarCommand.clear();
   }
   if("top"==cmd) {
      gCarCommand.push_back("a.speed:40000\n");
      gCarCommand.push_back("a.turn:fwd\n");
      gCarCommand.push_back("b.speed:40000\n");
      gCarCommand.push_back("b.turn:fwd\n");
      gCarCommand.push_back("c.speed:40000\n");
      gCarCommand.push_back("c.turn:fwd\n");
      gCarCommand.push_back("d.speed:40000\n");
      gCarCommand.push_back("d.turn:fwd\n");
      gCarCommand.push_back("run\n");
   }
   cv.notify_one();
}

void read_dummy()
{
  ::system("cat /dev/ttyUSB0");
}

void handle_read_content(const boost::system::error_code& err){
   DUMP_VAR(err);
}

void car_uart_main(void)
{
    io_service io_;
    serial_port port_( io_, "/dev/ttyUSB0" );
    port_.set_option( serial_port_base::baud_rate(115200));
    //std::thread thr_read(read_dummy);
    //thr_read.detach();
    while(true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock);
        if(false == gCarCommand.empty()) {
           for(auto cmd:gCarCommand) {
              boost::asio::write(port_, boost::asio::buffer(cmd.c_str(), cmd.size()));
              boost::asio::streambuf b;
              boost::asio::async_read(port_,streambuf,handle_read_content);
           }
           gCarCommand.clear();
        }
    }
}

<commit_msg>Update car.entry.cpp<commit_after>#include <string>
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <list>
#include <thread>

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/read.hpp>
using namespace::boost::asio;

#define DUMP_VAR(x) std::cout << __func__ << #x << "=<" << x <<">" << std::endl;

std::list<std::string> gCarCommand;

std::mutex mtx;
std::condition_variable cv;

void push_command(const std::string &cmd)
{
   std::unique_lock<std::mutex> lock(mtx);
   if("init"==cmd) {
      gCarCommand.clear();
   }
   if("top"==cmd) {
      gCarCommand.push_back("a.speed:40000\n");
      gCarCommand.push_back("a.turn:fwd\n");
      gCarCommand.push_back("b.speed:40000\n");
      gCarCommand.push_back("b.turn:fwd\n");
      gCarCommand.push_back("c.speed:40000\n");
      gCarCommand.push_back("c.turn:fwd\n");
      gCarCommand.push_back("d.speed:40000\n");
      gCarCommand.push_back("d.turn:fwd\n");
      gCarCommand.push_back("run\n");
   }
   cv.notify_one();
}

void read_dummy()
{
  ::system("cat /dev/ttyUSB0");
}

void handle_read_content(const boost::system::error_code& err){
   DUMP_VAR(err);
}

void car_uart_main(void)
{
    io_service io_;
    serial_port port_( io_, "/dev/ttyUSB0" );
    port_.set_option( serial_port_base::baud_rate(115200));
    //std::thread thr_read(read_dummy);
    //thr_read.detach();
    while(true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock);
        if(false == gCarCommand.empty()) {
           for(auto cmd:gCarCommand) {
              boost::asio::write(port_, boost::asio::buffer(cmd.c_str(), cmd.size()));
              boost::asio::streambuf b;
              boost::asio::async_read(port_,streambuf,boost::bind(&handle_read_content));
           }
           gCarCommand.clear();
        }
    }
}

<|endoftext|>


<commit_before>#include <string.h>
#include <node.h>
#include <nan.h>
#include <node_buffer.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/ecdh.h>

#include "eckey.h"

using namespace v8;
using namespace node;

// Not sure where this came from. but looks like a function that should be part of openssl
int static inline EC_KEY_regenerate_key(EC_KEY *eckey, const BIGNUM *priv_key) {
	if (!eckey) return 0;
	int ok = 0;
	BN_CTX *ctx = NULL;
	EC_POINT *pub_key = NULL;
	const EC_GROUP *group = EC_KEY_get0_group(eckey);
	if ((ctx = BN_CTX_new()) == NULL)
		goto err;
	pub_key = EC_POINT_new(group);
	if (pub_key == NULL)
		goto err;
	if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
		goto err;
	EC_KEY_set_private_key(eckey, priv_key);
	EC_KEY_set_public_key(eckey, pub_key);
	ok = 1;
err:
	if (pub_key)
		EC_POINT_free(pub_key);
	if (ctx != NULL)
		BN_CTX_free(ctx);
	return ok;
}

ECKey::ECKey(int curve) {
	mHasPrivateKey = false;
	mCurve = curve;
	mKey = EC_KEY_new_by_curve_name(mCurve);
	if (!mKey) {
		NanThrowError("EC_KEY_new_by_curve_name Invalid curve?");
		return;
	}
}
ECKey::~ECKey() {
	if (mKey) {
		EC_KEY_free(mKey);
	}
}

// Node module init
void ECKey::Init(Handle<Object> exports) {
	Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
	tpl->SetClassName(NanNew<String>("ECKey"));
	tpl->InstanceTemplate()->SetInternalFieldCount(1);

	//Accessors
	tpl->InstanceTemplate()->SetAccessor(NanNew<String>("HasPrivateKey"), GetHasPrivateKey);
	tpl->InstanceTemplate()->SetAccessor(NanNew<String>("PublicKey"), GetPublicKey);
	tpl->InstanceTemplate()->SetAccessor(NanNew<String>("PrivateKey"), GetPrivateKey);

	//Methods (Prototype)
	tpl->PrototypeTemplate()->Set(NanNew<String>("sign"), NanNew<FunctionTemplate>(Sign)->GetFunction());
	tpl->PrototypeTemplate()->Set(NanNew<String>("verifySignature"), NanNew<FunctionTemplate>(VerifySignature)->GetFunction());
	tpl->PrototypeTemplate()->Set(NanNew<String>("deriveSharedSecret"), NanNew<FunctionTemplate>(DeriveSharedSecret)->GetFunction());

	Persistent<Function> constructor = Persistent<Function>::New(tpl->GetFunction());
	exports->Set(NanNew<String>("ECKey"), constructor);
}

// Node constructor function
// new ECKey(curve, buffer, isPublic)
NAN_METHOD(ECKey::New) {
	if (!args.IsConstructCall()) {
		return NanThrowError("Must use new keyword");
	}
	if (args[0]->IsUndefined()) {
		return NanThrowError("First argument must be an ECCurve");
	}
	HandleScope scope;
	ECKey *eckey = new ECKey(args[0]->NumberValue());
	if (!args[1]->IsUndefined()) {
		if (!Buffer::HasInstance(args[1])) {
			return NanThrowError("Second parameter must be a buffer");
		}
		//we have a second parameter, check the third to see if it is public or private.
		Handle<Object> buffer = args[1]->ToObject();
		const unsigned char *bufferData = (unsigned char *) Buffer::Data(buffer);
		if ((args[2]->IsUndefined()) || (args[2]->BooleanValue() == false)) {
			// it's a private key
			BIGNUM *bn = BN_bin2bn(bufferData, Buffer::Length(buffer), BN_new());
			if (EC_KEY_regenerate_key(eckey->mKey, bn) == 0) {
				BN_clear_free(bn);
				return NanThrowError("Invalid private key");
			}
			BN_clear_free(bn);
			eckey->mHasPrivateKey = true;
		} else {
			// it's a public key
			if (!o2i_ECPublicKey(&(eckey->mKey), &bufferData, Buffer::Length(buffer))) {
				return NanThrowError("o2i_ECPublicKey failed, Invalid public key");
			}
		}
	} else {
		if (!EC_KEY_generate_key(eckey->mKey)) {
			return NanThrowError("EC_KEY_generate_key failed");
		}
		eckey->mHasPrivateKey = true;
	}
	eckey->Wrap(args.Holder());
	return args.Holder();
}

// Node properity functions
NAN_GETTER(ECKey::GetHasPrivateKey) {
	HandleScope scope;
	ECKey *eckey = ObjectWrap::Unwrap<ECKey>(info.Holder());
	return scope.Close(NanNew<Boolean>(eckey->mHasPrivateKey));
}
NAN_GETTER(ECKey::GetPublicKey) {
	ECKey *eckey = ObjectWrap::Unwrap<ECKey>(info.Holder());
	const EC_GROUP *group = EC_KEY_get0_group(eckey->mKey);
	const EC_POINT *point = EC_KEY_get0_public_key(eckey->mKey);
	unsigned int nReq = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, NULL, 0, NULL);
	if (!nReq) {
		return NanThrowError("EC_POINT_point2oct error");
	}
	unsigned char *buf, *buf2;
	buf = buf2 = (unsigned char *)malloc(nReq);
	if (EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, buf, nReq, NULL) != nReq) {
		return NanThrowError("EC_POINT_point2oct didn't return correct size");
	}
	HandleScope scope;
	Buffer *buffer = Buffer::New(nReq);
	memcpy(Buffer::Data(buffer), buf2, nReq);
	free(buf2);
	return scope.Close(buffer->handle_);
}
NAN_GETTER(ECKey::GetPrivateKey) {
	ECKey *eckey = ObjectWrap::Unwrap<ECKey>(info.Holder());
	const BIGNUM *bn = EC_KEY_get0_private_key(eckey->mKey);
	if (bn == NULL) {
		return NanThrowError("EC_KEY_get0_private_key failed");
	}
	int priv_size = BN_num_bytes(bn);
	unsigned char *priv_buf = (unsigned char *)malloc(priv_size);
	int n = BN_bn2bin(bn, priv_buf);
	if (n != priv_size) {
		return NanThrowError("BN_bn2bin didn't return priv_size");
	}
	HandleScope scope;
	Buffer *buffer = Buffer::New(priv_size);
	memcpy(Buffer::Data(buffer), priv_buf, priv_size);
	free(priv_buf);
	return scope.Close(buffer->handle_);
}

// Node method functions
NAN_METHOD(ECKey::Sign) {
	HandleScope scope;
	ECKey * eckey = ObjectWrap::Unwrap<ECKey>(args.Holder());
	if (!Buffer::HasInstance(args[0])) {
		return NanThrowError("digest must be a buffer");
	}
	if (!eckey->mHasPrivateKey) {
		return NanThrowError("cannot sign without private key");
	}
	Handle<Object> digest = args[0]->ToObject();
	const unsigned char *digest_data = (unsigned char *)Buffer::Data(digest);
	unsigned int digest_len = Buffer::Length(digest);

	ECDSA_SIG *sig = ECDSA_do_sign(digest_data, digest_len, eckey->mKey);
	if (!sig) {
		return NanThrowError("ECDSA_do_sign");
	}
	int sig_len = i2d_ECDSA_SIG(sig, NULL);
	if (!sig_len) {
		return NanThrowError("i2d_ECDSA_SIG");
	}
	unsigned char *sig_data, *sig_data2;
	sig_data = sig_data2 = (unsigned char *)malloc(sig_len);
	if (i2d_ECDSA_SIG(sig, &sig_data) != sig_len) {
		ECDSA_SIG_free(sig);
		free(sig_data2);
		return NanThrowError("i2d_ECDSA_SIG didnot return correct length");
	}
	ECDSA_SIG_free(sig);
	Buffer *result = Buffer::New(sig_len);
	memcpy(Buffer::Data(result), sig_data2, sig_len);
	free(sig_data2);
	return scope.Close(result->handle_);
}
NAN_METHOD(ECKey::VerifySignature) {
	HandleScope scope;
	ECKey *eckey = ObjectWrap::Unwrap<ECKey>(args.Holder());
	if (!Buffer::HasInstance(args[0])) {
		return NanThrowError("digest must be a buffer");
	}
	if (!Buffer::HasInstance(args[1])) {
		return NanThrowError("signature must be a buffer");
	}
	Handle<Object> digest = args[0]->ToObject();
	Handle<Object> signature = args[1]->ToObject();
	const unsigned char *digest_data = (unsigned char *)Buffer::Data(digest);
	const unsigned char *signature_data = (unsigned char *)Buffer::Data(signature);
	unsigned int digest_len = Buffer::Length(digest);
	unsigned int signature_len = Buffer::Length(signature);
	int result = ECDSA_verify(0, digest_data, digest_len, signature_data, signature_len, eckey->mKey);
	if (result == -1) {
		return NanThrowError("ECDSA_verify");
	} else if (result == 0) {
		return scope.Close(NanNew<Boolean>(false));
	} else if (result == 1) {
		return scope.Close(NanNew<Boolean>(true));
	} else {
		return NanThrowError("ECDSA_verify gave an unexpected return value");
	}
}
NAN_METHOD(ECKey::DeriveSharedSecret) {
	HandleScope scope;
	if (args[0]->IsUndefined()) {
		return NanThrowError("other is required");
	}
	ECKey *eckey = ObjectWrap::Unwrap<ECKey>(args.Holder());
	ECKey *other = ObjectWrap::Unwrap<ECKey>(args[0]->ToObject());
	if (!other) {
		return NanThrowError("other must be an ECKey");
	}
	unsigned char *secret = (unsigned char*)malloc(512);
	int len = ECDH_compute_key(secret, 512, EC_KEY_get0_public_key(other->mKey), eckey->mKey, NULL);
	Buffer *result = Buffer::New(len);
	memcpy(Buffer::Data(result), secret, len);
	free(secret);
	return scope.Close(result->handle_);
}
<commit_msg>Change scope and return value handling<commit_after>#include <string.h>
#include <node.h>
#include <nan.h>
#include <node_buffer.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/ecdh.h>

#include "eckey.h"

using namespace v8;
using namespace node;

// Not sure where this came from. but looks like a function that should be part of openssl
int static inline EC_KEY_regenerate_key(EC_KEY *eckey, const BIGNUM *priv_key) {
	if (!eckey) return 0;
	int ok = 0;
	BN_CTX *ctx = NULL;
	EC_POINT *pub_key = NULL;
	const EC_GROUP *group = EC_KEY_get0_group(eckey);
	if ((ctx = BN_CTX_new()) == NULL)
		goto err;
	pub_key = EC_POINT_new(group);
	if (pub_key == NULL)
		goto err;
	if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
		goto err;
	EC_KEY_set_private_key(eckey, priv_key);
	EC_KEY_set_public_key(eckey, pub_key);
	ok = 1;
err:
	if (pub_key)
		EC_POINT_free(pub_key);
	if (ctx != NULL)
		BN_CTX_free(ctx);
	return ok;
}

ECKey::ECKey(int curve) {
	mHasPrivateKey = false;
	mCurve = curve;
	mKey = EC_KEY_new_by_curve_name(mCurve);
	if (!mKey) {
		NanThrowError("EC_KEY_new_by_curve_name Invalid curve?");
		return;
	}
}
ECKey::~ECKey() {
	if (mKey) {
		EC_KEY_free(mKey);
	}
}

// Node module init
void ECKey::Init(Handle<Object> exports) {
	Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
	tpl->SetClassName(NanNew<String>("ECKey"));
	tpl->InstanceTemplate()->SetInternalFieldCount(1);

	//Accessors
	tpl->InstanceTemplate()->SetAccessor(NanNew<String>("HasPrivateKey"), GetHasPrivateKey);
	tpl->InstanceTemplate()->SetAccessor(NanNew<String>("PublicKey"), GetPublicKey);
	tpl->InstanceTemplate()->SetAccessor(NanNew<String>("PrivateKey"), GetPrivateKey);

	//Methods (Prototype)
	tpl->PrototypeTemplate()->Set(NanNew<String>("sign"), NanNew<FunctionTemplate>(Sign)->GetFunction());
	tpl->PrototypeTemplate()->Set(NanNew<String>("verifySignature"), NanNew<FunctionTemplate>(VerifySignature)->GetFunction());
	tpl->PrototypeTemplate()->Set(NanNew<String>("deriveSharedSecret"), NanNew<FunctionTemplate>(DeriveSharedSecret)->GetFunction());

	Persistent<Function> constructor = Persistent<Function>::New(tpl->GetFunction());
	exports->Set(NanNew<String>("ECKey"), constructor);
}

// Node constructor function
// new ECKey(curve, buffer, isPublic)
NAN_METHOD(ECKey::New) {
	if (!args.IsConstructCall()) {
		return NanThrowError("Must use new keyword");
	}
	if (args[0]->IsUndefined()) {
		return NanThrowError("First argument must be an ECCurve");
	}
	NanScope();
	ECKey *eckey = new ECKey(args[0]->NumberValue());
	if (!args[1]->IsUndefined()) {
		if (!Buffer::HasInstance(args[1])) {
			return NanThrowError("Second parameter must be a buffer");
		}
		//we have a second parameter, check the third to see if it is public or private.
		Handle<Object> buffer = args[1]->ToObject();
		const unsigned char *bufferData = (unsigned char *) Buffer::Data(buffer);
		if ((args[2]->IsUndefined()) || (args[2]->BooleanValue() == false)) {
			// it's a private key
			BIGNUM *bn = BN_bin2bn(bufferData, Buffer::Length(buffer), BN_new());
			if (EC_KEY_regenerate_key(eckey->mKey, bn) == 0) {
				BN_clear_free(bn);
				return NanThrowError("Invalid private key");
			}
			BN_clear_free(bn);
			eckey->mHasPrivateKey = true;
		} else {
			// it's a public key
			if (!o2i_ECPublicKey(&(eckey->mKey), &bufferData, Buffer::Length(buffer))) {
				return NanThrowError("o2i_ECPublicKey failed, Invalid public key");
			}
		}
	} else {
		if (!EC_KEY_generate_key(eckey->mKey)) {
			return NanThrowError("EC_KEY_generate_key failed");
		}
		eckey->mHasPrivateKey = true;
	}
	eckey->Wrap(args.Holder());
	NanReturnHolder();
}

// Node properity functions
NAN_GETTER(ECKey::GetHasPrivateKey) {
	NanScope();
	ECKey *eckey = ObjectWrap::Unwrap<ECKey>(info.Holder());
	NanReturnValue(NanNew<Boolean>(eckey->mHasPrivateKey));
}
NAN_GETTER(ECKey::GetPublicKey) {
	ECKey *eckey = ObjectWrap::Unwrap<ECKey>(info.Holder());
	const EC_GROUP *group = EC_KEY_get0_group(eckey->mKey);
	const EC_POINT *point = EC_KEY_get0_public_key(eckey->mKey);
	unsigned int nReq = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, NULL, 0, NULL);
	if (!nReq) {
		return NanThrowError("EC_POINT_point2oct error");
	}
	unsigned char *buf, *buf2;
	buf = buf2 = (unsigned char *)malloc(nReq);
	if (EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, buf, nReq, NULL) != nReq) {
		return NanThrowError("EC_POINT_point2oct didn't return correct size");
	}
	NanScope();
	Buffer *buffer = Buffer::New(nReq);
	memcpy(Buffer::Data(buffer), buf2, nReq);
	free(buf2);
	NanReturnValue(buffer->handle_);
}
NAN_GETTER(ECKey::GetPrivateKey) {
	ECKey *eckey = ObjectWrap::Unwrap<ECKey>(info.Holder());
	const BIGNUM *bn = EC_KEY_get0_private_key(eckey->mKey);
	if (bn == NULL) {
		return NanThrowError("EC_KEY_get0_private_key failed");
	}
	int priv_size = BN_num_bytes(bn);
	unsigned char *priv_buf = (unsigned char *)malloc(priv_size);
	int n = BN_bn2bin(bn, priv_buf);
	if (n != priv_size) {
		return NanThrowError("BN_bn2bin didn't return priv_size");
	}
	NanScope();
	Buffer *buffer = Buffer::New(priv_size);
	memcpy(Buffer::Data(buffer), priv_buf, priv_size);
	free(priv_buf);
	NanReturnValue(buffer->handle_);
}

// Node method functions
NAN_METHOD(ECKey::Sign) {
	NanScope();
	ECKey * eckey = ObjectWrap::Unwrap<ECKey>(args.Holder());
	if (!Buffer::HasInstance(args[0])) {
		return NanThrowError("digest must be a buffer");
	}
	if (!eckey->mHasPrivateKey) {
		return NanThrowError("cannot sign without private key");
	}
	Handle<Object> digest = args[0]->ToObject();
	const unsigned char *digest_data = (unsigned char *)Buffer::Data(digest);
	unsigned int digest_len = Buffer::Length(digest);

	ECDSA_SIG *sig = ECDSA_do_sign(digest_data, digest_len, eckey->mKey);
	if (!sig) {
		return NanThrowError("ECDSA_do_sign");
	}
	int sig_len = i2d_ECDSA_SIG(sig, NULL);
	if (!sig_len) {
		return NanThrowError("i2d_ECDSA_SIG");
	}
	unsigned char *sig_data, *sig_data2;
	sig_data = sig_data2 = (unsigned char *)malloc(sig_len);
	if (i2d_ECDSA_SIG(sig, &sig_data) != sig_len) {
		ECDSA_SIG_free(sig);
		free(sig_data2);
		return NanThrowError("i2d_ECDSA_SIG didnot return correct length");
	}
	ECDSA_SIG_free(sig);
	Buffer *result = Buffer::New(sig_len);
	memcpy(Buffer::Data(result), sig_data2, sig_len);
	free(sig_data2);
	NanReturnValue(result->handle_);
}
NAN_METHOD(ECKey::VerifySignature) {
	NanScope();
	ECKey *eckey = ObjectWrap::Unwrap<ECKey>(args.Holder());
	if (!Buffer::HasInstance(args[0])) {
		return NanThrowError("digest must be a buffer");
	}
	if (!Buffer::HasInstance(args[1])) {
		return NanThrowError("signature must be a buffer");
	}
	Handle<Object> digest = args[0]->ToObject();
	Handle<Object> signature = args[1]->ToObject();
	const unsigned char *digest_data = (unsigned char *)Buffer::Data(digest);
	const unsigned char *signature_data = (unsigned char *)Buffer::Data(signature);
	unsigned int digest_len = Buffer::Length(digest);
	unsigned int signature_len = Buffer::Length(signature);
	int result = ECDSA_verify(0, digest_data, digest_len, signature_data, signature_len, eckey->mKey);
	if (result == -1) {
		return NanThrowError("ECDSA_verify");
	} else if (result == 0) {
		NanReturnValue(NanNew<Boolean>(false));
	} else if (result == 1) {
		NanReturnValue(NanNew<Boolean>(true));
	} else {
		return NanThrowError("ECDSA_verify gave an unexpected return value");
	}
}
NAN_METHOD(ECKey::DeriveSharedSecret) {
	NanScope();
	if (args[0]->IsUndefined()) {
		return NanThrowError("other is required");
	}
	ECKey *eckey = ObjectWrap::Unwrap<ECKey>(args.Holder());
	ECKey *other = ObjectWrap::Unwrap<ECKey>(args[0]->ToObject());
	if (!other) {
		return NanThrowError("other must be an ECKey");
	}
	unsigned char *secret = (unsigned char*)malloc(512);
	int len = ECDH_compute_key(secret, 512, EC_KEY_get0_public_key(other->mKey), eckey->mKey, NULL);
	Buffer *result = Buffer::New(len);
	memcpy(Buffer::Data(result), secret, len);
	free(secret);
	NanReturnValue(result->handle_);
}
<|endoftext|>


<commit_before>/* Copyright 2019 Istio Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "extensions/stats/plugin.h"

// WASM_PROLOG
#ifndef NULL_PLUGIN
#include "proxy_wasm_intrinsics.h"

#else  // NULL_PLUGIN

#include "extensions/common/wasm/null/null.h"

namespace Envoy {
namespace Extensions {
namespace Common {
namespace Wasm {
namespace Null {
namespace Plugin {

#endif  // NULL_PLUGIN

// END WASM_PROLOG

namespace Stats {

bool PluginRootContext::onConfigure(std::unique_ptr<WasmData> configuration) {
  // Parse configuration JSON string.
  JsonParseOptions json_options;
  Status status =
      JsonStringToMessage(configuration->toString(), &config_, json_options);
  if (status != Status::OK) {
    LOG_WARN(absl::StrCat("Cannot parse plugin configuration JSON string ",
                          configuration->toString()));
    return false;
  }

  status = ::Wasm::Common::extractLocalNodeMetadata(&local_node_info_);
  if (status != Status::OK) {
    LOG_WARN("cannot parse local node metadata ");
    return false;
  }
  int64_t direction;
  if (getValue({"listener_direction"}, &direction)) {
    outbound_ = envoy::api::v2::core::TrafficDirection::OUTBOUND == direction;
  } else {
    LOG_WARN("Unable to get plugin direction");
  }
  // Local data does not change, so populate it on config load.
  istio_dimensions_.init(outbound_, local_node_info_);

  if (outbound_) {
    peer_metadata_id_key_ = ::Wasm::Common::kUpstreamMetadataIdKey;
    peer_metadata_key_ = ::Wasm::Common::kUpstreamMetadataKey;
  } else {
    peer_metadata_id_key_ = ::Wasm::Common::kDownstreamMetadataIdKey;
    peer_metadata_key_ = ::Wasm::Common::kDownstreamMetadataKey;
  }
  debug_ = config_.debug();
  node_info_cache_.set_max_cache_size(config_.max_peer_cache_size());

  auto field_separator = CONFIG_DEFAULT(field_separator);
  auto value_separator = CONFIG_DEFAULT(value_separator);
  auto stat_prefix = CONFIG_DEFAULT(stat_prefix);

  // prepend "_" to opt out of automatic namespacing
  // If "_" is not prepended, envoy_ is automatically added by prometheus
  // scraper"
  stat_prefix = absl::StrCat("_", stat_prefix, "_");

  Metric build(MetricType::Gauge, absl::StrCat(stat_prefix, "build"),
               {MetricTag{"component", MetricTag::TagType::String},
                MetricTag{"tag", MetricTag::TagType::String}});
  build.record(1, "proxy", absl::StrCat(local_node_info_.istio_version(), ";"));

  stats_ = std::vector<StatGen>{
      StatGen(
          absl::StrCat(stat_prefix, "requests_total"), MetricType::Counter,
          [](const ::Wasm::Common::RequestInfo&) -> uint64_t { return 1; },
          field_separator, value_separator),
      StatGen(
          absl::StrCat(stat_prefix, "request_duration_milliseconds"),
          MetricType::Histogram,
          [](const ::Wasm::Common::RequestInfo& request_info) -> uint64_t {
            return (request_info.end_timestamp - request_info.start_timestamp) /
                   1000000;
          },
          field_separator, value_separator),
      StatGen(
          absl::StrCat(stat_prefix, "request_bytes"), MetricType::Histogram,
          [](const ::Wasm::Common::RequestInfo& request_info) -> uint64_t {
            return request_info.request_size;
          },
          field_separator, value_separator),
      StatGen(
          absl::StrCat(stat_prefix, "response_bytes"), MetricType::Histogram,
          [](const ::Wasm::Common::RequestInfo& request_info) -> uint64_t {
            return request_info.response_size;
          },
          field_separator, value_separator)};
  return true;
}

void PluginRootContext::report(
    const ::Wasm::Common::RequestInfo& request_info) {
  const auto& peer_node =
      node_info_cache_.getPeerById(peer_metadata_id_key_, peer_metadata_key_);

  // map and overwrite previous mapping.
  istio_dimensions_.map(peer_node, request_info);

  auto stats_it = metrics_.find(istio_dimensions_);
  if (stats_it != metrics_.end()) {
    for (auto& stat : stats_it->second) {
      stat.record(request_info);
      LOG_DEBUG(absl::StrCat(
          "metricKey cache hit ", istio_dimensions_.debug_key(),
          ", stat=", stat.metric_id_, stats_it->first.to_string()));
    }
    cache_hits_accumulator_++;
    if (cache_hits_accumulator_ == 100) {
      incrementMetric(cache_hits_, cache_hits_accumulator_);
      cache_hits_accumulator_ = 0;
    }
    return;
  }

  // fetch dimensions in the required form for resolve.
  auto values = istio_dimensions_.values();

  std::vector<SimpleStat> stats;
  for (auto& statgen : stats_) {
    auto stat = statgen.resolve(values);
    LOG_DEBUG(absl::StrCat("metricKey cache miss ", statgen.name(), " ",
                           istio_dimensions_.debug_key(),
                           ", stat=", stat.metric_id_));
    stat.record(request_info);
    stats.push_back(stat);
  }

  incrementMetric(cache_misses_, 1);
  // TODO: When we have c++17, convert to try_emplace.
  metrics_.emplace(istio_dimensions_, stats);
}

const wasm::common::NodeInfo& NodeInfoCache::getPeerById(
    StringView peer_metadata_id_key, StringView peer_metadata_key) {
  std::string peer_id;
  if (!getStringValue({"filter_state", peer_metadata_id_key}, &peer_id)) {
    LOG_DEBUG(absl::StrCat("cannot get metadata for: ", peer_metadata_id_key));
    return cache_[""];
  }
  auto nodeinfo_it = cache_.find(peer_id);
  if (nodeinfo_it != cache_.end()) {
    return nodeinfo_it->second;
  }

  // Do not let the cache grow beyond max_cache_size_.
  if (cache_.size() > max_cache_size_) {
    auto it = cache_.begin();
    cache_.erase(cache_.begin(), std::next(it, max_cache_size_ / 4));
    LOG_INFO(absl::StrCat("cleaned cache, new cache_size:", cache_.size()));
  }

  google::protobuf::Struct metadata;
  if (!getStructValue({"filter_state", peer_metadata_key}, &metadata)) {
    LOG_DEBUG(absl::StrCat("cannot get metadata for: ", peer_metadata_key));
    return cache_[""];
  }

  auto status =
      ::Wasm::Common::extractNodeMetadata(metadata, &(cache_[peer_id]));
  if (status != Status::OK) {
    LOG_DEBUG(absl::StrCat("cannot parse peer node metadata ",
                           metadata.DebugString(), ": ", status.ToString()));
    return cache_[""];
  }

  return cache_[peer_id];
}

#ifdef NULL_PLUGIN
NullPluginRootRegistry* context_registry_{};

class StatsFactory : public NullVmPluginFactory {
 public:
  const std::string name() const override { return "envoy.wasm.stats"; }

  std::unique_ptr<NullVmPlugin> create() const override {
    return std::make_unique<NullPlugin>(context_registry_);
  }
};

static Registry::RegisterFactory<StatsFactory, NullVmPluginFactory> register_;
#endif

}  // namespace Stats

#ifdef NULL_PLUGIN
// WASM_EPILOG
}  // namespace Plugin
}  // namespace Null
}  // namespace Wasm
}  // namespace Common
}  // namespace Extensions
}  // namespace Envoy
#endif<commit_msg>remove config time build metric (#2473)<commit_after>/* Copyright 2019 Istio Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "extensions/stats/plugin.h"

// WASM_PROLOG
#ifndef NULL_PLUGIN
#include "proxy_wasm_intrinsics.h"

#else  // NULL_PLUGIN

#include "extensions/common/wasm/null/null.h"

namespace Envoy {
namespace Extensions {
namespace Common {
namespace Wasm {
namespace Null {
namespace Plugin {

#endif  // NULL_PLUGIN

// END WASM_PROLOG

namespace Stats {

bool PluginRootContext::onConfigure(std::unique_ptr<WasmData> configuration) {
  // Parse configuration JSON string.
  JsonParseOptions json_options;
  Status status =
      JsonStringToMessage(configuration->toString(), &config_, json_options);
  if (status != Status::OK) {
    LOG_WARN(absl::StrCat("Cannot parse plugin configuration JSON string ",
                          configuration->toString()));
    return false;
  }

  status = ::Wasm::Common::extractLocalNodeMetadata(&local_node_info_);
  if (status != Status::OK) {
    LOG_WARN("cannot parse local node metadata ");
    return false;
  }
  int64_t direction;
  if (getValue({"listener_direction"}, &direction)) {
    outbound_ = envoy::api::v2::core::TrafficDirection::OUTBOUND == direction;
  } else {
    LOG_WARN("Unable to get plugin direction");
  }
  // Local data does not change, so populate it on config load.
  istio_dimensions_.init(outbound_, local_node_info_);

  if (outbound_) {
    peer_metadata_id_key_ = ::Wasm::Common::kUpstreamMetadataIdKey;
    peer_metadata_key_ = ::Wasm::Common::kUpstreamMetadataKey;
  } else {
    peer_metadata_id_key_ = ::Wasm::Common::kDownstreamMetadataIdKey;
    peer_metadata_key_ = ::Wasm::Common::kDownstreamMetadataKey;
  }
  debug_ = config_.debug();
  node_info_cache_.set_max_cache_size(config_.max_peer_cache_size());

  auto field_separator = CONFIG_DEFAULT(field_separator);
  auto value_separator = CONFIG_DEFAULT(value_separator);
  auto stat_prefix = CONFIG_DEFAULT(stat_prefix);

  // prepend "_" to opt out of automatic namespacing
  // If "_" is not prepended, envoy_ is automatically added by prometheus
  // scraper"
  stat_prefix = absl::StrCat("_", stat_prefix, "_");

  stats_ = std::vector<StatGen>{
      StatGen(
          absl::StrCat(stat_prefix, "requests_total"), MetricType::Counter,
          [](const ::Wasm::Common::RequestInfo&) -> uint64_t { return 1; },
          field_separator, value_separator),
      StatGen(
          absl::StrCat(stat_prefix, "request_duration_milliseconds"),
          MetricType::Histogram,
          [](const ::Wasm::Common::RequestInfo& request_info) -> uint64_t {
            return (request_info.end_timestamp - request_info.start_timestamp) /
                   1000000;
          },
          field_separator, value_separator),
      StatGen(
          absl::StrCat(stat_prefix, "request_bytes"), MetricType::Histogram,
          [](const ::Wasm::Common::RequestInfo& request_info) -> uint64_t {
            return request_info.request_size;
          },
          field_separator, value_separator),
      StatGen(
          absl::StrCat(stat_prefix, "response_bytes"), MetricType::Histogram,
          [](const ::Wasm::Common::RequestInfo& request_info) -> uint64_t {
            return request_info.response_size;
          },
          field_separator, value_separator)};
  return true;
}

void PluginRootContext::report(
    const ::Wasm::Common::RequestInfo& request_info) {
  const auto& peer_node =
      node_info_cache_.getPeerById(peer_metadata_id_key_, peer_metadata_key_);

  // map and overwrite previous mapping.
  istio_dimensions_.map(peer_node, request_info);

  auto stats_it = metrics_.find(istio_dimensions_);
  if (stats_it != metrics_.end()) {
    for (auto& stat : stats_it->second) {
      stat.record(request_info);
      LOG_DEBUG(absl::StrCat(
          "metricKey cache hit ", istio_dimensions_.debug_key(),
          ", stat=", stat.metric_id_, stats_it->first.to_string()));
    }
    cache_hits_accumulator_++;
    if (cache_hits_accumulator_ == 100) {
      incrementMetric(cache_hits_, cache_hits_accumulator_);
      cache_hits_accumulator_ = 0;
    }
    return;
  }

  // fetch dimensions in the required form for resolve.
  auto values = istio_dimensions_.values();

  std::vector<SimpleStat> stats;
  for (auto& statgen : stats_) {
    auto stat = statgen.resolve(values);
    LOG_DEBUG(absl::StrCat("metricKey cache miss ", statgen.name(), " ",
                           istio_dimensions_.debug_key(),
                           ", stat=", stat.metric_id_));
    stat.record(request_info);
    stats.push_back(stat);
  }

  incrementMetric(cache_misses_, 1);
  // TODO: When we have c++17, convert to try_emplace.
  metrics_.emplace(istio_dimensions_, stats);
}

const wasm::common::NodeInfo& NodeInfoCache::getPeerById(
    StringView peer_metadata_id_key, StringView peer_metadata_key) {
  std::string peer_id;
  if (!getStringValue({"filter_state", peer_metadata_id_key}, &peer_id)) {
    LOG_DEBUG(absl::StrCat("cannot get metadata for: ", peer_metadata_id_key));
    return cache_[""];
  }
  auto nodeinfo_it = cache_.find(peer_id);
  if (nodeinfo_it != cache_.end()) {
    return nodeinfo_it->second;
  }

  // Do not let the cache grow beyond max_cache_size_.
  if (cache_.size() > max_cache_size_) {
    auto it = cache_.begin();
    cache_.erase(cache_.begin(), std::next(it, max_cache_size_ / 4));
    LOG_INFO(absl::StrCat("cleaned cache, new cache_size:", cache_.size()));
  }

  google::protobuf::Struct metadata;
  if (!getStructValue({"filter_state", peer_metadata_key}, &metadata)) {
    LOG_DEBUG(absl::StrCat("cannot get metadata for: ", peer_metadata_key));
    return cache_[""];
  }

  auto status =
      ::Wasm::Common::extractNodeMetadata(metadata, &(cache_[peer_id]));
  if (status != Status::OK) {
    LOG_DEBUG(absl::StrCat("cannot parse peer node metadata ",
                           metadata.DebugString(), ": ", status.ToString()));
    return cache_[""];
  }

  return cache_[peer_id];
}

#ifdef NULL_PLUGIN
NullPluginRootRegistry* context_registry_{};

class StatsFactory : public NullVmPluginFactory {
 public:
  const std::string name() const override { return "envoy.wasm.stats"; }

  std::unique_ptr<NullVmPlugin> create() const override {
    return std::make_unique<NullPlugin>(context_registry_);
  }
};

static Registry::RegisterFactory<StatsFactory, NullVmPluginFactory> register_;
#endif

}  // namespace Stats

#ifdef NULL_PLUGIN
// WASM_EPILOG
}  // namespace Plugin
}  // namespace Null
}  // namespace Wasm
}  // namespace Common
}  // namespace Extensions
}  // namespace Envoy
#endif
<|endoftext|>


<commit_before>#include <jsonp.h>

namespace jsonp {

static const char *error_message[] = {
	"no error",
	"ascii zero in source",
	"invalid utf8 in source",
	"unrecognized token",
	"bad literal",
	"unescaped control char in string",
	"unterminated string (at eof)",
	"invalid escape char",
	"invalide unicode escape",
	"unicode escape yields zero",
	"unicode escape yields surrogate",
	"invalid number format",
	"number too long",
};

Location::Location(size_t offs_, size_t character_, size_t line_)
:
	offs(offs_),
	character(character_),
	line(line_)
{ }

Error::Error(Type type_, Location location_)
:
	std::runtime_error(error_message[type_]),
	type(type_),
	location(location_)
{ }

}
<commit_msg>Error: add missing source license<commit_after>/*
   Copyright (c) 2015, Andreas Fett. All rights reserved.
   Use of this source code is governed by a BSD-style
   license that can be found in the LICENSE file.
*/
#include <jsonp.h>

namespace jsonp {

static const char *error_message[] = {
	"no error",
	"ascii zero in source",
	"invalid utf8 in source",
	"unrecognized token",
	"bad literal",
	"unescaped control char in string",
	"unterminated string (at eof)",
	"invalid escape char",
	"invalide unicode escape",
	"unicode escape yields zero",
	"unicode escape yields surrogate",
	"invalid number format",
	"number too long",
};

Location::Location(size_t offs_, size_t character_, size_t line_)
:
	offs(offs_),
	character(character_),
	line(line_)
{ }

Error::Error(Type type_, Location location_)
:
	std::runtime_error(error_message[type_]),
	type(type_),
	location(location_)
{ }

}
<|endoftext|>


<commit_before>#include "qaesencryption.h"
#include <QDebug>

#define Multiply(x, y)                                \
      (  ((y & 1) * x) ^                              \
      ((y>>1 & 1) * xTime(x)) ^                       \
      ((y>>2 & 1) * xTime(xTime(x))) ^                \
      ((y>>3 & 1) * xTime(xTime(xTime(x)))) ^         \
      ((y>>4 & 1) * xTime(xTime(xTime(xTime(x))))))   \

QAESEncryption::QAESEncryption(QAESEncryption::AES level, QAESEncryption::MODE mode) : m_level(level), m_mode(mode)
{
    m_state = NULL;

    switch (level)
    {
    case AES_128: {
        AES128 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES128";
        }
        break;
    case AES_192: {
        AES192 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES192";
        }
        break;
    case AES_256: {
        AES256 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES256";
        }
        break;
    default: {
        AES128 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "Defaulting to AES128";
        }
        break;
    }

}

QByteArray QAESEncryption::expandKey(const QByteArray key)
{
  int i, k;
  quint8 tempa[4]; // Used for the column/row operations
  QByteArray roundKey(key);
  qDebug() << "Key expansion before" << roundKey.size();

  // The first round key is the key itself.
  // ...

  // All other round keys are found from the previous round keys.
  //i == Nk
  for(i = m_nk; i < m_nb * (m_nr + 1); i++)
  {
    {
      tempa[0] = (quint8) roundKey.at((i-1) * 4 + 0);
      tempa[1] = (quint8) roundKey.at((i-1) * 4 + 1);
      tempa[2] = (quint8) roundKey.at((i-1) * 4 + 2);
      tempa[3] = (quint8) roundKey.at((i-1) * 4 + 3);
    }

    if (i % m_nk == 0)
    {
      // This function shifts the 4 bytes in a word to the left once.
      // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]

      // Function RotWord()
      {
        k = tempa[0];
        tempa[0] = tempa[1];
        tempa[1] = tempa[2];
        tempa[2] = tempa[3];
        tempa[3] = k;
      }

      // SubWord() is a function that takes a four-byte input word and
      // applies the S-box to each of the four bytes to produce an output word.

      // Function Subword()
      {
        tempa[0] = getSBoxValue(tempa[0]);
        tempa[1] = getSBoxValue(tempa[1]);
        tempa[2] = getSBoxValue(tempa[2]);
        tempa[3] = getSBoxValue(tempa[3]);
      }

      tempa[0] =  tempa[0] ^ Rcon[i/m_nk];
    }
    if (m_level == AES_256 && i % m_nk == 4)
    {
      // Function Subword()
      {
        qDebug() << "AES_256";
        tempa[0] = getSBoxValue(tempa[0]);
        tempa[1] = getSBoxValue(tempa[1]);
        tempa[2] = getSBoxValue(tempa[2]);
        tempa[3] = getSBoxValue(tempa[3]);
      }
    }
    roundKey.insert(i * 4 + 0, roundKey.at((i - m_nk) * 4 + 0) ^ tempa[0]);
    roundKey.insert(i * 4 + 1, roundKey.at((i - m_nk) * 4 + 1) ^ tempa[1]);
    roundKey.insert(i * 4 + 2, roundKey.at((i - m_nk) * 4 + 2) ^ tempa[2]);
    roundKey.insert(i * 4 + 3, roundKey.at((i - m_nk) * 4 + 3) ^ tempa[3]);
  }

  //qDebug() << print(roundKey);
  return roundKey;
}

// This function adds the round key to state.
// The round key is added to the state by an XOR function.
void QAESEncryption::addRoundKey(quint8 round, const QByteArray expKey)
{
  QByteArray::iterator it = m_state->begin();
  for(int i=0; i < 16; i++)
      it[i] = (quint8)it[i] ^ (quint8)expKey.at(round * m_nb * 4 + (i/4) * m_nb + (i%4));
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void QAESEncryption::subBytes()
{
  QByteArray::iterator it = m_state->begin();
  for(int i = 0; i < 16; i++)
    it[i] = getSBoxValue((quint8) it[i]);
}

// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
void QAESEncryption::shiftRows()
{
    QByteArray::iterator it = m_state->begin();
    quint8 temp;

     //Shift 1 to left
    temp = (quint8) it[4];
    it[4] = it[4+1];
    it[4+1] = it[4+2];
    it[4+2] = it[4+3];
    it[4+3] = temp;

    //Shift 2 to left
    temp = (quint8) it[8];
    it[8] = it[8+2];
    it[8+2] = temp;
    temp = it[8+1];
    it[8+1] = it[8+3];
    it[8+3] = temp;

    //Shift 3 to left
    temp = (quint8) it[12];
    it[12] = it[12+3];
    it[12+3] = it[12+2];
    it[12+2] = it[12+1];
    it[12+1] = temp;
}

// MixColumns function mixes the columns of the state matrix
//optimized!!
void QAESEncryption::mixColumns()
{
  QByteArray::iterator it = m_state->begin();
  quint8 Tmp,Tm,t;
  for(int i = 0; i < 16; i+=4)
  {
    t   = (quint8) it[i];
    Tmp = (quint8) it[i] ^ (quint8) it[i+1] ^ (quint8) it[i+2] ^ (quint8) it[i+3] ;

    Tm  = (quint8) it[i] ^ (quint8) it[i+1];
    Tm = xTime(Tm);
    it[i] = (quint8) it[i] ^ Tm ^ Tmp;

    Tm  = (quint8) it[i+1] ^ (quint8) it[i+2];
    Tm = xTime(Tm);
    it[i+1] = (quint8) it[i+1] ^ Tm ^ Tmp;

    Tm  = (quint8) it[i+2] ^ (quint8) it[i+3];
    Tm = xTime(Tm);
    it[i+2] = (quint8) it[i+2] ^ Tm ^ Tmp;

    Tm  = (quint8) it[i+3] ^ t;
    Tm = xTime(Tm);
    it[i+3] = (quint8)  it[i+3] ^ Tm ^ Tmp;
  }
}

// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
void QAESEncryption::invMixColumns()
{
  QByteArray::iterator it = m_state->begin();
  quint8 a,b,c,d;
  for(int i = 0; i < 16; i+=4)
  {
    a = (quint8) it[i];
    b = (quint8) it[i+1];
    c = (quint8) it[i+2];
    d = (quint8) it[i+3];

    it[i]   = (quint8) (Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09));
    it[i+1] = (quint8) (Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d));
    it[i+2] = (quint8) (Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b));
    it[i+3] = (quint8) (Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e));
  }
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void QAESEncryption::invSubBytes()
{
    QByteArray::iterator it = m_state->begin();
    for(int i = 0; i < 16; ++i)
        it[i] = getSBoxInvert(it[i]);
}

void QAESEncryption::invShiftRows()
{
    QByteArray::iterator it = m_state->begin();
    uint8_t temp;

    //Shift 1 to right
    temp = (quint8) it[4+3];
    it[4+3] = it[4+2];
    it[4+2] = it[4+1];
    it[4+1] = it[4];
    it[4] = temp;

    //Shift 2
    temp = (quint8) it[8+2];
    it[8+2] = it[8];
    it[8] = temp;
    temp = (quint8) it[8+3];
    it[8+3] = it[8+1];
    it[8+1] = temp;

    //Shift 3
    temp = (quint8) it[12+3];
    it[12+3] = it[12];
    it[12] = it[12+1];
    it[12+1] = it[12+2];
    it[12+2] = temp;
}

// Cipher is the main function that encrypts the PlainText.
QByteArray QAESEncryption::cipher(const QByteArray expKey, const QByteArray in)
{

  //m_state is the input buffer.... handle it!
  QByteArray output(in);
  m_state = &output;

  quint8 round = 0;

  // Add the First round key to the state before starting the rounds.
  addRoundKey(0, expKey);

  //qDebug() << print(output);
  // There will be Nr rounds.
  // The first Nr-1 rounds are identical.
  // These Nr-1 rounds are executed in the loop below.
  for(round = 1; round < m_nr; ++round)
  {
    subBytes();
    shiftRows();
    mixColumns();
    addRoundKey(round, expKey);
  }

  // The last round is given below.
  // The MixColumns function is not here in the last round.
  subBytes();
  shiftRows();
  addRoundKey(m_nr, expKey);

  return output;
}

QByteArray QAESEncryption::invCipher(const QByteArray expKey, const QByteArray in)
{
    //m_state is the input buffer.... handle it!
    QByteArray output(in);
    m_state = &output;
    uint8_t round = 0;

    // Add the First round key to the state before starting the rounds.
    addRoundKey(m_nr, expKey);

    // There will be Nr rounds.
    // The first Nr-1 rounds are identical.
    // These Nr-1 rounds are executed in the loop below.
    for(round=m_nr-1;round>0;round--)
    {
        invShiftRows();
        invSubBytes();
        addRoundKey(round, expKey);
        invMixColumns();
    }

    // The last round is given below.
    // The MixColumns function is not here in the last round.
    invShiftRows();
    invSubBytes();
    addRoundKey(0, expKey);

    return output;
}

QByteArray QAESEncryption::encode(const QByteArray rawText, const QByteArray key, const QByteArray iv)
{
   if (m_mode == CBC && iv.isNull())
       return QByteArray();

  //qDebug() << "key" << print(key);
  QByteArray expandedKey = expandKey(key);

  // The next function call encrypts the PlainText with the Key using AES algorithm.
  return cipher(expandedKey, rawText);
}

QString QAESEncryption::print(QByteArray in)
{
    QString ret="";
    for (int i=0; i < in.size();i++)
        ret.append(QString("0x%1 ").arg(QString::number((quint8)in.at(i), 16)));
    return ret;
}

QByteArray QAESEncryption::decode(const QByteArray rawText, const QByteArray key, const QByteArray iv)
{
   if (m_mode == CBC && iv.isNull())
       return QByteArray();

  QByteArray expandedKey = expandKey(key);

  return invCipher(expandedKey, rawText);
}
<commit_msg>cleaning<commit_after>#include "qaesencryption.h"
#include <QDebug>

#define Multiply(x, y)                                \
      (  ((y & 1) * x) ^                              \
      ((y>>1 & 1) * xTime(x)) ^                       \
      ((y>>2 & 1) * xTime(xTime(x))) ^                \
      ((y>>3 & 1) * xTime(xTime(xTime(x)))) ^         \
      ((y>>4 & 1) * xTime(xTime(xTime(xTime(x))))))   \

QAESEncryption::QAESEncryption(QAESEncryption::AES level, QAESEncryption::MODE mode) : m_level(level), m_mode(mode)
{
    m_state = NULL;

    switch (level)
    {
    case AES_128: {
        AES128 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES128";
        }
        break;
    case AES_192: {
        AES192 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES192";
        }
        break;
    case AES_256: {
        AES256 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES256";
        }
        break;
    default: {
        AES128 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "Defaulting to AES128";
        }
        break;
    }

}

QByteArray QAESEncryption::expandKey(const QByteArray key)
{
  int i, k;
  quint8 tempa[4]; // Used for the column/row operations
  QByteArray roundKey(key);
  qDebug() << "Key expansion before" << roundKey.size();

  // The first round key is the key itself.
  // ...

  // All other round keys are found from the previous round keys.
  //i == Nk
  for(i = m_nk; i < m_nb * (m_nr + 1); i++)
  {
    {
      tempa[0] = (quint8) roundKey.at((i-1) * 4 + 0);
      tempa[1] = (quint8) roundKey.at((i-1) * 4 + 1);
      tempa[2] = (quint8) roundKey.at((i-1) * 4 + 2);
      tempa[3] = (quint8) roundKey.at((i-1) * 4 + 3);
    }

    if (i % m_nk == 0)
    {
      // This function shifts the 4 bytes in a word to the left once.
      // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]

      // Function RotWord()
      {
        k = tempa[0];
        tempa[0] = tempa[1];
        tempa[1] = tempa[2];
        tempa[2] = tempa[3];
        tempa[3] = k;
      }

      // SubWord() is a function that takes a four-byte input word and
      // applies the S-box to each of the four bytes to produce an output word.

      // Function Subword()
      {
        tempa[0] = getSBoxValue(tempa[0]);
        tempa[1] = getSBoxValue(tempa[1]);
        tempa[2] = getSBoxValue(tempa[2]);
        tempa[3] = getSBoxValue(tempa[3]);
      }

      tempa[0] =  tempa[0] ^ Rcon[i/m_nk];
    }
    if (m_level == AES_256 && i % m_nk == 4)
    {
      // Function Subword()
      {
        qDebug() << "AES_256";
        tempa[0] = getSBoxValue(tempa[0]);
        tempa[1] = getSBoxValue(tempa[1]);
        tempa[2] = getSBoxValue(tempa[2]);
        tempa[3] = getSBoxValue(tempa[3]);
      }
    }
    roundKey.insert(i * 4 + 0, roundKey.at((i - m_nk) * 4 + 0) ^ tempa[0]);
    roundKey.insert(i * 4 + 1, roundKey.at((i - m_nk) * 4 + 1) ^ tempa[1]);
    roundKey.insert(i * 4 + 2, roundKey.at((i - m_nk) * 4 + 2) ^ tempa[2]);
    roundKey.insert(i * 4 + 3, roundKey.at((i - m_nk) * 4 + 3) ^ tempa[3]);
  }

  //qDebug() << print(roundKey);
  return roundKey;
}

// This function adds the round key to state.
// The round key is added to the state by an XOR function.
void QAESEncryption::addRoundKey(quint8 round, const QByteArray expKey)
{
  QByteArray::iterator it = m_state->begin();
  for(int i=0; i < 16; i++)
      it[i] = (quint8)it[i] ^ (quint8)expKey.at(round * m_nb * 4 + (i/4) * m_nb + (i%4));
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void QAESEncryption::subBytes()
{
  QByteArray::iterator it = m_state->begin();
  for(int i = 0; i < 16; i++)
    it[i] = getSBoxValue((quint8) it[i]);
}

// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
void QAESEncryption::shiftRows()
{
    QByteArray::iterator it = m_state->begin();
    quint8 temp;

     //Shift 1 to left
    temp = (quint8) it[4];
    it[4] = it[4+1];
    it[4+1] = it[4+2];
    it[4+2] = it[4+3];
    it[4+3] = temp;

    //Shift 2 to left
    temp = (quint8) it[8];
    it[8] = it[8+2];
    it[8+2] = temp;
    temp = it[8+1];
    it[8+1] = it[8+3];
    it[8+3] = temp;

    //Shift 3 to left
    temp = (quint8) it[12];
    it[12] = it[12+3];
    it[12+3] = it[12+2];
    it[12+2] = it[12+1];
    it[12+1] = temp;
}

// MixColumns function mixes the columns of the state matrix
//optimized!!
void QAESEncryption::mixColumns()
{
  QByteArray::iterator it = m_state->begin();
  quint8 tmp,t;

  for(int i = 0; i < 16; i += 4)
  {
    t   = it[i];
    tmp =  it[i] ^ it[i+1] ^ it[i+2] ^ it[i+3] ;

    Tm = xTime( it[i] ^ it[i+1] );
    it[i] ^= Tm ^ tmp;

    Tm = xTime( it[i+1] ^ it[i+2]);
    it[i+1] ^= Tm ^ tmp;

    Tm = xTime( it[i+2] ^ it[i+3]);
    it[i+2] ^= Tm ^ tmp;

    Tm = xTime(it[i+3] ^ t);
    it[i+3] ^= Tm ^ tmp;
  }
}

// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
void QAESEncryption::invMixColumns()
{
  QByteArray::iterator it = m_state->begin();
  quint8 a,b,c,d;
  for(int i = 0; i < 16; i+=4)
  {
    a = (quint8) it[i];
    b = (quint8) it[i+1];
    c = (quint8) it[i+2];
    d = (quint8) it[i+3];

    it[i]   = (quint8) (Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09));
    it[i+1] = (quint8) (Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d));
    it[i+2] = (quint8) (Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b));
    it[i+3] = (quint8) (Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e));
  }
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void QAESEncryption::invSubBytes()
{
    QByteArray::iterator it = m_state->begin();
    for(int i = 0; i < 16; ++i)
        it[i] = getSBoxInvert(it[i]);
}

void QAESEncryption::invShiftRows()
{
    QByteArray::iterator it = m_state->begin();
    uint8_t temp;

    //Shift 1 to right
    temp = (quint8) it[4+3];
    it[4+3] = it[4+2];
    it[4+2] = it[4+1];
    it[4+1] = it[4];
    it[4] = temp;

    //Shift 2
    temp = (quint8) it[8+2];
    it[8+2] = it[8];
    it[8] = temp;
    temp = (quint8) it[8+3];
    it[8+3] = it[8+1];
    it[8+1] = temp;

    //Shift 3
    temp = (quint8) it[12+3];
    it[12+3] = it[12];
    it[12] = it[12+1];
    it[12+1] = it[12+2];
    it[12+2] = temp;
}

// Cipher is the main function that encrypts the PlainText.
QByteArray QAESEncryption::cipher(const QByteArray expKey, const QByteArray in)
{

  //m_state is the input buffer.... handle it!
  QByteArray output(in);
  m_state = &output;

  quint8 round = 0;

  // Add the First round key to the state before starting the rounds.
  addRoundKey(0, expKey);

  //qDebug() << print(output);
  // There will be Nr rounds.
  // The first Nr-1 rounds are identical.
  // These Nr-1 rounds are executed in the loop below.
  for(round = 1; round < m_nr; ++round)
  {
    subBytes();
    shiftRows();
    mixColumns();
    addRoundKey(round, expKey);
  }

  // The last round is given below.
  // The MixColumns function is not here in the last round.
  subBytes();
  shiftRows();
  addRoundKey(m_nr, expKey);

  return output;
}

QByteArray QAESEncryption::invCipher(const QByteArray expKey, const QByteArray in)
{
    //m_state is the input buffer.... handle it!
    QByteArray output(in);
    m_state = &output;
    uint8_t round = 0;

    // Add the First round key to the state before starting the rounds.
    addRoundKey(m_nr, expKey);

    // There will be Nr rounds.
    // The first Nr-1 rounds are identical.
    // These Nr-1 rounds are executed in the loop below.
    for(round=m_nr-1;round>0;round--)
    {
        invShiftRows();
        invSubBytes();
        addRoundKey(round, expKey);
        invMixColumns();
    }

    // The last round is given below.
    // The MixColumns function is not here in the last round.
    invShiftRows();
    invSubBytes();
    addRoundKey(0, expKey);

    return output;
}

QByteArray QAESEncryption::encode(const QByteArray rawText, const QByteArray key, const QByteArray iv)
{
   if (m_mode == CBC && iv.isNull())
       return QByteArray();

  //qDebug() << "key" << print(key);
  QByteArray expandedKey = expandKey(key);

  // The next function call encrypts the PlainText with the Key using AES algorithm.
  return cipher(expandedKey, rawText);
}

QString QAESEncryption::print(QByteArray in)
{
    QString ret="";
    for (int i=0; i < in.size();i++)
        ret.append(QString("0x%1 ").arg(QString::number((quint8)in.at(i), 16)));
    return ret;
}

QByteArray QAESEncryption::decode(const QByteArray rawText, const QByteArray key, const QByteArray iv)
{
   if (m_mode == CBC && iv.isNull())
       return QByteArray();

  QByteArray expandedKey = expandKey(key);

  return invCipher(expandedKey, rawText);
}
<|endoftext|>