<commit_before>/*

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

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

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

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

*/

#ifndef TORRENT_LAZY_ENTRY_HPP_INCLUDED
#define TORRENT_LAZY_ENTRY_HPP_INCLUDED

#include <utility>
#include <vector>
#include <string>
#include <cstring>
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/size_type.hpp"

#if TORRENT_USE_IOSTREAM
#include <iosfwd>
#endif

namespace libtorrent
{
	struct lazy_entry;

	TORRENT_EXPORT char const* parse_int(char const* start, char const* end
		, char delimiter, boost::int64_t& val);
	// return 0 = success
	TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit = 1000);

	struct pascal_string
	{
		pascal_string(char const* p, int l): len(l), ptr(p) {}
		int len;
		char const* ptr;
		bool operator<(pascal_string const& rhs) const
		{
			return std::memcmp(ptr, rhs.ptr, (std::min)(len, rhs.len)) < 0
				|| len < rhs.len;
		}
	};

	struct lazy_dict_entry;

	struct TORRENT_EXPORT lazy_entry
	{
		enum entry_type_t
		{
			none_t, dict_t, list_t, string_t, int_t
		};

		lazy_entry() : m_begin(0), m_end(0), m_type(none_t)
		{ m_data.start = 0; }

		entry_type_t type() const { return m_type; }

		// start points to the first decimal digit
		// length is the number of digits
		void construct_int(char const* start, int length)
		{
			TORRENT_ASSERT(m_type == none_t);
			m_type = int_t;
			m_data.start = start;
			m_size = length;
			m_begin = start - 1; // include 'i'
			m_end = start + length + 1; // include 'e'
		}

		size_type int_value() const;

		// string functions
		// ================

		void construct_string(char const* start, int length);

		// the string is not null-terminated!
		char const* string_ptr() const
		{
			TORRENT_ASSERT(m_type == string_t);
			return m_data.start;
		}

		// this will return a null terminated string
		// it will write to the source buffer!
		char const* string_cstr() const
		{
			TORRENT_ASSERT(m_type == string_t);
			const_cast<char*>(m_data.start)[m_size] = 0;
			return m_data.start;
		}

		pascal_string string_pstr() const
		{
			TORRENT_ASSERT(m_type == string_t);
			return pascal_string(m_data.start, m_size);
		}

		std::string string_value() const
		{
			TORRENT_ASSERT(m_type == string_t);
			return std::string(m_data.start, m_size);
		}

		int string_length() const
		{ return m_size; }

		// dictionary functions
		// ====================

		void construct_dict(char const* begin)
		{
			TORRENT_ASSERT(m_type == none_t);
			m_type = dict_t;
			m_size = 0;
			m_capacity = 0;
			m_begin = begin;
		}

		lazy_entry* dict_append(char const* name);
		lazy_entry* dict_find(char const* name);
		lazy_entry const* dict_find(char const* name) const
		{ return const_cast<lazy_entry*>(this)->dict_find(name); }

		std::string dict_find_string_value(char const* name) const;
		pascal_string dict_find_pstr(char const* name) const;
		size_type dict_find_int_value(char const* name, size_type default_val = 0) const;
		lazy_entry const* dict_find_dict(char const* name) const;
		lazy_entry const* dict_find_list(char const* name) const;
		lazy_entry const* dict_find_string(char const* name) const;
		lazy_entry const* dict_find_int(char const* name) const;

		std::pair<std::string, lazy_entry const*> dict_at(int i) const;

		int dict_size() const
		{
			TORRENT_ASSERT(m_type == dict_t);
			return m_size;
		}

		// list functions
		// ==============

		void construct_list(char const* begin)
		{
			TORRENT_ASSERT(m_type == none_t);
			m_type = list_t;
			m_size = 0;
			m_capacity = 0;
			m_begin = begin;
		}

		lazy_entry* list_append();
		lazy_entry* list_at(int i)
		{
			TORRENT_ASSERT(m_type == list_t);
			TORRENT_ASSERT(i < int(m_size));
			return &m_data.list[i];
		}
		lazy_entry const* list_at(int i) const
		{ return const_cast<lazy_entry*>(this)->list_at(i); }

		std::string list_string_value_at(int i) const;
		pascal_string list_pstr_at(int i) const;
		size_type list_int_value_at(int i, size_type default_val = 0) const;

		int list_size() const
		{
			TORRENT_ASSERT(m_type == list_t);
			return int(m_size);
		}

		// end points one byte passed last byte
		void set_end(char const* end)
		{
			TORRENT_ASSERT(end > m_begin);
			m_end = end;
		}

		void clear();

		// releases ownership of any memory allocated
		void release()
		{
			m_data.start = 0;
			m_size = 0;
			m_capacity = 0;
			m_type = none_t;
		}

		~lazy_entry()
		{ clear(); }

		// returns pointers into the source buffer where
		// this entry has its bencoded data
		std::pair<char const*, int> data_section() const;

		void swap(lazy_entry& e)
		{
			using std::swap;
			entry_type_t tmp1 = e.m_type;
			e.m_type = m_type;
			m_type = tmp1;
			boost::uint32_t tmp2 = e.m_capacity;
			e.m_capacity = m_capacity;
			m_capacity = tmp2;
			swap(m_data.start, e.m_data.start);
			swap(m_size, e.m_size);
			swap(m_begin, e.m_begin);
			swap(m_end, e.m_end);
		}

	private:

		union data_t
		{
			lazy_dict_entry* dict;
			lazy_entry* list;
			char const* start;
		} m_data;

		// used for dictionaries and lists to record the range
		// in the original buffer they are based on
		char const* m_begin;
		char const* m_end;

		boost::uint32_t m_size; // if list or dictionary, the number of items
		boost::uint32_t m_capacity:29; // if list or dictionary, allocated number of items
		entry_type_t m_type:3;

		// non-copyable
		lazy_entry(lazy_entry const&);
		lazy_entry const& operator=(lazy_entry const&);
	};

	struct lazy_dict_entry
	{
		char const* name;
		lazy_entry val;
	};

	TORRENT_EXPORT std::string print_entry(lazy_entry const& e
		, bool single_line = false, int indent = 0);
#if TORRENT_USE_IOSTREAM
	TORRENT_EXPORT std::ostream& operator<<(std::ostream& os, lazy_entry const& e);
#endif

}

#endif

<commit_msg>fixed unsigned type issue in lazy_entry<commit_after>/*

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

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

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

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

*/

#ifndef TORRENT_LAZY_ENTRY_HPP_INCLUDED
#define TORRENT_LAZY_ENTRY_HPP_INCLUDED

#include <utility>
#include <vector>
#include <string>
#include <cstring>
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/size_type.hpp"

#if TORRENT_USE_IOSTREAM
#include <iosfwd>
#endif

namespace libtorrent
{
	struct lazy_entry;

	TORRENT_EXPORT char const* parse_int(char const* start, char const* end
		, char delimiter, boost::int64_t& val);
	// return 0 = success
	TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit = 1000);

	struct pascal_string
	{
		pascal_string(char const* p, int l): len(l), ptr(p) {}
		int len;
		char const* ptr;
		bool operator<(pascal_string const& rhs) const
		{
			return std::memcmp(ptr, rhs.ptr, (std::min)(len, rhs.len)) < 0
				|| len < rhs.len;
		}
	};

	struct lazy_dict_entry;

	struct TORRENT_EXPORT lazy_entry
	{
		enum entry_type_t
		{
			none_t, dict_t, list_t, string_t, int_t
		};

		lazy_entry() : m_begin(0), m_end(0), m_type(none_t)
		{ m_data.start = 0; }

		entry_type_t type() const { return (entry_type_t)m_type; }

		// start points to the first decimal digit
		// length is the number of digits
		void construct_int(char const* start, int length)
		{
			TORRENT_ASSERT(m_type == none_t);
			m_type = int_t;
			m_data.start = start;
			m_size = length;
			m_begin = start - 1; // include 'i'
			m_end = start + length + 1; // include 'e'
		}

		size_type int_value() const;

		// string functions
		// ================

		void construct_string(char const* start, int length);

		// the string is not null-terminated!
		char const* string_ptr() const
		{
			TORRENT_ASSERT(m_type == string_t);
			return m_data.start;
		}

		// this will return a null terminated string
		// it will write to the source buffer!
		char const* string_cstr() const
		{
			TORRENT_ASSERT(m_type == string_t);
			const_cast<char*>(m_data.start)[m_size] = 0;
			return m_data.start;
		}

		pascal_string string_pstr() const
		{
			TORRENT_ASSERT(m_type == string_t);
			return pascal_string(m_data.start, m_size);
		}

		std::string string_value() const
		{
			TORRENT_ASSERT(m_type == string_t);
			return std::string(m_data.start, m_size);
		}

		int string_length() const
		{ return m_size; }

		// dictionary functions
		// ====================

		void construct_dict(char const* begin)
		{
			TORRENT_ASSERT(m_type == none_t);
			m_type = dict_t;
			m_size = 0;
			m_capacity = 0;
			m_begin = begin;
		}

		lazy_entry* dict_append(char const* name);
		lazy_entry* dict_find(char const* name);
		lazy_entry const* dict_find(char const* name) const
		{ return const_cast<lazy_entry*>(this)->dict_find(name); }

		std::string dict_find_string_value(char const* name) const;
		pascal_string dict_find_pstr(char const* name) const;
		size_type dict_find_int_value(char const* name, size_type default_val = 0) const;
		lazy_entry const* dict_find_dict(char const* name) const;
		lazy_entry const* dict_find_list(char const* name) const;
		lazy_entry const* dict_find_string(char const* name) const;
		lazy_entry const* dict_find_int(char const* name) const;

		std::pair<std::string, lazy_entry const*> dict_at(int i) const;

		int dict_size() const
		{
			TORRENT_ASSERT(m_type == dict_t);
			return m_size;
		}

		// list functions
		// ==============

		void construct_list(char const* begin)
		{
			TORRENT_ASSERT(m_type == none_t);
			m_type = list_t;
			m_size = 0;
			m_capacity = 0;
			m_begin = begin;
		}

		lazy_entry* list_append();
		lazy_entry* list_at(int i)
		{
			TORRENT_ASSERT(m_type == list_t);
			TORRENT_ASSERT(i < int(m_size));
			return &m_data.list[i];
		}
		lazy_entry const* list_at(int i) const
		{ return const_cast<lazy_entry*>(this)->list_at(i); }

		std::string list_string_value_at(int i) const;
		pascal_string list_pstr_at(int i) const;
		size_type list_int_value_at(int i, size_type default_val = 0) const;

		int list_size() const
		{
			TORRENT_ASSERT(m_type == list_t);
			return int(m_size);
		}

		// end points one byte passed last byte
		void set_end(char const* end)
		{
			TORRENT_ASSERT(end > m_begin);
			m_end = end;
		}

		void clear();

		// releases ownership of any memory allocated
		void release()
		{
			m_data.start = 0;
			m_size = 0;
			m_capacity = 0;
			m_type = none_t;
		}

		~lazy_entry()
		{ clear(); }

		// returns pointers into the source buffer where
		// this entry has its bencoded data
		std::pair<char const*, int> data_section() const;

		void swap(lazy_entry& e)
		{
			using std::swap;
			boost::uint32_t tmp = e.m_type;
			e.m_type = m_type;
			m_type = tmp;
			tmp = e.m_capacity;
			e.m_capacity = m_capacity;
			m_capacity = tmp;
			swap(m_data.start, e.m_data.start);
			swap(m_size, e.m_size);
			swap(m_begin, e.m_begin);
			swap(m_end, e.m_end);
		}

	private:

		union data_t
		{
			lazy_dict_entry* dict;
			lazy_entry* list;
			char const* start;
		} m_data;

		// used for dictionaries and lists to record the range
		// in the original buffer they are based on
		char const* m_begin;
		char const* m_end;

		boost::uint32_t m_size; // if list or dictionary, the number of items
		boost::uint32_t m_capacity:29; // if list or dictionary, allocated number of items
		unsigned int m_type:3;

		// non-copyable
		lazy_entry(lazy_entry const&);
		lazy_entry const& operator=(lazy_entry const&);
	};

	struct lazy_dict_entry
	{
		char const* name;
		lazy_entry val;
	};

	TORRENT_EXPORT std::string print_entry(lazy_entry const& e
		, bool single_line = false, int indent = 0);
#if TORRENT_USE_IOSTREAM
	TORRENT_EXPORT std::ostream& operator<<(std::ostream& os, lazy_entry const& e);
#endif

}

#endif

<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#ifndef TORRENT_UTP_STREAM_HPP_INCLUDED
#define TORRENT_UTP_STREAM_HPP_INCLUDED

#include "libtorrent/connection_queue.hpp"
#include "libtorrent/proxy_base.hpp"
#include "libtorrent/udp_socket.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/packet_buffer.hpp"
#include "libtorrent/error_code.hpp"

#include <boost/bind.hpp>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>

#define CCONTROL_TARGET 100

namespace libtorrent
{
	struct utp_socket_manager;

	// some MTU and protocol header sizes constants
	enum
	{
		TORRENT_IPV4_HEADER = 20,
		TORRENT_IPV6_HEADER = 40,
		TORRENT_UDP_HEADER = 8,
		TORRENT_SOCKS5_HEADER = 6, // plus the size of the destination address

		TORRENT_ETHERNET_MTU = 1500,
		TORRENT_TEREDO_MTU = 1280,
		TORRENT_INET_MIN_MTU = 576,
		TORRENT_INET_MAX_MTU = 0xffff
	};

	// the point of the bif_endian_int is two-fold
	// one purpuse is to not have any alignment requirements
	// so that any byffer received from the network can be cast
	// to it and read as an integer of various sizes without
	// triggering a bus error. The other purpose is to convert
	// from network byte order to host byte order when read and
	// written, to offer a convenient interface to both interpreting
	// and writing network packets
	template <class T> struct big_endian_int
	{
		big_endian_int& operator=(T v)
		{
			char* p = m_storage;
			detail::write_impl(v, p);
			return *this;
		}
		operator T() const
		{
			const char* p = m_storage;
			return detail::read_impl(p, detail::type<T>());
		}
	private:
		char m_storage[sizeof(T)];
	};

	typedef big_endian_int<boost::uint64_t> be_uint64;
	typedef big_endian_int<boost::uint32_t> be_uint32;
	typedef big_endian_int<boost::uint16_t> be_uint16;
	typedef big_endian_int<boost::int64_t> be_int64;
	typedef big_endian_int<boost::int32_t> be_int32;
	typedef big_endian_int<boost::int16_t> be_int16;

/*
	uTP header from BEP 29

	0       4       8               16              24              32
	+-------+-------+---------------+---------------+---------------+
	| type  | ver   | extension     | connection_id                 |
	+-------+-------+---------------+---------------+---------------+
	| timestamp_microseconds                                        |
	+---------------+---------------+---------------+---------------+
	| timestamp_difference_microseconds                             |
	+---------------+---------------+---------------+---------------+
	| wnd_size                                                      |
	+---------------+---------------+---------------+---------------+
	| seq_nr                        | ack_nr                        |
	+---------------+---------------+---------------+---------------+

*/

	enum type { ST_DATA = 0, ST_FIN, ST_STATE, ST_RESET, ST_SYN, NUM_TYPES };

	struct utp_header
	{
		unsigned char type_ver;
		unsigned char extension;
		be_uint16 connection_id;
		be_uint32 timestamp_microseconds;
		be_uint32 timestamp_difference_microseconds;
		be_uint32 wnd_size;
		be_uint16 seq_nr;
		be_uint16 ack_nr;

		int get_type() const { return type_ver >> 4; }
		int get_version() const { return type_ver & 0xf; }
	};

struct utp_socket_impl;

utp_socket_impl* construct_utp_impl(boost::uint16_t recv_id
	, boost::uint16_t send_id, void* userdata
	, utp_socket_manager* sm);
void detach_utp_impl(utp_socket_impl* s);
void delete_utp_impl(utp_socket_impl* s);
bool should_delete(utp_socket_impl* s);
void tick_utp_impl(utp_socket_impl* s, ptime const& now);
void utp_init_mtu(utp_socket_impl* s, int link_mtu, int utp_mtu);
bool utp_incoming_packet(utp_socket_impl* s, char const* p
	, int size, udp::endpoint const& ep, ptime receive_time);
bool utp_match(utp_socket_impl* s, udp::endpoint const& ep, boost::uint16_t id);
udp::endpoint utp_remote_endpoint(utp_socket_impl* s);
boost::uint16_t utp_receive_id(utp_socket_impl* s);
int utp_socket_state(utp_socket_impl const* s);

#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
int socket_impl_size();
#endif

// this is the user-level stream interface to utp sockets.
// the reason why it's split up in a utp_stream class and
// an implementation class is because the socket state has
// to be able to out-live the user level socket. For instance
// when sending data on a stream and then closing it, the
// state holding the send buffer has to be kept around until
// it has been flushed, which may be longer than the client
// will keep the utp_stream object around for.
// for more details, see utp_socket_impl, which is analogous
// to the kernel state for a socket. It's defined in utp_stream.cpp
class TORRENT_EXPORT utp_stream
{
public:

	typedef stream_socket::endpoint_type endpoint_type;
	typedef stream_socket::protocol_type protocol_type;

	explicit utp_stream(asio::io_service& io_service);
	~utp_stream();

	// used for incoming connections
	void set_impl(utp_socket_impl* s);
	utp_socket_impl* get_impl();

#ifndef BOOST_NO_EXCEPTIONS
	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc) {}
#endif

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc, error_code& ec) {}

#ifndef BOOST_NO_EXCEPTIONS
	void bind(endpoint_type const& endpoint) {}
#endif

	void bind(endpoint_type const& endpoint, error_code& ec);

#ifndef BOOST_NO_EXCEPTIONS
	template <class SettableSocketOption>
	void set_option(SettableSocketOption const& opt) {}
#endif

	template <class SettableSocketOption>
	error_code set_option(SettableSocketOption const& opt, error_code& ec) { return ec; }

	void close();
	void close(error_code const& ec) { close(); }
	bool is_open() const { return m_open; }

	int read_buffer_size() const;
	static void on_read(void* self, size_t bytes_transferred, error_code const& ec, bool kill);
	static void on_write(void* self, size_t bytes_transferred, error_code const& ec, bool kill);
	static void on_connect(void* self, error_code const& ec, bool kill);

	typedef void(*handler_t)(void*, size_t, error_code const&, bool);
	typedef void(*connect_handler_t)(void*, error_code const&, bool);

	void add_read_buffer(void* buf, size_t len);
	void set_read_handler(handler_t h);
	void add_write_buffer(void const* buf, size_t len);
	void set_write_handler(handler_t h);
	size_t read_some(bool clear_buffers);

	void do_connect(tcp::endpoint const& ep, connect_handler_t h);

	endpoint_type local_endpoint() const
	{
		error_code ec;
		return local_endpoint(ec);
	}

	endpoint_type local_endpoint(error_code& ec) const;

	endpoint_type remote_endpoint() const
	{
		error_code ec;
		return remote_endpoint(ec);
	}

	endpoint_type remote_endpoint(error_code& ec) const;

	std::size_t available() const;
	std::size_t available(error_code& ec) const { return available(); }

	asio::io_service& io_service()
	{ return m_io_service; }

	template <class Handler>
	void async_connect(endpoint_type const& endpoint, Handler const& handler)
	{
		if (!endpoint.address().is_v4())
		{
			error_code ec = asio::error::operation_not_supported;
			m_io_service.post(boost::bind<void>(handler, asio::error::operation_not_supported, 0));
			return;
		}

		if (m_impl == 0)
		{
			m_io_service.post(boost::bind<void>(handler, asio::error::not_connected, 0));
			return;
		}

		m_connect_handler = handler;
		do_connect(endpoint, &utp_stream::on_connect);
	}

	template <class Mutable_Buffers, class Handler>
	void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
	{
		if (m_impl == 0)
		{
			m_io_service.post(boost::bind<void>(handler, asio::error::not_connected, 0));
			return;
		}

		TORRENT_ASSERT(!m_read_handler);
		if (m_read_handler)
		{
			m_io_service.post(boost::bind<void>(handler, asio::error::operation_not_supported, 0));
			return;
		}
		for (typename Mutable_Buffers::const_iterator i = buffers.begin()
			, end(buffers.end()); i != end; ++i)
		{
			TORRENT_ASSERT(buffer_size(*i) > 0);
			using asio::buffer_cast;
			using asio::buffer_size;
			add_read_buffer(buffer_cast<void*>(*i), buffer_size(*i));
		}
		m_read_handler = handler;
		set_read_handler(&utp_stream::on_read);
	}

	void do_async_connect(endpoint_type const& ep
		, boost::function<void(error_code const&)> const& handler);

	template <class Protocol>
	void open(Protocol const& p, error_code& ec)
	{ m_open = true; }

	template <class Protocol>
	void open(Protocol const& p)
	{ m_open = true; }

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
	{
		TORRENT_ASSERT(!m_read_handler);
		if (m_impl == 0)
		{
			ec = asio::error::not_connected;
			return 0;
		}

		if (read_buffer_size() == 0)
		{
			ec = asio::error::would_block;
			return 0;
		}
#ifdef TORRENT_DEBUG
		size_t buf_size = 0;
#endif

		for (typename Mutable_Buffers::const_iterator i = buffers.begin()
			, end(buffers.end()); i != end; ++i)
		{
			using asio::buffer_cast;
			using asio::buffer_size;
			add_read_buffer(buffer_cast<void*>(*i), buffer_size(*i));
#ifdef TORRENT_DEBUG
			buf_size += buffer_size(*i);
#endif
		}
		std::size_t ret = read_some(true);
		TORRENT_ASSERT(int(ret) <= buf_size);
		TORRENT_ASSERT(ret > 0);
		return ret;
	}

	template <class Const_Buffers>
	std::size_t write_some(Const_Buffers const& buffers, error_code& ec)
	{
		// TODO: implement
		return 0;
	}

	template <class Const_Buffers, class Handler>
	void async_write_some(Const_Buffers const& buffers, Handler const& handler)
	{
		if (m_impl == 0)
		{
			m_io_service.post(boost::bind<void>(handler, asio::error::not_connected, 0));
			return;
		}

		TORRENT_ASSERT(!m_write_handler);
		if (m_write_handler)
		{
			m_io_service.post(boost::bind<void>(handler, asio::error::operation_not_supported, 0));
			return;
		}

		for (typename Const_Buffers::const_iterator i = buffers.begin()
			, end(buffers.end()); i != end; ++i)
		{
			TORRENT_ASSERT(buffer_size(*i) > 0);
			using asio::buffer_cast;
			using asio::buffer_size;
			add_write_buffer((void*)buffer_cast<void const*>(*i), buffer_size(*i));
		}
		m_write_handler = handler;
		set_write_handler(&utp_stream::on_write);
	}

//private:

	void cancel_handlers(error_code const&);

	boost::function1<void, error_code const&> m_connect_handler;
	boost::function2<void, error_code const&, std::size_t> m_read_handler;
	boost::function2<void, error_code const&, std::size_t> m_write_handler;

	asio::io_service& m_io_service;
	utp_socket_impl* m_impl;
	bool m_open;
};

}

#endif
<commit_msg>fix warning in utp_stream<commit_after>/*

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

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

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

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

*/

#ifndef TORRENT_UTP_STREAM_HPP_INCLUDED
#define TORRENT_UTP_STREAM_HPP_INCLUDED

#include "libtorrent/connection_queue.hpp"
#include "libtorrent/proxy_base.hpp"
#include "libtorrent/udp_socket.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/packet_buffer.hpp"
#include "libtorrent/error_code.hpp"

#include <boost/bind.hpp>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>

#define CCONTROL_TARGET 100

namespace libtorrent
{
	struct utp_socket_manager;

	// some MTU and protocol header sizes constants
	enum
	{
		TORRENT_IPV4_HEADER = 20,
		TORRENT_IPV6_HEADER = 40,
		TORRENT_UDP_HEADER = 8,
		TORRENT_SOCKS5_HEADER = 6, // plus the size of the destination address

		TORRENT_ETHERNET_MTU = 1500,
		TORRENT_TEREDO_MTU = 1280,
		TORRENT_INET_MIN_MTU = 576,
		TORRENT_INET_MAX_MTU = 0xffff
	};

	// the point of the bif_endian_int is two-fold
	// one purpuse is to not have any alignment requirements
	// so that any byffer received from the network can be cast
	// to it and read as an integer of various sizes without
	// triggering a bus error. The other purpose is to convert
	// from network byte order to host byte order when read and
	// written, to offer a convenient interface to both interpreting
	// and writing network packets
	template <class T> struct big_endian_int
	{
		big_endian_int& operator=(T v)
		{
			char* p = m_storage;
			detail::write_impl(v, p);
			return *this;
		}
		operator T() const
		{
			const char* p = m_storage;
			return detail::read_impl(p, detail::type<T>());
		}
	private:
		char m_storage[sizeof(T)];
	};

	typedef big_endian_int<boost::uint64_t> be_uint64;
	typedef big_endian_int<boost::uint32_t> be_uint32;
	typedef big_endian_int<boost::uint16_t> be_uint16;
	typedef big_endian_int<boost::int64_t> be_int64;
	typedef big_endian_int<boost::int32_t> be_int32;
	typedef big_endian_int<boost::int16_t> be_int16;

/*
	uTP header from BEP 29

	0       4       8               16              24              32
	+-------+-------+---------------+---------------+---------------+
	| type  | ver   | extension     | connection_id                 |
	+-------+-------+---------------+---------------+---------------+
	| timestamp_microseconds                                        |
	+---------------+---------------+---------------+---------------+
	| timestamp_difference_microseconds                             |
	+---------------+---------------+---------------+---------------+
	| wnd_size                                                      |
	+---------------+---------------+---------------+---------------+
	| seq_nr                        | ack_nr                        |
	+---------------+---------------+---------------+---------------+

*/

	enum type { ST_DATA = 0, ST_FIN, ST_STATE, ST_RESET, ST_SYN, NUM_TYPES };

	struct utp_header
	{
		unsigned char type_ver;
		unsigned char extension;
		be_uint16 connection_id;
		be_uint32 timestamp_microseconds;
		be_uint32 timestamp_difference_microseconds;
		be_uint32 wnd_size;
		be_uint16 seq_nr;
		be_uint16 ack_nr;

		int get_type() const { return type_ver >> 4; }
		int get_version() const { return type_ver & 0xf; }
	};

struct utp_socket_impl;

utp_socket_impl* construct_utp_impl(boost::uint16_t recv_id
	, boost::uint16_t send_id, void* userdata
	, utp_socket_manager* sm);
void detach_utp_impl(utp_socket_impl* s);
void delete_utp_impl(utp_socket_impl* s);
bool should_delete(utp_socket_impl* s);
void tick_utp_impl(utp_socket_impl* s, ptime const& now);
void utp_init_mtu(utp_socket_impl* s, int link_mtu, int utp_mtu);
bool utp_incoming_packet(utp_socket_impl* s, char const* p
	, int size, udp::endpoint const& ep, ptime receive_time);
bool utp_match(utp_socket_impl* s, udp::endpoint const& ep, boost::uint16_t id);
udp::endpoint utp_remote_endpoint(utp_socket_impl* s);
boost::uint16_t utp_receive_id(utp_socket_impl* s);
int utp_socket_state(utp_socket_impl const* s);

#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
int socket_impl_size();
#endif

// this is the user-level stream interface to utp sockets.
// the reason why it's split up in a utp_stream class and
// an implementation class is because the socket state has
// to be able to out-live the user level socket. For instance
// when sending data on a stream and then closing it, the
// state holding the send buffer has to be kept around until
// it has been flushed, which may be longer than the client
// will keep the utp_stream object around for.
// for more details, see utp_socket_impl, which is analogous
// to the kernel state for a socket. It's defined in utp_stream.cpp
class TORRENT_EXPORT utp_stream
{
public:

	typedef stream_socket::endpoint_type endpoint_type;
	typedef stream_socket::protocol_type protocol_type;

	explicit utp_stream(asio::io_service& io_service);
	~utp_stream();

	// used for incoming connections
	void set_impl(utp_socket_impl* s);
	utp_socket_impl* get_impl();

#ifndef BOOST_NO_EXCEPTIONS
	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc) {}
#endif

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc, error_code& ec) {}

#ifndef BOOST_NO_EXCEPTIONS
	void bind(endpoint_type const& endpoint) {}
#endif

	void bind(endpoint_type const& endpoint, error_code& ec);

#ifndef BOOST_NO_EXCEPTIONS
	template <class SettableSocketOption>
	void set_option(SettableSocketOption const& opt) {}
#endif

	template <class SettableSocketOption>
	error_code set_option(SettableSocketOption const& opt, error_code& ec) { return ec; }

	void close();
	void close(error_code const& ec) { close(); }
	bool is_open() const { return m_open; }

	int read_buffer_size() const;
	static void on_read(void* self, size_t bytes_transferred, error_code const& ec, bool kill);
	static void on_write(void* self, size_t bytes_transferred, error_code const& ec, bool kill);
	static void on_connect(void* self, error_code const& ec, bool kill);

	typedef void(*handler_t)(void*, size_t, error_code const&, bool);
	typedef void(*connect_handler_t)(void*, error_code const&, bool);

	void add_read_buffer(void* buf, size_t len);
	void set_read_handler(handler_t h);
	void add_write_buffer(void const* buf, size_t len);
	void set_write_handler(handler_t h);
	size_t read_some(bool clear_buffers);

	void do_connect(tcp::endpoint const& ep, connect_handler_t h);

	endpoint_type local_endpoint() const
	{
		error_code ec;
		return local_endpoint(ec);
	}

	endpoint_type local_endpoint(error_code& ec) const;

	endpoint_type remote_endpoint() const
	{
		error_code ec;
		return remote_endpoint(ec);
	}

	endpoint_type remote_endpoint(error_code& ec) const;

	std::size_t available() const;
	std::size_t available(error_code& ec) const { return available(); }

	asio::io_service& io_service()
	{ return m_io_service; }

	template <class Handler>
	void async_connect(endpoint_type const& endpoint, Handler const& handler)
	{
		if (!endpoint.address().is_v4())
		{
			error_code ec = asio::error::operation_not_supported;
			m_io_service.post(boost::bind<void>(handler, asio::error::operation_not_supported, 0));
			return;
		}

		if (m_impl == 0)
		{
			m_io_service.post(boost::bind<void>(handler, asio::error::not_connected, 0));
			return;
		}

		m_connect_handler = handler;
		do_connect(endpoint, &utp_stream::on_connect);
	}

	template <class Mutable_Buffers, class Handler>
	void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
	{
		if (m_impl == 0)
		{
			m_io_service.post(boost::bind<void>(handler, asio::error::not_connected, 0));
			return;
		}

		TORRENT_ASSERT(!m_read_handler);
		if (m_read_handler)
		{
			m_io_service.post(boost::bind<void>(handler, asio::error::operation_not_supported, 0));
			return;
		}
		for (typename Mutable_Buffers::const_iterator i = buffers.begin()
			, end(buffers.end()); i != end; ++i)
		{
			TORRENT_ASSERT(buffer_size(*i) > 0);
			using asio::buffer_cast;
			using asio::buffer_size;
			add_read_buffer(buffer_cast<void*>(*i), buffer_size(*i));
		}
		m_read_handler = handler;
		set_read_handler(&utp_stream::on_read);
	}

	void do_async_connect(endpoint_type const& ep
		, boost::function<void(error_code const&)> const& handler);

	template <class Protocol>
	void open(Protocol const& p, error_code& ec)
	{ m_open = true; }

	template <class Protocol>
	void open(Protocol const& p)
	{ m_open = true; }

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
	{
		TORRENT_ASSERT(!m_read_handler);
		if (m_impl == 0)
		{
			ec = asio::error::not_connected;
			return 0;
		}

		if (read_buffer_size() == 0)
		{
			ec = asio::error::would_block;
			return 0;
		}
#ifdef TORRENT_DEBUG
		size_t buf_size = 0;
#endif

		for (typename Mutable_Buffers::const_iterator i = buffers.begin()
			, end(buffers.end()); i != end; ++i)
		{
			using asio::buffer_cast;
			using asio::buffer_size;
			add_read_buffer(buffer_cast<void*>(*i), buffer_size(*i));
#ifdef TORRENT_DEBUG
			buf_size += buffer_size(*i);
#endif
		}
		std::size_t ret = read_some(true);
		TORRENT_ASSERT(ret <= buf_size);
		TORRENT_ASSERT(ret > 0);
		return ret;
	}

	template <class Const_Buffers>
	std::size_t write_some(Const_Buffers const& buffers, error_code& ec)
	{
		// TODO: implement
		return 0;
	}

	template <class Const_Buffers, class Handler>
	void async_write_some(Const_Buffers const& buffers, Handler const& handler)
	{
		if (m_impl == 0)
		{
			m_io_service.post(boost::bind<void>(handler, asio::error::not_connected, 0));
			return;
		}

		TORRENT_ASSERT(!m_write_handler);
		if (m_write_handler)
		{
			m_io_service.post(boost::bind<void>(handler, asio::error::operation_not_supported, 0));
			return;
		}

		for (typename Const_Buffers::const_iterator i = buffers.begin()
			, end(buffers.end()); i != end; ++i)
		{
			TORRENT_ASSERT(buffer_size(*i) > 0);
			using asio::buffer_cast;
			using asio::buffer_size;
			add_write_buffer((void*)buffer_cast<void const*>(*i), buffer_size(*i));
		}
		m_write_handler = handler;
		set_write_handler(&utp_stream::on_write);
	}

//private:

	void cancel_handlers(error_code const&);

	boost::function1<void, error_code const&> m_connect_handler;
	boost::function2<void, error_code const&, std::size_t> m_read_handler;
	boost::function2<void, error_code const&, std::size_t> m_write_handler;

	asio::io_service& m_io_service;
	utp_socket_impl* m_impl;
	bool m_open;
};

}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ali Saidi
 *          Andreas Hansson
 */

#include "base/trace.hh"
#include "debug/Drain.hh"
#include "debug/PacketQueue.hh"
#include "mem/packet_queue.hh"

using namespace std;

PacketQueue::PacketQueue(EventManager& _em, const std::string& _label)
    : em(_em), sendEvent(this), drainManager(NULL), label(_label),
      waitingOnRetry(false)
{
}

PacketQueue::~PacketQueue()
{
}

void
PacketQueue::retry()
{
    DPRINTF(PacketQueue, "Queue %s received retry\n", name());
    assert(waitingOnRetry);
    sendDeferredPacket();
}

bool
PacketQueue::checkFunctional(PacketPtr pkt)
{
    pkt->pushLabel(label);

    DeferredPacketIterator i = transmitList.begin();
    DeferredPacketIterator end = transmitList.end();
    bool found = false;

    while (!found && i != end) {
        // If the buffered packet contains data, and it overlaps the
        // current packet, then update data
        found = pkt->checkFunctional(i->pkt);
        ++i;
    }

    pkt->popLabel();

    return found;
}

void
PacketQueue::schedSendEvent(Tick when)
{
    // if we are waiting on a retry, do not schedule a send event, and
    // instead rely on retry being called
    if (waitingOnRetry) {
        assert(!sendEvent.scheduled());
        return;
    }

    if (!sendEvent.scheduled()) {
        em.schedule(&sendEvent, when);
    } else if (sendEvent.when() > when) {
        em.reschedule(&sendEvent, when);
    }
}

void
PacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool send_as_snoop)
{
    // we can still send a packet before the end of this tick
    assert(when >= curTick());

    // express snoops should never be queued
    assert(!pkt->isExpressSnoop());

    // nothing on the list, or earlier than current front element,
    // schedule an event
    if (transmitList.empty() || when < transmitList.front().tick) {
        // note that currently we ignore a potentially outstanding retry
        // and could in theory put a new packet at the head of the
        // transmit list before retrying the existing packet
        transmitList.push_front(DeferredPacket(when, pkt, send_as_snoop));
        schedSendEvent(when);
        return;
    }

    // list is non-empty and this belongs at the end
    if (when >= transmitList.back().tick) {
        transmitList.push_back(DeferredPacket(when, pkt, send_as_snoop));
        return;
    }

    // this belongs in the middle somewhere, insertion sort
    DeferredPacketIterator i = transmitList.begin();
    ++i; // already checked for insertion at front
    while (i != transmitList.end() && when >= i->tick)
        ++i;
    transmitList.insert(i, DeferredPacket(when, pkt, send_as_snoop));
}

void PacketQueue::trySendTiming()
{
    assert(deferredPacketReady());

    // take the next packet off the list here, as we might return to
    // ourselves through the sendTiming call below
    DeferredPacket dp = transmitList.front();
    transmitList.pop_front();

    // use the appropriate implementation of sendTiming based on the
    // type of port associated with the queue, and whether the packet
    // is to be sent as a snoop or not
    waitingOnRetry = !sendTiming(dp.pkt, dp.sendAsSnoop);

    if (waitingOnRetry) {
        // put the packet back at the front of the list (packet should
        // not have changed since it wasn't accepted)
        assert(!sendEvent.scheduled());
        transmitList.push_front(dp);
    }
}

void
PacketQueue::scheduleSend(Tick time)
{
    // the next ready time is either determined by the next deferred packet,
    // or in the cache through the MSHR ready time
    Tick nextReady = std::min(deferredPacketReadyTime(), time);

    if (nextReady != MaxTick) {
        // if the sendTiming caused someone else to call our
        // recvTiming we could already have an event scheduled, check
        if (!sendEvent.scheduled())
            em.schedule(&sendEvent, std::max(nextReady, curTick() + 1));
    } else {
        // no more to send, so if we're draining, we may be done
        if (drainManager && transmitList.empty() && !sendEvent.scheduled()) {
            DPRINTF(Drain, "PacketQueue done draining,"
                    "processing drain event\n");
            drainManager->signalDrainDone();
            drainManager = NULL;
        }
    }
}

void
PacketQueue::sendDeferredPacket()
{
    // try to send what is on the list, this will set waitingOnRetry
    // accordingly
    trySendTiming();

    // if we succeeded and are not waiting for a retry, schedule the
    // next send
    if (!waitingOnRetry) {
        scheduleSend();
    }
}

void
PacketQueue::processSendEvent()
{
    assert(!waitingOnRetry);
    sendDeferredPacket();
}

unsigned int
PacketQueue::drain(DrainManager *dm)
{
    if (transmitList.empty() && !sendEvent.scheduled())
        return 0;
    DPRINTF(Drain, "PacketQueue not drained\n");
    drainManager = dm;
    return 1;
}

MasterPacketQueue::MasterPacketQueue(EventManager& _em, MasterPort& _masterPort,
                                     const std::string _label)
    : PacketQueue(_em, _label), masterPort(_masterPort)
{
}

bool
MasterPacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop)
{
    // attempt to send the packet and return according to the outcome
    if (!send_as_snoop)
        return masterPort.sendTimingReq(pkt);
    else
        return masterPort.sendTimingSnoopResp(pkt);
}

SlavePacketQueue::SlavePacketQueue(EventManager& _em, SlavePort& _slavePort,
                                   const std::string _label)
    : PacketQueue(_em, _label), slavePort(_slavePort)
{
}

bool
SlavePacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop)
{
    // we should never have queued snoop requests
    assert(!send_as_snoop);
    return slavePort.sendTimingResp(pkt);
}
<commit_msg>mem: Add sanity check to packet queue size<commit_after>/*
 * Copyright (c) 2012 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ali Saidi
 *          Andreas Hansson
 */

#include "base/trace.hh"
#include "debug/Drain.hh"
#include "debug/PacketQueue.hh"
#include "mem/packet_queue.hh"

using namespace std;

PacketQueue::PacketQueue(EventManager& _em, const std::string& _label)
    : em(_em), sendEvent(this), drainManager(NULL), label(_label),
      waitingOnRetry(false)
{
}

PacketQueue::~PacketQueue()
{
}

void
PacketQueue::retry()
{
    DPRINTF(PacketQueue, "Queue %s received retry\n", name());
    assert(waitingOnRetry);
    sendDeferredPacket();
}

bool
PacketQueue::checkFunctional(PacketPtr pkt)
{
    pkt->pushLabel(label);

    DeferredPacketIterator i = transmitList.begin();
    DeferredPacketIterator end = transmitList.end();
    bool found = false;

    while (!found && i != end) {
        // If the buffered packet contains data, and it overlaps the
        // current packet, then update data
        found = pkt->checkFunctional(i->pkt);
        ++i;
    }

    pkt->popLabel();

    return found;
}

void
PacketQueue::schedSendEvent(Tick when)
{
    // if we are waiting on a retry, do not schedule a send event, and
    // instead rely on retry being called
    if (waitingOnRetry) {
        assert(!sendEvent.scheduled());
        return;
    }

    if (!sendEvent.scheduled()) {
        em.schedule(&sendEvent, when);
    } else if (sendEvent.when() > when) {
        em.reschedule(&sendEvent, when);
    }
}

void
PacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool send_as_snoop)
{
    // we can still send a packet before the end of this tick
    assert(when >= curTick());

    // express snoops should never be queued
    assert(!pkt->isExpressSnoop());

    // add a very basic sanity check on the port to ensure the
    // invisible buffer is not growing beyond reasonable limits
    if (transmitList.size() > 100) {
        panic("Packet queue %s has grown beyond 100 packets\n",
              name());
    }

    // nothing on the list, or earlier than current front element,
    // schedule an event
    if (transmitList.empty() || when < transmitList.front().tick) {
        // note that currently we ignore a potentially outstanding retry
        // and could in theory put a new packet at the head of the
        // transmit list before retrying the existing packet
        transmitList.push_front(DeferredPacket(when, pkt, send_as_snoop));
        schedSendEvent(when);
        return;
    }

    // list is non-empty and this belongs at the end
    if (when >= transmitList.back().tick) {
        transmitList.push_back(DeferredPacket(when, pkt, send_as_snoop));
        return;
    }

    // this belongs in the middle somewhere, insertion sort
    DeferredPacketIterator i = transmitList.begin();
    ++i; // already checked for insertion at front
    while (i != transmitList.end() && when >= i->tick)
        ++i;
    transmitList.insert(i, DeferredPacket(when, pkt, send_as_snoop));
}

void PacketQueue::trySendTiming()
{
    assert(deferredPacketReady());

    // take the next packet off the list here, as we might return to
    // ourselves through the sendTiming call below
    DeferredPacket dp = transmitList.front();
    transmitList.pop_front();

    // use the appropriate implementation of sendTiming based on the
    // type of port associated with the queue, and whether the packet
    // is to be sent as a snoop or not
    waitingOnRetry = !sendTiming(dp.pkt, dp.sendAsSnoop);

    if (waitingOnRetry) {
        // put the packet back at the front of the list (packet should
        // not have changed since it wasn't accepted)
        assert(!sendEvent.scheduled());
        transmitList.push_front(dp);
    }
}

void
PacketQueue::scheduleSend(Tick time)
{
    // the next ready time is either determined by the next deferred packet,
    // or in the cache through the MSHR ready time
    Tick nextReady = std::min(deferredPacketReadyTime(), time);

    if (nextReady != MaxTick) {
        // if the sendTiming caused someone else to call our
        // recvTiming we could already have an event scheduled, check
        if (!sendEvent.scheduled())
            em.schedule(&sendEvent, std::max(nextReady, curTick() + 1));
    } else {
        // no more to send, so if we're draining, we may be done
        if (drainManager && transmitList.empty() && !sendEvent.scheduled()) {
            DPRINTF(Drain, "PacketQueue done draining,"
                    "processing drain event\n");
            drainManager->signalDrainDone();
            drainManager = NULL;
        }
    }
}

void
PacketQueue::sendDeferredPacket()
{
    // try to send what is on the list, this will set waitingOnRetry
    // accordingly
    trySendTiming();

    // if we succeeded and are not waiting for a retry, schedule the
    // next send
    if (!waitingOnRetry) {
        scheduleSend();
    }
}

void
PacketQueue::processSendEvent()
{
    assert(!waitingOnRetry);
    sendDeferredPacket();
}

unsigned int
PacketQueue::drain(DrainManager *dm)
{
    if (transmitList.empty() && !sendEvent.scheduled())
        return 0;
    DPRINTF(Drain, "PacketQueue not drained\n");
    drainManager = dm;
    return 1;
}

MasterPacketQueue::MasterPacketQueue(EventManager& _em, MasterPort& _masterPort,
                                     const std::string _label)
    : PacketQueue(_em, _label), masterPort(_masterPort)
{
}

bool
MasterPacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop)
{
    // attempt to send the packet and return according to the outcome
    if (!send_as_snoop)
        return masterPort.sendTimingReq(pkt);
    else
        return masterPort.sendTimingSnoopResp(pkt);
}

SlavePacketQueue::SlavePacketQueue(EventManager& _em, SlavePort& _slavePort,
                                   const std::string _label)
    : PacketQueue(_em, _label), slavePort(_slavePort)
{
}

bool
SlavePacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop)
{
    // we should never have queued snoop requests
    assert(!send_as_snoop);
    return slavePort.sendTimingResp(pkt);
}
<|endoftext|>


<commit_before>#include "network.h"

#include "server.h"
#include "client.h"
#include "gusgame.h"
#include "LuaCallbacks.h"
#include "gconsole.h"
#include "net_worm.h"
#include "game/WormInputHandler.h"
#include "particle.h"
#include "util/macros.h"
#include "util/log.h"
#include "util/text.h"
#include "lua/bindings-network.h"
#include "game/Game.h"

#include <string>
#include <iostream>
#include <memory>
#include <list>
#include <set>
#include <utility>
#include "netstream.h"
#include <boost/assign/list_inserter.hpp>
using namespace boost::assign;

using namespace std;

int const Network::protocolVersion = 2;

LuaReference LuaEventDef::metaTable;

namespace
{
	Network::State state = Network::StateDisconnected;
	int stateTimeOut = 0;

	void setLuaState(Network::State s)
	{
		LUACALLBACK(networkStateChange).call()(s)();
	}

	void setState(Network::State s)
	{
		state = s;
	}

#define SET_STATE(s_) DLOG("Network state: " #s_); setState(State##s_)

	struct LuaEventList
	{
		typedef std::map<std::string, LuaEventDef*> MapT;
		MapT stringToEvent;
		std::vector<LuaEventDef*> events;

		LuaEventDef* add(std::string const& name, LuaEventDef* event)
		{
			size_t idx = events.size() + 1;

			event->idx = idx;
			std::pair<MapT::iterator, bool> r = stringToEvent.insert(std::make_pair(name, event));
			if(!r.second) {
				delete event;
				event = r.first->second;
			}
			events.push_back(event);
			return event;
		}

		LuaEventDef* assign(std::string const& name, LuaEventDef* event)
		{
			std::pair<MapT::iterator, bool> r = stringToEvent.insert(std::make_pair(name, event));
			if(!r.second) {
				r.first->second->callb = event->callb;
				delete event;
				event = r.first->second;
			}
			return event;
		}

		void index(std::string const& name)
		{
			int idx = events.size() + 1;
			MapT::iterator i = stringToEvent.find(name);
			if(i != stringToEvent.end()) {
				i->second->idx = idx;
				events.push_back(i->second);
			} else
				events.push_back(0);
		}

		LuaEventDef* fromIndex(size_t idx)
		{
			if(idx > 0 && idx <= events.size())
				return events[idx - 1];
			return 0;
		}

		void clear()
		{
			stringToEvent.clear();
			events.clear();
		}

		void encode(BitStream* data)
		{
			data->addInt(events.size(), 8);
			foreach(i, events) {
				DLOG("Encoding lua event: " << (*i)->name);
				data->addString((*i)->name.c_str());
			}
		}
	};

	std::string serverName;
	std::string serverDesc;
	std::set<Net_U32> bannedIPs;

	int reconnectTimer = 0;
	int connCount = 0;

	Net_Control* m_control = 0;
	LuaEventList luaEvents[Network::LuaEventGroup::Max];

	void registerClasses() // Factorization of class registering in client and server
	{
		CWorm::classID = m_control->Net_registerClass("worm",Net_CLASSFLAG_ANNOUNCEDATA);
		CWormInputHandler::classID = m_control->Net_registerClass("player",Net_CLASSFLAG_ANNOUNCEDATA);
		GusGame::classID = m_control->Net_registerClass("gusGame",0);
		Particle::classID = m_control->Net_registerClass("particle",Net_CLASSFLAG_ANNOUNCEDATA);
	}
}

Network network;

void LuaEventDef::call(BitStream* s)
{
	BitStream* n = s->Duplicate();
	(luaIngame.call(callb), luaReference, luaIngame.fullReference(*n, LuaBindings::BitStreamMetaTable))();
}

void LuaEventDef::call(LuaReferenceLazy obj, BitStream* s)
{
	BitStream* n = s->Duplicate();
	(luaIngame.call(callb), luaReference, obj, luaIngame.fullReference(*n, LuaBindings::BitStreamMetaTable))();
}

LuaEventDef::~LuaEventDef()
{
	luaReference.destroy();
	callb.destroy();
}

Network::Network()
{
}

Network::~Network()
{
}

void Network::log(char const* msg)
{
	cerr << "Gusanos Network: " << msg << endl;
}

void Network::init()
{
}

void Network::shutDown()
{
	delete m_control;
	m_control = 0;
}

void Network::registerInConsole()
{
	console.registerVariables()
	("NET_CHECK_CRC", &network.checkCRC, 1)
	;

}

Net_ConnID Network::getServerID()
{
	return NetConnID_server();
}

void Network::update()
{
	if ( m_control ) {
		m_control->Net_processOutput();
		m_control->Net_processInput();
	}

	switch(state) {
			case StateConnecting:
			case StateHosting:
			break;

			case StateDisconnected:
			case StateIdle:
			break;

			case StateDisconnecting: {
				if(connCount == 0 || stateTimeOut <= 0) {
					if(connCount != 0)
						WLOG(connCount << " connection(s) might not have disconnected properly.");
					setLuaState(StateDisconnected);
					SET_STATE(Disconnected);

					if(m_control) {
						m_control->Shutdown();
						delete m_control;
						m_control = 0;
					}

					connCount = 0;

					gusGame.removeNode();
				} else
					--stateTimeOut;
			}
			break;
	}

	if( reconnectTimer > 0 ) {
		//disconnect();
		if(--reconnectTimer == 0) {
			DLOG("Reconnecting Gusanos");
			olxConnect();
		}
	}
}

void Network::olxShutdown() {
	setLuaState(StateDisconnected);
	SET_STATE(Disconnected);

	if(m_control) {
		m_control->Shutdown();
		delete m_control;
		m_control = 0;
	}

	connCount = 0;

	gusGame.removeNode();

	clear();
}

void Network::olxHost()
{
	assert(game.isServer());

	if(state != StateDisconnected) { // We assume that we're disconnected
		errors << "Network::olxHost: state is not disconnected" << endl;
	}

	m_control = new Server();
	registerClasses();
	gusGame.assignNetworkRole(); // Gives the gusGame class node authority role
	setLuaState(StateHosting);
	SET_STATE(Idle);
}

void Network::olxConnect()
{
	assert(game.isClient());
	// moved frmo Network::update() message queue handler to here:

	if(!isDisconnected()) {
		disconnect();

		// This would leave the Connect msg in the msg queue to do the connect as soon as we are disconnected
		//mq_delay(); // Wait until network is disconnected

		errors << "Network::olxConnect: we were not disconnected" << endl;
	}

	m_control = new Client();
	registerClasses();
	//m_client = true; // We wait with setting this until we've connected
	setLuaState(StateConnecting);
	SET_STATE(Idle);

	m_control->Net_ConnectToServer();

	gusGame.assignNetworkRole();
}

void Network::disconnect()
{
	if(state == StateIdle && m_control) {
		setLuaState(StateDisconnecting);
		SET_STATE(Disconnecting);
		stateTimeOut = 1000;
		LOG("Disconnecting...");
	}
}

void Network::clear()
{
	// The lua event tables contain pointers to objects allocated by lua
	for(int t = LuaEventGroup::GusGame; t < LuaEventGroup::Max; ++t) {
		luaEvents[t].clear();
	}
}

void Network::olxReconnect(int delay)
{
	reconnectTimer = delay;
}

bool Network::isHost()
{
	return game.isServer();
}

bool Network::isClient()
{
	return game.isClient();
}

Net_Control* Network::getNetControl()
{
	return m_control;
}

LuaEventDef* Network::addLuaEvent(LuaEventGroup::type type, const std::string& name, LuaEventDef* event)
{
	if(game.isServer())
		return luaEvents[type].add(name, event);
	else if(game.isClient())
		return luaEvents[type].assign(name, event);

	return event;
}

void Network::indexLuaEvent(LuaEventGroup::type type, const std::string& name)
{
	if(game.isClient())
		luaEvents[type].index(name);
}

void Network::encodeLuaEvents(BitStream* data)
{
	for(int t = LuaEventGroup::GusGame; t < LuaEventGroup::Max; ++t) {
		luaEvents[t].encode(data);
	}
}

LuaEventDef* Network::indexToLuaEvent(LuaEventGroup::type type, int idx)
{
	return luaEvents[type].fromIndex(idx);
}

void Network::incConnCount()
{
	++connCount;
}

void Network::decConnCount()
{
	--connCount;
}

bool Network::isDisconnected()
{
	return state == StateDisconnected;
}

bool Network::isDisconnecting()
{
	return state == StateDisconnecting;
}

void Network::olxParse(Net_ConnID src, CBytestream& bs) {
	if(m_control)
		m_control->olxParse(src, bs);
	else {
		errors << "GusNetwork::olxParse: net control not initialised" << endl;
		bs.SkipAll();
	}
}

void Network::olxParseUpdate(Net_ConnID src, CBytestream& bs) {
	if(m_control)
		m_control->olxParseUpdate(src, bs);
	else {
		errors << "GusNetwork::olxParseUpdate: net control not initialised" << endl;
		bs.SkipAll();
	}
}

void Network::olxSend(bool sendPendingOnly) {
	// we can ignore Gusanos network in local play
	if(game.isLocalGame()) return;

	// dont send if in lobby
	if(game.state < Game::S_Preparing) return;

	if(m_control)
		m_control->olxSend(sendPendingOnly);
	else
		errors << "GusNetwork::olxSend: net control not initialised" << endl;
}

void Network::sendEncodedLuaEvents(Net_ConnID cid) {
	if(!m_control) {
		errors << "Network::sendEncodedLuaEvents: control unset" << endl;
		return;
	}

	std::auto_ptr<BitStream> data(new BitStream);
	Encoding::encode(*data, Network::ClientEvents::LuaEvents, Network::ClientEvents::Max);
	network.encodeLuaEvents(data.get());
	m_control->Net_sendData(cid, data.release(), eNet_ReliableOrdered);
}

<commit_msg>comment<commit_after>#include "network.h"

#include "server.h"
#include "client.h"
#include "gusgame.h"
#include "LuaCallbacks.h"
#include "gconsole.h"
#include "net_worm.h"
#include "game/WormInputHandler.h"
#include "particle.h"
#include "util/macros.h"
#include "util/log.h"
#include "util/text.h"
#include "lua/bindings-network.h"
#include "game/Game.h"

#include <string>
#include <iostream>
#include <memory>
#include <list>
#include <set>
#include <utility>
#include "netstream.h"
#include <boost/assign/list_inserter.hpp>
using namespace boost::assign;

using namespace std;

int const Network::protocolVersion = 2;

LuaReference LuaEventDef::metaTable;

namespace
{
	Network::State state = Network::StateDisconnected;
	int stateTimeOut = 0;

	void setLuaState(Network::State s)
	{
		LUACALLBACK(networkStateChange).call()(s)();
	}

	void setState(Network::State s)
	{
		state = s;
	}

#define SET_STATE(s_) DLOG("Network state: " #s_); setState(State##s_)

	struct LuaEventList
	{
		typedef std::map<std::string, LuaEventDef*> MapT;
		MapT stringToEvent;
		std::vector<LuaEventDef*> events;

		LuaEventDef* add(std::string const& name, LuaEventDef* event)
		{
			size_t idx = events.size() + 1;

			event->idx = idx;
			std::pair<MapT::iterator, bool> r = stringToEvent.insert(std::make_pair(name, event));
			if(!r.second) {
				delete event;
				event = r.first->second;
			}
			events.push_back(event);
			return event;
		}

		LuaEventDef* assign(std::string const& name, LuaEventDef* event)
		{
			std::pair<MapT::iterator, bool> r = stringToEvent.insert(std::make_pair(name, event));
			if(!r.second) {
				r.first->second->callb = event->callb;
				delete event;
				event = r.first->second;
			}
			return event;
		}

		void index(std::string const& name)
		{
			int idx = events.size() + 1;
			MapT::iterator i = stringToEvent.find(name);
			if(i != stringToEvent.end()) {
				i->second->idx = idx;
				events.push_back(i->second);
			} else
				events.push_back(0);
		}

		LuaEventDef* fromIndex(size_t idx)
		{
			if(idx > 0 && idx <= events.size())
				return events[idx - 1];
			return 0;
		}

		void clear()
		{
			stringToEvent.clear();
			events.clear();
		}

		void encode(BitStream* data)
		{
			data->addInt(events.size(), 8);
			foreach(i, events) {
				DLOG("Encoding lua event: " << (*i)->name);
				data->addString((*i)->name.c_str());
			}
		}
	};

	std::string serverName;
	std::string serverDesc;
	std::set<Net_U32> bannedIPs;

	int reconnectTimer = 0;
	int connCount = 0;

	Net_Control* m_control = 0;
	LuaEventList luaEvents[Network::LuaEventGroup::Max];

	void registerClasses() // Factorization of class registering in client and server
	{
		CWorm::classID = m_control->Net_registerClass("worm",Net_CLASSFLAG_ANNOUNCEDATA);
		CWormInputHandler::classID = m_control->Net_registerClass("player",Net_CLASSFLAG_ANNOUNCEDATA);
		GusGame::classID = m_control->Net_registerClass("gusGame",0);
		Particle::classID = m_control->Net_registerClass("particle",Net_CLASSFLAG_ANNOUNCEDATA);
	}
}

Network network;

void LuaEventDef::call(BitStream* s)
{
	BitStream* n = s->Duplicate();
	(luaIngame.call(callb), luaReference, luaIngame.fullReference(*n, LuaBindings::BitStreamMetaTable))();
}

void LuaEventDef::call(LuaReferenceLazy obj, BitStream* s)
{
	BitStream* n = s->Duplicate();
	(luaIngame.call(callb), luaReference, obj, luaIngame.fullReference(*n, LuaBindings::BitStreamMetaTable))();
}

LuaEventDef::~LuaEventDef()
{
	luaReference.destroy();
	callb.destroy();
}

Network::Network()
{
}

Network::~Network()
{
}

void Network::log(char const* msg)
{
	cerr << "Gusanos Network: " << msg << endl;
}

void Network::init()
{
}

void Network::shutDown()
{
	delete m_control;
	m_control = 0;
}

void Network::registerInConsole()
{
	console.registerVariables()
	("NET_CHECK_CRC", &network.checkCRC, 1)
	;

}

Net_ConnID Network::getServerID()
{
	return NetConnID_server();
}

void Network::update()
{
	if ( m_control ) {
		m_control->Net_processOutput();
		m_control->Net_processInput();
	}

	switch(state) {
			case StateConnecting:
			case StateHosting:
			break;

			case StateDisconnected:
			case StateIdle:
			break;

			case StateDisconnecting: {
				if(connCount == 0 || stateTimeOut <= 0) {
					if(connCount != 0)
						WLOG(connCount << " connection(s) might not have disconnected properly.");
					setLuaState(StateDisconnected);
					SET_STATE(Disconnected);

					if(m_control) {
						m_control->Shutdown();
						delete m_control;
						m_control = 0;
					}

					connCount = 0;

					gusGame.removeNode();
				} else
					--stateTimeOut;
			}
			break;
	}

	if( reconnectTimer > 0 ) {
		//disconnect();
		if(--reconnectTimer == 0) {
			DLOG("Reconnecting Gusanos");
			olxConnect();
		}
	}
}

void Network::olxShutdown() {
	setLuaState(StateDisconnected);
	SET_STATE(Disconnected);

	if(m_control) {
		m_control->Shutdown();
		delete m_control;
		m_control = 0;
	}

	connCount = 0;

	gusGame.removeNode();

	clear();
}

void Network::olxHost()
{
	assert(game.isServer());

	if(state != StateDisconnected) { // We assume that we're disconnected
		errors << "Network::olxHost: state is not disconnected" << endl;
	}

	m_control = new Server();
	registerClasses();
	gusGame.assignNetworkRole(); // Gives the gusGame class node authority role
	setLuaState(StateHosting);
	SET_STATE(Idle);
}

void Network::olxConnect()
{
	assert(game.isClient());
	// moved frmo Network::update() message queue handler to here:

	if(!isDisconnected()) {
		disconnect();

		// This would leave the Connect msg in the msg queue to do the connect as soon as we are disconnected
		//mq_delay(); // Wait until network is disconnected

		errors << "Network::olxConnect: we were not disconnected" << endl;
	}

	m_control = new Client();
	registerClasses();
	//m_client = true; // We wait with setting this until we've connected
	setLuaState(StateConnecting);
	SET_STATE(Idle);

	m_control->Net_ConnectToServer();

	gusGame.assignNetworkRole();
}

void Network::disconnect()
{
	if(state == StateIdle && m_control) {
		setLuaState(StateDisconnecting);
		SET_STATE(Disconnecting);
		stateTimeOut = 1000;
		LOG("Disconnecting...");
	}
}

void Network::clear()
{
	// The lua event tables contain pointers to objects allocated by lua
	for(int t = LuaEventGroup::GusGame; t < LuaEventGroup::Max; ++t) {
		luaEvents[t].clear();
	}
}

void Network::olxReconnect(int delay)
{
	reconnectTimer = delay;
}

bool Network::isHost()
{
	return game.isServer();
}

bool Network::isClient()
{
	return game.isClient();
}

Net_Control* Network::getNetControl()
{
	return m_control;
}

LuaEventDef* Network::addLuaEvent(LuaEventGroup::type type, const std::string& name, LuaEventDef* event)
{
	if(game.isServer())
		return luaEvents[type].add(name, event);
	else if(game.isClient())
		return luaEvents[type].assign(name, event);

	return event;
}

void Network::indexLuaEvent(LuaEventGroup::type type, const std::string& name)
{
	if(game.isClient())
		luaEvents[type].index(name);
}

void Network::encodeLuaEvents(BitStream* data)
{
	for(int t = LuaEventGroup::GusGame; t < LuaEventGroup::Max; ++t) {
		luaEvents[t].encode(data);
	}
}

LuaEventDef* Network::indexToLuaEvent(LuaEventGroup::type type, int idx)
{
	return luaEvents[type].fromIndex(idx);
}

void Network::incConnCount()
{
	++connCount;
}

void Network::decConnCount()
{
	--connCount;
}

bool Network::isDisconnected()
{
	return state == StateDisconnected;
}

bool Network::isDisconnecting()
{
	return state == StateDisconnecting;
}

void Network::olxParse(Net_ConnID src, CBytestream& bs) {
	if(m_control)
		m_control->olxParse(src, bs);
	else {
		errors << "GusNetwork::olxParse: net control not initialised" << endl;
		bs.SkipAll();
	}
}

void Network::olxParseUpdate(Net_ConnID src, CBytestream& bs) {
	if(m_control)
		m_control->olxParseUpdate(src, bs);
	else {
		errors << "GusNetwork::olxParseUpdate: net control not initialised" << endl;
		bs.SkipAll();
	}
}

void Network::olxSend(bool sendPendingOnly) {
	// we can ignore Gusanos network in local play
	if(game.isLocalGame()) return;

	// dont send if in lobby
	if(game.state < Game::S_Preparing) return;

	if(m_control)
		m_control->olxSend(sendPendingOnly);
	else
		errors << "GusNetwork::olxSend: net control not initialised" << endl;
}

void Network::sendEncodedLuaEvents(Net_ConnID cid) {
	if(!m_control) {
		errors << "Network::sendEncodedLuaEvents: control unset" << endl;
		return;
	}

	// on the client side, this is handled in Client::Net_cbDataReceived
	std::auto_ptr<BitStream> data(new BitStream);
	Encoding::encode(*data, Network::ClientEvents::LuaEvents, Network::ClientEvents::Max);
	network.encodeLuaEvents(data.get());
	m_control->Net_sendData(cid, data.release(), eNet_ReliableOrdered);
}

<|endoftext|>


<commit_before>/*

DYADIC.cc -- interface implementation of dyadic numbers for the iRRAM library

Copyright (C) 2003 Norbert Mueller

This file is part of the iRRAM Library.

The iRRAM Library is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.

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

You should have received a copy of the GNU Library General Public License
along with the iRRAM Library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
*/
#include <cmath>
#include <stdlib.h>
#include <stdarg.h>

#include "iRRAM/core.h"

#if ($iRRAM_BACKEND == MPFR)
	#include "MPFR_ext.h"
#else
	#include "Currently no further backends defined!"
#endif

namespace iRRAM {

DYADIC::DYADIC() {
   MP_init(value);
   MP_int_to_mp(0,value);
};

DYADIC::DYADIC(MP_type  y) {
  value=y;
};

DYADIC::DYADIC(const int i) {
   MP_init(value);MP_int_to_mp(i,value);
};

DYADIC::DYADIC(const INTEGER& i) {
   MP_init(value);MP_INTEGER_to_mp(i.value,value);
};

DYADIC::DYADIC(const DYADIC& y) {
  MP_duplicate_w_init(y.value,value);
};

DYADIC::DYADIC(const double x) {
   MP_init(value);MP_double_to_mp(x,value);
};

DYADIC::~DYADIC() {
  MP_clear(value);
};

DYADIC ADD (const DYADIC& x, const DYADIC& y, const int p) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_add(x.value,y.value,zvalue,p);
  return zvalue;
};

DYADIC operator + (const DYADIC& x, const DYADIC& y) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_add(x.value,y.value,zvalue,iRRAM_DYADIC_precision);
  return zvalue;
};

DYADIC  operator +  (const int      x, const DYADIC&  y){return DYADIC(x)+y;};
DYADIC  operator +  (const DYADIC&  x, const int      y){return x+DYADIC(y);};
DYADIC  operator +  (const INTEGER& x, const DYADIC&  y){return DYADIC(x)+y;};
DYADIC  operator +  (const DYADIC&  x, const INTEGER& y){return x+DYADIC(y);};
DYADIC  operator +  (const double   x, const DYADIC&  y){return DYADIC(x)+y;};
DYADIC  operator +  (const DYADIC&  x, const double   y){return x+DYADIC(y);};

DYADIC SUB (const DYADIC& x, const DYADIC& y,const int p) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_sub(x.value,y.value,zvalue,p);
  return zvalue;
};

DYADIC operator - (const DYADIC& x, const DYADIC& y) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_sub(x.value,y.value,zvalue,iRRAM_DYADIC_precision);
  return zvalue;
};

DYADIC  operator -  (const int      x, const DYADIC&  y){return DYADIC(x)-y;};
DYADIC  operator -  (const DYADIC&  x, const int      y){return x-DYADIC(y);};
DYADIC  operator -  (const INTEGER& x, const DYADIC&  y){return DYADIC(x)-y;};
DYADIC  operator -  (const DYADIC&  x, const INTEGER& y){return x-DYADIC(y);};
DYADIC  operator -  (const double   x, const DYADIC&  y){return DYADIC(x)-y;};
DYADIC  operator -  (const DYADIC&  x, const double   y){return x-DYADIC(y);};

DYADIC operator - (const DYADIC& x) {
  DYADIC y;
  MP_type zvalue;
  MP_init(zvalue);
  MP_sub(y.value,x.value,zvalue,iRRAM_DYADIC_precision);
  return zvalue;
};

DYADIC MULT (const DYADIC& x, const DYADIC& y, const int p) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_mul(x.value,y.value,zvalue,p);
  return zvalue;
};

DYADIC operator * (const DYADIC& x, const DYADIC& y) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_mul(x.value,y.value,zvalue,iRRAM_DYADIC_precision);
  return zvalue;
};

DYADIC  operator *  (const int      x, const DYADIC&  y){return DYADIC(x)*y;};
DYADIC  operator *  (const DYADIC&  x, const int      y){return x*DYADIC(y);};
DYADIC  operator *  (const INTEGER& x, const DYADIC&  y){return DYADIC(x)*y;};
DYADIC  operator *  (const DYADIC&  x, const INTEGER& y){return x*DYADIC(y);};
DYADIC  operator *  (const double   x, const DYADIC&  y){return DYADIC(x)*y;};
DYADIC  operator *  (const DYADIC&  x, const double   y){return x*DYADIC(y);};

DYADIC DIV (const DYADIC& x, const DYADIC& y,const int p) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_div(x.value,y.value,zvalue,p);
  return zvalue;
};

DYADIC operator / (const DYADIC& x, const DYADIC& y) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_div(x.value,y.value,zvalue,iRRAM_DYADIC_precision);
  return zvalue;
};

DYADIC  operator /  (const int      x, const DYADIC&  y){return DYADIC(x)/y;};
DYADIC  operator /  (const DYADIC&  x, const int      y){return x/DYADIC(y);};
DYADIC  operator /  (const INTEGER& x, const DYADIC&  y){return DYADIC(x)/y;};
DYADIC  operator /  (const DYADIC&  x, const INTEGER& y){return x/DYADIC(y);};
DYADIC  operator /  (const double   x, const DYADIC&  y){return DYADIC(x)/y;};
DYADIC  operator /  (const DYADIC&  x, const double   y){return x/DYADIC(y);};

#ifdef MP_shift
DYADIC scale(const DYADIC& x, const int n) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_shift(x.value,zvalue,n);
  return DYADIC(zvalue);
}
#else
DYADIC scale(const DYADIC& x, int n) {
 exit(1);
//#error this can not be compiled
//#error the implementation is missing for this backend
}
#endif

DYADIC& DYADIC::operator = (const DYADIC& y) {
  MP_duplicate_wo_init(y.value,value);
  return (*this);
};

bool operator <  (const DYADIC& x, const DYADIC& y) {
  int erg=MP_compare((x.value),(y.value));
  return  (erg==-1);
};

bool operator <  (const int      x, const DYADIC&  y) {return DYADIC(x)<y;};
bool operator <  (const DYADIC&  x, const int      y) {return x<DYADIC(y);};
bool operator <  (const double   x, const DYADIC&  y) {return DYADIC(x)<y;};
bool operator <  (const DYADIC&  x, const double   y) {return x<DYADIC(y);};
bool operator <  (const INTEGER& x, const DYADIC&  y) {return DYADIC(x)<y;};
bool operator <  (const DYADIC&  x, const INTEGER  y) {return x<DYADIC(y);};

bool operator >  (const DYADIC&  x, const DYADIC&  y) {return (y<x);};
bool operator >  (const int      x, const DYADIC&  y) {return y<DYADIC(x);};
bool operator >  (const DYADIC&  x, const int      y) {return DYADIC(y)<x;};
bool operator >  (const double   x, const DYADIC&  y) {return y<DYADIC(x);};
bool operator >  (const DYADIC&  x, const double   y) {return DYADIC(y)<x;};
bool operator >  (const INTEGER& x, const DYADIC&  y) {return y<DYADIC(x);};
bool operator >  (const DYADIC&  x, const INTEGER  y) {return DYADIC(y)<x;};

bool operator <= (const DYADIC&  x, const DYADIC&  y) {return !(y<x);};
bool operator <= (const int      x, const DYADIC&  y) {return !(y<DYADIC(x));};
bool operator <= (const DYADIC&  x, const int      y) {return !(DYADIC(y)<x);};
bool operator <= (const double   x, const DYADIC&  y) {return !(y<DYADIC(x));};
bool operator <= (const DYADIC&  x, const double   y) {return !(DYADIC(y)<x);};
bool operator <= (const INTEGER& x, const DYADIC&  y) {return !(y<DYADIC(x));};
bool operator <= (const DYADIC&  x, const INTEGER  y) {return !(DYADIC(y)<x);};

bool operator >= (const DYADIC&  x, const DYADIC&  y) {return !(x<y);};
bool operator >= (const int      x, const DYADIC&  y) {return !(DYADIC(x)<y);};
bool operator >= (const DYADIC&  x, const int      y) {return !(x<DYADIC(y));};
bool operator >= (const double   x, const DYADIC&  y) {return !(DYADIC(x)<y);};
bool operator >= (const DYADIC&  x, const double   y) {return !(x<DYADIC(y));};
bool operator >= (const INTEGER& x, const DYADIC&  y) {return !(DYADIC(x)<y);};
bool operator >= (const DYADIC&  x, const INTEGER  y) {return !(x<DYADIC(y));};

bool operator == (const DYADIC& x, const DYADIC& y) {
  int erg=MP_compare((x.value),(y.value));
  return  (erg==0);
};
bool operator == (const int      x, const DYADIC&  y) {return DYADIC(x)==y;};
bool operator == (const DYADIC&  x, const int      y) {return x==DYADIC(y);};
bool operator == (const double   x, const DYADIC&  y) {return DYADIC(x)==y;};
bool operator == (const DYADIC&  x, const double   y) {return x==DYADIC(y);};
bool operator == (const INTEGER& x, const DYADIC&  y) {return DYADIC(x)==y;};
bool operator == (const DYADIC&  x, const INTEGER  y) {return x==DYADIC(y);};

bool operator != (const DYADIC&  x, const DYADIC&  y) {return !(x==y);};
bool operator != (const int      x, const DYADIC&  y) {return !(DYADIC(x)==y);};
bool operator != (const DYADIC&  x, const int      y) {return !(x==DYADIC(y));};
bool operator != (const double   x, const DYADIC&  y) {return !(DYADIC(x)==y);};
bool operator != (const DYADIC&  x, const double   y) {return !(x==DYADIC(y));};
bool operator != (const INTEGER& x, const DYADIC&  y) {return !(DYADIC(x)==y);};
bool operator != (const DYADIC&  x, const INTEGER  y) {return !(x==DYADIC(y));};

std::string swrite (const DYADIC& x,const int w){
  int width=w;
  if (width<9) width=9;
  char * s=MP_swrite(x.value,width);
  std::string erg=s;
  free(s);
  return erg;
}

int size (const DYADIC& x) {
  int s=MP_size((x.value));
  if ( s <= MP_min) throw iRRAM_Numerical_Exception(iRRAM_underflow_error);
  return s;
};

DYADIC abs (const DYADIC& x) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_abs(x.value,zvalue);
  return zvalue;
};

} // namespace iRRAM
<commit_msg>-Wpedantic: removed unneeded ";", reformatted comments<commit_after>/*

DYADIC.cc -- interface implementation of dyadic numbers for the iRRAM library

Copyright (C) 2003 Norbert Mueller

This file is part of the iRRAM Library.

The iRRAM Library is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.

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

You should have received a copy of the GNU Library General Public License
along with the iRRAM Library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
*/
#include <cmath>
#include <stdlib.h>
#include <stdarg.h>

#include "iRRAM/core.h"

#if ($iRRAM_BACKEND == MPFR)
	#include "MPFR_ext.h"
#else
	#include "Currently no further backends defined!"
#endif

namespace iRRAM {

DYADIC::DYADIC() {
   MP_init(value);
   MP_int_to_mp(0,value);
}

DYADIC::DYADIC(MP_type  y) {
  value=y;
}

DYADIC::DYADIC(const int i) {
   MP_init(value);MP_int_to_mp(i,value);
}

DYADIC::DYADIC(const INTEGER& i) {
   MP_init(value);MP_INTEGER_to_mp(i.value,value);
}

DYADIC::DYADIC(const DYADIC& y) {
  MP_duplicate_w_init(y.value,value);
}

DYADIC::DYADIC(const double x) {
   MP_init(value);MP_double_to_mp(x,value);
}

DYADIC::~DYADIC() {
  MP_clear(value);
}

DYADIC ADD (const DYADIC& x, const DYADIC& y, const int p) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_add(x.value,y.value,zvalue,p);
  return zvalue;
}

DYADIC operator + (const DYADIC& x, const DYADIC& y) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_add(x.value,y.value,zvalue,iRRAM_DYADIC_precision);
  return zvalue;
}

DYADIC  operator +  (const int      x, const DYADIC&  y){return DYADIC(x)+y;}
DYADIC  operator +  (const DYADIC&  x, const int      y){return x+DYADIC(y);}
DYADIC  operator +  (const INTEGER& x, const DYADIC&  y){return DYADIC(x)+y;}
DYADIC  operator +  (const DYADIC&  x, const INTEGER& y){return x+DYADIC(y);}
DYADIC  operator +  (const double   x, const DYADIC&  y){return DYADIC(x)+y;}
DYADIC  operator +  (const DYADIC&  x, const double   y){return x+DYADIC(y);}

DYADIC SUB (const DYADIC& x, const DYADIC& y,const int p) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_sub(x.value,y.value,zvalue,p);
  return zvalue;
}

DYADIC operator - (const DYADIC& x, const DYADIC& y) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_sub(x.value,y.value,zvalue,iRRAM_DYADIC_precision);
  return zvalue;
}

DYADIC  operator -  (const int      x, const DYADIC&  y){return DYADIC(x)-y;}
DYADIC  operator -  (const DYADIC&  x, const int      y){return x-DYADIC(y);}
DYADIC  operator -  (const INTEGER& x, const DYADIC&  y){return DYADIC(x)-y;}
DYADIC  operator -  (const DYADIC&  x, const INTEGER& y){return x-DYADIC(y);}
DYADIC  operator -  (const double   x, const DYADIC&  y){return DYADIC(x)-y;}
DYADIC  operator -  (const DYADIC&  x, const double   y){return x-DYADIC(y);}

DYADIC operator - (const DYADIC& x) {
  DYADIC y;
  MP_type zvalue;
  MP_init(zvalue);
  MP_sub(y.value,x.value,zvalue,iRRAM_DYADIC_precision);
  return zvalue;
}

DYADIC MULT (const DYADIC& x, const DYADIC& y, const int p) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_mul(x.value,y.value,zvalue,p);
  return zvalue;
}

DYADIC operator * (const DYADIC& x, const DYADIC& y) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_mul(x.value,y.value,zvalue,iRRAM_DYADIC_precision);
  return zvalue;
}

DYADIC  operator *  (const int      x, const DYADIC&  y){return DYADIC(x)*y;}
DYADIC  operator *  (const DYADIC&  x, const int      y){return x*DYADIC(y);}
DYADIC  operator *  (const INTEGER& x, const DYADIC&  y){return DYADIC(x)*y;}
DYADIC  operator *  (const DYADIC&  x, const INTEGER& y){return x*DYADIC(y);}
DYADIC  operator *  (const double   x, const DYADIC&  y){return DYADIC(x)*y;}
DYADIC  operator *  (const DYADIC&  x, const double   y){return x*DYADIC(y);}

DYADIC DIV (const DYADIC& x, const DYADIC& y,const int p) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_div(x.value,y.value,zvalue,p);
  return zvalue;
}

DYADIC operator / (const DYADIC& x, const DYADIC& y) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_div(x.value,y.value,zvalue,iRRAM_DYADIC_precision);
  return zvalue;
}

DYADIC  operator /  (const int      x, const DYADIC&  y){return DYADIC(x)/y;}
DYADIC  operator /  (const DYADIC&  x, const int      y){return x/DYADIC(y);}
DYADIC  operator /  (const INTEGER& x, const DYADIC&  y){return DYADIC(x)/y;}
DYADIC  operator /  (const DYADIC&  x, const INTEGER& y){return x/DYADIC(y);}
DYADIC  operator /  (const double   x, const DYADIC&  y){return DYADIC(x)/y;}
DYADIC  operator /  (const DYADIC&  x, const double   y){return x/DYADIC(y);}

#ifdef MP_shift
DYADIC scale(const DYADIC& x, const int n) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_shift(x.value,zvalue,n);
  return DYADIC(zvalue);
}
#else
DYADIC scale(const DYADIC& x, int n) {
 exit(1);
//#error this can not be compiled
//#error the implementation is missing for this backend
}
#endif

DYADIC& DYADIC::operator = (const DYADIC& y) {
  MP_duplicate_wo_init(y.value,value);
  return (*this);
}

bool operator <  (const DYADIC& x, const DYADIC& y) {
  int erg=MP_compare((x.value),(y.value));
  return  (erg==-1);
}

bool operator <  (const int      x, const DYADIC&  y) {return DYADIC(x)<y;}
bool operator <  (const DYADIC&  x, const int      y) {return x<DYADIC(y);}
bool operator <  (const double   x, const DYADIC&  y) {return DYADIC(x)<y;}
bool operator <  (const DYADIC&  x, const double   y) {return x<DYADIC(y);}
bool operator <  (const INTEGER& x, const DYADIC&  y) {return DYADIC(x)<y;}
bool operator <  (const DYADIC&  x, const INTEGER  y) {return x<DYADIC(y);}

bool operator >  (const DYADIC&  x, const DYADIC&  y) {return (y<x);}
bool operator >  (const int      x, const DYADIC&  y) {return y<DYADIC(x);}
bool operator >  (const DYADIC&  x, const int      y) {return DYADIC(y)<x;}
bool operator >  (const double   x, const DYADIC&  y) {return y<DYADIC(x);}
bool operator >  (const DYADIC&  x, const double   y) {return DYADIC(y)<x;}
bool operator >  (const INTEGER& x, const DYADIC&  y) {return y<DYADIC(x);}
bool operator >  (const DYADIC&  x, const INTEGER  y) {return DYADIC(y)<x;}

bool operator <= (const DYADIC&  x, const DYADIC&  y) {return !(y<x);}
bool operator <= (const int      x, const DYADIC&  y) {return !(y<DYADIC(x));}
bool operator <= (const DYADIC&  x, const int      y) {return !(DYADIC(y)<x);}
bool operator <= (const double   x, const DYADIC&  y) {return !(y<DYADIC(x));}
bool operator <= (const DYADIC&  x, const double   y) {return !(DYADIC(y)<x);}
bool operator <= (const INTEGER& x, const DYADIC&  y) {return !(y<DYADIC(x));}
bool operator <= (const DYADIC&  x, const INTEGER  y) {return !(DYADIC(y)<x);}

bool operator >= (const DYADIC&  x, const DYADIC&  y) {return !(x<y);}
bool operator >= (const int      x, const DYADIC&  y) {return !(DYADIC(x)<y);}
bool operator >= (const DYADIC&  x, const int      y) {return !(x<DYADIC(y));}
bool operator >= (const double   x, const DYADIC&  y) {return !(DYADIC(x)<y);}
bool operator >= (const DYADIC&  x, const double   y) {return !(x<DYADIC(y));}
bool operator >= (const INTEGER& x, const DYADIC&  y) {return !(DYADIC(x)<y);}
bool operator >= (const DYADIC&  x, const INTEGER  y) {return !(x<DYADIC(y));}

bool operator == (const DYADIC& x, const DYADIC& y) {
  int erg=MP_compare((x.value),(y.value));
  return  (erg==0);
}
bool operator == (const int      x, const DYADIC&  y) {return DYADIC(x)==y;}
bool operator == (const DYADIC&  x, const int      y) {return x==DYADIC(y);}
bool operator == (const double   x, const DYADIC&  y) {return DYADIC(x)==y;}
bool operator == (const DYADIC&  x, const double   y) {return x==DYADIC(y);}
bool operator == (const INTEGER& x, const DYADIC&  y) {return DYADIC(x)==y;}
bool operator == (const DYADIC&  x, const INTEGER  y) {return x==DYADIC(y);}

bool operator != (const DYADIC&  x, const DYADIC&  y) {return !(x==y);}
bool operator != (const int      x, const DYADIC&  y) {return !(DYADIC(x)==y);}
bool operator != (const DYADIC&  x, const int      y) {return !(x==DYADIC(y));}
bool operator != (const double   x, const DYADIC&  y) {return !(DYADIC(x)==y);}
bool operator != (const DYADIC&  x, const double   y) {return !(x==DYADIC(y));}
bool operator != (const INTEGER& x, const DYADIC&  y) {return !(DYADIC(x)==y);}
bool operator != (const DYADIC&  x, const INTEGER  y) {return !(x==DYADIC(y));}

std::string swrite (const DYADIC& x,const int w){
  int width=w;
  if (width<9) width=9;
  char * s=MP_swrite(x.value,width);
  std::string erg=s;
  free(s);
  return erg;
}

int size (const DYADIC& x) {
  int s=MP_size((x.value));
  if ( s <= MP_min) throw iRRAM_Numerical_Exception(iRRAM_underflow_error);
  return s;
}

DYADIC abs (const DYADIC& x) {
  MP_type zvalue;
  MP_init(zvalue);
  MP_abs(x.value,zvalue);
  return zvalue;
}

} // namespace iRRAM
<|endoftext|>


<commit_before>#include <MacTypes.h>
#include "actor-zeta/messaging/message_header.hpp"

namespace actor_zeta {
    namespace messaging {
        message_header::message_header(const char *str, std::size_t len)
                : type_(str, len),  prioritie(message_priority::normal), callback(false) {}

        message_header::message_header(const char *str, std::size_t len, actor::actor_address aa)
                : type_(str, len),  prioritie(message_priority::normal), callback(true), address(aa) {}

        message_header::message_header(const char *str, std::size_t len, message_priority p)
                :type_(str, len),  prioritie(p), callback(false) {}

        message_header::message_header(const char *str, std::size_t len, message_priority p, actor::actor_address aa)
                : type_(str, len), prioritie(p), callback(true), address(aa) {}

        auto message_header::type() const -> const behavior::type_action & {
            return type_;
        }

        actor::actor_address message_header::return_address() const {
            return address;
        }

        bool message_header::is_callback() const {
            return callback;
        }

        message_priority message_header::priorities() const {
            return prioritie;
        }
    }
}<commit_msg>removed the wrong include<commit_after>#include "actor-zeta/messaging/message_header.hpp"

namespace actor_zeta {
    namespace messaging {
        message_header::message_header(const char *str, std::size_t len)
                : type_(str, len),  prioritie(message_priority::normal), callback(false) {}

        message_header::message_header(const char *str, std::size_t len, actor::actor_address aa)
                : type_(str, len),  prioritie(message_priority::normal), callback(true), address(aa) {}

        message_header::message_header(const char *str, std::size_t len, message_priority p)
                :type_(str, len),  prioritie(p), callback(false) {}

        message_header::message_header(const char *str, std::size_t len, message_priority p, actor::actor_address aa)
                : type_(str, len), prioritie(p), callback(true), address(aa) {}

        auto message_header::type() const -> const behavior::type_action & {
            return type_;
        }

        actor::actor_address message_header::return_address() const {
            return address;
        }

        bool message_header::is_callback() const {
            return callback;
        }

        message_priority message_header::priorities() const {
            return prioritie;
        }
    }
}<|endoftext|>


<commit_before>
#ifdef _MSC_VER
#include <Windows.h>
#endif
#include <cstdio>
#include <cstdarg>
#include <malloc.h>

#include <nstd/Debug.h>
#include <nstd/Memory.h>

int_t Debug::print(const tchar_t* str)
{
#ifdef _MSC_VER
  OutputDebugString(str);
#ifdef _UNICODE
  return (int_t)wcslen(str);
#else
  return (int_t)strlen(str);
#endif
#else
  return fputs(str, stderr);
#endif
}

int_t Debug::printf(const tchar_t* format, ...)
{
#ifdef _MSC_VER
  va_list ap;
  va_start(ap, format);
  {
    tchar_t buffer[4096];
#if _UNICODE
    int_t result = _vsnwprintf(buffer, sizeof(buffer), format, ap);
#else
    int_t result = vsnprintf(buffer, sizeof(buffer), format, ap);
#endif
    if(result >= 0 && result < (int_t)sizeof(buffer))
    {
      OutputDebugString(buffer);
      va_end(ap);
      return result;
    }
  }

  // buffer was too small
  {
    int_t result;
#ifdef _UNICODE
    result = _vscwprintf(format, ap);
#else
    result = _vscprintf(format, ap);
#endif
    size_t maxCount = result + 1;
    tchar_t* buffer, *allocatedBuffer = 0;
    try // try using stack buffer
    {
      buffer = (tchar_t*)alloca(maxCount * sizeof(tchar_t));
    }
    catch(...) // fall back on heap buffer
    {
      buffer = (tchar_t*)Memory::alloc(maxCount * sizeof(tchar_t));
      allocatedBuffer = buffer;
    }
#ifdef _UNICODE
    result = _vsnwprintf(buffer, maxCount, format, ap);
#else
    result = vsnprintf(buffer, maxCount, format, ap);
#endif
    va_end(ap);
    OutputDebugString(buffer);
    if(allocatedBuffer)
      Memory::free(allocatedBuffer);
    return result;
  }
#else
  va_list ap;
  va_start(ap, format);
  int_t result = vfprintf(stderr, format, ap);
  va_end(ap);
  return result;
#endif
}
<commit_msg>Debug: Do not use alloca<commit_after>
#ifdef _MSC_VER
#include <Windows.h>
#endif
#include <cstdio>
#include <cstdarg>

#include <nstd/Debug.h>
#include <nstd/Memory.h>

int_t Debug::print(const tchar_t* str)
{
#ifdef _MSC_VER
  OutputDebugString(str);
#ifdef _UNICODE
  return (int_t)wcslen(str);
#else
  return (int_t)strlen(str);
#endif
#else
  return fputs(str, stderr);
#endif
}

int_t Debug::printf(const tchar_t* format, ...)
{
#ifdef _MSC_VER
  va_list ap;
  va_start(ap, format);
  {
    tchar_t buffer[4096];
#if _UNICODE
    int_t result = _vsnwprintf(buffer, sizeof(buffer), format, ap);
#else
    int_t result = vsnprintf(buffer, sizeof(buffer), format, ap);
#endif
    if(result >= 0 && result < (int_t)sizeof(buffer))
    {
      OutputDebugString(buffer);
      va_end(ap);
      return result;
    }
  }

  // buffer was too small
  {
    int_t result;
#ifdef _UNICODE
    result = _vscwprintf(format, ap);
#else
    result = _vscprintf(format, ap);
#endif
    size_t maxCount = result + 1;
    tchar_t* buffer = (tchar_t*)Memory::alloc(maxCount * sizeof(tchar_t));
#ifdef _UNICODE
    result = _vsnwprintf(buffer, maxCount, format, ap);
#else
    result = vsnprintf(buffer, maxCount, format, ap);
#endif
    va_end(ap);
    OutputDebugString(buffer);
    Memory::free(buffer);
    return result;
  }
#else
  va_list ap;
  va_start(ap, format);
  int_t result = vfprintf(stderr, format, ap);
  va_end(ap);
  return result;
#endif
}
<|endoftext|>