<commit_before>#include "stdafx.h"
#include <byte_buffer.h>
#include "tcp_connection.h"
#include "common_def.h"
#include "packet.h"

TcpConnection::TcpConnection(IOService& io_service)
    : _io_service(io_service),
    _strand(io_service.service()),
    _socket(io_service.service())
{
}

TcpConnection::~TcpConnection()
{
    if (isOpen())
        _socket.close();

    std::cout << "connection destroyed." << std::endl;
}

void TcpConnection::write(const byte* data, size_t size)
{
    if (!data)
    {
        std::cout << "empty data." << std::endl;
        return;
    }

    boost::asio::async_write(
        _socket,
        boost::asio::buffer(data, size),
        _strand.wrap(
            boost::bind(
                &TcpConnection::handleWrite,
                shared_from_this(),
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred
            )
        )
    );
}

void TcpConnection::read()
{
    _socket.async_read_some(
        boost::asio::buffer(_recvBuffer),
        _strand.wrap(
            boost::bind(
                &TcpConnection::handleRead,
                shared_from_this(),
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred
            )
        )
    );
}

void TcpConnection::shutdown()
{
    _socket.shutdown(boost::asio::socket_base::shutdown_both);
}

tcp::socket& TcpConnection::socket()
{
    return _socket;
}

bool TcpConnection::isOpen()
{
    return _socket.is_open();
}

void TcpConnection::setWriteCompletedCallback(const WriteCompletedCallback& cb)
{
    _writeCompletedCallback = cb;
}

void TcpConnection::setReadCompletedCallback(const ReadCompletedCallback& cb)
{
    _readComplectedCallback = cb;
}

void TcpConnection::setConnectionClosedCallback(const ConnectionClosedCallback& cb)
{
    _connectionClosedCallback = cb;
}

void TcpConnection::handleWrite(
    const boost::system::error_code& error, // Result of operation.
    std::size_t bytes_transferred           // Number of bytes sent.
)
{
    if (error)
    {
        onError(error);
    }
    else
    {
        std::cout << "bytes_transferred = " << bytes_transferred << std::endl;
        if (_writeCompletedCallback)
        {
            _writeCompletedCallback(shared_from_this(), bytes_transferred);
        }
        else
        {
            std::cout << "write complected." << std::endl;
        }
    }
}

void TcpConnection::handleRead(const boost::system::error_code& error, std::size_t bytes_transferred)
{
    if (error)
        return onError(error);

    if (bytes_transferred == 0)
    {
        std::cout << "oops, connection lost :(" << std::endl;
        return;
    }

    this->read();
    ByteBufferPtr read_buffer(new ByteBuffer(_recvBuffer.data(), bytes_transferred));
    if (append_buffer_fragment(read_buffer))
    {
        if (_integrity_packet != NULL)
        {
            uint32_t opcode = _integrity_packet->opcode;
            google::protobuf::Message* message = _integrity_packet->message;

            if (message != NULL && _readComplectedCallback)
            {
                _readComplectedCallback(shared_from_this(), opcode, *message, bytes_transferred);
            }
            else
            {
                std::cout << "fatal : NULL proto message!" << std::endl;
            }
        }
        else
        {
            std::cout << "fatal : NULL Packet!" << std::endl;
        }
    }
}

void TcpConnection::onError(const boost::system::error_code& error)
{
    std::cout << "An error occured, code = " << error.value() << ", message = " << error.message() << std::endl;

    shutdown();
    switch (error.value())
    {
        case boost::asio::error::bad_descriptor:
        case boost::asio::error::eof:
        case boost::asio::error::operation_aborted:
        case boost::asio::error::connection_reset:
        {
            if (_connectionClosedCallback)
            {
                _connectionClosedCallback(shared_from_this());
            }
            break;
        }
    }
}

bool TcpConnection::append_buffer_fragment(const ByteBufferPtr& buffer)
{
    if (_state == S_IDLE && buffer->size() < ServerPacket::MIN_HEADER_LENGTH)
    {
        _buffer.append(*buffer);
        _state = S_PROCESSING;
        return false;
    }
    else
    {
        _buffer.append(*buffer);
    }

    //黺Ƿpacketֽ
    if (_buffer.size() < sizeof(ServerPacket))
    {
        std::cout
            << "buffer size not enough the minimum bytesize of ServerPacket("
            << sizeof(ServerPacket) << " bytes, buffer size = " << _buffer.size() << ")." << std::endl;

        return false;
    }

    size_t packet_len = 0;
    _buffer >> packet_len;

    if (packet_len >= MAX_RECV_LEN)
    {
        std::cout << "Warning: Read packet header length " << packet_len << " bytes (which is too large) on peer socket. (Invalid Packet?)" << std::endl;
        reset();
        shutdown();
        return false;
    }

    if (_buffer.size() < packet_len)
    {
        //յСڰͷָȣ
        return false;
    }
    else if (_buffer.size() == packet_len)
    {
        _integrity_packet = (ServerPacket*)(reinterpret_cast<const ServerPacket*>(_buffer.buffer()));
        reset();
        return true;
    }
    else
    {
        std::cout << "invalid packet" << std::endl;
        return false;
    }
}
<commit_msg>* 去掉错误的打印信息<commit_after>#include "stdafx.h"
#include <byte_buffer.h>
#include "tcp_connection.h"
#include "common_def.h"
#include "packet.h"

TcpConnection::TcpConnection(IOService& io_service)
    : _io_service(io_service),
    _strand(io_service.service()),
    _socket(io_service.service())
{
}

TcpConnection::~TcpConnection()
{
    if (isOpen())
        _socket.close();

    std::cout << "connection destroyed." << std::endl;
}

void TcpConnection::write(const byte* data, size_t size)
{
    if (!data)
    {
        std::cout << "empty data." << std::endl;
        return;
    }

    boost::asio::async_write(
        _socket,
        boost::asio::buffer(data, size),
        _strand.wrap(
            boost::bind(
                &TcpConnection::handleWrite,
                shared_from_this(),
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred
            )
        )
    );
}

void TcpConnection::read()
{
    _socket.async_read_some(
        boost::asio::buffer(_recvBuffer),
        _strand.wrap(
            boost::bind(
                &TcpConnection::handleRead,
                shared_from_this(),
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred
            )
        )
    );
}

void TcpConnection::shutdown()
{
    _socket.shutdown(boost::asio::socket_base::shutdown_both);
}

tcp::socket& TcpConnection::socket()
{
    return _socket;
}

bool TcpConnection::isOpen()
{
    return _socket.is_open();
}

void TcpConnection::setWriteCompletedCallback(const WriteCompletedCallback& cb)
{
    _writeCompletedCallback = cb;
}

void TcpConnection::setReadCompletedCallback(const ReadCompletedCallback& cb)
{
    _readComplectedCallback = cb;
}

void TcpConnection::setConnectionClosedCallback(const ConnectionClosedCallback& cb)
{
    _connectionClosedCallback = cb;
}

void TcpConnection::handleWrite(
    const boost::system::error_code& error, // Result of operation.
    std::size_t bytes_transferred           // Number of bytes sent.
)
{
    if (error)
    {
        onError(error);
    }
    else
    {
        std::cout << "bytes_transferred = " << bytes_transferred << std::endl;
        if (_writeCompletedCallback)
        {
            _writeCompletedCallback(shared_from_this(), bytes_transferred);
        }
        else
        {
            std::cout << "write complected." << std::endl;
        }
    }
}

void TcpConnection::handleRead(const boost::system::error_code& error, std::size_t bytes_transferred)
{
    if (error)
        return onError(error);

    if (bytes_transferred == 0)
    {
        std::cout << "oops, connection lost :(" << std::endl;
        return;
    }

    this->read();
    ByteBufferPtr read_buffer(new ByteBuffer(_recvBuffer.data(), bytes_transferred));
    if (append_buffer_fragment(read_buffer))
    {
        if (_integrity_packet != NULL)
        {
            uint32_t opcode = _integrity_packet->opcode;
            google::protobuf::Message* message = _integrity_packet->message;

            if (message != NULL && _readComplectedCallback)
            {
                _readComplectedCallback(shared_from_this(), opcode, *message, bytes_transferred);
            }
            else
            {
                std::cout << "fatal : NULL proto message!" << std::endl;
            }
        }
        else
        {
            std::cout << "fatal : NULL Packet!" << std::endl;
        }
    }
}

void TcpConnection::onError(const boost::system::error_code& error)
{
    std::cout << "An error occured, code = " << error.value() << ", message = " << error.message() << std::endl;

    shutdown();
    switch (error.value())
    {
        case boost::asio::error::bad_descriptor:
        case boost::asio::error::eof:
        case boost::asio::error::operation_aborted:
        case boost::asio::error::connection_reset:
        {
            if (_connectionClosedCallback)
            {
                _connectionClosedCallback(shared_from_this());
            }
            break;
        }
    }
}

bool TcpConnection::append_buffer_fragment(const ByteBufferPtr& buffer)
{
    if (_state == S_IDLE && buffer->size() < ServerPacket::MIN_HEADER_LENGTH)
    {
        _buffer.append(*buffer);
        _state = S_PROCESSING;
        return false;
    }
    else
    {
        _buffer.append(*buffer);
    }

    //黺Ƿpacketֽ
    if (_buffer.size() < sizeof(ServerPacket))
    {
        std::cout
            << "buffer size not enough the minimum bytesize of ServerPacket("
            << sizeof(ServerPacket) << " bytes, buffer size = " << _buffer.size() << ")." << std::endl;

        return false;
    }

    size_t packet_len = 0;
    _buffer >> packet_len;

    if (packet_len >= MAX_RECV_LEN)
    {
        std::cout << "Warning: Read packet header length " << packet_len << " bytes (which is too large) on peer socket. (Invalid Packet?)" << std::endl;
        reset();
        shutdown();
        return false;
    }

    if (_buffer.size() < packet_len)
    {
        //յСڰͷָȣ
        return false;
    }
    else if (_buffer.size() == packet_len)
    {
        _integrity_packet = (ServerPacket*)(reinterpret_cast<const ServerPacket*>(_buffer.buffer()));
        reset();
        return true;
    }
    else
    {
        //ʣ
        return false;
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009  Barracuda Networks, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 *
 */

#include "stunallocate.h"

#include <QMetaType>
#include <QHostAddress>
#include <QtCrypto>
#include "stunmessage.h"
#include "stuntypes.h"
#include "stuntransaction.h"

Q_DECLARE_METATYPE(XMPP::StunAllocate::Error)

namespace XMPP {

class StunAllocate::Private : public QObject
{
	Q_OBJECT

public:
	StunAllocate *q;
	StunTransactionPool *pool;
	StunTransaction *trans;
	QString clientSoftware, serverSoftware;
	QHostAddress reflexiveAddress, relayedAddress;
	int reflexivePort, relayedPort;
	StunMessage msg;
	QList<QHostAddress> perms;

	Private(StunAllocate *_q) :
		QObject(_q),
		q(_q),
		pool(0),
		trans(0)
	{
		qRegisterMetaType<StunAllocate::Error>();
	}

	void start()
	{
		Q_ASSERT(!trans);

		trans = new StunTransaction(this);
		connect(trans, SIGNAL(createMessage(const QByteArray &)), SLOT(trans_createMessage(const QByteArray &)));
		connect(trans, SIGNAL(finished(const XMPP::StunMessage &)), SLOT(trans_finished(const XMPP::StunMessage &)));
		connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error)));

		trans->start(pool);
	}

	void stop()
	{
		// TODO
		QMetaObject::invokeMethod(q, "stopped", Qt::QueuedConnection);
	}

	void setPermissions(const QList<QHostAddress> &newPerms)
	{
		perms = newPerms;

		trans = new StunTransaction(this);
		connect(trans, SIGNAL(createMessage(const QByteArray &)), SLOT(trans_createMessage(const QByteArray &)));
		connect(trans, SIGNAL(finished(const XMPP::StunMessage &)), SLOT(trans_finished(const XMPP::StunMessage &)));
		connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error)));

		trans->start(pool);
	}

private slots:
	void trans_createMessage(const QByteArray &transactionId)
	{
		if(perms.isEmpty())
		{
			StunMessage message;
			message.setMethod(StunTypes::Allocate);
			message.setId((const quint8 *)transactionId.data());

			QList<StunMessage::Attribute> list;

			if(!clientSoftware.isEmpty())
			{
				StunMessage::Attribute a;
				a.type = StunTypes::SOFTWARE;
				a.value = StunTypes::createSoftware(clientSoftware);
				list += a;
			}

			{
				StunMessage::Attribute a;
				a.type = StunTypes::LIFETIME;
				a.value = StunTypes::createLifetime(3600);
				list += a;
			}

			{
				StunMessage::Attribute a;
				a.type = StunTypes::REQUESTED_TRANSPORT;
				a.value = StunTypes::createRequestedTransport(17); // 17=UDP
				list += a;
			}

			{
				StunMessage::Attribute a;
				a.type = StunTypes::DONT_FRAGMENT;
				list += a;
			}

			message.setAttributes(list);

			trans->setMessage(message);
		}
		else
		{
			StunMessage message;
			message.setMethod(StunTypes::CreatePermission);
			message.setId((const quint8 *)transactionId.data());

			QList<StunMessage::Attribute> list;

			{
				StunMessage::Attribute a;
				a.type = StunTypes::XOR_PEER_ADDRESS;
				a.value = StunTypes::createXorPeerAddress(perms.first(), 0, message.magic(), message.id());
				list += a;
			}

			message.setAttributes(list);

			trans->setMessage(message);
		}
	}

	void trans_finished(const XMPP::StunMessage &response)
	{
		//printf("trans_finished\n");
		delete trans;
		trans = 0;

		// HACK
		if(perms.isEmpty())
		{
			QHostAddress addr;
			quint16 port;

			if(StunTypes::parseXorRelayedAddress(response.attribute(StunTypes::XOR_MAPPED_ADDRESS), response.magic(), response.id(), &addr, &port))
			{
				relayedAddress = addr;
				relayedPort = port;
			}

			if(StunTypes::parseXorMappedAddress(response.attribute(StunTypes::XOR_MAPPED_ADDRESS), response.magic(), response.id(), &addr, &port))
			{
				reflexiveAddress = addr;
				reflexivePort = port;
			}

			emit q->started();
		}
		else
			emit q->permissionsChanged();

#if 0
		StunTypes::print_packet(response);

		pool->remove(trans);
		trans = 0;

		if(response.mclass() == StunMessage::ErrorResponse)
		{
			//errorString = "Server responded with an error.";
			//emit q->error(StunBinding::ErrorRejected);

			if(!msg.attribute(StunTypes::NONCE).isNull())
				return;

			QList<StunMessage::Attribute> list = msg.attributes();

			{
				StunMessage::Attribute a;
				a.type = StunTypes::REALM;
				a.value = "domain.org"; //response.attribute(StunTypes::REALM);
				list += a;
			}

			{
				StunMessage::Attribute a;
				a.type = StunTypes::NONCE;
				a.value = response.attribute(StunTypes::NONCE);
				list += a;
			}

			msg.setAttributes(list);

			trans = new StunTransaction(this);
			connect(trans, SIGNAL(finished(const XMPP::StunMessage &)), SLOT(trans_finished(const XMPP::StunMessage &)));
			connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error)));
			trans->start(pool->mode(), msg, "toto", "toto:domain.org:password");

			pool->insert(trans);

			return;
		}

		/*QHostAddress saddr;
		quint16 sport = 0;

		QByteArray val;
		val = response.attribute(0x0020);
		if(!val.isNull())
		{
			if(!parse_mapped_address(val, response.magic(), response.id(), &saddr, &sport))
			{
				errorString = "Unable to parse XOR-MAPPED-ADDRESS response.";
				emit q->error(StunBinding::ErrorProtocol);
				return;
			}
		}
		else
		{
			val = response.attribute(0x0001);
			if(!val.isNull())
			{
				if(!parse_mapped_address(val, 0, 0, &saddr, &sport))
				{
					errorString = "Unable to parse MAPPED-ADDRESS response.";
					emit q->error(StunBinding::ErrorProtocol);
					return;
				}
			}
			else
			{
				errorString = "Response does not contain XOR-MAPPED-ADDRESS or MAPPED-ADDRESS.";
				emit q->error(StunBinding::ErrorProtocol);
				return;
			}
		}

		addr = saddr;
		port = sport;
		emit q->success();*/
#endif
	}

	void trans_error(XMPP::StunTransaction::Error e)
	{
		printf("trans_error\n");
		/*pool->remove(trans);
		trans = 0;

		if(e == StunTransaction::ErrorTimeout)
		{
			errorString = "Request timed out.";
			emit q->error(StunBinding::ErrorTimeout);
		}
		else
		{
			errorString = "Generic transaction error.";
			emit q->error(StunBinding::ErrorGeneric);
		}*/
	}
};

StunAllocate::StunAllocate(StunTransactionPool *pool) :
	QObject(pool)
{
	d = new Private(this);
	d->pool = pool;
}

StunAllocate::~StunAllocate()
{
	delete d;
}

void StunAllocate::setClientSoftwareNameAndVersion(const QString &str)
{
	d->clientSoftware = str;
}

void StunAllocate::start()
{
	d->start();
}

void StunAllocate::stop()
{
	d->stop();
}

QString StunAllocate::serverSoftwareNameAndVersion() const
{
	return d->serverSoftware;
}

QHostAddress StunAllocate::reflexiveAddress() const
{
	return d->reflexiveAddress;
}

int StunAllocate::reflexivePort() const
{
	return d->reflexivePort;
}

QHostAddress StunAllocate::relayedAddress() const
{
	return d->relayedAddress;
}

int StunAllocate::relayedPort() const
{
	return d->relayedPort;
}

QList<QHostAddress> StunAllocate::permissions() const
{
	return d->perms;
}

void StunAllocate::setPermissions(const QList<QHostAddress> &perms)
{
	d->setPermissions(perms);
}

int StunAllocate::packetHeaderOverhead(const QHostAddress &addr) const
{
	// TODO
	Q_UNUSED(addr);
	return 0;
}

QByteArray StunAllocate::encode(const QByteArray &datagram, const QHostAddress &addr, int port)
{
	StunMessage message;
	message.setClass(StunMessage::Indication);
	message.setMethod(StunTypes::Send);
	QByteArray id = d->pool->generateId();
	message.setId((const quint8 *)id.data());

	QList<StunMessage::Attribute> list;

	{
		StunMessage::Attribute a;
		a.type = StunTypes::XOR_PEER_ADDRESS;
		a.value = StunTypes::createXorPeerAddress(addr, port, message.magic(), message.id());
		list += a;
	}

	{
		StunMessage::Attribute a;
		a.type = StunTypes::DATA;
		a.value = datagram;
		list += a;
	}

	message.setAttributes(list);

	QByteArray out = message.toBinary();
	//StunMessage tmp = StunMessage::fromBinary(out);
	//StunTypes::print_packet(message);
	//StunTypes::print_packet(tmp);

	return out; //return message.toBinary();
}

QByteArray StunAllocate::decode(const QByteArray &encoded, QHostAddress *addr, int *port)
{
	printf("decode raw\n");
	// TODO
	Q_UNUSED(encoded);
	Q_UNUSED(addr);
	Q_UNUSED(port);
	return QByteArray();
}

QByteArray StunAllocate::decode(const StunMessage &encoded, QHostAddress *addr, int *port)
{
	QHostAddress paddr;
	quint16 pport;

	if(!StunTypes::parseXorPeerAddress(encoded.attribute(StunTypes::XOR_PEER_ADDRESS), encoded.magic(), encoded.id(), &paddr, &pport))
		return QByteArray();

	QByteArray data = encoded.attribute(StunTypes::DATA);
	if(data.isNull())
		return QByteArray();

	*addr = paddr;
	*port = pport;
	return data;
}

QString StunAllocate::errorString() const
{
	// TODO
	return QString();
}

}

#include "stunallocate.moc"
<commit_msg>typo<commit_after>/*
 * Copyright (C) 2009  Barracuda Networks, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 *
 */

#include "stunallocate.h"

#include <QMetaType>
#include <QHostAddress>
#include <QtCrypto>
#include "stunmessage.h"
#include "stuntypes.h"
#include "stuntransaction.h"

Q_DECLARE_METATYPE(XMPP::StunAllocate::Error)

namespace XMPP {

class StunAllocate::Private : public QObject
{
	Q_OBJECT

public:
	StunAllocate *q;
	StunTransactionPool *pool;
	StunTransaction *trans;
	QString clientSoftware, serverSoftware;
	QHostAddress reflexiveAddress, relayedAddress;
	int reflexivePort, relayedPort;
	StunMessage msg;
	QList<QHostAddress> perms;

	Private(StunAllocate *_q) :
		QObject(_q),
		q(_q),
		pool(0),
		trans(0)
	{
		qRegisterMetaType<StunAllocate::Error>();
	}

	void start()
	{
		Q_ASSERT(!trans);

		trans = new StunTransaction(this);
		connect(trans, SIGNAL(createMessage(const QByteArray &)), SLOT(trans_createMessage(const QByteArray &)));
		connect(trans, SIGNAL(finished(const XMPP::StunMessage &)), SLOT(trans_finished(const XMPP::StunMessage &)));
		connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error)));

		trans->start(pool);
	}

	void stop()
	{
		// TODO
		QMetaObject::invokeMethod(q, "stopped", Qt::QueuedConnection);
	}

	void setPermissions(const QList<QHostAddress> &newPerms)
	{
		perms = newPerms;

		trans = new StunTransaction(this);
		connect(trans, SIGNAL(createMessage(const QByteArray &)), SLOT(trans_createMessage(const QByteArray &)));
		connect(trans, SIGNAL(finished(const XMPP::StunMessage &)), SLOT(trans_finished(const XMPP::StunMessage &)));
		connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error)));

		trans->start(pool);
	}

private slots:
	void trans_createMessage(const QByteArray &transactionId)
	{
		if(perms.isEmpty())
		{
			StunMessage message;
			message.setMethod(StunTypes::Allocate);
			message.setId((const quint8 *)transactionId.data());

			QList<StunMessage::Attribute> list;

			if(!clientSoftware.isEmpty())
			{
				StunMessage::Attribute a;
				a.type = StunTypes::SOFTWARE;
				a.value = StunTypes::createSoftware(clientSoftware);
				list += a;
			}

			{
				StunMessage::Attribute a;
				a.type = StunTypes::LIFETIME;
				a.value = StunTypes::createLifetime(3600);
				list += a;
			}

			{
				StunMessage::Attribute a;
				a.type = StunTypes::REQUESTED_TRANSPORT;
				a.value = StunTypes::createRequestedTransport(17); // 17=UDP
				list += a;
			}

			{
				StunMessage::Attribute a;
				a.type = StunTypes::DONT_FRAGMENT;
				list += a;
			}

			message.setAttributes(list);

			trans->setMessage(message);
		}
		else
		{
			StunMessage message;
			message.setMethod(StunTypes::CreatePermission);
			message.setId((const quint8 *)transactionId.data());

			QList<StunMessage::Attribute> list;

			{
				StunMessage::Attribute a;
				a.type = StunTypes::XOR_PEER_ADDRESS;
				a.value = StunTypes::createXorPeerAddress(perms.first(), 0, message.magic(), message.id());
				list += a;
			}

			message.setAttributes(list);

			trans->setMessage(message);
		}
	}

	void trans_finished(const XMPP::StunMessage &response)
	{
		//printf("trans_finished\n");
		delete trans;
		trans = 0;

		// HACK
		if(perms.isEmpty())
		{
			QHostAddress addr;
			quint16 port;

			if(StunTypes::parseXorRelayedAddress(response.attribute(StunTypes::XOR_RELAYED_ADDRESS), response.magic(), response.id(), &addr, &port))
			{
				relayedAddress = addr;
				relayedPort = port;
			}

			if(StunTypes::parseXorMappedAddress(response.attribute(StunTypes::XOR_MAPPED_ADDRESS), response.magic(), response.id(), &addr, &port))
			{
				reflexiveAddress = addr;
				reflexivePort = port;
			}

			emit q->started();
		}
		else
			emit q->permissionsChanged();

#if 0
		StunTypes::print_packet(response);

		pool->remove(trans);
		trans = 0;

		if(response.mclass() == StunMessage::ErrorResponse)
		{
			//errorString = "Server responded with an error.";
			//emit q->error(StunBinding::ErrorRejected);

			if(!msg.attribute(StunTypes::NONCE).isNull())
				return;

			QList<StunMessage::Attribute> list = msg.attributes();

			{
				StunMessage::Attribute a;
				a.type = StunTypes::REALM;
				a.value = "domain.org"; //response.attribute(StunTypes::REALM);
				list += a;
			}

			{
				StunMessage::Attribute a;
				a.type = StunTypes::NONCE;
				a.value = response.attribute(StunTypes::NONCE);
				list += a;
			}

			msg.setAttributes(list);

			trans = new StunTransaction(this);
			connect(trans, SIGNAL(finished(const XMPP::StunMessage &)), SLOT(trans_finished(const XMPP::StunMessage &)));
			connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error)));
			trans->start(pool->mode(), msg, "toto", "toto:domain.org:password");

			pool->insert(trans);

			return;
		}

		/*QHostAddress saddr;
		quint16 sport = 0;

		QByteArray val;
		val = response.attribute(0x0020);
		if(!val.isNull())
		{
			if(!parse_mapped_address(val, response.magic(), response.id(), &saddr, &sport))
			{
				errorString = "Unable to parse XOR-MAPPED-ADDRESS response.";
				emit q->error(StunBinding::ErrorProtocol);
				return;
			}
		}
		else
		{
			val = response.attribute(0x0001);
			if(!val.isNull())
			{
				if(!parse_mapped_address(val, 0, 0, &saddr, &sport))
				{
					errorString = "Unable to parse MAPPED-ADDRESS response.";
					emit q->error(StunBinding::ErrorProtocol);
					return;
				}
			}
			else
			{
				errorString = "Response does not contain XOR-MAPPED-ADDRESS or MAPPED-ADDRESS.";
				emit q->error(StunBinding::ErrorProtocol);
				return;
			}
		}

		addr = saddr;
		port = sport;
		emit q->success();*/
#endif
	}

	void trans_error(XMPP::StunTransaction::Error e)
	{
		printf("trans_error\n");
		/*pool->remove(trans);
		trans = 0;

		if(e == StunTransaction::ErrorTimeout)
		{
			errorString = "Request timed out.";
			emit q->error(StunBinding::ErrorTimeout);
		}
		else
		{
			errorString = "Generic transaction error.";
			emit q->error(StunBinding::ErrorGeneric);
		}*/
	}
};

StunAllocate::StunAllocate(StunTransactionPool *pool) :
	QObject(pool)
{
	d = new Private(this);
	d->pool = pool;
}

StunAllocate::~StunAllocate()
{
	delete d;
}

void StunAllocate::setClientSoftwareNameAndVersion(const QString &str)
{
	d->clientSoftware = str;
}

void StunAllocate::start()
{
	d->start();
}

void StunAllocate::stop()
{
	d->stop();
}

QString StunAllocate::serverSoftwareNameAndVersion() const
{
	return d->serverSoftware;
}

QHostAddress StunAllocate::reflexiveAddress() const
{
	return d->reflexiveAddress;
}

int StunAllocate::reflexivePort() const
{
	return d->reflexivePort;
}

QHostAddress StunAllocate::relayedAddress() const
{
	return d->relayedAddress;
}

int StunAllocate::relayedPort() const
{
	return d->relayedPort;
}

QList<QHostAddress> StunAllocate::permissions() const
{
	return d->perms;
}

void StunAllocate::setPermissions(const QList<QHostAddress> &perms)
{
	d->setPermissions(perms);
}

int StunAllocate::packetHeaderOverhead(const QHostAddress &addr) const
{
	// TODO
	Q_UNUSED(addr);
	return 0;
}

QByteArray StunAllocate::encode(const QByteArray &datagram, const QHostAddress &addr, int port)
{
	StunMessage message;
	message.setClass(StunMessage::Indication);
	message.setMethod(StunTypes::Send);
	QByteArray id = d->pool->generateId();
	message.setId((const quint8 *)id.data());

	QList<StunMessage::Attribute> list;

	{
		StunMessage::Attribute a;
		a.type = StunTypes::XOR_PEER_ADDRESS;
		a.value = StunTypes::createXorPeerAddress(addr, port, message.magic(), message.id());
		list += a;
	}

	{
		StunMessage::Attribute a;
		a.type = StunTypes::DATA;
		a.value = datagram;
		list += a;
	}

	message.setAttributes(list);

	QByteArray out = message.toBinary();
	//StunMessage tmp = StunMessage::fromBinary(out);
	//StunTypes::print_packet(message);
	//StunTypes::print_packet(tmp);

	return out; //return message.toBinary();
}

QByteArray StunAllocate::decode(const QByteArray &encoded, QHostAddress *addr, int *port)
{
	printf("decode raw\n");
	// TODO
	Q_UNUSED(encoded);
	Q_UNUSED(addr);
	Q_UNUSED(port);
	return QByteArray();
}

QByteArray StunAllocate::decode(const StunMessage &encoded, QHostAddress *addr, int *port)
{
	QHostAddress paddr;
	quint16 pport;

	if(!StunTypes::parseXorPeerAddress(encoded.attribute(StunTypes::XOR_PEER_ADDRESS), encoded.magic(), encoded.id(), &paddr, &pport))
		return QByteArray();

	QByteArray data = encoded.attribute(StunTypes::DATA);
	if(data.isNull())
		return QByteArray();

	*addr = paddr;
	*port = pport;
	return data;
}

QString StunAllocate::errorString() const
{
	// TODO
	return QString();
}

}

#include "stunallocate.moc"
<|endoftext|>


<commit_before>//*****************************************************************************
// Copyright 2017-2019 Intel Corporation
//
// 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 <sstream>

#include "ngraph/file_util.hpp"
#include "ngraph/runtime/executable.hpp"
#include "ngraph/runtime/tensor.hpp"
#include "ngraph/util.hpp"

using namespace std;
using namespace ngraph;

runtime::Executable::Executable()
{
}

runtime::Executable::~Executable()
{
}

bool runtime::Executable::call_with_validate(const vector<shared_ptr<runtime::Tensor>>& outputs,
                                             const vector<shared_ptr<runtime::Tensor>>& inputs)
{
    validate(outputs, inputs);
    return call(outputs, inputs);
}

void runtime::Executable::validate(const vector<std::shared_ptr<runtime::Tensor>>& outputs,
                                   const vector<std::shared_ptr<runtime::Tensor>>& inputs)
{
    const ParameterVector& parameters = get_parameters();
    const ResultVector& results = get_results();
    if (parameters.size() != inputs.size())
    {
        stringstream ss;
        ss << "Call input count " << inputs.size() << " does not match Function's Parameter count "
           << parameters.size();
        throw runtime_error(ss.str());
    }
    if (results.size() != outputs.size())
    {
        stringstream ss;
        ss << "Call output count " << outputs.size() << " does not match Function's Result count "
           << results.size();
        throw runtime_error(ss.str());
    }

    for (size_t i = 0; i < parameters.size(); i++)
    {
        if (parameters[i]->get_element_type().is_static() &&
            parameters[i]->get_element_type() != inputs[i]->get_element_type())
        {
            stringstream ss;
            ss << "Input " << i << " type '" << inputs[i]->get_element_type()
               << "' does not match Parameter type '" << parameters[i]->get_element_type() << "'";
            throw runtime_error(ss.str());
        }
        if (!(parameters[i]->get_output_partial_shape(0).relaxes(inputs[i]->get_partial_shape())))
        {
            stringstream ss;
            ss << "Input " << i << " shape " << inputs[i]->get_partial_shape()
               << " does not match Parameter shape " << parameters[i]->get_output_partial_shape(0);
            throw runtime_error(ss.str());
        }
    }

    for (size_t i = 0; i < results.size(); i++)
    {
        if (outputs[i]->get_element_type().is_static() &&
            results[i]->get_element_type() != outputs[i]->get_element_type())
        {
            stringstream ss;
            ss << "Output " << i << " type '" << outputs[i]->get_element_type()
               << "' does not match Result type '" << results[i]->get_element_type() << "'";
            throw runtime_error(ss.str());
        }
        if (!(outputs[i]->get_partial_shape()).relaxes(results[i]->get_output_partial_shape(0)))
        {
            stringstream ss;
            ss << "Output " << i << " shape " << outputs[i]->get_partial_shape()
               << " does not match Result shape " << results[i]->get_output_partial_shape(0);
            throw runtime_error(ss.str());
        }
    }
}

const ngraph::ParameterVector& runtime::Executable::get_parameters() const
{
    return m_parameters;
}

const ngraph::ResultVector& runtime::Executable::get_results() const
{
    return m_results;
}

void runtime::Executable::set_parameters_and_results(const Function& func)
{
    m_parameters = func.get_parameters();
    m_results = func.get_results();
}

vector<runtime::PerformanceCounter> runtime::Executable::get_performance_data() const
{
    return vector<PerformanceCounter>();
}

void runtime::Executable::save(std::ostream& output_stream)
{
    throw runtime_error("save opertion unimplemented.");
}

vector<shared_ptr<runtime::Tensor>> runtime::Executable::create_input_tensor(size_t input_number,
                                                                 size_t pipeline_depth)
{
    vector<shared_ptr<runtime::Tensor>> tensors;
    // if (m_backend)
    // {
    //     const ParameterVector& parameters = get_parameters();
    //     if (index >= parameters.size())
    //     {
    //         throw runtime_error("create_tensor for input out of bounds");
    //     }
    //     shared_ptr<op::Parameter> parameter = parameters[index];
    //     tensor = m_backend->create_tensor(
    //         parameter->get_element_type(), parameter->get_shape(), memory_pointer);
    //     tensor->m_source_node = parameter;
    // }
    // else
    // {
    //     throw runtime_error("Backend does not support Executable::create_tensor");
    // }
    return tensors;
}

vector<shared_ptr<runtime::Tensor>> runtime::Executable::create_output_tensor(size_t input_number,
                                                                  size_t pipeline_depth)
{
    vector<shared_ptr<runtime::Tensor>> tensors;
    // if (m_backend)
    // {
    //     const ResultVector& results = get_results();
    //     if (index >= results.size())
    //     {
    //         throw runtime_error("create_tensor for input out of bounds");
    //     }
    //     shared_ptr<op::Result> result = results[index];
    //     tensor = m_backend->create_tensor(
    //         result->get_element_type(), result->get_shape(), memory_pointer);
    //     tensor->m_source_node = result;
    // }
    // else
    // {
    //     throw runtime_error("Backend does not support Executable::create_tensor");
    // }
    return tensors;
}
<commit_msg>new methods throw exception if not implemented<commit_after>//*****************************************************************************
// Copyright 2017-2019 Intel Corporation
//
// 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 <sstream>

#include "ngraph/file_util.hpp"
#include "ngraph/runtime/executable.hpp"
#include "ngraph/runtime/tensor.hpp"
#include "ngraph/util.hpp"

using namespace std;
using namespace ngraph;

runtime::Executable::Executable()
{
}

runtime::Executable::~Executable()
{
}

bool runtime::Executable::call_with_validate(const vector<shared_ptr<runtime::Tensor>>& outputs,
                                             const vector<shared_ptr<runtime::Tensor>>& inputs)
{
    validate(outputs, inputs);
    return call(outputs, inputs);
}

void runtime::Executable::validate(const vector<std::shared_ptr<runtime::Tensor>>& outputs,
                                   const vector<std::shared_ptr<runtime::Tensor>>& inputs)
{
    const ParameterVector& parameters = get_parameters();
    const ResultVector& results = get_results();
    if (parameters.size() != inputs.size())
    {
        stringstream ss;
        ss << "Call input count " << inputs.size() << " does not match Function's Parameter count "
           << parameters.size();
        throw runtime_error(ss.str());
    }
    if (results.size() != outputs.size())
    {
        stringstream ss;
        ss << "Call output count " << outputs.size() << " does not match Function's Result count "
           << results.size();
        throw runtime_error(ss.str());
    }

    for (size_t i = 0; i < parameters.size(); i++)
    {
        if (parameters[i]->get_element_type().is_static() &&
            parameters[i]->get_element_type() != inputs[i]->get_element_type())
        {
            stringstream ss;
            ss << "Input " << i << " type '" << inputs[i]->get_element_type()
               << "' does not match Parameter type '" << parameters[i]->get_element_type() << "'";
            throw runtime_error(ss.str());
        }
        if (!(parameters[i]->get_output_partial_shape(0).relaxes(inputs[i]->get_partial_shape())))
        {
            stringstream ss;
            ss << "Input " << i << " shape " << inputs[i]->get_partial_shape()
               << " does not match Parameter shape " << parameters[i]->get_output_partial_shape(0);
            throw runtime_error(ss.str());
        }
    }

    for (size_t i = 0; i < results.size(); i++)
    {
        if (outputs[i]->get_element_type().is_static() &&
            results[i]->get_element_type() != outputs[i]->get_element_type())
        {
            stringstream ss;
            ss << "Output " << i << " type '" << outputs[i]->get_element_type()
               << "' does not match Result type '" << results[i]->get_element_type() << "'";
            throw runtime_error(ss.str());
        }
        if (!(outputs[i]->get_partial_shape()).relaxes(results[i]->get_output_partial_shape(0)))
        {
            stringstream ss;
            ss << "Output " << i << " shape " << outputs[i]->get_partial_shape()
               << " does not match Result shape " << results[i]->get_output_partial_shape(0);
            throw runtime_error(ss.str());
        }
    }
}

const ngraph::ParameterVector& runtime::Executable::get_parameters() const
{
    return m_parameters;
}

const ngraph::ResultVector& runtime::Executable::get_results() const
{
    return m_results;
}

void runtime::Executable::set_parameters_and_results(const Function& func)
{
    m_parameters = func.get_parameters();
    m_results = func.get_results();
}

vector<runtime::PerformanceCounter> runtime::Executable::get_performance_data() const
{
    return vector<PerformanceCounter>();
}

void runtime::Executable::save(std::ostream& output_stream)
{
    throw runtime_error("save opertion unimplemented.");
}

vector<shared_ptr<runtime::Tensor>> runtime::Executable::create_input_tensor(size_t input_number,
                                                                 size_t pipeline_depth)
{
    throw runtime_error("create_input_tensor unimplemented");
}

vector<shared_ptr<runtime::Tensor>> runtime::Executable::create_output_tensor(size_t input_number,
                                                                  size_t pipeline_depth)
{
    throw runtime_error("create_input_tensor unimplemented");
}
<|endoftext|>


<commit_before>/*
* (C) 2015,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/ffi.h>
#include <botan/internal/ffi_util.h>
#include <botan/block_cipher.h>

extern "C" {

using namespace Botan_FFI;

BOTAN_FFI_DECLARE_STRUCT(botan_block_cipher_struct, Botan::BlockCipher, 0x64C29716);

int botan_block_cipher_init(botan_block_cipher_t* bc, const char* bc_name)
   {
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() {
      if(bc == nullptr || bc_name == nullptr || *bc_name == 0)
         return BOTAN_FFI_ERROR_NULL_POINTER;

      *bc = nullptr;

      std::unique_ptr<Botan::BlockCipher> cipher(Botan::BlockCipher::create(bc_name));
      if(cipher == nullptr)
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;

      *bc = new botan_block_cipher_struct(cipher.release());
      return BOTAN_FFI_SUCCESS;
      });
   }

/**
* Destroy a block cipher object
*/
int botan_block_cipher_destroy(botan_block_cipher_t bc)
   {
   return BOTAN_FFI_CHECKED_DELETE(bc);
   }

int botan_block_cipher_clear(botan_block_cipher_t bc)
   {
   return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.clear(); });
   }

/**
* Set the key for a block cipher instance
*/
int botan_block_cipher_set_key(botan_block_cipher_t bc,
                               const uint8_t key[], size_t len)
   {
   return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.set_key(key, len); });
   }

/**
* Return the positive block size of this block cipher, or negative to
* indicate an error
*/
int botan_block_cipher_block_size(botan_block_cipher_t bc)
   {
   return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { return b.block_size(); });
   }

int botan_block_cipher_encrypt_blocks(botan_block_cipher_t bc,
                                      const uint8_t in[],
                                      uint8_t out[],
                                      size_t blocks)
   {
   return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.encrypt_n(in, out, blocks); });
   }

int botan_block_cipher_decrypt_blocks(botan_block_cipher_t bc,
                                      const uint8_t in[],
                                      uint8_t out[],
                                      size_t blocks)
   {
   return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.decrypt_n(in, out, blocks); });
   }

}
<commit_msg>Add static_cast to avoid conversion warning<commit_after>/*
* (C) 2015,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/ffi.h>
#include <botan/internal/ffi_util.h>
#include <botan/block_cipher.h>

extern "C" {

using namespace Botan_FFI;

BOTAN_FFI_DECLARE_STRUCT(botan_block_cipher_struct, Botan::BlockCipher, 0x64C29716);

int botan_block_cipher_init(botan_block_cipher_t* bc, const char* bc_name)
   {
   return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() {
      if(bc == nullptr || bc_name == nullptr || *bc_name == 0)
         return BOTAN_FFI_ERROR_NULL_POINTER;

      *bc = nullptr;

      std::unique_ptr<Botan::BlockCipher> cipher(Botan::BlockCipher::create(bc_name));
      if(cipher == nullptr)
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;

      *bc = new botan_block_cipher_struct(cipher.release());
      return BOTAN_FFI_SUCCESS;
      });
   }

/**
* Destroy a block cipher object
*/
int botan_block_cipher_destroy(botan_block_cipher_t bc)
   {
   return BOTAN_FFI_CHECKED_DELETE(bc);
   }

int botan_block_cipher_clear(botan_block_cipher_t bc)
   {
   return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.clear(); });
   }

/**
* Set the key for a block cipher instance
*/
int botan_block_cipher_set_key(botan_block_cipher_t bc,
                               const uint8_t key[], size_t len)
   {
   return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.set_key(key, len); });
   }

/**
* Return the positive block size of this block cipher, or negative to
* indicate an error
*/
int botan_block_cipher_block_size(botan_block_cipher_t bc)
   {
   return BOTAN_FFI_DO(Botan::BlockCipher, bc, b,
                       { return static_cast<int>(b.block_size()); });
   }

int botan_block_cipher_encrypt_blocks(botan_block_cipher_t bc,
                                      const uint8_t in[],
                                      uint8_t out[],
                                      size_t blocks)
   {
   return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.encrypt_n(in, out, blocks); });
   }

int botan_block_cipher_decrypt_blocks(botan_block_cipher_t bc,
                                      const uint8_t in[],
                                      uint8_t out[],
                                      size_t blocks)
   {
   return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.decrypt_n(in, out, blocks); });
   }

}
<|endoftext|>


<commit_before>/*
    vertexData.cpp
    Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch>
    All rights reserved.

    Implementation of the VertexData class.
*/

/** note, derived from Equalizer LGPL source.*/

#include "typedefs.h"
#include "vertexData.h"
#include "ply.h"

#include <cstdlib>
#include <algorithm>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/io_utils>

using namespace std;
using namespace ply;

struct Normal{
    osg::Vec3 triNormal;
    void normal(osg::Vec3 v1, osg::Vec3 v2, osg::Vec3 v3)
    {
        osg::Vec3 u,v;

        // right hand system, CCW triangle
        u = v2 - v1;
        v = v3 - v1;
        triNormal = u^v;
        triNormal.normalize();
    }
};

/*  Contructor.  */
VertexData::VertexData()
    : _invertFaces( false )
{
    // Initialize the members
    _vertices = NULL;
    _colors = NULL;
    _normals = NULL;
    _triangles = NULL;

}

/*  Read the vertex and (if available/wanted) color data from the open file.  */
void VertexData::readVertices( PlyFile* file, const int nVertices,
                               const bool readColors )
{
    // temporary vertex structure for ply loading
    struct _Vertex
    {
        float           x;
        float           y;
        float           z;
        unsigned char   r;
        unsigned char   g;
        unsigned char   b;
    } vertex;

    PlyProperty vertexProps[] =
    {
        { "x", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, x ), 0, 0, 0, 0 },
        { "y", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, y ), 0, 0, 0, 0 },
        { "z", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, z ), 0, 0, 0, 0 },
        { "red", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, r ), 0, 0, 0, 0 },
        { "green", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, g ), 0, 0, 0, 0 },
        { "blue", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, b ), 0, 0, 0, 0 }
    };

    // use all 6 properties when reading colors, only the first 3 otherwise
    int limit = readColors ? 6 : 3;
    for( int i = 0; i < limit; ++i )
        ply_get_property( file, "vertex", &vertexProps[i] );

    // check whether array is valid otherwise allocate the space
    if(!_vertices.valid())
        _vertices = new osg::Vec3Array;

    // If read colors allocate space for color array
    if( readColors )
    {
        if(!_colors.valid())
            _colors = new osg::Vec4Array;
    }

    // read in the vertices
    for( int i = 0; i < nVertices; ++i )
    {
        ply_get_element( file, static_cast< void* >( &vertex ) );
        _vertices->push_back( osg::Vec3( vertex.x, vertex.y, vertex.z ) );
        if( readColors )
            _colors->push_back( osg::Vec4( (unsigned int) vertex.r / 256.0, (unsigned int) vertex.g / 256.0 , (unsigned int) vertex.b/ 256.0, 0.0 ) );
    }
}

/*  Read the index data from the open file.  */
void VertexData::readTriangles( PlyFile* file, const int nFaces )
{
    // temporary face structure for ply loading
    struct _Face
    {
        unsigned char   nVertices;
        int*            vertices;
    } face;

    PlyProperty faceProps[] =
    {
        { "vertex_indices", PLY_INT, PLY_INT, offsetof( _Face, vertices ),
          1, PLY_UCHAR, PLY_UCHAR, offsetof( _Face, nVertices ) }
    };

    ply_get_property( file, "face", &faceProps[0] );

    //triangles.clear();
    //triangles.reserve( nFaces );
    if(!_triangles.valid())
        _triangles = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);

    // read in the faces, asserting that they are only triangles
    uint8_t ind1 = _invertFaces ? 2 : 0;
    uint8_t ind3 = _invertFaces ? 0 : 2;
    for( int i = 0; i < nFaces; ++i )
    {
        ply_get_element( file, static_cast< void* >( &face ) );
        MESHASSERT( face.vertices != 0 );
        if( (unsigned int)(face.nVertices) != 3 )
        {
            free( face.vertices );
            throw MeshException( "Error reading PLY file. Encountered a "
                                 "face which does not have three vertices." );
        }
        // Add the face indices in the premitive set
        _triangles->push_back( face.vertices[ind1]);
        _triangles->push_back( face.vertices[1]);
        _triangles->push_back( face.vertices[ind3] );

        // free the memory that was allocated by ply_get_element
        free( face.vertices );
    }
}

/*  Open a PLY file and read vertex, color and index data. and returns the node  */
osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColors )
{
    int     nPlyElems;
    char**  elemNames;
    int     fileType;
    float   version;
    bool    result = false;
    int     nComments;
    char**  comments;

    PlyFile* file = NULL;

    // Try to open ply file as for reading
    try{
            file  = ply_open_for_reading( const_cast< char* >( filename ),
                                          &nPlyElems, &elemNames,
                                          &fileType, &version );
    }
    // Catch the if any exception thrown
    catch( exception& e )
    {
        MESHERROR << "Unable to read PLY file, an exception occured:  "
                    << e.what() << endl;
    }

    if( !file )
    {
        MESHERROR << "Unable to open PLY file " << filename
                  << " for reading." << endl;
        return NULL;
    }

    MESHASSERT( elemNames != 0 );

    nComments = file->num_comments;
    comments = file->comments;

    #ifndef NDEBUG
    MESHINFO << filename << ": " << nPlyElems << " elements, file type = "
             << fileType << ", version = " << version << endl;
    #endif

    for( int i = 0; i < nComments; i++ )
    {
        if( equal_strings( comments[i], "modified by flipply" ) )
        {
            _invertFaces = true;
        }

    }
    for( int i = 0; i < nPlyElems; ++i )
    {
        int nElems;
        int nProps;

        PlyProperty** props = NULL;
        try{
                props = ply_get_element_description( file, elemNames[i],
                                                     &nElems, &nProps );
        }
        catch( exception& e )
        {
            MESHERROR << "Unable to get PLY file description, an exception occured:  "
                        << e.what() << endl;
        }
        MESHASSERT( props != 0 );

        #ifndef NDEBUG
        MESHINFO << "element " << i << ": name = " << elemNames[i] << ", "
                 << nProps << " properties, " << nElems << " elements" << endl;
        for( int j = 0; j < nProps; ++j )
        {
            MESHINFO << "element " << i << ", property " << j << ": "
                     << "name = " << props[j]->name << endl;
        }
        #endif

        // if the string is vertex means vertex data is started
        if( equal_strings( elemNames[i], "vertex" ) )
        {
            bool hasColors = false;
            // determine if the file stores vertex colors
            for( int j = 0; j < nProps; ++j )
                // if the string have the red means color info is there
                if( equal_strings( props[j]->name, "red" ) )
                    hasColors = true;

            if( ignoreColors )
                MESHINFO << "Colors in PLY file ignored per request." << endl;

            try {
                // Read vertices and store in a std::vector array
                readVertices( file, nElems, hasColors && !ignoreColors );
                // Check whether all vertices are loaded or not
                MESHASSERT( _vertices->size() == static_cast< size_t >( nElems ) );
                // Check all color elements read or not
                if( hasColors && !ignoreColors )
                {
                    MESHASSERT( _colors->size() == static_cast< size_t >( nElems ) );
                }
            }
            catch( exception& e )
            {
                MESHERROR << "Unable to read vertex in PLY file, an exception occured:  "
                            << e.what() << endl;
                // stop for loop by setting the loop variable to break condition
                // this way resources still get released even on error cases
                i = nPlyElems;

            }
        }
        // If the string is face means triangle info started
        else if( equal_strings( elemNames[i], "face" ) )
        try
        {
            // Read Triangles
            readTriangles( file, nElems );
            // Check whether all face elements read or not
            MESHASSERT( _triangles->size()/3  == static_cast< size_t >( nElems ) );
            result = true;
        }
        catch( exception& e )
        {
            MESHERROR << "Unable to read PLY file, an exception occured:  "
                      << e.what() << endl;
            // stop for loop by setting the loop variable to break condition
            // this way resources still get released even on error cases
            i = nPlyElems;
        }

        // free the memory that was allocated by ply_get_element_description
        for( int j = 0; j < nProps; ++j )
            free( props[j] );
        free( props );
    }

    ply_close( file );

    // free the memory that was allocated by ply_open_for_reading
    for( int i = 0; i < nPlyElems; ++i )
        free( elemNames[i] );
    free( elemNames );

   // If the result is true means the ply file is successfully read
   if(result)
   {
        // Create geometry node
        osg::Geometry* geom  =  new osg::Geometry;

        // set the vertex array
        geom->setVertexArray(_vertices.get());

        // If the normals are not calculated calculate the normals for faces
        if(!_normals.valid())
            _calculateNormals();

        // set the normals
        geom->setNormalArray(_normals.get());
        geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);

        // Add the premetive set
        geom->addPrimitiveSet(_triangles.get());

        // if color info is given set the color array
        if(_colors.valid())
        {
            geom->setColorArray(_colors.get());
            geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );

        }

        // set flage true to activate the vertex buffer object of drawable
        geom->setUseVertexBufferObjects(true);

        osg::Geode* geode = new osg::Geode;
        geode->addDrawable(geom);
        return geode;
   }

    return NULL;
}

/*  Calculate the face or vertex normals of the current vertex data.  */
void VertexData::_calculateNormals( const bool vertexNormals )
{

    if(_normals.valid())
        return;

    #ifndef NDEBUG
    int wrongNormals = 0;
    #endif

    if(!_normals.valid())
    {
        _normals = new osg::Vec3Array;
    }

    //normals.clear();
    if( vertexNormals )
    {
        // initialize all normals to zero
        for( size_t i = 0; i < _vertices->size(); ++i )
        {
            _normals->push_back( osg::Vec3( 0, 0, 0 ) );
        }
    }

    for( size_t i = 0; i < ((_triangles->size()));  i += 3 )
    {
        // iterate over all triangles and add their normals to adjacent vertices
        Normal  triangleNormal;
        unsigned int i0, i1, i2;
        i0 = (*_triangles)[i+0];
        i1 = (*_triangles)[i+1];
        i2 = (*_triangles)[i+2];
        triangleNormal.normal((*_vertices)[i0],
                               (*_vertices)[i1],
                               (*_vertices)[i2] );

        // count emtpy normals in debug mode
        #ifndef NDEBUG
        if( triangleNormal.triNormal.length() == 0.0f )
            ++wrongNormals;
        #endif

        if( vertexNormals )
        {
            (*_normals)[i0] += triangleNormal.triNormal;
            (*_normals)[i1] += triangleNormal.triNormal;
            (*_normals)[i2] += triangleNormal.triNormal;
        }
        else
            _normals->push_back( triangleNormal.triNormal );
    }

    // normalize all the normals
    if( vertexNormals )
        for( size_t i = 0; i < _normals->size(); ++i )
            (*_normals)[i].normalize();

    #ifndef NDEBUG
    if( wrongNormals > 0 )
        MESHINFO << wrongNormals << " faces had no valid normal." << endl;
    #endif
}

<commit_msg>From MAthias Froehlich, "Attached is a compile fix I need on Suse 11.1 for a successful compile. Just avoid uint8_t typed values in src/osgPlugins/ply/vertexData.cpp if they are not needed for a particular reason ..."<commit_after>/*
    vertexData.cpp
    Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch>
    All rights reserved.

    Implementation of the VertexData class.
*/

/** note, derived from Equalizer LGPL source.*/

#include "typedefs.h"
#include "vertexData.h"
#include "ply.h"

#include <cstdlib>
#include <algorithm>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/io_utils>

using namespace std;
using namespace ply;

struct Normal{
    osg::Vec3 triNormal;
    void normal(osg::Vec3 v1, osg::Vec3 v2, osg::Vec3 v3)
    {
        osg::Vec3 u,v;

        // right hand system, CCW triangle
        u = v2 - v1;
        v = v3 - v1;
        triNormal = u^v;
        triNormal.normalize();
    }
};

/*  Contructor.  */
VertexData::VertexData()
    : _invertFaces( false )
{
    // Initialize the members
    _vertices = NULL;
    _colors = NULL;
    _normals = NULL;
    _triangles = NULL;

}

/*  Read the vertex and (if available/wanted) color data from the open file.  */
void VertexData::readVertices( PlyFile* file, const int nVertices,
                               const bool readColors )
{
    // temporary vertex structure for ply loading
    struct _Vertex
    {
        float           x;
        float           y;
        float           z;
        unsigned char   r;
        unsigned char   g;
        unsigned char   b;
    } vertex;

    PlyProperty vertexProps[] =
    {
        { "x", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, x ), 0, 0, 0, 0 },
        { "y", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, y ), 0, 0, 0, 0 },
        { "z", PLY_FLOAT, PLY_FLOAT, offsetof( _Vertex, z ), 0, 0, 0, 0 },
        { "red", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, r ), 0, 0, 0, 0 },
        { "green", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, g ), 0, 0, 0, 0 },
        { "blue", PLY_UCHAR, PLY_UCHAR, offsetof( _Vertex, b ), 0, 0, 0, 0 }
    };

    // use all 6 properties when reading colors, only the first 3 otherwise
    int limit = readColors ? 6 : 3;
    for( int i = 0; i < limit; ++i )
        ply_get_property( file, "vertex", &vertexProps[i] );

    // check whether array is valid otherwise allocate the space
    if(!_vertices.valid())
        _vertices = new osg::Vec3Array;

    // If read colors allocate space for color array
    if( readColors )
    {
        if(!_colors.valid())
            _colors = new osg::Vec4Array;
    }

    // read in the vertices
    for( int i = 0; i < nVertices; ++i )
    {
        ply_get_element( file, static_cast< void* >( &vertex ) );
        _vertices->push_back( osg::Vec3( vertex.x, vertex.y, vertex.z ) );
        if( readColors )
            _colors->push_back( osg::Vec4( (unsigned int) vertex.r / 256.0, (unsigned int) vertex.g / 256.0 , (unsigned int) vertex.b/ 256.0, 0.0 ) );
    }
}

/*  Read the index data from the open file.  */
void VertexData::readTriangles( PlyFile* file, const int nFaces )
{
    // temporary face structure for ply loading
    struct _Face
    {
        unsigned char   nVertices;
        int*            vertices;
    } face;

    PlyProperty faceProps[] =
    {
        { "vertex_indices", PLY_INT, PLY_INT, offsetof( _Face, vertices ),
          1, PLY_UCHAR, PLY_UCHAR, offsetof( _Face, nVertices ) }
    };

    ply_get_property( file, "face", &faceProps[0] );

    //triangles.clear();
    //triangles.reserve( nFaces );
    if(!_triangles.valid())
        _triangles = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);

    // read in the faces, asserting that they are only triangles
    int ind1 = _invertFaces ? 2 : 0;
    int ind3 = _invertFaces ? 0 : 2;
    for( int i = 0; i < nFaces; ++i )
    {
        ply_get_element( file, static_cast< void* >( &face ) );
        MESHASSERT( face.vertices != 0 );
        if( (unsigned int)(face.nVertices) != 3 )
        {
            free( face.vertices );
            throw MeshException( "Error reading PLY file. Encountered a "
                                 "face which does not have three vertices." );
        }
        // Add the face indices in the premitive set
        _triangles->push_back( face.vertices[ind1]);
        _triangles->push_back( face.vertices[1]);
        _triangles->push_back( face.vertices[ind3] );

        // free the memory that was allocated by ply_get_element
        free( face.vertices );
    }
}

/*  Open a PLY file and read vertex, color and index data. and returns the node  */
osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColors )
{
    int     nPlyElems;
    char**  elemNames;
    int     fileType;
    float   version;
    bool    result = false;
    int     nComments;
    char**  comments;

    PlyFile* file = NULL;

    // Try to open ply file as for reading
    try{
            file  = ply_open_for_reading( const_cast< char* >( filename ),
                                          &nPlyElems, &elemNames,
                                          &fileType, &version );
    }
    // Catch the if any exception thrown
    catch( exception& e )
    {
        MESHERROR << "Unable to read PLY file, an exception occured:  "
                    << e.what() << endl;
    }

    if( !file )
    {
        MESHERROR << "Unable to open PLY file " << filename
                  << " for reading." << endl;
        return NULL;
    }

    MESHASSERT( elemNames != 0 );

    nComments = file->num_comments;
    comments = file->comments;

    #ifndef NDEBUG
    MESHINFO << filename << ": " << nPlyElems << " elements, file type = "
             << fileType << ", version = " << version << endl;
    #endif

    for( int i = 0; i < nComments; i++ )
    {
        if( equal_strings( comments[i], "modified by flipply" ) )
        {
            _invertFaces = true;
        }

    }
    for( int i = 0; i < nPlyElems; ++i )
    {
        int nElems;
        int nProps;

        PlyProperty** props = NULL;
        try{
                props = ply_get_element_description( file, elemNames[i],
                                                     &nElems, &nProps );
        }
        catch( exception& e )
        {
            MESHERROR << "Unable to get PLY file description, an exception occured:  "
                        << e.what() << endl;
        }
        MESHASSERT( props != 0 );

        #ifndef NDEBUG
        MESHINFO << "element " << i << ": name = " << elemNames[i] << ", "
                 << nProps << " properties, " << nElems << " elements" << endl;
        for( int j = 0; j < nProps; ++j )
        {
            MESHINFO << "element " << i << ", property " << j << ": "
                     << "name = " << props[j]->name << endl;
        }
        #endif

        // if the string is vertex means vertex data is started
        if( equal_strings( elemNames[i], "vertex" ) )
        {
            bool hasColors = false;
            // determine if the file stores vertex colors
            for( int j = 0; j < nProps; ++j )
                // if the string have the red means color info is there
                if( equal_strings( props[j]->name, "red" ) )
                    hasColors = true;

            if( ignoreColors )
                MESHINFO << "Colors in PLY file ignored per request." << endl;

            try {
                // Read vertices and store in a std::vector array
                readVertices( file, nElems, hasColors && !ignoreColors );
                // Check whether all vertices are loaded or not
                MESHASSERT( _vertices->size() == static_cast< size_t >( nElems ) );
                // Check all color elements read or not
                if( hasColors && !ignoreColors )
                {
                    MESHASSERT( _colors->size() == static_cast< size_t >( nElems ) );
                }
            }
            catch( exception& e )
            {
                MESHERROR << "Unable to read vertex in PLY file, an exception occured:  "
                            << e.what() << endl;
                // stop for loop by setting the loop variable to break condition
                // this way resources still get released even on error cases
                i = nPlyElems;

            }
        }
        // If the string is face means triangle info started
        else if( equal_strings( elemNames[i], "face" ) )
        try
        {
            // Read Triangles
            readTriangles( file, nElems );
            // Check whether all face elements read or not
            MESHASSERT( _triangles->size()/3  == static_cast< size_t >( nElems ) );
            result = true;
        }
        catch( exception& e )
        {
            MESHERROR << "Unable to read PLY file, an exception occured:  "
                      << e.what() << endl;
            // stop for loop by setting the loop variable to break condition
            // this way resources still get released even on error cases
            i = nPlyElems;
        }

        // free the memory that was allocated by ply_get_element_description
        for( int j = 0; j < nProps; ++j )
            free( props[j] );
        free( props );
    }

    ply_close( file );

    // free the memory that was allocated by ply_open_for_reading
    for( int i = 0; i < nPlyElems; ++i )
        free( elemNames[i] );
    free( elemNames );

   // If the result is true means the ply file is successfully read
   if(result)
   {
        // Create geometry node
        osg::Geometry* geom  =  new osg::Geometry;

        // set the vertex array
        geom->setVertexArray(_vertices.get());

        // If the normals are not calculated calculate the normals for faces
        if(!_normals.valid())
            _calculateNormals();

        // set the normals
        geom->setNormalArray(_normals.get());
        geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);

        // Add the premetive set
        geom->addPrimitiveSet(_triangles.get());

        // if color info is given set the color array
        if(_colors.valid())
        {
            geom->setColorArray(_colors.get());
            geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );

        }

        // set flage true to activate the vertex buffer object of drawable
        geom->setUseVertexBufferObjects(true);

        osg::Geode* geode = new osg::Geode;
        geode->addDrawable(geom);
        return geode;
   }

    return NULL;
}

/*  Calculate the face or vertex normals of the current vertex data.  */
void VertexData::_calculateNormals( const bool vertexNormals )
{

    if(_normals.valid())
        return;

    #ifndef NDEBUG
    int wrongNormals = 0;
    #endif

    if(!_normals.valid())
    {
        _normals = new osg::Vec3Array;
    }

    //normals.clear();
    if( vertexNormals )
    {
        // initialize all normals to zero
        for( size_t i = 0; i < _vertices->size(); ++i )
        {
            _normals->push_back( osg::Vec3( 0, 0, 0 ) );
        }
    }

    for( size_t i = 0; i < ((_triangles->size()));  i += 3 )
    {
        // iterate over all triangles and add their normals to adjacent vertices
        Normal  triangleNormal;
        unsigned int i0, i1, i2;
        i0 = (*_triangles)[i+0];
        i1 = (*_triangles)[i+1];
        i2 = (*_triangles)[i+2];
        triangleNormal.normal((*_vertices)[i0],
                               (*_vertices)[i1],
                               (*_vertices)[i2] );

        // count emtpy normals in debug mode
        #ifndef NDEBUG
        if( triangleNormal.triNormal.length() == 0.0f )
            ++wrongNormals;
        #endif

        if( vertexNormals )
        {
            (*_normals)[i0] += triangleNormal.triNormal;
            (*_normals)[i1] += triangleNormal.triNormal;
            (*_normals)[i2] += triangleNormal.triNormal;
        }
        else
            _normals->push_back( triangleNormal.triNormal );
    }

    // normalize all the normals
    if( vertexNormals )
        for( size_t i = 0; i < _normals->size(); ++i )
            (*_normals)[i].normalize();

    #ifndef NDEBUG
    if( wrongNormals > 0 )
        MESHINFO << wrongNormals << " faces had no valid normal." << endl;
    #endif
}

<|endoftext|>


<commit_before>/*
 * gateway.c - Gateway for Cassandra
 * CSC 652 - 2014
 */
extern "C" {
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcre.h>
#include <pthread.h>
#include <stdint.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>

}
#include "gateway.hpp"

/*
 * Main processing loop of gateway. Spawns individual threads to handle each incoming TCP connection from a client.
 * Return 0 on success (never reached, since it will listen for connections until killed), 1 on error.
*/
int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <IP addr to listen on>\n", argv[0]);
        exit(1);
    }
    if (inet_addr(argv[1]) == INADDR_NONE) {
        fprintf(stderr, "Please specify a valid IP address to listen on.\n");
        exit(1);
    }

    #if DEBUG
    printf("Cassandra gateway starting up on %s:%d.\n", argv[1], CASSANDRA_PORT);
    #endif

    pthread_attr_t attr;
    pthread_t thread; // Only need one

    /* The 2 file descriptors
     * listenfd - listen file
     * connfd   - accepted connection file
     */
    int listenfd = 0, connfd = 0;
    int* thread_data;

    struct sockaddr_in serv_addr;

    // Do some quick pthread attr setup
    pthread_attr_init(&attr);

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd < 0) {
        fprintf(stderr, "Socket creation error: %s\n", strerror(errno));
        exit(1);
    }

    // Clear the serv_addr struct
    memset(&serv_addr, 0, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;

    // Bind to IP address specified on command line
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_addr.sin_port = htons(CASSANDRA_PORT);

    // Bind the socket and port to the name
    if (bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
        fprintf(stderr, "Socket bind error: %s\n", strerror(errno));
        exit(1);
    }

    // Listen for connections, with a backlog of 10
    if (listen(listenfd, 10) == -1) {
        fprintf(stderr, "Socket listen error: %s\n", strerror(errno));
        exit(1);
    }

    #if DEBUG
    printf("Setup complete, beginning loop to listen for connections.\n");
    #endif

    // Main listen loop
    while (1) {
        // This is a blocking call!
        connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);

        // Must free in function, now threads have their own conn addr.
        thread_data = malloc(sizeof(int));
        *thread_data = connfd;

        if (pthread_create(&thread, &attr, HandleConn, (void *)thread_data) != 0) {
            fprintf(stderr, "pthread_create failed.\n");
            exit(1);
        }
        /*
         * Creating the threads as detached for 2 reasons:
         *  1. They will never rejoin
         *  2. This will save some sys resources
         */
        pthread_detach(thread);
    }

    // Execution will never reach here, but we need to return a value
    return 0;
}

/*
 * This method handles each client connection, processes packets, rewrites queries as needed, and then forwards new packets onto the actaul Cassandra instance.
 * Assumes the real Cassandra instance is listening on 127.0.0.1:(CASSANDRA_PORT + 1).
 */
void* HandleConn(void* thread_data) {
    int connfd = *(int *)thread_data;

    // Need to free asap
    free(thread_data);

    // Save this thread's ID to prefix all messages with
    pthread_t tid = pthread_self();

    #if DEBUG
    printf("%u: Thread spawned.\n", (uint32_t)tid);
    #endif

    // Before entering the processing loop, we need to establish a connection to the real Cassandra

    #if DEBUG
    printf("%u: Establishing connection to Cassandra listening on 127.0.0.1:%d.\n", (uint32_t)tid, CASSANDRA_PORT + 1);
    #endif

    struct sockaddr_in cassandra_addr;
    int cassandrafd = socket(AF_INET, SOCK_STREAM, 0);
    if (cassandrafd < 0) {
        fprintf(stderr, "%u: Socket creation error: %s\n", (uint32_t)tid, strerror(errno));
        exit(1);
    }

    // Setup sockaddr struct
    memset(&cassandra_addr, 0, sizeof(cassandra_addr));
    cassandra_addr.sin_family = AF_INET;
    cassandra_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    cassandra_addr.sin_port = htons(CASSANDRA_PORT + 1);

    // Bind the socket and port to the name
    if (connect(cassandrafd, (struct sockaddr*)&cassandra_addr, sizeof(cassandra_addr)) < 0) {
        fprintf(stderr, "%u: Socket bind error: %s\n", (uint32_t)tid, strerror(errno));
        exit(1);
    }

    // Now, enter the packet processing loop

    #if DEBUG
    printf("%u: Entering the packet processing loop.\n", (uint32_t)tid);
    #endif

    cql_packet_t *packet;
    uint32_t header_len = sizeof(cql_packet_t);
    uint32_t body_len;
    int bytesAvail = 0;

    while (1) {
        // At the top of the loop, we are expecting the start of another CQL packet. If it doesn't look right, send back an error and close the connection.
        // We poll each socket to see if any data is present for us to read. If not, we check the other one, then repeat. Hopefully this won't tax the CPU too
        // much and will give good performance by not being stuck processing lots of packets from only one direction.

        // FIXME There's not a one-to-one correspondance of client to server packets / this first approach may be too CPU intensive.
        //       We may need to use non-blocking I/O.

        // Test to see if any bytes have arrived from the client
        // FIXME when client closes connection, we should break out of this loop, otherwise we may crash when reading a closed socket!
        ioctl(connfd, FIONREAD, &bytesAvail);
        if (bytesAvail > 0) {

            #if DEBUG
            printf("%u: Processing packet from client.\n", (uint32_t)tid);
            #endif

            // Get packet from client
            packet = malloc(header_len);
            // FIXME need to come back and do proper sanity checks on data from client (ie, verify proper CQL version, etc)
            if (recv(connfd, packet, header_len, 0) < 0) { //The CQL header is 8 bytes
                fprintf(stderr, "%u: Error reading packet header from client: %s\n", (uint32_t)tid, strerror(errno));
                exit(1);
            }
            body_len = ntohl(packet->length);

            // Allocate more memory for rest of packet
            void *newpacket = realloc(packet, header_len + body_len);
            if (newpacket == NULL) {
                fprintf(stderr, "%u: Filed to realloc memory for packet body!\n", (uint32_t)tid);
                exit(1);
            }
            else {
                free(packet);
                packet = newpacket;
            }

            // Read in body of packet
            if (recv(connfd, packet + header_len, body_len, 0) < 0) { //Get the rest of the body
                fprintf(stderr, "%u: Error reading packet body from client: %s\n", (uint32_t)tid, strerror(errno));
                exit(1);
            }

            // Modify packet (if needed)

            // Send packet to Cassandra
            if (send(cassandrafd, packet, header_len + body_len, 0) < 0) { //Packet total size is header + body => 8 + packet->length
                fprintf(stderr, "%u: Error sending packet to Cassandra: %s\n", (uint32_t)tid, strerror(errno));
                exit(1);
            }

            free(packet);
        }

        // Test to see if any bytes have arrived from Cassandra
        ioctl(cassandrafd, FIONREAD, &bytesAvail);
        if (bytesAvail > 0) {

            #if DEBUG
            printf("%u: Processing packet from Cassandra.\n", (uint32_t)tid);
            #endif

            // Get packet back from Cassandra. We assume Cassandra will always give us properly formed packets.
            packet = malloc(header_len);
            if (recv(cassandrafd, packet, header_len, 0) < 0) { //The CQL header is 8 bytes
                fprintf(stderr, "%u: Error reading packet header from Cassandra: %s\n", (uint32_t)tid, strerror(errno));
                exit(1);
            }
            body_len = ntohl(packet->length);

            // Allocate more memory for rest of packet
            void *newpacket = realloc(packet, header_len + body_len);
            if (newpacket == NULL) {
                fprintf(stderr, "%u: Filed to realloc memory for packet body!\n", (uint32_t)tid);
                exit(1);
            }
            else {
                free(packet);
                packet = newpacket;
            }

            // Read in body of packet
            if (recv(cassandrafd, packet + header_len, body_len, 0) < 0) { //Get the rest of the body
                fprintf(stderr, "%u: Error reading packet body from Cassandra: %s\n", (uint32_t)tid, strerror(errno));
                exit(1);
            }

            // Modify packet (if needed)

            // Send packet to client
            if (send(connfd, packet, header_len + body_len, 0) < 0) { //Packet total size is header + body => 8 + packet->length
                fprintf(stderr, "%u: Error sending packet to client: %s\n", (uint32_t)tid, strerror(errno));
                exit(1);
            }

            free(packet);
        }
    }

    #if DEBUG
    printf("%u: Client connection terminated, thread dying.\n", (uint32_t)tid);
    #endif

    // Properly close connection to Cassandra server
    close(cassandrafd);

    return NULL;
}

char* prefix_cmd(char *cql_cmd, char *prefix){
	pcre *reCompiled;
        pcre_extra *pcreExtra;
        const char *pcreErrorStr;
        int pcreErrorOffset;
        int subStrVec[30];
        const char *psubStrMatchStr;
	char *p_string = (char *)malloc(100);
        int i;
        int pcreExecRet;
        char *aStrRegex;

	//chomp newline character and replace whenever found
	int length = strlen(cql_cmd);
	int j = 0;
	while(j < length){
		if(cql_cmd[j] == '\n'){
			cql_cmd[j] = ' ';
		}
		j++;
	}

        //Regex to match
	aStrRegex = "USE[ ]+(.*);";
        printf("Regex to use: %s, %s\n", aStrRegex, prefix);

	reCompiled = pcre_compile(aStrRegex, 0, &pcreErrorStr,
                                 &pcreErrorOffset, NULL );

        if(reCompiled == NULL){
                printf("ERROR: Compilation failed: '%s'", pcreErrorStr);
                exit(1);
        }

        // Regex optimization
        pcreExtra = pcre_study(reCompiled, 0, &pcreErrorStr);
        if(pcreErrorStr != NULL) {
                printf("ERROR: Something went wrong in optimization attempt:'%s'\n", pcreErrorStr);
                exit(1);
        }

	pcreExecRet = pcre_exec(reCompiled,
                                        pcreExtra,
                                        cql_cmd,
                                        strlen(cql_cmd),
                                        0,
                                        0,
                                        subStrVec,
                                        30);
	if(pcreExecRet < 0) {
                switch(pcreExecRet){
                case PCRE_ERROR_NOMATCH     :printf("String did not match\n");
                                             break;
                case PCRE_ERROR_NULL        :printf("Encountered null\n");
                                             break;
                case PCRE_ERROR_BADOPTION   :printf("A bad option was passed\n");
                                             break;
                case PCRE_ERROR_BADMAGIC    :printf("Magic number bad\n");
                                             break;
                case PCRE_ERROR_UNKNOWN_NODE:printf("Something bad in recompiled regex\n");
                                             break;
                case PCRE_ERROR_NOMEMORY    :printf("Ran out of memory\n");
                                             break;
                default                     :printf("Unknown error\n");
                                             break;
         }
        }
	else{
         printf("######A match was found#######\n");

         if(pcreExecRet == 0){
           printf("Too many substrings for substring vector\n");
           pcreExecRet = 10;
                }

        for(i=0;i<pcreExecRet;i++){
          pcre_get_substring(cql_cmd, subStrVec, pcreExecRet, i, &(psubStrMatchStr));
          printf("Match(%2d/%2d): (%2d,%2d): '%s'\n", i, pcreExecRet-1,subStrVec[i*2],subStrVec[i*2+1], psubStrMatchStr);
	  if(i){
                strcpy(p_string, psubStrMatchStr);
                prepend(p_string, "USE 123abc");
                printf("Result of processing: %s\n", p_string);
          }

        }
        pcre_free_substring(psubStrMatchStr);
        }
	 pcre_free(reCompiled);

        if(pcreExtra != NULL){
                pcre_free(pcreExtra);
        }

	return p_string;
}

void prepend(char* s, const char* t)
{
    size_t len = strlen(t);
    size_t i;

    memmove(s + len, s, len + 1);

    for (i = 0; i < len; ++i)
    {
        s[i] = t[i];
    }
}

/*
 * Returns true on success, false on failure (auth or otherwise)
 * Assume that internalToken is already malloc-ed in calling function
 * On failure, internalToken is NULL and false is returned
 */
bool checkToken(char *inToken, char *internalToken){

}

<commit_msg>Fixed build errors caused by c++ conversion --kkd<commit_after>/*
 * gateway.c - Gateway for Cassandra
 * CSC 652 - 2014
 */
extern "C" {
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcre.h>
#include <pthread.h>
#include <stdint.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>

}
#include "gateway.hpp"

/*
 * Main processing loop of gateway. Spawns individual threads to handle each incoming TCP connection from a client.
 * Return 0 on success (never reached, since it will listen for connections until killed), 1 on error.
*/
int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <IP addr to listen on>\n", argv[0]);
        exit(1);
    }
    if (inet_addr(argv[1]) == INADDR_NONE) {
        fprintf(stderr, "Please specify a valid IP address to listen on.\n");
        exit(1);
    }

    #if DEBUG
    printf("Cassandra gateway starting up on %s:%d.\n", argv[1], CASSANDRA_PORT);
    #endif

    pthread_attr_t attr;
    pthread_t thread; // Only need one

    /* The 2 file descriptors
     * listenfd - listen file
     * connfd   - accepted connection file
     */
    int listenfd = 0, connfd = 0;
    int* thread_data;

    struct sockaddr_in serv_addr;

    // Do some quick pthread attr setup
    pthread_attr_init(&attr);

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd < 0) {
        fprintf(stderr, "Socket creation error: %s\n", strerror(errno));
        exit(1);
    }

    // Clear the serv_addr struct
    memset(&serv_addr, 0, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;

    // Bind to IP address specified on command line
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_addr.sin_port = htons(CASSANDRA_PORT);

    // Bind the socket and port to the name
    if (bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
        fprintf(stderr, "Socket bind error: %s\n", strerror(errno));
        exit(1);
    }

    // Listen for connections, with a backlog of 10
    if (listen(listenfd, 10) == -1) {
        fprintf(stderr, "Socket listen error: %s\n", strerror(errno));
        exit(1);
    }

    #if DEBUG
    printf("Setup complete, beginning loop to listen for connections.\n");
    #endif

    // Main listen loop
    while (1) {
        // This is a blocking call!
        connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);

        // Must free in function, now threads have their own conn addr.
        thread_data = (int*)malloc(sizeof(int));
        *thread_data = connfd;

        if (pthread_create(&thread, &attr, HandleConn, (void *)thread_data) != 0) {
            fprintf(stderr, "pthread_create failed.\n");
            exit(1);
        }
        /*
         * Creating the threads as detached for 2 reasons:
         *  1. They will never rejoin
         *  2. This will save some sys resources
         */
        pthread_detach(thread);
    }

    // Execution will never reach here, but we need to return a value
    return 0;
}

/*
 * This method handles each client connection, processes packets, rewrites queries as needed, and then forwards new packets onto the actaul Cassandra instance.
 * Assumes the real Cassandra instance is listening on 127.0.0.1:(CASSANDRA_PORT + 1).
 */
void* HandleConn(void* thread_data) {
    int connfd = *(int *)thread_data;

    // Need to free asap
    free(thread_data);

    // Save this thread's ID to prefix all messages with
    pthread_t tid = pthread_self();

    #if DEBUG
    printf("%lu: Thread spawned.\n", (unsigned long)tid);
    #endif

    // Before entering the processing loop, we need to establish a connection to the real Cassandra

    #if DEBUG
    printf("%lu: Establishing connection to Cassandra listening on 127.0.0.1:%d.\n", (unsigned long)tid, CASSANDRA_PORT + 1);
    #endif

    struct sockaddr_in cassandra_addr;
    int cassandrafd = socket(AF_INET, SOCK_STREAM, 0);
    if (cassandrafd < 0) {
        fprintf(stderr, "%lu: Socket creation error: %s\n", (unsigned long)tid, strerror(errno));
        exit(1);
    }

    // Setup sockaddr struct
    memset(&cassandra_addr, 0, sizeof(cassandra_addr));
    cassandra_addr.sin_family = AF_INET;
    cassandra_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    cassandra_addr.sin_port = htons(CASSANDRA_PORT + 1);

    // Bind the socket and port to the name
    if (connect(cassandrafd, (struct sockaddr*)&cassandra_addr, sizeof(cassandra_addr)) < 0) {
        fprintf(stderr, "%lu: Socket bind error: %s\n", (unsigned long)tid, strerror(errno));
        exit(1);
    }

    // Now, enter the packet processing loop

    #if DEBUG
    printf("%lu: Entering the packet processing loop.\n", (unsigned long)tid);
    #endif

    cql_packet_t *packet;
    uint32_t header_len = sizeof(cql_packet_t);
    uint32_t body_len;
    int bytesAvail = 0;

    while (1) {
        // At the top of the loop, we are expecting the start of another CQL packet. If it doesn't look right, send back an error and close the connection.
        // We poll each socket to see if any data is present for us to read. If not, we check the other one, then repeat. Hopefully this won't tax the CPU too
        // much and will give good performance by not being stuck processing lots of packets from only one direction.

        // FIXME There's not a one-to-one correspondance of client to server packets / this first approach may be too CPU intensive.
        //       We may need to use non-blocking I/O.

        // Test to see if any bytes have arrived from the client
        // FIXME when client closes connection, we should break out of this loop, otherwise we may crash when reading a closed socket!
        ioctl(connfd, FIONREAD, &bytesAvail);
        if (bytesAvail > 0) {

            #if DEBUG
            printf("%lu: Processing packet from client.\n", (unsigned long)tid);
            #endif

            // Get packet from client
            packet = (cql_packet_t *)malloc(header_len);
            // FIXME need to come back and do proper sanity checks on data from client (ie, verify proper CQL version, etc)
            if (recv(connfd, packet, header_len, 0) < 0) { //The CQL header is 8 bytes
                fprintf(stderr, "%lu: Error reading packet header from client: %s\n", (unsigned long)tid, strerror(errno));
                exit(1);
            }
            body_len = ntohl(packet->length);

            // Allocate more memory for rest of packet
            cql_packet_t *newpacket = (cql_packet_t *)realloc(packet, header_len + body_len);
            if (newpacket == NULL) {
                fprintf(stderr, "%lu: Filed to realloc memory for packet body!\n", (unsigned long)tid);
                exit(1);
            }
            else {
                free(packet);
                packet = newpacket;
            }

            // Read in body of packet
            if (recv(connfd, packet + header_len, body_len, 0) < 0) { //Get the rest of the body
                fprintf(stderr, "%lu: Error reading packet body from client: %s\n", (unsigned long)tid, strerror(errno));
                exit(1);
            }

            // Modify packet (if needed)

            // Send packet to Cassandra
            if (send(cassandrafd, packet, header_len + body_len, 0) < 0) { //Packet total size is header + body => 8 + packet->length
                fprintf(stderr, "%lu: Error sending packet to Cassandra: %s\n", (unsigned long)tid, strerror(errno));
                exit(1);
            }

            free(packet);
        }

        // Test to see if any bytes have arrived from Cassandra
        ioctl(cassandrafd, FIONREAD, &bytesAvail);
        if (bytesAvail > 0) {

            #if DEBUG
            printf("%lu: Processing packet from Cassandra.\n", (unsigned long)tid);
            #endif

            // Get packet back from Cassandra. We assume Cassandra will always give us properly formed packets.
            packet = (cql_packet_t *)malloc(header_len);
            if (recv(cassandrafd, packet, header_len, 0) < 0) { //The CQL header is 8 bytes
                fprintf(stderr, "%lu: Error reading packet header from Cassandra: %s\n", (unsigned long)tid, strerror(errno));
                exit(1);
            }
            body_len = ntohl(packet->length);

            // Allocate more memory for rest of packet
            cql_packet_t *newpacket = (cql_packet_t *)realloc(packet, header_len + body_len);
            if (newpacket == NULL) {
                fprintf(stderr, "%lu: Filed to realloc memory for packet body!\n", (unsigned long)tid);
                exit(1);
            }
            else {
                free(packet);
                packet = newpacket;
            }

            // Read in body of packet
            if (recv(cassandrafd, packet + header_len, body_len, 0) < 0) { //Get the rest of the body
                fprintf(stderr, "%lu: Error reading packet body from Cassandra: %s\n", (unsigned long)tid, strerror(errno));
                exit(1);
            }

            // Modify packet (if needed)

            // Send packet to client
            if (send(connfd, packet, header_len + body_len, 0) < 0) { //Packet total size is header + body => 8 + packet->length
                fprintf(stderr, "%lu: Error sending packet to client: %s\n", (unsigned long)tid, strerror(errno));
                exit(1);
            }

            free(packet);
        }
    }

    #if DEBUG
    printf("%lu: Client connection terminated, thread dying.\n", (unsigned long)tid);
    #endif

    // Properly close connection to Cassandra server
    close(cassandrafd);

    return NULL;
}

char* prefix_cmd(char *cql_cmd, char *prefix){
	pcre *reCompiled;
        pcre_extra *pcreExtra;
        const char *pcreErrorStr;
        int pcreErrorOffset;
        int subStrVec[30];
        const char *psubStrMatchStr;
	char *p_string = (char *)malloc(100);
        int i;
        int pcreExecRet;
        const char *aStrRegex;

	//chomp newline character and replace whenever found
	int length = strlen(cql_cmd);
	int j = 0;
	while(j < length){
		if(cql_cmd[j] == '\n'){
			cql_cmd[j] = ' ';
		}
		j++;
	}

        //Regex to match
	aStrRegex = "USE[ ]+(.*);";
        printf("Regex to use: %s, %s\n", aStrRegex, prefix);

	reCompiled = pcre_compile(aStrRegex, 0, &pcreErrorStr,
                                 &pcreErrorOffset, NULL );

        if(reCompiled == NULL){
                printf("ERROR: Compilation failed: '%s'", pcreErrorStr);
                exit(1);
        }

        // Regex optimization
        pcreExtra = pcre_study(reCompiled, 0, &pcreErrorStr);
        if(pcreErrorStr != NULL) {
                printf("ERROR: Something went wrong in optimization attempt:'%s'\n", pcreErrorStr);
                exit(1);
        }

	pcreExecRet = pcre_exec(reCompiled,
                                        pcreExtra,
                                        cql_cmd,
                                        strlen(cql_cmd),
                                        0,
                                        0,
                                        subStrVec,
                                        30);
	if(pcreExecRet < 0) {
                switch(pcreExecRet){
                case PCRE_ERROR_NOMATCH     :printf("String did not match\n");
                                             break;
                case PCRE_ERROR_NULL        :printf("Encountered null\n");
                                             break;
                case PCRE_ERROR_BADOPTION   :printf("A bad option was passed\n");
                                             break;
                case PCRE_ERROR_BADMAGIC    :printf("Magic number bad\n");
                                             break;
                case PCRE_ERROR_UNKNOWN_NODE:printf("Something bad in recompiled regex\n");
                                             break;
                case PCRE_ERROR_NOMEMORY    :printf("Ran out of memory\n");
                                             break;
                default                     :printf("Unknown error\n");
                                             break;
         }
        }
	else{
         printf("######A match was found#######\n");

         if(pcreExecRet == 0){
           printf("Too many substrings for substring vector\n");
           pcreExecRet = 10;
                }

        for(i=0;i<pcreExecRet;i++){
          pcre_get_substring(cql_cmd, subStrVec, pcreExecRet, i, &(psubStrMatchStr));
          printf("Match(%2d/%2d): (%2d,%2d): '%s'\n", i, pcreExecRet-1,subStrVec[i*2],subStrVec[i*2+1], psubStrMatchStr);
	  if(i){
                strcpy(p_string, psubStrMatchStr);
                prepend(p_string, "USE 123abc");
                printf("Result of processing: %s\n", p_string);
          }

        }
        pcre_free_substring(psubStrMatchStr);
        }
	 pcre_free(reCompiled);

        if(pcreExtra != NULL){
                pcre_free(pcreExtra);
        }

	return p_string;
}

void prepend(char* s, const char* t)
{
    size_t len = strlen(t);
    size_t i;

    memmove(s + len, s, len + 1);

    for (i = 0; i < len; ++i)
    {
        s[i] = t[i];
    }
}

/*
 * Returns true on success, false on failure (auth or otherwise)
 * Assume that internalToken is already malloc-ed in calling function
 * On failure, internalToken is NULL and false is returned

bool checkToken(char *inToken, char *internalToken){

}
*/

<|endoftext|>


<commit_before>#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <bitcoin/bitcoin.hpp>
#include <wallet/wallet.hpp>
using namespace bc;
using namespace libwallet;

std::string dump_file(std::istream& in_file)
{
    std::istreambuf_iterator<char> it(in_file);
    std::istreambuf_iterator<char> end;
    return std::string(it, end);
}

int main(int argc, char** argv)
{
    if (argc != 2 && argc != 3)
    {
        std::cerr << "Usage: genpriv N [CHANGE]" << std::endl;
        return -1;
    }
    size_t n;
    try
    {
        n = boost::lexical_cast<size_t>(argv[1]);
    }
    catch (const boost::bad_lexical_cast&)
    {
        std::cerr << "genpriv: Bad N provided." << std::endl;
        return -1;
    }
    bool for_change = false;
    if (argc == 3)
    {
        std::string change_str = argv[2];
        boost::algorithm::to_lower(change_str);
        if (change_str == "true" || change_str == "1")
            for_change = true;
    }
    std::string seed = dump_file(std::cin);
    libwallet::deterministic_wallet wallet;
    if (!wallet.set_seed(seed))
    {
        std::cerr << "genpriv: This command wants a seed." << std::endl;
        return -1;
    }
    secret_parameter secret = wallet.generate_secret(n, for_change);
    std::cout << libwallet::secret_to_wif(secret) << std::endl;
    return 0;
}

<commit_msg>Fix for electrum-style deterministic wallet. Always exports uncompressed secret to wif.<commit_after>#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <bitcoin/bitcoin.hpp>
#include <wallet/wallet.hpp>
using namespace bc;
using namespace libwallet;

std::string dump_file(std::istream& in_file)
{
    std::istreambuf_iterator<char> it(in_file);
    std::istreambuf_iterator<char> end;
    return std::string(it, end);
}

int main(int argc, char** argv)
{
    if (argc != 2 && argc != 3)
    {
        std::cerr << "Usage: genpriv N [CHANGE]" << std::endl;
        return -1;
    }
    size_t n;
    try
    {
        n = boost::lexical_cast<size_t>(argv[1]);
    }
    catch (const boost::bad_lexical_cast&)
    {
        std::cerr << "genpriv: Bad N provided." << std::endl;
        return -1;
    }
    bool for_change = false;
    if (argc == 3)
    {
        std::string change_str = argv[2];
        boost::algorithm::to_lower(change_str);
        if (change_str == "true" || change_str == "1")
            for_change = true;
    }
    std::string seed = dump_file(std::cin);
    libwallet::deterministic_wallet wallet;
    if (!wallet.set_seed(seed))
    {
        std::cerr << "genpriv: This command wants a seed." << std::endl;
        return -1;
    }
    secret_parameter secret = wallet.generate_secret(n, for_change);
    std::cout << libwallet::secret_to_wif(secret, false) << std::endl;
    return 0;
}

<|endoftext|>