<commit_before>/*
 * Copyright (C) 2013
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cmath>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <CLData.hpp>
#include <utils.hpp>
#include <Folding.hpp>
#include <Timer.hpp>
using isa::utils::ArgumentList;
using isa::utils::toStringValue;
using isa::utils::Timer;
using AstroData::Observation;
using isa::OpenCL::initializeOpenCL;
using isa::OpenCL::CLData;
using PulsarSearch::Folding;

typedef float dataType;
const string typeName("float");
const unsigned int maxThreadsPerBlock = 1024;
const unsigned int maxThreadsMultiplier = 512;
const unsigned int maxItemsPerThread = 256;
const unsigned int maxItemsMultiplier = 256;
const unsigned int padding = 32;

// Common parameters
const unsigned int nrBeams = 1;
const unsigned int nrStations = 64;
// LOFAR
/*const float minFreq = 138.965f;
const float channelBandwidth = 0.195f;
const unsigned int nrSamplesPerSecond = 200000;
const unsigned int nrChannels = 32;*/
// Apertif
const float minFreq = 1425.0f;
const float channelBandwidth = 0.2929f;
const unsigned int nrSamplesPerSecond = 20000;
const unsigned int nrChannels = 1024;
// Periods
const unsigned int nrBins = 256;

int main(int argc, char * argv[]) {
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	Observation< dataType > observation("FoldingTuning", typeName);
	CLData< dataType > * dedispersedData = new CLData< dataType >("DedispersedData", true);
	CLData< dataType > * foldedData = new CLData<dataType >("FoldedData", true);
	CLData< unsigned int > * counterData = new CLData< unsigned int >("CounterData", true);

	try {
		ArgumentList args(argc, argv);
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
	} catch ( exception & err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Setup of the observation
	observation.setPadding(padding);
	observation.setNrSamplesPerSecond(nrSamplesPerSecond);
	observation.setFirstPeriod(nrBins);
	observation.setPeriodStep(nrBins);
	observation.setNrBins(nrBins);

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	cout << fixed << endl;
	cout << "# nrDMs nrPeriods nrDMsPerBlock nrPeriodsPerBlock nrBinsPerBlock nrDMsPerThread nrPeriodsPerThread nrBinsPerThread GFLOP/s err time err" << endl << endl;

	for ( unsigned int nrDMs = 2; nrDMs <= 4096; nrDMs *= 2 )	{
		observation.setNrDMs(nrDMs);

		for ( unsigned int nrPeriods = 2; nrPeriods <= 1024; nrPeriods *= 2 ) {
			observation.setNrPeriods(nrPeriods);

			// Allocate memory
			dedispersedData->allocateHostData(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
			foldedData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
			foldedData->blankHostData();
			counterData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
			counterData->blankHostData();

			dedispersedData->setCLContext(clContext);
			dedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
			foldedData->setCLContext(clContext);
			foldedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
			counterData->setCLContext(clContext);
			counterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));

			try {
				dedispersedData->allocateDeviceData();
				foldedData->allocateDeviceData();
				foldedData->copyHostToDevice();
				counterData->allocateDeviceData();
				counterData->copyHostToDevice();
			} catch ( OpenCLError err ) {
				cerr << err.what() << endl;
			}

			// Find the parameters
			vector< unsigned int > DMsPerBlock;
			for ( unsigned int DMs = 2; DMs <= maxThreadsPerBlock; DMs++ ) {
				if ( (observation.getNrDMs() % DMs) == 0 ) {
					DMsPerBlock.push_back(DMs);
				}
			}

			for ( vector< unsigned int >::iterator DMs = DMsPerBlock.begin(); DMs != DMsPerBlock.end(); DMs++ ) {
				for (unsigned int periodsPerBlock = 1; periodsPerBlock <= maxThreadsMultiplier; periodsPerBlock++ ) {
					if ( (*DMs * periodsPerBlock) > maxThreadsPerBlock ) {
						break;
					} else if ( (observation.getNrPeriods() % periodsPerBlock) != 0 ) {
						continue;
					}

					for ( unsigned int binsPerBlock = 1; binsPerBlock <= maxThreadsMultiplier; binsPerBlock++ ) {
						if ( (*DMs * periodsPerBlock * binsPerBlock) > maxThreadsPerBlock ) {
							break;
						} else if ( (observation.getNrBins() % binsPerBlock) != 0 ) {
							continue;
						}

						for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItemsPerThread; DMsPerThread++ ) {
							if ( (observation.getNrDMs() % (*DMs * DMsPerThread)) != 0 ) {
								continue;
							}

							for ( unsigned int periodsPerThread = 1; periodsPerThread <= maxItemsPerThread; periodsPerThread++ ) {
								if ( (DMsPerThread * periodsPerThread) > maxItemsPerThread ) {
									break;
								} else if ( (observation.getNrPeriods() % (periodsPerBlock * periodsPerThread)) != 0 ) {
									continue;
								}

								for ( unsigned int binsPerThread = 1; binsPerThread <= maxItemsPerThread; binsPerThread++ ) {
									if ( (DMsPerThread * periodsPerThread * binsPerThread) > maxItemsPerThread ) {
										break;
									} else if ( (observation.getNrBins() % (binsPerBlock * binsPerThread))) != 0 ) {
										continue;
									}

									double Acur = 0.0;
									double Aold = 0.0;
									double Vcur = 0.0;
									double Vold = 0.0;

									try {
										// Generate kernel
										Folding< dataType > clFold("clFold", typeName);
										clFold.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
										clFold.setObservation(&observation);
										clFold.setNrDMsPerBlock(*DMs);
										clFold.setNrPeriodsPerBlock(periodsPerBlock);
										clFold.setNrBinsPerBlock(binsPerBlock);
										clFold.setNrDMsPerThread(DMsPerThread);
										clFold.setNrPeriodsPerThread(periodsPerThread);
										clFold.setNrBinsPerThread(binsPerThread);
										clFold.generateCode();

										clFold(dedispersedData, foldedData, counterData);
										(clFold.getTimer()).reset();
										for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
											clFold(dedispersedData, foldedData, counterData);

											if ( iteration == 0 ) {
												Acur = clFold.getGFLOP() / clFold.getTimer().getLastRunTime();
											} else {
												Aold = Acur;
												Vold = Vcur;

												Acur = Aold + (((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Aold) / (iteration + 1));
												Vcur = Vold + (((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Aold) * ((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Acur));
											}
										}
										Vcur = sqrt(Vcur / nrIterations);

										cout << nrDMs << " " << nrPeriods << " " << *DMs << " " << periodsPerBlock << " " << binsPerBlock << " " << DMsPerThread << " " << periodsPerThread << " " << binsPerThread << " " << setprecision(3) << Acur << " " << Vcur << " " << setprecision(6) << clFold.getTimer().getAverageTime() << " " << clFold.getTimer().getStdDev() << endl;
									} catch ( OpenCLError err ) {
										cerr << err.what() << endl;
										continue;
									}
								}
							}
						}
					}
				}
			}

			cout << endl << endl;
		}
	}

	cout << endl;

	return 0;
}
<commit_msg>Typo, Fixed.<commit_after>/*
 * Copyright (C) 2013
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cmath>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <CLData.hpp>
#include <utils.hpp>
#include <Folding.hpp>
#include <Timer.hpp>
using isa::utils::ArgumentList;
using isa::utils::toStringValue;
using isa::utils::Timer;
using AstroData::Observation;
using isa::OpenCL::initializeOpenCL;
using isa::OpenCL::CLData;
using PulsarSearch::Folding;

typedef float dataType;
const string typeName("float");
const unsigned int maxThreadsPerBlock = 1024;
const unsigned int maxThreadsMultiplier = 512;
const unsigned int maxItemsPerThread = 256;
const unsigned int maxItemsMultiplier = 256;
const unsigned int padding = 32;

// Common parameters
const unsigned int nrBeams = 1;
const unsigned int nrStations = 64;
// LOFAR
/*const float minFreq = 138.965f;
const float channelBandwidth = 0.195f;
const unsigned int nrSamplesPerSecond = 200000;
const unsigned int nrChannels = 32;*/
// Apertif
const float minFreq = 1425.0f;
const float channelBandwidth = 0.2929f;
const unsigned int nrSamplesPerSecond = 20000;
const unsigned int nrChannels = 1024;
// Periods
const unsigned int nrBins = 256;

int main(int argc, char * argv[]) {
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	Observation< dataType > observation("FoldingTuning", typeName);
	CLData< dataType > * dedispersedData = new CLData< dataType >("DedispersedData", true);
	CLData< dataType > * foldedData = new CLData<dataType >("FoldedData", true);
	CLData< unsigned int > * counterData = new CLData< unsigned int >("CounterData", true);

	try {
		ArgumentList args(argc, argv);
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
	} catch ( exception & err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Setup of the observation
	observation.setPadding(padding);
	observation.setNrSamplesPerSecond(nrSamplesPerSecond);
	observation.setFirstPeriod(nrBins);
	observation.setPeriodStep(nrBins);
	observation.setNrBins(nrBins);

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	cout << fixed << endl;
	cout << "# nrDMs nrPeriods nrDMsPerBlock nrPeriodsPerBlock nrBinsPerBlock nrDMsPerThread nrPeriodsPerThread nrBinsPerThread GFLOP/s err time err" << endl << endl;

	for ( unsigned int nrDMs = 2; nrDMs <= 4096; nrDMs *= 2 )	{
		observation.setNrDMs(nrDMs);

		for ( unsigned int nrPeriods = 2; nrPeriods <= 1024; nrPeriods *= 2 ) {
			observation.setNrPeriods(nrPeriods);

			// Allocate memory
			dedispersedData->allocateHostData(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
			foldedData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
			foldedData->blankHostData();
			counterData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
			counterData->blankHostData();

			dedispersedData->setCLContext(clContext);
			dedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
			foldedData->setCLContext(clContext);
			foldedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
			counterData->setCLContext(clContext);
			counterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));

			try {
				dedispersedData->allocateDeviceData();
				foldedData->allocateDeviceData();
				foldedData->copyHostToDevice();
				counterData->allocateDeviceData();
				counterData->copyHostToDevice();
			} catch ( OpenCLError err ) {
				cerr << err.what() << endl;
			}

			// Find the parameters
			vector< unsigned int > DMsPerBlock;
			for ( unsigned int DMs = 2; DMs <= maxThreadsPerBlock; DMs++ ) {
				if ( (observation.getNrDMs() % DMs) == 0 ) {
					DMsPerBlock.push_back(DMs);
				}
			}

			for ( vector< unsigned int >::iterator DMs = DMsPerBlock.begin(); DMs != DMsPerBlock.end(); DMs++ ) {
				for (unsigned int periodsPerBlock = 1; periodsPerBlock <= maxThreadsMultiplier; periodsPerBlock++ ) {
					if ( (*DMs * periodsPerBlock) > maxThreadsPerBlock ) {
						break;
					} else if ( (observation.getNrPeriods() % periodsPerBlock) != 0 ) {
						continue;
					}

					for ( unsigned int binsPerBlock = 1; binsPerBlock <= maxThreadsMultiplier; binsPerBlock++ ) {
						if ( (*DMs * periodsPerBlock * binsPerBlock) > maxThreadsPerBlock ) {
							break;
						} else if ( (observation.getNrBins() % binsPerBlock) != 0 ) {
							continue;
						}

						for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItemsPerThread; DMsPerThread++ ) {
							if ( (observation.getNrDMs() % (*DMs * DMsPerThread)) != 0 ) {
								continue;
							}

							for ( unsigned int periodsPerThread = 1; periodsPerThread <= maxItemsPerThread; periodsPerThread++ ) {
								if ( (DMsPerThread * periodsPerThread) > maxItemsPerThread ) {
									break;
								} else if ( (observation.getNrPeriods() % (periodsPerBlock * periodsPerThread)) != 0 ) {
									continue;
								}

								for ( unsigned int binsPerThread = 1; binsPerThread <= maxItemsPerThread; binsPerThread++ ) {
									if ( (DMsPerThread * periodsPerThread * binsPerThread) > maxItemsPerThread ) {
										break;
									} else if ( (observation.getNrBins() % (binsPerBlock * binsPerThread)) != 0 ) {
										continue;
									}

									double Acur = 0.0;
									double Aold = 0.0;
									double Vcur = 0.0;
									double Vold = 0.0;

									try {
										// Generate kernel
										Folding< dataType > clFold("clFold", typeName);
										clFold.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
										clFold.setObservation(&observation);
										clFold.setNrDMsPerBlock(*DMs);
										clFold.setNrPeriodsPerBlock(periodsPerBlock);
										clFold.setNrBinsPerBlock(binsPerBlock);
										clFold.setNrDMsPerThread(DMsPerThread);
										clFold.setNrPeriodsPerThread(periodsPerThread);
										clFold.setNrBinsPerThread(binsPerThread);
										clFold.generateCode();

										clFold(dedispersedData, foldedData, counterData);
										(clFold.getTimer()).reset();
										for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
											clFold(dedispersedData, foldedData, counterData);

											if ( iteration == 0 ) {
												Acur = clFold.getGFLOP() / clFold.getTimer().getLastRunTime();
											} else {
												Aold = Acur;
												Vold = Vcur;

												Acur = Aold + (((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Aold) / (iteration + 1));
												Vcur = Vold + (((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Aold) * ((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Acur));
											}
										}
										Vcur = sqrt(Vcur / nrIterations);

										cout << nrDMs << " " << nrPeriods << " " << *DMs << " " << periodsPerBlock << " " << binsPerBlock << " " << DMsPerThread << " " << periodsPerThread << " " << binsPerThread << " " << setprecision(3) << Acur << " " << Vcur << " " << setprecision(6) << clFold.getTimer().getAverageTime() << " " << clFold.getTimer().getStdDev() << endl;
									} catch ( OpenCLError err ) {
										cerr << err.what() << endl;
										continue;
									}
								}
							}
						}
					}
				}
			}

			cout << endl << endl;
		}
	}

	cout << endl;

	return 0;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "video_engine/test/auto_test/primitives/choice_helpers.h"

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <algorithm>

namespace webrtc {

ChoiceBuilder::ChoiceBuilder(const std::string& title, const Choices& choices)
    : choices_(choices),
      input_helper_(TypedInput(title)) {
  input_helper_.WithInputValidator(
      new IntegerWithinRangeValidator(1, choices.size()));
  input_helper_.WithAdditionalInfo(MakeHumanReadableOptions());
}

int ChoiceBuilder::Choose() {
  std::string input = input_helper_.AskForInput();
  return atoi(input.c_str());
}

ChoiceBuilder& ChoiceBuilder::WithDefault(const std::string& default_choice) {
  Choices::const_iterator iterator = std::find(
      choices_.begin(), choices_.end(), default_choice);
  assert(iterator != choices_.end() && "No such choice.");

  // Store the value as the choice number, e.g. its index + 1.
  int choice_index = (iterator - choices_.begin()) + 1;
  char number[16];
  sprintf(number, "%d", choice_index);

  input_helper_.WithDefault(number);
  return *this;
}

ChoiceBuilder& ChoiceBuilder::WithInputSource(FILE* input_source) {
  input_helper_.WithInputSource(input_source);
  return *this;
}

std::string ChoiceBuilder::MakeHumanReadableOptions() {
  std::string result = "";
  Choices::const_iterator iterator = choices_.begin();
  for (int number = 1; iterator != choices_.end(); ++iterator, ++number) {
    char buffer[128];
    sprintf(buffer, "\n  %d. %s", number, (*iterator).c_str());
    result += buffer;
  }
  return result;
}

Choices SplitChoices(const std::string& raw_choices) {
  return Split(raw_choices, "\n");
}

ChoiceBuilder FromChoices(
    const std::string& title, const std::string& raw_choices) {
  return ChoiceBuilder(title, SplitChoices(raw_choices));
}

}  // namespace webrtc
<commit_msg>Fix for buffer overflow, WebRTC issue 1196 Review URL: https://webrtc-codereview.appspot.com/998004<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "video_engine/test/auto_test/primitives/choice_helpers.h"

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <sstream>

namespace webrtc {

ChoiceBuilder::ChoiceBuilder(const std::string& title, const Choices& choices)
    : choices_(choices),
      input_helper_(TypedInput(title)) {
  input_helper_.WithInputValidator(
      new IntegerWithinRangeValidator(1, choices.size()));
  input_helper_.WithAdditionalInfo(MakeHumanReadableOptions());
}

int ChoiceBuilder::Choose() {
  std::string input = input_helper_.AskForInput();
  return atoi(input.c_str());
}

ChoiceBuilder& ChoiceBuilder::WithDefault(const std::string& default_choice) {
  Choices::const_iterator iterator = std::find(
      choices_.begin(), choices_.end(), default_choice);
  assert(iterator != choices_.end() && "No such choice.");

  // Store the value as the choice number, e.g. its index + 1.
  int choice_index = (iterator - choices_.begin()) + 1;
  char number[16];
  sprintf(number, "%d", choice_index);

  input_helper_.WithDefault(number);
  return *this;
}

ChoiceBuilder& ChoiceBuilder::WithInputSource(FILE* input_source) {
  input_helper_.WithInputSource(input_source);
  return *this;
}

std::string ChoiceBuilder::MakeHumanReadableOptions() {
  std::string result = "";
  Choices::const_iterator iterator = choices_.begin();
  for (int number = 1; iterator != choices_.end(); ++iterator, ++number) {
    std::ostringstream os;
    os << "\n  " << number << ". " << (*iterator).c_str();
    result += os.str();
  }
  return result;
}

Choices SplitChoices(const std::string& raw_choices) {
  return Split(raw_choices, "\n");
}

ChoiceBuilder FromChoices(
    const std::string& title, const std::string& raw_choices) {
  return ChoiceBuilder(title, SplitChoices(raw_choices));
}

}  // namespace webrtc
<|endoftext|>


<commit_before>// ==Montelight==
// Tegan Brennan, Stephen Merity, Taiyo Wilson
#include <cmath>
#include <string>
#include <fstream>

#define EPSILON 0.01f

using namespace std;

struct Vector {
  double x, y, z;
  //
  Vector(const Vector &o) : x(o.x), y(o.y), z(o.z) {}
  Vector(double x_=0, double y_=0, double z_=0) : x(x_), y(y_), z(z_) {}
  inline Vector operator+(const Vector &o) const {
    return Vector(x + o.x, y + o.y, z + o.z);
  }
  inline Vector operator-(const Vector &o) const {
    return Vector(x - o.x, y - o.y, z - o.z);
  }
  inline Vector operator*(double o) const {
    return Vector(x * o, y * o, z * o);
  }
  inline double dot(const Vector &o) const {
    return x * o.x + y * o.y + z * o.z;
  }
  inline Vector &norm(){
    return *this = *this * (1 / sqrt(x * x + y * y + z * z));
  }
  inline Vector cross(Vector &o){
    return Vector(y * o.z - z * o.y, z * o.x - x * o.z, x * o.y - y * o.x);
  }
};

struct Ray {
  Vector origin, direction;
  Ray(const Vector &o_, const Vector &d_) : origin(o_), direction(d_) {}
};

struct Image {
  unsigned int width, height;
  Vector *pixels;
  //
  Image(unsigned int w, unsigned int h) : width(w), height(h) {
    pixels = new Vector[width * height];
  }
  void setPixel(unsigned int x, unsigned int y, const Vector &v) {
    pixels[(height - y) * width + x] = v;
  }
  void save(std::string filePrefix) {
    std::string filename = filePrefix + ".ppm";
    std::ofstream f;
    f.open(filename.c_str(), std::ofstream::out);
    // PPM header: P3 => RGB, width, height, and max RGB value
    f << "P3 " << width << " " << height << " " << 255 << std::endl;
    // For each pixel, write the space separated RGB values
    for (int i=0; i < width * height; i++) {
      unsigned int r = pixels[i].x * 255, g = pixels[i].y * 255, b = pixels[i].z * 255;
      f << r << " " << g << " " << b << std::endl;
    }
  }
  ~Image() {
    delete[] pixels;
  }
};

struct Shape {
  Vector color;
  //
  Shape(const Vector color_) : color(color_) {}
  virtual double intersects(const Ray &r) const { return 0; }
};

struct Sphere : Shape {
  Vector center, color;
  double radius;
  //
  Sphere(const Vector center_, double radius_, const Vector color_) :
    Shape(color_), center(center_), radius(radius_) {}
  double intersects(const Ray &r) const {
    // Find if, and at what distance, the ray intersects with this object
    // Equation follows from solving quadratic equation of (r - c) ^ 2
    // http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
    Vector offset = r.origin - center;
    double a = r.direction.dot(r.direction);
    double b = 2 * offset.dot(r.direction);
    double c = offset.dot(offset) - radius * radius;
    // Find discriminant for use in quadratic equation (b^2 - 4ac)
    double disc = b * b - 4 * a * c;
    // If the discriminant is negative, there are no real roots
    // (ray misses sphere)
    if (disc < 0) {
      return 0;
    }
    // The smallest positive root is the closest intersection point
    disc = sqrt(disc);
    double t = - b - disc;
    if (t > EPSILON) {
      return t;
    }
    t = - b + disc;
    if (t > EPSILON) {
      return t;
    }
    return 0;
  }
};

int main(int argc, const char *argv[]) {
  // Initialize the image
  int w = 256, h = 256;
  Image img(w, h);
  // Set up the scene
  // Cornell box inspired: http://graphics.ucsd.edu/~henrik/images/cbox.html
  Shape *scene[] = {//Scene: radius, position, emission, color, material
    new Sphere(Vector(1e5+1,40.8,81.6), 1e5f, Vector(.75,.25,.25)),//Left
    new Sphere(Vector(-1e5+99,40.8,81.6), 1e5f, Vector(.25,.25,.75)),//Rght
    new Sphere(Vector(50,40.8, 1e5), 1e5f, Vector(.75,.75,.75)),//Back
    new Sphere(Vector(50,40.8,-1e5+170), 1e5f, Vector()),//Frnt
    new Sphere(Vector(50, 1e5, 81.6), 1e5f, Vector(.75,.75,.75)),//Botm
    new Sphere(Vector(50,-1e5+81.6,81.6), 1e5f, Vector(.75,.75,.75)),//Top
    new Sphere(Vector(27,16.5,47), 16.5f, Vector(1,1,1) * 0.9),//Mirr
    new Sphere(Vector(73,16.5,78), 16.5f, Vector(1,1,1) * 0.9),//Glas
    new Sphere(Vector(50,681.6-.27,81.6), 600, Vector(1,1,1)) //Light
  };
  // Set up the camera
  Ray camera = Ray(Vector(50, 52, 295.6), Vector(0, -0.042612, -1).norm());
  // Upright camera with field of view angle set by 0.5135
  Vector cx = Vector((w * 0.5135) / h, 0, 0);
  // Cross product gets the vector perpendicular to cx and the "gaze" direction
  Vector cy = (cx.cross(camera.direction)).norm() * 0.5135;
  // Take a set number of samples per pixel
  for (int samples = 0; samples < 1; ++samples) {
    // For each pixel, sample a ray in that direction
    for (int y = 0; y < h; ++y) {
      for (int x = 0; x < w; ++x) {
        // Calculate the direction of the camera ray
        Vector d = (cx * ((x / float(w)) - 0.5)) + (cy * ((y / float(h)) - 0.5)) + camera.direction;
        Ray ray = Ray(camera.origin + d * 140, d.norm());
        // Check for intersection with objects in scene
        Vector color;
        double closest = 1e20f;
        for (auto obj : scene) {
          double hit = obj->intersects(ray);
          if (hit > 0 && hit < closest) {
            color = obj->color;
            closest = hit;
          }
        }
        // Add result of sample to image
        img.setPixel(x, y, color);
      }
    }
  }
  // Save the resulting raytraced image
  img.save("render");
  return 0;
}
<commit_msg>Tracer now handles scene + intersections and we have shadow ray testing<commit_after>// ==Montelight==
// Tegan Brennan, Stephen Merity, Taiyo Wilson
#include <cmath>
#include <string>
#include <iostream>
#include <fstream>
#include <vector>

#define EPSILON 0.1f

using namespace std;

struct Vector {
  double x, y, z;
  //
  Vector(const Vector &o) : x(o.x), y(o.y), z(o.z) {}
  Vector(double x_=0, double y_=0, double z_=0) : x(x_), y(y_), z(z_) {}
  inline Vector operator+(const Vector &o) const {
    return Vector(x + o.x, y + o.y, z + o.z);
  }
  inline Vector operator-(const Vector &o) const {
    return Vector(x - o.x, y - o.y, z - o.z);
  }
  inline Vector operator*(const Vector &o) const {
    return Vector(x * o.x, y * o.y, z * o.z);
  }
  inline Vector operator*(double o) const {
    return Vector(x * o, y * o, z * o);
  }
  inline double dot(const Vector &o) const {
    return x * o.x + y * o.y + z * o.z;
  }
  inline Vector &norm(){
    return *this = *this * (1 / sqrt(x * x + y * y + z * z));
  }
  inline Vector cross(Vector &o){
    return Vector(y * o.z - z * o.y, z * o.x - x * o.z, x * o.y - y * o.x);
  }
  inline double max() {
    return fmax(x, fmax(y, z));
  }
};

struct Ray {
  Vector origin, direction;
  Ray(const Vector &o_, const Vector &d_) : origin(o_), direction(d_) {}
};

struct Image {
  unsigned int width, height;
  Vector *pixels;
  //
  Image(unsigned int w, unsigned int h) : width(w), height(h) {
    pixels = new Vector[width * height];
  }
  void setPixel(unsigned int x, unsigned int y, const Vector &v) {
    pixels[(height - y) * width + x] = v;
  }
  void save(std::string filePrefix) {
    std::string filename = filePrefix + ".ppm";
    std::ofstream f;
    f.open(filename.c_str(), std::ofstream::out);
    // PPM header: P3 => RGB, width, height, and max RGB value
    f << "P3 " << width << " " << height << " " << 255 << std::endl;
    // For each pixel, write the space separated RGB values
    for (int i=0; i < width * height; i++) {
      unsigned int r = pixels[i].x * 255, g = pixels[i].y * 255, b = pixels[i].z * 255;
      f << r << " " << g << " " << b << std::endl;
    }
  }
  ~Image() {
    delete[] pixels;
  }
};

struct Shape {
  Vector color, emit;
  //
  Shape(const Vector color_, const Vector emit_) : color(color_), emit(emit_) {}
  virtual double intersects(const Ray &r) const { return 0; }
  virtual Vector randomPoint() const { return Vector(); }
};

struct Sphere : Shape {
  Vector center;
  double radius;
  //
  Sphere(const Vector center_, double radius_, const Vector color_, const Vector emit_) :
    Shape(color_, emit_), center(center_), radius(radius_) {}
  double intersects(const Ray &r) const {
    // Find if, and at what distance, the ray intersects with this object
    // Equation follows from solving quadratic equation of (r - c) ^ 2
    // http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
    Vector offset = r.origin - center;
    double a = r.direction.dot(r.direction);
    double b = 2 * offset.dot(r.direction);
    double c = offset.dot(offset) - radius * radius;
    // Find discriminant for use in quadratic equation (b^2 - 4ac)
    double disc = b * b - 4 * a * c;
    // If the discriminant is negative, there are no real roots
    // (ray misses sphere)
    if (disc < 0) {
      return 0;
    }
    // The smallest positive root is the closest intersection point
    disc = sqrt(disc);
    double t = - b - disc;
    if (t > EPSILON) {
      return t / 2;
    }
    t = - b + disc;
    if (t > EPSILON) {
      return t / 2;
    }
    return 0;
  }
  Vector randomPoint() const {
    return center;
  }
};

struct Tracer {
  std::vector<Shape *> scene;
  //
  Tracer(const std::vector<Shape *> &scene_) : scene(scene_) {}
  std::pair<Shape *, double> getIntersection(const Ray &r) const {
    Shape *hitObj = NULL;
    double closest = 1e20f;
    for (Shape *obj : scene) {
      double distToHit = obj->intersects(r);
      if (distToHit > 0 && distToHit < closest) {
        hitObj = obj;
        closest = distToHit;
      }
    }
    return std::make_pair(hitObj, closest);
  }
  Vector getRadiance(const Ray &r, int depth) {
    // Work out what (if anything) was hit
    auto result = getIntersection(r);
    if (!result.first) {
      return Vector();
    }
    Vector hit = r.origin + r.direction * result.second;
    // Work out the color
    Vector color;
    for (Shape *light : scene) {
      // Skip any objects that don't emit light
      if (light->emit.max() == 0) {
        continue;
      }
      Vector lightDirection = (light->randomPoint() - hit).norm();
      Ray rayToLight = Ray(hit, lightDirection);
      auto lightHit = getIntersection(rayToLight);
      if (light == lightHit.first) {
        color = light->emit * result.first->color;
      }
    }
    return result.first->emit + color;
  }
};

int main(int argc, const char *argv[]) {
  // Initialize the image
  int w = 256, h = 256;
  Image img(w, h);
  // Set up the scene
  // Cornell box inspired: http://graphics.ucsd.edu/~henrik/images/cbox.html
  std::vector<Shape *> scene = {//Scene: radius, position, emission, color, material
    new Sphere(Vector(1e5+1,40.8,81.6), 1e5f, Vector(.75,.25,.25), Vector()),//Left
    new Sphere(Vector(-1e5+99,40.8,81.6), 1e5f, Vector(.25,.25,.75), Vector()),//Rght
    new Sphere(Vector(50,40.8, 1e5), 1e5f, Vector(.75,.75,.75), Vector()),//Back
    new Sphere(Vector(50,40.8,-1e5+170), 1e5f, Vector(), Vector()),//Frnt
    new Sphere(Vector(50, 1e5, 81.6), 1e5f, Vector(.75,.75,.75), Vector()),//Botm
    new Sphere(Vector(50,-1e5+81.6,81.6), 1e5f, Vector(.75,.75,.75), Vector()),//Top
    new Sphere(Vector(27,16.5,47), 16.5f, Vector(1,1,1) * 0.9, Vector()),//Mirr
    new Sphere(Vector(73,16.5,78), 16.5f, Vector(1,1,1) * 0.9, Vector(0.4, 0.4, 0.4)),//Glas
    //new Sphere(Vector(50,681.6-.27,81.6), 600, Vector(1,1,1)) //Light
    new Sphere(Vector(50,65.1,81.6), 1.5, Vector(1,1,1), Vector(1,1,1)) //Light
  };
  Tracer tracer = Tracer(scene);
  // Set up the camera
  Ray camera = Ray(Vector(50, 52, 295.6), Vector(0, -0.042612, -1).norm());
  // Upright camera with field of view angle set by 0.5135
  Vector cx = Vector((w * 0.5135) / h, 0, 0);
  // Cross product gets the vector perpendicular to cx and the "gaze" direction
  Vector cy = (cx.cross(camera.direction)).norm() * 0.5135;
  // Take a set number of samples per pixel
  for (int samples = 0; samples < 1; ++samples) {
    // For each pixel, sample a ray in that direction
    for (int y = 0; y < h; ++y) {
      for (int x = 0; x < w; ++x) {
        // Calculate the direction of the camera ray
        Vector d = (cx * ((x / float(w)) - 0.5)) + (cy * ((y / float(h)) - 0.5)) + camera.direction;
        Ray ray = Ray(camera.origin + d * 140, d.norm());
        Vector color = tracer.getRadiance(ray, 0);
        // Add result of sample to image
        img.setPixel(x, y, color);
      }
    }
  }
  // Save the resulting raytraced image
  img.save("render");
  return 0;
}
<|endoftext|>


<commit_before>// Copyright (C) 2010-2013 Joshua Boyce.
// See the file COPYING for copying permission.

#include <memory>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>

#include <hadesmem/detail/warning_disable_prefix.hpp>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <hadesmem/detail/warning_disable_suffix.hpp>

#include <windows.h>

#include <hadesmem/call.hpp>
#include <hadesmem/error.hpp>
#include <hadesmem/config.hpp>
#include <hadesmem/module.hpp>
#include <hadesmem/process.hpp>
#include <hadesmem/injector.hpp>
#include <hadesmem/detail/self_path.hpp>
#include <hadesmem/detail/initialize.hpp>

// TODO: Add support for for passing args, work dir, etc to CreateAndInject.
// e.g. exe-arg0, exe-arg1, exe-arg2, ..., exe-argN?

namespace
{

std::wstring PtrToString(void const* const ptr)
{
  std::wostringstream str;
  str.imbue(std::locale::classic());
  str << std::hex << reinterpret_cast<DWORD_PTR>(ptr);
  return str.str();
}

}

int main(int argc, char* /*argv*/[])
{
  try
  {
    hadesmem::detail::InitializeAll();

    std::cout << "HadesMem Injector\n";

    boost::program_options::options_description opts_desc(
      "General options");
    opts_desc.add_options()
      ("help", "produce help message")
      ("pid", boost::program_options::value<DWORD>(), "process id")
      ("module", boost::program_options::wvalue<std::wstring>(), "module path")
      ("path-resolution", "perform path resolution")
      ("export", boost::program_options::value<std::string>(), "export name")
      ("free", "unload module")
      ("add-path", "add module dir to serach order")
      ("run", boost::program_options::wvalue<std::wstring>(), "process path")
      ;

    std::vector<std::wstring> const args = boost::program_options::
      split_winmain(GetCommandLine());
    boost::program_options::variables_map var_map;
    boost::program_options::store(boost::program_options::wcommand_line_parser(
      args).options(opts_desc).run(), var_map);
    boost::program_options::notify(var_map);

    if (var_map.count("help") || argc == 1)
    {
      std::cout << '\n' << opts_desc << '\n';
      return 1;
    }

    if (!var_map.count("module"))
    {
      std::cerr << "\nError! Module path must be specified.\n";
      return 1;
    }

    bool const has_pid = (var_map.count("pid") != 0);
    bool const create_proc = (var_map.count("run") != 0);
    if ((has_pid && create_proc) || (!has_pid && !create_proc))
    {
      std::cerr << "\nError! A process ID or an executable path must be "
        "specified.\n";
      return 1;
    }

    bool const inject = (var_map.count("free") == 0);
    if (!inject && create_proc)
    {
      std::cerr << "\nError! Modules can only be unloaded from running "
        "targets.\n";
      return 1;
    }

    std::wstring const module_path = var_map["module"].as<std::wstring>();
    bool const path_resolution = var_map.count("path-resolution") != 0;
    bool const add_path = var_map.count("add-path") != 0;

    int flags = hadesmem::InjectFlags::kNone;
    if (path_resolution)
    {
      flags |= hadesmem::InjectFlags::kPathResolution;
    }
    if (add_path)
    {
      flags |= hadesmem::InjectFlags::kAddToSearchOrder;
    }

    if (has_pid)
    {
      try
      {
        hadesmem::GetSeDebugPrivilege();

        std::wcout << "\nAcquired SeDebugPrivilege.\n";
      }
      catch (std::exception const& /*e*/)
      {
        std::wcout << "\nFailed to acquire SeDebugPrivilege.\n";
      }

      DWORD const pid = var_map["pid"].as<DWORD>();

      hadesmem::Process const process(pid);

      HMODULE module = nullptr;

      if (inject)
      {
        module = hadesmem::InjectDll(process, module_path, flags);

        std::wcout << "\nSuccessfully injected module at base address " <<
          PtrToString(module) << ".\n";
      }
      else
      {
        boost::filesystem::path path_real(module_path);
        if (path_resolution && path_real.is_relative())
        {
          path_real = boost::filesystem::absolute(path_real,
            hadesmem::detail::GetSelfDirPath());
        }
        path_real.make_preferred();

        hadesmem::Module const remote_module(process, path_real.native());
        module = remote_module.GetHandle();
      }

      if (var_map.count("export"))
      {
        std::string const export_name = var_map["export"].as<std::string>();
        auto const export_ret = hadesmem::CallExport(process, module,
          export_name);

        std::wcout << "\nSuccessfully called module export.\n";
        std::wcout << "Return: " << export_ret.GetReturnValue() << ".\n";
        std::wcout << "LastError: " << export_ret.GetLastError() << ".\n";
      }

      if (!inject)
      {
        hadesmem::FreeDll(process, module);

        std::wcout << "\nSuccessfully freed module at base address " <<
          PtrToString(module) << ".\n";
      }
    }
    else
    {
      std::vector<std::wstring> create_args;
      std::wstring const exe_path = var_map["run"].as<std::wstring>();
      std::string const export_name = var_map.count("export") ?
        var_map["export"].as<std::string>() : "";
      hadesmem::CreateAndInjectData const inject_data =
        hadesmem::CreateAndInject(
        exe_path,
        L"",
        std::begin(create_args),
        std::end(create_args),
        module_path,
        export_name,
        flags);

      std::wcout << "\nSuccessfully created target.\n";
      std::wcout << "Process ID: " << inject_data.GetProcess() << ".\n";
      std::wcout << "Module Base: " << PtrToString(inject_data.GetModule())
        << ".\n";
      std::wcout << "Export Return: " << inject_data.GetExportRet() << ".\n";
      std::wcout << "Export LastError: " << inject_data.GetExportLastError()
        << ".\n";
    }

    return 0;
  }
  catch (std::exception const& e)
  {
    std::cerr << "\nError!\n";
    std::cerr << boost::diagnostic_information(e) << '\n';

    return 1;
  }
}
<commit_msg>* Make calling either InjectDll or FreeDll optional. (Support calling export by itself.)<commit_after>// Copyright (C) 2010-2013 Joshua Boyce.
// See the file COPYING for copying permission.

#include <memory>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>

#include <hadesmem/detail/warning_disable_prefix.hpp>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <hadesmem/detail/warning_disable_suffix.hpp>

#include <windows.h>

#include <hadesmem/call.hpp>
#include <hadesmem/error.hpp>
#include <hadesmem/config.hpp>
#include <hadesmem/module.hpp>
#include <hadesmem/process.hpp>
#include <hadesmem/injector.hpp>
#include <hadesmem/detail/self_path.hpp>
#include <hadesmem/detail/initialize.hpp>

// TODO: Add support for for passing args, work dir, etc to CreateAndInject.
// e.g. exe-arg0, exe-arg1, exe-arg2, ..., exe-argN?

namespace
{

std::wstring PtrToString(void const* const ptr)
{
  std::wostringstream str;
  str.imbue(std::locale::classic());
  str << std::hex << reinterpret_cast<DWORD_PTR>(ptr);
  return str.str();
}

}

int main(int argc, char* /*argv*/[])
{
  try
  {
    hadesmem::detail::InitializeAll();

    std::cout << "HadesMem Injector\n";

    boost::program_options::options_description opts_desc(
      "General options");
    opts_desc.add_options()
      ("help", "produce help message")
      ("pid", boost::program_options::value<DWORD>(), "process id")
      ("module", boost::program_options::wvalue<std::wstring>(), "module path")
      ("path-resolution", "perform path resolution")
      ("export", boost::program_options::value<std::string>(), "export name")
      ("inject", "inject module")
      ("free", "unload module")
      ("add-path", "add module dir to search order")
      ("run", boost::program_options::wvalue<std::wstring>(), "process path")
      ;

    std::vector<std::wstring> const args = boost::program_options::
      split_winmain(GetCommandLine());
    boost::program_options::variables_map var_map;
    boost::program_options::store(boost::program_options::wcommand_line_parser(
      args).options(opts_desc).run(), var_map);
    boost::program_options::notify(var_map);

    if (var_map.count("help") || argc == 1)
    {
      std::cout << '\n' << opts_desc << '\n';
      return 1;
    }

    if (!var_map.count("module"))
    {
      std::cerr << "\nError! Module path must be specified.\n";
      return 1;
    }

    bool const has_pid = (var_map.count("pid") != 0);
    bool const create_proc = (var_map.count("run") != 0);
    if ((has_pid && create_proc) || (!has_pid && !create_proc))
    {
      std::cerr << "\nError! A process ID or an executable path must be "
        "specified.\n";
      return 1;
    }

    bool const inject = (var_map.count("inject") != 0);
    bool const free = (var_map.count("free") != 0);

    if (inject && free)
    {
      std::cerr << "\nError! Please specify inject or free, not both.\n";
    }

    if ((!inject || free) && create_proc)
    {
      std::cerr << "\nError! Modules can only be unloaded from running "
        "targets.\n";
      return 1;
    }

    std::wstring const module_path = var_map["module"].as<std::wstring>();
    bool const path_resolution = var_map.count("path-resolution") != 0;
    bool const add_path = var_map.count("add-path") != 0;

    int flags = hadesmem::InjectFlags::kNone;
    if (path_resolution)
    {
      flags |= hadesmem::InjectFlags::kPathResolution;
    }
    if (add_path)
    {
      flags |= hadesmem::InjectFlags::kAddToSearchOrder;
    }

    if (has_pid)
    {
      try
      {
        hadesmem::GetSeDebugPrivilege();

        std::wcout << "\nAcquired SeDebugPrivilege.\n";
      }
      catch (std::exception const& /*e*/)
      {
        std::wcout << "\nFailed to acquire SeDebugPrivilege.\n";
      }

      DWORD const pid = var_map["pid"].as<DWORD>();

      hadesmem::Process const process(pid);

      HMODULE module = nullptr;

      if (inject)
      {
        module = hadesmem::InjectDll(process, module_path, flags);

        std::wcout << "\nSuccessfully injected module at base address " <<
          PtrToString(module) << ".\n";
      }
      else
      {
        boost::filesystem::path path_real(module_path);
        if (path_resolution && path_real.is_relative())
        {
          path_real = boost::filesystem::absolute(path_real,
            hadesmem::detail::GetSelfDirPath());
        }
        path_real.make_preferred();

        hadesmem::Module const remote_module(process, path_real.native());
        module = remote_module.GetHandle();
      }

      if (var_map.count("export"))
      {
        std::string const export_name = var_map["export"].as<std::string>();
        auto const export_ret = hadesmem::CallExport(process, module,
          export_name);

        std::wcout << "\nSuccessfully called module export.\n";
        std::wcout << "Return: " << export_ret.GetReturnValue() << ".\n";
        std::wcout << "LastError: " << export_ret.GetLastError() << ".\n";
      }

      if (free)
      {
        hadesmem::FreeDll(process, module);

        std::wcout << "\nSuccessfully freed module at base address " <<
          PtrToString(module) << ".\n";
      }
    }
    else
    {
      std::vector<std::wstring> create_args;
      std::wstring const exe_path = var_map["run"].as<std::wstring>();
      std::string const export_name = var_map.count("export") ?
        var_map["export"].as<std::string>() : "";
      hadesmem::CreateAndInjectData const inject_data =
        hadesmem::CreateAndInject(
        exe_path,
        L"",
        std::begin(create_args),
        std::end(create_args),
        module_path,
        export_name,
        flags);

      std::wcout << "\nSuccessfully created target.\n";
      std::wcout << "Process ID: " << inject_data.GetProcess() << ".\n";
      std::wcout << "Module Base: " << PtrToString(inject_data.GetModule())
        << ".\n";
      std::wcout << "Export Return: " << inject_data.GetExportRet() << ".\n";
      std::wcout << "Export LastError: " << inject_data.GetExportLastError()
        << ".\n";
    }

    return 0;
  }
  catch (std::exception const& e)
  {
    std::cerr << "\nError!\n";
    std::cerr << boost::diagnostic_information(e) << '\n';

    return 1;
  }
}
<|endoftext|>


<commit_before>/*
 * server_memory_test.cpp - Kurento Media Server
 *
 * Copyright (C) 2013 Kurento
 * Contact: Miguel París Díaz <mparisdiaz@gmail.com>
 * Contact: José Antonio Santos Cadenas <santoscadenas@kurento.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3
 * as published by the Free Software Foundation.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "server_test_base.hpp"
#include <boost/test/unit_test.hpp>

#include "memory.hpp"
#include "mediaServer_constants.h"

#include <gst/gst.h>

using namespace kurento;

using namespace kurento;

#define GST_CAT_DEFAULT _server_memory_test_
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "server_memory_test"

#define ITERATIONS 10000
#define MEMORY_TOLERANCE 1024

BOOST_FIXTURE_TEST_SUITE ( server_memory_test_suite, F )

BOOST_AUTO_TEST_CASE ( create_media_pipeline_memory_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);

  for (i = 0; i < ITERATIONS; i++) {
    client->createMediaPipeline (mediaPipeline, 0);
    client->release (mediaPipeline);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( create_rtp_end_point_memory_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);

  for (i = 0; i < ITERATIONS; i++) {
    client->createMediaPipeline (mediaPipeline, 0);
    client->createSdpEndPoint (mo, mediaPipeline, SdpEndPointType::type::RTP_END_POINT);
    client->release (mediaPipeline);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( create_zbar_filter_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);

  for (i = 0; i < ITERATIONS; i++) {
    client->createMediaPipeline (mediaPipeline, 0);
    client->createFilter (mo, mediaPipeline, FilterType::type::ZBAR_FILTER);
    client->release (mediaPipeline);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( connect_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId player = MediaObjectId();
  MediaObjectId recorder = MediaObjectId();
  std::vector<MediaObjectId> srcs, sinks;
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);

  for (i = 0; i < ITERATIONS; i++) {
    client->createMediaPipeline (mediaPipeline, 0);
    client->createUriEndPoint (player, mediaPipeline, UriEndPointType::type::PLAYER_END_POINT, "file:///tmp/a");
    client->createUriEndPoint (recorder, mediaPipeline, UriEndPointType::type::RECORDER_END_POINT, "file:///tmp/b");

    client->getMediaSrcsByMediaType (srcs, player, MediaType::type::VIDEO);
    client->getMediaSinksByMediaType (sinks, recorder, MediaType::type::VIDEO);
    client->connect (srcs.front (), sinks.front () );
    client->release (mediaPipeline);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( connect_releasing_sink_element_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId player = MediaObjectId();
  MediaObjectId recorder = MediaObjectId();
  std::vector<MediaObjectId> srcs, sinks;
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);
  client->createMediaPipeline (mediaPipeline, 0);
  client->createUriEndPoint (player, mediaPipeline, UriEndPointType::type::PLAYER_END_POINT, "file:///tmp/a");
  client->getMediaSrcsByMediaType (srcs, player, MediaType::type::VIDEO);

  for (i = 0; i < ITERATIONS; i++) {
    client->createUriEndPoint (recorder, mediaPipeline, UriEndPointType::type::RECORDER_END_POINT, "file:///tmp/b");
    client->getMediaSinksByMediaType (sinks, recorder, MediaType::type::VIDEO);
    client->connect (srcs.front (), sinks.front () );
    client->release (recorder);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( connect_releasing_source_element_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId player = MediaObjectId();
  MediaObjectId recorder = MediaObjectId();
  std::vector<MediaObjectId> srcs, sinks;
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);
  client->createMediaPipeline (mediaPipeline, 0);
  client->createUriEndPoint (recorder, mediaPipeline, UriEndPointType::type::RECORDER_END_POINT, "file:///tmp/b");
  client->getMediaSinksByMediaType (sinks, recorder, MediaType::type::VIDEO);

  for (i = 0; i < ITERATIONS; i++) {
    client->createUriEndPoint (player, mediaPipeline, UriEndPointType::type::PLAYER_END_POINT, "file:///tmp/a");
    client->getMediaSrcsByMediaType (srcs, player, MediaType::type::VIDEO);
    client->connect (srcs.front (), sinks.front () );
    client->release (player);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Add memory test for creating player<commit_after>/*
 * server_memory_test.cpp - Kurento Media Server
 *
 * Copyright (C) 2013 Kurento
 * Contact: Miguel París Díaz <mparisdiaz@gmail.com>
 * Contact: José Antonio Santos Cadenas <santoscadenas@kurento.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3
 * as published by the Free Software Foundation.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "server_test_base.hpp"
#include <boost/test/unit_test.hpp>

#include "memory.hpp"
#include "mediaServer_constants.h"

#include <gst/gst.h>

using namespace kurento;

using namespace kurento;

#define GST_CAT_DEFAULT _server_memory_test_
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "server_memory_test"

#define ITERATIONS 10000
#define MEMORY_TOLERANCE 1024

BOOST_FIXTURE_TEST_SUITE ( server_memory_test_suite, F )

BOOST_AUTO_TEST_CASE ( create_media_pipeline_memory_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);

  for (i = 0; i < ITERATIONS; i++) {
    client->createMediaPipeline (mediaPipeline, 0);
    client->release (mediaPipeline);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( create_player_memory_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);

  for (i = 0; i < ITERATIONS; i++) {
    client->createMediaPipeline (mediaPipeline, 0);
    client->createUriEndPoint (mo, mediaPipeline, UriEndPointType::type::PLAYER_END_POINT, "file:///tmp/a");
    client->release (mediaPipeline);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( create_rtp_end_point_memory_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);

  for (i = 0; i < ITERATIONS; i++) {
    client->createMediaPipeline (mediaPipeline, 0);
    client->createSdpEndPoint (mo, mediaPipeline, SdpEndPointType::type::RTP_END_POINT);
    client->release (mediaPipeline);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( create_zbar_filter_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);

  for (i = 0; i < ITERATIONS; i++) {
    client->createMediaPipeline (mediaPipeline, 0);
    client->createFilter (mo, mediaPipeline, FilterType::type::ZBAR_FILTER);
    client->release (mediaPipeline);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( connect_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId player = MediaObjectId();
  MediaObjectId recorder = MediaObjectId();
  std::vector<MediaObjectId> srcs, sinks;
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);

  for (i = 0; i < ITERATIONS; i++) {
    client->createMediaPipeline (mediaPipeline, 0);
    client->createUriEndPoint (player, mediaPipeline, UriEndPointType::type::PLAYER_END_POINT, "file:///tmp/a");
    client->createUriEndPoint (recorder, mediaPipeline, UriEndPointType::type::RECORDER_END_POINT, "file:///tmp/b");

    client->getMediaSrcsByMediaType (srcs, player, MediaType::type::VIDEO);
    client->getMediaSinksByMediaType (sinks, recorder, MediaType::type::VIDEO);
    client->connect (srcs.front (), sinks.front () );
    client->release (mediaPipeline);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( connect_releasing_sink_element_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId player = MediaObjectId();
  MediaObjectId recorder = MediaObjectId();
  std::vector<MediaObjectId> srcs, sinks;
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);
  client->createMediaPipeline (mediaPipeline, 0);
  client->createUriEndPoint (player, mediaPipeline, UriEndPointType::type::PLAYER_END_POINT, "file:///tmp/a");
  client->getMediaSrcsByMediaType (srcs, player, MediaType::type::VIDEO);

  for (i = 0; i < ITERATIONS; i++) {
    client->createUriEndPoint (recorder, mediaPipeline, UriEndPointType::type::RECORDER_END_POINT, "file:///tmp/b");
    client->getMediaSinksByMediaType (sinks, recorder, MediaType::type::VIDEO);
    client->connect (srcs.front (), sinks.front () );
    client->release (recorder);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_CASE ( connect_releasing_source_element_test )
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId player = MediaObjectId();
  MediaObjectId recorder = MediaObjectId();
  std::vector<MediaObjectId> srcs, sinks;
  int i, maxMemorySize, currentMemorySize;

  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);

  client->addHandlerAddress (0, "localhost", 2323);
  client->createMediaPipeline (mediaPipeline, 0);
  client->createUriEndPoint (recorder, mediaPipeline, UriEndPointType::type::RECORDER_END_POINT, "file:///tmp/b");
  client->getMediaSinksByMediaType (sinks, recorder, MediaType::type::VIDEO);

  for (i = 0; i < ITERATIONS; i++) {
    client->createUriEndPoint (player, mediaPipeline, UriEndPointType::type::PLAYER_END_POINT, "file:///tmp/a");
    client->getMediaSrcsByMediaType (srcs, player, MediaType::type::VIDEO);
    client->connect (srcs.front (), sinks.front () );
    client->release (player);

    if (i == 0) {
      maxMemorySize = get_data_memory (pid) + MEMORY_TOLERANCE;
      GST_INFO ("MAX memory size: %d", maxMemorySize);
    }

    if (i % 100 == 0) {
      currentMemorySize = get_data_memory (pid);
      GST_INFO ("Memory size: %d", currentMemorySize);
      BOOST_REQUIRE (currentMemorySize <= maxMemorySize);
    }
  }
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "../config.h"

#include <iostream>
#include <fstream>
#include <getopt.h>
#include <netinet/in.h>
#include <ev.h>
#include <sysexits.h>

#include "../Socket/Socket.hxx"
#include "../Log/TimestampLog.hxx"

static const size_t READ_SIZE = 4096;
static const int MAX_CONN_BACKLOG = 32;

std::string logfilename;
std::ofstream logfile;
std::auto_ptr<std::ostream> log;

std::auto_ptr<SockAddr::SockAddr> bind_addr_outgoing;

void received_sigint(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGINT, exiting\n" << std::flush;
	ev_break(EV_A_ EVUNLOOP_ALL);
}
void received_sigterm(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGTERM, exiting\n" << std::flush;
	ev_break(EV_A_ EVUNLOOP_ALL);
}

void received_sighup(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGHUP, closing this logfile\n" << std::flush;
	logfile.close();
	logfile.open(logfilename.c_str(), std::ios_base::app | std::ios_base::out );
	*log << "Received SIGHUP, (re)opening this logfile\n" << std::flush;
}

static void listening_socket_ready_for_read(EV_P_ ev_io *w, int revents) {
	Socket* s_listen = reinterpret_cast<Socket*>( w->data );

	std::auto_ptr<SockAddr::SockAddr> client_addr;
	Socket client_socket = s_listen->accept(&client_addr);

	std::auto_ptr<SockAddr::SockAddr> server_addr;
	server_addr = client_socket.getsockname();

	*log << "Connection intercepted "
	     << client_addr->string() << "-->"
	     << server_addr->string() << "\n" << std::flush;

	Socket server_socket = Socket::socket(AF_INET, SOCK_STREAM, 0);

	if( bind_addr_outgoing.get() != NULL ) {
		server_socket.bind( *bind_addr_outgoing );
		*log << "Connecting " << bind_addr_outgoing->string()
		    << "-->";
	} else {
#if HAVE_DECL_IP_TRANSPARENT
		int value = 1;
		server_socket.setsockopt(SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
#endif
		server_socket.bind( *client_addr );
		*log << "Connecting " << client_addr->string()
		    << "-->";
	}
	*log << server_addr->string() << "\n" << std::flush;

	server_socket.connect( *server_addr );

	// TODO: keep client_socket around
	// TODO: keep server_socket around
	// TODO: connect these sockets
	// TODO: make connect async
}

int main(int argc, char* argv[]) {
	// Default options
	struct {
		bool fork;
		std::string pid_file;
		std::string bind_addr_listen;
		std::string bind_addr_outgoing;
	} options = {
		/* fork = */ true,
		/* pid_file = */ "",
		/* bind_addr_listen = */ "[0.0.0.0]:[5000]",
		/* bind_addr_outgoing = */ "[0.0.0.0]:[0]"
		};
	log.reset( new TimestampLog( std::cerr ) );

	{ // Parse options
		char optstring[] = "hVfp:b:B:l:";
		struct option longopts[] = {
			{"help",			no_argument, NULL, 'h'},
			{"version",			no_argument, NULL, 'V'},
			{"forgeground",		no_argument, NULL, 'f'},
			{"pid-file",		required_argument, NULL, 'p'},
			{"bind-listen",		required_argument, NULL, 'b'},
			{"bind-outgoing",	required_argument, NULL, 'B'},
			{"log",				required_argument, NULL, 'l'},
			{NULL, 0, 0, 0}
		};
		int longindex;
		int opt;
		while( (opt = getopt_long(argc, argv, optstring, longopts, &longindex)) != -1 ) {
			switch(opt) {
			case '?':
			case 'h':
				std::cerr <<
				//  >---------------------- Standard terminal width ---------------------------------<
					"Options:\n"
					"  -h -? --help                    Displays this help message and exits\n"
					"  -V --version                    Displays the version and exits\n"
					"  --foreground -f                 Don't fork into the background after init\n"
					"  --pid-file -p file              The file to write the PID to, especially\n"
					"                                  usefull when running as a daemon\n"
					"  --bind-listen -b host:port      Bind to the specified address for incomming\n"
					"                                  connections.\n"
					"                                  host and port resolving can be bypassed by\n"
					"                                  placing [] around them\n"
					"  --bind-outgoing -b host:port    Bind to the specified address for outgoing\n"
					"                                  connections.\n"
					"                                  host and port resolving can be bypassed by\n"
					"                                  placing [] around them\n"
					"                                  the special string \"client\" can be used to\n"
					"                                  reuse the client's source address. Note that\n"
					"                                  you should take care that the return packets\n"
					"                                  pass through this process again!\n"
					"  --log -l file                   Log to file\n"
					;
				if( opt == '?' ) exit(EX_USAGE);
				exit(EX_OK);
			case 'V':
				std::cout << PACKAGE_NAME << " version " << PACKAGE_VERSION
				          << " (" << PACKAGE_GITREVISION << ")\n";
				exit(EX_OK);
			case 'f':
				options.fork = false;
				break;
			case 'p':
				options.pid_file = optarg;
				break;
			case 'b':
				options.bind_addr_listen = optarg;
				break;
			case 'B':
				options.bind_addr_outgoing = optarg;
				break;
			case 'l':
				logfilename = optarg;
				logfile.open(logfilename.c_str(), std::ios_base::app | std::ios_base::out );
				log.reset( new TimestampLog( logfile ) );
				break;
			}
		}
	}

	*log << "Parsed options, opening listening socket on "
	     << options.bind_addr_listen << "\n" << std::flush;

	Socket s_listen;
	{ // Open listening socket
		std::string host, port;

		/* Address format is
		 *   - hostname:portname
		 *   - [numeric ip]:portname
		 *   - hostname:[portnumber]
		 *   - [numeric ip]:[portnumber]
		 */
		size_t c = options.bind_addr_listen.rfind(":");
		if( c == std::string::npos ) {
			std::cerr << "Invalid bind string \"" << options.bind_addr_listen << "\": could not find ':'\n";
			exit(EX_DATAERR);
		}
		host = options.bind_addr_listen.substr(0, c);
		port = options.bind_addr_listen.substr(c+1);

		std::auto_ptr< boost::ptr_vector< SockAddr::SockAddr> > bind_sa
			= SockAddr::resolve( host, port, 0, SOCK_STREAM, 0);
		if( bind_sa->size() == 0 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_listen << "\": Could not resolve\n";
			exit(EX_DATAERR);
		} else if( bind_sa->size() > 1 ) {
			// TODO: allow this
			std::cerr << "Can not bind to \"" << options.bind_addr_listen << "\": Resolves to multiple entries:\n";
			for( typeof(bind_sa->begin()) i = bind_sa->begin(); i != bind_sa->end(); i++ ) {
				std::cerr << "  " << i->string() << "\n";
			}
			exit(EX_DATAERR);
		}
		s_listen = Socket::socket( (*bind_sa)[0].proto_family() , SOCK_STREAM, 0);
		s_listen.set_reuseaddr();
		s_listen.bind((*bind_sa)[0]);
		s_listen.listen(MAX_CONN_BACKLOG);

#if HAVE_DECL_IP_TRANSPARENT
		int value = 1;
		s_listen.setsockopt(SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
#endif

		*log << "Listening on " << (*bind_sa)[0].string() << "\n" << std::flush;
	}

	if( options.bind_addr_outgoing == "client" ) {
		bind_addr_outgoing.reset(NULL);
	} else { // Resolve client address
		std::string host, port;

		/* Address format is
		 *   - hostname:portname
		 *   - [numeric ip]:portname
		 *   - hostname:[portnumber]
		 *   - [numeric ip]:[portnumber]
		 */
		size_t c = options.bind_addr_outgoing.rfind(":");
		if( c == std::string::npos ) {
			std::cerr << "Invalid bind string \"" << options.bind_addr_outgoing << "\": could not find ':'\n";
			exit(EX_DATAERR);
		}
		host = options.bind_addr_outgoing.substr(0, c);
		port = options.bind_addr_outgoing.substr(c+1);

		std::auto_ptr< boost::ptr_vector< SockAddr::SockAddr> > bind_sa
			= SockAddr::resolve( host, port, 0, SOCK_STREAM, 0);
		if( bind_sa->size() == 0 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_outgoing << "\": Could not resolve\n";
			exit(EX_DATAERR);
		} else if( bind_sa->size() > 1 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_outgoing << "\": Resolves to multiple entries:\n";
			for( typeof(bind_sa->begin()) i = bind_sa->begin(); i != bind_sa->end(); i++ ) {
				std::cerr << "  " << i->string() << "\n";
			}
			exit(EX_DATAERR);
		}
		bind_addr_outgoing.reset( bind_sa->release(bind_sa->begin()).release() ); // Transfer ownership; TODO: this should be simpeler that double release()

		*log << "Outgoing connections will connect from "
		     << bind_addr_outgoing->string() << "\n" << std::flush;
	}

	{
		ev_signal ev_sigint_watcher;
		ev_signal_init( &ev_sigint_watcher, received_sigint, SIGINT);
		ev_signal_start( EV_DEFAULT_ &ev_sigint_watcher);
		ev_signal ev_sigterm_watcher;
		ev_signal_init( &ev_sigterm_watcher, received_sigterm, SIGTERM);
		ev_signal_start( EV_DEFAULT_ &ev_sigterm_watcher);

		ev_signal ev_sighup_watcher;
		ev_signal_init( &ev_sighup_watcher, received_sighup, SIGHUP);
		ev_signal_start( EV_DEFAULT_ &ev_sighup_watcher);

		ev_io e_listen;
		e_listen.data = &s_listen;
		ev_io_init( &e_listen, listening_socket_ready_for_read, s_listen, EV_READ );
		ev_io_start( EV_DEFAULT_ &e_listen );

		*log << "Setup done, starting event loop\n" << std::flush;
		ev_run(EV_DEFAULT_ 0);
	}

	*log << "Exiting...\n" << std::flush;
	return 0;
}
<commit_msg>Var change 2<commit_after>#include "../config.h"

#include <iostream>
#include <fstream>
#include <getopt.h>
#include <netinet/in.h>
#include <ev.h>
#include <sysexits.h>

#include "../Socket/Socket.hxx"
#include "../Log/TimestampLog.hxx"

static const size_t READ_SIZE = 4096;
static const int MAX_CONN_BACKLOG = 32;

std::string logfilename;
std::ofstream logfile;
std::auto_ptr<std::ostream> log;

std::auto_ptr<SockAddr::SockAddr> bind_addr_outgoing;

void received_sigint(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGINT, exiting\n" << std::flush;
	ev_break(EV_A_ EVUNLOOP_ALL);
}
void received_sigterm(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGTERM, exiting\n" << std::flush;
	ev_break(EV_A_ EVUNLOOP_ALL);
}

void received_sighup(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGHUP, closing this logfile\n" << std::flush;
	logfile.close();
	logfile.open(logfilename.c_str(), std::ios_base::app | std::ios_base::out );
	*log << "Received SIGHUP, (re)opening this logfile\n" << std::flush;
}

static void listening_socket_ready_for_read(EV_P_ ev_io *w, int revents) {
	Socket* s_listen = reinterpret_cast<Socket*>( w->data );

	std::auto_ptr<SockAddr::SockAddr> client_addr;
	Socket s_client = s_listen->accept(&client_addr);

	std::auto_ptr<SockAddr::SockAddr> server_addr;
	server_addr = s_client.getsockname();

	*log << "Connection intercepted "
	     << client_addr->string() << "-->"
	     << server_addr->string() << "\n" << std::flush;

	Socket s_server = Socket::socket(AF_INET, SOCK_STREAM, 0);

	if( bind_addr_outgoing.get() != NULL ) {
		s_server.bind( *bind_addr_outgoing );
		*log << "Connecting " << bind_addr_outgoing->string()
		    << "-->";
	} else {
#if HAVE_DECL_IP_TRANSPARENT
		int value = 1;
		s_server.setsockopt(SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
#endif
		s_server.bind( *client_addr );
		*log << "Connecting " << client_addr->string()
		    << "-->";
	}
	*log << server_addr->string() << "\n" << std::flush;

	s_server.connect( *server_addr );

	// TODO: keep client_socket around
	// TODO: keep server_socket around
	// TODO: connect these sockets
	// TODO: make connect async
}

int main(int argc, char* argv[]) {
	// Default options
	struct {
		bool fork;
		std::string pid_file;
		std::string bind_addr_listen;
		std::string bind_addr_outgoing;
	} options = {
		/* fork = */ true,
		/* pid_file = */ "",
		/* bind_addr_listen = */ "[0.0.0.0]:[5000]",
		/* bind_addr_outgoing = */ "[0.0.0.0]:[0]"
		};
	log.reset( new TimestampLog( std::cerr ) );

	{ // Parse options
		char optstring[] = "hVfp:b:B:l:";
		struct option longopts[] = {
			{"help",			no_argument, NULL, 'h'},
			{"version",			no_argument, NULL, 'V'},
			{"forgeground",		no_argument, NULL, 'f'},
			{"pid-file",		required_argument, NULL, 'p'},
			{"bind-listen",		required_argument, NULL, 'b'},
			{"bind-outgoing",	required_argument, NULL, 'B'},
			{"log",				required_argument, NULL, 'l'},
			{NULL, 0, 0, 0}
		};
		int longindex;
		int opt;
		while( (opt = getopt_long(argc, argv, optstring, longopts, &longindex)) != -1 ) {
			switch(opt) {
			case '?':
			case 'h':
				std::cerr <<
				//  >---------------------- Standard terminal width ---------------------------------<
					"Options:\n"
					"  -h -? --help                    Displays this help message and exits\n"
					"  -V --version                    Displays the version and exits\n"
					"  --foreground -f                 Don't fork into the background after init\n"
					"  --pid-file -p file              The file to write the PID to, especially\n"
					"                                  usefull when running as a daemon\n"
					"  --bind-listen -b host:port      Bind to the specified address for incomming\n"
					"                                  connections.\n"
					"                                  host and port resolving can be bypassed by\n"
					"                                  placing [] around them\n"
					"  --bind-outgoing -b host:port    Bind to the specified address for outgoing\n"
					"                                  connections.\n"
					"                                  host and port resolving can be bypassed by\n"
					"                                  placing [] around them\n"
					"                                  the special string \"client\" can be used to\n"
					"                                  reuse the client's source address. Note that\n"
					"                                  you should take care that the return packets\n"
					"                                  pass through this process again!\n"
					"  --log -l file                   Log to file\n"
					;
				if( opt == '?' ) exit(EX_USAGE);
				exit(EX_OK);
			case 'V':
				std::cout << PACKAGE_NAME << " version " << PACKAGE_VERSION
				          << " (" << PACKAGE_GITREVISION << ")\n";
				exit(EX_OK);
			case 'f':
				options.fork = false;
				break;
			case 'p':
				options.pid_file = optarg;
				break;
			case 'b':
				options.bind_addr_listen = optarg;
				break;
			case 'B':
				options.bind_addr_outgoing = optarg;
				break;
			case 'l':
				logfilename = optarg;
				logfile.open(logfilename.c_str(), std::ios_base::app | std::ios_base::out );
				log.reset( new TimestampLog( logfile ) );
				break;
			}
		}
	}

	*log << "Parsed options, opening listening socket on "
	     << options.bind_addr_listen << "\n" << std::flush;

	Socket s_listen;
	{ // Open listening socket
		std::string host, port;

		/* Address format is
		 *   - hostname:portname
		 *   - [numeric ip]:portname
		 *   - hostname:[portnumber]
		 *   - [numeric ip]:[portnumber]
		 */
		size_t c = options.bind_addr_listen.rfind(":");
		if( c == std::string::npos ) {
			std::cerr << "Invalid bind string \"" << options.bind_addr_listen << "\": could not find ':'\n";
			exit(EX_DATAERR);
		}
		host = options.bind_addr_listen.substr(0, c);
		port = options.bind_addr_listen.substr(c+1);

		std::auto_ptr< boost::ptr_vector< SockAddr::SockAddr> > bind_sa
			= SockAddr::resolve( host, port, 0, SOCK_STREAM, 0);
		if( bind_sa->size() == 0 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_listen << "\": Could not resolve\n";
			exit(EX_DATAERR);
		} else if( bind_sa->size() > 1 ) {
			// TODO: allow this
			std::cerr << "Can not bind to \"" << options.bind_addr_listen << "\": Resolves to multiple entries:\n";
			for( typeof(bind_sa->begin()) i = bind_sa->begin(); i != bind_sa->end(); i++ ) {
				std::cerr << "  " << i->string() << "\n";
			}
			exit(EX_DATAERR);
		}
		s_listen = Socket::socket( (*bind_sa)[0].proto_family() , SOCK_STREAM, 0);
		s_listen.set_reuseaddr();
		s_listen.bind((*bind_sa)[0]);
		s_listen.listen(MAX_CONN_BACKLOG);

#if HAVE_DECL_IP_TRANSPARENT
		int value = 1;
		s_listen.setsockopt(SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
#endif

		*log << "Listening on " << (*bind_sa)[0].string() << "\n" << std::flush;
	}

	if( options.bind_addr_outgoing == "client" ) {
		bind_addr_outgoing.reset(NULL);
	} else { // Resolve client address
		std::string host, port;

		/* Address format is
		 *   - hostname:portname
		 *   - [numeric ip]:portname
		 *   - hostname:[portnumber]
		 *   - [numeric ip]:[portnumber]
		 */
		size_t c = options.bind_addr_outgoing.rfind(":");
		if( c == std::string::npos ) {
			std::cerr << "Invalid bind string \"" << options.bind_addr_outgoing << "\": could not find ':'\n";
			exit(EX_DATAERR);
		}
		host = options.bind_addr_outgoing.substr(0, c);
		port = options.bind_addr_outgoing.substr(c+1);

		std::auto_ptr< boost::ptr_vector< SockAddr::SockAddr> > bind_sa
			= SockAddr::resolve( host, port, 0, SOCK_STREAM, 0);
		if( bind_sa->size() == 0 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_outgoing << "\": Could not resolve\n";
			exit(EX_DATAERR);
		} else if( bind_sa->size() > 1 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_outgoing << "\": Resolves to multiple entries:\n";
			for( typeof(bind_sa->begin()) i = bind_sa->begin(); i != bind_sa->end(); i++ ) {
				std::cerr << "  " << i->string() << "\n";
			}
			exit(EX_DATAERR);
		}
		bind_addr_outgoing.reset( bind_sa->release(bind_sa->begin()).release() ); // Transfer ownership; TODO: this should be simpeler that double release()

		*log << "Outgoing connections will connect from "
		     << bind_addr_outgoing->string() << "\n" << std::flush;
	}

	{
		ev_signal ev_sigint_watcher;
		ev_signal_init( &ev_sigint_watcher, received_sigint, SIGINT);
		ev_signal_start( EV_DEFAULT_ &ev_sigint_watcher);
		ev_signal ev_sigterm_watcher;
		ev_signal_init( &ev_sigterm_watcher, received_sigterm, SIGTERM);
		ev_signal_start( EV_DEFAULT_ &ev_sigterm_watcher);

		ev_signal ev_sighup_watcher;
		ev_signal_init( &ev_sighup_watcher, received_sighup, SIGHUP);
		ev_signal_start( EV_DEFAULT_ &ev_sighup_watcher);

		ev_io e_listen;
		e_listen.data = &s_listen;
		ev_io_init( &e_listen, listening_socket_ready_for_read, s_listen, EV_READ );
		ev_io_start( EV_DEFAULT_ &e_listen );

		*log << "Setup done, starting event loop\n" << std::flush;
		ev_run(EV_DEFAULT_ 0);
	}

	*log << "Exiting...\n" << std::flush;
	return 0;
}
<|endoftext|>


<commit_before><commit_msg>planning: address code review comments<commit_after><|endoftext|>


<commit_before><commit_msg>Update cruise_mlp_evaluator.cc<commit_after><|endoftext|>