<commit_before>#ifndef AL_OMNIAPP_H
#define AL_OMNIAPP_H

#include "allocore/al_Allocore.hpp"
#include "allocore/io/al_Window.hpp"
#include "allocore/protocol/al_OSC.hpp"
#include "alloutil/al_FPS.hpp"
#include "alloutil/al_OmniStereo.hpp"

#define PORT_TO_DEVICE_SERVER (12000)
#define PORT_FROM_DEVICE_SERVER (PORT_TO_DEVICE_SERVER+1)

// deprecated, do not use:
#define DEVICE_SERVER_SEND_PORT (PORT_FROM_DEVICE_SERVER)
#define DEVICE_SERVER_RECEIVE_PORT (PORT_TO_DEVICE_SERVER)

#define DEVICE_SERVER_IP_ADDRESS "BOSSANOVA"

namespace al {

class OmniApp : public Window, public osc::PacketHandler, public FPS, public OmniStereo::Drawable {
public:
	OmniApp(std::string name = "omniapp", bool slave=false);
	virtual ~OmniApp();

	void start();

	virtual void onDraw(Graphics& gl) {}
	virtual void onAnimate(al_sec dt) {}
	virtual void onSound(AudioIOData& io) {}
	virtual void onMessage(osc::Message& m);

	const AudioIO&		audioIO() const { return mAudioIO; }
	AudioIO&			audioIO(){ return mAudioIO; }

	const Lens&			lens() const { return mLens; }
	Lens&				lens() { return mLens; }

	const Graphics&		graphics() const { return mGraphics; }
	Graphics&			graphics(){ return mGraphics; }

	const Nav&			nav() const { return mNav; }
	Nav&				nav(){ return mNav; }

	ShaderProgram&		shader() { return mShader; }

	const std::string&	name() const { return mName; }
	OmniApp&			name(const std::string& v){ mName=v; return *this; }

	osc::Recv&			oscRecv(){ return mOSCRecv; }
	osc::Send&			oscSend(){ return mOSCSend; }

	OmniStereo&			omni() { return mOmni; }

	const std::string&	hostName() const { return mHostName; }

	bool				omniEnable() const { return bOmniEnable; }
	void				omniEnable(bool b) { bOmniEnable = b; }

	void initWindow(
		const Window::Dim& dims = Window::Dim(800, 400),
		const std::string title = "OmniApp",
		double fps = 60,
		Window::DisplayMode mode = Window::DEFAULT_BUF);

	void initAudio(
		double audioRate=44100, int audioBlockSize=256
	);

	void initAudio(
		std::string devicename,
    double audioRate, int audioBlockSize,
		int audioInputs, int audioOutputs
	);
	void initOmni(std::string path = "../../allosphere/calibration-current/");

	void sendHandshake();
	void sendDisconnect();

	virtual bool onCreate();
	virtual bool onFrame();
	virtual void onDrawOmni(OmniStereo& omni);

	virtual std::string	vertexCode();
	virtual std::string	fragmentCode();

protected:

	AudioIO mAudioIO;
	OmniStereo mOmni;

	Lens mLens;
	Graphics mGraphics;

	ShaderProgram mShader;

	// control
	Nav mNav;
	NavInputControl mNavControl;
	StandardWindowKeyControls mStdControls;
	osc::Recv mOSCRecv;
	osc::Send mOSCSend;

	std::string mName;
	std::string mHostName;

	double mNavSpeed, mNavTurnSpeed;

	bool bOmniEnable, bSlave;

	static void AppAudioCB(AudioIOData& io);
};

// INLINE IMPLEMENTATION //

inline OmniApp::OmniApp(std::string name, bool slave)
:	mNavControl(mNav),
	mOSCRecv(PORT_FROM_DEVICE_SERVER),
	mOSCSend(PORT_TO_DEVICE_SERVER, DEVICE_SERVER_IP_ADDRESS),
	bSlave(slave)
{
	bOmniEnable = true;
	mHostName = Socket::hostName();
	mName = name;

	mNavSpeed = 1;
	mNavTurnSpeed = 0.02;

	lens().near(0.01).far(40).eyeSep(0.03);
	nav().smooth(0.8);

	Window::append(mStdControls);
	initWindow();
	initOmni();

	if (!bSlave) {
		Window::append(mNavControl);
		initAudio();

		oscRecv().bufferSize(32000);
		oscRecv().handler(*this);
		sendHandshake();
	}
}

inline OmniApp::~OmniApp() {
	if (!bSlave) sendDisconnect();
}

inline void OmniApp::initOmni(std::string path) {
	mOmni.configure(path, mHostName);
	if (mOmni.activeStereo()) {
		mOmni.mode(OmniStereo::ACTIVE).stereo(true);
	}
}

inline void OmniApp::initWindow(
	const Window::Dim& dims, const std::string title, double fps, Window::DisplayMode mode) {
	Window::dimensions(dims);
	Window::title(title);
	Window::fps(fps);
	Window::displayMode(mode);
}

inline void OmniApp::initAudio(
	double audioRate, int audioBlockSize
) {
	mAudioIO.callback = AppAudioCB;
	mAudioIO.user(this);
	mAudioIO.framesPerSecond(audioRate);
	mAudioIO.framesPerBuffer(audioBlockSize);
}

inline void OmniApp::initAudio(
	std::string devicename,
	double audioRate, int audioBlockSize,
	int audioInputs, int audioOutputs
) {
	AudioDevice indev(devicename, AudioDevice::INPUT);
	AudioDevice outdev(devicename, AudioDevice::OUTPUT);
	indev.print();
	outdev.print();
	mAudioIO.deviceIn(indev);
	mAudioIO.deviceOut(outdev);
	mAudioIO.channelsOut(audioOutputs);
	mAudioIO.channelsIn(audioInputs);
	initAudio(audioRate, audioBlockSize);
}

inline void OmniApp::sendHandshake(){
	oscSend().send("/handshake", name(), oscRecv().port());
}

inline void OmniApp::sendDisconnect(){
	oscSend().send("/disconnectApplication", name());
}

inline void OmniApp::start() {
	if (mOmni.activeStereo()) {
		Window::displayMode(Window::displayMode() | Window::STEREO_BUF);
	}

	create();

	if (mOmni.fullScreen()) {
		fullScreen(true);
		cursorHide(true);
	}

	if (!bSlave) {
		if(oscSend().opened()) sendHandshake();
		mAudioIO.start();
	}

	Main::get().start();
}

inline bool OmniApp::onCreate() {
	mOmni.onCreate();

	Shader vert, frag;
	vert.source(OmniStereo::glsl() + vertexCode(), Shader::VERTEX).compile();
	vert.printLog();
	frag.source(fragmentCode(), Shader::FRAGMENT).compile();
	frag.printLog();
	mShader.attach(vert).attach(frag).link();
	mShader.printLog();
	mShader.begin();
	mShader.uniform("lighting", 1.0);
	mShader.end();

	return true;
}

inline bool OmniApp::onFrame() {
	FPS::onFrame();

	while(oscRecv().recv()) {}

	nav().step();

	onAnimate(dt);

	Viewport vp(width(), height());

	if (bOmniEnable) {
		mOmni.onFrame(*this, lens(), nav(), vp);
	} else {
		mOmni.onFrameFront(*this, lens(), nav(), vp);
	}
	return true;
}

inline void OmniApp::onDrawOmni(OmniStereo& omni) {
	graphics().error("start onDraw");

	mShader.begin();
	mOmni.uniforms(mShader);

	onDraw(graphics());

	mShader.end();
}

inline void OmniApp::onMessage(osc::Message& m) {
	float x;
	if (m.addressPattern() == "/mx") {
		m >> x;
		nav().moveR(-x * mNavSpeed);

	} else if (m.addressPattern() == "/my") {
		m >> x;
		nav().moveU(x * mNavSpeed);

	} else if (m.addressPattern() == "/mz") {
		m >> x;
		nav().moveF(x * mNavSpeed);

	} else if (m.addressPattern() == "/tx") {
		m >> x;
		nav().spinR(x * -mNavTurnSpeed);

	} else if (m.addressPattern() == "/ty") {
		m >> x;
		nav().spinU(x * mNavTurnSpeed);

	} else if (m.addressPattern() == "/tz") {
		m >> x;
		nav().spinF(x * -mNavTurnSpeed);

	}
}

inline std::string	OmniApp::vertexCode() {
	return AL_STRINGIFY(
		varying vec4 color;
		varying vec3 normal, lightDir, eyeVec;
		void main(){
			color = gl_Color;
			vec4 vertex = gl_ModelViewMatrix * gl_Vertex;
			normal = gl_NormalMatrix * gl_Normal;
			vec3 V = vertex.xyz;
			eyeVec = normalize(-V);
			lightDir = normalize(vec3(gl_LightSource[0].position.xyz - V));
			gl_Position = omni_render(vertex);
		}
	);
}

inline std::string OmniApp::fragmentCode() {
	return AL_STRINGIFY(
		uniform float lighting;
		varying vec4 color;
		varying vec3 normal, lightDir, eyeVec;
    	void main() {
			vec4 final_color = color * gl_LightSource[0].ambient;
			vec3 N = normalize(normal);
			vec3 L = lightDir;
			float lambertTerm = max(dot(N, L), 0.0);
			final_color += gl_LightSource[0].diffuse * color * lambertTerm;
			vec3 E = eyeVec;
			vec3 R = reflect(-L, N);
			float spec = pow(max(dot(R, E), 0.0), 0.9 + 1e-20);
			final_color += gl_LightSource[0].specular * spec;
			gl_FragColor = mix(color, final_color, lighting);
		}
	);
}

inline void OmniApp::AppAudioCB(AudioIOData& io){
	OmniApp& app = io.user<OmniApp>();
	io.frame(0);
	app.onSound(io);
}

}

#endif
<commit_msg>added nav home/halt osc messages to omniapp<commit_after>#ifndef AL_OMNIAPP_H
#define AL_OMNIAPP_H

#include "allocore/al_Allocore.hpp"
#include "allocore/io/al_Window.hpp"
#include "allocore/protocol/al_OSC.hpp"
#include "alloutil/al_FPS.hpp"
#include "alloutil/al_OmniStereo.hpp"

#define PORT_TO_DEVICE_SERVER (12000)
#define PORT_FROM_DEVICE_SERVER (PORT_TO_DEVICE_SERVER+1)

// deprecated, do not use:
#define DEVICE_SERVER_SEND_PORT (PORT_FROM_DEVICE_SERVER)
#define DEVICE_SERVER_RECEIVE_PORT (PORT_TO_DEVICE_SERVER)

#define DEVICE_SERVER_IP_ADDRESS "BOSSANOVA"

namespace al {

class OmniApp : public Window, public osc::PacketHandler, public FPS, public OmniStereo::Drawable {
public:
	OmniApp(std::string name = "omniapp", bool slave=false);
	virtual ~OmniApp();

	void start();

	virtual void onDraw(Graphics& gl) {}
	virtual void onAnimate(al_sec dt) {}
	virtual void onSound(AudioIOData& io) {}
	virtual void onMessage(osc::Message& m);

	const AudioIO&		audioIO() const { return mAudioIO; }
	AudioIO&			audioIO(){ return mAudioIO; }

	const Lens&			lens() const { return mLens; }
	Lens&				lens() { return mLens; }

	const Graphics&		graphics() const { return mGraphics; }
	Graphics&			graphics(){ return mGraphics; }

	const Nav&			nav() const { return mNav; }
	Nav&				nav(){ return mNav; }

	ShaderProgram&		shader() { return mShader; }

	const std::string&	name() const { return mName; }
	OmniApp&			name(const std::string& v){ mName=v; return *this; }

	osc::Recv&			oscRecv(){ return mOSCRecv; }
	osc::Send&			oscSend(){ return mOSCSend; }

	OmniStereo&			omni() { return mOmni; }

	const std::string&	hostName() const { return mHostName; }

	bool				omniEnable() const { return bOmniEnable; }
	void				omniEnable(bool b) { bOmniEnable = b; }

	void initWindow(
		const Window::Dim& dims = Window::Dim(800, 400),
		const std::string title = "OmniApp",
		double fps = 60,
		Window::DisplayMode mode = Window::DEFAULT_BUF);

	void initAudio(
		double audioRate=44100, int audioBlockSize=256
	);

	void initAudio(
		std::string devicename,
    double audioRate, int audioBlockSize,
		int audioInputs, int audioOutputs
	);
	void initOmni(std::string path = "../../allosphere/calibration-current/");

	void sendHandshake();
	void sendDisconnect();

	virtual bool onCreate();
	virtual bool onFrame();
	virtual void onDrawOmni(OmniStereo& omni);

	virtual std::string	vertexCode();
	virtual std::string	fragmentCode();

protected:

	AudioIO mAudioIO;
	OmniStereo mOmni;

	Lens mLens;
	Graphics mGraphics;

	ShaderProgram mShader;

	// control
	Nav mNav;
	NavInputControl mNavControl;
	StandardWindowKeyControls mStdControls;
	osc::Recv mOSCRecv;
	osc::Send mOSCSend;

	std::string mName;
	std::string mHostName;

	double mNavSpeed, mNavTurnSpeed;

	bool bOmniEnable, bSlave;

	static void AppAudioCB(AudioIOData& io);
};

// INLINE IMPLEMENTATION //

inline OmniApp::OmniApp(std::string name, bool slave)
:	mNavControl(mNav),
	mOSCRecv(PORT_FROM_DEVICE_SERVER),
	mOSCSend(PORT_TO_DEVICE_SERVER, DEVICE_SERVER_IP_ADDRESS),
	bSlave(slave)
{
	bOmniEnable = true;
	mHostName = Socket::hostName();
	mName = name;

	mNavSpeed = 1;
	mNavTurnSpeed = 0.02;

	lens().near(0.01).far(40).eyeSep(0.03);
	nav().smooth(0.8);

	Window::append(mStdControls);
	initWindow();
	initOmni();

	if (!bSlave) {
		Window::append(mNavControl);
		initAudio();

		oscRecv().bufferSize(32000);
		oscRecv().handler(*this);
		sendHandshake();
	}
}

inline OmniApp::~OmniApp() {
	if (!bSlave) sendDisconnect();
}

inline void OmniApp::initOmni(std::string path) {
	mOmni.configure(path, mHostName);
	if (mOmni.activeStereo()) {
		mOmni.mode(OmniStereo::ACTIVE).stereo(true);
	}
}

inline void OmniApp::initWindow(
	const Window::Dim& dims, const std::string title, double fps, Window::DisplayMode mode) {
	Window::dimensions(dims);
	Window::title(title);
	Window::fps(fps);
	Window::displayMode(mode);
}

inline void OmniApp::initAudio(
	double audioRate, int audioBlockSize
) {
	mAudioIO.callback = AppAudioCB;
	mAudioIO.user(this);
	mAudioIO.framesPerSecond(audioRate);
	mAudioIO.framesPerBuffer(audioBlockSize);
}

inline void OmniApp::initAudio(
	std::string devicename,
	double audioRate, int audioBlockSize,
	int audioInputs, int audioOutputs
) {
	AudioDevice indev(devicename, AudioDevice::INPUT);
	AudioDevice outdev(devicename, AudioDevice::OUTPUT);
	indev.print();
	outdev.print();
	mAudioIO.deviceIn(indev);
	mAudioIO.deviceOut(outdev);
	mAudioIO.channelsOut(audioOutputs);
	mAudioIO.channelsIn(audioInputs);
	initAudio(audioRate, audioBlockSize);
}

inline void OmniApp::sendHandshake(){
	oscSend().send("/handshake", name(), oscRecv().port());
}

inline void OmniApp::sendDisconnect(){
	oscSend().send("/disconnectApplication", name());
}

inline void OmniApp::start() {
	if (mOmni.activeStereo()) {
		Window::displayMode(Window::displayMode() | Window::STEREO_BUF);
	}

	create();

	if (mOmni.fullScreen()) {
		fullScreen(true);
		cursorHide(true);
	}

	if (!bSlave) {
		if(oscSend().opened()) sendHandshake();
		mAudioIO.start();
	}

	Main::get().start();
}

inline bool OmniApp::onCreate() {
	mOmni.onCreate();

	Shader vert, frag;
	vert.source(OmniStereo::glsl() + vertexCode(), Shader::VERTEX).compile();
	vert.printLog();
	frag.source(fragmentCode(), Shader::FRAGMENT).compile();
	frag.printLog();
	mShader.attach(vert).attach(frag).link();
	mShader.printLog();
	mShader.begin();
	mShader.uniform("lighting", 1.0);
	mShader.end();

	return true;
}

inline bool OmniApp::onFrame() {
	FPS::onFrame();

	while(oscRecv().recv()) {}

	nav().step();

	onAnimate(dt);

	Viewport vp(width(), height());

	if (bOmniEnable) {
		mOmni.onFrame(*this, lens(), nav(), vp);
	} else {
		mOmni.onFrameFront(*this, lens(), nav(), vp);
	}
	return true;
}

inline void OmniApp::onDrawOmni(OmniStereo& omni) {
	graphics().error("start onDraw");

	mShader.begin();
	mOmni.uniforms(mShader);

	onDraw(graphics());

	mShader.end();
}

inline void OmniApp::onMessage(osc::Message& m) {
	float x;
	if (m.addressPattern() == "/mx") {
		m >> x;
		nav().moveR(-x * mNavSpeed);

	} else if (m.addressPattern() == "/my") {
		m >> x;
		nav().moveU(x * mNavSpeed);

	} else if (m.addressPattern() == "/mz") {
		m >> x;
		nav().moveF(x * mNavSpeed);

	} else if (m.addressPattern() == "/tx") {
		m >> x;
		nav().spinR(x * -mNavTurnSpeed);

	} else if (m.addressPattern() == "/ty") {
		m >> x;
		nav().spinU(x * mNavTurnSpeed);

	} else if (m.addressPattern() == "/tz") {
		m >> x;
		nav().spinF(x * -mNavTurnSpeed);

	} else if (m.addressPattern() == "/home") {
		nav().home();

	} else if (m.addressPattern() == "/halt") {
		nav().halt();

	}
}

inline std::string	OmniApp::vertexCode() {
	return AL_STRINGIFY(
		varying vec4 color;
		varying vec3 normal, lightDir, eyeVec;
		void main(){
			color = gl_Color;
			vec4 vertex = gl_ModelViewMatrix * gl_Vertex;
			normal = gl_NormalMatrix * gl_Normal;
			vec3 V = vertex.xyz;
			eyeVec = normalize(-V);
			lightDir = normalize(vec3(gl_LightSource[0].position.xyz - V));
			gl_Position = omni_render(vertex);
		}
	);
}

inline std::string OmniApp::fragmentCode() {
	return AL_STRINGIFY(
		uniform float lighting;
		varying vec4 color;
		varying vec3 normal, lightDir, eyeVec;
    	void main() {
			vec4 final_color = color * gl_LightSource[0].ambient;
			vec3 N = normalize(normal);
			vec3 L = lightDir;
			float lambertTerm = max(dot(N, L), 0.0);
			final_color += gl_LightSource[0].diffuse * color * lambertTerm;
			vec3 E = eyeVec;
			vec3 R = reflect(-L, N);
			float spec = pow(max(dot(R, E), 0.0), 0.9 + 1e-20);
			final_color += gl_LightSource[0].specular * spec;
			gl_FragColor = mix(color, final_color, lighting);
		}
	);
}

inline void OmniApp::AppAudioCB(AudioIOData& io){
	OmniApp& app = io.user<OmniApp>();
	io.frame(0);
	app.onSound(io);
}

}

#endif
<|endoftext|>


<commit_before>/* LICENSE NOTICE
	Copyright (c) 2009, Frederick Emmott <mail@fredemmott.co.uk>

	Permission to use, copy, modify, and/or distribute this software for any
	purpose with or without fee is hereby granted, provided that the above
	copyright notice and this permission notice appear in all copies.

	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
	WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
	MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
	ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
	WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
	ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
	OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "Dumper.h"

#include <QByteArray>
#include <QHash>
#include <QTextStream>

using namespace FastCgiQt;

void Dumper::respond(Request* request)
{
	QTextStream out(request);
	out << "
" << tr("Variable Dump") << "
";
	out << "
" << endl;
	out << "
Root URL:

" << request->url(RootUrl).toEncoded() << "
" << endl;
	out << "
Location URL:

" << request->url(LocationUrl).toEncoded() << "
" << endl;
	out << "
Full URL:

" << request->url(RequestUrl).toEncoded() << "
" << endl;
	out << "
" << endl;
	dumpHash(tr("Get variables"), request->rawValues(GetData), out);
	dumpHash(tr("Post variables"), request->rawValues(PostData), out);
	dumpHash(tr("Server variables"), request->rawValues(ServerData), out);
}

void Dumper::dumpHash(const QString& label, const QHash<QByteArray, QByteArray>& data, QTextStream& out)
{
	// Print out server variables
	out << "
" << label << "
" << endl;

	out << "
" << endl;

	for(
		QHash<QByteArray, QByteArray>::ConstIterator it = data.constBegin();
		it != data.constEnd();
		++it
	)
	{
		out << "
" << it.key() << "	" << it.value() << "
" << endl;
	}

	out << "
" << endl;

}
<commit_msg>Make output of Dumper sorted<commit_after>/* LICENSE NOTICE
	Copyright (c) 2009, Frederick Emmott <mail@fredemmott.co.uk>

	Permission to use, copy, modify, and/or distribute this software for any
	purpose with or without fee is hereby granted, provided that the above
	copyright notice and this permission notice appear in all copies.

	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
	WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
	MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
	ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
	WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
	ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
	OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "Dumper.h"

#include <QByteArray>
#include <QHash>
#include <QTextStream>

using namespace FastCgiQt;

void Dumper::respond(Request* request)
{
	QTextStream out(request);
	out << "
" << tr("Variable Dump") << "
";
	out << "
" << endl;
	out << "
Root URL:

" << request->url(RootUrl).toEncoded() << "
" << endl;
	out << "
Location URL:

" << request->url(LocationUrl).toEncoded() << "
" << endl;
	out << "
Full URL:

" << request->url(RequestUrl).toEncoded() << "
" << endl;
	out << "
" << endl;
	dumpHash(tr("Get variables"), request->rawValues(GetData), out);
	dumpHash(tr("Post variables"), request->rawValues(PostData), out);
	dumpHash(tr("Server variables"), request->rawValues(ServerData), out);
}

void Dumper::dumpHash(const QString& label, const QHash<QByteArray, QByteArray>& data, QTextStream& out)
{
	// Print out server variables
	out << "
" << label << "
" << endl;

	out << "
" << endl;

	QList<QByteArray> keys = data.keys();
	qSort(keys);

	Q_FOREACH(const QByteArray& key, keys)
	{
		QList<QByteArray> values = data.values(key);
		out << "
<th rowspan='" << values.count() << "'>" << key << "	";
		Q_FOREVER
		{
			const QByteArray value = values.takeFirst();
			out << "" << value << "
" << endl;
			if(!values.isEmpty())
			{
				out << "
";
			}
			else
			{
				break;
			}
		}
	}

	out << "
" << endl;

}
<|endoftext|>


<commit_before><commit_msg>Added workaround for broadcast mode UE noise window<commit_after><|endoftext|>


<commit_before>/*********************************************************************
** Author: Zach Colbert
** Date: 18 October 2017
** Description: Defines a function to find the vertical displacement of a falling body in a given time.
*********************************************************************/

// Main function MUST BE REMOVED before submitting the assignment!
int main()
{
    // Don't write the actual code here! Use this to call the real function.
    return 0;
}

// Description
double fallDistance()
{
    // The actual code goes here.
}<commit_msg>Gave it some structure<commit_after>/*********************************************************************
** Author: Zach Colbert
** Date: 18 October 2017
** Description: Defines a function to find the vertical displacement of a falling body in a given time.
*********************************************************************/

/*********************************************************************
Testing section MUST BE REMOVED OR COMMENTED BEFORE SUBMISSION
*********************************************************************/
double fallDistance(double time);

int main()
{
    // Don't write the actual code here! Use this to call the real function.
    return 0;
}
/*********************************************************************
End testing section
*********************************************************************/

// Description
double fallDistance(double time)
{
    // The actual code goes here.
}<|endoftext|>


<commit_before>/*
 * ThreatMatrix.cpp
 *
 *  Created on: 1/23/2012
 *      Author: Kyle
 */

#include "ThreatMatrix.h"
#include "ThreatMap.h"
#include "server/zone/objects/creature/CreatureObject.h"

ThreatMatrix::ThreatMatrix() {
	tauntThreat = NULL;
	focusedThreat = NULL;
}

ThreatMatrix::~ThreatMatrix() {

}

ThreatMatrix::ThreatMatrix(const ThreatMatrix& e) {

}

ThreatMatrix& ThreatMatrix::operator=(const ThreatMatrix& e) {
	//VectorMap<ManagedReference<WeaponObject*>, uint32>::operator=(e);

	return *this;
}

void ThreatMatrix::clear() {

	tauntThreat = NULL;
	focusedThreat = NULL;

	damageMap.removeAll();
	aggroMap.removeAll();
}

void ThreatMatrix::add(CreatureObject* creature, ThreatMapEntry* entry) {

	if(!creature->isPlayerCreature())
		return;

	// Get Total Damage
	uint32 totalDamage = 0;
	for (int j = 0; j < entry->size(); ++j) {
		uint32 damage = entry->elementAt(j).getValue();
		totalDamage += damage;
	}

	/// We don't want to add someone who hasn't done
	/// and damage to this
	if(totalDamage > 0)
		damageMap.put(totalDamage, creature);

	/// Anyone with an entry should be in this map
	aggroMap.put(entry->getAggroMod(), creature);

	/// Only healers should be in this map
	if(entry->getHeal() > 0)
		healMap.put(entry->getHeal(), creature);

	if (entry->hasState(ThreatStates::TAUNTED)) {
		tauntThreat = creature;
	}

	if (entry->hasState(ThreatStates::FOCUSED)) {
		focusedThreat = creature;
	}
}

CreatureObject* ThreatMatrix::getLargestThreat() {

	CreatureObject* returnThreat = NULL;

	if(tauntThreat != NULL) {

		returnThreat = tauntThreat;

	} else if(focusedThreat != NULL) {

		returnThreat = focusedThreat;

	} else {

		Vector<CreatureObject*> targetSelection;
		if(damageMap.size() > 0) {
			targetSelection.add(damageMap.elementAt(damageMap.size() -1).getValue());
			targetSelection.add(damageMap.elementAt(damageMap.size() -1).getValue());
			targetSelection.add(damageMap.elementAt(System::random(damageMap.size() -1)).getValue());
		}

		if(aggroMap.size() > 0) {
			targetSelection.add(aggroMap.elementAt(aggroMap.size() -1).getValue());
			targetSelection.add(aggroMap.elementAt(aggroMap.size() -1).getValue());
			targetSelection.add(aggroMap.elementAt(System::random(aggroMap.size() -1)).getValue());
		}

		if(healMap.size() > 0) {
			targetSelection.add(healMap.elementAt(healMap.size() -1).getValue());
		}

		returnThreat = targetSelection.get(System::random(targetSelection.size()- 1));
	}

#ifdef DEBUG
	print();

	if(returnThreat != NULL)
		System::out << "Targeting " << returnThreat->getFirstName() << endl;
	else
		System::out << "Targeting Nothing" << endl;
#endif
	clear();
	return returnThreat;
}

void ThreatMatrix::print() {
	System::out << "************* Targets *****************" << endl;
	System::out << "Taunted by: ";
	if(tauntThreat != NULL)
		System::out << tauntThreat->getFirstName() << endl;
	else
		System::out << "NULL" << endl;

	System::out << "Focused on: ";
	if(focusedThreat != NULL)
		System::out << focusedThreat->getFirstName() << endl;
	else
		System::out << "NULL" << endl;

	System::out << "************* DamageMap ***************" << endl;
	for(int i = 0; i < damageMap.size(); ++i) {
		System::out << "DamageMap["  << i << "] "
				<< damageMap.elementAt(i).getValue()->getFirstName()
				<< " " << damageMap.elementAt(i).getKey() << endl;

	}

	System::out << "************* AggroMap ***************" << endl;
	for(int i = 0; i < aggroMap.size(); ++i) {
		System::out << "AggroMap["  << i << "] "
				<< aggroMap.elementAt(i).getValue()->getFirstName()
				<< " " << aggroMap.elementAt(i).getKey() << endl;

	}

	System::out << "************* HealMap ***************" << endl;
	for(int i = 0; i < healMap.size(); ++i) {
		System::out << "HealMap["  << i << "] "
				<< healMap.elementAt(i).getValue()->getFirstName()
				<< " " << healMap.elementAt(i).getKey() << endl;
	}
	System::out << "*************************************" << endl;

}

<commit_msg>[fixed] stability issues<commit_after>/*
 * ThreatMatrix.cpp
 *
 *  Created on: 1/23/2012
 *      Author: Kyle
 */

#include "ThreatMatrix.h"
#include "ThreatMap.h"
#include "server/zone/objects/creature/CreatureObject.h"

ThreatMatrix::ThreatMatrix() {
	tauntThreat = NULL;
	focusedThreat = NULL;
}

ThreatMatrix::~ThreatMatrix() {

}

ThreatMatrix::ThreatMatrix(const ThreatMatrix& e) {

}

ThreatMatrix& ThreatMatrix::operator=(const ThreatMatrix& e) {
	//VectorMap<ManagedReference<WeaponObject*>, uint32>::operator=(e);

	return *this;
}

void ThreatMatrix::clear() {

	tauntThreat = NULL;
	focusedThreat = NULL;

	damageMap.removeAll();
	aggroMap.removeAll();
}

void ThreatMatrix::add(CreatureObject* creature, ThreatMapEntry* entry) {

	if(!creature->isPlayerCreature())
		return;

	// Get Total Damage
	uint32 totalDamage = 0;
	for (int j = 0; j < entry->size(); ++j) {
		uint32 damage = entry->elementAt(j).getValue();
		totalDamage += damage;
	}

	/// We don't want to add someone who hasn't done
	/// and damage to this
	if(totalDamage > 0)
		damageMap.put(totalDamage, creature);

	/// Anyone with an entry should be in this map
	aggroMap.put(entry->getAggroMod(), creature);

	/// Only healers should be in this map
	if(entry->getHeal() > 0)
		healMap.put(entry->getHeal(), creature);

	if (entry->hasState(ThreatStates::TAUNTED)) {
		tauntThreat = creature;
	}

	if (entry->hasState(ThreatStates::FOCUSED)) {
		focusedThreat = creature;
	}
}

CreatureObject* ThreatMatrix::getLargestThreat() {

	CreatureObject* returnThreat = NULL;

	if(tauntThreat != NULL) {

		returnThreat = tauntThreat;

	} else if(focusedThreat != NULL) {

		returnThreat = focusedThreat;

	} else {

		Vector<CreatureObject*> targetSelection;
		if(damageMap.size() > 0) {
			targetSelection.add(damageMap.elementAt(damageMap.size() -1).getValue());
			targetSelection.add(damageMap.elementAt(damageMap.size() -1).getValue());
			targetSelection.add(damageMap.elementAt(System::random(damageMap.size() -1)).getValue());
		}

		if(aggroMap.size() > 0) {
			targetSelection.add(aggroMap.elementAt(aggroMap.size() -1).getValue());
			targetSelection.add(aggroMap.elementAt(aggroMap.size() -1).getValue());
			targetSelection.add(aggroMap.elementAt(System::random(aggroMap.size() -1)).getValue());
		}

		if(healMap.size() > 0) {
			targetSelection.add(healMap.elementAt(healMap.size() -1).getValue());
		}

		if (targetSelection.size() > 0)
			returnThreat = targetSelection.get(System::random(targetSelection.size()- 1));
	}

#ifdef DEBUG
	print();

	if(returnThreat != NULL)
		System::out << "Targeting " << returnThreat->getFirstName() << endl;
	else
		System::out << "Targeting Nothing" << endl;
#endif
	clear();
	return returnThreat;
}

void ThreatMatrix::print() {
	System::out << "************* Targets *****************" << endl;
	System::out << "Taunted by: ";
	if(tauntThreat != NULL)
		System::out << tauntThreat->getFirstName() << endl;
	else
		System::out << "NULL" << endl;

	System::out << "Focused on: ";
	if(focusedThreat != NULL)
		System::out << focusedThreat->getFirstName() << endl;
	else
		System::out << "NULL" << endl;

	System::out << "************* DamageMap ***************" << endl;
	for(int i = 0; i < damageMap.size(); ++i) {
		System::out << "DamageMap["  << i << "] "
				<< damageMap.elementAt(i).getValue()->getFirstName()
				<< " " << damageMap.elementAt(i).getKey() << endl;

	}

	System::out << "************* AggroMap ***************" << endl;
	for(int i = 0; i < aggroMap.size(); ++i) {
		System::out << "AggroMap["  << i << "] "
				<< aggroMap.elementAt(i).getValue()->getFirstName()
				<< " " << aggroMap.elementAt(i).getKey() << endl;

	}

	System::out << "************* HealMap ***************" << endl;
	for(int i = 0; i < healMap.size(); ++i) {
		System::out << "HealMap["  << i << "] "
				<< healMap.elementAt(i).getValue()->getFirstName()
				<< " " << healMap.elementAt(i).getKey() << endl;
	}
	System::out << "*************************************" << endl;

}

<|endoftext|>


<commit_before>#include <stddef.h>
#include <stdlib.h>
#include <new>
#include <string>
#include <locale>
#include <stdio.h>
#include <iostream>
#include "novoht.h"

NoVoHT::NoVoHT(){
   kvpairs = new kvpair*[1000];
   size = 1000;
   numEl = 0;
   magicNumber = 1000;
   resizeNum = -1;
}

/*
NoVoHT::NoVoHT(int s){
   kvpairs = new kvpair*[s];
   size = s;
   numEl=0;
   file = NULL;
}

NoVoHT::NoVoHT(char * f){
   kvpairs = new kvpair*[1000];
   size = 1000;
   numEl=0;
   file = f;
   readFile();
}
*/
NoVoHT::NoVoHT(string f,int s, int m){
   kvpairs = new kvpair*[s];
   for (int x = 0;x<s;s++){
      kvpairs[x] = NULL;
   }
   magicNumber = m;
   nRem = 0;
   resizeNum = 0;
   size = s;
   numEl=0;
   filename=f;
   dbfile = fopen(f.c_str(), "r+");
   if (!dbfile) dbfile = fopen(f.c_str(), "w+");
   readFile();
}
NoVoHT::NoVoHT(string f,int s, int m, float r){
   kvpairs = new kvpair*[s];
   for (int x = 0;x<s;x++){
      kvpairs[x] = NULL;
   }
   magicNumber = m;
   nRem = 0;
   resizeNum = r;
   size = s;
   numEl=0;
   filename=f;
   dbfile = fopen(f.c_str(), "r+");
   if (!dbfile) dbfile = fopen(f.c_str(), "w+");
   readFile();
}
/*
NoVoHT::NoVoHT(char * f, NoVoHT *map){
   kvpairs = new kvpair*[1000];
   size = 1000;
   numEl=0;
   file = f;
   readFile();
}*/
NoVoHT::~NoVoHT(){
   if (dbfile){
      writeFile();
      fclose(dbfile);
   }
   for (int i = 0; i < size; i++){
      fsu(kvpairs[i]);
   }
   delete [] kvpairs;
}

//0 success, -1 no insert, -2 no write
int NoVoHT::put(string k, string v){
   if (numEl >= size*resizeNum) {
      if (resizeNum !=0){
         resize(size*2);
      }
   }
   int slot;
   slot = hash(k)%size;
   kvpair *cur = kvpairs[slot];
   kvpair *add = new kvpair;
   add->key = k;
   add->val = v;
   add->next = NULL;
   if (cur == NULL){
      kvpairs[slot] = add;
      numEl++;
      return write(add);
   }
   while (cur->next != NULL){
      if (k.compare(cur->key) == 0) {delete add; return -1;}
      cur = cur->next;
   }
   if (k.compare(cur->key) == 0) {delete add; return -1;}
   cur->next = add;
   numEl++;
   return write(add);
}

string* NoVoHT::get(string k){
   int loc = hash(k)%size;
   kvpair *cur = kvpairs[loc];
   while (cur != NULL && !k.empty()){
      if (k.compare(cur->key) == 0) return &(cur->val);
      cur = cur->next;
   }
   return NULL;
}

//return 0 for success, -1 fail to remove, -2+ write failure
int NoVoHT::remove(string k){
   int ret =0;
   int loc = hash(k)%size;
   kvpair *cur = kvpairs[loc];
   if (cur == NULL) return ret-1;       //not found
   if (k.compare(cur->key) ==0) {
      fpos_t toRem = kvpairs[loc]->pos;
      kvpairs[loc] = cur->next;
      numEl--;
      ret+=mark(toRem);
      delete cur;
      nRem++;
      if (nRem == magicNumber) ret+=writeFile(); //write and save write success
      return ret;
   }
   while(cur != NULL){
      if (cur->next == NULL) return ret-1;
      else if (k.compare(cur->next->key)==0){
         kvpair *r = cur->next;
         cur->next = r->next;
         ret+=mark(r->pos);              //mark and sace status code
         delete r;
         numEl--;
         nRem++;
         if (nRem == magicNumber) ret+=writeFile();              //mark and sace status code
         return ret;
      }
      cur = cur->next;
   }
   return ret-1;        //not found
}

//return 0 if success -2 if failed
//write hashmap to file
int NoVoHT::writeFile(){
   int ret =0;
   if (!dbfile)return -2;
   //fclose(dbfile);
   //dbfile = fopen(filename.c_str(), "w+");
   //dbfile = freopen(filename.c_str(), "w+", dbfile);
   fseek(dbfile, 0,SEEK_CUR);
   for (int i=0; i<size;i++){
      kvpair *cur = kvpairs[i];
      while (cur != NULL){
         if(!cur->key.empty() && !cur->val.empty()){
                fgetpos(dbfile, &(cur->pos));
                fprintf(dbfile, "%s\t%s\n", cur->key.c_str(), cur->val.c_str());
         }
         cur = cur->next;
      }
   }
   ftruncate(fileno(dbfile), (off_t)SEEK_CUR-SEEK_SET-1);
   //fclose(out);
   return ret;
}

//success 0 fail -2
//resize the hashmap's base size
void NoVoHT::resize(int ns){
   int olds = size;
   size = ns;
   kvpair** old = kvpairs;
   kvpairs = new kvpair*[ns];
   for (int z=0; z<ns; z++) { kvpairs[z] = NULL;}
   numEl = 0;
   for (int i=0; i<olds;i++){
      kvpair *cur = old[i];
      while (cur != NULL){
         put(cur->key, cur->val);
         kvpair *last = cur;
         cur = cur->next;
         delete last;
      }
   }
   delete [] old;
}

//success 0 fail -2
//write kvpair to file
int NoVoHT::write(kvpair * p){
   //FILE * data = fopen(file.c_str(), "a");
   if (!dbfile) return -2;
   fseek(dbfile, 0, SEEK_END);
   fgetpos(dbfile, &(p->pos));
   fprintf(dbfile, "%s\t%s\n", p->key.c_str(), p->val.c_str());
   //fclose(data);
   return 0;
}

//success 0 fail -2
//mark line in file for deletion
int NoVoHT::mark(fpos_t position){
   if(!dbfile) return -2;
   //FILE * data = fopen(file.c_str(), "r+");
   fsetpos(dbfile, &position);
   fputc((int) '~', dbfile);
   //fclose(data);
   return 0;
}

void NoVoHT::readFile(){
   if(!dbfile) return;
   //FILE * data = fopen(file.c_str(), "r+");
   char s[300];
   while(fscanf(dbfile, "%s", s) != EOF){
      string key(s);
      fscanf(dbfile,"%s",s);
      string val(s);
      if (key[0] != '~'){
         put(key,val);
      }
   }
   //fclose(data);
   writeFile();
}

unsigned long long hash(string k){ //FNV hash
#if SIZE_OF_LONG_LONG_INT==8
#define FNV_PRIME 14695981039346656037
#define FNV_OFFSET 1099511628211
#else //SIZE_OF_LONG_LONG_INT == 4
#define FNV_PRIME 16777619
#define FNV_OFFSET 2166136261
#endif
   unsigned long long x = FNV_PRIME;
   for (unsigned int y=0;y<k.length();y++){
      x = x ^ (k[y]);
      x = x * FNV_OFFSET;
   }
   return (x);
}

void fsu(kvpair* p){
   if(p != NULL){
      fsu(p->next);
      delete p;
   }
}
<commit_msg>	modified:   novoht.cxx<commit_after>#include <stddef.h>
#include <stdlib.h>
#include <new>
#include <string>
#include <locale>
#include <stdio.h>
#include <iostream>
#include "novoht.h"

NoVoHT::NoVoHT(){
   kvpairs = new kvpair*[1000];
   size = 1000;
   numEl = 0;
   magicNumber = 1000;
   resizeNum = -1;
}

/*
NoVoHT::NoVoHT(int s){
   kvpairs = new kvpair*[s];
   size = s;
   numEl=0;
   file = NULL;
}

NoVoHT::NoVoHT(char * f){
   kvpairs = new kvpair*[1000];
   size = 1000;
   numEl=0;
   file = f;
   readFile();
}
*/
NoVoHT::NoVoHT(string f,int s, int m){
   kvpairs = new kvpair*[s];
   for (int x = 0;x<s;s++){
      kvpairs[x] = NULL;
   }
   magicNumber = m;
   nRem = 0;
   resizeNum = 0;
   size = s;
   numEl=0;
   filename=f;
   dbfile = fopen(f.c_str(), "r+");
   if (!dbfile) dbfile = fopen(f.c_str(), "w+");
   readFile();
}
NoVoHT::NoVoHT(string f,int s, int m, float r){
   kvpairs = new kvpair*[s];
   for (int x = 0;x<s;x++){
      kvpairs[x] = NULL;
   }
   magicNumber = m;
   nRem = 0;
   resizeNum = r;
   size = s;
   numEl=0;
   filename=f;
   dbfile = fopen(f.c_str(), "r+");
   if (!dbfile) dbfile = fopen(f.c_str(), "w+");
   readFile();
}
/*
NoVoHT::NoVoHT(char * f, NoVoHT *map){
   kvpairs = new kvpair*[1000];
   size = 1000;
   numEl=0;
   file = f;
   readFile();
}*/
NoVoHT::~NoVoHT(){
   if (dbfile){
      writeFile();
      fclose(dbfile);
   }
   for (int i = 0; i < size; i++){
      fsu(kvpairs[i]);
   }
   delete [] kvpairs;
}

//0 success, -1 no insert, -2 no write
int NoVoHT::put(string k, string v){
   if (numEl >= size*resizeNum) {
      if (resizeNum !=0){
         resize(size*2);
      }
   }
   int slot;
   slot = hash(k)%size;
   kvpair *cur = kvpairs[slot];
   kvpair *add = new kvpair;
   add->key = k;
   add->val = v;
   add->next = NULL;
   if (cur == NULL){
      kvpairs[slot] = add;
      numEl++;
      return write(add);
   }
   while (cur->next != NULL){
      if (k.compare(cur->key) == 0) {delete add; return -1;}
      cur = cur->next;
   }
   if (k.compare(cur->key) == 0) {delete add; return -1;}
   cur->next = add;
   numEl++;
   return write(add);
}

string* NoVoHT::get(string k){
   int loc = hash(k)%size;
   kvpair *cur = kvpairs[loc];
   while (cur != NULL && !k.empty()){
      if (k.compare(cur->key) == 0) return &(cur->val);
      cur = cur->next;
   }
   return NULL;
}

//return 0 for success, -1 fail to remove, -2+ write failure
int NoVoHT::remove(string k){
   int ret =0;
   int loc = hash(k)%size;
   kvpair *cur = kvpairs[loc];
   if (cur == NULL) return ret-1;       //not found
   if (k.compare(cur->key) ==0) {
      fpos_t toRem = kvpairs[loc]->pos;
      kvpairs[loc] = cur->next;
      numEl--;
      ret+=mark(toRem);
      delete cur;
      nRem++;
      if (nRem == magicNumber) ret+=writeFile(); //write and save write success
      return ret;
   }
   while(cur != NULL){
      if (cur->next == NULL) return ret-1;
      else if (k.compare(cur->next->key)==0){
         kvpair *r = cur->next;
         cur->next = r->next;
         ret+=mark(r->pos);              //mark and sace status code
         delete r;
         numEl--;
         nRem++;
         if (nRem == magicNumber) ret+=writeFile();              //mark and sace status code
         return ret;
      }
      cur = cur->next;
   }
   return ret-1;        //not found
}

//return 0 if success -2 if failed
//write hashmap to file
int NoVoHT::writeFile(){
   int ret =0;
   if (!dbfile)return -2;
   //fclose(dbfile);
   //dbfile = fopen(filename.c_str(), "w+");
   //dbfile = freopen(filename.c_str(), "w+", dbfile);
   fseek(dbfile, 0,SEEK_CUR);
   for (int i=0; i<size;i++){
      kvpair *cur = kvpairs[i];
      while (cur != NULL){
         if(!cur->key.empty() && !cur->val.empty()){
                fgetpos(dbfile, &(cur->pos));
                fprintf(dbfile, "%s\t%s\n", cur->key.c_str(), cur->val.c_str());
         }
         cur = cur->next;
      }
   }
   ftruncate(fileno(dbfile), (off_t)SEEK_CUR-SEEK_SET-1);
   //fclose(out);
   return ret;
}

//success 0 fail -2
//resize the hashmap's base size
void NoVoHT::resize(int ns){
   int olds = size;
   size = ns;
   kvpair** old = kvpairs;
   kvpairs = new kvpair*[ns];
   for (int z=0; z<ns; z++) { kvpairs[z] = NULL;}
   numEl = 0;
   for (int i=0; i<olds;i++){
      kvpair *cur = old[i];
      while (cur != NULL){
         put(cur->key, cur->val);
         kvpair *last = cur;
         cur = cur->next;
         delete last;
      }
   }
   delete [] old;
}

//success 0 fail -2
//write kvpair to file
int NoVoHT::write(kvpair * p){
   //FILE * data = fopen(file.c_str(), "a");
   if (!dbfile) return -2;
   fseek(dbfile, 0, SEEK_END);
   fgetpos(dbfile, &(p->pos));
   fprintf(dbfile, "%s\t%s\t", p->key.c_str(), p->val.c_str());
   //fclose(data);
   return 0;
}

//success 0 fail -2
//mark line in file for deletion
int NoVoHT::mark(fpos_t position){
   if(!dbfile) return -2;
   //FILE * data = fopen(file.c_str(), "r+");
   fsetpos(dbfile, &position);
   fputc((int) '~', dbfile);
   //fclose(data);
   return 0;
}

void NoVoHT::readFile(){
   if(!dbfile) return;
   //FILE * data = fopen(file.c_str(), "r+");
   char s[300];
   while(fscanf(dbfile, "%s\t", s) != EOF){
      string key(s);
      fscanf(dbfile,"%s\t",s);
      string val(s);
      if (key[0] != '~'){
         put(key,val);
      }
   }
   //fclose(data);
   writeFile();
}

unsigned long long hash(string k){ //FNV hash
#if SIZE_OF_LONG_LONG_INT==8
#define FNV_PRIME 14695981039346656037
#define FNV_OFFSET 1099511628211
#else //SIZE_OF_LONG_LONG_INT == 4
#define FNV_PRIME 16777619
#define FNV_OFFSET 2166136261
#endif
   unsigned long long x = FNV_PRIME;
   for (unsigned int y=0;y<k.length();y++){
      x = x ^ (k[y]);
      x = x * FNV_OFFSET;
   }
   return (x);
}

void fsu(kvpair* p){
   if(p != NULL){
      fsu(p->next);
      delete p;
   }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/detail/AtFork.h>

#include <atomic>
#include <mutex>
#include <thread>

#include <glog/logging.h>

#include <folly/portability/GMock.h>
#include <folly/portability/GTest.h>

class AtForkTest : public testing::Test {};

TEST_F(AtForkTest, prepare) {
  int foo;
  bool forked = false;
  folly::detail::AtFork::registerHandler(
      &foo,
      [&] {
        forked = true;
        return true;
      },
      [] {},
      [] {});
  auto pid = folly::kIsSanitizeThread
      ? folly::detail::AtFork::forkInstrumented(fork)
      : fork();
  if (pid) {
    int status;
    auto pid2 = waitpid(pid, &status, 0);
    EXPECT_EQ(status, 0);
    EXPECT_EQ(pid, pid2);
  } else {
    _exit(0);
  }
  EXPECT_TRUE(forked);
  forked = false;
  folly::detail::AtFork::unregisterHandler(&foo);
  pid = fork();
  if (pid) {
    int status;
    auto pid2 = waitpid(pid, &status, 0);
    EXPECT_EQ(status, 0);
    EXPECT_EQ(pid, pid2);
  } else {
    _exit(0);
  }
  EXPECT_FALSE(forked);
}

TEST_F(AtForkTest, ordering) {
  std::atomic<bool> started{false};
  std::mutex a;
  std::mutex b;
  int foo;
  int foo2;
  folly::detail::AtFork::registerHandler(
      &foo,
      [&] { return a.try_lock(); },
      [&] { a.unlock(); },
      [&] { a.unlock(); });
  folly::detail::AtFork::registerHandler(
      &foo2,
      [&] { return b.try_lock(); },
      [&] { b.unlock(); },
      [&] { b.unlock(); });

  auto thr = std::thread([&]() {
    std::lock_guard<std::mutex> g(a);
    started = true;
    usleep(100);
    std::lock_guard<std::mutex> g2(b);
  });
  while (!started) {
  }
  auto pid = folly::kIsSanitizeThread
      ? folly::detail::AtFork::forkInstrumented(fork)
      : fork();
  if (pid) {
    int status;
    auto pid2 = waitpid(pid, &status, 0);
    EXPECT_TRUE(WIFEXITED(status));
    EXPECT_THAT(
        WEXITSTATUS(status),
        folly::kIsSanitizeThread //
            ? testing::AnyOfArray({0, 66})
            : testing::AnyOfArray({0}));
    EXPECT_EQ(pid, pid2);
  } else {
    _exit(0);
  }
  thr.join();
}
<commit_msg>check that fork() returns success in AtFork tests<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/detail/AtFork.h>

#include <atomic>
#include <mutex>
#include <thread>

#include <glog/logging.h>

#include <folly/portability/GMock.h>
#include <folly/portability/GTest.h>

class AtForkTest : public testing::Test {};

TEST_F(AtForkTest, prepare) {
  int foo;
  bool forked = false;
  folly::detail::AtFork::registerHandler(
      &foo,
      [&] {
        forked = true;
        return true;
      },
      [] {},
      [] {});
  auto pid = folly::kIsSanitizeThread
      ? folly::detail::AtFork::forkInstrumented(fork)
      : fork();
  PCHECK(pid != -1);
  if (pid) {
    int status;
    auto pid2 = waitpid(pid, &status, 0);
    EXPECT_EQ(status, 0);
    EXPECT_EQ(pid, pid2);
  } else {
    _exit(0);
  }
  EXPECT_TRUE(forked);
  forked = false;
  folly::detail::AtFork::unregisterHandler(&foo);
  pid = fork();
  PCHECK(pid != -1);
  if (pid) {
    int status;
    auto pid2 = waitpid(pid, &status, 0);
    EXPECT_EQ(status, 0);
    EXPECT_EQ(pid, pid2);
  } else {
    _exit(0);
  }
  EXPECT_FALSE(forked);
}

TEST_F(AtForkTest, ordering) {
  std::atomic<bool> started{false};
  std::mutex a;
  std::mutex b;
  int foo;
  int foo2;
  folly::detail::AtFork::registerHandler(
      &foo,
      [&] { return a.try_lock(); },
      [&] { a.unlock(); },
      [&] { a.unlock(); });
  folly::detail::AtFork::registerHandler(
      &foo2,
      [&] { return b.try_lock(); },
      [&] { b.unlock(); },
      [&] { b.unlock(); });

  auto thr = std::thread([&]() {
    std::lock_guard<std::mutex> g(a);
    started = true;
    usleep(100);
    std::lock_guard<std::mutex> g2(b);
  });
  while (!started) {
  }
  auto pid = folly::kIsSanitizeThread
      ? folly::detail::AtFork::forkInstrumented(fork)
      : fork();
  PCHECK(pid != -1);
  if (pid) {
    int status;
    auto pid2 = waitpid(pid, &status, 0);
    EXPECT_TRUE(WIFEXITED(status));
    EXPECT_THAT(
        WEXITSTATUS(status),
        folly::kIsSanitizeThread //
            ? testing::AnyOfArray({0, 66})
            : testing::AnyOfArray({0}));
    EXPECT_EQ(pid, pid2);
  } else {
    _exit(0);
  }
  thr.join();
}
<|endoftext|>


<commit_before>// Copyright (c) 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quiche/quic/qbone/bonnet/tun_device_controller.h"

#include <linux/if_addr.h>
#include <linux/rtnetlink.h>

#include "absl/strings/string_view.h"
#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/qbone/platform/mock_netlink.h"
#include "quiche/quic/qbone/qbone_constants.h"

ABSL_DECLARE_FLAG(bool, qbone_tun_device_replace_default_routing_rules);
ABSL_DECLARE_FLAG(int, qbone_route_init_cwnd);

namespace quic::test {
namespace {
using ::testing::Eq;

constexpr int kIfindex = 42;
constexpr char kIfname[] = "qbone0";

const IpRange kIpRange = []() {
  IpRange range;
  QCHECK(range.FromString("2604:31c0:2::/64"));
  return range;
}();

constexpr char kOldAddress[] = "1.2.3.4";
constexpr int kOldPrefixLen = 24;

using ::testing::_;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::StrictMock;

MATCHER_P(IpRangeEq, range,
          absl::StrCat("expected IpRange to equal ", range.ToString())) {
  return arg == range;
}

class TunDeviceControllerTest : public QuicTest {
 public:
  TunDeviceControllerTest()
      : controller_(kIfname, true, &netlink_),
        link_local_range_(*QboneConstants::TerminatorLocalAddressRange()) {
    controller_.RegisterAddressUpdateCallback(
        [this](QuicIpAddress address) { notified_address_ = address; });
  }

 protected:
  void ExpectLinkInfo(const std::string& interface_name, int ifindex) {
    EXPECT_CALL(netlink_, GetLinkInfo(interface_name, _))
        .WillOnce(Invoke([ifindex](absl::string_view ifname,
                                   NetlinkInterface::LinkInfo* link_info) {
          link_info->index = ifindex;
          return true;
        }));
  }

  MockNetlink netlink_;
  TunDeviceController controller_;
  QuicIpAddress notified_address_;

  IpRange link_local_range_;
};

TEST_F(TunDeviceControllerTest, AddressAppliedWhenNoneExisted) {
  ExpectLinkInfo(kIfname, kIfindex);

  EXPECT_CALL(netlink_, GetAddresses(kIfindex, _, _, _)).WillOnce(Return(true));

  EXPECT_CALL(netlink_,
              ChangeLocalAddress(
                  kIfindex, NetlinkInterface::Verb::kAdd,
                  kIpRange.FirstAddressInRange(), kIpRange.prefix_length(),
                  IFA_F_PERMANENT | IFA_F_NODAD, RT_SCOPE_LINK, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateAddress(kIpRange));
  EXPECT_THAT(notified_address_, Eq(kIpRange.FirstAddressInRange()));
}

TEST_F(TunDeviceControllerTest, OldAddressesAreRemoved) {
  ExpectLinkInfo(kIfname, kIfindex);

  EXPECT_CALL(netlink_, GetAddresses(kIfindex, _, _, _))
      .WillOnce(Invoke([](int interface_index, uint8_t unwanted_flags,
                          std::vector<NetlinkInterface::AddressInfo>* addresses,
                          int* num_ipv6_nodad_dadfailed_addresses) {
        NetlinkInterface::AddressInfo info{};
        info.interface_address.FromString(kOldAddress);
        info.prefix_length = kOldPrefixLen;
        addresses->emplace_back(info);
        return true;
      }));

  QuicIpAddress old_address;
  old_address.FromString(kOldAddress);

  EXPECT_CALL(netlink_,
              ChangeLocalAddress(kIfindex, NetlinkInterface::Verb::kRemove,
                                 old_address, kOldPrefixLen, _, _, _))
      .WillOnce(Return(true));

  EXPECT_CALL(netlink_,
              ChangeLocalAddress(
                  kIfindex, NetlinkInterface::Verb::kAdd,
                  kIpRange.FirstAddressInRange(), kIpRange.prefix_length(),
                  IFA_F_PERMANENT | IFA_F_NODAD, RT_SCOPE_LINK, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateAddress(kIpRange));
  EXPECT_THAT(notified_address_, Eq(kIpRange.FirstAddressInRange()));
}

TEST_F(TunDeviceControllerTest, UpdateRoutesRemovedOldRoutes) {
  ExpectLinkInfo(kIfname, kIfindex);

  const int num_matching_routes = 3;
  EXPECT_CALL(netlink_, GetRouteInfo(_))
      .WillOnce(
          Invoke([](std::vector<NetlinkInterface::RoutingRule>* routing_rules) {
            NetlinkInterface::RoutingRule non_matching_route;
            non_matching_route.table = QboneConstants::kQboneRouteTableId;
            non_matching_route.out_interface = kIfindex + 1;
            routing_rules->push_back(non_matching_route);

            NetlinkInterface::RoutingRule matching_route;
            matching_route.table = QboneConstants::kQboneRouteTableId;
            matching_route.out_interface = kIfindex;
            matching_route.init_cwnd = NetlinkInterface::kUnspecifiedInitCwnd;
            for (int i = 0; i < num_matching_routes; i++) {
              routing_rules->push_back(matching_route);
            }

            NetlinkInterface::RoutingRule non_matching_table;
            non_matching_table.table = QboneConstants::kQboneRouteTableId + 1;
            non_matching_table.out_interface = kIfindex;
            routing_rules->push_back(non_matching_table);
            return true;
          }));

  EXPECT_CALL(netlink_,
              ChangeRoute(NetlinkInterface::Verb::kRemove,
                          QboneConstants::kQboneRouteTableId, _, _, _, kIfindex,
                          NetlinkInterface::kUnspecifiedInitCwnd))
      .Times(num_matching_routes)
      .WillRepeatedly(Return(true));

  EXPECT_CALL(netlink_, GetRuleInfo(_)).WillOnce(Return(true));

  EXPECT_CALL(netlink_, ChangeRule(NetlinkInterface::Verb::kAdd,
                                   QboneConstants::kQboneRouteTableId,
                                   IpRangeEq(kIpRange)))
      .WillOnce(Return(true));

  EXPECT_CALL(netlink_,
              ChangeRoute(NetlinkInterface::Verb::kReplace,
                          QboneConstants::kQboneRouteTableId,
                          IpRangeEq(link_local_range_), _, _, kIfindex, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateRoutes(kIpRange, {}));
}

TEST_F(TunDeviceControllerTest, UpdateRoutesAddsNewRoutes) {
  ExpectLinkInfo(kIfname, kIfindex);

  EXPECT_CALL(netlink_, GetRouteInfo(_)).WillOnce(Return(true));

  EXPECT_CALL(netlink_, GetRuleInfo(_)).WillOnce(Return(true));

  absl::SetFlag(&FLAGS_qbone_route_init_cwnd, 32);
  EXPECT_CALL(netlink_, ChangeRoute(NetlinkInterface::Verb::kReplace,
                                    QboneConstants::kQboneRouteTableId,
                                    IpRangeEq(kIpRange), _, _, kIfindex,
                                    absl::GetFlag(FLAGS_qbone_route_init_cwnd)))
      .Times(2)
      .WillRepeatedly(Return(true))
      .RetiresOnSaturation();

  EXPECT_CALL(netlink_, ChangeRule(NetlinkInterface::Verb::kAdd,
                                   QboneConstants::kQboneRouteTableId,
                                   IpRangeEq(kIpRange)))
      .WillOnce(Return(true));

  EXPECT_CALL(netlink_,
              ChangeRoute(NetlinkInterface::Verb::kReplace,
                          QboneConstants::kQboneRouteTableId,
                          IpRangeEq(link_local_range_), _, _, kIfindex, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateRoutes(kIpRange, {kIpRange, kIpRange}));
}

TEST_F(TunDeviceControllerTest, EmptyUpdateRouteKeepsLinkLocalRoute) {
  ExpectLinkInfo(kIfname, kIfindex);

  EXPECT_CALL(netlink_, GetRouteInfo(_)).WillOnce(Return(true));

  EXPECT_CALL(netlink_, GetRuleInfo(_)).WillOnce(Return(true));

  EXPECT_CALL(netlink_, ChangeRule(NetlinkInterface::Verb::kAdd,
                                   QboneConstants::kQboneRouteTableId,
                                   IpRangeEq(kIpRange)))
      .WillOnce(Return(true));

  EXPECT_CALL(netlink_,
              ChangeRoute(NetlinkInterface::Verb::kReplace,
                          QboneConstants::kQboneRouteTableId,
                          IpRangeEq(link_local_range_), _, _, kIfindex, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateRoutes(kIpRange, {}));
}

TEST_F(TunDeviceControllerTest, DisablingRoutingRulesSkipsRuleCreation) {
  absl::SetFlag(&FLAGS_qbone_tun_device_replace_default_routing_rules, false);
  ExpectLinkInfo(kIfname, kIfindex);

  EXPECT_CALL(netlink_, GetRouteInfo(_)).WillOnce(Return(true));

  EXPECT_CALL(netlink_, ChangeRoute(NetlinkInterface::Verb::kReplace,
                                    QboneConstants::kQboneRouteTableId,
                                    IpRangeEq(kIpRange), _, _, kIfindex, _))
      .Times(2)
      .WillRepeatedly(Return(true))
      .RetiresOnSaturation();

  EXPECT_CALL(netlink_,
              ChangeRoute(NetlinkInterface::Verb::kReplace,
                          QboneConstants::kQboneRouteTableId,
                          IpRangeEq(link_local_range_), _, _, kIfindex, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateRoutes(kIpRange, {kIpRange, kIpRange}));
}

class DisabledTunDeviceControllerTest : public QuicTest {
 public:
  DisabledTunDeviceControllerTest()
      : controller_(kIfname, false, &netlink_),
        link_local_range_(*QboneConstants::TerminatorLocalAddressRange()) {}

  StrictMock<MockNetlink> netlink_;
  TunDeviceController controller_;

  IpRange link_local_range_;
};

TEST_F(DisabledTunDeviceControllerTest, UpdateRoutesIsNop) {
  EXPECT_THAT(controller_.UpdateRoutes(kIpRange, {}), Eq(true));
}

TEST_F(DisabledTunDeviceControllerTest, UpdateAddressIsNop) {
  EXPECT_THAT(controller_.UpdateAddress(kIpRange), Eq(true));
}

}  // namespace
}  // namespace quic::test
<commit_msg>Internal change<commit_after>// Copyright (c) 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quiche/quic/qbone/bonnet/tun_device_controller.h"

#include <linux/if_addr.h>
#include <linux/rtnetlink.h>

#include "absl/strings/string_view.h"
#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/qbone/platform/mock_netlink.h"
#include "quiche/quic/qbone/qbone_constants.h"

ABSL_DECLARE_FLAG(bool, qbone_tun_device_replace_default_routing_rules);
ABSL_DECLARE_FLAG(int, qbone_route_init_cwnd);

namespace quic::test {
namespace {
using ::testing::Eq;

constexpr int kIfindex = 42;
constexpr char kIfname[] = "qbone0";

const IpRange kIpRange = []() {
  IpRange range;
  QCHECK(range.FromString("2604:31c0:2::/64"));
  return range;
}();

constexpr char kOldAddress[] = "1.2.3.4";
constexpr int kOldPrefixLen = 24;

using ::testing::_;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::StrictMock;

MATCHER_P(IpRangeEq, range,
          absl::StrCat("expected IpRange to equal ", range.ToString())) {
  return arg == range;
}

class TunDeviceControllerTest : public QuicTest {
 public:
  TunDeviceControllerTest()
      : controller_(kIfname, true, &netlink_),
        link_local_range_(*QboneConstants::TerminatorLocalAddressRange()) {
    controller_.RegisterAddressUpdateCallback(
        [this](QuicIpAddress address) { notified_address_ = address; });
  }

 protected:
  void ExpectLinkInfo(const std::string& interface_name, int ifindex) {
    EXPECT_CALL(netlink_, GetLinkInfo(interface_name, _))
        .WillOnce(Invoke([ifindex](absl::string_view ifname,
                                   NetlinkInterface::LinkInfo* link_info) {
          link_info->index = ifindex;
          return true;
        }));
  }

  MockNetlink netlink_;
  TunDeviceController controller_;
  QuicIpAddress notified_address_;

  IpRange link_local_range_;
};

TEST_F(TunDeviceControllerTest, AddressAppliedWhenNoneExisted) {
  ExpectLinkInfo(kIfname, kIfindex);

  EXPECT_CALL(netlink_, GetAddresses(kIfindex, _, _, _)).WillOnce(Return(true));

  EXPECT_CALL(netlink_,
              ChangeLocalAddress(
                  kIfindex, NetlinkInterface::Verb::kAdd,
                  kIpRange.FirstAddressInRange(), kIpRange.prefix_length(),
                  IFA_F_PERMANENT | IFA_F_NODAD, RT_SCOPE_LINK, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateAddress(kIpRange));
  EXPECT_THAT(notified_address_, Eq(kIpRange.FirstAddressInRange()));
}

TEST_F(TunDeviceControllerTest, OldAddressesAreRemoved) {
  ExpectLinkInfo(kIfname, kIfindex);

  EXPECT_CALL(netlink_, GetAddresses(kIfindex, _, _, _))
      .WillOnce(Invoke([](int interface_index, uint8_t unwanted_flags,
                          std::vector<NetlinkInterface::AddressInfo>* addresses,
                          int* num_ipv6_nodad_dadfailed_addresses) {
        NetlinkInterface::AddressInfo info{};
        info.interface_address.FromString(kOldAddress);
        info.prefix_length = kOldPrefixLen;
        addresses->emplace_back(info);
        return true;
      }));

  QuicIpAddress old_address;
  old_address.FromString(kOldAddress);

  EXPECT_CALL(netlink_,
              ChangeLocalAddress(kIfindex, NetlinkInterface::Verb::kRemove,
                                 old_address, kOldPrefixLen, _, _, _))
      .WillOnce(Return(true));

  EXPECT_CALL(netlink_,
              ChangeLocalAddress(
                  kIfindex, NetlinkInterface::Verb::kAdd,
                  kIpRange.FirstAddressInRange(), kIpRange.prefix_length(),
                  IFA_F_PERMANENT | IFA_F_NODAD, RT_SCOPE_LINK, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateAddress(kIpRange));
  EXPECT_THAT(notified_address_, Eq(kIpRange.FirstAddressInRange()));
}

TEST_F(TunDeviceControllerTest, UpdateRoutesRemovedOldRoutes) {
  ExpectLinkInfo(kIfname, kIfindex);

  const int num_matching_routes = 3;
  EXPECT_CALL(netlink_, GetRouteInfo(_))
      .WillOnce(
          Invoke([](std::vector<NetlinkInterface::RoutingRule>* routing_rules) {
            NetlinkInterface::RoutingRule non_matching_route{};
            non_matching_route.table = QboneConstants::kQboneRouteTableId;
            non_matching_route.out_interface = kIfindex + 1;
            routing_rules->push_back(non_matching_route);

            NetlinkInterface::RoutingRule matching_route{};
            matching_route.table = QboneConstants::kQboneRouteTableId;
            matching_route.out_interface = kIfindex;
            matching_route.init_cwnd = NetlinkInterface::kUnspecifiedInitCwnd;
            for (int i = 0; i < num_matching_routes; i++) {
              routing_rules->push_back(matching_route);
            }

            NetlinkInterface::RoutingRule non_matching_table{};
            non_matching_table.table = QboneConstants::kQboneRouteTableId + 1;
            non_matching_table.out_interface = kIfindex;
            routing_rules->push_back(non_matching_table);
            return true;
          }));

  EXPECT_CALL(netlink_,
              ChangeRoute(NetlinkInterface::Verb::kRemove,
                          QboneConstants::kQboneRouteTableId, _, _, _, kIfindex,
                          NetlinkInterface::kUnspecifiedInitCwnd))
      .Times(num_matching_routes)
      .WillRepeatedly(Return(true));

  EXPECT_CALL(netlink_, GetRuleInfo(_)).WillOnce(Return(true));

  EXPECT_CALL(netlink_, ChangeRule(NetlinkInterface::Verb::kAdd,
                                   QboneConstants::kQboneRouteTableId,
                                   IpRangeEq(kIpRange)))
      .WillOnce(Return(true));

  EXPECT_CALL(netlink_,
              ChangeRoute(NetlinkInterface::Verb::kReplace,
                          QboneConstants::kQboneRouteTableId,
                          IpRangeEq(link_local_range_), _, _, kIfindex, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateRoutes(kIpRange, {}));
}

TEST_F(TunDeviceControllerTest, UpdateRoutesAddsNewRoutes) {
  ExpectLinkInfo(kIfname, kIfindex);

  EXPECT_CALL(netlink_, GetRouteInfo(_)).WillOnce(Return(true));

  EXPECT_CALL(netlink_, GetRuleInfo(_)).WillOnce(Return(true));

  absl::SetFlag(&FLAGS_qbone_route_init_cwnd, 32);
  EXPECT_CALL(netlink_, ChangeRoute(NetlinkInterface::Verb::kReplace,
                                    QboneConstants::kQboneRouteTableId,
                                    IpRangeEq(kIpRange), _, _, kIfindex,
                                    absl::GetFlag(FLAGS_qbone_route_init_cwnd)))
      .Times(2)
      .WillRepeatedly(Return(true))
      .RetiresOnSaturation();

  EXPECT_CALL(netlink_, ChangeRule(NetlinkInterface::Verb::kAdd,
                                   QboneConstants::kQboneRouteTableId,
                                   IpRangeEq(kIpRange)))
      .WillOnce(Return(true));

  EXPECT_CALL(netlink_,
              ChangeRoute(NetlinkInterface::Verb::kReplace,
                          QboneConstants::kQboneRouteTableId,
                          IpRangeEq(link_local_range_), _, _, kIfindex, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateRoutes(kIpRange, {kIpRange, kIpRange}));
}

TEST_F(TunDeviceControllerTest, EmptyUpdateRouteKeepsLinkLocalRoute) {
  ExpectLinkInfo(kIfname, kIfindex);

  EXPECT_CALL(netlink_, GetRouteInfo(_)).WillOnce(Return(true));

  EXPECT_CALL(netlink_, GetRuleInfo(_)).WillOnce(Return(true));

  EXPECT_CALL(netlink_, ChangeRule(NetlinkInterface::Verb::kAdd,
                                   QboneConstants::kQboneRouteTableId,
                                   IpRangeEq(kIpRange)))
      .WillOnce(Return(true));

  EXPECT_CALL(netlink_,
              ChangeRoute(NetlinkInterface::Verb::kReplace,
                          QboneConstants::kQboneRouteTableId,
                          IpRangeEq(link_local_range_), _, _, kIfindex, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateRoutes(kIpRange, {}));
}

TEST_F(TunDeviceControllerTest, DisablingRoutingRulesSkipsRuleCreation) {
  absl::SetFlag(&FLAGS_qbone_tun_device_replace_default_routing_rules, false);
  ExpectLinkInfo(kIfname, kIfindex);

  EXPECT_CALL(netlink_, GetRouteInfo(_)).WillOnce(Return(true));

  EXPECT_CALL(netlink_, ChangeRoute(NetlinkInterface::Verb::kReplace,
                                    QboneConstants::kQboneRouteTableId,
                                    IpRangeEq(kIpRange), _, _, kIfindex, _))
      .Times(2)
      .WillRepeatedly(Return(true))
      .RetiresOnSaturation();

  EXPECT_CALL(netlink_,
              ChangeRoute(NetlinkInterface::Verb::kReplace,
                          QboneConstants::kQboneRouteTableId,
                          IpRangeEq(link_local_range_), _, _, kIfindex, _))
      .WillOnce(Return(true));

  EXPECT_TRUE(controller_.UpdateRoutes(kIpRange, {kIpRange, kIpRange}));
}

class DisabledTunDeviceControllerTest : public QuicTest {
 public:
  DisabledTunDeviceControllerTest()
      : controller_(kIfname, false, &netlink_),
        link_local_range_(*QboneConstants::TerminatorLocalAddressRange()) {}

  StrictMock<MockNetlink> netlink_;
  TunDeviceController controller_;

  IpRange link_local_range_;
};

TEST_F(DisabledTunDeviceControllerTest, UpdateRoutesIsNop) {
  EXPECT_THAT(controller_.UpdateRoutes(kIpRange, {}), Eq(true));
}

TEST_F(DisabledTunDeviceControllerTest, UpdateAddressIsNop) {
  EXPECT_THAT(controller_.UpdateAddress(kIpRange), Eq(true));
}

}  // namespace
}  // namespace quic::test
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_page_actions_module.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/extensions/extension_page_actions_module_constants.h"
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_error_utils.h"

namespace keys = extension_page_actions_module_constants;

bool PageActionFunction::SetPageActionEnabled(bool enable) {
  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
  const ListValue* args = static_cast<const ListValue*>(args_);

  std::string page_action_id;
  EXTENSION_FUNCTION_VALIDATE(args->GetString(0, &page_action_id));
  DictionaryValue* action;
  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &action));

  int tab_id;
  EXTENSION_FUNCTION_VALIDATE(action->GetInteger(keys::kTabIdKey, &tab_id));
  std::string url;
  EXTENSION_FUNCTION_VALIDATE(action->GetString(keys::kUrlKey, &url));

  // Find the TabContents that contains this tab id.
  TabContents* contents = NULL;
  ExtensionTabUtil::GetTabById(tab_id, profile(), NULL, NULL, &contents, NULL);
  if (!contents) {
    error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kNoTabError,
                                                     IntToString(tab_id));
    return false;
  }

  // Make sure the URL hasn't changed.
  if (url != contents->controller().GetActiveEntry()->url().spec()) {
    error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kUrlNotActiveError,
                                                     url);
    return false;
  }

  // Find our extension.
  Extension* extension = NULL;
  ExtensionsService* service = profile()->GetExtensionsService();
  extension = service->GetExtensionById(extension_id());
  if (!extension) {
    error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
                                                     extension_id());
    return false;
  }

  const PageAction* page_action = extension->GetPageAction(page_action_id);
  if (!page_action) {
    error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kNoPageActionError,
                                                     page_action_id);
    return false;
  }

  // Set visibility and broadcast notifications that the UI should be updated.
  contents->SetPageActionEnabled(page_action, enable);
  contents->NotifyNavigationStateChanged(TabContents::INVALIDATE_PAGE_ACTIONS);

  return true;
}

bool EnablePageActionFunction::RunImpl() {
  return SetPageActionEnabled(true);
}

bool DisablePageActionFunction::RunImpl() {
  return SetPageActionEnabled(false);
}
<commit_msg>Fix crash 15371<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_page_actions_module.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/extensions/extension_page_actions_module_constants.h"
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_error_utils.h"

namespace keys = extension_page_actions_module_constants;

bool PageActionFunction::SetPageActionEnabled(bool enable) {
  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
  const ListValue* args = static_cast<const ListValue*>(args_);

  std::string page_action_id;
  EXTENSION_FUNCTION_VALIDATE(args->GetString(0, &page_action_id));
  DictionaryValue* action;
  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &action));

  int tab_id;
  EXTENSION_FUNCTION_VALIDATE(action->GetInteger(keys::kTabIdKey, &tab_id));
  std::string url;
  EXTENSION_FUNCTION_VALIDATE(action->GetString(keys::kUrlKey, &url));

  // Find the TabContents that contains this tab id.
  TabContents* contents = NULL;
  ExtensionTabUtil::GetTabById(tab_id, profile(), NULL, NULL, &contents, NULL);
  if (!contents) {
    error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kNoTabError,
                                                     IntToString(tab_id));
    return false;
  }

  // Make sure the URL hasn't changed.
  NavigationEntry* entry = contents->controller().GetActiveEntry();
  if (!entry || url != entry->url().spec()) {
    error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kUrlNotActiveError,
                                                     url);
    return false;
  }

  // Find our extension.
  Extension* extension = NULL;
  ExtensionsService* service = profile()->GetExtensionsService();
  extension = service->GetExtensionById(extension_id());
  if (!extension) {
    error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
                                                     extension_id());
    return false;
  }

  const PageAction* page_action = extension->GetPageAction(page_action_id);
  if (!page_action) {
    error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kNoPageActionError,
                                                     page_action_id);
    return false;
  }

  // Set visibility and broadcast notifications that the UI should be updated.
  contents->SetPageActionEnabled(page_action, enable);
  contents->NotifyNavigationStateChanged(TabContents::INVALIDATE_PAGE_ACTIONS);

  return true;
}

bool EnablePageActionFunction::RunImpl() {
  return SetPageActionEnabled(true);
}

bool DisablePageActionFunction::RunImpl() {
  return SetPageActionEnabled(false);
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2015, Project OSRM contributors
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.

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

*/

#include "library/osrm.hpp"
#include "server/server.hpp"
#include "util/version.hpp"
#include "util/routed_options.hpp"
#include "util/simple_logger.hpp"

#ifdef __linux__
#include <sys/mman.h>
#endif

#include <cstdlib>

#include <signal.h>

#include <chrono>
#include <future>
#include <iostream>
#include <thread>

#ifdef _WIN32
boost::function0<void> console_ctrl_function;

BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
{
    switch (ctrl_type)
    {
    case CTRL_C_EVENT:
    case CTRL_BREAK_EVENT:
    case CTRL_CLOSE_EVENT:
    case CTRL_SHUTDOWN_EVENT:
        console_ctrl_function();
        return TRUE;
    default:
        return FALSE;
    }
}
#endif

int main(int argc, const char *argv[]) try
{
    LogPolicy::GetInstance().Unmute();

    bool trial_run = false;
    std::string ip_address;
    int ip_port, requested_thread_num;

    libosrm_config lib_config;
    // make the behaviour of routed backward compatible
    lib_config.use_shared_memory = false;

    const unsigned init_result = GenerateServerProgramOptions(
        argc, argv, lib_config.server_paths, ip_address, ip_port, requested_thread_num,
        lib_config.use_shared_memory, trial_run, lib_config.max_locations_distance_table,
        lib_config.max_locations_map_matching);
    if (init_result == INIT_OK_DO_NOT_START_ENGINE)
    {
        return 0;
    }
    if (init_result == INIT_FAILED)
    {
        return 1;
    }

#ifdef __linux__
    struct MemoryLocker final
    {
        explicit MemoryLocker(bool shouldLock_) : shouldLock(shouldLock_)
        {
            if (-1 == mlockall(MCL_CURRENT | MCL_FUTURE))
            {
                couldLock = false;
                SimpleLogger().Write(logWARNING) << "memory could not be locked to RAM";
            }
        }
        ~MemoryLocker()
        {
            if (couldLock)
                (void)munlockall();
        }
        bool shouldLock = false, couldLock = true;
    } memoryLocker(lib_config.use_shared_memory);
#endif
    SimpleLogger().Write() << "starting up engines, " << OSRM_VERSION;

    if (lib_config.use_shared_memory)
    {
        SimpleLogger().Write(logDEBUG) << "Loading from shared memory";
    }

    SimpleLogger().Write(logDEBUG) << "Threads:\t" << requested_thread_num;
    SimpleLogger().Write(logDEBUG) << "IP address:\t" << ip_address;
    SimpleLogger().Write(logDEBUG) << "IP port:\t" << ip_port;
#ifndef _WIN32
    int sig = 0;
    sigset_t new_mask;
    sigset_t old_mask;
    sigfillset(&new_mask);
    pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
#endif

    OSRM osrm_lib(lib_config);
    auto routing_server = Server::CreateServer(ip_address, ip_port, requested_thread_num);

    routing_server->GetRequestHandlerPtr().RegisterRoutingMachine(&osrm_lib);

    if (trial_run)
    {
        SimpleLogger().Write() << "trial run, quitting after successful initialization";
    }
    else
    {
        std::packaged_task<int()> server_task([&]() -> int
                                              {
                                                  routing_server->Run();
                                                  return 0;
                                              });
        auto future = server_task.get_future();
        std::thread server_thread(std::move(server_task));

#ifndef _WIN32
        sigset_t wait_mask;
        pthread_sigmask(SIG_SETMASK, &old_mask, nullptr);
        sigemptyset(&wait_mask);
        sigaddset(&wait_mask, SIGINT);
        sigaddset(&wait_mask, SIGQUIT);
        sigaddset(&wait_mask, SIGTERM);
        pthread_sigmask(SIG_BLOCK, &wait_mask, nullptr);
        SimpleLogger().Write() << "running and waiting for requests";
        sigwait(&wait_mask, &sig);
#else
        // Set console control handler to allow server to be stopped.
        console_ctrl_function = std::bind(&Server::Stop, routing_server);
        SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
        SimpleLogger().Write() << "running and waiting for requests";
        routing_server->Run();
#endif
        SimpleLogger().Write() << "initiating shutdown";
        routing_server->Stop();
        SimpleLogger().Write() << "stopping threads";

        auto status = future.wait_for(std::chrono::seconds(2));

        if (status == std::future_status::ready)
        {
            server_thread.join();
        }
        else
        {
            SimpleLogger().Write(logWARNING) << "Didn't exit within 2 seconds. Hard abort!";
            server_task.reset(); // just kill it
        }
    }

    SimpleLogger().Write() << "freeing objects";
    routing_server.reset();
    SimpleLogger().Write() << "shutdown completed";
}
catch (const std::exception &e)
{
    SimpleLogger().Write(logWARNING) << "exception: " << e.what();
    return 1;
}
<commit_msg>Check if memory locking should be done before locking unconditionally<commit_after>/*

Copyright (c) 2015, Project OSRM contributors
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.

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

*/

#include "library/osrm.hpp"
#include "server/server.hpp"
#include "util/version.hpp"
#include "util/routed_options.hpp"
#include "util/simple_logger.hpp"

#ifdef __linux__
#include <sys/mman.h>
#endif

#include <cstdlib>

#include <signal.h>

#include <chrono>
#include <future>
#include <iostream>
#include <thread>

#ifdef _WIN32
boost::function0<void> console_ctrl_function;

BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
{
    switch (ctrl_type)
    {
    case CTRL_C_EVENT:
    case CTRL_BREAK_EVENT:
    case CTRL_CLOSE_EVENT:
    case CTRL_SHUTDOWN_EVENT:
        console_ctrl_function();
        return TRUE;
    default:
        return FALSE;
    }
}
#endif

int main(int argc, const char *argv[]) try
{
    LogPolicy::GetInstance().Unmute();

    bool trial_run = false;
    std::string ip_address;
    int ip_port, requested_thread_num;

    libosrm_config lib_config;
    // make the behaviour of routed backward compatible
    lib_config.use_shared_memory = false;

    const unsigned init_result = GenerateServerProgramOptions(
        argc, argv, lib_config.server_paths, ip_address, ip_port, requested_thread_num,
        lib_config.use_shared_memory, trial_run, lib_config.max_locations_distance_table,
        lib_config.max_locations_map_matching);
    if (init_result == INIT_OK_DO_NOT_START_ENGINE)
    {
        return 0;
    }
    if (init_result == INIT_FAILED)
    {
        return 1;
    }

#ifdef __linux__
    struct MemoryLocker final
    {
        explicit MemoryLocker(bool shouldLock_) : shouldLock(shouldLock_)
        {
            if (shouldLock && -1 == mlockall(MCL_CURRENT | MCL_FUTURE))
            {
                couldLock = false;
                SimpleLogger().Write(logWARNING) << "memory could not be locked to RAM";
            }
        }
        ~MemoryLocker()
        {
            if (shouldLock && couldLock)
                (void)munlockall();
        }
        bool shouldLock = false, couldLock = true;
    } memoryLocker(lib_config.use_shared_memory);
#endif
    SimpleLogger().Write() << "starting up engines, " << OSRM_VERSION;

    if (lib_config.use_shared_memory)
    {
        SimpleLogger().Write(logDEBUG) << "Loading from shared memory";
    }

    SimpleLogger().Write(logDEBUG) << "Threads:\t" << requested_thread_num;
    SimpleLogger().Write(logDEBUG) << "IP address:\t" << ip_address;
    SimpleLogger().Write(logDEBUG) << "IP port:\t" << ip_port;
#ifndef _WIN32
    int sig = 0;
    sigset_t new_mask;
    sigset_t old_mask;
    sigfillset(&new_mask);
    pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
#endif

    OSRM osrm_lib(lib_config);
    auto routing_server = Server::CreateServer(ip_address, ip_port, requested_thread_num);

    routing_server->GetRequestHandlerPtr().RegisterRoutingMachine(&osrm_lib);

    if (trial_run)
    {
        SimpleLogger().Write() << "trial run, quitting after successful initialization";
    }
    else
    {
        std::packaged_task<int()> server_task([&]() -> int
                                              {
                                                  routing_server->Run();
                                                  return 0;
                                              });
        auto future = server_task.get_future();
        std::thread server_thread(std::move(server_task));

#ifndef _WIN32
        sigset_t wait_mask;
        pthread_sigmask(SIG_SETMASK, &old_mask, nullptr);
        sigemptyset(&wait_mask);
        sigaddset(&wait_mask, SIGINT);
        sigaddset(&wait_mask, SIGQUIT);
        sigaddset(&wait_mask, SIGTERM);
        pthread_sigmask(SIG_BLOCK, &wait_mask, nullptr);
        SimpleLogger().Write() << "running and waiting for requests";
        sigwait(&wait_mask, &sig);
#else
        // Set console control handler to allow server to be stopped.
        console_ctrl_function = std::bind(&Server::Stop, routing_server);
        SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
        SimpleLogger().Write() << "running and waiting for requests";
        routing_server->Run();
#endif
        SimpleLogger().Write() << "initiating shutdown";
        routing_server->Stop();
        SimpleLogger().Write() << "stopping threads";

        auto status = future.wait_for(std::chrono::seconds(2));

        if (status == std::future_status::ready)
        {
            server_thread.join();
        }
        else
        {
            SimpleLogger().Write(logWARNING) << "Didn't exit within 2 seconds. Hard abort!";
            server_task.reset(); // just kill it
        }
    }

    SimpleLogger().Write() << "freeing objects";
    routing_server.reset();
    SimpleLogger().Write() << "shutdown completed";
}
catch (const std::exception &e)
{
    SimpleLogger().Write(logWARNING) << "exception: " << e.what();
    return 1;
}
<|endoftext|>