<commit_before>/*
 * simulation.cpp
 *
 *  Created on: Nov 23, 2014
 *      Author: tony
 */

#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using std::flush;
using std::string;

#include <sim/simulation.h>

simulation::simulation(const unsigned int type, const unsigned int n,
		const double* par, const string folder, const string fpre) :
								sim_type( type ),
								nCell( n ),
								folderName(folder){
	mycells = new cellmodel::Cells( nCell, this , par );
	if (nCell==1) {
		nCellOutputs = 1;
		nCellsToOutput = new unsigned int[nCellOutputs];
		nCellsToOutput[0] = 0;
		files   = new filesStruct(folder, fpre, 1 );
	} else {
		nCellOutputs = 5;
		nCellsToOutput = new unsigned int[nCellOutputs];
		nCellsToOutput[0] = 0;
		nCellsToOutput[1] = nCell/(nCellOutputs-1);
		for (unsigned int i=2; i<nCellOutputs-1; i++)
			nCellsToOutput[i] = nCellsToOutput[i-1] + nCellsToOutput[1];
		nCellsToOutput[nCellOutputs-1] = nCell-1;
		files   = new filesStruct(folder, fpre, nCellOutputs /* # of cell files */);
	}
	// The next line assumes all cells have the same number of states
	const unsigned int nstates = mycells->getNstates();
	neqns = nstates * nCell;
	Yold	= new double[neqns];
	Ynew	= new double[neqns];
}

simulation::~simulation(){
	// Deallocate work space
	delete[] Yold;
	delete[] Ynew;

	delete[] nCellsToOutput;
	delete files;
	delete mycells;
}

void simulation::SetInitialConditions(){
	// Load in initial conditions for each cell in the array
	mycells->SetInitialConditions();

	switch (sim_type){
	case 0:
		// Sim type 0 is for initial conditions set in code - no file read.
		break;
	case 1:
		// Read in file containing state of 1 cell
		// Sim type 1 typically uses the state of a single cell to set
		//  the states of all the cells in a cable
		// We need to set the initial conditions first - done above - and then
		//  reset the values using the data from the input file
		// This is because we use references in the Cell class/struct
		// Reading references from the input file does not work.
		readsinglecell( );
		break;
	case 2:
		// Sim type 2 starts up from  last cable state - read in the
		// states of all cells from a file
		readcells( );
		break;
	default:
		break;
	}

	// Get a complete copy of all the state variables of all the cells
	mycells->getStateFromCells( Yold );
}

void simulation::printcellAux(ofstream& of, const double t, Cell& c) {
	of << t << ", "
			<< c.getV() << ", " << c.getI_K1() << ", " << c.getI_Na() << ", "
			<< c.getI_axnm1() << ", " << c.getI_axnp1() << ", " << c.getI_axial()
			<< endl;
}

void simulation::printcellEAD(ofstream& of, Cell& c, Cell& c2, int r, int p, double S1) {
	double th_diff = 0;
	if (r == 0)
		th_diff = 1000 * 0.01 / (c.t_thr - c2.t_thr);
	else
		th_diff = 1000 * 0.01 / (c2.t_thr - c.t_thr); // special case for Cell[0]

	of << c.t_min << ", " << c.V_min << ", " << c.t_thr << ", " << c.V_thr
			<< ", " << c.t_max << ", " << c.V_max << ", " << c.t_90 << ", "
			<< c.V_90 << ", " << c.t_EAD << ", " << c.V_EAD << ", " << c.t_EAD2
			<< ", " << c.V_EAD2 << ", " << c.L_EAD << ", " << c.APD_90 << ", "
			<< c.DI << ", " << p << ", " << S1 << " , " << th_diff << ", "
			<< c.peak_slope << endl;
}

/*
 * savecells
 */
void simulation::savecells( ) {
	// if n == 1 --> save a single cell state
	//    n > 1  --> save multiple cells state
	const unsigned int ncells = mycells->getNcells();
	const char *f = (ncells==1)	? (folderName + "/" + cellstateFileName).c_str()
								: (folderName + "/" + stateFileName).c_str();
	cout << " Writing to: " << f << ". ";
	FILE *fp = fopen(f, "wb");
	int nw=0;
	for (unsigned int i = 0; i < ncells; i++) {
		Cell temp = mycells->getCell( i );
		nw += fwrite(temp.state, sizeof(Cell::state), 1, fp);
	}
	fclose(fp);
	std::cout << " Wrote state of " << nw << " cell(s)" << std::endl << flush;
}

void simulation::readcells( ) {
	const char *f = (folderName + "/" + stateFileName).c_str();
	const unsigned int ncells = mycells->getNcells();

	cout << " Reading data for " << ncells << " cells from " << f << ".";
	FILE *fp = fopen(f, "r");
	int nr = 0;
	unsigned int ntotal = 0;
	// References are messed up after reading structs from a file
	for (unsigned int i = 0; i < ncells; i++) {
		Cell temp;
		nr = fread(temp.state, sizeof(Cell::state), 1, fp);
		if (nr <= 0)
			break;
		mycells->copyCell( i, temp);
		ntotal++;
	}
	fclose(fp);
	if (ntotal < ncells)
		cout << " --> Read " << nr << " cells. ";
	cout << " Done reading." << endl << flush;
}

void simulation::readsinglecell( ) {
	const char *f = (folderName + "/" + cellstateFileName).c_str();
	const unsigned int ncells = mycells->getNcells();

	cout << " Reading data for " << ncells << " cells from " << f << ".";
	FILE *fp = fopen(f, "r");
	Cell temp;
	int nr = fread(temp.state, sizeof(Cell::state), 1, fp);
	switch (nr){
	case 0:
		cout << " --> Could not read cell state!!! ";
		break;
	case 1:
		cout << " --> Read single cell state. ";
		mycells->copyCells( temp );
		break;
	default:
		cout << " --> fread returned: " << nr << ", cell state not changed.";
		break;
	}
	fclose(fp);
	cout << " Done setting cell states from file." << endl << flush;
}

void simulation::printEverything(const double time, const int cycle,
					 const double interval, const int S2_cycle,
					 int& counter ){
	counter++;
	if ((counter % counterupdates) == 0) {
		cout << ".";
		// Print auxilliary variables
		if ((counter % (printtimeupdate*counterupdates)) == 0){
			//This file will have voltages against time for each cell
			mycells->printV( files->result, time );
			if (printMarkovIts)
				printMarkovIterations( time );

			//This file prints The Markov States for cell 50
			if (cycle > printMarkovStatesAfterCycle) {
				mycells->printNacell( files->Na, time, nCell/2 );
			}

			cout << "t=" << time << "msec" << endl;
			for (unsigned int i=0; i<nCellOutputs; i++){
				Cell  c = mycells->getCell( nCellsToOutput[i] );
				printcellAux( *(files->cellAuxFs[ i ]), time, c );
			}

			/* Used to be:
			Cell  c0 = mycells->getCell( n0p00 );
			printcellAux( *(files->First), time, c0 );
			if (n0p25 > n0p00){
				Cell c25 = mycells->getCell( n0p25 );
				printcellAux( *(files->Quarter), time, c25 );
				if (n0p50 > n0p25){
					Cell c50 = mycells->getCell( n0p50 );
					printcellAux( *(files->Midpoint), time, c50 );
					if (n0p75 > n0p50){
						Cell c75 = mycells->getCell( n0p75 );
						printcellAux( *(files->Three4ths), time, c75 );
						if (n1p00 > n0p75){
							Cell c99 = mycells->getCell( n1p00 );
							printcellAux( *(files->Last), time, c99 );
						}
					}
				}
			}
			*/
		}

		if ( (counter % (printCycleUpdate*printtimeupdate*counterupdates)) == 0){
			switch (sim_type){
			case 0:
				cout << "Non-paced simulation, t=" << time  << " end time= ";
				break;
			case 1:
			case 2:
				cout << "Paced simulation, cycle: " << cycle << " of " << MaxNumberOfBeats
						<< ", t=" << time  << ", this interval= ";
				break;
			default:
				break;
			}
			counter = 0;
			cout  << interval << ", [drug] is " << drug << endl;
		}
		cout << flush;
	}

	if ( nCell > 1 ){
		//This file is for individual cells that calculates all of the min, max, V_90 parameters.
		bool isPrintingNeeded = mycells->isPrintingNeeded();
		if (isPrintingNeeded) {
			mycells->printThreshold( 50, cycle );

			for (unsigned int i=0; i<nCellOutputs; i++){
				unsigned int cellout  = nCellsToOutput[i];
				unsigned int cellnext = 1;
				int flag = 0;
				if (nCellsToOutput[i] == 0 ){
					// For the 0th cell, the adjacent one is 1
					cellnext = nCellsToOutput[i] + 1;
					flag = 1;
				} else {
					// For the other cells, the adjacent one is the one before it
					cellnext =  nCellsToOutput[i] - 1;
				}

				Cell  c    = mycells->getCell( cellout );
				Cell  cadj = mycells->getCell( cellnext );

				printcellEAD( *(files->EADFs[ i ]),  c,  cadj, flag, cellout,  cycle );
			}

			/* Used to be
			Cell  c0 = mycells->getCell( n0p00 );
			Cell  c1 = mycells->getCell( n0p00+1 );
			printcell( *(files->EAD00),  c0,  c1, 1,     0,   cycle );
			Cell c25 = mycells->getCell( n0p25 );
			Cell c24 = mycells->getCell( n0p25-1 );
			printcell( *(files->EAD25), c25, c24, 0,    25,   cycle );
			Cell c50 = mycells->getCell( n0p50 );
			Cell c49 = mycells->getCell( n0p50-1 );
			printcell( *(files->EAD50), c50, c49, 0,    50,   cycle );
			Cell c75 = mycells->getCell( n0p75 );
			Cell c74 = mycells->getCell( n0p75-1 );
			printcell( *(files->EAD75), c75, c74, 0,    75,   cycle );
			Cell c99 = mycells->getCell( n1p00 );
			Cell c98 = mycells->getCell( n1p00-1 );
			printcell( *(files->EAD99), c99, c98, 0, nCell-1, cycle );
			*/

			mycells->resetPrintFlag();
			isPrintingNeeded = false;
		} // End of individual result files
	}
}

bool simulation::step( const double told, const double tnew ){
	const bool success = solve->step( told, tnew, Yold, Ynew );
	if (success) {
		if (solve->isInplace()) {
			// Get a copy of all the state variables of all the cells
			mycells->getStateFromCells( Yold );
		} else {
			// Update the old state to have the new values
			for (unsigned int i=0; i<neqns; i++)
				Yold[i] = Ynew[i];
		}
	}
	return success;
}

void simulation::printCV(const double time, const int cycle){
	if ( nCell > 1 ){
		mycells->printCV( files->CV, cycle );
	}
}
void simulation::printMarkovIterations( const double t ){
	const unsigned int ncells = mycells->getNcells();
	// find middle cell
	const unsigned int middlecell = ncells/2;
	Cell  c = mycells->getCell( middlecell);
//MarkovIterations should be in the rushlarsen object
	*(files->MarkovIterations) << t <<", " << c.MarkovIterations
						       << ", " << c.MarkovIterationError << endl;
	// reset markov iteration count
}
<commit_msg>Fixed up simulation.cpp<commit_after>/*
 * simulation.cpp
 *
 *  Created on: Nov 23, 2014
 *      Author: tony
 */

#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using std::flush;
using std::string;

#include <sim/simulation.h>

simulation::simulation(const unsigned int type, const unsigned int n,
		const double* par, const string folder, const string fpre) :
								sim_type( type ),
								nCell( n ),
								folderName(folder){
	mycells = new cellmodel::Cells( nCell, this , par );
	if (nCell==1) {
		nCellOutputs = 1;
		nCellsToOutput = new unsigned int[nCellOutputs];
		nCellsToOutput[0] = 0;
		files   = new filesStruct(folder, fpre, 1 );
	} else {
		nCellOutputs = 5;
		nCellsToOutput = new unsigned int[nCellOutputs];
		nCellsToOutput[0] = 0;
		nCellsToOutput[1] = nCell/(nCellOutputs-1);
		for (unsigned int i=2; i<nCellOutputs-1; i++)
			nCellsToOutput[i] = nCellsToOutput[i-1] + nCellsToOutput[1];
		nCellsToOutput[nCellOutputs-1] = nCell-1;
		files   = new filesStruct(folder, fpre, nCellOutputs /* # of cell files */);
	}
	// The next line assumes all cells have the same number of states
	const unsigned int nstates = mycells->getNstates();
	neqns = nstates * nCell;
	Yold	= new double[neqns];
	Ynew	= new double[neqns];
}

simulation::~simulation(){
	// Deallocate work space
	delete[] Yold;
	delete[] Ynew;

	delete[] nCellsToOutput;
	delete files;
	delete mycells;
}

void simulation::SetInitialConditions(){
	// Load in initial conditions for each cell in the array
	mycells->SetInitialConditions();

	switch (sim_type){
	case 0:
		// Sim type 0 is for initial conditions set in code - no file read.
		break;
	case 1:
		// Read in file containing state of 1 cell
		// Sim type 1 typically uses the state of a single cell to set
		//  the states of all the cells in a cable
		// We need to set the initial conditions first - done above - and then
		//  reset the values using the data from the input file
		// This is because we use references in the Cell class/struct
		// Reading references from the input file does not work.
		readsinglecell( );
		break;
	case 2:
		// Sim type 2 starts up from  last cable state - read in the
		// states of all cells from a file
		readcells( );
		break;
	default:
		break;
	}

	// Get a complete copy of all the state variables of all the cells
	mycells->getStateFromCells( Yold );
}

void simulation::printcellAux(ofstream& of, const double t, Cell& c) {
	of << t << ", "
			<< c.getV() << ", " << c.getI_K1() << ", " << c.getI_Na() << ", "
			<< c.getI_axnm1() << ", " << c.getI_axnp1() << ", " << c.getI_axial()
			<< endl;
}

void simulation::printcellEAD(ofstream& of, Cell& c, Cell& c2, int r, int p, double S1) {
	double th_diff = 0;
	if (r == 0)
		th_diff = 1000 * 0.01 / (c.t_thr - c2.t_thr);
	else
		th_diff = 1000 * 0.01 / (c2.t_thr - c.t_thr); // special case for Cell[0]

	of << c.t_min << ", " << c.V_min << ", " << c.t_thr << ", " << c.V_thr
			<< ", " << c.t_max << ", " << c.V_max << ", " << c.t_90 << ", "
			<< c.V_90 << ", " << c.t_EAD << ", " << c.V_EAD << ", " << c.t_EAD2
			<< ", " << c.V_EAD2 << ", " << c.L_EAD << ", " << c.APD_90 << ", "
			<< c.DI << ", " << p << ", " << S1 << " , " << th_diff << ", "
			<< c.peak_slope << endl;
}

/*
 * savecells
 */
void simulation::savecells( ) {
	// if n == 1 --> save a single cell state
	//    n > 1  --> save multiple cells state
	const unsigned int ncells = mycells->getNcells();
	// The following two lines resulted in f pointing to an empty string
	//const char *f = (ncells==1)	? (folderName + "/" + cellstateFileName).c_str()
	//							: (folderName + "/" + stateFileName).c_str();

	string f = (ncells==1)	? (folderName + "/" + cellstateFileName)
									: (folderName + "/" + stateFileName);

	cout << " Writing to: " << f << ". " << flush;
	FILE *fp = fopen(f.c_str(), "wb");
	int nw=0;
	for (unsigned int i = 0; i < ncells; i++) {
		Cell temp = mycells->getCell( i );
		nw += fwrite(temp.state, sizeof(Cell::state), 1, fp);
	}
	fclose(fp);
	std::cout << " Wrote state of " << nw << " cell(s)" << std::endl << flush;
}

void simulation::readcells( ) {
	// The next line resulted in f pointing to an empty string
	// const char *f = (folderName + "/" + cellstateFileName).c_str();
	string f = folderName + "/" + cellstateFileName;
	const unsigned int ncells = mycells->getNcells();

	cout << " Reading data for " << ncells << " cells from " << f << ".";
	FILE *fp = fopen(f.c_str(), "r");
	int nr = 0;
	unsigned int ntotal = 0;
	// References are messed up after reading structs from a file
	for (unsigned int i = 0; i < ncells; i++) {
		Cell temp;
		nr = fread(temp.state, sizeof(Cell::state), 1, fp);
		if (nr <= 0)
			break;
		mycells->copyCell( i, temp);
		ntotal++;
	}
	fclose(fp);
	if (ntotal < ncells)
		cout << " --> Read " << nr << " cells. ";
	cout << " Done reading." << endl << flush;
}

void simulation::readsinglecell( ) {
	string f = folderName + "/" + cellstateFileName;
	const unsigned int ncells = mycells->getNcells();

	cout << " Reading data for " << ncells << " cells from " << f << ".";
	FILE *fp = fopen(f.c_str(), "r");
	Cell temp;
	int nr = fread(temp.state, sizeof(Cell::state), 1, fp);
	switch (nr){
	case 0:
		cout << " --> Could not read cell state!!! ";
		break;
	case 1:
		cout << " --> Read single cell state. ";
		mycells->copyCells( temp );
		break;
	default:
		cout << " --> fread returned: " << nr << ", cell state not changed.";
		break;
	}
	fclose(fp);
	cout << " Done setting cell states from file." << endl << flush;
}

void simulation::printEverything(const double time, const int cycle,
					 const double interval, const int S2_cycle,
					 int& counter ){
	counter++;
	if ((counter % counterupdates) == 0) {
		cout << ".";
		// Print auxilliary variables
		if ((counter % (printtimeupdate*counterupdates)) == 0){
			//This file will have voltages against time for each cell
			mycells->printV( files->result, time );
			if (printMarkovIts)
				printMarkovIterations( time );

			//This file prints The Markov States for cell 50
			if (cycle > printMarkovStatesAfterCycle) {
				mycells->printNacell( files->Na, time, nCell/2 );
			}

			cout << "t=" << time << "msec" << endl;
			for (unsigned int i=0; i<nCellOutputs; i++){
				Cell  c = mycells->getCell( nCellsToOutput[i] );
				printcellAux( *(files->cellAuxFs[ i ]), time, c );
			}

			/* Used to be:
			Cell  c0 = mycells->getCell( n0p00 );
			printcellAux( *(files->First), time, c0 );
			if (n0p25 > n0p00){
				Cell c25 = mycells->getCell( n0p25 );
				printcellAux( *(files->Quarter), time, c25 );
				if (n0p50 > n0p25){
					Cell c50 = mycells->getCell( n0p50 );
					printcellAux( *(files->Midpoint), time, c50 );
					if (n0p75 > n0p50){
						Cell c75 = mycells->getCell( n0p75 );
						printcellAux( *(files->Three4ths), time, c75 );
						if (n1p00 > n0p75){
							Cell c99 = mycells->getCell( n1p00 );
							printcellAux( *(files->Last), time, c99 );
						}
					}
				}
			}
			*/
		}

		if ( (counter % (printCycleUpdate*printtimeupdate*counterupdates)) == 0){
			switch (sim_type){
			case 0:
				cout << "Non-paced simulation, t=" << time  << " end time= ";
				break;
			case 1:
			case 2:
				cout << "Paced simulation, cycle: " << cycle << " of " << MaxNumberOfBeats
						<< ", t=" << time  << ", this interval= ";
				break;
			default:
				break;
			}
			counter = 0;
			cout  << interval << ", [drug] is " << drug << endl;
		}
		cout << flush;
	}

	if ( nCell > 1 ){
		//This file is for individual cells that calculates all of the min, max, V_90 parameters.
		bool isPrintingNeeded = mycells->isPrintingNeeded();
		if (isPrintingNeeded) {
			mycells->printThreshold( 50, cycle );

			for (unsigned int i=0; i<nCellOutputs; i++){
				unsigned int cellout  = nCellsToOutput[i];
				unsigned int cellnext = 1;
				int flag = 0;
				if (nCellsToOutput[i] == 0 ){
					// For the 0th cell, the adjacent one is 1
					cellnext = nCellsToOutput[i] + 1;
					flag = 1;
				} else {
					// For the other cells, the adjacent one is the one before it
					cellnext =  nCellsToOutput[i] - 1;
				}

				Cell  c    = mycells->getCell( cellout );
				Cell  cadj = mycells->getCell( cellnext );

				printcellEAD( *(files->EADFs[ i ]),  c,  cadj, flag, cellout,  cycle );
			}

			/* Used to be
			Cell  c0 = mycells->getCell( n0p00 );
			Cell  c1 = mycells->getCell( n0p00+1 );
			printcell( *(files->EAD00),  c0,  c1, 1,     0,   cycle );
			Cell c25 = mycells->getCell( n0p25 );
			Cell c24 = mycells->getCell( n0p25-1 );
			printcell( *(files->EAD25), c25, c24, 0,    25,   cycle );
			Cell c50 = mycells->getCell( n0p50 );
			Cell c49 = mycells->getCell( n0p50-1 );
			printcell( *(files->EAD50), c50, c49, 0,    50,   cycle );
			Cell c75 = mycells->getCell( n0p75 );
			Cell c74 = mycells->getCell( n0p75-1 );
			printcell( *(files->EAD75), c75, c74, 0,    75,   cycle );
			Cell c99 = mycells->getCell( n1p00 );
			Cell c98 = mycells->getCell( n1p00-1 );
			printcell( *(files->EAD99), c99, c98, 0, nCell-1, cycle );
			*/

			mycells->resetPrintFlag();
			isPrintingNeeded = false;
		} // End of individual result files
	}
}

bool simulation::step( const double told, const double tnew ){
	const bool success = solve->step( told, tnew, Yold, Ynew );
	if (success) {
		if (solve->isInplace()) {
			// Get a copy of all the state variables of all the cells
			mycells->getStateFromCells( Yold );
		} else {
			// Update the old state to have the new values
			for (unsigned int i=0; i<neqns; i++)
				Yold[i] = Ynew[i];
		}
	}
	return success;
}

void simulation::printCV(const double time, const int cycle){
	if ( nCell > 1 ){
		mycells->printCV( files->CV, cycle );
	}
}
void simulation::printMarkovIterations( const double t ){
	const unsigned int ncells = mycells->getNcells();
	// find middle cell
	const unsigned int middlecell = ncells/2;
	Cell  c = mycells->getCell( middlecell);
//MarkovIterations should be in the rushlarsen object
	*(files->MarkovIterations) << t <<", " << c.MarkovIterations
						       << ", " << c.MarkovIterationError << endl;
	// reset markov iteration count
}
<|endoftext|>


<commit_before>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2014 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  support/thread.cpp                                                              */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// include i/f header

#include "support/thread.hpp"

// includes, system

#define GLIBCXX_NO_CODECVT 20131212

#if !defined(__GLIBCXX__) || (defined(__GLIBCXX__) && (__GLIBCXX__ > GLIBCXX_NO_CODECVT))
#  include <codecvt> // std::codecvt_utf8<>
#endif

#include <locale>    // std::wstring_convert<>

// includes, project

// #include <>

#define UKACHULLDCS_USE_TRACE
#undef UKACHULLDCS_USE_TRACE
#include <support/trace.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  // variables, internal

  // functions, internal

} // namespace {

namespace support {

  // variables, exported

  // functions, exported

  std::string
  wstring_to_string(std::wstring const& a)
  {
    TRACE("support::wstring_to_string");

#if defined(__GLIBCXX__) && (__GLIBCXX__ <= GLIBCXX_NO_CODECVT)
    return std::string(a.begin(), a.end());
#else
    return std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(a);
#endif
  }

  std::wstring
  string_to_wstring(std::string const& a)
  {
    TRACE("support::string_to_wstring");

    return std::wstring(a.begin(), a.end());
  }

} // namespace support {
<commit_msg>fixed: typo<commit_after>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2014 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  support/string.cpp                                                              */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// include i/f header

#include "support/thread.hpp"

// includes, system

#define GLIBCXX_NO_CODECVT 20131212

#if !defined(__GLIBCXX__) || (defined(__GLIBCXX__) && (__GLIBCXX__ > GLIBCXX_NO_CODECVT))
#  include <codecvt> // std::codecvt_utf8<>
#endif

#include <locale>    // std::wstring_convert<>

// includes, project

// #include <>

#define UKACHULLDCS_USE_TRACE
#undef UKACHULLDCS_USE_TRACE
#include <support/trace.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  // variables, internal

  // functions, internal

} // namespace {

namespace support {

  // variables, exported

  // functions, exported

  std::string
  wstring_to_string(std::wstring const& a)
  {
    TRACE("support::wstring_to_string");

#if defined(__GLIBCXX__) && (__GLIBCXX__ <= GLIBCXX_NO_CODECVT)
    return std::string(a.begin(), a.end());
#else
    return std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(a);
#endif
  }

  std::wstring
  string_to_wstring(std::string const& a)
  {
    TRACE("support::string_to_wstring");

    return std::wstring(a.begin(), a.end());
  }

} // namespace support {
<|endoftext|>


<commit_before>#pragma once
#ifndef FORWARDER_HPP
# define FORWARDER_HPP

#include <cassert>

#include <cstddef>

#include <cstdint>

#include <type_traits>

#include <utility>

#include <new>

namespace generic
{

template<typename F>
class forwarder;

template<typename R, typename ...A>
class forwarder<R (A...)>
{
public:
  forwarder() = default;

  forwarder(forwarder const&) = default;

  template<typename T>
  forwarder(T&& f) : stub_(invoker_stub<T>)
  {
    static_assert(sizeof(T) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_destructible<T>::value,
      "functor not trivially destructible");
    using functor_type = typename ::std::decay<T>::type;
    new (static_cast<void*>(&store_)) functor_type(::std::forward<T>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<forwarder, typename ::std::decay<T>::type>{}
    >::type
  >
  forwarder& operator=(T&& f)
  {
    static_assert(sizeof(T) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_destructible<T>::value,
      "functor not trivially destructible");
    using functor_type = typename ::std::decay<T>::type;
    new (&store_) functor_type(::std::forward<T>(f));

    stub_ = invoker_stub<functor_type>;

    return *this;
  }

  R operator() (A... args) const
  {
    //assert(stub_);
    return stub_(&store_, ::std::forward<A>(args)...);
  }

private:
  template <typename U>
  static R invoker_stub(void const* const ptr, A&&... args)
  {
    return (*static_cast<U const*>(ptr))(::std::forward<A>(args)...);
  }

  R (*stub_)(void const*, A&&...){};

  typename ::std::aligned_storage<sizeof(::std::uintptr_t)>::type store_;
};

}

#endif // FORWARDER_HPP
<commit_msg>some fixes<commit_after>#pragma once
#ifndef FORWARDER_HPP
# define FORWARDER_HPP

#include <cassert>

#include <cstddef>

#include <cstdint>

#include <type_traits>

#include <utility>

#include <new>

namespace generic
{

template<typename F>
class forwarder;

template<typename R, typename ...A>
class forwarder<R (A...)>
{
public:
  forwarder() = default;

  forwarder(forwarder const&) = default;

  template<typename T> forwarder(T&& f) { *this = ::std::forward<T>(f); }

  forwarder& operator=(forwarder const&) = default;

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<forwarder, typename ::std::decay<T>::type>{}
    >::type
  >
  forwarder& operator=(T&& f)
  {
    static_assert(sizeof(T) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_destructible<T>::value,
      "functor not trivially destructible");
    using functor_type = typename ::std::decay<T>::type;
    new (&store_) functor_type(::std::forward<T>(f));

    stub_ = invoker_stub<functor_type>;

    return *this;
  }

  R operator() (A... args) const
  {
    //assert(stub_);
    return stub_(&store_, ::std::forward<A>(args)...);
  }

private:
  template <typename U>
  static R invoker_stub(void const* const ptr, A&&... args)
  {
    return (*static_cast<U const*>(ptr))(::std::forward<A>(args)...);
  }

  R (*stub_)(void const*, A&&...){};

  typename ::std::aligned_storage<sizeof(::std::uintptr_t)>::type store_;
};

}

#endif // FORWARDER_HPP
<|endoftext|>


<commit_before>
#include <stdio.h>
#include <string>
#include "statesaver.h"

using namespace std;
StateSaver::StateSaver(QMTopology& qmtop)
{}

//void StateSaver::Open(string file)
void StateSaver::Open(string file, bool bAppend)
{
    //_out = fopen(file.c_str(), bAppend ? "at" : "wt");
    ofstream _out(file.c_str(), ios::binary|ios::out);
    //_out = datafile(datafile.c_str(), ios::binary|ios::out);
}

void StateSaver::Close()
{
 _out.close();
}

void StateSaver::Write_QMBeads(QMTopology *top)
{   QMTopology *qmtop = top;
    for(BeadContainer::iterator iter=qmtop->Beads().begin();
    iter!=qmtop->Beads().end(); ++iter) {
        QMBead *bi = dynamic_cast<QMBead*>(*iter);

    string crg_unit_name = bi->GetCrgUnit()->GetType()->GetName();
        unsigned short len_name = crg_unit_name.length();
    int ipos=bi->getiPos();
    string type=bi->getType()->getName();
        unsigned short len_type = type.length();
    int symmetry=bi->getSymmetry();
    string bead_name=bi->getName();
        unsigned short len_bead_name = bead_name.length();
    int res_number=bi->getResnr();
    double mass=bi->getM();
    double charge=bi->getQ();
    vec r = bi->getPos();
    vec u = bi->getU();
    vec v = bi->getV();

    //writing all out
     _out.write((char *) &len_name, sizeof(len_name));
     cout<<"We have"<<len_name<<"letters in the name\n";
     _out.write((char *) crg_unit_name.c_str(), sizeof(crg_unit_name));
     _out.write((char *) &ipos, sizeof(ipos));
     _out.write((char *) &len_type, sizeof(len_type));
     _out.write((char *) type.c_str(), sizeof(type));
     _out.write((char *) &symmetry, sizeof(symmetry));
     _out.write((char *) &len_bead_name, sizeof(len_bead_name));
     _out.write((char *) bead_name.c_str(), sizeof(bead_name));
     _out.write((char *) &res_number, sizeof(len_bead_name));
     _out.write((char *) &mass, sizeof(mass));
     _out.write((char *) &charge, sizeof(charge));
     _out.write((char *) &r, sizeof(r));
     _out.write((char *) &u, sizeof(u));
     _out.write((char *) &v, sizeof(v));
    }

    // fflush(_out);
}

/*VICTOR:
void PDBWriter::Open(string file, bool bAppend)
{
    _out = fopen(file.c_str(), bAppend ? "at" : "wt");
}

void PDBWriter::Close()
{
    fclose(_out);
}

void PDBWriter::Write(Topology *conf)
{
    Topology *top = conf;
    fprintf(_out, "MODEL     %4d\n", conf->getStep());
    for(BeadContainer::iterator iter=conf->Beads().begin();
    iter!=conf->Beads().end(); ++iter) {
        Bead *bi = *iter;
        vec r = bi->getPos();
        fprintf(_out,
                "ATOM  %5d %4s %3s %1s%4d    %8.3f%8.3f%8.3f%6.2f%6.2f\n",
                (bi->getId()+1)%100000,   // atom serial number
                bi->getName().c_str(),  // atom name
                top->getResidue(bi->getResnr())->getName().c_str(), // residue name
                " ", // chain identifier 1 char
                bi->getResnr()+1, // residue sequence number
                10.*r.x(), 10.*r.y(), 10.*r.z(),
                bi->getQ(), bi->getM());  // is this correct??

        if(bi->getSymmetry()>=2) {
           vec ru = 0.1*bi->getU() + r;

            fprintf(_out,
                "HETATM%5d %4s %3s %1s%4d    %8.3f%8.3f%8.4f%6.2f%6.2f\n",
                bi->getId()+1,   // atom serial number
                bi->getName().c_str(),  // atom name
                "REU", // residue name
                " ", // chain identifier 1 char
                bi->getResnr()+1, // residue sequence number
                10.*ru.x(), 10.*ru.y(), 10.*ru.z(),
                0., 0.);  // is this correct??
        }
        if(bi->getSymmetry()>=3) {
           vec rv = 0.1*bi->getV() + r;
            fprintf(_out,
                "HETATM%5d %4s %3s %1s%4d    %8.3f%8.3f%8.4f%6.2f%6.2f\n",
                bi->getId()+1,   // atom serial number
                bi->getName().c_str(),  // atom name
                "REV", // residue name
                " ", // chain identifier 1 char
                bi->getResnr()+1, // residue sequence number
                10.*rv.x(), 10.*rv.y(), 10.*rv.z(),
                0.,0.);
        }
   }
    fprintf(_out, "ENDMDL\n");
    fflush(_out);
}*/
<commit_msg>better statesaver.cc<commit_after>
#include <stdio.h>
#include <string>
#include "statesaver.h"

using namespace std;

StateSaver::StateSaver(QMTopology &qmtop) {
    _qmtop = &qmtop;
}

//void StateSaver::Open(string file)

void StateSaver::Save(string file, bool bAppend) {
    //_out = fopen(file.c_str(), bAppend ? "at" : "wt");
    _out.open(file.c_str(), ios::out | ios::binary);
    Write_QMBeads();
    //Write NBL
    _out.close();
    //_out = datafile(datafile.c_str(), ios::binary|ios::out);
}

void StateSaver::Write_QMBeads() {
    assert(_out.is_open());

    write<unsigned long>(_qmtop->BeadCount());
    for (BeadContainer::iterator iter = _qmtop->Beads().begin();
            iter != _qmtop->Beads().end(); ++iter) {
        QMBead *bi = dynamic_cast<QMBead*> (*iter);

        write<byte_t > (bi->getSymmetry());
        write<string > (bi->getName());
        write<string > (bi->getType()->getName());
        write<int>(bi->getResnr());
        write<double>(bi->getM());
        write<double>(bi->getQ());

        write<string > (bi->GetCrgUnit()->GetType()->GetName());
        write<unsigned short>(bi->getiPos());
        write<vec > (bi->getPos());
        write<vec > (bi->getU());
        write<vec > (bi->getV());
    }

}

void StateSaver::Load(string file) {
    _qmtop->Cleanup();
    _in.open(file.c_str(), ios::in | ios::binary);
    Read_QMBeads();
    //Read NBL
    _in.close();
}

void StateSaver::Read_QMBeads() {
    assert(_in.is_open());

    unsigned long nr_qmbeads = read<unsigned long>();
    cout << "Total number of QMBeads is " << nr_qmbeads << "\n";
    for (unsigned long i = 0; i < 1; i++) {

        byte_t symmetry = read<byte_t> ();
        string bead_name = read<string> ();
        string type_name = read<string> ();
        BeadType *type = _qmtop->GetOrCreateBeadType(type_name);
        int resnr = read<int>();
        double M = read<double>();
        double Q = read<double>();

        string crg_unit_name = read<string> ();
        unsigned short ipos = read<unsigned short>();
        vec Pos = read<vec> ();
        vec U = read<vec> ();
        vec V = read<vec> ();

        cout << "Bead Symmetry " << symmetry << "\n";
        cout << "Bead Name " << bead_name << "\n";
        cout << "Bead Type " << type_name << "\n";
        cout << "Residue Number " << resnr << "\n";
        cout << "Bead Mass " << M << "\n";
        cout << "Bead Charge " << Q << "\n";

        Bead *bead = _qmtop->CreateBead(symmetry, bead_name, type, resnr, M, Q);
        int molid = bead->getMolecule()->getId();
        string molandtype = lexical_cast<string > (molid) + ":" + crg_unit_name;
        cout << "molandtype " << molandtype << "\n";
        // CrgUnit * acrg = GetCrgUnitByName(molandtype);
        // if(acrg == NULL)
        //     acrg = CreateCrgUnit(molandtype, crg_unit_name, molid);

        // bead->setCrg(acrg);
        // bead->setPos(ipos);
        bead->setPos(Pos);
        bead->setU(U);
        bead->setV(V);

        cout << "The charge unit is called " << crg_unit_name << "\n";
        cout << "This bead is at int position " << ipos << "\n";
        cout << "This bead hast position  " << U << "\n";
        cout << "This bead has U " << U << "\n";
        cout << "This bead has V " << V << "\n";
                _in.close();
    }
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
All Rights Reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.
* Neither the name of Sony Pictures Imageworks nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <vector>
#include <string>
#include <cstdio>

#include <boost/foreach.hpp>
#include <boost/regex.hpp>

#include <OpenImageIO/dassert.h>
#include <OpenImageIO/sysutil.h>
#include <OpenImageIO/timer.h>
#include <OpenImageIO/thread.h>

#include "oslexec_pvt.h"

OSL_NAMESPACE_ENTER

static mutex buffered_errors_mutex;

ShadingContext::ShadingContext (ShadingSystemImpl &shadingsys,
                                PerThreadInfo *threadinfo)
    : m_shadingsys(shadingsys), m_renderer(m_shadingsys.renderer()),
      m_attribs(NULL), m_max_warnings(shadingsys.max_warnings_per_thread()), m_dictionary(NULL), m_next_failed_attrib(0)
{
    m_shadingsys.m_stat_contexts += 1;
    m_threadinfo = threadinfo ? threadinfo : shadingsys.get_perthread_info ();
}

ShadingContext::~ShadingContext ()
{
    process_errors ();
    m_shadingsys.m_stat_contexts -= 1;
    for (RegexMap::iterator it = m_regex_map.begin(); it != m_regex_map.end(); ++it) {
      delete it->second;
    }
    free_dict_resources ();
}

bool
ShadingContext::execute (ShaderGroup &sgroup, ShaderGlobals &ssg, bool run)
{
    m_attribs = &sgroup;

    // Optimize if we haven't already
    if (sgroup.nlayers()) {
        sgroup.start_running ();
        if (! sgroup.optimized()) {
            shadingsys().optimize_group (sgroup);
            if (shadingsys().m_greedyjit && shadingsys().m_groups_to_compile_count) {
                // If we are greedily JITing, optimize/JIT everything now
                shadingsys().optimize_all_groups ();
            }
        }
        if (sgroup.does_nothing())
            return false;
    } else {
       // empty shader - nothing to do!
       return false;
    }

    int profile = shadingsys().m_profile;
    OIIO::Timer timer (profile);

    // Allocate enough space on the heap
    size_t heap_size_needed = sgroup.llvm_groupdata_size();
    if (heap_size_needed > m_heap.size()) {
        if (shadingsys().debug())
            info ("  ShadingContext %p growing heap to %llu",
                  this, (unsigned long long) heap_size_needed);
        m_heap.resize (heap_size_needed);
    }
    // Zero out the heap memory we will be using
    if (shadingsys().m_clearmemory)
        memset (&m_heap[0], 0, heap_size_needed);

    // Set up closure storage
    m_closure_pool.clear();

    // Clear the message blackboard
    m_messages.clear ();

    // Clear miscellaneous scratch space
    m_scratch_pool.clear ();

    // Zero out stats for this execution
    clear_runtime_stats ();

    if (run) {
        ssg.context = this;
        ssg.renderer = renderer();
        ssg.Ci = NULL;
        RunLLVMGroupFunc run_func = sgroup.llvm_compiled_version();
        DASSERT (run_func);
        DASSERT (sgroup.llvm_groupdata_size() <= m_heap.size());
        run_func (&ssg, &m_heap[0]);
    }

    // Process any queued up error messages, warnings, printfs from shaders
    process_errors ();

    record_runtime_stats ();   // Transfer runtime stats to the shadingsys
    if (profile) {
        long long ticks = timer.ticks();
        shadingsys().m_stat_total_shading_time_ticks += ticks;
        sgroup.m_stat_total_shading_time_ticks += ticks;
    }

    return true;
}

void
ShadingContext::record_error (ErrorHandler::ErrCode code,
                              const std::string &text) const
{
    m_buffered_errors.push_back (ErrorItem(code,text));
    // If we aren't buffering, just process immediately
    if (! shadingsys().m_buffer_printf)
        process_errors ();
}

void
ShadingContext::process_errors () const
{
    size_t nerrors = m_buffered_errors.size();
    if (! nerrors)
        return;

    // Use a mutex to make sure output from different threads stays
    // together, at least for one shader invocation, rather than being
    // interleaved with other threads.
    lock_guard lock (buffered_errors_mutex);

    for (size_t i = 0;  i < nerrors;  ++i) {
        switch (m_buffered_errors[i].first) {
        case ErrorHandler::EH_MESSAGE :
        case ErrorHandler::EH_DEBUG :
           shadingsys().message (m_buffered_errors[i].second);
            break;
        case ErrorHandler::EH_INFO :
            shadingsys().info (m_buffered_errors[i].second);
            break;
        case ErrorHandler::EH_WARNING :
            shadingsys().warning (m_buffered_errors[i].second);
            break;
        case ErrorHandler::EH_ERROR :
        case ErrorHandler::EH_SEVERE :
            shadingsys().error (m_buffered_errors[i].second);
            break;
        default:
            break;
        }
    }
    m_buffered_errors.clear();
}

Symbol *
ShadingContext::symbol (ustring layername, ustring symbolname)
{
    ShaderGroup &sgroup (*attribs());
    int nlayers = sgroup.nlayers ();
    if (sgroup.llvm_compiled_version()) {
        for (int layer = nlayers-1;  layer >= 0;  --layer) {
            ShaderInstance *inst (sgroup[layer]);
            if (layername.size() && layername != inst->layername())
                continue;  // They asked for a specific layer and this isn't it
            int symidx = inst->findsymbol (symbolname);
            if (symidx >= 0)
                return inst->symbol (symidx);
        }
    }
    return NULL;
}

void *
ShadingContext::symbol_data (Symbol &sym)
{
    ShaderGroup &sgroup (*attribs());
    if (! sgroup.llvm_compiled_version())
        return NULL;   // can't retrieve symbol if we didn't JIT and runit

    if (sym.dataoffset() >= 0 && (int)m_heap.size() > sym.dataoffset()) {
        // lives on the heap
        return &m_heap[sym.dataoffset()];
    }

    // doesn't live on the heap
    if ((sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam) &&
        (sym.valuesource() == Symbol::DefaultVal || sym.valuesource() == Symbol::InstanceVal)) {
        ASSERT (sym.data());
        return sym.data() ? sym.data() : NULL;
    }

    return NULL;  // not something we can retrieve
}

const boost::regex &
ShadingContext::find_regex (ustring r)
{
    RegexMap::const_iterator found = m_regex_map.find (r);
    if (found != m_regex_map.end())
        return *found->second;
    // otherwise, it wasn't found, add it
    m_regex_map[r] = new boost::regex(r.c_str());
    m_shadingsys.m_stat_regexes += 1;
    // std::cerr << "Made new regex for " << r << "\n";
    return *m_regex_map[r];
}

bool
ShadingContext::osl_get_attribute (ShaderGlobals *sg, void *objdata,
                                   int dest_derivs,
                                   ustring obj_name, ustring attr_name,
                                   int array_lookup, int index,
                                   TypeDesc attr_type, void *attr_dest)
{
#if 0
    // Change the #if's below if you want to
    OIIO::Timer timer;
#endif
    bool ok;

    for (int i = 0;  i < FAILED_ATTRIBS;  ++i) {
        if ((obj_name || m_failed_attribs[i].objdata == objdata) &&
            m_failed_attribs[i].attr_name == attr_name &&
            m_failed_attribs[i].obj_name == obj_name &&
            m_failed_attribs[i].attr_type == attr_type &&
            m_failed_attribs[i].array_lookup == array_lookup &&
            m_failed_attribs[i].index == index &&
            m_failed_attribs[i].objdata) {
#if 0
            double time = timer();
            shadingsys().m_stat_getattribute_time += time;
            shadingsys().m_stat_getattribute_fail_time += time;
            shadingsys().m_stat_getattribute_calls += 1;
#endif
            return false;
        }
    }

    if (array_lookup)
        ok = renderer()->get_array_attribute (sg, dest_derivs,
                                              obj_name, attr_type,
                                              attr_name, index, attr_dest);
    else
        ok = renderer()->get_attribute (sg, dest_derivs,
                                        obj_name, attr_type,
                                        attr_name, attr_dest);
    if (!ok) {
        int i = m_next_failed_attrib;
        m_failed_attribs[i].objdata = objdata;
        m_failed_attribs[i].obj_name = obj_name;
        m_failed_attribs[i].attr_name = attr_name;
        m_failed_attribs[i].attr_type = attr_type;
        m_failed_attribs[i].array_lookup = array_lookup;
        m_failed_attribs[i].index = index;
        m_next_failed_attrib = (i == FAILED_ATTRIBS-1) ? 0 : (i+1);
    }

#if 0
    double time = timer();
    shadingsys().m_stat_getattribute_time += time;
    if (!ok)
        shadingsys().m_stat_getattribute_fail_time += time;
    shadingsys().m_stat_getattribute_calls += 1;
#endif
//    std::cout << "getattribute! '" << obj_name << "' " << attr_name << ' ' << attr_type.c_str() << " ok=" << ok << ", objdata was " << objdata << "\n";
    return ok;
}

OSL_SHADEOP void
osl_incr_layers_executed (ShaderGlobals *sg)
{
    ShadingContext *ctx = (ShadingContext *)sg->context;
    ctx->incr_layers_executed ();
}

OSL_NAMESPACE_EXIT
<commit_msg>Avoid incrementing profile related stats on every execution if profiling is disabled This fixes a performance regression that is particularly noticeable for small shaders executed from many threads<commit_after>/*
Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
All Rights Reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.
* Neither the name of Sony Pictures Imageworks nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <vector>
#include <string>
#include <cstdio>

#include <boost/foreach.hpp>
#include <boost/regex.hpp>

#include <OpenImageIO/dassert.h>
#include <OpenImageIO/sysutil.h>
#include <OpenImageIO/timer.h>
#include <OpenImageIO/thread.h>

#include "oslexec_pvt.h"

OSL_NAMESPACE_ENTER

static mutex buffered_errors_mutex;

ShadingContext::ShadingContext (ShadingSystemImpl &shadingsys,
                                PerThreadInfo *threadinfo)
    : m_shadingsys(shadingsys), m_renderer(m_shadingsys.renderer()),
      m_attribs(NULL), m_max_warnings(shadingsys.max_warnings_per_thread()), m_dictionary(NULL), m_next_failed_attrib(0)
{
    m_shadingsys.m_stat_contexts += 1;
    m_threadinfo = threadinfo ? threadinfo : shadingsys.get_perthread_info ();
}

ShadingContext::~ShadingContext ()
{
    process_errors ();
    m_shadingsys.m_stat_contexts -= 1;
    for (RegexMap::iterator it = m_regex_map.begin(); it != m_regex_map.end(); ++it) {
      delete it->second;
    }
    free_dict_resources ();
}

bool
ShadingContext::execute (ShaderGroup &sgroup, ShaderGlobals &ssg, bool run)
{
    m_attribs = &sgroup;

    // Optimize if we haven't already
    if (sgroup.nlayers()) {
        sgroup.start_running ();
        if (! sgroup.optimized()) {
            shadingsys().optimize_group (sgroup);
            if (shadingsys().m_greedyjit && shadingsys().m_groups_to_compile_count) {
                // If we are greedily JITing, optimize/JIT everything now
                shadingsys().optimize_all_groups ();
            }
        }
        if (sgroup.does_nothing())
            return false;
    } else {
       // empty shader - nothing to do!
       return false;
    }

    int profile = shadingsys().m_profile;
    OIIO::Timer timer (profile);

    // Allocate enough space on the heap
    size_t heap_size_needed = sgroup.llvm_groupdata_size();
    if (heap_size_needed > m_heap.size()) {
        if (shadingsys().debug())
            info ("  ShadingContext %p growing heap to %llu",
                  this, (unsigned long long) heap_size_needed);
        m_heap.resize (heap_size_needed);
    }
    // Zero out the heap memory we will be using
    if (shadingsys().m_clearmemory)
        memset (&m_heap[0], 0, heap_size_needed);

    // Set up closure storage
    m_closure_pool.clear();

    // Clear the message blackboard
    m_messages.clear ();

    // Clear miscellaneous scratch space
    m_scratch_pool.clear ();

    // Zero out stats for this execution
    clear_runtime_stats ();

    if (run) {
        ssg.context = this;
        ssg.renderer = renderer();
        ssg.Ci = NULL;
        RunLLVMGroupFunc run_func = sgroup.llvm_compiled_version();
        DASSERT (run_func);
        DASSERT (sgroup.llvm_groupdata_size() <= m_heap.size());
        run_func (&ssg, &m_heap[0]);
    }

    // Process any queued up error messages, warnings, printfs from shaders
    process_errors ();

    if (profile) {
        record_runtime_stats ();   // Transfer runtime stats to the shadingsys
        long long ticks = timer.ticks();
        shadingsys().m_stat_total_shading_time_ticks += ticks;
        sgroup.m_stat_total_shading_time_ticks += ticks;
    }

    return true;
}

void
ShadingContext::record_error (ErrorHandler::ErrCode code,
                              const std::string &text) const
{
    m_buffered_errors.push_back (ErrorItem(code,text));
    // If we aren't buffering, just process immediately
    if (! shadingsys().m_buffer_printf)
        process_errors ();
}

void
ShadingContext::process_errors () const
{
    size_t nerrors = m_buffered_errors.size();
    if (! nerrors)
        return;

    // Use a mutex to make sure output from different threads stays
    // together, at least for one shader invocation, rather than being
    // interleaved with other threads.
    lock_guard lock (buffered_errors_mutex);

    for (size_t i = 0;  i < nerrors;  ++i) {
        switch (m_buffered_errors[i].first) {
        case ErrorHandler::EH_MESSAGE :
        case ErrorHandler::EH_DEBUG :
           shadingsys().message (m_buffered_errors[i].second);
            break;
        case ErrorHandler::EH_INFO :
            shadingsys().info (m_buffered_errors[i].second);
            break;
        case ErrorHandler::EH_WARNING :
            shadingsys().warning (m_buffered_errors[i].second);
            break;
        case ErrorHandler::EH_ERROR :
        case ErrorHandler::EH_SEVERE :
            shadingsys().error (m_buffered_errors[i].second);
            break;
        default:
            break;
        }
    }
    m_buffered_errors.clear();
}

Symbol *
ShadingContext::symbol (ustring layername, ustring symbolname)
{
    ShaderGroup &sgroup (*attribs());
    int nlayers = sgroup.nlayers ();
    if (sgroup.llvm_compiled_version()) {
        for (int layer = nlayers-1;  layer >= 0;  --layer) {
            ShaderInstance *inst (sgroup[layer]);
            if (layername.size() && layername != inst->layername())
                continue;  // They asked for a specific layer and this isn't it
            int symidx = inst->findsymbol (symbolname);
            if (symidx >= 0)
                return inst->symbol (symidx);
        }
    }
    return NULL;
}

void *
ShadingContext::symbol_data (Symbol &sym)
{
    ShaderGroup &sgroup (*attribs());
    if (! sgroup.llvm_compiled_version())
        return NULL;   // can't retrieve symbol if we didn't JIT and runit

    if (sym.dataoffset() >= 0 && (int)m_heap.size() > sym.dataoffset()) {
        // lives on the heap
        return &m_heap[sym.dataoffset()];
    }

    // doesn't live on the heap
    if ((sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam) &&
        (sym.valuesource() == Symbol::DefaultVal || sym.valuesource() == Symbol::InstanceVal)) {
        ASSERT (sym.data());
        return sym.data() ? sym.data() : NULL;
    }

    return NULL;  // not something we can retrieve
}

const boost::regex &
ShadingContext::find_regex (ustring r)
{
    RegexMap::const_iterator found = m_regex_map.find (r);
    if (found != m_regex_map.end())
        return *found->second;
    // otherwise, it wasn't found, add it
    m_regex_map[r] = new boost::regex(r.c_str());
    m_shadingsys.m_stat_regexes += 1;
    // std::cerr << "Made new regex for " << r << "\n";
    return *m_regex_map[r];
}

bool
ShadingContext::osl_get_attribute (ShaderGlobals *sg, void *objdata,
                                   int dest_derivs,
                                   ustring obj_name, ustring attr_name,
                                   int array_lookup, int index,
                                   TypeDesc attr_type, void *attr_dest)
{
#if 0
    // Change the #if's below if you want to
    OIIO::Timer timer;
#endif
    bool ok;

    for (int i = 0;  i < FAILED_ATTRIBS;  ++i) {
        if ((obj_name || m_failed_attribs[i].objdata == objdata) &&
            m_failed_attribs[i].attr_name == attr_name &&
            m_failed_attribs[i].obj_name == obj_name &&
            m_failed_attribs[i].attr_type == attr_type &&
            m_failed_attribs[i].array_lookup == array_lookup &&
            m_failed_attribs[i].index == index &&
            m_failed_attribs[i].objdata) {
#if 0
            double time = timer();
            shadingsys().m_stat_getattribute_time += time;
            shadingsys().m_stat_getattribute_fail_time += time;
            shadingsys().m_stat_getattribute_calls += 1;
#endif
            return false;
        }
    }

    if (array_lookup)
        ok = renderer()->get_array_attribute (sg, dest_derivs,
                                              obj_name, attr_type,
                                              attr_name, index, attr_dest);
    else
        ok = renderer()->get_attribute (sg, dest_derivs,
                                        obj_name, attr_type,
                                        attr_name, attr_dest);
    if (!ok) {
        int i = m_next_failed_attrib;
        m_failed_attribs[i].objdata = objdata;
        m_failed_attribs[i].obj_name = obj_name;
        m_failed_attribs[i].attr_name = attr_name;
        m_failed_attribs[i].attr_type = attr_type;
        m_failed_attribs[i].array_lookup = array_lookup;
        m_failed_attribs[i].index = index;
        m_next_failed_attrib = (i == FAILED_ATTRIBS-1) ? 0 : (i+1);
    }

#if 0
    double time = timer();
    shadingsys().m_stat_getattribute_time += time;
    if (!ok)
        shadingsys().m_stat_getattribute_fail_time += time;
    shadingsys().m_stat_getattribute_calls += 1;
#endif
//    std::cout << "getattribute! '" << obj_name << "' " << attr_name << ' ' << attr_type.c_str() << " ok=" << ok << ", objdata was " << objdata << "\n";
    return ok;
}

OSL_SHADEOP void
osl_incr_layers_executed (ShaderGlobals *sg)
{
    ShadingContext *ctx = (ShadingContext *)sg->context;
    ctx->incr_layers_executed ();
}

OSL_NAMESPACE_EXIT
<|endoftext|>


<commit_before>/* Copyright (c) 2014, Fengping Bao <jamol@live.com>
 *
 * 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.
 */

#ifdef KUMA_HAS_OPENSSL

#include "OpenSslLib.h"
#include "util/kmtrace.h"
#include "util/util.h"

#include <string>
#include <thread>
#include <sstream>

KUMA_NS_BEGIN

SSL_CTX* OpenSslLib::ssl_ctx_client_ = NULL;
SSL_CTX* OpenSslLib::ssl_ctx_server_ = NULL;
std::mutex* OpenSslLib::ssl_locks_ = NULL;

bool OpenSslLib::init(const char* path)
{
    if(ssl_ctx_client_ || ssl_ctx_server_) {
        return true;
    }

    std::string cert_path;
    if(path == NULL) {
        cert_path = getCurrentModulePath();
    } else {
        cert_path = path;
        if(cert_path.empty()) {
            cert_path = getCurrentModulePath();
        } else if(cert_path.at(cert_path.length() - 1) != PATH_SEPARATOR) {
            cert_path += PATH_SEPARATOR;
        }
    }

    std::string server_cert_file = cert_path + "server.cer";
    std::string server_key_file = cert_path + "server.key";
    std::string client_cert_file;// = cert_path + "cleint.cer";
    std::string client_key_file;// = cert_path + "client.key";
    std::string ca_cert_file = cert_path + "ca.cer";

    SSL_library_init();
    //OpenSSL_add_all_algorithms();
    SSL_load_error_strings();

    bool server_ctx_ok = false;
    bool client_ctx_ok = false;
    do {
        ssl_ctx_server_ = SSL_CTX_new(SSLv23_server_method());
        if(NULL == ssl_ctx_server_) {
            KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_new failed, err="<<ERR_reason_error_string(ERR_get_error()));
            break;
        }

        if(!server_cert_file.empty() && !server_key_file.empty()) {
            if(SSL_CTX_use_certificate_file(ssl_ctx_server_, server_cert_file.c_str(), SSL_FILETYPE_PEM) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_certificate_file failed, file="<<server_cert_file
                               <<", err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
            if(SSL_CTX_use_PrivateKey_file(ssl_ctx_server_, server_key_file.c_str(), SSL_FILETYPE_PEM) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_PrivateKey_file failed, file:"<<server_key_file
                               <<", err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
            if(SSL_CTX_check_private_key(ssl_ctx_server_) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_check_private_key failed, err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
        }

        /*
         SSL_CTX_set_verify(ssl_ctx_client_, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyCallback);
         app_verify_arg arg0;
         SSL_CTX_set_cert_verify_callback(ssl_ctx_server_, appVerifyCallback, &arg0);

         int session_id_context = 1;
         if(SSL_CTX_set_session_id_context(ssl_ctx_server_, (unsigned char *)&session_id_context, sizeof(session_id_context)) != 1)
         {
         }
         */
        server_ctx_ok = true;
    } while(0);

    do {
        ssl_ctx_client_ = SSL_CTX_new(SSLv23_client_method());
        if(NULL == ssl_ctx_client_) {
            KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_new failed, err="<<ERR_reason_error_string(ERR_get_error()));
            break;
        }

        // set AES256_SHA cipher for client.
        //if(SSL_CTX_set_cipher_list(ssl_ctx_client_,"AES256-SHA") != 1)
        //{
        //	KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_set_cipher_list failed, err="<<ERR_reason_error_string(ERR_get_error()));
        //}

        if(!client_cert_file.empty() && !client_key_file.empty()) {
            if(SSL_CTX_use_certificate_file(ssl_ctx_client_, client_cert_file.c_str(), SSL_FILETYPE_PEM) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_certificate_file failed, file="<<client_cert_file
                               <<", err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
            if(SSL_CTX_use_PrivateKey_file(ssl_ctx_client_, client_key_file.c_str(), SSL_FILETYPE_PEM) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_PrivateKey_file failed, file="<<client_key_file
                               <<", err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
            if(SSL_CTX_check_private_key(ssl_ctx_client_) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_check_private_key failed, err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
        }

        if(!ca_cert_file.empty() &&
           SSL_CTX_load_verify_locations(ssl_ctx_client_, ca_cert_file.c_str(), NULL) != 1) {
            KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_load_verify_locations failed, file="<<ca_cert_file
                           <<", err="<<ERR_reason_error_string(ERR_get_error()));
            break;
        }
        if(SSL_CTX_set_default_verify_paths(ssl_ctx_client_) != 1) {
            KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_set_default_verify_paths failed, err="
                           <<ERR_reason_error_string(ERR_get_error()));
            break;
        }
        SSL_CTX_set_verify(ssl_ctx_client_, SSL_VERIFY_PEER, verifyCallback);
        //app_verify_arg arg1;
        //SSL_CTX_set_cert_verify_callback(ssl_ctx_client_, appVerifyCallback, &arg1);
        client_ctx_ok = true;
    } while(0);

    if(!server_ctx_ok && ssl_ctx_server_) {
        SSL_CTX_free(ssl_ctx_server_);
        ssl_ctx_server_ = NULL;
    }
    if(!client_ctx_ok && ssl_ctx_client_) {
        SSL_CTX_free(ssl_ctx_client_);
        ssl_ctx_client_ = NULL;
    }
    if(!server_ctx_ok && !client_ctx_ok) {
        return false;
    }

    ssl_locks_ = new std::mutex[CRYPTO_num_locks()];
    CRYPTO_set_id_callback(threadIdCallback);
    CRYPTO_set_locking_callback(lockingCallback);

    // PRNG
    RAND_poll();
    while(RAND_status() == 0) {
        unsigned short rand_ret = rand() % 65536;
        RAND_seed(&rand_ret, sizeof(rand_ret));
    }

    return true;
}

void OpenSslLib::fini()
{

}

struct app_verify_arg
{
    char *string;
    int app_verify;
    int allow_proxy_certs;
    char *proxy_auth;
    char *proxy_cond;
};

int OpenSslLib::verifyCallback(int ok, X509_STORE_CTX *ctx)
{
    if(NULL == ctx) {
        return -1;
    }
    if(ctx->current_cert) {
        char *s, buf[1024];
        s = X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof(buf));
        if(s != NULL) {
            if(ok) {
                KUMA_INFOTRACE("verifyCallback ok, depth="<<ctx->error_depth<<", subject="<<buf);
                if(X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, sizeof(buf))) {
                    KUMA_INFOTRACE("verifyCallback, issuer="<<buf);
                }
            } else {
                KUMA_ERRTRACE("verifyCallback failed, depth="<<ctx->error_depth
                              <<", err="<<ctx->error<<", subject="<<buf);
            }
        }
    }

    if (0 == ok) {
        KUMA_INFOTRACE("verifyCallback, err="<<X509_verify_cert_error_string(ctx->error));
        switch (ctx->error)
        {
                //case X509_V_ERR_CERT_NOT_YET_VALID:
                //case X509_V_ERR_CERT_HAS_EXPIRED:
            case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
                KUMA_INFOTRACE("verifyCallback, ... ignored, err="<<ctx->error);
                ok = 1;
                break;
        }
    }

    return ok;
}

int OpenSslLib::appVerifyCallback(X509_STORE_CTX *ctx, void *arg)
{
    if(!ctx || !arg) {
        return -1;
    }

    int ok = 1;
    struct app_verify_arg *cb_arg = (struct app_verify_arg *)arg;

    if (cb_arg->app_verify) {
        char *s = NULL, buf[256];
        if(ctx->cert) {
            s = X509_NAME_oneline(X509_get_subject_name(ctx->cert), buf, 256);
        }
        if(s != NULL) {
            KUMA_INFOTRACE("appVerifyCallback, depth="<<ctx->error_depth<<", "<<buf);
        }
        return 1;
    }

    ok = X509_verify_cert(ctx);

    return ok;
}

unsigned long OpenSslLib::threadIdCallback(void)
{
#if 0
    unsigned long ret = 0;
    std::thread::id thread_id = std::this_thread::get_id();
    std::stringstream ss;
    ss << thread_id;
    ss >> ret;
    return ret;
#else
    return getCurrentThreadId();
#endif
}

void OpenSslLib::lockingCallback(int mode, int n, const char *file, int line)
{
    if (mode & CRYPTO_LOCK) {
        ssl_locks_[n].lock();
    }
    else {
        ssl_locks_[n].unlock();
    }
}

KUMA_NS_END

#endif // KUMA_HAS_OPENSSL
<commit_msg>disable SSLv2<commit_after>/* Copyright (c) 2014, Fengping Bao <jamol@live.com>
 *
 * 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.
 */

#ifdef KUMA_HAS_OPENSSL

#include "OpenSslLib.h"
#include "util/kmtrace.h"
#include "util/util.h"

#include <string>
#include <thread>
#include <sstream>

KUMA_NS_BEGIN

SSL_CTX* OpenSslLib::ssl_ctx_client_ = NULL;
SSL_CTX* OpenSslLib::ssl_ctx_server_ = NULL;
std::mutex* OpenSslLib::ssl_locks_ = NULL;

bool OpenSslLib::init(const char* path)
{
    if(ssl_ctx_client_ || ssl_ctx_server_) {
        return true;
    }

    std::string cert_path;
    if(path == NULL) {
        cert_path = getCurrentModulePath();
    } else {
        cert_path = path;
        if(cert_path.empty()) {
            cert_path = getCurrentModulePath();
        } else if(cert_path.at(cert_path.length() - 1) != PATH_SEPARATOR) {
            cert_path += PATH_SEPARATOR;
        }
    }

    std::string server_cert_file = cert_path + "server.cer";
    std::string server_key_file = cert_path + "server.key";
    std::string client_cert_file;// = cert_path + "cleint.cer";
    std::string client_key_file;// = cert_path + "client.key";
    std::string ca_cert_file = cert_path + "ca.cer";

    SSL_library_init();
    //OpenSSL_add_all_algorithms();
    SSL_load_error_strings();

    bool server_ctx_ok = false;
    bool client_ctx_ok = false;
    do {
        ssl_ctx_server_ = SSL_CTX_new(SSLv23_server_method());
        if(NULL == ssl_ctx_server_) {
            KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_new failed, err="<<ERR_reason_error_string(ERR_get_error()));
            break;
        }

        //const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
        //SSL_CTX_set_options(ssl_ctx_server_, flags);
        SSL_CTX_set_options(ssl_ctx_server_, SSL_OP_NO_SSLv2);

        if(!server_cert_file.empty() && !server_key_file.empty()) {
            if(SSL_CTX_use_certificate_file(ssl_ctx_server_, server_cert_file.c_str(), SSL_FILETYPE_PEM) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_certificate_file failed, file="<<server_cert_file
                               <<", err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
            if(SSL_CTX_use_PrivateKey_file(ssl_ctx_server_, server_key_file.c_str(), SSL_FILETYPE_PEM) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_PrivateKey_file failed, file:"<<server_key_file
                               <<", err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
            if(SSL_CTX_check_private_key(ssl_ctx_server_) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_check_private_key failed, err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
        }

        /*
         SSL_CTX_set_verify(ssl_ctx_client_, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyCallback);
         app_verify_arg arg0;
         SSL_CTX_set_cert_verify_callback(ssl_ctx_server_, appVerifyCallback, &arg0);

         int session_id_context = 1;
         if(SSL_CTX_set_session_id_context(ssl_ctx_server_, (unsigned char *)&session_id_context, sizeof(session_id_context)) != 1)
         {
         }
         */
        server_ctx_ok = true;
    } while(0);

    do {
        ssl_ctx_client_ = SSL_CTX_new(SSLv23_client_method());
        if(NULL == ssl_ctx_client_) {
            KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_new failed, err="<<ERR_reason_error_string(ERR_get_error()));
            break;
        }

        SSL_CTX_set_verify(ssl_ctx_client_, SSL_VERIFY_PEER, verifyCallback);
        //SSL_CTX_set_verify_depth(ssl_ctx_client_, 4);
        //app_verify_arg arg1;
        //SSL_CTX_set_cert_verify_callback(ssl_ctx_client_, appVerifyCallback, &arg1);

        //const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
        //SSL_CTX_set_options(ssl_ctx_client_, flags);
        SSL_CTX_set_options(ssl_ctx_client_, SSL_OP_NO_SSLv2);

        // set AES256_SHA cipher for client.
        //if(SSL_CTX_set_cipher_list(ssl_ctx_client_,"AES256-SHA") != 1)
        //{
        //	KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_set_cipher_list failed, err="<<ERR_reason_error_string(ERR_get_error()));
        //}

        if(!client_cert_file.empty() && !client_key_file.empty()) {
            if(SSL_CTX_use_certificate_file(ssl_ctx_client_, client_cert_file.c_str(), SSL_FILETYPE_PEM) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_certificate_file failed, file="<<client_cert_file
                               <<", err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
            if(SSL_CTX_use_PrivateKey_file(ssl_ctx_client_, client_key_file.c_str(), SSL_FILETYPE_PEM) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_PrivateKey_file failed, file="<<client_key_file
                               <<", err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
            if(SSL_CTX_check_private_key(ssl_ctx_client_) != 1) {
                KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_check_private_key failed, err="<<ERR_reason_error_string(ERR_get_error()));
                break;
            }
        }

        if(!ca_cert_file.empty() &&
           SSL_CTX_load_verify_locations(ssl_ctx_client_, ca_cert_file.c_str(), NULL) != 1) {
            KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_load_verify_locations failed, file="<<ca_cert_file
                           <<", err="<<ERR_reason_error_string(ERR_get_error()));
            break;
        }
        if(SSL_CTX_set_default_verify_paths(ssl_ctx_client_) != 1) {
            KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_set_default_verify_paths failed, err="
                           <<ERR_reason_error_string(ERR_get_error()));
            break;
        }
        client_ctx_ok = true;
    } while(0);

    if(!server_ctx_ok && ssl_ctx_server_) {
        SSL_CTX_free(ssl_ctx_server_);
        ssl_ctx_server_ = NULL;
    }
    if(!client_ctx_ok && ssl_ctx_client_) {
        SSL_CTX_free(ssl_ctx_client_);
        ssl_ctx_client_ = NULL;
    }
    if(!server_ctx_ok && !client_ctx_ok) {
        return false;
    }

    ssl_locks_ = new std::mutex[CRYPTO_num_locks()];
    CRYPTO_set_id_callback(threadIdCallback);
    CRYPTO_set_locking_callback(lockingCallback);

    // PRNG
    RAND_poll();
    while(RAND_status() == 0) {
        unsigned short rand_ret = rand() % 65536;
        RAND_seed(&rand_ret, sizeof(rand_ret));
    }

    return true;
}

void OpenSslLib::fini()
{

}

struct app_verify_arg
{
    char *string;
    int app_verify;
    int allow_proxy_certs;
    char *proxy_auth;
    char *proxy_cond;
};

int OpenSslLib::verifyCallback(int ok, X509_STORE_CTX *ctx)
{
    if(NULL == ctx) {
        return -1;
    }
    if(ctx->current_cert) {
        char *s, buf[1024];
        s = X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof(buf));
        if(s != NULL) {
            if(ok) {
                KUMA_INFOTRACE("verifyCallback ok, depth="<<ctx->error_depth<<", subject="<<buf);
                if(X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, sizeof(buf))) {
                    KUMA_INFOTRACE("verifyCallback, issuer="<<buf);
                }
            } else {
                KUMA_ERRTRACE("verifyCallback failed, depth="<<ctx->error_depth
                              <<", err="<<ctx->error<<", subject="<<buf);
            }
        }
    }

    if (0 == ok) {
        KUMA_INFOTRACE("verifyCallback, err="<<X509_verify_cert_error_string(ctx->error));
        switch (ctx->error)
        {
                //case X509_V_ERR_CERT_NOT_YET_VALID:
                //case X509_V_ERR_CERT_HAS_EXPIRED:
            case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
                KUMA_INFOTRACE("verifyCallback, ... ignored, err="<<ctx->error);
                ok = 1;
                break;
        }
    }

    return ok;
}

int OpenSslLib::appVerifyCallback(X509_STORE_CTX *ctx, void *arg)
{
    if(!ctx || !arg) {
        return -1;
    }

    int ok = 1;
    struct app_verify_arg *cb_arg = (struct app_verify_arg *)arg;

    if (cb_arg->app_verify) {
        char *s = NULL, buf[256];
        if(ctx->cert) {
            s = X509_NAME_oneline(X509_get_subject_name(ctx->cert), buf, 256);
        }
        if(s != NULL) {
            KUMA_INFOTRACE("appVerifyCallback, depth="<<ctx->error_depth<<", "<<buf);
        }
        return 1;
    }

    ok = X509_verify_cert(ctx);

    return ok;
}

unsigned long OpenSslLib::threadIdCallback(void)
{
#if 0
    unsigned long ret = 0;
    std::thread::id thread_id = std::this_thread::get_id();
    std::stringstream ss;
    ss << thread_id;
    ss >> ret;
    return ret;
#else
    return getCurrentThreadId();
#endif
}

void OpenSslLib::lockingCallback(int mode, int n, const char *file, int line)
{
    if (mode & CRYPTO_LOCK) {
        ssl_locks_[n].lock();
    }
    else {
        ssl_locks_[n].unlock();
    }
}

KUMA_NS_END

#endif // KUMA_HAS_OPENSSL
<|endoftext|>


<commit_before>/*
  Copyright 2007 Albert Strasheim <fullung@gmail.com>

  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 <boost/python/class.hpp>

#include <cms/StreamMessage.h>

namespace py = boost::python;

using cms::StreamMessage;
using cms::Message;

void export_StreamMessage()
{
    py::class_<StreamMessage, py::bases<Message>, boost::noncopyable>("StreamMessage", py::no_init);
}
<commit_msg>Wrapped easy parts of StreamMessage.<commit_after>/*
  Copyright 2007 Albert Strasheim <fullung@gmail.com>

  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 <boost/python/class.hpp>

#include <cms/StreamMessage.h>

namespace py = boost::python;

using cms::StreamMessage;
using cms::Message;

void export_StreamMessage()
{
    py::class_<StreamMessage, py::bases<Message>, boost::noncopyable>("StreamMessage", py::no_init)
        .def("readBoolean", &StreamMessage::readBoolean)
        .def("writeBoolean", &StreamMessage::writeBoolean)
        .def("readByte", &StreamMessage::readByte)
        .def("writeByte", &StreamMessage::writeByte)
#if 0
        .def("readBytes", &StreamMessage::readBytes)
        .def("writeBytes", &StreamMessage::writeBytes)
#endif
        .def("readChar", &StreamMessage::readChar)
        .def("writeChar", &StreamMessage::writeChar)
        .def("readFloat", &StreamMessage::readFloat)
        .def("writeFloat", &StreamMessage::writeFloat)
        .def("readDouble", &StreamMessage::readDouble)
        .def("writeDouble", &StreamMessage::writeDouble)
        .def("readShort", &StreamMessage::readShort)
        .def("writeShort", &StreamMessage::writeShort)
        .def("readUnsignedShort", &StreamMessage::readUnsignedShort)
        .def("writeUnsignedShort", &StreamMessage::writeUnsignedShort)
        .def("readInt", &StreamMessage::readInt)
        .def("writeInt", &StreamMessage::writeInt)
        .def("readLong", &StreamMessage::readLong)
        .def("writeLong", &StreamMessage::writeLong)
        .def("readString", &StreamMessage::readString)
        .def("writeString", &StreamMessage::writeString)
        ;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <test/fuzz/fuzz.h>

#include <cstdint>
#include <unistd.h>
#include <vector>

static bool read_stdin(std::vector<uint8_t>& data)
{
    uint8_t buffer[1024];
    ssize_t length = 0;
    while ((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
        data.insert(data.end(), buffer, buffer + length);

        if (data.size() > (1 << 20)) return false;
    }
    return length == 0;
}

// Default initialization: Override using a non-weak initialize().
__attribute__((weak)) void initialize()
{
}

// This function is used by libFuzzer
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
    const std::vector<uint8_t> input(data, data + size);
    test_one_input(input);
    return 0;
}

// This function is used by libFuzzer
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
{
    initialize();
    return 0;
}

// Disabled under WIN32 due to clash with Cygwin's WinMain.
#ifndef WIN32
// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides
// the main(...) function.
__attribute__((weak))
#endif
int
main(int argc, char** argv)
{
    initialize();
#ifdef __AFL_INIT
    // Enable AFL deferred forkserver mode. Requires compilation using
    // afl-clang-fast++. See fuzzing.md for details.
    __AFL_INIT();
#endif

#ifdef __AFL_LOOP
    // Enable AFL persistent mode. Requires compilation using afl-clang-fast++.
    // See fuzzing.md for details.
    while (__AFL_LOOP(1000)) {
        std::vector<uint8_t> buffer;
        if (!read_stdin(buffer)) {
            continue;
        }
        test_one_input(buffer);
    }
#else
    std::vector<uint8_t> buffer;
    if (!read_stdin(buffer)) {
        return 0;
    }
    test_one_input(buffer);
#endif
    return 0;
}
<commit_msg>tests: Remove Cygwin WinMain workaround<commit_after>// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <test/fuzz/fuzz.h>

#include <cstdint>
#include <unistd.h>
#include <vector>

static bool read_stdin(std::vector<uint8_t>& data)
{
    uint8_t buffer[1024];
    ssize_t length = 0;
    while ((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
        data.insert(data.end(), buffer, buffer + length);

        if (data.size() > (1 << 20)) return false;
    }
    return length == 0;
}

// Default initialization: Override using a non-weak initialize().
__attribute__((weak)) void initialize()
{
}

// This function is used by libFuzzer
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
    const std::vector<uint8_t> input(data, data + size);
    test_one_input(input);
    return 0;
}

// This function is used by libFuzzer
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
{
    initialize();
    return 0;
}

// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides
// the main(...) function.
__attribute__((weak)) int main(int argc, char** argv)
{
    initialize();
#ifdef __AFL_INIT
    // Enable AFL deferred forkserver mode. Requires compilation using
    // afl-clang-fast++. See fuzzing.md for details.
    __AFL_INIT();
#endif

#ifdef __AFL_LOOP
    // Enable AFL persistent mode. Requires compilation using afl-clang-fast++.
    // See fuzzing.md for details.
    while (__AFL_LOOP(1000)) {
        std::vector<uint8_t> buffer;
        if (!read_stdin(buffer)) {
            continue;
        }
        test_one_input(buffer);
    }
#else
    std::vector<uint8_t> buffer;
    if (!read_stdin(buffer)) {
        return 0;
    }
    test_one_input(buffer);
#endif
    return 0;
}
<|endoftext|>