<commit_before>/**
 * @file		iprofile.hpp
 * @brief		Component Profile interface class
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 6. 21
 * @details	Read component profile interface
 */

#ifndef _COSSB_IPROFILE_HPP_
#define _COSSB_IPROFILE_HPP_

#include <string>
#include <vector>
#include <map>
#include <boost/lexical_cast.hpp>
#include <cstring>
#include <algorithm>
#include <util/format.h>
#include <util/uuid.hpp>

using namespace std;
using namespace cossb;

namespace cossb {
namespace service {

/**
 * @brief	service method type
 */
enum class methodtype : int {
	PUBLISH = 1,
	SUBSCRIBE,
	UNDEFINED,
};

/**
 * @brief	service method
 */
typedef struct _service_method {
public:
	_service_method():method(methodtype::UNDEFINED) {}
	_service_method(const char* type) {
		if(strcmp(type, "publish")==0)
			method = methodtype::PUBLISH;
		else if(strcmp(type, "subscribe")==0)
			method = methodtype::SUBSCRIBE;
	}
	const char* str() {
		string mt = "Undefined";
		switch(method) {
		case methodtype::PUBLISH: mt = "Publish"; break;
		case methodtype::SUBSCRIBE: mt = "Subscribe"; break;
		case methodtype::UNDEFINED: mt = "Undefined"; break;
		}
		return mt.c_str();
	}
	_service_method& operator= (_service_method const& m) { this->method = m.method; return *this; }
private:
	methodtype method = methodtype::UNDEFINED;
} service_method;

/**
 * @brief	service description
 */

typedef struct _service_desc {
private:
	util::uuid service_id;	//service id
public:
	string component_name;	//component name
	string name;				//service name
	service_method method;	//service method
	string topic;				//service topic
	const char* show() {
		return fmt::format("[{}] Name : {}, Method : {}, Topic : {}", service_id.str(), name, method.str(), topic).c_str();
	}
} service_desc;

/**
 * @brief	profile service section container
 */
typedef vector<service::service_desc> service_desc_container;

} /* namespace service */

namespace interface { class iprofile; }

namespace profile {

/**
 * @brief	profile information section container
 */
//typedef map<string, string> profile_info_container;

enum class section : unsigned int {
	info = 0,	//component information
	property, 	//properties
	resource,	//related resource
	service,	//service supporting
};

class type_value
{
public:
	type_value():value("") { }
	type_value(const char* val) { this->value = val; }
	virtual ~type_value() { }

	friend class interface::iprofile;

	template<typename T>
	inline T as(T default_value) {
		try {
			T val = boost::lexical_cast<T>(value);
			return val;
		} catch( boost::bad_lexical_cast const& ) {
			return default_value;
		}
	}

	int asInt(int default_value) { return as(default_value); }
	unsigned int asUInt(unsigned int default_value) { return as(default_value); }
	unsigned long asUlong(unsigned long default_value) { return as(default_value); }
	double asDouble(double default_value) { return as(default_value); }
	float asFloat(float default_value) { return as(default_value); }
	bool asBool(bool default_value) { return as(default_value); }
	string asString(string default_value) { return as(default_value); }
	unsigned char asUChar(unsigned char default_value) { return as(default_value); }
	char asChar(char default_value) { return as(default_value); }

private:
	std::string value;

};
}

namespace driver { class component_driver; }
namespace manager { class component_manager; }

namespace interface {
class icomponent;
class iprofile {

	friend class driver::component_driver;
	friend class manager::component_manager;

public:
	iprofile() { }
	virtual ~iprofile() {
		_services.clear();
	}

	/**
	 * @brief	get profile value list
	 */
	virtual vector<profile::type_value> gets(profile::section section, const char* element) = 0;
	virtual vector<string> gets(profile::section section, const char* element) = 0;

	/**
	 * @brief	get profile value
	 */
	virtual profile::type_value get(profile::section section, const char* element) = 0;

	/**
	 * @brief	get attribute in element
	 */
	virtual profile::type_value get_attribute(string& node, const char* attr) = 0;

	/**
	 * @brief	update profile value
	 */
	virtual bool update(profile::section section, const char* element, const char* value) = 0;

	/**
	 * @brief	save profile
	 */
	virtual bool save() = 0;

private:
	/**
	 * @brief	load profile
	 */
	virtual bool load(icomponent* pComponent, const char* filepath) = 0;

protected:
	/**
	 * @brief
	 */
	void set(profile::type_value& profile, string value) { profile.value = value; }

	/**
	 * @brief	insert into the service container
	 * @return total number of services registered
	 */
	int add(service::service_desc& svc) {
		_services.push_back(svc);
		return _services.size();
	}

private:

	/**
	 * @brief	service description container
	 */
	service::service_desc_container _services;

};

} /* namespace interface */
} /* namespace cossb */

#endif
<commit_msg>bug fixed<commit_after>/**
 * @file		iprofile.hpp
 * @brief		Component Profile interface class
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 6. 21
 * @details	Read component profile interface
 */

#ifndef _COSSB_IPROFILE_HPP_
#define _COSSB_IPROFILE_HPP_

#include <string>
#include <vector>
#include <map>
#include <boost/lexical_cast.hpp>
#include <cstring>
#include <algorithm>
#include <util/format.h>
#include <util/uuid.hpp>

using namespace std;
using namespace cossb;

namespace cossb {
namespace service {

/**
 * @brief	service method type
 */
enum class methodtype : int {
	PUBLISH = 1,
	SUBSCRIBE,
	UNDEFINED,
};

/**
 * @brief	service method
 */
typedef struct _service_method {
public:
	_service_method():method(methodtype::UNDEFINED) {}
	_service_method(const char* type) {
		if(strcmp(type, "publish")==0)
			method = methodtype::PUBLISH;
		else if(strcmp(type, "subscribe")==0)
			method = methodtype::SUBSCRIBE;
	}
	const char* str() {
		string mt = "Undefined";
		switch(method) {
		case methodtype::PUBLISH: mt = "Publish"; break;
		case methodtype::SUBSCRIBE: mt = "Subscribe"; break;
		case methodtype::UNDEFINED: mt = "Undefined"; break;
		}
		return mt.c_str();
	}
	_service_method& operator= (_service_method const& m) { this->method = m.method; return *this; }
private:
	methodtype method = methodtype::UNDEFINED;
} service_method;

/**
 * @brief	service description
 */

typedef struct _service_desc {
private:
	util::uuid service_id;	//service id
public:
	string component_name;	//component name
	string name;				//service name
	service_method method;	//service method
	string topic;				//service topic
	const char* show() {
		return fmt::format("[{}] Name : {}, Method : {}, Topic : {}", service_id.str(), name, method.str(), topic).c_str();
	}
} service_desc;

/**
 * @brief	profile service section container
 */
typedef vector<service::service_desc> service_desc_container;

} /* namespace service */

namespace interface { class iprofile; }

namespace profile {

/**
 * @brief	profile information section container
 */
//typedef map<string, string> profile_info_container;

enum class section : unsigned int {
	info = 0,	//component information
	property, 	//properties
	resource,	//related resource
	service,	//service supporting
};

class type_value
{
public:
	type_value():value("") { }
	type_value(const char* val) { this->value = val; }
	virtual ~type_value() { }

	friend class interface::iprofile;

	template<typename T>
	inline T as(T default_value) {
		try {
			T val = boost::lexical_cast<T>(value);
			return val;
		} catch( boost::bad_lexical_cast const& ) {
			return default_value;
		}
	}

	int asInt(int default_value) { return as(default_value); }
	unsigned int asUInt(unsigned int default_value) { return as(default_value); }
	unsigned long asUlong(unsigned long default_value) { return as(default_value); }
	double asDouble(double default_value) { return as(default_value); }
	float asFloat(float default_value) { return as(default_value); }
	bool asBool(bool default_value) { return as(default_value); }
	string asString(string default_value) { return as(default_value); }
	unsigned char asUChar(unsigned char default_value) { return as(default_value); }
	char asChar(char default_value) { return as(default_value); }

private:
	std::string value;

};
}

namespace driver { class component_driver; }
namespace manager { class component_manager; }

namespace interface {
class icomponent;
class iprofile {

	friend class driver::component_driver;
	friend class manager::component_manager;

public:
	iprofile() { }
	virtual ~iprofile() {
		_services.clear();
	}

	/**
	 * @brief	get profile value list
	 */
	virtual vector<profile::type_value> gets(profile::section section, const char* element) = 0;

	/**
	 * @brief	get profile value
	 */
	virtual profile::type_value get(profile::section section, const char* element) = 0;

	/**
	 * @brief	get attribute in element
	 */
	virtual profile::type_value get_attribute(string& node, const char* attr) = 0;

	/**
	 * @brief	update profile value
	 */
	virtual bool update(profile::section section, const char* element, const char* value) = 0;

	/**
	 * @brief	save profile
	 */
	virtual bool save() = 0;

private:
	/**
	 * @brief	load profile
	 */
	virtual bool load(icomponent* pComponent, const char* filepath) = 0;

protected:
	/**
	 * @brief
	 */
	void set(profile::type_value& profile, string value) { profile.value = value; }

	/**
	 * @brief	insert into the service container
	 * @return total number of services registered
	 */
	int add(service::service_desc& svc) {
		_services.push_back(svc);
		return _services.size();
	}

private:

	/**
	 * @brief	service description container
	 */
	service::service_desc_container _services;

};

} /* namespace interface */
} /* namespace cossb */

#endif
<|endoftext|>


<commit_before>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2008 <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "Common.h"
#include "Config/ConfigEnv.h"
#include "Log.h"
#include "NGLog.h"
#include <stdarg.h>

string FormatOutputString(const char * Prefix, const char * Description, bool useTimeStamp)
{

	char p[MAX_PATH];
	p[0] = 0;
	time_t t = time(NULL);
	tm * a = gmtime(&t);
	strcat(p, Prefix);
	strcat(p, "/");
	strcat(p, Description);
	if(useTimeStamp)
	{
		char ftime[100];
		snprintf(ftime, 100, "-%-4d-%02d-%02d %02d-%02d-%02d", a->tm_year+1900, a->tm_mon+1, a->tm_mday, a->tm_hour, a->tm_min, a->tm_sec);
		strcat(p, ftime);
	}

	strcat(p, ".log");
	return string(p);
}

createFileSingleton( oLog );
createFileSingleton(CLog);
initialiseSingleton( WorldLog );

SERVER_DECL time_t UNIXTIME;
SERVER_DECL tm g_localTime;
#ifndef WIN32
static const char* colorstrings[TBLUE+1] = {
"",
"\033[22;31m",
"\033[22;32m",
"\033[01;33m",
//"\033[22;37m",
"\033[0m",
"\033[01;37m",
"\033[22;34m",
};
#endif

void oLog::outTime()
{
#ifndef WIN32
	char buf[256];
	time_t t = time(NULL);
	struct tm *tm = localtime(&t);

	if (tm)
	{
		strftime(buf, 256, "[%Y-%m-%d %T] ", tm);
		fprintf(m_file, buf);
	}
#endif
}

void oLog::outString( const char * str, ... )
{
	va_list ap;
	char buf[32768];

	if(m_fileLogLevel < 0 && m_screenLogLevel < 0)
		return;

	va_start(ap, str);
	vsnprintf(buf, 32768, str, ap);
	va_end(ap);

	if(m_screenLogLevel >= 0)
	{
		printf(str);
		putc('\n', stdout);
	}
	if(m_fileLogLevel >= 0 && m_file)
	{
		outTime();
		fprintf(m_file, str);
		putc('\n', m_file);
	}
}

void oLog::outError( const char * err, ... )
{
	va_list ap;
	char buf[32768];

	if(m_fileLogLevel < 1 && m_screenLogLevel < 1)
		return;

	va_start(ap, err);
	vsnprintf(buf, 32768, err, ap);
	va_end(ap);

	if(m_screenLogLevel >= 1)
	{
#ifdef WIN32
		SetConsoleTextAttribute(stderr_handle, FOREGROUND_RED | FOREGROUND_INTENSITY);
#else
		puts(colorstrings[TRED]);
#endif
		fprintf(stderr, err);
		putc('\n', stderr);
#ifdef WIN32
		SetConsoleTextAttribute(stderr_handle, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN);
#else
		puts(colorstrings[TNORMAL]);
#endif
	}
	if(m_fileLogLevel >= 1 && m_file)
	{
		outTime();
		fprintf(m_file, err);
		putc('\n', m_file);
	}
}

void oLog::outBasic( const char * str, ... )
{
	va_list ap;
	char buf[32768];

	if(m_fileLogLevel < 1 && m_screenLogLevel < 1)
		return;

	va_start(ap, str);
	vsnprintf(buf, 32768, str, ap);
	va_end(ap);

	if(m_screenLogLevel >= 1)
	{
		printf(str);
		putc('\n', stdout);
	}
	if(m_fileLogLevel >= 1 && m_file)
	{
		fprintf(m_file, str);
		putc('\n', m_file);
	}
}

void oLog::outDetail( const char * str, ... )
{
	va_list ap;
	char buf[32768];

	if(m_fileLogLevel < 2 && m_screenLogLevel < 2)
		return;

	va_start(ap, str);
	vsnprintf(buf, 32768, str, ap);
	va_end(ap);

	if(m_screenLogLevel >= 2)
	{
		printf(str);
		putc('\n', stdout);
	}
	if(m_fileLogLevel >= 2 && m_file)
	{
		outTime();
		fprintf(m_file, str);
		putc('\n', m_file);
	}
}

void oLog::outDebug( const char * str, ... )
{
	va_list ap;
	char buf[32768];

	if(m_fileLogLevel < 3 && m_screenLogLevel < 3)
		return;

	va_start(ap, str);
	vsnprintf(buf, 32768, str, ap);
	va_end(ap);

	if(m_screenLogLevel >= 3)
	{
		printf(str);
		putc('\n', stdout);
	}
	if(m_fileLogLevel >= 3 && m_file)
	{
		outTime();
		fprintf(m_file, str);
		putc('\n', m_file);
	}
}

void oLog::outMenu( const char * str, ... )
{
	va_list ap;
	va_start(ap, str);
	vprintf( str, ap );
	va_end(ap);
	fflush(stdout);
}

void oLog::Init(int32 fileLogLevel, int32 screenLogLevel)
{
	m_screenLogLevel = screenLogLevel;
	m_fileLogLevel = fileLogLevel;

	// get error handle
#ifdef WIN32
	stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
	stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
#endif
}

void oLog::SetScreenLoggingLevel(int32 level)
{
	m_screenLogLevel = level;
}

void oLog::SetFileLoggingLevel(int32 level)
{
	m_fileLogLevel = level;

	if (m_fileLogLevel >= 0)
	{
		char *filename = "file.log";
		m_file = fopen(filename, "w");
		if (m_file == NULL)
		{
			fprintf(stderr, "%s: Error opening '%s': %s\n", __FUNCTION__, filename, strerror(errno));
		}
	}
}

void SessionLogWriter::write(const char* format, ...)
{
	if(!m_file)
		return;

	va_list ap;
	va_start(ap, format);
	char out[32768];

	time_t t = time(NULL);
	tm* aTm = localtime(&t);
	sprintf(out, "[%-4d-%02d-%02d %02d:%02d:%02d] ",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec);
	size_t l = strlen(out);
	vsnprintf(&out[l], 32768 - l, format, ap);

	fprintf(m_file, "%s\n", out);
	va_end(ap);
}

WorldLog::WorldLog()
{
	bEnabled = false;
	m_file=NULL;

	if (Config.MainConfig.GetBoolDefault("LogLevel", "World", false))
	{
		Log.Notice("WorldLog", "Enabling packetlog output to \"world.log\"");
		Enable();
	} else {
		Disable();
	}
}

void WorldLog::Enable()
{
	if(bEnabled)
		return;

	bEnabled = true;
	if(m_file != NULL)
	{
		Disable();
		bEnabled=true;
	}
	m_file = fopen("world.log", "w");
}

void WorldLog::Disable()
{
	if(!bEnabled)
		return;

	bEnabled = false;
	if(!m_file)
		return;

	fflush(m_file);
	fclose(m_file);
	m_file=NULL;
}

WorldLog::~WorldLog()
{

}

void oLog::outColor(uint32 colorcode, const char * str, ...)
{
	if( !str ) return;
	va_list ap;
	va_start(ap, str);
#ifdef WIN32
	SetConsoleTextAttribute(stdout_handle, colorcode);
#else
	printf(colorstrings[colorcode]);
#endif
	vprintf( str, ap );
	fflush(stdout);
	va_end(ap);
}

void SessionLogWriter::Open()
{
	m_file = fopen(m_filename, "a");
}

void SessionLogWriter::Close()
{
	if(!m_file) return;
	fflush(m_file);
	fclose(m_file);
	m_file=NULL;
}

SessionLogWriter::SessionLogWriter(const char * filename, bool open)
{
	m_filename = strdup(filename);
	m_file=NULL;
	if(open)
		Open();
}

SessionLogWriter::~SessionLogWriter()
{
	if(m_file)
		Close();

	free(m_filename);
}
<commit_msg>whoopss xD<commit_after>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2008 <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "Common.h"
#include "Config/ConfigEnv.h"
#include "Log.h"
#include "NGLog.h"
#include <stdarg.h>

string FormatOutputString(const char * Prefix, const char * Description, bool useTimeStamp)
{

	char p[MAX_PATH];
	p[0] = 0;
	time_t t = time(NULL);
	tm * a = gmtime(&t);
	strcat(p, Prefix);
	strcat(p, "/");
	strcat(p, Description);
	if(useTimeStamp)
	{
		char ftime[100];
		snprintf(ftime, 100, "-%-4d-%02d-%02d %02d-%02d-%02d", a->tm_year+1900, a->tm_mon+1, a->tm_mday, a->tm_hour, a->tm_min, a->tm_sec);
		strcat(p, ftime);
	}

	strcat(p, ".log");
	return string(p);
}

createFileSingleton( oLog );
createFileSingleton(CLog);
initialiseSingleton( WorldLog );

SERVER_DECL time_t UNIXTIME;
SERVER_DECL tm g_localTime;
#ifndef WIN32
static const char* colorstrings[TBLUE+1] = {
"",
"\033[22;31m",
"\033[22;32m",
"\033[01;33m",
//"\033[22;37m",
"\033[0m",
"\033[01;37m",
"\033[22;34m",
};
#endif

void oLog::outTime()
{
#ifndef WIN32
	char buf[256];
	time_t t = time(NULL);
	struct tm *tm = localtime(&t);

	if (tm)
	{
		strftime(buf, 256, "[%Y-%m-%d %T] ", tm);
		fprintf(m_file, buf);
	}
#endif
}

void oLog::outString( const char * str, ... )
{
	va_list ap;
	char buf[32768];

	if(m_fileLogLevel < 0 && m_screenLogLevel < 0)
		return;

	va_start(ap, str);
	vsnprintf(buf, 32768, str, ap);
	va_end(ap);

	if(m_screenLogLevel >= 0)
	{
		printf(buf);
		putc('\n', stdout);
	}
	if(m_fileLogLevel >= 0 && m_file)
	{
		outTime();
		fprintf(m_file, buf);
		putc('\n', m_file);
	}
}

void oLog::outError( const char * err, ... )
{
	va_list ap;
	char buf[32768];

	if(m_fileLogLevel < 1 && m_screenLogLevel < 1)
		return;

	va_start(ap, err);
	vsnprintf(buf, 32768, err, ap);
	va_end(ap);

	if(m_screenLogLevel >= 1)
	{
#ifdef WIN32
		SetConsoleTextAttribute(stderr_handle, FOREGROUND_RED | FOREGROUND_INTENSITY);
#else
		puts(colorstrings[TRED]);
#endif
		fprintf(stderr, buf);
		putc('\n', stderr);
#ifdef WIN32
		SetConsoleTextAttribute(stderr_handle, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN);
#else
		puts(colorstrings[TNORMAL]);
#endif
	}
	if(m_fileLogLevel >= 1 && m_file)
	{
		outTime();
		fprintf(m_file, buf);
		putc('\n', m_file);
	}
}

void oLog::outBasic( const char * str, ... )
{
	va_list ap;
	char buf[32768];

	if(m_fileLogLevel < 1 && m_screenLogLevel < 1)
		return;

	va_start(ap, str);
	vsnprintf(buf, 32768, str, ap);
	va_end(ap);

	if(m_screenLogLevel >= 1)
	{
		printf(buf);
		putc('\n', stdout);
	}
	if(m_fileLogLevel >= 1 && m_file)
	{
		fprintf(m_file, buf);
		putc('\n', m_file);
	}
}

void oLog::outDetail( const char * str, ... )
{
	va_list ap;
	char buf[32768];

	if(m_fileLogLevel < 2 && m_screenLogLevel < 2)
		return;

	va_start(ap, str);
	vsnprintf(buf, 32768, str, ap);
	va_end(ap);

	if(m_screenLogLevel >= 2)
	{
		printf(buf);
		putc('\n', stdout);
	}
	if(m_fileLogLevel >= 2 && m_file)
	{
		outTime();
		fprintf(m_file, buf);
		putc('\n', m_file);
	}
}

void oLog::outDebug( const char * str, ... )
{
	va_list ap;
	char buf[32768];

	if(m_fileLogLevel < 3 && m_screenLogLevel < 3)
		return;

	va_start(ap, str);
	vsnprintf(buf, 32768, str, ap);
	va_end(ap);

	if(m_screenLogLevel >= 3)
	{
		printf(buf);
		putc('\n', stdout);
	}
	if(m_fileLogLevel >= 3 && m_file)
	{
		outTime();
		fprintf(m_file, buf);
		putc('\n', m_file);
	}
}

void oLog::outMenu( const char * str, ... )
{
	va_list ap;
	va_start(ap, str);
	vprintf( str, ap );
	va_end(ap);
	fflush(stdout);
}

void oLog::Init(int32 fileLogLevel, int32 screenLogLevel)
{
	m_screenLogLevel = screenLogLevel;
	m_fileLogLevel = fileLogLevel;

	// get error handle
#ifdef WIN32
	stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
	stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
#endif
}

void oLog::SetScreenLoggingLevel(int32 level)
{
	m_screenLogLevel = level;
}

void oLog::SetFileLoggingLevel(int32 level)
{
	m_fileLogLevel = level;

	if (m_fileLogLevel >= 0)
	{
		char *filename = "file.log";
		m_file = fopen(filename, "w");
		if (m_file == NULL)
		{
			fprintf(stderr, "%s: Error opening '%s': %s\n", __FUNCTION__, filename, strerror(errno));
		}
	}
}

void SessionLogWriter::write(const char* format, ...)
{
	if(!m_file)
		return;

	va_list ap;
	va_start(ap, format);
	char out[32768];

	time_t t = time(NULL);
	tm* aTm = localtime(&t);
	sprintf(out, "[%-4d-%02d-%02d %02d:%02d:%02d] ",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec);
	size_t l = strlen(out);
	vsnprintf(&out[l], 32768 - l, format, ap);

	fprintf(m_file, "%s\n", out);
	va_end(ap);
}

WorldLog::WorldLog()
{
	bEnabled = false;
	m_file=NULL;

	if (Config.MainConfig.GetBoolDefault("LogLevel", "World", false))
	{
		Log.Notice("WorldLog", "Enabling packetlog output to \"world.log\"");
		Enable();
	} else {
		Disable();
	}
}

void WorldLog::Enable()
{
	if(bEnabled)
		return;

	bEnabled = true;
	if(m_file != NULL)
	{
		Disable();
		bEnabled=true;
	}
	m_file = fopen("world.log", "w");
}

void WorldLog::Disable()
{
	if(!bEnabled)
		return;

	bEnabled = false;
	if(!m_file)
		return;

	fflush(m_file);
	fclose(m_file);
	m_file=NULL;
}

WorldLog::~WorldLog()
{

}

void oLog::outColor(uint32 colorcode, const char * str, ...)
{
	if( !str ) return;
	va_list ap;
	va_start(ap, str);
#ifdef WIN32
	SetConsoleTextAttribute(stdout_handle, colorcode);
#else
	printf(colorstrings[colorcode]);
#endif
	vprintf( str, ap );
	fflush(stdout);
	va_end(ap);
}

void SessionLogWriter::Open()
{
	m_file = fopen(m_filename, "a");
}

void SessionLogWriter::Close()
{
	if(!m_file) return;
	fflush(m_file);
	fclose(m_file);
	m_file=NULL;
}

SessionLogWriter::SessionLogWriter(const char * filename, bool open)
{
	m_filename = strdup(filename);
	m_file=NULL;
	if(open)
		Open();
}

SessionLogWriter::~SessionLogWriter()
{
	if(m_file)
		Close();

	free(m_filename);
}
<|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_ADDRESS_HPP_INCLUDED
#define TORRENT_ADDRESS_HPP_INCLUDED

#include <boost/version.hpp>

#ifdef __OBJC__
#define Protocol Protocol_
#endif

#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif

#if BOOST_VERSION < 103500
#include <asio/ip/address.hpp>
#else
#include <boost/asio/ip/address.hpp>
#endif

#ifdef __OBJC__
#undef Protocol
#endif

namespace libtorrent
{

#if BOOST_VERSION < 103500
	typedef ::asio::ip::address address;
	typedef ::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef ::asio::ip::address_v6 address_v6;
#endif
#else
	typedef boost::asio::ip::address address;
	typedef boost::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef boost::asio::ip::address_v6 address_v6;
#endif
#endif
}

#endif

<commit_msg>include config.hpp<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_ADDRESS_HPP_INCLUDED
#define TORRENT_ADDRESS_HPP_INCLUDED

#include <boost/version.hpp>
#include "libtorrent/config.hpp"

#ifdef __OBJC__
#define Protocol Protocol_
#endif

#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif

#if BOOST_VERSION < 103500
#include <asio/ip/address.hpp>
#else
#include <boost/asio/ip/address.hpp>
#endif

#ifdef __OBJC__
#undef Protocol
#endif

namespace libtorrent
{

#if BOOST_VERSION < 103500
	typedef ::asio::ip::address address;
	typedef ::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef ::asio::ip::address_v6 address_v6;
#endif
#else
	typedef boost::asio::ip::address address;
	typedef boost::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef boost::asio::ip::address_v6 address_v6;
#endif
#endif
}

#endif

<|endoftext|>


<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_BENCODE_HPP_INCLUDED
#define TORRENT_BENCODE_HPP_INCLUDED

/*
 * This file declares the following functions:
 *
 *----------------------------------
 * template<class OutIt>
 * void libtorrent::bencode(OutIt out, const libtorrent::entry& e);
 *
 * Encodes a message entry with bencoding into the output
 * iterator given. The bencoding is described in the BitTorrent
 * protocol description document OutIt must be an OutputIterator
 * of type char. This may throw libtorrent::invalid_encoding if
 * the entry contains invalid nodes (undefined_t for example).
 *
 *----------------------------------
 * template<class InIt>
 * libtorrent::entry libtorrent::bdecode(InIt start, InIt end);
 *
 * Decodes the buffer given by the start and end iterators
 * and returns the decoded entry. InIt must be an InputIterator
 * of type char. May throw libtorrent::invalid_encoding if
 * the string is not correctly bencoded.
 *
 */

#include <stdlib.h>
#include <string>
#include <exception>
#include <iterator> // for distance

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/static_assert.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp"

#include "libtorrent/assert.hpp"
#include "libtorrent/escape_string.hpp"

namespace libtorrent
{

	struct TORRENT_EXPORT invalid_encoding: std::exception
	{
		virtual const char* what() const throw() { return "invalid bencoding"; }
	};

	namespace detail
	{
		template <class OutIt>
		int write_string(OutIt& out, const std::string& val)
		{
			for (std::string::const_iterator i = val.begin()
				, end(val.end()); i != end; ++i)
				*out++ = *i;
			return int(val.length());
		}

		TORRENT_EXTRA_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val);

		template <class OutIt>
		int write_integer(OutIt& out, entry::integer_type val)
		{
			// the stack allocated buffer for keeping the
			// decimal representation of the number can
			// not hold number bigger than this:
			BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8);
			char buf[21];
			int ret = 0;
			for (char const* str = integer_to_str(buf, 21, val);
				*str != 0; ++str)
			{
				*out = *str;
				++out;
				++ret;
			}
			return ret;
		}

		template <class OutIt>
		void write_char(OutIt& out, char c)
		{
			*out = c;
			++out;
		}

		template <class InIt>
		std::string read_until(InIt& in, InIt end, char end_token, bool& err)
		{
			std::string ret;
			if (in == end)
			{
				err = true;
				return ret;
			}
			while (*in != end_token)
			{
				ret += *in;
				++in;
				if (in == end)
				{
					err = true;
					return ret;
				}
			}
			return ret;
		}

		template<class InIt>
		void read_string(InIt& in, InIt end, int len, std::string& str, bool& err)
		{
			TORRENT_ASSERT(len >= 0);
			for (int i = 0; i < len; ++i)
			{
				if (in == end)
				{
					err = true;
					return;
				}
				str += *in;
				++in;
			}
		}

		// returns the number of bytes written
		template<class OutIt>
		int bencode_recursive(OutIt& out, const entry& e)
		{
			int ret = 0;
			switch(e.type())
			{
			case entry::int_t:
				write_char(out, 'i');
				ret += write_integer(out, e.integer());
				write_char(out, 'e');
				ret += 2;
				break;
			case entry::string_t:
				ret += write_integer(out, e.string().length());
				write_char(out, ':');
				ret += write_string(out, e.string());
				ret += 1;
				break;
			case entry::list_t:
				write_char(out, 'l');
				for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i)
					ret += bencode_recursive(out, *i);
				write_char(out, 'e');
				ret += 2;
				break;
			case entry::dictionary_t:
				write_char(out, 'd');
				for (entry::dictionary_type::const_iterator i = e.dict().begin();
					i != e.dict().end(); ++i)
				{
					// write key
					ret += write_integer(out, i->first.length());
					write_char(out, ':');
					ret += write_string(out, i->first);
					// write value
					ret += bencode_recursive(out, i->second);
					ret += 1;
				}
				write_char(out, 'e');
				ret += 2;
				break;
			default:
				// trying to encode a structure with uninitialized values!
				TORRENT_ASSERT_VAL(false, e.type());
				// do nothing
				break;
			}
			return ret;
		}

		template<class InIt>
		void bdecode_recursive(InIt& in, InIt end, entry& ret, bool& err, int depth)
		{
			if (depth >= 100)
			{
				err = true;
				return;
			}

			if (in == end)
			{
				err = true;
#ifdef TORRENT_DEBUG
				ret.m_type_queried = false;
#endif
				return;
			}
			switch (*in)
			{

			// ----------------------------------------------
			// integer
			case 'i':
				{
				++in; // 'i'
				std::string val = read_until(in, end, 'e', err);
				if (err) return;
				TORRENT_ASSERT(*in == 'e');
				++in; // 'e'
				ret = entry(entry::int_t);
				char* end_pointer;
				ret.integer() = strtoll(val.c_str(), &end_pointer, 10);
#ifdef TORRENT_DEBUG
				ret.m_type_queried = false;
#endif
				if (end_pointer == val.c_str())
				{
					err = true;
					return;
				}
				} break;

			// ----------------------------------------------
			// list
			case 'l':
				{
				ret = entry(entry::list_t);
				++in; // 'l'
				while (*in != 'e')
				{
					ret.list().push_back(entry());
					entry& e = ret.list().back();
					bdecode_recursive(in, end, e, err, depth + 1);
					if (err)
					{
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
					if (in == end)
					{
						err = true;
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
				}
#ifdef TORRENT_DEBUG
				ret.m_type_queried = false;
#endif
				TORRENT_ASSERT(*in == 'e');
				++in; // 'e'
				} break;

			// ----------------------------------------------
			// dictionary
			case 'd':
				{
				ret = entry(entry::dictionary_t);
				++in; // 'd'
				while (*in != 'e')
				{
					entry key;
					bdecode_recursive(in, end, key, err, depth + 1);
					if (err || key.type() != entry::string_t)
					{
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
					entry& e = ret[key.string()];
					bdecode_recursive(in, end, e, err, depth + 1);
					if (err)
					{
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
					if (in == end)
					{
						err = true;
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
				}
#ifdef TORRENT_DEBUG
				ret.m_type_queried = false;
#endif
				TORRENT_ASSERT(*in == 'e');
				++in; // 'e'
				} break;

			// ----------------------------------------------
			// string
			default:
				if (is_digit((unsigned char)*in))
				{
					std::string len_s = read_until(in, end, ':', err);
					if (err)
					{
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
					TORRENT_ASSERT(*in == ':');
					++in; // ':'
					int len = atoi(len_s.c_str());
					ret = entry(entry::string_t);
					read_string(in, end, len, ret.string(), err);
					if (err)
					{
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
				}
				else
				{
					err = true;
#ifdef TORRENT_DEBUG
					ret.m_type_queried = false;
#endif
					return;
				}
#ifdef TORRENT_DEBUG
				ret.m_type_queried = false;
#endif
			}
		}
	}

	template<class OutIt>
	int bencode(OutIt out, const entry& e)
	{
		return detail::bencode_recursive(out, e);
	}

	template<class InIt>
	entry bdecode(InIt start, InIt end)
	{
		entry e;
		bool err = false;
		detail::bdecode_recursive(start, end, e, err, 0);
#ifdef TORRENT_DEBUG
		TORRENT_ASSERT(e.m_type_queried == false);
#endif
		if (err) return entry();
		return e;
	}

	template<class InIt>
	entry bdecode(InIt start, InIt end, int& len)
	{
		entry e;
		bool err = false;
		InIt s = start;
		detail::bdecode_recursive(start, end, e, err, 0);
		len = std::distance(s, start);
		TORRENT_ASSERT(len >= 0);
		if (err) return entry();
		return e;
	}
}

#endif // TORRENT_BENCODE_HPP_INCLUDED

<commit_msg>fix incorrect export<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_BENCODE_HPP_INCLUDED
#define TORRENT_BENCODE_HPP_INCLUDED

/*
 * This file declares the following functions:
 *
 *----------------------------------
 * template<class OutIt>
 * void libtorrent::bencode(OutIt out, const libtorrent::entry& e);
 *
 * Encodes a message entry with bencoding into the output
 * iterator given. The bencoding is described in the BitTorrent
 * protocol description document OutIt must be an OutputIterator
 * of type char. This may throw libtorrent::invalid_encoding if
 * the entry contains invalid nodes (undefined_t for example).
 *
 *----------------------------------
 * template<class InIt>
 * libtorrent::entry libtorrent::bdecode(InIt start, InIt end);
 *
 * Decodes the buffer given by the start and end iterators
 * and returns the decoded entry. InIt must be an InputIterator
 * of type char. May throw libtorrent::invalid_encoding if
 * the string is not correctly bencoded.
 *
 */

#include <stdlib.h>
#include <string>
#include <exception>
#include <iterator> // for distance

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/static_assert.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp"

#include "libtorrent/assert.hpp"
#include "libtorrent/escape_string.hpp"

namespace libtorrent
{

	struct TORRENT_EXPORT invalid_encoding: std::exception
	{
		virtual const char* what() const throw() { return "invalid bencoding"; }
	};

	namespace detail
	{
		template <class OutIt>
		int write_string(OutIt& out, const std::string& val)
		{
			for (std::string::const_iterator i = val.begin()
				, end(val.end()); i != end; ++i)
				*out++ = *i;
			return int(val.length());
		}

		// this is used in the template, so it must be available to the client
		TORRENT_EXPORT char const* integer_to_str(char* buf, int size
			, entry::integer_type val);

		template <class OutIt>
		int write_integer(OutIt& out, entry::integer_type val)
		{
			// the stack allocated buffer for keeping the
			// decimal representation of the number can
			// not hold number bigger than this:
			BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8);
			char buf[21];
			int ret = 0;
			for (char const* str = integer_to_str(buf, 21, val);
				*str != 0; ++str)
			{
				*out = *str;
				++out;
				++ret;
			}
			return ret;
		}

		template <class OutIt>
		void write_char(OutIt& out, char c)
		{
			*out = c;
			++out;
		}

		template <class InIt>
		std::string read_until(InIt& in, InIt end, char end_token, bool& err)
		{
			std::string ret;
			if (in == end)
			{
				err = true;
				return ret;
			}
			while (*in != end_token)
			{
				ret += *in;
				++in;
				if (in == end)
				{
					err = true;
					return ret;
				}
			}
			return ret;
		}

		template<class InIt>
		void read_string(InIt& in, InIt end, int len, std::string& str, bool& err)
		{
			TORRENT_ASSERT(len >= 0);
			for (int i = 0; i < len; ++i)
			{
				if (in == end)
				{
					err = true;
					return;
				}
				str += *in;
				++in;
			}
		}

		// returns the number of bytes written
		template<class OutIt>
		int bencode_recursive(OutIt& out, const entry& e)
		{
			int ret = 0;
			switch(e.type())
			{
			case entry::int_t:
				write_char(out, 'i');
				ret += write_integer(out, e.integer());
				write_char(out, 'e');
				ret += 2;
				break;
			case entry::string_t:
				ret += write_integer(out, e.string().length());
				write_char(out, ':');
				ret += write_string(out, e.string());
				ret += 1;
				break;
			case entry::list_t:
				write_char(out, 'l');
				for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i)
					ret += bencode_recursive(out, *i);
				write_char(out, 'e');
				ret += 2;
				break;
			case entry::dictionary_t:
				write_char(out, 'd');
				for (entry::dictionary_type::const_iterator i = e.dict().begin();
					i != e.dict().end(); ++i)
				{
					// write key
					ret += write_integer(out, i->first.length());
					write_char(out, ':');
					ret += write_string(out, i->first);
					// write value
					ret += bencode_recursive(out, i->second);
					ret += 1;
				}
				write_char(out, 'e');
				ret += 2;
				break;
			default:
				// trying to encode a structure with uninitialized values!
				TORRENT_ASSERT_VAL(false, e.type());
				// do nothing
				break;
			}
			return ret;
		}

		template<class InIt>
		void bdecode_recursive(InIt& in, InIt end, entry& ret, bool& err, int depth)
		{
			if (depth >= 100)
			{
				err = true;
				return;
			}

			if (in == end)
			{
				err = true;
#ifdef TORRENT_DEBUG
				ret.m_type_queried = false;
#endif
				return;
			}
			switch (*in)
			{

			// ----------------------------------------------
			// integer
			case 'i':
				{
				++in; // 'i'
				std::string val = read_until(in, end, 'e', err);
				if (err) return;
				TORRENT_ASSERT(*in == 'e');
				++in; // 'e'
				ret = entry(entry::int_t);
				char* end_pointer;
				ret.integer() = strtoll(val.c_str(), &end_pointer, 10);
#ifdef TORRENT_DEBUG
				ret.m_type_queried = false;
#endif
				if (end_pointer == val.c_str())
				{
					err = true;
					return;
				}
				} break;

			// ----------------------------------------------
			// list
			case 'l':
				{
				ret = entry(entry::list_t);
				++in; // 'l'
				while (*in != 'e')
				{
					ret.list().push_back(entry());
					entry& e = ret.list().back();
					bdecode_recursive(in, end, e, err, depth + 1);
					if (err)
					{
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
					if (in == end)
					{
						err = true;
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
				}
#ifdef TORRENT_DEBUG
				ret.m_type_queried = false;
#endif
				TORRENT_ASSERT(*in == 'e');
				++in; // 'e'
				} break;

			// ----------------------------------------------
			// dictionary
			case 'd':
				{
				ret = entry(entry::dictionary_t);
				++in; // 'd'
				while (*in != 'e')
				{
					entry key;
					bdecode_recursive(in, end, key, err, depth + 1);
					if (err || key.type() != entry::string_t)
					{
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
					entry& e = ret[key.string()];
					bdecode_recursive(in, end, e, err, depth + 1);
					if (err)
					{
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
					if (in == end)
					{
						err = true;
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
				}
#ifdef TORRENT_DEBUG
				ret.m_type_queried = false;
#endif
				TORRENT_ASSERT(*in == 'e');
				++in; // 'e'
				} break;

			// ----------------------------------------------
			// string
			default:
				if (is_digit((unsigned char)*in))
				{
					std::string len_s = read_until(in, end, ':', err);
					if (err)
					{
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
					TORRENT_ASSERT(*in == ':');
					++in; // ':'
					int len = atoi(len_s.c_str());
					ret = entry(entry::string_t);
					read_string(in, end, len, ret.string(), err);
					if (err)
					{
#ifdef TORRENT_DEBUG
						ret.m_type_queried = false;
#endif
						return;
					}
				}
				else
				{
					err = true;
#ifdef TORRENT_DEBUG
					ret.m_type_queried = false;
#endif
					return;
				}
#ifdef TORRENT_DEBUG
				ret.m_type_queried = false;
#endif
			}
		}
	}

	template<class OutIt>
	int bencode(OutIt out, const entry& e)
	{
		return detail::bencode_recursive(out, e);
	}

	template<class InIt>
	entry bdecode(InIt start, InIt end)
	{
		entry e;
		bool err = false;
		detail::bdecode_recursive(start, end, e, err, 0);
#ifdef TORRENT_DEBUG
		TORRENT_ASSERT(e.m_type_queried == false);
#endif
		if (err) return entry();
		return e;
	}

	template<class InIt>
	entry bdecode(InIt start, InIt end, int& len)
	{
		entry e;
		bool err = false;
		InIt s = start;
		detail::bdecode_recursive(start, end, e, err, 0);
		len = std::distance(s, start);
		TORRENT_ASSERT(len >= 0);
		if (err) return entry();
		return e;
	}
}

#endif // TORRENT_BENCODE_HPP_INCLUDED

<|endoftext|>


<commit_before>#include "dsb/domain/slave_provider.hpp"

#include <algorithm>
#include <cassert>
#include <chrono>

#include "boost/numeric/conversion/cast.hpp"
#include "zmq.hpp"

#include "dsb/comm/messaging.hpp"
#include "dsb/comm/util.hpp"
#include "dsb/error.hpp"
#include "dsb/protocol/glue.hpp"
#include "dsb/protobuf.hpp"
#include "dsb/protocol/domain.hpp"
#include "dsb/util.hpp"
#include "domain.pb.h"

namespace dp = dsb::protocol::domain;

namespace dsb
{
namespace domain
{

namespace
{
    // Defined below MessagingLoop();
    void HandleRequest(
        std::vector<zmq::message_t>& msg,
        const std::vector<std::unique_ptr<dsb::domain::ISlaveType>>& slaveTypes);

    // Slave provider messaging loop
    void MessagingLoop(
        std::shared_ptr<zmq::socket_t> killSocket,
        std::shared_ptr<zmq::socket_t> controlSocket,
        std::shared_ptr<zmq::socket_t> beaconSocket,
        std::shared_ptr<std::vector<std::unique_ptr<dsb::domain::ISlaveType>>> slaveTypesPtr,
        std::function<void(std::exception_ptr)> exceptionHandler)
    {
        auto& slaveTypes = *slaveTypesPtr;
        try {
            char slaveProviderIDBuffer[255];
            std::size_t slaveProviderIDSize = 255;
            controlSocket->getsockopt(
                ZMQ_IDENTITY, slaveProviderIDBuffer, &slaveProviderIDSize);
            const auto slaveProviderID =
                std::string(slaveProviderIDBuffer, slaveProviderIDSize);

            const std::size_t POLLITEM_COUNT = 2;
            zmq::pollitem_t pollItems[POLLITEM_COUNT] = {
                { static_cast<void*>(*killSocket),    0, ZMQ_POLLIN, 0 },
                { static_cast<void*>(*controlSocket), 0, ZMQ_POLLIN, 0 }
            };

            namespace bc = std::chrono;
            const auto HELLO_INTERVAL = bc::milliseconds(1000);
            auto nextHelloTime = bc::steady_clock::now() + HELLO_INTERVAL;
            for (;;) {
                const auto timeout = bc::duration_cast<bc::milliseconds>
                                     (nextHelloTime - bc::steady_clock::now());
                zmq::poll(pollItems, POLLITEM_COUNT, boost::numeric_cast<long>(timeout.count()));

                if (pollItems[0].revents & ZMQ_POLLIN) {
                    break;
                }

                if (pollItems[1].revents & ZMQ_POLLIN) {
                    std::vector<zmq::message_t> msg;
                    dsb::comm::Receive(*controlSocket, msg);
                    // TODO: Resolve this bug. See:
                    // http://stackoverflow.com/questions/23281405/how-to-use-a-stdvectorunique-ptrt-as-default-parameter
                    HandleRequest(msg, slaveTypes);
                    dsb::comm::Send(*controlSocket, msg);
                }

                if (bc::steady_clock::now() >= nextHelloTime) {
                    std::vector<zmq::message_t> msg;
                    msg.push_back(dp::CreateHeader(dp::MSG_SLAVEPROVIDER_HELLO,
                                                   dp::MAX_PROTOCOL_VERSION));
                    msg.push_back(dsb::comm::ToFrame(slaveProviderID));
                    dsb::comm::Send(*beaconSocket, msg);
                    nextHelloTime = bc::steady_clock::now() + HELLO_INTERVAL;
                }
            }
        } catch (...) {
            if (exceptionHandler) {
                exceptionHandler(std::current_exception());
            } else {
                throw;
            }
        }
    }

    void HandleRequest(
        std::vector<zmq::message_t>& msg,
        const std::vector<std::unique_ptr<dsb::domain::ISlaveType>>& slaveTypes)
    {
        if (msg.size() < 4 || msg[0].size() > 0 || msg[2].size() > 0) {
            throw dsb::error::ProtocolViolationException("Wrong message format");
        }
        namespace dp = dsb::protocol::domain;
        const auto header = dp::ParseHeader(msg[3]);
        switch (header.messageType) {
            case dp::MSG_GET_SLAVE_LIST: {
                msg[3] = dp::CreateHeader(dp::MSG_SLAVE_LIST, header.protocol);
                dsbproto::domain::SlaveTypeList stList;
                for (const auto& slaveType : slaveTypes) {
                    auto stInfo = stList.add_slave_type();
                    *stInfo->mutable_description() =
                        dsb::protocol::ToProto(slaveType->Description());
                }
                msg.push_back(zmq::message_t());
                dsb::protobuf::SerializeToFrame(stList, msg.back());
                break; }

            case dp::MSG_INSTANTIATE_SLAVE: {
                if (msg.size() != 5) {
                    throw dsb::error::ProtocolViolationException(
                        "Wrong INSTANTIATE_SLAVE message format");
                }
                dsbproto::domain::InstantiateSlaveData data;
                dsb::protobuf::ParseFromFrame(msg[4], data);
                const auto stIt = std::find_if(
                    slaveTypes.begin(),
                    slaveTypes.end(),
                    [&](const std::unique_ptr<dsb::domain::ISlaveType>& s) {
                        return s->Description().UUID() == data.slave_type_uuid();
                    });

                const auto instantiationTimeout = std::chrono::milliseconds(data.timeout_ms());
                dsb::net::SlaveLocator slaveLocator;
                if (stIt != slaveTypes.end()
                    && (*stIt)->Instantiate(instantiationTimeout, slaveLocator))
                {
                    msg[3] = dp::CreateHeader(
                        dp::MSG_INSTANTIATE_SLAVE_OK, header.protocol);
                    dsbproto::net::SlaveLocator slaveLocPb;
                    slaveLocPb.set_endpoint(slaveLocator.Endpoint());
                    slaveLocPb.set_identity(slaveLocator.Identity());
                    dsb::protobuf::SerializeToFrame(slaveLocPb, msg[4]);
                } else {
                    msg[3] = dp::CreateHeader(
                        dp::MSG_INSTANTIATE_SLAVE_FAILED,
                        header.protocol);
                    dsbproto::domain::Error errorPb;
                    errorPb.set_message((*stIt)->InstantiationFailureDescription());
                    dsb::protobuf::SerializeToFrame(errorPb, msg[4]);
                }
                break; }

            default:
                assert (false);
        }
    }
}

SlaveProvider::SlaveProvider(
    const dsb::net::DomainLocator& domainLocator,
    std::vector<std::unique_ptr<dsb::domain::ISlaveType>>&& slaveTypes,
    std::function<void(std::exception_ptr)> exceptionHandler)
{
    // We set up all the sockets in the "foreground" thread so that any
    // exceptions (e.g. due to invalid endpoints) are thrown there.
    const auto killEndpoint = "inproc://" + dsb::util::RandomUUID();
    m_killSocket = std::make_unique<zmq::socket_t>(
        dsb::comm::GlobalContext(), ZMQ_PAIR);
    m_killSocket->bind(killEndpoint);
    auto otherKillSocket = std::make_shared<zmq::socket_t>(
        dsb::comm::GlobalContext(), ZMQ_PAIR);
    otherKillSocket->connect(killEndpoint);

    const auto slaveProviderID = dsb::util::RandomUUID();
    auto controlSocket = std::make_shared<zmq::socket_t>(
        dsb::comm::GlobalContext(), ZMQ_DEALER);
    controlSocket->setsockopt(
        ZMQ_IDENTITY, slaveProviderID.data(), slaveProviderID.size());
    controlSocket->connect(domainLocator.InfoSlavePEndpoint());

    auto beaconSocket = std::make_shared<zmq::socket_t>(
        dsb::comm::GlobalContext(), ZMQ_PUB);
    beaconSocket->connect(domainLocator.ReportSlavePEndpoint());

    m_thread = std::thread{&MessagingLoop,
        otherKillSocket,
        controlSocket,
        beaconSocket,
        std::make_shared<std::vector<std::unique_ptr<dsb::domain::ISlaveType>>>(std::move(slaveTypes)),
        exceptionHandler};
}

// This is just here so we can declare m_killSocket to be a std::unique_ptr
// to an incomplete type in the header.
SlaveProvider::~SlaveProvider() DSB_NOEXCEPT { }

void SlaveProvider::Stop()
{
    if (m_thread.joinable()) {
        char dummy = 0;
        m_killSocket->send(&dummy, 0, ZMQ_DONTWAIT);
        m_killSocket->recv(&dummy, 1, ZMQ_DONTWAIT);
        m_thread.join();
    }
}

}} // namespace
<commit_msg>Switch to using Reactor in slave provider<commit_after>#include "dsb/domain/slave_provider.hpp"

#include <algorithm>
#include <cassert>
#include <chrono>

#include "zmq.hpp"

#include "dsb/comm/messaging.hpp"
#include "dsb/comm/reactor.hpp"
#include "dsb/comm/util.hpp"
#include "dsb/error.hpp"
#include "dsb/protocol/glue.hpp"
#include "dsb/protobuf.hpp"
#include "dsb/protocol/domain.hpp"
#include "dsb/util.hpp"
#include "domain.pb.h"

namespace dp = dsb::protocol::domain;

namespace dsb
{
namespace domain
{

namespace
{
    // Defined below MessagingLoop();
    void HandleRequest(
        std::vector<zmq::message_t>& msg,
        const std::vector<std::unique_ptr<dsb::domain::ISlaveType>>& slaveTypes);

    // Slave provider messaging loop
    void MessagingLoop(
        std::shared_ptr<zmq::socket_t> killSocket,
        std::shared_ptr<zmq::socket_t> controlSocket,
        std::shared_ptr<zmq::socket_t> beaconSocket,
        std::shared_ptr<std::vector<std::unique_ptr<dsb::domain::ISlaveType>>> slaveTypes,
        std::function<void(std::exception_ptr)> exceptionHandler)
    {
        try {
            char slaveProviderIDBuffer[255];
            std::size_t slaveProviderIDSize = 255;
            controlSocket->getsockopt(
                ZMQ_IDENTITY, slaveProviderIDBuffer, &slaveProviderIDSize);
            const auto slaveProviderID =
                std::string(slaveProviderIDBuffer, slaveProviderIDSize);

            dsb::comm::Reactor reactor;
            reactor.AddSocket(
                *killSocket,
                [] (dsb::comm::Reactor& r, zmq::socket_t&) { r.Stop(); });
            reactor.AddSocket(
                *controlSocket,
                [slaveTypes] (dsb::comm::Reactor&, zmq::socket_t& s) {
                    std::vector<zmq::message_t> msg;
                    dsb::comm::Receive(s, msg);
                    // TODO: Resolve this bug. See:
                    // http://stackoverflow.com/questions/23281405/how-to-use-a-stdvectorunique-ptrt-as-default-parameter
                    HandleRequest(msg, *slaveTypes);
                    dsb::comm::Send(s, msg);
                });

            const auto HELLO_INTERVAL = std::chrono::milliseconds(1000);
            reactor.AddTimer(
                HELLO_INTERVAL,
                -1,
                [=] (dsb::comm::Reactor&, int) {
                    std::vector<zmq::message_t> msg;
                    msg.push_back(dp::CreateHeader(
                        dp::MSG_SLAVEPROVIDER_HELLO,
                        dp::MAX_PROTOCOL_VERSION));
                    msg.push_back(dsb::comm::ToFrame(slaveProviderID));
                    dsb::comm::Send(*beaconSocket, msg);
                });

            reactor.Run();
        } catch (...) {
            if (exceptionHandler) {
                exceptionHandler(std::current_exception());
            } else {
                throw;
            }
        }
    }

    void HandleRequest(
        std::vector<zmq::message_t>& msg,
        const std::vector<std::unique_ptr<dsb::domain::ISlaveType>>& slaveTypes)
    {
        if (msg.size() < 4 || msg[0].size() > 0 || msg[2].size() > 0) {
            throw dsb::error::ProtocolViolationException("Wrong message format");
        }
        namespace dp = dsb::protocol::domain;
        const auto header = dp::ParseHeader(msg[3]);
        switch (header.messageType) {
            case dp::MSG_GET_SLAVE_LIST: {
                msg[3] = dp::CreateHeader(dp::MSG_SLAVE_LIST, header.protocol);
                dsbproto::domain::SlaveTypeList stList;
                for (const auto& slaveType : slaveTypes) {
                    auto stInfo = stList.add_slave_type();
                    *stInfo->mutable_description() =
                        dsb::protocol::ToProto(slaveType->Description());
                }
                msg.push_back(zmq::message_t());
                dsb::protobuf::SerializeToFrame(stList, msg.back());
                break; }

            case dp::MSG_INSTANTIATE_SLAVE: {
                if (msg.size() != 5) {
                    throw dsb::error::ProtocolViolationException(
                        "Wrong INSTANTIATE_SLAVE message format");
                }
                dsbproto::domain::InstantiateSlaveData data;
                dsb::protobuf::ParseFromFrame(msg[4], data);
                const auto stIt = std::find_if(
                    slaveTypes.begin(),
                    slaveTypes.end(),
                    [&](const std::unique_ptr<dsb::domain::ISlaveType>& s) {
                        return s->Description().UUID() == data.slave_type_uuid();
                    });

                const auto instantiationTimeout = std::chrono::milliseconds(data.timeout_ms());
                dsb::net::SlaveLocator slaveLocator;
                if (stIt != slaveTypes.end()
                    && (*stIt)->Instantiate(instantiationTimeout, slaveLocator))
                {
                    msg[3] = dp::CreateHeader(
                        dp::MSG_INSTANTIATE_SLAVE_OK, header.protocol);
                    dsbproto::net::SlaveLocator slaveLocPb;
                    slaveLocPb.set_endpoint(slaveLocator.Endpoint());
                    slaveLocPb.set_identity(slaveLocator.Identity());
                    dsb::protobuf::SerializeToFrame(slaveLocPb, msg[4]);
                } else {
                    msg[3] = dp::CreateHeader(
                        dp::MSG_INSTANTIATE_SLAVE_FAILED,
                        header.protocol);
                    dsbproto::domain::Error errorPb;
                    errorPb.set_message((*stIt)->InstantiationFailureDescription());
                    dsb::protobuf::SerializeToFrame(errorPb, msg[4]);
                }
                break; }

            default:
                assert (false);
        }
    }
}

SlaveProvider::SlaveProvider(
    const dsb::net::DomainLocator& domainLocator,
    std::vector<std::unique_ptr<dsb::domain::ISlaveType>>&& slaveTypes,
    std::function<void(std::exception_ptr)> exceptionHandler)
{
    // We set up all the sockets in the "foreground" thread so that any
    // exceptions (e.g. due to invalid endpoints) are thrown there.
    const auto killEndpoint = "inproc://" + dsb::util::RandomUUID();
    m_killSocket = std::make_unique<zmq::socket_t>(
        dsb::comm::GlobalContext(), ZMQ_PAIR);
    m_killSocket->bind(killEndpoint);
    auto otherKillSocket = std::make_shared<zmq::socket_t>(
        dsb::comm::GlobalContext(), ZMQ_PAIR);
    otherKillSocket->connect(killEndpoint);

    const auto slaveProviderID = dsb::util::RandomUUID();
    auto controlSocket = std::make_shared<zmq::socket_t>(
        dsb::comm::GlobalContext(), ZMQ_DEALER);
    controlSocket->setsockopt(
        ZMQ_IDENTITY, slaveProviderID.data(), slaveProviderID.size());
    controlSocket->connect(domainLocator.InfoSlavePEndpoint());

    auto beaconSocket = std::make_shared<zmq::socket_t>(
        dsb::comm::GlobalContext(), ZMQ_PUB);
    beaconSocket->connect(domainLocator.ReportSlavePEndpoint());

    m_thread = std::thread{&MessagingLoop,
        otherKillSocket,
        controlSocket,
        beaconSocket,
        std::make_shared<std::vector<std::unique_ptr<dsb::domain::ISlaveType>>>(std::move(slaveTypes)),
        exceptionHandler};
}

// This is just here so we can declare m_killSocket to be a std::unique_ptr
// to an incomplete type in the header.
SlaveProvider::~SlaveProvider() DSB_NOEXCEPT { }

void SlaveProvider::Stop()
{
    if (m_thread.joinable()) {
        char dummy = 0;
        m_killSocket->send(&dummy, 0, ZMQ_DONTWAIT);
        m_killSocket->recv(&dummy, 1, ZMQ_DONTWAIT);
        m_thread.join();
    }
}

}} // namespace
<|endoftext|>


<commit_before>/*

Copyright (c) 2006, 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_SESSION_HPP_INCLUDED
#define TORRENT_SESSION_HPP_INCLUDED

#include <algorithm>
#include <vector>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/limits.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/config.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/session_status.hpp"
#include "libtorrent/version.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/alert.hpp" // alert::error_notification
#include "libtorrent/add_torrent_params.hpp"

#include "libtorrent/storage.hpp"
#include <boost/preprocessor/cat.hpp>

#ifdef _MSC_VER
#	include <eh.h>
#endif

namespace libtorrent
{
	struct torrent_plugin;
	class torrent;
	class ip_filter;
	class port_filter;
	class connection_queue;
	class natpmp;
	class upnp;
	class alert;

	// this is used to create linker errors when trying to link to
	// a library with a conflicting build configuration than the application
#ifdef TORRENT_DEBUG
#define G _release
#else
#define G _debug
#endif

#ifdef TORRENT_USE_OPENSSL
#define S _ssl
#else
#define S _nossl
#endif

#ifdef TORRENT_DISABLE_DHT
#define D _nodht
#else
#define D _dht
#endif

#ifdef TORRENT_DISABLE_POOL_ALLOCATOR
#define P _nopoolalloc
#else
#define P _poolalloc
#endif

#define TORRENT_LINK_TEST_PREFIX libtorrent_build_config
#define TORRENT_LINK_TEST_NAME BOOST_PP_CAT(TORRENT_LINK_TEST_PREFIX, BOOST_PP_CAT(P, BOOST_PP_CAT(D, BOOST_PP_CAT(S, G))))
#undef P
#undef D
#undef S
#undef G

	inline void test_link()
	{
		extern void TORRENT_LINK_TEST_NAME();
		TORRENT_LINK_TEST_NAME();
	}

	session_settings min_memory_usage();
	session_settings high_performance_seed();

	namespace aux
	{
		// workaround for microsofts
		// hardware exceptions that makes
		// it hard to debug stuff
#ifdef _MSC_VER
		struct eh_initializer
		{
			eh_initializer()
			{
				::_set_se_translator(straight_to_debugger);
			}

			static void straight_to_debugger(unsigned int, _EXCEPTION_POINTERS*)
			{ throw; }
		};
#else
		struct eh_initializer {};
#endif
		struct session_impl;
	}

	class TORRENT_EXPORT session_proxy
	{
		friend class session;
	public:
		session_proxy() {}
	private:
		session_proxy(boost::shared_ptr<aux::session_impl> impl)
			: m_impl(impl) {}
		boost::shared_ptr<aux::session_impl> m_impl;
	};

	class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_initializer
	{
	public:

		session(fingerprint const& print = fingerprint("LT"
			, LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0)
			, int flags = start_default_features | add_default_plugins
			, int alert_mask = alert::error_notification
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
			, std::string logpath = "."
#endif
				);
		session(
			fingerprint const& print
			, std::pair<int, int> listen_port_range
			, char const* listen_interface = "0.0.0.0"
			, int flags = start_default_features | add_default_plugins
			, int alert_mask = alert::error_notification
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
			, std::string logpath = "."
#endif
			);

		~session();

		void save_state(entry& e) const;
		void load_state(lazy_entry const& e);

		// returns a list of all torrents in this session
		std::vector<torrent_handle> get_torrents() const;

		io_service& get_io_service();

		// returns an invalid handle in case the torrent doesn't exist
		torrent_handle find_torrent(sha1_hash const& info_hash) const;

		// all torrent_handles must be destructed before the session is destructed!
#ifndef BOOST_NO_EXCEPTIONS
		torrent_handle add_torrent(add_torrent_params const& params);
#endif
		torrent_handle add_torrent(add_torrent_params const& params, error_code& ec);

#ifndef TORRENT_NO_DEPRECATE
		// deprecated in 0.14
		TORRENT_DEPRECATED_PREFIX
		torrent_handle add_torrent(
			torrent_info const& ti
			, std::string const& save_path
			, entry const& resume_data = entry()
			, storage_mode_t storage_mode = storage_mode_sparse
			, bool paused = false
			, storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED;

		// deprecated in 0.14
		TORRENT_DEPRECATED_PREFIX
		torrent_handle add_torrent(
			boost::intrusive_ptr<torrent_info> ti
			, std::string const& save_path
			, entry const& resume_data = entry()
			, storage_mode_t storage_mode = storage_mode_sparse
			, bool paused = false
			, storage_constructor_type sc = default_storage_constructor
			, void* userdata = 0) TORRENT_DEPRECATED;

		// deprecated in 0.14
		TORRENT_DEPRECATED_PREFIX
		torrent_handle add_torrent(
			char const* tracker_url
			, sha1_hash const& info_hash
			, char const* name
			, std::string const& save_path
			, entry const& resume_data = entry()
			, storage_mode_t storage_mode = storage_mode_sparse
			, bool paused = false
			, storage_constructor_type sc = default_storage_constructor
			, void* userdata = 0) TORRENT_DEPRECATED;
#endif

		session_proxy abort() { return session_proxy(m_impl); }

		void pause();
		void resume();
		bool is_paused() const;

		session_status status() const;
		cache_status get_cache_status() const;

		void get_cache_info(sha1_hash const& ih
			, std::vector<cached_piece_info>& ret) const;

#ifndef TORRENT_DISABLE_DHT
		void start_dht(entry const& startup_state = entry());
		void stop_dht();
		void set_dht_settings(dht_settings const& settings);
		entry dht_state() const;
		void add_dht_node(std::pair<std::string, int> const& node);
		void add_dht_router(std::pair<std::string, int> const& node);
		bool is_dht_running() const;
#endif

#ifndef TORRENT_DISABLE_ENCRYPTION
		void set_pe_settings(pe_settings const& settings);
		pe_settings const& get_pe_settings() const;
#endif

#ifndef TORRENT_DISABLE_EXTENSIONS
		void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext);
#endif

#ifndef TORRENT_DISABLE_GEO_IP
		int as_for_ip(address const& addr);
		bool load_asnum_db(char const* file);
		bool load_country_db(char const* file);
#if TORRENT_USE_WSTRING
		bool load_country_db(wchar_t const* file);
		bool load_asnum_db(wchar_t const* file);
#endif
#endif

		void load_state(entry const& ses_state);
		entry state() const;

		void set_ip_filter(ip_filter const& f);
		ip_filter const& get_ip_filter() const;

		void set_port_filter(port_filter const& f);
		void set_peer_id(peer_id const& pid);
		void set_key(int key);
		peer_id id() const;

		bool is_listening() const;

		// if the listen port failed in some way
		// you can retry to listen on another port-
		// range with this function. If the listener
		// succeeded and is currently listening,
		// a call to this function will shut down the
		// listen port and reopen it using these new
		// properties (the given interface and port range).
		// As usual, if the interface is left as 0
		// this function will return false on failure.
		// If it fails, it will also generate alerts describing
		// the error. It will return true on success.
		bool listen_on(
			std::pair<int, int> const& port_range
			, const char* net_interface = 0);

		// returns the port we ended up listening on
		unsigned short listen_port() const;

		// Get the number of uploads.
		int num_uploads() const;

		// Get the number of connections. This number also contains the
		// number of half open connections.
		int num_connections() const;

		enum options_t
		{
			none = 0,
			delete_files = 1
		};

		enum session_flags_t
		{
			add_default_plugins = 1,
			start_default_features = 2
		};

		void remove_torrent(const torrent_handle& h, int options = none);

		void set_settings(session_settings const& s);
		session_settings const& settings();

		void set_peer_proxy(proxy_settings const& s);
		void set_web_seed_proxy(proxy_settings const& s);
		void set_tracker_proxy(proxy_settings const& s);

		proxy_settings const& peer_proxy() const;
		proxy_settings const& web_seed_proxy() const;
		proxy_settings const& tracker_proxy() const;

#ifndef TORRENT_DISABLE_DHT
		void set_dht_proxy(proxy_settings const& s);
		proxy_settings const& dht_proxy() const;
#endif

#if TORRENT_USE_I2P
		void set_i2p_proxy(proxy_settings const& s);
		proxy_settings const& i2p_proxy() const;
#endif

		int upload_rate_limit() const;
		int download_rate_limit() const;
		int local_upload_rate_limit() const;
		int local_download_rate_limit() const;
		int max_half_open_connections() const;

		void set_local_upload_rate_limit(int bytes_per_second);
		void set_local_download_rate_limit(int bytes_per_second);
		void set_upload_rate_limit(int bytes_per_second);
		void set_download_rate_limit(int bytes_per_second);
		void set_max_uploads(int limit);
		void set_max_connections(int limit);
		void set_max_half_open_connections(int limit);

		int max_connections() const;
		int max_uploads() const;

		std::auto_ptr<alert> pop_alert();
#ifndef TORRENT_NO_DEPRECATE
		TORRENT_DEPRECATED_PREFIX
		void set_severity_level(alert::severity_t s) TORRENT_DEPRECATED;
#endif
		void set_alert_mask(int m);
		size_t set_alert_queue_size_limit(size_t queue_size_limit_);

		alert const* wait_for_alert(time_duration max_wait);
		void set_alert_dispatch(boost::function<void(alert const&)> const& fun);

		connection_queue& get_connection_queue();

		// starts/stops UPnP, NATPMP or LSD port mappers
		// they are stopped by default
		void start_lsd();
		natpmp* start_natpmp();
		upnp* start_upnp();

		void stop_lsd();
		void stop_natpmp();
		void stop_upnp();

	private:

		// data shared between the main thread
		// and the working thread
		boost::shared_ptr<aux::session_impl> m_impl;
	};

}

#endif // TORRENT_SESSION_HPP_INCLUDED

<commit_msg>disable exception-only functions when exceptions are disabled<commit_after>/*

Copyright (c) 2006, 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_SESSION_HPP_INCLUDED
#define TORRENT_SESSION_HPP_INCLUDED

#include <algorithm>
#include <vector>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/limits.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/config.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/session_status.hpp"
#include "libtorrent/version.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/alert.hpp" // alert::error_notification
#include "libtorrent/add_torrent_params.hpp"

#include "libtorrent/storage.hpp"
#include <boost/preprocessor/cat.hpp>

#ifdef _MSC_VER
#	include <eh.h>
#endif

namespace libtorrent
{
	struct torrent_plugin;
	class torrent;
	class ip_filter;
	class port_filter;
	class connection_queue;
	class natpmp;
	class upnp;
	class alert;

	// this is used to create linker errors when trying to link to
	// a library with a conflicting build configuration than the application
#ifdef TORRENT_DEBUG
#define G _release
#else
#define G _debug
#endif

#ifdef TORRENT_USE_OPENSSL
#define S _ssl
#else
#define S _nossl
#endif

#ifdef TORRENT_DISABLE_DHT
#define D _nodht
#else
#define D _dht
#endif

#ifdef TORRENT_DISABLE_POOL_ALLOCATOR
#define P _nopoolalloc
#else
#define P _poolalloc
#endif

#define TORRENT_LINK_TEST_PREFIX libtorrent_build_config
#define TORRENT_LINK_TEST_NAME BOOST_PP_CAT(TORRENT_LINK_TEST_PREFIX, BOOST_PP_CAT(P, BOOST_PP_CAT(D, BOOST_PP_CAT(S, G))))
#undef P
#undef D
#undef S
#undef G

	inline void test_link()
	{
		extern void TORRENT_LINK_TEST_NAME();
		TORRENT_LINK_TEST_NAME();
	}

	session_settings min_memory_usage();
	session_settings high_performance_seed();

	namespace aux
	{
		// workaround for microsofts
		// hardware exceptions that makes
		// it hard to debug stuff
#ifdef _MSC_VER
		struct eh_initializer
		{
			eh_initializer()
			{
				::_set_se_translator(straight_to_debugger);
			}

			static void straight_to_debugger(unsigned int, _EXCEPTION_POINTERS*)
			{ throw; }
		};
#else
		struct eh_initializer {};
#endif
		struct session_impl;
	}

	class TORRENT_EXPORT session_proxy
	{
		friend class session;
	public:
		session_proxy() {}
	private:
		session_proxy(boost::shared_ptr<aux::session_impl> impl)
			: m_impl(impl) {}
		boost::shared_ptr<aux::session_impl> m_impl;
	};

	class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_initializer
	{
	public:

		session(fingerprint const& print = fingerprint("LT"
			, LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0)
			, int flags = start_default_features | add_default_plugins
			, int alert_mask = alert::error_notification
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
			, std::string logpath = "."
#endif
				);
		session(
			fingerprint const& print
			, std::pair<int, int> listen_port_range
			, char const* listen_interface = "0.0.0.0"
			, int flags = start_default_features | add_default_plugins
			, int alert_mask = alert::error_notification
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
			, std::string logpath = "."
#endif
			);

		~session();

		void save_state(entry& e) const;
		void load_state(lazy_entry const& e);

		// returns a list of all torrents in this session
		std::vector<torrent_handle> get_torrents() const;

		io_service& get_io_service();

		// returns an invalid handle in case the torrent doesn't exist
		torrent_handle find_torrent(sha1_hash const& info_hash) const;

		// all torrent_handles must be destructed before the session is destructed!
#ifndef BOOST_NO_EXCEPTIONS
		torrent_handle add_torrent(add_torrent_params const& params);
#endif
		torrent_handle add_torrent(add_torrent_params const& params, error_code& ec);

#ifndef BOOST_NO_EXCEPTIONS
#ifndef TORRENT_NO_DEPRECATE
		// deprecated in 0.14
		TORRENT_DEPRECATED_PREFIX
		torrent_handle add_torrent(
			torrent_info const& ti
			, std::string const& save_path
			, entry const& resume_data = entry()
			, storage_mode_t storage_mode = storage_mode_sparse
			, bool paused = false
			, storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED;

		// deprecated in 0.14
		TORRENT_DEPRECATED_PREFIX
		torrent_handle add_torrent(
			boost::intrusive_ptr<torrent_info> ti
			, std::string const& save_path
			, entry const& resume_data = entry()
			, storage_mode_t storage_mode = storage_mode_sparse
			, bool paused = false
			, storage_constructor_type sc = default_storage_constructor
			, void* userdata = 0) TORRENT_DEPRECATED;

		// deprecated in 0.14
		TORRENT_DEPRECATED_PREFIX
		torrent_handle add_torrent(
			char const* tracker_url
			, sha1_hash const& info_hash
			, char const* name
			, std::string const& save_path
			, entry const& resume_data = entry()
			, storage_mode_t storage_mode = storage_mode_sparse
			, bool paused = false
			, storage_constructor_type sc = default_storage_constructor
			, void* userdata = 0) TORRENT_DEPRECATED;
#endif
#endif

		session_proxy abort() { return session_proxy(m_impl); }

		void pause();
		void resume();
		bool is_paused() const;

		session_status status() const;
		cache_status get_cache_status() const;

		void get_cache_info(sha1_hash const& ih
			, std::vector<cached_piece_info>& ret) const;

#ifndef TORRENT_DISABLE_DHT
		void start_dht(entry const& startup_state = entry());
		void stop_dht();
		void set_dht_settings(dht_settings const& settings);
		entry dht_state() const;
		void add_dht_node(std::pair<std::string, int> const& node);
		void add_dht_router(std::pair<std::string, int> const& node);
		bool is_dht_running() const;
#endif

#ifndef TORRENT_DISABLE_ENCRYPTION
		void set_pe_settings(pe_settings const& settings);
		pe_settings const& get_pe_settings() const;
#endif

#ifndef TORRENT_DISABLE_EXTENSIONS
		void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext);
#endif

#ifndef TORRENT_DISABLE_GEO_IP
		int as_for_ip(address const& addr);
		bool load_asnum_db(char const* file);
		bool load_country_db(char const* file);
#if TORRENT_USE_WSTRING
		bool load_country_db(wchar_t const* file);
		bool load_asnum_db(wchar_t const* file);
#endif
#endif

		void load_state(entry const& ses_state);
		entry state() const;

		void set_ip_filter(ip_filter const& f);
		ip_filter const& get_ip_filter() const;

		void set_port_filter(port_filter const& f);
		void set_peer_id(peer_id const& pid);
		void set_key(int key);
		peer_id id() const;

		bool is_listening() const;

		// if the listen port failed in some way
		// you can retry to listen on another port-
		// range with this function. If the listener
		// succeeded and is currently listening,
		// a call to this function will shut down the
		// listen port and reopen it using these new
		// properties (the given interface and port range).
		// As usual, if the interface is left as 0
		// this function will return false on failure.
		// If it fails, it will also generate alerts describing
		// the error. It will return true on success.
		bool listen_on(
			std::pair<int, int> const& port_range
			, const char* net_interface = 0);

		// returns the port we ended up listening on
		unsigned short listen_port() const;

		// Get the number of uploads.
		int num_uploads() const;

		// Get the number of connections. This number also contains the
		// number of half open connections.
		int num_connections() const;

		enum options_t
		{
			none = 0,
			delete_files = 1
		};

		enum session_flags_t
		{
			add_default_plugins = 1,
			start_default_features = 2
		};

		void remove_torrent(const torrent_handle& h, int options = none);

		void set_settings(session_settings const& s);
		session_settings const& settings();

		void set_peer_proxy(proxy_settings const& s);
		void set_web_seed_proxy(proxy_settings const& s);
		void set_tracker_proxy(proxy_settings const& s);

		proxy_settings const& peer_proxy() const;
		proxy_settings const& web_seed_proxy() const;
		proxy_settings const& tracker_proxy() const;

#ifndef TORRENT_DISABLE_DHT
		void set_dht_proxy(proxy_settings const& s);
		proxy_settings const& dht_proxy() const;
#endif

#if TORRENT_USE_I2P
		void set_i2p_proxy(proxy_settings const& s);
		proxy_settings const& i2p_proxy() const;
#endif

		int upload_rate_limit() const;
		int download_rate_limit() const;
		int local_upload_rate_limit() const;
		int local_download_rate_limit() const;
		int max_half_open_connections() const;

		void set_local_upload_rate_limit(int bytes_per_second);
		void set_local_download_rate_limit(int bytes_per_second);
		void set_upload_rate_limit(int bytes_per_second);
		void set_download_rate_limit(int bytes_per_second);
		void set_max_uploads(int limit);
		void set_max_connections(int limit);
		void set_max_half_open_connections(int limit);

		int max_connections() const;
		int max_uploads() const;

		std::auto_ptr<alert> pop_alert();
#ifndef TORRENT_NO_DEPRECATE
		TORRENT_DEPRECATED_PREFIX
		void set_severity_level(alert::severity_t s) TORRENT_DEPRECATED;
#endif
		void set_alert_mask(int m);
		size_t set_alert_queue_size_limit(size_t queue_size_limit_);

		alert const* wait_for_alert(time_duration max_wait);
		void set_alert_dispatch(boost::function<void(alert const&)> const& fun);

		connection_queue& get_connection_queue();

		// starts/stops UPnP, NATPMP or LSD port mappers
		// they are stopped by default
		void start_lsd();
		natpmp* start_natpmp();
		upnp* start_upnp();

		void stop_lsd();
		void stop_natpmp();
		void stop_upnp();

	private:

		// data shared between the main thread
		// and the working thread
		boost::shared_ptr<aux::session_impl> m_impl;
	};

}

#endif // TORRENT_SESSION_HPP_INCLUDED

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 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: Gabe Black
 */

#ifndef __ARCH_SPARC_UTILITY_HH__
#define __ARCH_SPARC_UTILITY_HH__

#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/tlb.hh"
#include "base/misc.hh"
#include "base/bitfield.hh"
#include "cpu/thread_context.hh"

namespace SparcISA
{

    uint64_t getArgument(ThreadContext *tc, int number, bool fp);

    static inline bool
    inUserMode(ThreadContext *tc)
    {
        return !(tc->readMiscRegNoEffect(MISCREG_PSTATE & (1 << 2)) ||
                tc->readMiscRegNoEffect(MISCREG_HPSTATE & (1 << 2)));
    }

    inline bool isCallerSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCallerSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    // Instruction address compression hooks
    inline Addr realPCToFetchPC(const Addr &addr)
    {
        return addr;
    }

    inline Addr fetchPCToRealPC(const Addr &addr)
    {
        return addr;
    }

    // the size of "fetched" instructions (not necessarily the size
    // of real instructions for PISA)
    inline size_t fetchInstSize()
    {
        return sizeof(MachInst);
    }

    /**
     * Function to insure ISA semantics about 0 registers.
     * @param tc The thread context.
     */
    template <class TC>
    void zeroRegisters(TC *tc);

    inline void initCPU(ThreadContext *tc, int cpuId)
    {
        static Fault por = new PowerOnReset();
        if (cpuId == 0)
            por->invoke(tc);

    }

    inline void startupCPU(ThreadContext *tc, int cpuId)
    {
#if FULL_SYSTEM
        // Other CPUs will get activated by IPIs
        if (cpuId == 0)
            tc->activate(0);
#else
        tc->activate(0);
#endif
    }

} // namespace SparcISA

#endif
<commit_msg>SPARC: Fix the parenthesis in inUserMode.<commit_after>/*
 * Copyright (c) 2003-2005 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: Gabe Black
 */

#ifndef __ARCH_SPARC_UTILITY_HH__
#define __ARCH_SPARC_UTILITY_HH__

#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/tlb.hh"
#include "base/misc.hh"
#include "base/bitfield.hh"
#include "cpu/thread_context.hh"

namespace SparcISA
{

    uint64_t getArgument(ThreadContext *tc, int number, bool fp);

    static inline bool
    inUserMode(ThreadContext *tc)
    {
        return !((tc->readMiscRegNoEffect(MISCREG_PSTATE) & (1 << 2)) ||
                 (tc->readMiscRegNoEffect(MISCREG_HPSTATE) & (1 << 2)));
    }

    inline bool isCallerSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCallerSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    // Instruction address compression hooks
    inline Addr realPCToFetchPC(const Addr &addr)
    {
        return addr;
    }

    inline Addr fetchPCToRealPC(const Addr &addr)
    {
        return addr;
    }

    // the size of "fetched" instructions (not necessarily the size
    // of real instructions for PISA)
    inline size_t fetchInstSize()
    {
        return sizeof(MachInst);
    }

    /**
     * Function to insure ISA semantics about 0 registers.
     * @param tc The thread context.
     */
    template <class TC>
    void zeroRegisters(TC *tc);

    inline void initCPU(ThreadContext *tc, int cpuId)
    {
        static Fault por = new PowerOnReset();
        if (cpuId == 0)
            por->invoke(tc);

    }

    inline void startupCPU(ThreadContext *tc, int cpuId)
    {
#if FULL_SYSTEM
        // Other CPUs will get activated by IPIs
        if (cpuId == 0)
            tc->activate(0);
#else
        tc->activate(0);
#endif
    }

} // namespace SparcISA

#endif
<|endoftext|>