<commit_before>/**
 Copyright 2012 FAU (Friedrich Alexander University of Erlangen-Nuremberg)

 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.
 */

/**
 * look header for docu
 */

#include "m2etis/wrapper/udp/UdpWrapper.h"

#include "m2etis/message/MessageSerialization.h"
#include "m2etis/message/NetworkMessage.h"
#include "m2etis/net/NodeHandle.h"
#include "m2etis/parameters/WrapperParameters.h"
#include "m2etis/util/Logger.h"

#include "boost/array.hpp"      // nur fuer array buff anstatt streambuf
#include "boost/bind.hpp"
#include "boost/date_time/posix_time/posix_time.hpp"
#include "boost/enable_shared_from_this.hpp"
#include "boost/shared_ptr.hpp"

namespace m2etis {
namespace wrapper {
namespace udp {

	UdpWrapper::UdpWrapper(const std::string & ownIP, uint16_t listenPort, const std::string & hostIP, uint16_t hostPort) : _initialized(false), _name(ownIP), _hostName(hostIP), _listenPort(listenPort), _hostPort(hostPort), _io_service(), _socket(), _root(), _strand__(_io_service), _outbox(), _work(_io_service), _endpoint(), _remote_endpoint() {
			std::stringstream ss;
			ss << _hostName << ":" << _hostPort;
			_root = net::NetworkType<net::UDP>::Key(ss.str());

			threads_.push_back(new boost::thread(boost::bind(&boost::asio::io_service::run, &_strand__.get_io_service())));
			boost::this_thread::sleep(boost::posix_time::milliseconds(100));
			threads_.push_back(new boost::thread(boost::bind(&UdpWrapper::workerFunc, this)));
			boost::this_thread::sleep(boost::posix_time::milliseconds(100));
			_initialized = true;
	}

	UdpWrapper::~UdpWrapper() {
		_initialized = false;
		_io_service.stop();
		for (size_t i = 0; i < threads_.size(); ++i) {
			//threads_[i]->interrupt();
			threads_[i]->join();
			delete threads_[i];
		}
		if (_socket != nullptr) {
			_socket->close();
			delete _socket;
		}
		delete _endpoint;
		delete _remote_endpoint;
	}

	void UdpWrapper::workerFunc() {
		try {
			if (_socket == nullptr) {
				_endpoint = new boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), _listenPort);

				try {
					_socket = new boost::asio::ip::udp::socket(_io_service, *_endpoint);
				} catch(boost::system::system_error & e) {
					M2ETIS_THROW_FAILURE("UdpWrapper - workerFunc", e.what(), e.code().value());
				}
			}
			_remote_endpoint = new boost::asio::ip::udp::endpoint();
			// start receiving again
			boost::system::error_code error;
			_socket->async_receive_from(boost::asio::buffer(recv_buf, parameters::UDPWRAPPER_SIZE), *_remote_endpoint, boost::bind(&UdpWrapper::handleReceive, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, _remote_endpoint));
		} catch (util::SystemFailureException & e) {
			e.writeLog();
			e.PassToMain();
		}
	}

	void UdpWrapper::handleReceive(const boost::system::error_code & e, size_t len, boost::asio::ip::udp::endpoint * re) {
		if (e.value() != 0) {
			return;
		}
		std::vector<uint8_t> data(len);
		for (size_t i = 0; i < len; i++) {
			data[i] = recv_buf[i];
		}
		std::string message(data.begin(), data.begin() + std::string::difference_type(len));

		std::stringstream ss;
		ss << re->address().to_string() << ":" << re->port();
		message::Key<message::IPv4KeyProvider> k(ss.str());

		threads_.push_back(new boost::thread(boost::bind(&UdpWrapper::handleReceive, this, _socket, message, re, len)));
		workerFunc();
	}

	void UdpWrapper::handleReceive(boost::asio::ip::udp::socket *, std::string message, boost::asio::ip::udp::endpoint * endpoint, size_t len) {
		std::vector<uint8_t> v(message.begin(), message.begin() + std::string::difference_type(len));
		std::string msgString(v.begin(), v.end());

		try {
			message::NetworkMessage<net::NetworkType<net::UDP>>::Ptr msg(message::serialization::deserializeNetworkMsg<net::NetworkType<net::UDP>>(msgString));

			msg->sender = net::NetworkType<net::UDP>::Key(endpoint->address().to_string() + ":" + std::to_string(endpoint->port()));

			delete endpoint;

			_callback->deliver(msg);
		} catch (boost::archive::archive_exception & e) {
			std::cout << "Caught exception: " << e.what() << std::endl;
		}
	}

	void UdpWrapper::send(const message::NetworkMessage<net::NetworkType<net::UDP>>::Ptr msg, net::NodeHandle<net::NetworkType<net::UDP>>::Ptr_const hint) {
		// TODO: write or delete
		if (!_initialized) {
			M2ETIS_THROW_FAILURE("UdpWrapper - UdpWrapper not initialized", "Call init first!", -1);
		}

		send(msg);
	}

	void UdpWrapper::send(const message::NetworkMessage<net::NetworkType<net::UDP>>::Ptr msg) {
		if (!_initialized) {
			M2ETIS_THROW_FAILURE("UdpWrapper - UdpWrapper not initialized", "Call init first!", -1);
		}
		try {
			message::Key<message::IPv4KeyProvider> key = msg->receiver;

			std::string msgString = message::serialization::serializeNetworkMsg<message::NetworkMessage<net::NetworkType<net::UDP>>>(msg);
			std::vector<uint8_t> v(msgString.begin(), msgString.end());

			write(v, msg->receiver);
		} catch(util::SystemFailureException & e) {
			e.writeLog();
			e.PassToMain();
		}
	}

	void UdpWrapper::write(const std::vector<uint8_t> & message, message::Key<message::IPv4KeyProvider> key) {
		if (_initialized) {
			_strand__.post(boost::bind(&UdpWrapper::writeImpl, this, message, key));
		}
	}

	void UdpWrapper::writeImpl(const std::vector<uint8_t> & message, message::Key<message::IPv4KeyProvider> key) {
		if (_initialized) {
			_outbox.push_back(std::make_pair(message, key));
			if (_outbox.size() > 1) {
				// outstanding async_write
				return;
			}
			this->write();
		}
	}

	void UdpWrapper::write() {
		while (!_outbox.empty() && _initialized) {
			msgPair & message = _outbox[0];
			boost::asio::ip::udp::resolver resolver(_io_service);
			boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), message.second.ipStr(), message.second.portStr());
			boost::asio::ip::udp::endpoint endpoint(*resolver.resolve(query));
			boost::system::error_code err;

			_socket->send_to(boost::asio::buffer(message.first), endpoint);
			_outbox.pop_front();
		}
	}

	void UdpWrapper::registerMessageType(const message::MessageType, const bool) const {
		if (!_initialized) {
			M2ETIS_THROW_FAILURE("UdpWrapper - UdpWrapper not initialized", "Call init first!", -1);
		}
	}

} /* namespace udp */
} /* namespace wrapper */
} /* namespace m2etis */
<commit_msg>METIS-75 fixed crash in UdpWrapper caused by stupid use of thread buffering<commit_after>/**
 Copyright 2012 FAU (Friedrich Alexander University of Erlangen-Nuremberg)

 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.
 */

/**
 * look header for docu
 */

#include "m2etis/wrapper/udp/UdpWrapper.h"

#include "m2etis/message/MessageSerialization.h"
#include "m2etis/message/NetworkMessage.h"
#include "m2etis/net/NodeHandle.h"
#include "m2etis/parameters/WrapperParameters.h"
#include "m2etis/util/Logger.h"

#include "boost/array.hpp"      // nur fuer array buff anstatt streambuf
#include "boost/bind.hpp"
#include "boost/date_time/posix_time/posix_time.hpp"
#include "boost/enable_shared_from_this.hpp"
#include "boost/shared_ptr.hpp"

namespace m2etis {
namespace wrapper {
namespace udp {

	UdpWrapper::UdpWrapper(const std::string & ownIP, uint16_t listenPort, const std::string & hostIP, uint16_t hostPort) : _initialized(false), _name(ownIP), _hostName(hostIP), _listenPort(listenPort), _hostPort(hostPort), _io_service(), _socket(), _root(), _strand__(_io_service), _outbox(), _work(_io_service), _endpoint(), _remote_endpoint() {
			std::stringstream ss;
			ss << _hostName << ":" << _hostPort;
			_root = net::NetworkType<net::UDP>::Key(ss.str());

			threads_.push_back(new boost::thread(boost::bind(&boost::asio::io_service::run, &_strand__.get_io_service())));
			boost::this_thread::sleep(boost::posix_time::milliseconds(100));
			threads_.push_back(new boost::thread(boost::bind(&UdpWrapper::workerFunc, this)));
			boost::this_thread::sleep(boost::posix_time::milliseconds(100));
			_initialized = true;
	}

	UdpWrapper::~UdpWrapper() {
		_initialized = false;
		_io_service.stop();
		for (size_t i = 0; i < threads_.size(); ++i) {
			//threads_[i]->interrupt();
			threads_[i]->join();
			delete threads_[i];
		}
		if (_socket != nullptr) {
			_socket->close();
			delete _socket;
		}
		delete _endpoint;
		delete _remote_endpoint;
	}

	void UdpWrapper::workerFunc() {
		try {
			if (_socket == nullptr) {
				_endpoint = new boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), _listenPort);

				try {
					_socket = new boost::asio::ip::udp::socket(_io_service, *_endpoint);
				} catch(boost::system::system_error & e) {
					M2ETIS_THROW_FAILURE("UdpWrapper - workerFunc", e.what(), e.code().value());
				}
			}
			_remote_endpoint = new boost::asio::ip::udp::endpoint();
			// start receiving again
			boost::system::error_code error;
			_socket->async_receive_from(boost::asio::buffer(recv_buf, parameters::UDPWRAPPER_SIZE), *_remote_endpoint, boost::bind(&UdpWrapper::handleReceive, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, _remote_endpoint));
		} catch (util::SystemFailureException & e) {
			e.writeLog();
			e.PassToMain();
		}
	}

	void UdpWrapper::handleReceive(const boost::system::error_code & e, size_t len, boost::asio::ip::udp::endpoint * re) {
		if (e.value() != 0) {
			return;
		}
		std::vector<uint8_t> data(len);
		for (size_t i = 0; i < len; i++) {
			data[i] = recv_buf[i];
		}
		std::string message(data.begin(), data.begin() + std::string::difference_type(len));

		std::stringstream ss;
		ss << re->address().to_string() << ":" << re->port();
		message::Key<message::IPv4KeyProvider> k(ss.str());

		boost::thread t(boost::bind(&UdpWrapper::handleReceive, this, _socket, message, re, len));
		workerFunc();
		t.join();
	}

	void UdpWrapper::handleReceive(boost::asio::ip::udp::socket *, std::string message, boost::asio::ip::udp::endpoint * endpoint, size_t len) {
		std::vector<uint8_t> v(message.begin(), message.begin() + std::string::difference_type(len));
		std::string msgString(v.begin(), v.end());

		try {
			message::NetworkMessage<net::NetworkType<net::UDP>>::Ptr msg(message::serialization::deserializeNetworkMsg<net::NetworkType<net::UDP>>(msgString));

			msg->sender = net::NetworkType<net::UDP>::Key(endpoint->address().to_string() + ":" + std::to_string(endpoint->port()));

			delete endpoint;

			_callback->deliver(msg);
		} catch (boost::archive::archive_exception & e) {
			std::cout << "Caught exception: " << e.what() << std::endl;
		}
	}

	void UdpWrapper::send(const message::NetworkMessage<net::NetworkType<net::UDP>>::Ptr msg, net::NodeHandle<net::NetworkType<net::UDP>>::Ptr_const hint) {
		// TODO: write or delete
		if (!_initialized) {
			M2ETIS_THROW_FAILURE("UdpWrapper - UdpWrapper not initialized", "Call init first!", -1);
		}

		send(msg);
	}

	void UdpWrapper::send(const message::NetworkMessage<net::NetworkType<net::UDP>>::Ptr msg) {
		if (!_initialized) {
			M2ETIS_THROW_FAILURE("UdpWrapper - UdpWrapper not initialized", "Call init first!", -1);
		}
		try {
			message::Key<message::IPv4KeyProvider> key = msg->receiver;

			std::string msgString = message::serialization::serializeNetworkMsg<message::NetworkMessage<net::NetworkType<net::UDP>>>(msg);
			std::vector<uint8_t> v(msgString.begin(), msgString.end());

			write(v, msg->receiver);
		} catch(util::SystemFailureException & e) {
			e.writeLog();
			e.PassToMain();
		}
	}

	void UdpWrapper::write(const std::vector<uint8_t> & message, message::Key<message::IPv4KeyProvider> key) {
		if (_initialized) {
			_strand__.post(boost::bind(&UdpWrapper::writeImpl, this, message, key));
		}
	}

	void UdpWrapper::writeImpl(const std::vector<uint8_t> & message, message::Key<message::IPv4KeyProvider> key) {
		if (_initialized) {
			_outbox.push_back(std::make_pair(message, key));
			if (_outbox.size() > 1) {
				// outstanding async_write
				return;
			}
			this->write();
		}
	}

	void UdpWrapper::write() {
		while (!_outbox.empty() && _initialized) {
			msgPair & message = _outbox[0];
			boost::asio::ip::udp::resolver resolver(_io_service);
			boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), message.second.ipStr(), message.second.portStr());
			boost::asio::ip::udp::endpoint endpoint(*resolver.resolve(query));
			boost::system::error_code err;

			_socket->send_to(boost::asio::buffer(message.first), endpoint);
			_outbox.pop_front();
		}
	}

	void UdpWrapper::registerMessageType(const message::MessageType, const bool) const {
		if (!_initialized) {
			M2ETIS_THROW_FAILURE("UdpWrapper - UdpWrapper not initialized", "Call init first!", -1);
		}
	}

} /* namespace udp */
} /* namespace wrapper */
} /* namespace m2etis */
<|endoftext|>


<commit_before>#include "Channel.h"
#include "public_definitions.h"
#include "public_errors.h"
#include "ts3_functions.h"
#include "plugin.h"
#include <list>
#include <vector>

Channel::Channel(void)
	: id(0), parent(NULL)
{
}

Channel::Channel(uint64 id, Channel* parent)
	: id(id), parent(parent)
{
}

Channel::~Channel(void)
{
}

Channel* Channel::find(uint64 id)
{
	if(id == this->id) return this;

	for(std::list<Channel>::iterator it = subchannels.begin(); it != subchannels.end(); ++it)
	{
		Channel* result = it->find(id);
		if(result != NULL) return result;
	}

	return NULL;
}

Channel* Channel::first()
{
	if(subchannels.empty()) return this;
	return &subchannels.front();
}

Channel* Channel::last()
{
	if(subchannels.empty()) return this;
	return subchannels.back().last();
}

Channel* Channel::next()
{
	// If this is the root, there is no next
	if(parent == NULL) return NULL;

	// Find self in parent channel list
	std::list<Channel>::iterator it;
	for(it = parent->subchannels.begin(); it != parent->subchannels.end() && it->id != this->id; ++it);
	if(it == parent->subchannels.end()) return NULL; // Abort if parent is not really the parent

	// Return the next channel
	it++;
	if(it == parent->subchannels.end()) return parent->next();
	return &(*it);
}

Channel* Channel::prev()
{
	// If this is the root, there is no next
	if(parent == NULL) return NULL;

	// Find self in parent channel list
	std::list<Channel>::iterator it;
	for(it = parent->subchannels.begin(); it != parent->subchannels.end() && it->id != this->id; ++it);
	if(it == parent->subchannels.end()) return NULL; // Abort if parent is not really the parent

	// Return the next channel
	if(it == parent->subchannels.begin()) return parent;
	it--;
	return it->last();
}

int Channel::GetChannelHierarchy(uint64 scHandlerID, Channel* root)
{
	unsigned int error;

	// Get channel list
	uint64* channels;
	if((error = ts3Functions.getChannelList(scHandlerID, &channels)) != ERROR_ok)
	{
		char* errorMsg;
		if(ts3Functions.getErrorMessage(error, &errorMsg) == ERROR_ok)
		{
			ts3Functions.logMessage("Error retrieving list of channels:", LogLevel_WARNING, "G-Key Plugin", 0);
			ts3Functions.logMessage(errorMsg, LogLevel_WARNING, "G-Key Plugin", 0);
			ts3Functions.freeMemory(errorMsg);
		}
		return 1;
	}

	// Sort channels
	for(uint64* channel = channels; *channel != NULL; channel++)
	{
		Channel* parent = root;

		/*
		 * There doesn't seem to be any upper limit to the length of the channel path.
		 * As much as I hate doing this, 256 characters should be more than enough,
		 * getChannelConnectInfo is protected from buffer overflow.
		 */
		// Get the channel path
		char* path = (char*)malloc(256);
		ts3Functions.getChannelConnectInfo(scHandlerID, *channel, path, NULL, 256);

		// Split the string, following the hierachy until the subchannel is found
		char* str = path;
		char* lastStr = path;
		std::vector<char*> hierachy;
		while(str != NULL)
		{
			lastStr = str;
			str = strchr(lastStr, '/');
			if(str!=NULL)
			{
				*str = NULL;
				str++;
			}
			hierachy.push_back(lastStr);

			uint64 id;
			hierachy.push_back(""); // Add the terminator
			/*
			 * For efficiency purposes I will violate the vector abstraction and give a direct pointer to its internal C array
			 */
			if((error = ts3Functions.getChannelIDFromChannelNames(scHandlerID, &hierachy[0], &id)) != ERROR_ok)
			{
				char* errorMsg;
				if(ts3Functions.getErrorMessage(error, &errorMsg) == ERROR_ok)
				{
					ts3Functions.logMessage("Error getting parent channel ID:", LogLevel_WARNING, "G-Key Plugin", 0);
					ts3Functions.logMessage(errorMsg, LogLevel_WARNING, "G-Key Plugin", 0);
					ts3Functions.freeMemory(errorMsg);
				}
				ts3Functions.freeMemory(channels);
				return 1;
			}
			hierachy.pop_back();

			// Find the channel
			std::list<Channel>::iterator it;
			for(it = parent->subchannels.begin(); it != parent->subchannels.end() && it->id != id; ++it);

			// If the channel was found, set the parent, else add it
			if(it != parent->subchannels.end()) parent = &(*it);
			else
			{
				// Get the channel order
				int order;
				if((error = ts3Functions.getChannelVariableAsInt(scHandlerID, id, CHANNEL_ORDER, &order)) != ERROR_ok)
				{
					char* errorMsg;
					if(ts3Functions.getErrorMessage(error, &errorMsg) == ERROR_ok)
					{
						ts3Functions.logMessage("Error getting channel info:", LogLevel_WARNING, "G-Key Plugin", 0);
						ts3Functions.logMessage(errorMsg, LogLevel_WARNING, "G-Key Plugin", 0);
						ts3Functions.freeMemory(errorMsg);
					}
					ts3Functions.freeMemory(channels);
					return 1;
				}

				if(order == 0) // Top channel is added after parent
				{
					if(parent->subchannels.empty() || parent->subchannels.front().id != id) parent->subchannels.push_front(Channel(id, parent));
					parent = &parent->subchannels.front();
				}
				else // Other channels need to be sorted
				{
					// Find the channel after which this channel is sorted
					std::list<Channel>::iterator orderIt;
					for(orderIt = parent->subchannels.begin(); orderIt != parent->subchannels.end() && orderIt->id != order; ++orderIt);

					if(orderIt != parent->subchannels.end())
					{
						// If the channel was found, add it after
						orderIt++;
						parent = &(*parent->subchannels.insert(orderIt, Channel(id, parent)));
					}
					else
					{
						// If the channel was not found, add it to the back
						parent->subchannels.push_back(Channel(id, parent));
						parent = &parent->subchannels.back();
					}
				}
			}
		}
		free(path);
	}

	ts3Functions.freeMemory(channels);
	return 0;
}
<commit_msg>Hierarchy now generated using getParentChannelOfChannel<commit_after>#include "Channel.h"
#include "public_definitions.h"
#include "public_errors.h"
#include "ts3_functions.h"
#include "plugin.h"
#include <list>
#include <vector>
#include <stack>

Channel::Channel(void)
	: id(0), parent(NULL)
{
}

Channel::Channel(uint64 id, Channel* parent)
	: id(id), parent(parent)
{
}

Channel::~Channel(void)
{
}

Channel* Channel::find(uint64 id)
{
	if(id == this->id) return this;

	for(std::list<Channel>::iterator it = subchannels.begin(); it != subchannels.end(); ++it)
	{
		Channel* result = it->find(id);
		if(result != NULL) return result;
	}

	return NULL;
}

Channel* Channel::first()
{
	if(subchannels.empty()) return this;
	return &subchannels.front();
}

Channel* Channel::last()
{
	if(subchannels.empty()) return this;
	return subchannels.back().last();
}

Channel* Channel::next()
{
	// If this is the root, there is no next
	if(parent == NULL) return NULL;

	// Find self in parent channel list
	std::list<Channel>::iterator it;
	for(it = parent->subchannels.begin(); it != parent->subchannels.end() && it->id != this->id; ++it);
	if(it == parent->subchannels.end()) return NULL; // Abort if parent is not really the parent

	// Return the next channel
	it++;
	if(it == parent->subchannels.end()) return parent->next();
	return &(*it);
}

Channel* Channel::prev()
{
	// If this is the root, there is no next
	if(parent == NULL) return NULL;

	// Find self in parent channel list
	std::list<Channel>::iterator it;
	for(it = parent->subchannels.begin(); it != parent->subchannels.end() && it->id != this->id; ++it);
	if(it == parent->subchannels.end()) return NULL; // Abort if parent is not really the parent

	// Return the next channel
	if(it == parent->subchannels.begin()) return parent;
	it--;
	return it->last();
}

int Channel::GetChannelHierarchy(uint64 scHandlerID, Channel* root)
{
	unsigned int error;

	// Get channel list
	uint64* channels;
	if((error = ts3Functions.getChannelList(scHandlerID, &channels)) != ERROR_ok)
	{
		char* errorMsg;
		if(ts3Functions.getErrorMessage(error, &errorMsg) == ERROR_ok)
		{
			ts3Functions.logMessage("Error retrieving list of channels:", LogLevel_WARNING, "G-Key Plugin", 0);
			ts3Functions.logMessage(errorMsg, LogLevel_WARNING, "G-Key Plugin", 0);
			ts3Functions.freeMemory(errorMsg);
		}
		return 1;
	}

	// Sort channels
	for(uint64* channel = channels; *channel != NULL; channel++)
	{
		Channel* parent = root;
		uint64 id = *channel;
		std::stack<uint64> hierachy;

		// Build the hierarchy stack
		while(id != 0)
		{
			hierachy.push(id);
			ts3Functions.getParentChannelOfChannel(scHandlerID, id, &id);
		}

		while(!hierachy.empty())
		{
			id = hierachy.top();
			hierachy.pop();

			// Find the channel
			std::list<Channel>::iterator it;
			for(it = parent->subchannels.begin(); it != parent->subchannels.end() && it->id != id; ++it);

			// If the channel was found, set the parent, else add it
			if(it != parent->subchannels.end()) parent = &(*it);
			else
			{
				// Get the channel order
				int order;
				if((error = ts3Functions.getChannelVariableAsInt(scHandlerID, id, CHANNEL_ORDER, &order)) != ERROR_ok)
				{
					char* errorMsg;
					if(ts3Functions.getErrorMessage(error, &errorMsg) == ERROR_ok)
					{
						ts3Functions.logMessage("Error getting channel info:", LogLevel_WARNING, "G-Key Plugin", 0);
						ts3Functions.logMessage(errorMsg, LogLevel_WARNING, "G-Key Plugin", 0);
						ts3Functions.freeMemory(errorMsg);
					}
					ts3Functions.freeMemory(channels);
					return 1;
				}

				if(order == 0) // Top channel is added after parent
				{
					if(parent->subchannels.empty() || parent->subchannels.front().id != id) parent->subchannels.push_front(Channel(id, parent));
					parent = &parent->subchannels.front();
				}
				else // Other channels need to be sorted
				{
					// Find the channel after which this channel is sorted
					std::list<Channel>::iterator orderIt;
					for(orderIt = parent->subchannels.begin(); orderIt != parent->subchannels.end() && orderIt->id != order; ++orderIt);

					if(orderIt != parent->subchannels.end())
					{
						// If the channel was found, add it after
						orderIt++;
						parent = &(*parent->subchannels.insert(orderIt, Channel(id, parent)));
					}
					else
					{
						// If the channel was not found, add it to the back
						parent->subchannels.push_back(Channel(id, parent));
						parent = &parent->subchannels.back();
					}
				}
			}
		}
	}

	ts3Functions.freeMemory(channels);
	return 0;
}
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(1)

class Solution {
public:
    bool isSelfCrossing(vector<int>& x) {
        for (int i = 3; i < x.size(); ++i) {
            if (x[i] >= x[i - 2] && x[i - 1] <= x[i - 3]) {
//                         i-2
//             case 1 : i-1┌─┐
//                         └─┼─>i
//                          i-3
                return true;
            } else if (i >= 4 && x[i - 1] == x[i - 3] && x[i] + x[i - 4] >= x[i - 2]) {
//                           i-2
//             case 2 : i-1 ┌────┐
//                          └─══>┘i-3
//                          i  i-4  (overlapped)
                return true;
            } else if (i >= 5 && x[i - 2] >= x[i - 4] && x[i] + x[i - 4] >= x[i - 2] &&
                       x[i - 1] <= x[i - 3] && x[i - 1] + x[i - 5] >= x[i - 3]) {
//                         i-4
//                         ┌──┐
//              case 3 :   │i<┼─┐
//                      i-3│ i-5│i-1
//                         └────┘
//                          i-2
                return true;
            }
        }
        return false;
    }
};
<commit_msg>Update self-crossing.cpp<commit_after>// Time:  O(n)
// Space: O(1)

class Solution {
public:
    bool isSelfCrossing(vector<int>& x) {
        for (int i = 3; i < x.size(); ++i) {
            if (x[i] >= x[i - 2] && x[i - 3] >= x[i - 1]) {
//                         i-2
//             case 1 : i-1┌─┐
//                         └─┼─>i
//                          i-3
                return true;
            } else if (i >= 4 && x[i - 1] == x[i - 3] && x[i] + x[i - 4] >= x[i - 2]) {
//                           i-2
//             case 2 : i-1 ┌────┐
//                          └─══>┘i-3
//                          i  i-4  (overlapped)
                return true;
            } else if (i >= 5 && x[i - 4] <= x[i - 2] && x[i] + x[i - 4] >= x[i - 2] &&
                       x[i - 1] <= x[i - 3] && x[i - 1] + x[i - 5] >= x[i - 3]) {
//                         i-4
//                         ┌──┐
//              case 3 :   │i<┼─┐
//                      i-3│ i-5│i-1
//                         └────┘
//                          i-2
                return true;
            }
        }
        return false;
    }
};
<|endoftext|>


<commit_before>// better_sqlite3.cpp
//

#include "better_sqlite3.hpp"
#line 11 "./src2/better_sqlite3.lzz"
void RegisterModule(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {
	v8::HandleScope scope(v8::Isolate::GetCurrent());

	Int64::Init(exports);
}
NODE_MODULE(better_sqlite3, RegisterModule);
#define LZZ_INLINE inline
#line 14 "./src2/objects/int64/int64.lzz"
sqlite3_int64 const MAX_SAFE = (sqlite3_int64)9007199254740991;
#line 15 "./src2/objects/int64/int64.lzz"
sqlite3_int64 const MIN_SAFE = (sqlite3_int64)-9007199254740991;
#line 16 "./src2/objects/int64/int64.lzz"
sqlite3_uint64 const U32_in_U64 = (sqlite3_uint64)0xffffffff;
#line 20 "./src2/objects/int64/int64.lzz"
Int64::Int64 (int32_t _low, int32_t _high)
#line 20 "./src2/objects/int64/int64.lzz"
  : Nan::ObjectWrap ()
#line 20 "./src2/objects/int64/int64.lzz"
                                                                        {
		low = _low;
		high = _high;
		full = (sqlite3_int64)((((sqlite3_uint64)((uint32_t)_high)) << 32) | (uint32_t)_low);
	}
#line 25 "./src2/objects/int64/int64.lzz"
Int64::Int64 (sqlite3_int64 _full)
#line 25 "./src2/objects/int64/int64.lzz"
  : Nan::ObjectWrap ()
#line 25 "./src2/objects/int64/int64.lzz"
                                                                {
		low = (int32_t)((uint32_t)(((sqlite3_uint64)_full) & U32_in_U64));
		high = (int32_t)((uint32_t)(((sqlite3_uint64)_full) >> 32));
		full = _full;
	}
#line 30 "./src2/objects/int64/int64.lzz"
void Int64::Init (v8::Local <v8::Object> exports)
#line 30 "./src2/objects/int64/int64.lzz"
                                                        {
		v8::Local<v8::FunctionTemplate> t = Nan::New<v8::FunctionTemplate>(JS_new);
		t->InstanceTemplate()->SetInternalFieldCount(1);
		t->SetClassName(NEW_INTERNAL_STRING_FAST("Int64"));

		Nan::SetAccessor(t->InstanceTemplate(), NEW_INTERNAL_STRING_FAST("low"), JS_low);
		Nan::SetAccessor(t->InstanceTemplate(), NEW_INTERNAL_STRING_FAST("high"), JS_high);
		Nan::SetPrototypeMethod(t, "toString", JS_toString);
		Nan::SetPrototypeMethod(t, "valueOf", JS_valueOf);

		constructor.Reset(exports->GetIsolate(), Nan::GetFunction(t).ToLocalChecked());
		constructorTemplate.Reset(exports->GetIsolate(), t);
		fast_construct_int = NULL;

		Nan::Set(exports, NEW_INTERNAL_STRING_FAST("Int64"), Nan::GetFunction(t).ToLocalChecked());
	}
#line 67 "./src2/objects/int64/int64.lzz"
v8::Persistent <v8::Function> Int64::constructor;
#line 68 "./src2/objects/int64/int64.lzz"
v8::Persistent <v8::FunctionTemplate> Int64::constructorTemplate;
#line 69 "./src2/objects/int64/int64.lzz"
sqlite3_int64 * Int64::fast_construct_int;
#line 75 "./src2/objects/int64/int64.lzz"
void Int64::JS_new (Nan::FunctionCallbackInfo <v8::Value> const & info)
#line 75 "./src2/objects/int64/int64.lzz"
                                                                             {
		if (fast_construct_int != NULL) {
			Int64* int64 = new Int64(*fast_construct_int);
			fast_construct_int = NULL;
			int64->Wrap(info.This());
			return info.GetReturnValue().Set(info.This());
		}

		int32_t low;
		int32_t high;

		if (info.Length() < 1 || !info[0]->IsInt32()) {
			info.GetIsolate()->ThrowException(v8::Exception::TypeError(
				StringFromUtf8(info.GetIsolate(), "Expected arguemnt 1 to be a 32-bit signed integer", -1)));
			return;
		}
		low = v8::Local<v8::Int32>::Cast(info[0])->Value();

		if (info.Length() > 1) {
			if (!info[1]->IsInt32()) {
				info.GetIsolate()->ThrowException(v8::Exception::TypeError(
					StringFromUtf8(info.GetIsolate(), "Expected arguemnt 2 to be a 32-bit signed integer", -1)));
				return;
			}
			high = v8::Local<v8::Int32>::Cast(info[1])->Value();
		} else {
			high = 0;
		}

		Int64* int64 = new Int64(low, high);
		int64->Wrap(info.This());
		info.GetReturnValue().Set(info.This());
	}
#line 108 "./src2/objects/int64/int64.lzz"
void Int64::JS_low (v8::Local <v8::String> _, Nan::PropertyCallbackInfo <v8::Value> const & info)
#line 108 "./src2/objects/int64/int64.lzz"
                                                                                {
		info.GetReturnValue().Set(v8::Int32::New(info.GetIsolate(), Nan::ObjectWrap::Unwrap<Int64>(info.This())->low));
	}
#line 111 "./src2/objects/int64/int64.lzz"
void Int64::JS_high (v8::Local <v8::String> _, Nan::PropertyCallbackInfo <v8::Value> const & info)
#line 111 "./src2/objects/int64/int64.lzz"
                                                                                {
		info.GetReturnValue().Set(v8::Int32::New(info.GetIsolate(), Nan::ObjectWrap::Unwrap<Int64>(info.This())->high));
	}
#line 114 "./src2/objects/int64/int64.lzz"
void Int64::JS_toString (Nan::FunctionCallbackInfo <v8::Value> const & info)
#line 114 "./src2/objects/int64/int64.lzz"
                                                                                {
		v8::Isolate* const isolate = info.GetIsolate();
		std::string string = std::to_string(static_cast<long long>(Nan::ObjectWrap::Unwrap<Int64>(info.This())->full));
		info.GetReturnValue().Set(StringFromLatin1(isolate, string.c_str(), string.length()));
	}
#line 119 "./src2/objects/int64/int64.lzz"
void Int64::JS_valueOf (Nan::FunctionCallbackInfo <v8::Value> const & info)
#line 119 "./src2/objects/int64/int64.lzz"
                                                                                {
		sqlite3_int64 full = Nan::ObjectWrap::Unwrap<Int64>(info.This())->full;
		if (full <= MAX_SAFE && full >= MIN_SAFE) {
			info.GetReturnValue().Set(v8::Number::New(info.GetIsolate(), static_cast<double>(full)));
		} else {
			info.GetReturnValue().Set(v8::Number::New(info.GetIsolate(), std::numeric_limits<double>::quiet_NaN()));
		}
	}
#undef LZZ_INLINE
<commit_msg>tweak<commit_after><|endoftext|>


<commit_before>/*****************************************************************************
 * dispatcher.hpp : matroska demuxer
 *****************************************************************************
 * Copyright (C) 2016 VLC authors, VideoLAN, Videolabs SAS
 * $Id$
 *
 * Authors: Filip Roseen <filip@videolabs.io>
 *
 * This program 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 program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/
#ifndef VLC_MKV_DISPATCHER_HPP_
#define VLC_MKV_DISPATCHER_HPP_

// ----------------------------------------------------------------------------
// This header contains helpers to simulate lambdas in C++03.
//
// It will be used to create "dispatchers" which can be thought of like a
// `switch` but only more dynamic.
// ----------------------------------------------------------------------------

namespace {

  template<class Impl, class Processor>
  class Dispatcher {
    protected:
      Dispatcher() : _default_handler (NULL) { }
    public:
      template<class It>
      void iterate (It beg, It end, void* const& payload) const {
        for (; beg != end; ++beg)
          static_cast<Impl const*> (this)->Impl::send (*beg, payload);
      }

      void set_default_handler (Processor const& callback) {
        _default_handler = callback;
      }

      void on_create () {
        /* empty default implementation */
      }

      Processor _default_handler;
  };

  template<int>
  struct DispatcherTag;

  template<class T, T*, class DispatcherType>
  class DispatchContainer {
    public:    static DispatcherType dispatcher;
    protected: static vlc_mutex_t   _dispatcher_lock;
  };

  template<class T, T* P, class DT>
  DT DispatchContainer<T, P, DT>::dispatcher;

  template<class T, T* P, class DT>
  vlc_mutex_t DispatchContainer<T, P, DT>::_dispatcher_lock = VLC_STATIC_MUTEX;
}

// ----------------------------------------------------------------------------
//   * `GroupName_##_tag` is used so that we can refer to a static dispatcher
//      of the correct type without instantiating DispatchContainer with a
//      locally declared type (since it is illegal in C++03).
//
//      We are however allowed to pass the variable of a variable declared
//      `extern`, and this will effectively be our handle to the "foreign"
//      static dispatcher.
//
//      We make the variable have type `DispatcherTag<__LINE__>` so that you
//      can use MKV_SWITCH_CREATE with the same name in different parts of the
//      translation-unit (without collision).
//
//   *  `GroupName_ ## _base` is used to declare a bunch of helpers; names that
//       must be available in our fake "lambdas" (C++03 is a pain).
// ----------------------------------------------------------------------------

#define MKV_SWITCH_CREATE(DispatchType_, GroupName_, PayloadType_) \
  typedef DispatcherTag<__LINE__> GroupName_ ## _tag_t; \
  extern GroupName_##_tag_t GroupName_ ## _tag; \
  struct GroupName_##_base : DispatchContainer<GroupName_##_tag_t, &GroupName_##_tag, DispatchType_> { \
      typedef      PayloadType_ payload_t;                         \
      typedef     DispatchType_ dispatch_t;                        \
      typedef struct GroupName_ handler_t;                         \
      static void* Payload (payload_t& data) {                     \
          return static_cast<void*> (&data);                       \
      }                                                            \
  };                                                               \
  struct GroupName_ : GroupName_ ## _base

// ----------------------------------------------------------------------------
//   * `Dispatcher` is a static function used to access the dispatcher in a
//      thread-safe manner. We only want _one_ thread to actually construct
//      and initialize it, hence the lock.
// ----------------------------------------------------------------------------

#define MKV_SWITCH_INIT()                     \
  static dispatch_t& Dispatcher () {          \
      static handler_t * p_handler = NULL;    \
      vlc_mutex_lock( &_dispatcher_lock );    \
      if (unlikely( p_handler == NULL) ) {    \
          static handler_t handler;           \
          p_handler = &handler;               \
          p_handler->dispatcher.on_create (); \
      }                                       \
      vlc_mutex_unlock( &_dispatcher_lock );  \
      return p_handler->dispatcher;           \
  } struct PleaseAddSemicolon {}

// ----------------------------------------------------------------------------
//   * The following is to be used inside `struct GroupName_`, effectivelly
//     declaring a local struct and a data-member, `ClassName_ ## _processor`,
//     of that type.
//
//     When the data-member is constructed it will run `InitializationExpr_`,
//     meaning that it can access the static dispatcher and register itself (or
//     whatever is desired).
//
//   * Since we need to do type-erasure, once again, because of the fact that
//     C++03 does not support locally declared types as template-arguments, we
//     declare a static function `ClassName_ ## _callback` that will cast our
//     payload from `void*` to the appropriate type.
//
//   * The body of `ClassName_ ## _handler` will be written by the user of the
//     MACRO, and the implementation will effectively be invoked whenever the
//     dispatcher decides to (through `ClassName_ ## _callback`).
//
//   * Since the type of the `VariableName_` argument to `ClassName_ ## _handler`
//     might not necessarily be the same as the type passed from the dispatcher
//     (because of the type-erasure), the macro provides a way to change the
//     type with a `UnwrapExpr_` (see the function call within `ClassName_ ##
//     _callback`).
// ----------------------------------------------------------------------------

#define MKV_SWITCH_CASE_DEFINITION(ClassName_, RealType_, Type_, VariableName_, PayloadName_, InitializationExpr_, UnwrapExpr_) \
  struct ClassName_##_processor {                                             \
    ClassName_##_processor () { InitializationExpr_; }                        \
  } ClassName_##__wrapper;                                                    \
  static inline void ClassName_##_callback (Type_ data, void* PayloadName_) { \
    ClassName_##_handler (UnwrapExpr_, *static_cast<payload_t*>(PayloadName_));      \
  }                                                                             \
  static inline void ClassName_##_handler (RealType_& VariableName_, payload_t& PayloadName_)

#endif
<commit_msg>mkv: fix build failure when compiled with llvm<commit_after>/*****************************************************************************
 * dispatcher.hpp : matroska demuxer
 *****************************************************************************
 * Copyright (C) 2016 VLC authors, VideoLAN, Videolabs SAS
 * $Id$
 *
 * Authors: Filip Roseen <filip@videolabs.io>
 *
 * This program 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 program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/
#ifndef VLC_MKV_DISPATCHER_HPP_
#define VLC_MKV_DISPATCHER_HPP_

// ----------------------------------------------------------------------------
// This header contains helpers to simulate lambdas in C++03.
//
// It will be used to create "dispatchers" which can be thought of like a
// `switch` but only more dynamic.
// ----------------------------------------------------------------------------

namespace {

  template<class Impl, class Processor>
  class Dispatcher {
    protected:
      Dispatcher() : _default_handler (NULL) { }
    public:
      template<class It>
      void iterate (It beg, It end, void* const& payload) const {
        for (; beg != end; ++beg)
          static_cast<Impl const*> (this)->Impl::send (*beg, payload);
      }

      void set_default_handler (Processor const& callback) {
        _default_handler = callback;
      }

      void on_create () {
        /* empty default implementation */
      }

      Processor _default_handler;
  };

  template<int>
  struct DispatcherTag;

  template<class T, T*, class DispatcherType>
  class DispatchContainer {
    public:    static DispatcherType dispatcher;
    protected: static vlc_mutex_t   _dispatcher_lock;
  };

  template<class T, T* P, class DT>
  DT DispatchContainer<T, P, DT>::dispatcher;

  template<class T, T* P, class DT>
  vlc_mutex_t DispatchContainer<T, P, DT>::_dispatcher_lock = VLC_STATIC_MUTEX;
}

// ----------------------------------------------------------------------------
//   * `GroupName_##_tag` is used so that we can refer to a static dispatcher
//      of the correct type without instantiating DispatchContainer with a
//      locally declared type (since it is illegal in C++03).
//
//      We are however allowed to pass the variable of a variable declared
//      `extern`, and this will effectively be our handle to the "foreign"
//      static dispatcher.
//
//      We make the variable have type `DispatcherTag<__LINE__>` so that you
//      can use MKV_SWITCH_CREATE with the same name in different parts of the
//      translation-unit (without collision).
//
//   *  `GroupName_ ## _base` is used to declare a bunch of helpers; names that
//       must be available in our fake "lambdas" (C++03 is a pain).
// ----------------------------------------------------------------------------

#define MKV_SWITCH_CREATE(DispatchType_, GroupName_, PayloadType_) \
  typedef DispatcherTag<__LINE__> GroupName_ ## _tag_t; \
  extern GroupName_##_tag_t GroupName_ ## _tag; \
  struct GroupName_; \
  struct GroupName_##_base : DispatchContainer<GroupName_##_tag_t, &GroupName_##_tag, DispatchType_> { \
      typedef      PayloadType_ payload_t;                         \
      typedef     DispatchType_ dispatch_t;                        \
      typedef struct GroupName_ handler_t;                         \
      static void* Payload (payload_t& data) {                     \
          return static_cast<void*> (&data);                       \
      }                                                            \
  };                                                               \
  struct GroupName_ : GroupName_ ## _base

// ----------------------------------------------------------------------------
//   * `Dispatcher` is a static function used to access the dispatcher in a
//      thread-safe manner. We only want _one_ thread to actually construct
//      and initialize it, hence the lock.
// ----------------------------------------------------------------------------

#define MKV_SWITCH_INIT()                     \
  static dispatch_t& Dispatcher () {          \
      static handler_t * p_handler = NULL;    \
      vlc_mutex_lock( &_dispatcher_lock );    \
      if (unlikely( p_handler == NULL) ) {    \
          static handler_t handler;           \
          p_handler = &handler;               \
          p_handler->dispatcher.on_create (); \
      }                                       \
      vlc_mutex_unlock( &_dispatcher_lock );  \
      return p_handler->dispatcher;           \
  } struct PleaseAddSemicolon {}

// ----------------------------------------------------------------------------
//   * The following is to be used inside `struct GroupName_`, effectivelly
//     declaring a local struct and a data-member, `ClassName_ ## _processor`,
//     of that type.
//
//     When the data-member is constructed it will run `InitializationExpr_`,
//     meaning that it can access the static dispatcher and register itself (or
//     whatever is desired).
//
//   * Since we need to do type-erasure, once again, because of the fact that
//     C++03 does not support locally declared types as template-arguments, we
//     declare a static function `ClassName_ ## _callback` that will cast our
//     payload from `void*` to the appropriate type.
//
//   * The body of `ClassName_ ## _handler` will be written by the user of the
//     MACRO, and the implementation will effectively be invoked whenever the
//     dispatcher decides to (through `ClassName_ ## _callback`).
//
//   * Since the type of the `VariableName_` argument to `ClassName_ ## _handler`
//     might not necessarily be the same as the type passed from the dispatcher
//     (because of the type-erasure), the macro provides a way to change the
//     type with a `UnwrapExpr_` (see the function call within `ClassName_ ##
//     _callback`).
// ----------------------------------------------------------------------------

#define MKV_SWITCH_CASE_DEFINITION(ClassName_, RealType_, Type_, VariableName_, PayloadName_, InitializationExpr_, UnwrapExpr_) \
  struct ClassName_##_processor {                                             \
    ClassName_##_processor () { InitializationExpr_; }                        \
  } ClassName_##__wrapper;                                                    \
  static inline void ClassName_##_callback (Type_ data, void* PayloadName_) { \
    ClassName_##_handler (UnwrapExpr_, *static_cast<payload_t*>(PayloadName_));      \
  }                                                                             \
  static inline void ClassName_##_handler (RealType_& VariableName_, payload_t& PayloadName_)

#endif
<|endoftext|>


<commit_before>// =STS=> UDPsocket.cpp[1732].aa11   open     SMID:11
//////////////////////////////////////////////////////////////////////
//
// (c) Copyright 2003 Cyberkinetics, Inc.
//
// $Workfile: UDPsocket.cpp $
// $Archive: /Cerebus/WindowsApps/Central/UDPsocket.cpp $
// $Revision: 1 $
// $Date: 1/05/04 4:29p $
// $Author: Kkorver $
//
// $NoKeywords: $
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "debugmacs.h"
#include "UDPsocket.h"
#ifdef WIN32
#include <conio.h>
typedef int socklen_t;
#else
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
typedef struct sockaddr SOCKADDR;
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define FAR
#define SD_BOTH SHUT_RDWR
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

UDPSocket::UDPSocket() :
    m_nStartupOptionsFlags(OPT_NONE), m_bVerbose(false)
{
    inst_sock = INVALID_SOCKET;
}

UDPSocket::~UDPSocket()
{
    if (inst_sock != INVALID_SOCKET)
        Close();
}

// Author & Date:   Ehsan Azar     12 March 2010
// Purpose: Open a network UDP socket
// Inputs:
//  nStartupOptionsFlags - the network startup option
//  nRange               - the maximum allowed increments to the given IP address of the instrument to automatically connect to
//  bVerbose             - verbose mode
//  szInIP               - the IP of the instrument through which connects to me
//  szOutIP              - the IP of the instrument to connect to (it could be a subnet)
//  bBroadcast           - establish a broadcast socket
//  bDontRoute           - establish a direct socket with no routing or gateway
//  bNonBlocking         - establish a non-blocking socket
//  nRecBufSize          - the system receive-buffer size allocated for this socket
//  nInPort              - the input port through which instrument connects to me
//  nOutPort             - the output port to connect to in order to connect to the instrument
//  nPacketSize          - the maximum packet size that we receive
// Outputs:
//  Returns the error code (0 means success)
cbRESULT UDPSocket::Open(STARTUP_OPTIONS nStartupOptionsFlags, int nRange, bool bVerbose, LPCSTR szInIP,
          LPCSTR szOutIP, bool bBroadcast, bool bDontRoute, bool bNonBlocking,
          int nRecBufSize, int nInPort, int nOutPort, int nPacketSize)
{
    m_bVerbose = bVerbose;
    m_nPacketSize = nPacketSize;
    m_nStartupOptionsFlags = nStartupOptionsFlags;

#ifdef WIN32
    // Initialize Winsock 2.2
    WSADATA data;
    if (WSAStartup (MAKEWORD(2,0), &data) != 0)
        return cbRESULT_SOCKERR;
#endif

    // Create Socket for Receiving the Data Stream
#ifdef WIN32
    inst_sock = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
#else
    inst_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
#endif
    if (inst_sock == INVALID_SOCKET)
    {
        Close();
        return cbRESULT_SOCKERR;
    }

    BOOL opt_val = TRUE;
    socklen_t  opt_len = sizeof(BOOL);

    if (bBroadcast)
    {
        if (setsockopt(inst_sock, SOL_SOCKET, SO_BROADCAST, (char*)&opt_val, opt_len) != 0)
        {
            Close();
            return cbRESULT_SOCKOPTERR;
        }
    }

    if (bDontRoute)
    {
        if (setsockopt(inst_sock, SOL_SOCKET, SO_DONTROUTE, (char*)&opt_val, opt_len) != 0)
        {
            Close();
            return cbRESULT_SOCKOPTERR;
        }
    }

    if (nRecBufSize > 0)
    {
        // Set the data stream input buffer size
        opt_len = sizeof(int);
        int data_buff_size = nRecBufSize;
        if (setsockopt(inst_sock, SOL_SOCKET, SO_RCVBUF, (char*)&data_buff_size, opt_len) != 0)
        {
            Close();
            return cbRESULT_SOCKOPTERR;
        }
        if (getsockopt(inst_sock, SOL_SOCKET, SO_RCVBUF, (char *)&data_buff_size, &opt_len) != 0)
        {
            Close();
            return cbRESULT_SOCKOPTERR;
        }
#ifndef WIN32
        // Linux returns double the requested size up to twice the rmem_max
        data_buff_size /= 2;
#endif
        if (data_buff_size < nRecBufSize)
        {
            // to increase buffer
            // sysctl -w net.core.rmem_max=8388608
            //  or
            // sysctl -w kern.ipc.maxsockbuf=8388608
            Close();
            return cbRESULT_SOCKMEMERR;
        }
    }

    if (bNonBlocking)
    {
        // Set the data socket to non-blocking operation
#ifdef WIN32
        u_long arg_val = 1;
        if (ioctlsocket(inst_sock, FIONBIO, &arg_val) == SOCKET_ERROR)
#else
        if (fcntl(inst_sock, F_SETFL, O_NONBLOCK))
#endif
        {
            Close();
            return cbRESULT_SOCKOPTERR;
        }
    }

    // Attempt to bind Data Stream Socket to lowest address in range 192.168.137.1 to XXX.16
    BOOL socketbound = FALSE;
    SOCKADDR_IN inst_sockaddr = {0};

    inst_sockaddr.sin_family      = AF_INET;
    inst_sockaddr.sin_port        = htons(nInPort);    // Neuroflow Data Port
    if (szInIP == 0)
        inst_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    else
        inst_sockaddr.sin_addr.s_addr = inet_addr(szInIP);

    int nCount = 0;
    do
    {
        if (bind(inst_sock, (struct sockaddr FAR *)&inst_sockaddr, sizeof(inst_sockaddr)) == 0)
            socketbound = TRUE;
        else
        {
            // increment the last ip number
            inst_sockaddr.sin_addr.s_addr = htonl(ntohl(inst_sockaddr.sin_addr.s_addr) + 1);
        }
        nCount++;
    } while( (!socketbound) && (nCount <= nRange));

    if (socketbound)
    {
        // Set up transmission target address
        dest_sockaddr.sin_family      = AF_INET;
        dest_sockaddr.sin_port        = htons(nOutPort);	// Neuroflow Control Port
        dest_sockaddr.sin_addr.s_addr = inet_addr(szOutIP);	// Subnet Broadcast
    }
    else
    {
        if (OPT_NONE == nStartupOptionsFlags)
        {
            // if no valid address was found to bind the socket, shut her down and return error
            Close();
            return cbRESULT_SOCKBIND;
        }
        else
        {
            // if no valid address was found to bind the socket, just connect on any available
            // interface
            if (m_bVerbose)
                _cprintf("Warning: could not bind to socket on the subnet...\n");

            opt_len = sizeof(BOOL);
            if (setsockopt(inst_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&opt_val, opt_len) != 0)
            {
                if(m_bVerbose)
                    _cprintf("Error enabling address re-used\n");
                Close();
                return cbRESULT_SOCKOPTERR;
            }

            // Bind to the broadcast address
            if (OPT_LOOPBACK == nStartupOptionsFlags)
                inst_sockaddr.sin_addr.s_addr = inet_addr(LOOPBACK_ADDRESS);
            else
                inst_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

            int result = bind(inst_sock, (struct sockaddr FAR *)&inst_sockaddr, sizeof(inst_sockaddr));

            if (result == 0)
            {
                // Set up transmission target address
                //
                // Assume there's no cerebus subnet, so control packets should go to
                // broadcast
                dest_sockaddr.sin_family      = AF_INET;
                dest_sockaddr.sin_port        = htons(nOutPort); // Neuroflow Control Port

                if (OPT_LOOPBACK == nStartupOptionsFlags)
                    dest_sockaddr.sin_addr.s_addr = inet_addr(LOOPBACK_BROADCAST);
                else
                    dest_sockaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
            } else {      // if we still can't bind, it's an error
                Close();
                return cbRESULT_SOCKBIND;
            }
        }
    }
    if(m_bVerbose) {
        _cprintf("Successfully initialized network socket, bound to %s:%d\n",
        inet_ntoa(inst_sockaddr.sin_addr),(int)(ntohs(inst_sockaddr.sin_port)));

        _cprintf("Sending control packets to %s:%d\n",
        inet_ntoa(dest_sockaddr.sin_addr),(int)(ntohs(dest_sockaddr.sin_port)));
    }
    return cbRESULT_OK;
}

// Author & Date:   Ehsan Azar     13 Aug 2010
// Purpose: Change destination port number.
// Inputs:
//   nOutPort - new port number
void UDPSocket::OutPort(int nOutPort)
{
    dest_sockaddr.sin_port        = htons(nOutPort);
}

void UDPSocket::Close()
{
    shutdown(inst_sock, SD_BOTH); // shutdown communication
#ifdef WIN32
    closesocket(inst_sock);
    WSACleanup();
#else
    close(inst_sock);
#endif
    inst_sock = INVALID_SOCKET;
}

int UDPSocket::Recv(void * packet) const
{
    int ret = recv(inst_sock, (char*)packet, m_nPacketSize, 0);

    if (ret != SOCKET_ERROR)
        return ret; // This is actual size returned
    else
    {
        int err = 0;
#ifdef WIN32
        err = ::WSAGetLastError();
        if (err == WSAEWOULDBLOCK)
            return 0;
        TRACE("Socket Recv error was %i\n", err);
#else
        err = errno;
        if (err == EAGAIN)
            return 0;
        TRACE("Socket Recv error was %i\n", err);
#endif
        return 0;
    }
}

int UDPSocket::Send(void *ppkt, int cbBytes) const
{
    int sendRet = sendto(inst_sock, (const char *)ppkt, cbBytes, 0,
                         (SOCKADDR*)&dest_sockaddr, sizeof(dest_sockaddr));
#ifdef WIN32
    DEBUG_CODE
    (
        if (sendRet == SOCKET_ERROR) {
            TRACE("Socket Send error was %i\n", ::WSAGetLastError());
        }
    )
#else
    DEBUG_CODE
    (
        if (sendRet == SOCKET_ERROR) {
            TRACE("Socket Send error was %i\n", errno);
        }
    )
#endif

    return sendRet;

}
<commit_msg>OSX bind needs zero-initialization as well as filling sin_len<commit_after>// =STS=> UDPsocket.cpp[1732].aa11   open     SMID:11
//////////////////////////////////////////////////////////////////////
//
// (c) Copyright 2003 Cyberkinetics, Inc.
//
// $Workfile: UDPsocket.cpp $
// $Archive: /Cerebus/WindowsApps/Central/UDPsocket.cpp $
// $Revision: 1 $
// $Date: 1/05/04 4:29p $
// $Author: Kkorver $
//
// $NoKeywords: $
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "debugmacs.h"
#include "UDPsocket.h"
#ifdef WIN32
#include <conio.h>
typedef int socklen_t;
#else
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
typedef struct sockaddr SOCKADDR;
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define FAR
#define SD_BOTH SHUT_RDWR
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

UDPSocket::UDPSocket() :
    m_nStartupOptionsFlags(OPT_NONE), m_bVerbose(false)
{
    inst_sock = INVALID_SOCKET;
}

UDPSocket::~UDPSocket()
{
    if (inst_sock != INVALID_SOCKET)
        Close();
}

// Author & Date:   Ehsan Azar     12 March 2010
// Purpose: Open a network UDP socket
// Inputs:
//  nStartupOptionsFlags - the network startup option
//  nRange               - the maximum allowed increments to the given IP address of the instrument to automatically connect to
//  bVerbose             - verbose mode
//  szInIP               - the IP of the instrument through which connects to me
//  szOutIP              - the IP of the instrument to connect to (it could be a subnet)
//  bBroadcast           - establish a broadcast socket
//  bDontRoute           - establish a direct socket with no routing or gateway
//  bNonBlocking         - establish a non-blocking socket
//  nRecBufSize          - the system receive-buffer size allocated for this socket
//  nInPort              - the input port through which instrument connects to me
//  nOutPort             - the output port to connect to in order to connect to the instrument
//  nPacketSize          - the maximum packet size that we receive
// Outputs:
//  Returns the error code (0 means success)
cbRESULT UDPSocket::Open(STARTUP_OPTIONS nStartupOptionsFlags, int nRange, bool bVerbose, LPCSTR szInIP,
          LPCSTR szOutIP, bool bBroadcast, bool bDontRoute, bool bNonBlocking,
          int nRecBufSize, int nInPort, int nOutPort, int nPacketSize)
{
    m_bVerbose = bVerbose;
    m_nPacketSize = nPacketSize;
    m_nStartupOptionsFlags = nStartupOptionsFlags;

#ifdef WIN32
    // Initialize Winsock 2.2
    WSADATA data;
    if (WSAStartup (MAKEWORD(2,0), &data) != 0)
        return cbRESULT_SOCKERR;
#endif

    // Create Socket for Receiving the Data Stream
#ifdef WIN32
    inst_sock = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
#else
    inst_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
#endif
    if (inst_sock == INVALID_SOCKET)
    {
        Close();
        return cbRESULT_SOCKERR;
    }

    BOOL opt_val = TRUE;
    socklen_t  opt_len = sizeof(BOOL);

    if (bBroadcast)
    {
        if (setsockopt(inst_sock, SOL_SOCKET, SO_BROADCAST, (char*)&opt_val, opt_len) != 0)
        {
            Close();
            return cbRESULT_SOCKOPTERR;
        }
    }

    if (bDontRoute)
    {
        if (setsockopt(inst_sock, SOL_SOCKET, SO_DONTROUTE, (char*)&opt_val, opt_len) != 0)
        {
            Close();
            return cbRESULT_SOCKOPTERR;
        }
    }

    if (nRecBufSize > 0)
    {
        // Set the data stream input buffer size
        opt_len = sizeof(int);
        int data_buff_size = nRecBufSize;
        if (setsockopt(inst_sock, SOL_SOCKET, SO_RCVBUF, (char*)&data_buff_size, opt_len) != 0)
        {
            Close();
            return cbRESULT_SOCKOPTERR;
        }
        if (getsockopt(inst_sock, SOL_SOCKET, SO_RCVBUF, (char *)&data_buff_size, &opt_len) != 0)
        {
            Close();
            return cbRESULT_SOCKOPTERR;
        }
#ifndef WIN32
        // Linux returns double the requested size up to twice the rmem_max
        data_buff_size /= 2;
#endif
        if (data_buff_size < nRecBufSize)
        {
            // to increase buffer
            // sysctl -w net.core.rmem_max=8388608
            //  or
            // sysctl -w kern.ipc.maxsockbuf=8388608
            Close();
            return cbRESULT_SOCKMEMERR;
        }
    }

    if (bNonBlocking)
    {
        // Set the data socket to non-blocking operation
#ifdef WIN32
        u_long arg_val = 1;
        if (ioctlsocket(inst_sock, FIONBIO, &arg_val) == SOCKET_ERROR)
#else
        if (fcntl(inst_sock, F_SETFL, O_NONBLOCK))
#endif
        {
            Close();
            return cbRESULT_SOCKOPTERR;
        }
    }

    // Attempt to bind Data Stream Socket to lowest address in range 192.168.137.1 to XXX.16
    BOOL socketbound = FALSE;
    SOCKADDR_IN inst_sockaddr;
    memset(&inst_sockaddr, 0, sizeof(inst_sockaddr));

    inst_sockaddr.sin_family      = AF_INET;
    inst_sockaddr.sin_port        = htons(nInPort);    // Neuroflow Data Port
#ifdef __APPLE__
	inst_sockaddr.sin_len = sizeof(inst_sockaddr);
#endif
    if (szInIP == 0)
        inst_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    else
        inst_sockaddr.sin_addr.s_addr = inet_addr(szInIP);

    int nCount = 0;
    do
    {
        if (bind(inst_sock, (struct sockaddr FAR *)&inst_sockaddr, sizeof(inst_sockaddr)) == 0)
            socketbound = TRUE;
        else
        {
            // increment the last ip number
            inst_sockaddr.sin_addr.s_addr = htonl(ntohl(inst_sockaddr.sin_addr.s_addr) + 1);
        }
        nCount++;
    } while( (!socketbound) && (nCount <= nRange));

    if (socketbound)
    {
        // Set up transmission target address
        dest_sockaddr.sin_family      = AF_INET;
        dest_sockaddr.sin_port        = htons(nOutPort);	// Neuroflow Control Port
        dest_sockaddr.sin_addr.s_addr = inet_addr(szOutIP);	// Subnet Broadcast
    }
    else
    {
        if (OPT_NONE == nStartupOptionsFlags)
        {
            // if no valid address was found to bind the socket, shut her down and return error
            Close();
            return cbRESULT_SOCKBIND;
        }
        else
        {
            // if no valid address was found to bind the socket, just connect on any available
            // interface
            if (m_bVerbose)
                _cprintf("Warning: could not bind to socket on the subnet...\n");

            opt_len = sizeof(BOOL);
            if (setsockopt(inst_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&opt_val, opt_len) != 0)
            {
                if(m_bVerbose)
                    _cprintf("Error enabling address re-used\n");
                Close();
                return cbRESULT_SOCKOPTERR;
            }

            // Bind to the broadcast address
            if (OPT_LOOPBACK == nStartupOptionsFlags)
                inst_sockaddr.sin_addr.s_addr = inet_addr(LOOPBACK_ADDRESS);
            else
                inst_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

            int result = bind(inst_sock, (struct sockaddr FAR *)&inst_sockaddr, sizeof(inst_sockaddr));

            if (result == 0)
            {
                // Set up transmission target address
                //
                // Assume there's no cerebus subnet, so control packets should go to
                // broadcast
                dest_sockaddr.sin_family      = AF_INET;
                dest_sockaddr.sin_port        = htons(nOutPort); // Neuroflow Control Port

                if (OPT_LOOPBACK == nStartupOptionsFlags)
                    dest_sockaddr.sin_addr.s_addr = inet_addr(LOOPBACK_BROADCAST);
                else
                    dest_sockaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
            } else {      // if we still can't bind, it's an error
                Close();
                return cbRESULT_SOCKBIND;
            }
        }
    }
    if(m_bVerbose) {
        _cprintf("Successfully initialized network socket, bound to %s:%d\n",
        inet_ntoa(inst_sockaddr.sin_addr),(int)(ntohs(inst_sockaddr.sin_port)));

        _cprintf("Sending control packets to %s:%d\n",
        inet_ntoa(dest_sockaddr.sin_addr),(int)(ntohs(dest_sockaddr.sin_port)));
    }
    return cbRESULT_OK;
}

// Author & Date:   Ehsan Azar     13 Aug 2010
// Purpose: Change destination port number.
// Inputs:
//   nOutPort - new port number
void UDPSocket::OutPort(int nOutPort)
{
    dest_sockaddr.sin_port        = htons(nOutPort);
}

void UDPSocket::Close()
{
    shutdown(inst_sock, SD_BOTH); // shutdown communication
#ifdef WIN32
    closesocket(inst_sock);
    WSACleanup();
#else
    close(inst_sock);
#endif
    inst_sock = INVALID_SOCKET;
}

int UDPSocket::Recv(void * packet) const
{
    int ret = recv(inst_sock, (char*)packet, m_nPacketSize, 0);

    if (ret != SOCKET_ERROR)
        return ret; // This is actual size returned
    else
    {
        int err = 0;
#ifdef WIN32
        err = ::WSAGetLastError();
        if (err == WSAEWOULDBLOCK)
            return 0;
        TRACE("Socket Recv error was %i\n", err);
#else
        err = errno;
        if (err == EAGAIN)
            return 0;
        TRACE("Socket Recv error was %i\n", err);
#endif
        return 0;
    }
}

int UDPSocket::Send(void *ppkt, int cbBytes) const
{
    int sendRet = sendto(inst_sock, (const char *)ppkt, cbBytes, 0,
                         (SOCKADDR*)&dest_sockaddr, sizeof(dest_sockaddr));
#ifdef WIN32
    DEBUG_CODE
    (
        if (sendRet == SOCKET_ERROR) {
            TRACE("Socket Send error was %i\n", ::WSAGetLastError());
        }
    )
#else
    DEBUG_CODE
    (
        if (sendRet == SOCKET_ERROR) {
            TRACE("Socket Send error was %i\n", errno);
        }
    )
#endif

    return sendRet;

}
<|endoftext|>


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

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

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

You should have received a copy of the GNU General Public License
along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file whisperMessage.cpp
* @author Vladislav Gluhovsky <vlad@ethdev.com>
* @date June 2015
*/

#include <boost/test/unit_test.hpp>
#include <libdevcore/SHA3.h>
#include <libwhisper/BloomFilter.h>

using namespace std;
using namespace dev;
using namespace dev::shh;

using TopicBloomFilterShort = TopicBloomFilterBase<4>;
using TopicBloomFilterTest = TopicBloomFilterBase<c_topicBloomFilterSize>;

void testAddNonExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(!_f.containsRaw(_h));
	_f.addRaw(_h);
	BOOST_REQUIRE(_f.containsRaw(_h));
}

void testRemoveExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(_f.containsRaw(_h));
	_f.removeRaw(_h);
	BOOST_REQUIRE(!_f.containsRaw(_h));
}

void testAddNonExistingBloom(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(!_f.containsBloom(_h));
	_f.addBloom(_h);
	BOOST_REQUIRE(_f.containsBloom(_h));
}

void testRemoveExistingBloom(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(_f.containsBloom(_h));
	_f.removeBloom(_h);
	BOOST_REQUIRE(!_f.containsBloom(_h));
}

double calculateExpected(TopicBloomFilterTest const& f, int n)
{
	int const m = f.size * 8; // number of bits in the bloom
	int const k = f.BitsPerBloom; // number of hash functions (e.g. bits set to 1 in every bloom)

	double singleBitSet = 1.0 / m; // probability of any bit being set after inserting a single bit
	double singleBitNotSet = (1.0 - singleBitSet);

	double singleNot = 1; // single bit not set after inserting N elements in the bloom filter
	for (int i = 0; i < k * n; ++i)
		singleNot *= singleBitNotSet;

	double single = 1.0 - singleNot; // probability of a single bit being set after inserting N elements in the bloom filter

	double kBitsSet = 1; // probability of K bits being set after inserting N elements in the bloom filter
	for (int i = 0; i < k; ++i)
		kBitsSet *= single;

	return kBitsSet;
}

double testFalsePositiveRate(TopicBloomFilterTest const& f, int inserted, Topic& x)
{
	int const c_sampleSize = 1000;
	int falsePositive = 0;

	for (int i = 0; i < c_sampleSize; ++i)
	{
		x = sha3(x);
		AbridgedTopic a(x);
		if (f.containsBloom(a))
			++falsePositive;
	}

	double res = double(falsePositive) / double(c_sampleSize);

	double expected = calculateExpected(f, inserted);
	double allowed = expected * 1.2 + 0.05; // allow deviations ~25%

	//cnote << "Inserted: " << inserted << ", False Positive Rate: " << res << ", Expected: " << expected;
	BOOST_REQUIRE(res <= allowed);
	return expected;
}

BOOST_AUTO_TEST_SUITE(bloomFilter)

BOOST_AUTO_TEST_CASE(falsePositiveRate)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Bloom Filter False Positive Rate...";

	TopicBloomFilterTest f;
	Topic x(0xC0DEFEED); // deterministic pseudorandom value

	double expectedRate = 0;

	for (int i = 1; i < 50 && isless(expectedRate, 0.5); ++i)
	{
		x = sha3(x);
		f.addBloom(AbridgedTopic(x));
		expectedRate = testFalsePositiveRate(f, i, x);
	}
}

BOOST_AUTO_TEST_CASE(bloomFilterRandom)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Bloom Filter matching...";

	TopicBloomFilterShort f;
	vector<AbridgedTopic> vec;
	Topic x(0xDEADBEEF);
	int const c_rounds = 4;

	for (int i = 0; i < c_rounds; ++i, x = sha3(x))
		vec.push_back(abridge(x));

	for (int i = 0; i < c_rounds; ++i)
		testAddNonExisting(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testRemoveExisting(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testAddNonExistingBloom(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testRemoveExistingBloom(f, vec[i]);
}

BOOST_AUTO_TEST_CASE(bloomFilterRaw)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Raw Bloom matching...";

	TopicBloomFilterShort f;

	AbridgedTopic b00000001(0x01);
	AbridgedTopic b00010000(0x10);
	AbridgedTopic b00011000(0x18);
	AbridgedTopic b00110000(0x30);
	AbridgedTopic b00110010(0x32);
	AbridgedTopic b00111000(0x38);
	AbridgedTopic b00000110(0x06);
	AbridgedTopic b00110110(0x36);
	AbridgedTopic b00110111(0x37);

	testAddNonExisting(f, b00000001);
	testAddNonExisting(f, b00010000);
	testAddNonExisting(f, b00011000);
	testAddNonExisting(f, b00110000);
	BOOST_REQUIRE(f.contains(b00111000));
	testAddNonExisting(f, b00110010);
	testAddNonExisting(f, b00000110);
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(f.contains(b00110111));

	f.removeRaw(b00000001);
	f.removeRaw(b00000001);
	f.removeRaw(b00000001);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00010000);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00111000);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.addRaw(b00000001);
	BOOST_REQUIRE(f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(f.contains(b00110111));

	f.removeRaw(b00110111);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(!f.contains(b00110000));
	BOOST_REQUIRE(!f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(!f.contains(b00000110));
	BOOST_REQUIRE(!f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00110111);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(!f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(!f.contains(b00110000));
	BOOST_REQUIRE(!f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(!f.contains(b00000110));
	BOOST_REQUIRE(!f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));
}

enum { DistributionTestSize = 8 };

void updateDistribution(FixedHash<DistributionTestSize> const& _h, unsigned* _distribution)
{
	unsigned bits = 0;
	for (unsigned i = 0; i < DistributionTestSize; ++i)
		if (_h[i])
			for (unsigned j = 0; j < 8; ++j)
				if (_h[i] & c_powerOfTwoBitMmask[j])
				{
					_distribution[i * 8 + j]++;
					if (++bits >= TopicBloomFilterTest::BitsPerBloom)
						return;
				}
}

BOOST_AUTO_TEST_CASE(distributionRate)
{
	cnote << "Testing Bloom Filter Distribution Rate...";

	unsigned const c_arrSize = DistributionTestSize * 8;
	unsigned distribution[c_arrSize];
	memset(distribution, 0, c_arrSize * sizeof(unsigned));
	Topic x(0xC0FFEE); // deterministic pseudorandom value

	for (unsigned i = 0; i < 22000; ++i)
	{
		x = sha3(x);
		FixedHash<DistributionTestSize> h = x.template bloomPart<TopicBloomFilterTest::BitsPerBloom, DistributionTestSize>();
		updateDistribution(h, distribution);
	}

	unsigned average = 0;
	for (unsigned i = 0; i < c_arrSize; ++i)
		average += distribution[i];

	average /= c_arrSize;
	unsigned deviation = average / 10; // approx. 10%
	unsigned maxAllowed = average + deviation;
	unsigned minAllowed = average - deviation;

	for (unsigned i = 0; i < c_arrSize; ++i)
	{
		//cnote << i << ":" << distribution[i];
		BOOST_REQUIRE(distribution[i] > minAllowed);
		BOOST_REQUIRE(distribution[i] < maxAllowed);
	}
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>style fix<commit_after>/*
This file is part of cpp-ethereum.

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

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

You should have received a copy of the GNU General Public License
along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file whisperMessage.cpp
* @author Vladislav Gluhovsky <vlad@ethdev.com>
* @date June 2015
*/

#include <boost/test/unit_test.hpp>
#include <libdevcore/SHA3.h>
#include <libwhisper/BloomFilter.h>

using namespace std;
using namespace dev;
using namespace dev::shh;

using TopicBloomFilterShort = TopicBloomFilterBase<4>;
using TopicBloomFilterTest = TopicBloomFilterBase<c_topicBloomFilterSize>;

void testAddNonExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(!_f.containsRaw(_h));
	_f.addRaw(_h);
	BOOST_REQUIRE(_f.containsRaw(_h));
}

void testRemoveExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(_f.containsRaw(_h));
	_f.removeRaw(_h);
	BOOST_REQUIRE(!_f.containsRaw(_h));
}

void testAddNonExistingBloom(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(!_f.containsBloom(_h));
	_f.addBloom(_h);
	BOOST_REQUIRE(_f.containsBloom(_h));
}

void testRemoveExistingBloom(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(_f.containsBloom(_h));
	_f.removeBloom(_h);
	BOOST_REQUIRE(!_f.containsBloom(_h));
}

double calculateExpected(TopicBloomFilterTest const& f, int n)
{
	int const m = f.size * 8; // number of bits in the bloom
	int const k = f.BitsPerBloom; // number of hash functions (e.g. bits set to 1 in every bloom)

	double singleBitSet = 1.0 / m; // probability of any bit being set after inserting a single bit
	double singleBitNotSet = (1.0 - singleBitSet);

	double singleNot = 1; // single bit not set after inserting N elements in the bloom filter
	for (int i = 0; i < k * n; ++i)
		singleNot *= singleBitNotSet;

	double single = 1.0 - singleNot; // probability of a single bit being set after inserting N elements in the bloom filter

	double kBitsSet = 1; // probability of K bits being set after inserting N elements in the bloom filter
	for (int i = 0; i < k; ++i)
		kBitsSet *= single;

	return kBitsSet;
}

double testFalsePositiveRate(TopicBloomFilterTest const& f, int inserted, Topic& x)
{
	int const c_sampleSize = 1000;
	int falsePositive = 0;

	for (int i = 0; i < c_sampleSize; ++i)
	{
		x = sha3(x);
		AbridgedTopic a(x);
		if (f.containsBloom(a))
			++falsePositive;
	}

	double res = double(falsePositive) / double(c_sampleSize);

	double expected = calculateExpected(f, inserted);
	double allowed = expected * 1.2 + 0.05; // allow deviations ~25%

	//cnote << "Inserted: " << inserted << ", False Positive Rate: " << res << ", Expected: " << expected;
	BOOST_REQUIRE(res <= allowed);
	return expected;
}

BOOST_AUTO_TEST_SUITE(bloomFilter)

BOOST_AUTO_TEST_CASE(falsePositiveRate)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Bloom Filter False Positive Rate...";

	TopicBloomFilterTest f;
	Topic x(0xC0DEFEED); // deterministic pseudorandom value

	double expectedRate = 0;

	for (int i = 1; i < 50 && isless(expectedRate, 0.5); ++i)
	{
		x = sha3(x);
		f.addBloom(AbridgedTopic(x));
		expectedRate = testFalsePositiveRate(f, i, x);
	}
}

BOOST_AUTO_TEST_CASE(bloomFilterRandom)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Bloom Filter matching...";

	TopicBloomFilterShort f;
	vector<AbridgedTopic> vec;
	Topic x(0xDEADBEEF);
	int const c_rounds = 4;

	for (int i = 0; i < c_rounds; ++i, x = sha3(x))
		vec.push_back(abridge(x));

	for (int i = 0; i < c_rounds; ++i)
		testAddNonExisting(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testRemoveExisting(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testAddNonExistingBloom(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testRemoveExistingBloom(f, vec[i]);
}

BOOST_AUTO_TEST_CASE(bloomFilterRaw)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Raw Bloom matching...";

	TopicBloomFilterShort f;

	AbridgedTopic b00000001(0x01);
	AbridgedTopic b00010000(0x10);
	AbridgedTopic b00011000(0x18);
	AbridgedTopic b00110000(0x30);
	AbridgedTopic b00110010(0x32);
	AbridgedTopic b00111000(0x38);
	AbridgedTopic b00000110(0x06);
	AbridgedTopic b00110110(0x36);
	AbridgedTopic b00110111(0x37);

	testAddNonExisting(f, b00000001);
	testAddNonExisting(f, b00010000);
	testAddNonExisting(f, b00011000);
	testAddNonExisting(f, b00110000);
	BOOST_REQUIRE(f.contains(b00111000));
	testAddNonExisting(f, b00110010);
	testAddNonExisting(f, b00000110);
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(f.contains(b00110111));

	f.removeRaw(b00000001);
	f.removeRaw(b00000001);
	f.removeRaw(b00000001);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00010000);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00111000);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.addRaw(b00000001);
	BOOST_REQUIRE(f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(f.contains(b00110111));

	f.removeRaw(b00110111);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(!f.contains(b00110000));
	BOOST_REQUIRE(!f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(!f.contains(b00000110));
	BOOST_REQUIRE(!f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00110111);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(!f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(!f.contains(b00110000));
	BOOST_REQUIRE(!f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(!f.contains(b00000110));
	BOOST_REQUIRE(!f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));
}

static unsigned const DistributionTestSize = 8;

void updateDistribution(FixedHash<DistributionTestSize> const& _h, unsigned* _distribution)
{
	unsigned bits = 0;
	for (unsigned i = 0; i < DistributionTestSize; ++i)
		if (_h[i])
			for (unsigned j = 0; j < 8; ++j)
				if (_h[i] & c_powerOfTwoBitMmask[j])
				{
					_distribution[i * 8 + j]++;
					if (++bits >= TopicBloomFilterTest::BitsPerBloom)
						return;
				}
}

BOOST_AUTO_TEST_CASE(distributionRate)
{
	cnote << "Testing Bloom Filter Distribution Rate...";

	unsigned const c_arrSize = DistributionTestSize * 8;
	unsigned distribution[c_arrSize];
	memset(distribution, 0, c_arrSize * sizeof(unsigned));
	Topic x(0xC0FFEE); // deterministic pseudorandom value

	for (unsigned i = 0; i < 22000; ++i)
	{
		x = sha3(x);
		FixedHash<DistributionTestSize> h = x.template bloomPart<TopicBloomFilterTest::BitsPerBloom, DistributionTestSize>();
		updateDistribution(h, distribution);
	}

	unsigned average = 0;
	for (unsigned i = 0; i < c_arrSize; ++i)
		average += distribution[i];

	average /= c_arrSize;
	unsigned deviation = average / 10; // approx. 10%
	unsigned maxAllowed = average + deviation;
	unsigned minAllowed = average - deviation;

	for (unsigned i = 0; i < c_arrSize; ++i)
	{
		//cnote << i << ":" << distribution[i];
		BOOST_REQUIRE(distribution[i] > minAllowed);
		BOOST_REQUIRE(distribution[i] < maxAllowed);
	}
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "MainScene.h"
#include <random>

USING_NS_CC;

Scene* MainScene::createScene()
{
	auto scene = Scene::create();

	auto layer = MainScene::create();

	scene->addChild(layer);

	return scene;
}

bool MainScene::init()
{
	if( !Layer::init() )
		return false;

	auto visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();

	auto label = Label::createWithTTF("世界,你好", "fonts/SIMLI.TTF", 24);
	label->setColor(Color3B::RED);
	label->setPosition(Vec2(origin.x + visibleSize.width / 2,
		origin.y + visibleSize.height - label->getContentSize().height));
	this->addChild(label,0);

	std::random_device rd;						//采用非确定性随机数发生器产生随机数种子
	std::default_random_engine gen(rd());		//采用默认随机数引擎产生随机数
	std::uniform_int_distribution<> unif_x(origin.x, origin.x + visibleSize.width);		//采用整数均匀分布器产生x均匀分布的随机数
	std::uniform_int_distribution<> unif_y(origin.y, origin.y + visibleSize.height);		//采用整数均匀分布器产生y均匀分布的随机数

	for (int i = 0; i < 5; i++)
	{
		Airplane* plane;
		plane = Airplane::createPlane("Picture/airplane.png");
		plane->setScale(0.1, 0.1);
		plane->setPosition(unif_x(gen), unif_y(gen));
		this->addChild(plane);
		this->my_planes.push_back(plane);
	}

	for (int i = 0; i < 5; i++)
	{
		Airplane* plane;
		plane = Airplane::createPlane("Picture/airplane_red.png");
		plane->setScale(0.1, 0.1);
		plane->setPosition(unif_x(gen), unif_y(gen));
		this->addChild(plane);
		this->enemy_planes.push_back(plane);
	}

	this->schedule(schedule_selector(MainScene::update));

	auto listen = EventListenerTouchOneByOne::create();
	listen->onTouchBegan = CC_CALLBACK_2(MainScene::onTouchBegan, this);
	listen->onTouchMoved = CC_CALLBACK_2(MainScene::onTouchMoved, this);
	listen->onTouchEnded = CC_CALLBACK_2(MainScene::onTouchEnded, this);
	listen->setSwallowTouches(true);
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen, this);

	return true;

}

void MainScene::update(float f)
{
	for (auto my_plane : this->my_planes)
		if (my_plane->isActive())
			my_plane->update();

	//log("touch point:%f,%f",touchPoint.x,touchPoint.y);
}

bool MainScene::onTouchBegan(cocos2d::Touch* pTouch, cocos2d::Event*)
{

	Point touch = pTouch->getLocation();//返回点击的位置
	this->touchPoint = touch;

	for (auto my_plane : this->my_planes)
		if (my_plane->getBoundingBox().containsPoint(touch))
		{
			for (auto other_plane : this->my_planes)
				other_plane->unselect();
			my_plane->select();
			this->state = 1;
			return true;
		}

	return true;
}

void MainScene::onTouchMoved(cocos2d::Touch* pTouch, cocos2d::Event* pEvent)
{
	Point touch = pTouch->getLocation();//返回点击的位置

	if (state != 2)
	{
		this->mouse_rect = DrawNode::create();
		this->addChild(this->mouse_rect, 2);
	}

	this->state = 2;

	this->mouse_rect->clear();
	Vec2 mouse_rect_points[4];
	mouse_rect_points[0] = this->touchPoint;
	mouse_rect_points[1] = Vec2(this->touchPoint.x, touch.y);
	mouse_rect_points[2] = touch;
	mouse_rect_points[3] = Vec2(touch.x, this->touchPoint.y);

	//绘制空心多边形
	//填充颜色：Color4F(1, 0, 0, 0), 透明
	//轮廓颜色：Color4F(0, 1, 0, 1), 绿色
	this->mouse_rect->drawPolygon(mouse_rect_points, 4, Color4F(1, 0, 0, 0), 1, Color4F(0, 1, 0, 1));
}

void MainScene::onTouchEnded(cocos2d::Touch* pTouch, cocos2d::Event* pEvent)
{
	if (this->state == 1)
	{
		Point touch = pTouch->getLocation();//返回点击的位置
		for (auto my_plane : my_planes)
			if (my_plane->isSelected())
			{
				my_plane->setDest(touch);
				my_plane->activate();
			}
	}

	if (this->state == 2)
	{
		this->removeChild(this->mouse_rect);
		this->state = 1;

		Point touch = pTouch->getLocation();//返回点击的位置

		Rect select_rect{ MIN(this->touchPoint.x, touch.x), MIN(this->touchPoint.y, touch.y), abs(this->touchPoint.x - touch.x), abs(this->touchPoint.y - touch.y) };

		for (auto other_plane : this->my_planes)
			other_plane->unselect();

		for (auto my_plane : my_planes)
		{
			if (select_rect.containsPoint(my_plane->getPosition()))
				my_plane->select();
		}
	}
}

void Airplane::update()
{
	if (selected)
		if ((dest - getPosition()).getLength() < 10)
			active = 0;
		else
		{
			active = 1;
			auto esp = (dest - getPosition()).getNormalized();
			setPosition(getPosition() + esp * move_speed);
		}
}<commit_msg>Correct airplane moving<commit_after>#include "MainScene.h"
#include <random>

USING_NS_CC;

Scene* MainScene::createScene()
{
	auto scene = Scene::create();

	auto layer = MainScene::create();

	scene->addChild(layer);

	return scene;
}

bool MainScene::init()
{
	if( !Layer::init() )
		return false;

	auto visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();

	auto label = Label::createWithTTF("世界,你好", "fonts/SIMLI.TTF", 24);
	label->setColor(Color3B::RED);
	label->setPosition(Vec2(origin.x + visibleSize.width / 2,
		origin.y + visibleSize.height - label->getContentSize().height));
	this->addChild(label,0);

	std::random_device rd;						//采用非确定性随机数发生器产生随机数种子
	std::default_random_engine gen(rd());		//采用默认随机数引擎产生随机数
	std::uniform_int_distribution<> unif_x(origin.x, origin.x + visibleSize.width);		//采用整数均匀分布器产生x均匀分布的随机数
	std::uniform_int_distribution<> unif_y(origin.y, origin.y + visibleSize.height);		//采用整数均匀分布器产生y均匀分布的随机数

	for (int i = 0; i < 5; i++)
	{
		Airplane* plane;
		plane = Airplane::createPlane("Picture/airplane.png");
		plane->setScale(0.1, 0.1);
		plane->setPosition(unif_x(gen), unif_y(gen));
		this->addChild(plane);
		this->my_planes.push_back(plane);
	}

	for (int i = 0; i < 5; i++)
	{
		Airplane* plane;
		plane = Airplane::createPlane("Picture/airplane_red.png");
		plane->setScale(0.1, 0.1);
		plane->setPosition(unif_x(gen), unif_y(gen));
		this->addChild(plane);
		this->enemy_planes.push_back(plane);
	}

	this->schedule(schedule_selector(MainScene::update));

	auto listen = EventListenerTouchOneByOne::create();
	listen->onTouchBegan = CC_CALLBACK_2(MainScene::onTouchBegan, this);
	listen->onTouchMoved = CC_CALLBACK_2(MainScene::onTouchMoved, this);
	listen->onTouchEnded = CC_CALLBACK_2(MainScene::onTouchEnded, this);
	listen->setSwallowTouches(true);
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen, this);

	return true;

}

void MainScene::update(float f)
{
	for (auto my_plane : this->my_planes)
		if (my_plane->isActive())
			my_plane->update();

	//log("touch point:%f,%f",touchPoint.x,touchPoint.y);
}

bool MainScene::onTouchBegan(cocos2d::Touch* pTouch, cocos2d::Event*)
{

	Point touch = pTouch->getLocation();//返回点击的位置
	this->touchPoint = touch;

	for (auto my_plane : this->my_planes)
		if (my_plane->getBoundingBox().containsPoint(touch))
		{
			for (auto other_plane : this->my_planes)
				other_plane->unselect();
			my_plane->select();
			this->state = 1;
			return true;
		}

	return true;
}

void MainScene::onTouchMoved(cocos2d::Touch* pTouch, cocos2d::Event* pEvent)
{
	Point touch = pTouch->getLocation();//返回点击的位置

	if (state != 2)
	{
		this->mouse_rect = DrawNode::create();
		this->addChild(this->mouse_rect, 2);
	}

	this->state = 2;

	this->mouse_rect->clear();
	Vec2 mouse_rect_points[4];
	mouse_rect_points[0] = this->touchPoint;
	mouse_rect_points[1] = Vec2(this->touchPoint.x, touch.y);
	mouse_rect_points[2] = touch;
	mouse_rect_points[3] = Vec2(touch.x, this->touchPoint.y);

	//绘制空心多边形
	//填充颜色：Color4F(1, 0, 0, 0), 透明
	//轮廓颜色：Color4F(0, 1, 0, 1), 绿色
	this->mouse_rect->drawPolygon(mouse_rect_points, 4, Color4F(1, 0, 0, 0), 1, Color4F(0, 1, 0, 1));
}

void MainScene::onTouchEnded(cocos2d::Touch* pTouch, cocos2d::Event* pEvent)
{
	if (this->state == 1)
	{
		Point touch = pTouch->getLocation();//返回点击的位置
		for (auto my_plane : my_planes)
			if (my_plane->isSelected())
			{
				my_plane->setDest(touch);
				my_plane->activate();
			}
	}

	if (this->state == 2)
	{
		this->removeChild(this->mouse_rect);
		this->state = 1;

		Point touch = pTouch->getLocation();//返回点击的位置

		Rect select_rect{ MIN(this->touchPoint.x, touch.x), MIN(this->touchPoint.y, touch.y), abs(this->touchPoint.x - touch.x), abs(this->touchPoint.y - touch.y) };

		for (auto other_plane : this->my_planes)
			other_plane->unselect();

		for (auto my_plane : my_planes)
		{
			if (select_rect.containsPoint(my_plane->getPosition()))
				my_plane->select();
		}
	}
}

void Airplane::update()
{
	if ((dest - getPosition()).getLength() < 10)
		active = 0;
	else
	{
		active = 1;
		auto esp = (dest - getPosition()).getNormalized();
		setPosition(getPosition() + esp * move_speed);
	}
}<|endoftext|>


<commit_before>// @(#)root/mathmore:$Name:  $:$Id: ProbFuncMathMore.cxx,v 1.1 2005/09/08 07:14:56 brun Exp $
// Authors: L. Moneta, A. Zsenei   08/2005

#include <cmath>
#include "Math/ProbFuncMathMore.h"
#include "cdf/gsl_cdf.h"

namespace ROOT {
namespace Math {

  double chisquared_prob(double x, double r, double x0) {

    return gsl_cdf_chisq_Q(x-x0, r);

  }

  double chisquared_quant(double x, double r, double x0) {

    return gsl_cdf_chisq_P(x-x0, r);

  }

  double fdistribution_prob(double x, double n, double m, double x0) {

    return gsl_cdf_fdist_Q(x-x0, n, m);

  }

  double fdistribution_quant(double x, double n, double m, double x0) {

    return gsl_cdf_fdist_P(x-x0, n, m);

  }

  double gamma_prob(double x, double alpha, double theta, double x0) {

    return gsl_cdf_gamma_Q(x-x0, alpha, theta);

  }

  double gamma_quant(double x, double alpha, double theta, double x0) {

    return gsl_cdf_gamma_P(x-x0, alpha, theta);

  }

  double tdistribution_prob(double x, double r, double x0) {

    return gsl_cdf_tdist_Q(x-x0, r);

  }

  double tdistribution_quant(double x, double r, double x0) {

    return gsl_cdf_tdist_P(x-x0, r);

  }

} // namespace Math
} // namespace ROOT

<commit_msg>use correct exposed gsl include file and not internal one<commit_after>// @(#)root/mathmore:$Name:  $:$Id: ProbFuncMathMore.cxx,v 1.2 2005/09/18 20:41:25 brun Exp $
// Authors: L. Moneta, A. Zsenei   08/2005

#include <cmath>
#include "Math/ProbFuncMathMore.h"
#include "gsl/gsl_cdf.h"

namespace ROOT {
namespace Math {

  double chisquared_prob(double x, double r, double x0) {

    return gsl_cdf_chisq_Q(x-x0, r);

  }

  double chisquared_quant(double x, double r, double x0) {

    return gsl_cdf_chisq_P(x-x0, r);

  }

  double fdistribution_prob(double x, double n, double m, double x0) {

    return gsl_cdf_fdist_Q(x-x0, n, m);

  }

  double fdistribution_quant(double x, double n, double m, double x0) {

    return gsl_cdf_fdist_P(x-x0, n, m);

  }

  double gamma_prob(double x, double alpha, double theta, double x0) {

    return gsl_cdf_gamma_Q(x-x0, alpha, theta);

  }

  double gamma_quant(double x, double alpha, double theta, double x0) {

    return gsl_cdf_gamma_P(x-x0, alpha, theta);

  }

  double tdistribution_prob(double x, double r, double x0) {

    return gsl_cdf_tdist_Q(x-x0, r);

  }

  double tdistribution_quant(double x, double r, double x0) {

    return gsl_cdf_tdist_P(x-x0, r);

  }

} // namespace Math
} // namespace ROOT

<|endoftext|>