<commit_before>#include "mpx2bits.h"

#include <complex>
#include <deque>

#include "liquid_wrappers.h"

#define FS        228000.0f
#define FC_0      57000.0f
#define IBUFLEN   4096
#define OBUFLEN   128
#define BITBUFLEN 1024

#define PI_f      3.1415926535898f
#define PI_2_f    1.5707963267949f

namespace redsea {

namespace {

  int sign(float x) {
    return (x >= 0);
  }
}

float phaseDiff(std::complex<float> a, std::complex<float> b) {
  float dph = arg(b) - arg(a);
  if (dph > M_PI)
    dph -= 2*M_PI;
  if (dph < -M_PI)
    dph += 2*M_PI;
  dph = fabs(dph) - M_PI_2;
  return dph;
}

RunningSum::RunningSum(int len) : values_(len), len_(len), i_(0), max_i_(0),
  last_max_i_(0) {
}

RunningSum::~RunningSum() {
}

float RunningSum::pushAndRead(float s) {
  sum_ += s;
  sum_ -= values_[i_];
  values_[i_] = s;

  if (fabs(sum_) > max_sum_) {
    max_i_ = i_;
    max_sum_ = fabs(sum_);
  }

  i_ = (i_ + 1) % len_;

  if (i_ == max_i_) {
    last_max_i_ = max_i_;
    max_sum_ = sum_;
    max_i_ = i_;
  }

  return sum_;
}

int RunningSum::lastMaxIndex() const {
  return last_max_i_;
}

DeltaDecoder::DeltaDecoder() : prev_(0) {

}

DeltaDecoder::~DeltaDecoder() {

}

unsigned DeltaDecoder::decode(unsigned d) {
  unsigned bit = (d != prev_);
  prev_ = d;
  return bit;
}

DPSK::DPSK() : subcarr_freq_(FC_0), gain_(1.0f),
  counter_(0), tot_errs_(2), reading_frame_(0), bit_buffer_(),
  fir_lpf_(511, 2100.0f / FS),
  fir_phase_(63, 1500.0 / FS * 12),
  is_eof_(false),
  agc_(0.001f),
  nco_if_(FC_0 * 2 * PI_f / FS),
  nco_doublerate_(1187.5 * 2 * 2 * PI_f / FS),
  ph0_(0.0f), sym_delay_(wdelaycf_create(17)),
  clock_shift_(0), clock_phase_(0), last_rising_at_(0), lastbit_(0),
  running_sum_(16), symsync_(symsync_crcf_create_rnyquist(LIQUID_FIRFILT_RRC, 2,
        5, 0.5f, 32)),
  prev_dphc_(0.0f)
  {

    symsync_crcf_set_lf_bw(symsync_, 0.02f);
    symsync_crcf_set_output_rate(symsync_,2);

}

DPSK::~DPSK() {
}

void DPSK::demodulateMoreBits() {

  int16_t sample[IBUFLEN];
  int samplesread = fread(sample, sizeof(int16_t), IBUFLEN, stdin);
  if (samplesread < IBUFLEN) {
    is_eof_ = true;
    return;
  }

  for (int i = 0; i < samplesread; i++) {

    std::complex<float> sample_down = nco_if_.mixDown(sample[i]);

    fir_lpf_.push(sample_down);
    std::complex<float> sample_shaped_unnorm = fir_lpf_.execute();

    std::complex<float> sample_shaped = agc_.execute(sample_shaped_unnorm);

    std::complex<double> sq = std::pow(sample_shaped, 2);
    //printf("pe:%.10f,%.10f\n",real(sq),imag(sq));

    if (numsamples_ % 12 == 0) {

      std::complex<float> sym0;
      wdelaycf_push(sym_delay_, sample_shaped);
      wdelaycf_read(sym_delay_, &sym0);
      float dph = phaseDiff(sample_shaped, sym0);
      std::complex<float> dphc(dph,0),dphc_lpf;

      //printf("pe:%f,%f\n",real(sq)*1000,imag(sq)*1000);

      fir_phase_.push(dphc);
      dphc_lpf = fir_phase_.execute();

      //printf("pe:%f,%f\n",real(dphc),imag(dphc));

      if (sign(real(dphc_lpf)) != sign(real(prev_dphc_))) {
        float fractional_zc = clock_phase_ - 1 +
          (-real(prev_dphc_)) / (real(dphc_lpf) - real(prev_dphc_));
        //printf("zc:%d,%f\n",numsamples_,fractional_zc);
        clock_shift_ += (fractional_zc > 7.0f ? -1 : 1) * 0.00003;

      }

      prev_dphc_ = dphc_lpf;

      float bval = running_sum_.pushAndRead(real(dphc_lpf));

      if (clock_phase_ == 0) {
        unsigned bit = sign(bval);
        bit_buffer_.push_back(bit);
        //printf("lmi:%d\n",running_sum_.lastMaxIndex());
      }
      //printf("g:%d,%f\n",clock_phase_,fabs(bval));

      clock_phase_ = int(clock_phase_ + 1 + clock_shift_ + .5) % 16;

    }

    nco_if_.step();

    numsamples_ ++;

  }

}

int DPSK::getNextBit() {
  while (bit_buffer_.size() < 1 && !isEOF())
    demodulateMoreBits();

  int bit = 0;

  if (bit_buffer_.size() > 0) {
    bit = bit_buffer_.front();
    bit_buffer_.pop_front();
  }

  return bit;
}

bool DPSK::isEOF() const {
  return is_eof_;
}

AsciiBits::AsciiBits() : is_eof_(false) {

}

AsciiBits::~AsciiBits() {

}

int AsciiBits::getNextBit() {
  int result = 0;
  while (result != '0' && result != '1' && result != EOF)
    result = getchar();

  if (result == EOF) {
    is_eof_ = true;
    return 0;
  }

  return (result == '1');

}

bool AsciiBits::isEOF() const {
  return is_eof_;
}

} // namespace redsea
<commit_msg>reimplement decoder using liquid symsync<commit_after>#include "mpx2bits.h"

#include <complex>
#include <deque>

#include "liquid_wrappers.h"

#define FS        228000.0f
#define FC_0      57000.0f
#define IBUFLEN   4096
#define OBUFLEN   128
#define BITBUFLEN 1024

#define PI_f      3.1415926535898f
#define PI_2_f    1.5707963267949f

namespace redsea {

namespace {

  int sign(float x) {
    return (x >= 0);
  }
}

float phaseDiff(std::complex<float> a, std::complex<float> b) {
  float dph = arg(b) - arg(a);
  if (dph > M_PI)
    dph -= 2*M_PI;
  if (dph < -M_PI)
    dph += 2*M_PI;
  dph = fabs(dph) - M_PI_2;
  return dph;
}

RunningSum::RunningSum(int len) : values_(len), len_(len), i_(0), max_i_(0),
  last_max_i_(0) {
}

RunningSum::~RunningSum() {
}

float RunningSum::pushAndRead(float s) {
  sum_ += s;
  sum_ -= values_[i_];
  values_[i_] = s;

  if (fabs(sum_) > max_sum_) {
    max_i_ = i_;
    max_sum_ = fabs(sum_);
  }

  i_ = (i_ + 1) % len_;

  if (i_ == max_i_) {
    last_max_i_ = max_i_;
    max_sum_ = sum_;
    max_i_ = i_;
  }

  return sum_;
}

int RunningSum::lastMaxIndex() const {
  return last_max_i_;
}

DeltaDecoder::DeltaDecoder() : prev_(0) {

}

DeltaDecoder::~DeltaDecoder() {

}

unsigned DeltaDecoder::decode(unsigned d) {
  unsigned bit = (d != prev_);
  prev_ = d;
  return bit;
}

DPSK::DPSK() : subcarr_freq_(FC_0), gain_(1.0f),
  counter_(0), tot_errs_(2), reading_frame_(0), bit_buffer_(),
  fir_lpf_(511, 2100.0f / FS),
  is_eof_(false),
  agc_(0.001f),
  nco_if_(FC_0 * 2 * PI_f / FS),
  nco_carrier_(0.0f),//FC_0 * 2 * PI_f / FS),
  symsync_(LIQUID_FIRFILT_RRC, 2, 5, 0.5f, 32),
  modem_(LIQUID_MODEM_DPSK2),
  prev_sym_(0), sym_clk_(0),
  biphase_(0), prev_biphase_(0)
  {

    symsync_.setBandwidth(0.02f);
    symsync_.setOutputRate(1);
    nco_carrier_.setPLLBandwidth(0.0004f);

}

DPSK::~DPSK() {
}

void DPSK::demodulateMoreBits() {

  int16_t sample[IBUFLEN];
  int samplesread = fread(sample, sizeof(int16_t), IBUFLEN, stdin);
  if (samplesread < IBUFLEN) {
    is_eof_ = true;
    return;
  }

  for (int i = 0; i < samplesread; i++) {

    std::complex<float> sample_down = nco_if_.mixDown(sample[i]);

    fir_lpf_.push(sample_down);
    std::complex<float> sample_shaped_unnorm = fir_lpf_.execute();

    std::complex<float> sample_shaped = agc_.execute(sample_shaped_unnorm);

    //std::complex<float> sample_bp = nco_if_.mixUp(sample_shaped);
    //std::complex<float> sample_pll = nco_carrier_.mixDown(sample_bp);

    //printf("pe:%.10f,%.10f\n",real(sample_bp), imag(sample_bp));

      //printf("pe:%.10f,%.10f\n",real(sample_pll),imag(sample_pll));
    if (numsamples_ % 48 == 0) {
      std::vector<std::complex<float>> y;
      y = symsync_.execute(sample_shaped);
      for (auto sy : y) {
        unsigned u = modem_.demodulate(sy);
        nco_carrier_.stepPLL(modem_.getPhaseError());
        biphase_ ^= u;

        if (sym_clk_ == 1) {

          if (prev_biphase_ == 0 && biphase_ == 1) {
            bit_buffer_.push_back(delta_decoder_.decode(1));
          }
          if (prev_biphase_ == 1 && biphase_ == 0) {
            bit_buffer_.push_back(delta_decoder_.decode(0));
          }
        }

        if (prev_biphase_ == biphase_)
          sym_clk_ = 0;

        prev_biphase_ = biphase_;

        sym_clk_ = (sym_clk_ + 1) % 2;

      }
    }

    nco_if_.step();
    nco_carrier_.step();

    numsamples_ ++;

  }

}

int DPSK::getNextBit() {
  while (bit_buffer_.size() < 1 && !isEOF())
    demodulateMoreBits();

  int bit = 0;

  if (bit_buffer_.size() > 0) {
    bit = bit_buffer_.front();
    bit_buffer_.pop_front();
  }

  return bit;
}

bool DPSK::isEOF() const {
  return is_eof_;
}

AsciiBits::AsciiBits() : is_eof_(false) {

}

AsciiBits::~AsciiBits() {

}

int AsciiBits::getNextBit() {
  int result = 0;
  while (result != '0' && result != '1' && result != EOF)
    result = getchar();

  if (result == EOF) {
    is_eof_ = true;
    return 0;
  }

  return (result == '1');

}

bool AsciiBits::isEOF() const {
  return is_eof_;
}

} // namespace redsea
<|endoftext|>


<commit_before>#include <string>
#include <stdlib.h>
#include <sstream>

#include "../USB.h"
#include "../configuration.h"

extern HINSTANCE hInst;
std::wstring IniDir;
std::wstring LogDir;

void CALLBACK USBsetSettingsDir( const char* dir )
{
	OSDebugOut(L"USBsetSettingsDir: %S\n", dir);
	wchar_t dst[4096] = {0};
	size_t num = 0;
	mbstowcs_s(&num, dst, dir, ARRAYSIZE(dst));
	IniDir = dst;
}

void CALLBACK USBsetLogDir( const char* dir )
{
	OSDebugOut(L"USBsetLogDir: %S\n", dir);
	wchar_t dst[4096] = {0};
	size_t num = 0;
	mbstowcs_s(&num, dst, dir, ARRAYSIZE(dst));
	LogDir = dst;
}

//TODO Use \\?\ to go past 260 char limit
void GetIniFile(std::wstring &iniFile)
{
	iniFile.clear();
	if(!IniDir.length()) {
		WCHAR tmp[MAX_PATH] = {0};
		GetModuleFileName(GetModuleHandle((LPWSTR)hInst), tmp, MAX_PATH);

		std::wstring path(tmp);
		unsigned last = path.find_last_of(L"\\");
		iniFile = path.substr(0, last);
		iniFile.append(L"\\inis");
		CreateDirectory(iniFile.c_str(), NULL);
		iniFile.append(L"\\USBqemu-wheel.ini");
	} else {
		iniFile.append(IniDir);
		iniFile.append(L"USBqemu-wheel.ini");
	}
}

bool LoadSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, std::string& value)
{
	wchar_t tmp[4096] = { 0 };
	if (!GetPrivateProfileStringW(section.c_str(), param, NULL, tmp, sizeof(tmp) / sizeof(*tmp), ini.c_str()))
		return false;
	if (GetLastError() == ERROR_FILE_NOT_FOUND)
		return false;

	char tmpA[4096] = { 0 };
	size_t num = 0;
	wcstombs_s(&num, tmpA, tmp, sizeof(tmpA)); //TODO error-check
	value = tmpA;
	return true;
}

bool LoadSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, std::wstring& value)
{
	wchar_t tmp[4096] = { 0 };
	if (!GetPrivateProfileStringW(section.c_str(), param, NULL, tmp, sizeof(tmp) / sizeof(*tmp), ini.c_str()))
		return false;
	if (GetLastError() == ERROR_FILE_NOT_FOUND)
		return false;
	value = tmp;
	return true;
}

bool LoadSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, bool& value)
{
	//value = GetPrivateProfileIntW(section.c_str(), param, 0, ini.c_str());
	wchar_t tmp[4096] = { 0 };
	if (!GetPrivateProfileStringW(section.c_str(), param, NULL, tmp, sizeof(tmp) / sizeof(*tmp), ini.c_str()))
		return false;
	if (GetLastError() == ERROR_FILE_NOT_FOUND)
		return false;
	value = !!wcstoul(tmp, NULL, 10);
	return true;
}

bool LoadSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, int32_t& value)
{
	//value = GetPrivateProfileIntW(section.c_str(), param, 0, ini.c_str());
	wchar_t tmp[4096] = { 0 };
	if (!GetPrivateProfileStringW(section.c_str(), param, NULL, tmp, sizeof(tmp) / sizeof(*tmp), ini.c_str()))
		return false;
	if (GetLastError() == ERROR_FILE_NOT_FOUND)
		return false;
	value = wcstoul(tmp, NULL, 10);
	return true;
}

bool SaveSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, const std::string& value)
{
	std::wstring wstr;
	wstr.assign(value.begin(), value.end());
	return !!WritePrivateProfileStringW(section.c_str(), param, wstr.c_str(), ini.c_str());
}

bool SaveSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, const std::wstring& value)
{
	return !!WritePrivateProfileStringW(section.c_str(), param, value.c_str(), ini.c_str());
}

bool SaveSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, const bool value)
{
	wchar_t tmp[2] = { 0 };
	swprintf_s(tmp, L"%d", value ? 1 : 0);
	return !!WritePrivateProfileStringW(section.c_str(), param, tmp, ini.c_str());
}

bool SaveSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, const int32_t value)
{
	wchar_t tmp[32] = { 0 };
	swprintf_s(tmp, L"%d", value);
	return !!WritePrivateProfileStringW(section.c_str(), param, tmp, ini.c_str());
}

bool LoadSetting(int port, const std::string& key, CONFIGVARIANT& var)
{
	OSDebugOut(L"USBqemu load \"%s\" from [%S %d]\n", var.name, key.c_str(), port);

	std::wstringstream section;
	std::wstring wkey;
	wkey.assign(key.begin(), key.end());
	section << wkey << " " << port;

	std::wstring ini;
	GetIniFile(ini);

	switch (var.type)
	{
	case CONFIG_TYPE_BOOL:
		return LoadSettingValue(ini, section.str(), var.name, var.boolValue);
	case CONFIG_TYPE_INT:
		return LoadSettingValue(ini, section.str(), var.name, var.intValue);
		//case CONFIG_TYPE_DOUBLE:
		//	return LoadSettingValue(ini, section.str(), var.name, var.doubleValue);
	case CONFIG_TYPE_TCHAR:
		return LoadSettingValue(ini, section.str(), var.name, var.wstrValue);
	case CONFIG_TYPE_CHAR:
		return LoadSettingValue(ini, section.str(), var.name, var.strValue);
	case CONFIG_TYPE_WCHAR:
		return LoadSettingValue(ini, section.str(), var.name, var.wstrValue);
	default:
		OSDebugOut(L"Invalid config type %d for %s\n", var.type, var.name);
		break;
	};
	return false;
}

/**
*
* [devices]
* portX = pad
*
* [pad X]
* api = joydev
*
* [joydev X]
* button0 = 1
* button1 = 2
* ...
*
* */
bool SaveSetting(int port, const std::string& key, CONFIGVARIANT& var)
{
	OSDebugOut(L"USBqemu save \"%s\" to [%S %d]\n", var.name, key.c_str(), port);

	std::wstringstream section;
	std::wstring wkey;
	wkey.assign(key.begin(), key.end());
	section << wkey << " " << port;

	std::wstring ini;
	GetIniFile(ini);

	switch (var.type)
	{
	case CONFIG_TYPE_BOOL:
		return SaveSettingValue(ini, section.str(), var.name, var.boolValue);
	case CONFIG_TYPE_INT:
		return SaveSettingValue(ini, section.str(), var.name, var.intValue);
	case CONFIG_TYPE_TCHAR:
		return SaveSettingValue(ini, section.str(), var.name, var.wstrValue);
	case CONFIG_TYPE_WCHAR:
		return SaveSettingValue(ini, section.str(), var.name, var.wstrValue);
	case CONFIG_TYPE_CHAR:
		return SaveSettingValue(ini, section.str(), var.name, var.strValue);
	default:
		OSDebugOut(L"Invalid config type %d for %s\n", var.type, var.name);
		break;
	};
	return false;
}

void SaveConfig()
{
	Config *Conf1 = &conf;
	std::wstring szIniFile;
	TCHAR szValue[256];

	GetIniFile(szIniFile);

	FILE *f = nullptr;
	auto err = _wfopen_s(&f, szIniFile.c_str(), L"a+");
	if (!f) {
		MessageBoxW(NULL, L"Cannot save to ini!", L"USBqemu", MB_ICONERROR);
	} else
		fclose(f);

	swprintf_s(szValue,L"%u",Conf1->Log);
	WritePrivateProfileStringW(L"Interface", L"Logging", szValue, szIniFile.c_str());

	swprintf_s(szValue,L"%u",Conf1->DFPPass);
	WritePrivateProfileStringW(N_DEVICES, L"DFP Passthrough", szValue, szIniFile.c_str());

	swprintf_s(szValue,L"%S",Conf1->Port0.c_str());
	WritePrivateProfileStringW(N_DEVICES, N_DEVICE_PORT0, szValue, szIniFile.c_str());

	swprintf_s(szValue,L"%S",Conf1->Port1.c_str());
	WritePrivateProfileStringW(N_DEVICES, N_DEVICE_PORT1, szValue, szIniFile.c_str());

	swprintf_s(szValue,L"%u",Conf1->WheelType[0]);
	WritePrivateProfileStringW(N_DEVICES, N_WHEEL_TYPE0, szValue, szIniFile.c_str());

	swprintf_s(szValue,L"%u",Conf1->WheelType[1]);
	WritePrivateProfileStringW(N_DEVICES, N_WHEEL_TYPE1, szValue, szIniFile.c_str());

	for (auto &kp : changedAPIs)
	{
		CONFIGVARIANT var(N_DEVICE_API, kp.second);
		SaveSetting(kp.first.first, kp.first.second, var);
	}
	changedAPIs.clear();
}

void LoadConfig() {

	Config *Conf1 = &conf;
	std::wstring szIniFile;
	wchar_t szValue[MAX_PATH+1];
	char tmpA[MAX_PATH + 1] = { 0 };
	size_t num = 0;

	GetIniFile(szIniFile);

	FILE *fp = nullptr;
	auto err = _wfopen_s(&fp, szIniFile.c_str(), L"rt");//check if ini really exists
	if (!fp)
	{
		conf.Log = 0;//default value
		SaveConfig();//save and return
		return ;
	}
	fclose(fp);

	GetPrivateProfileStringW(L"Interface", L"Logging", NULL, szValue, 20, szIniFile.c_str());
	Conf1->Log = wcstoul(szValue, NULL, 10);

	GetPrivateProfileStringW(N_DEVICES, TEXT("DFP Passthrough"), NULL, szValue, 20, szIniFile.c_str());
	Conf1->DFPPass = wcstoul(szValue, NULL, 10);

	GetPrivateProfileStringW(N_DEVICES, N_DEVICE_PORT0, NULL, szValue, ARRAYSIZE(szValue), szIniFile.c_str());
	wcstombs_s(&num, tmpA, szValue, sizeof(tmpA));//TODO error-check
	Conf1->Port0 = tmpA;

	GetPrivateProfileStringW(N_DEVICES, N_DEVICE_PORT1, NULL, szValue, ARRAYSIZE(szValue), szIniFile.c_str());
	wcstombs_s(&num, tmpA, szValue, sizeof(tmpA));//TODO error-check
	Conf1->Port1 = tmpA;

	GetPrivateProfileStringW(N_DEVICES, N_WHEEL_TYPE0, NULL, szValue, 20, szIniFile.c_str());
	Conf1->WheelType[0] = wcstoul(szValue, NULL, 10);

	GetPrivateProfileStringW(N_DEVICES, N_WHEEL_TYPE1, NULL, szValue, 20, szIniFile.c_str());
	Conf1->WheelType[1] = wcstoul(szValue, NULL, 10);

	return ;

}

<commit_msg>win32: load CONFIG_TYPE_TCHAR into proper variable<commit_after>#include <string>
#include <stdlib.h>
#include <sstream>

#include "../USB.h"
#include "../configuration.h"

extern HINSTANCE hInst;
std::wstring IniDir;
std::wstring LogDir;

void CALLBACK USBsetSettingsDir( const char* dir )
{
	OSDebugOut(L"USBsetSettingsDir: %S\n", dir);
	wchar_t dst[4096] = {0};
	size_t num = 0;
	mbstowcs_s(&num, dst, dir, ARRAYSIZE(dst));
	IniDir = dst;
}

void CALLBACK USBsetLogDir( const char* dir )
{
	OSDebugOut(L"USBsetLogDir: %S\n", dir);
	wchar_t dst[4096] = {0};
	size_t num = 0;
	mbstowcs_s(&num, dst, dir, ARRAYSIZE(dst));
	LogDir = dst;
}

//TODO Use \\?\ to go past 260 char limit
void GetIniFile(std::wstring &iniFile)
{
	iniFile.clear();
	if(!IniDir.length()) {
		WCHAR tmp[MAX_PATH] = {0};
		GetModuleFileName(GetModuleHandle((LPWSTR)hInst), tmp, MAX_PATH);

		std::wstring path(tmp);
		unsigned last = path.find_last_of(L"\\");
		iniFile = path.substr(0, last);
		iniFile.append(L"\\inis");
		CreateDirectory(iniFile.c_str(), NULL);
		iniFile.append(L"\\USBqemu-wheel.ini");
	} else {
		iniFile.append(IniDir);
		iniFile.append(L"USBqemu-wheel.ini");
	}
}

bool LoadSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, std::string& value)
{
	wchar_t tmp[4096] = { 0 };
	if (!GetPrivateProfileStringW(section.c_str(), param, NULL, tmp, sizeof(tmp) / sizeof(*tmp), ini.c_str()))
		return false;
	if (GetLastError() == ERROR_FILE_NOT_FOUND)
		return false;

	char tmpA[4096] = { 0 };
	size_t num = 0;
	wcstombs_s(&num, tmpA, tmp, sizeof(tmpA)); //TODO error-check
	value = tmpA;
	return true;
}

bool LoadSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, std::wstring& value)
{
	wchar_t tmp[4096] = { 0 };
	if (!GetPrivateProfileStringW(section.c_str(), param, NULL, tmp, sizeof(tmp) / sizeof(*tmp), ini.c_str()))
		return false;
	if (GetLastError() == ERROR_FILE_NOT_FOUND)
		return false;
	value = tmp;
	return true;
}

bool LoadSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, bool& value)
{
	//value = GetPrivateProfileIntW(section.c_str(), param, 0, ini.c_str());
	wchar_t tmp[4096] = { 0 };
	if (!GetPrivateProfileStringW(section.c_str(), param, NULL, tmp, sizeof(tmp) / sizeof(*tmp), ini.c_str()))
		return false;
	if (GetLastError() == ERROR_FILE_NOT_FOUND)
		return false;
	value = !!wcstoul(tmp, NULL, 10);
	return true;
}

bool LoadSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, int32_t& value)
{
	//value = GetPrivateProfileIntW(section.c_str(), param, 0, ini.c_str());
	wchar_t tmp[4096] = { 0 };
	if (!GetPrivateProfileStringW(section.c_str(), param, NULL, tmp, sizeof(tmp) / sizeof(*tmp), ini.c_str()))
		return false;
	if (GetLastError() == ERROR_FILE_NOT_FOUND)
		return false;
	value = wcstoul(tmp, NULL, 10);
	return true;
}

bool SaveSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, const std::string& value)
{
	std::wstring wstr;
	wstr.assign(value.begin(), value.end());
	return !!WritePrivateProfileStringW(section.c_str(), param, wstr.c_str(), ini.c_str());
}

bool SaveSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, const std::wstring& value)
{
	return !!WritePrivateProfileStringW(section.c_str(), param, value.c_str(), ini.c_str());
}

bool SaveSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, const bool value)
{
	wchar_t tmp[2] = { 0 };
	swprintf_s(tmp, L"%d", value ? 1 : 0);
	return !!WritePrivateProfileStringW(section.c_str(), param, tmp, ini.c_str());
}

bool SaveSettingValue(const std::wstring& ini, const std::wstring& section, const wchar_t* param, const int32_t value)
{
	wchar_t tmp[32] = { 0 };
	swprintf_s(tmp, L"%d", value);
	return !!WritePrivateProfileStringW(section.c_str(), param, tmp, ini.c_str());
}

bool LoadSetting(int port, const std::string& key, CONFIGVARIANT& var)
{
	OSDebugOut(L"USBqemu load \"%s\" from [%S %d]\n", var.name, key.c_str(), port);

	std::wstringstream section;
	std::wstring wkey;
	wkey.assign(key.begin(), key.end());
	section << wkey << " " << port;

	std::wstring ini;
	GetIniFile(ini);

	switch (var.type)
	{
	case CONFIG_TYPE_BOOL:
		return LoadSettingValue(ini, section.str(), var.name, var.boolValue);
	case CONFIG_TYPE_INT:
		return LoadSettingValue(ini, section.str(), var.name, var.intValue);
		//case CONFIG_TYPE_DOUBLE:
		//	return LoadSettingValue(ini, section.str(), var.name, var.doubleValue);
	case CONFIG_TYPE_TCHAR:
		return LoadSettingValue(ini, section.str(), var.name, var.tstrValue);
	case CONFIG_TYPE_CHAR:
		return LoadSettingValue(ini, section.str(), var.name, var.strValue);
	case CONFIG_TYPE_WCHAR:
		return LoadSettingValue(ini, section.str(), var.name, var.wstrValue);
	default:
		OSDebugOut(L"Invalid config type %d for %s\n", var.type, var.name);
		break;
	};
	return false;
}

/**
*
* [devices]
* portX = pad
*
* [pad X]
* api = joydev
*
* [joydev X]
* button0 = 1
* button1 = 2
* ...
*
* */
bool SaveSetting(int port, const std::string& key, CONFIGVARIANT& var)
{
	OSDebugOut(L"USBqemu save \"%s\" to [%S %d]\n", var.name, key.c_str(), port);

	std::wstringstream section;
	std::wstring wkey;
	wkey.assign(key.begin(), key.end());
	section << wkey << " " << port;

	std::wstring ini;
	GetIniFile(ini);

	switch (var.type)
	{
	case CONFIG_TYPE_BOOL:
		return SaveSettingValue(ini, section.str(), var.name, var.boolValue);
	case CONFIG_TYPE_INT:
		return SaveSettingValue(ini, section.str(), var.name, var.intValue);
	case CONFIG_TYPE_TCHAR:
		return SaveSettingValue(ini, section.str(), var.name, var.wstrValue);
	case CONFIG_TYPE_WCHAR:
		return SaveSettingValue(ini, section.str(), var.name, var.wstrValue);
	case CONFIG_TYPE_CHAR:
		return SaveSettingValue(ini, section.str(), var.name, var.strValue);
	default:
		OSDebugOut(L"Invalid config type %d for %s\n", var.type, var.name);
		break;
	};
	return false;
}

void SaveConfig()
{
	Config *Conf1 = &conf;
	std::wstring szIniFile;
	TCHAR szValue[256];

	GetIniFile(szIniFile);

	FILE *f = nullptr;
	auto err = _wfopen_s(&f, szIniFile.c_str(), L"a+");
	if (!f) {
		MessageBoxW(NULL, L"Cannot save to ini!", L"USBqemu", MB_ICONERROR);
	} else
		fclose(f);

	swprintf_s(szValue,L"%u",Conf1->Log);
	WritePrivateProfileStringW(L"Interface", L"Logging", szValue, szIniFile.c_str());

	swprintf_s(szValue,L"%u",Conf1->DFPPass);
	WritePrivateProfileStringW(N_DEVICES, L"DFP Passthrough", szValue, szIniFile.c_str());

	swprintf_s(szValue,L"%S",Conf1->Port0.c_str());
	WritePrivateProfileStringW(N_DEVICES, N_DEVICE_PORT0, szValue, szIniFile.c_str());

	swprintf_s(szValue,L"%S",Conf1->Port1.c_str());
	WritePrivateProfileStringW(N_DEVICES, N_DEVICE_PORT1, szValue, szIniFile.c_str());

	swprintf_s(szValue,L"%u",Conf1->WheelType[0]);
	WritePrivateProfileStringW(N_DEVICES, N_WHEEL_TYPE0, szValue, szIniFile.c_str());

	swprintf_s(szValue,L"%u",Conf1->WheelType[1]);
	WritePrivateProfileStringW(N_DEVICES, N_WHEEL_TYPE1, szValue, szIniFile.c_str());

	for (auto &kp : changedAPIs)
	{
		CONFIGVARIANT var(N_DEVICE_API, kp.second);
		SaveSetting(kp.first.first, kp.first.second, var);
	}
	changedAPIs.clear();
}

void LoadConfig() {

	Config *Conf1 = &conf;
	std::wstring szIniFile;
	wchar_t szValue[MAX_PATH+1];
	char tmpA[MAX_PATH + 1] = { 0 };
	size_t num = 0;

	GetIniFile(szIniFile);

	FILE *fp = nullptr;
	auto err = _wfopen_s(&fp, szIniFile.c_str(), L"rt");//check if ini really exists
	if (!fp)
	{
		conf.Log = 0;//default value
		SaveConfig();//save and return
		return ;
	}
	fclose(fp);

	GetPrivateProfileStringW(L"Interface", L"Logging", NULL, szValue, 20, szIniFile.c_str());
	Conf1->Log = wcstoul(szValue, NULL, 10);

	GetPrivateProfileStringW(N_DEVICES, TEXT("DFP Passthrough"), NULL, szValue, 20, szIniFile.c_str());
	Conf1->DFPPass = wcstoul(szValue, NULL, 10);

	GetPrivateProfileStringW(N_DEVICES, N_DEVICE_PORT0, NULL, szValue, ARRAYSIZE(szValue), szIniFile.c_str());
	wcstombs_s(&num, tmpA, szValue, sizeof(tmpA));//TODO error-check
	Conf1->Port0 = tmpA;

	GetPrivateProfileStringW(N_DEVICES, N_DEVICE_PORT1, NULL, szValue, ARRAYSIZE(szValue), szIniFile.c_str());
	wcstombs_s(&num, tmpA, szValue, sizeof(tmpA));//TODO error-check
	Conf1->Port1 = tmpA;

	GetPrivateProfileStringW(N_DEVICES, N_WHEEL_TYPE0, NULL, szValue, 20, szIniFile.c_str());
	Conf1->WheelType[0] = wcstoul(szValue, NULL, 10);

	GetPrivateProfileStringW(N_DEVICES, N_WHEEL_TYPE1, NULL, szValue, 20, szIniFile.c_str());
	Conf1->WheelType[1] = wcstoul(szValue, NULL, 10);

	return ;

}

<|endoftext|>


<commit_before>/*
*      Copyright 2016 Riccardo Melioli.
*/

#include "network.h"

Server::Server(std::string encryptionKeyArg) {
    encryptionKey = encryptionKeyArg;
    port = "none";
    hThread = NULL;
    listenSocket = INVALID_SOCKET;

    sta.encryptionKey = encryptionKeyArg;
    sta.ListenSocket = INVALID_SOCKET;
}

Server &Server::operator=(const Server &server) {
    encryptionKey = server.encryptionKey;
    port = server.port;
    hThread = server.hThread;
    listenSocket = server.listenSocket;

    sta.encryptionKey = server.sta.encryptionKey;
    sta.ListenSocket = server.sta.ListenSocket;
    return *this;
}

Network &Network::operator=(const Network &network) {
    encryptionKey = network.encryptionKey;
    server = network.server;
    return *this;
}

Network::Network(std::string encryptionKeyArg) {
    encryptionKey = encryptionKeyArg;
    server = Server(encryptionKeyArg);
}

std::string Network::RawRequest(const char *serverAddress, const char *port, const char *request) {
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL, *ptr = NULL, hints;
    const char *sendbuf = request;
    const int bufferlength = 512;
    char recvbuf[bufferlength];
    int iResult;
    std::string response;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        return "Error";
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(serverAddress, port, &hints, &result);
    if (iResult != 0) {
        WSACleanup();
        return "Error";
    }

    // Attempt to connect to an address until one succeeds
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
                               ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            WSACleanup();
            return "Error";
        }

        // Connect to server.
        iResult = connect(ConnectSocket, ptr->ai_addr, (int) ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);
    if (ConnectSocket == INVALID_SOCKET) {
        WSACleanup();
        return "Error";
    }

    // Send an initial buffer
    iResult = send(ConnectSocket, sendbuf, (int) strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR) {
        closesocket(ConnectSocket);
        WSACleanup();
        return "Error";
    }

    // Receive until the peer closes the connection
    do {

        iResult = recv(ConnectSocket, recvbuf, bufferlength, 0);
        if (iResult > 0) {
            // answer
            response.append(recvbuf);
        } else if (iResult == 0) {
            // connection closed
        } else {
            // error
        }

    } while (iResult > 0);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        closesocket(ConnectSocket);
        WSACleanup();
        return "Error";
    }

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return response;
}

bool Network::UploadInfoToRMS(const char *serverAddress, const char *port, const char *userAssociated) {
    const char *serverPort = server.getPort();
    Crypto crypto(encryptionKey);

    std::string name = getenv("COMPUTERNAME");
    name.append("/");
    name.append(getenv("USERNAME"));

    // encrypt only serverPort because name is used by the server to recognize the device
    std::string serverPortS = crypto.Encrypt(serverPort);
    //Device device = Device(name, serverPortS);
    //std::string deviceStr = "$" + device.getName() + "," + device.getServerPort() + "$";

    std::string userAssociatedS = crypto.Encrypt(userAssociated);

    std::string packet = "PUT /Richkware-Manager-Server/device?data0=" + name +
                                "&data1=" + serverPortS +
                                "&data2=" + userAssociatedS +
                                " HTTP/1.1\r\n" +
                                "Host: " + serverAddress + "\r\n" +
                                "Connection: close\r\n" +
                                "\r\n";

    RawRequest(serverAddress, port, packet.c_str());

    return true;
}

std::string Network::GetEncryptionKeyFromRMS(const char *serverAddress, const char *port, const char *userAssociated) {
    Crypto crypto(encryptionKey);
    std::string key = "";

    // create a database entry into the Richkware-Manager-Server, to obtain the encryption key server-side generated
    UploadInfoToRMS(serverAddress, port, userAssociated);

    // Primary key in RMS database.
    std::string name = getenv("COMPUTERNAME");
    name.append("/");
    name.append(getenv("USERNAME"));

    std::string nameS = crypto.Encrypt(name);

    std::string packet = "GET /Richkware-Manager-Server/GetEncryptionKey?id=" + nameS + " HTTP/1.1\r\n"
            "Host: " + serverAddress + "\r\n" +
                         "Connection: close\r\n" +
                         "\r\n";

    key = RawRequest(serverAddress, port, packet.c_str());
    // If no matches were found, the function "find" returns string::npos
    if(key.find('$') !=  std::string::npos) {
        key = key.substr(key.find('$') + 1, (key.find('#') - key.find('$')) - 1);
        key = crypto.Decrypt(key);
    }
    //TODO server error: key not received
    return key;
}

const char *Network::ResolveAddress(const char *address) {
    const char *addressIP = "";
    WSADATA wsaData;
    struct hostent *remoteHost;
    char *host_name;
    struct in_addr addr;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    host_name = (char *) address;
    remoteHost = gethostbyname(host_name);
    if (remoteHost != NULL) {
        if (remoteHost->h_addrtype == AF_INET) {
            int i = 0;
            while (remoteHost->h_addr_list[i] != 0) {
                addr.s_addr = *(u_long *) remoteHost->h_addr_list[i++];
                addressIP = inet_ntoa(addr);
                break;
            }
        }
    }
    return addressIP;
}

void Server::Start(const char *portArg, bool encrypted) {
    DWORD dwThreadId;
    port = portArg;

    if (encrypted)
        sta.encryptionKey = encryptionKey;
    else
        sta.encryptionKey = "";

    SOCKET listenSocketTmp = INVALID_SOCKET;

    WSADATA wsaData;
    int iResult;

    struct addrinfo *result = NULL;
    struct addrinfo hints;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        //throw 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    // Resolve the server address and port
    iResult = getaddrinfo(NULL, portArg, &hints, &result);
    if (iResult != 0) {
        WSACleanup();
        //throw 1;
    }

    // Create a SOCKET for connecting to server
    listenSocketTmp = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (listenSocketTmp == INVALID_SOCKET) {
        freeaddrinfo(result);
        WSACleanup();
        //throw 1;
    }

    // Setup the TCP listening socket
    iResult = bind(listenSocketTmp, result->ai_addr, (int) result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        freeaddrinfo(result);
        closesocket(listenSocketTmp);
        WSACleanup();
        //throw 1;
    }

    freeaddrinfo(result);

    iResult = listen(listenSocketTmp, SOMAXCONN);
    if (iResult == SOCKET_ERROR) {
        closesocket(listenSocketTmp);
        WSACleanup();
        //throw 1;
    }

    listenSocket = listenSocketTmp;
    sta.ListenSocket = listenSocketTmp;

    hThread = CreateThread(0, 0, &ServerThread,
                           (void *) &sta, 0, &dwThreadId);

}

void Server::Stop() {
    port = "none";

    closesocket(listenSocket);
    WSACleanup();

    DWORD dwExit;
    GetExitCodeThread(hThread, &dwExit);
    TerminateThread(hThread, dwExit);
    //CloseHandle(hThread);
}

HANDLE Server::getHhread() {
    return hThread;
}

const char *Server::getPort() {
    return port;
}

DWORD WINAPI ServerThread(void *arg) {
    std::string encryptionKey = (std::string) ((*((ServerThreadArgs *) arg)).encryptionKey);
    SOCKET ListenSocket = (SOCKET) ((*((ServerThreadArgs *) arg)).ListenSocket);

    //HANDLE hClientThreadArray[1000];
    SOCKET ClientSocket = INVALID_SOCKET;
    while (true) {
        // Accept a client socket
        ClientSocket = accept(ListenSocket, NULL, NULL);
        if (ClientSocket == INVALID_SOCKET) {
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        } else {
            ClientSocketThreadArgs* csa = new ClientSocketThreadArgs();
            csa->ClientSocket = ClientSocket;
            csa->encryptionKey = encryptionKey;

            //hClientThreadArray[i] =
            CreateThread(0, 0, &ClientSocketThread, (void *) /*&*/csa, 0, NULL);
        }
    }
    return 0;
}

DWORD WINAPI ClientSocketThread(void *arg) {
    ClientSocketThreadArgs csta = *((ClientSocketThreadArgs *) arg);
    SOCKET ClientSocket = csta.ClientSocket;
    std::string encryptionKey = csta.encryptionKey;

    Crypto crypto(encryptionKey);
    const int bufferlength = 512;
    int iResult;

    std::string command;
    std::string response;
    int iSendResult;
    char recvbuf[bufferlength];
    std::size_t posSubStr;

    // Receive until the peer shuts down the connection
    if (encryptionKey.compare("") != 0){
        send(ClientSocket, "\nEncrypted Connection Established\n", 34, 0);
    }else{
        send(ClientSocket, "\nConnection Established\n", 24, 0);
    }

    do {
        memset(&recvbuf[0], 0, sizeof(recvbuf));
        iResult = recv(ClientSocket, recvbuf, bufferlength, 0);
        command.append(recvbuf);
        //command = recvbuf;

        // string decryption

        if (encryptionKey.compare("") != 0) {
            command.erase(command.find("\r\n"), command.length());
            command = crypto.Decrypt(command);
            command.append("\r\n");
        }

        posSubStr = command.find("\n");
        if (posSubStr != std::string::npos) {
            // erase escape characters
            //command.erase(posSubStr);

            response = CommandsDispatcher(command);

            // string encryption
            if (encryptionKey.compare("") != 0){
                std::string encResponse = (crypto.Encrypt(response) + "\n");
                iSendResult = send(ClientSocket, encResponse.c_str(),encResponse.length(), 0);
            } else{
                iSendResult = send(ClientSocket, response.c_str(),response.length(), 0);
            }

            if (iSendResult == SOCKET_ERROR) {
                closesocket(ClientSocket);
                WSACleanup();
                return 1;
            }
        }
        command = "";
        command.clear();

    } while (iResult > 0 && response.compare("***quit***") != 0);

    send(ClientSocket, "\nConnection Stopped\n", 20, 0);

    // shutdown the connection
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }
    return 0;
}

Device::Device(std::string nameArg, std::string serverPortArg) {
    name = nameArg;
    serverPort = serverPortArg;
}

Device &Device::operator=(const Device &device) {
    name = device.name;
    serverPort = device.serverPort;
    return *this;
}

std::string Device::getName() {
    return name;
}

std::string Device::getServerPort() {
    return serverPort;
}

void Device::setName(std::string nameArg) {
    name = nameArg;
}

void Device::setServerPort(std::string serverPortArg) {
    serverPort = serverPortArg;
}
<commit_msg>add userAssociated for user authorization on the server<commit_after>/*
*      Copyright 2016 Riccardo Melioli.
*/

#include "network.h"

Server::Server(std::string encryptionKeyArg) {
    encryptionKey = encryptionKeyArg;
    port = "none";
    hThread = NULL;
    listenSocket = INVALID_SOCKET;

    sta.encryptionKey = encryptionKeyArg;
    sta.ListenSocket = INVALID_SOCKET;
}

Server &Server::operator=(const Server &server) {
    encryptionKey = server.encryptionKey;
    port = server.port;
    hThread = server.hThread;
    listenSocket = server.listenSocket;

    sta.encryptionKey = server.sta.encryptionKey;
    sta.ListenSocket = server.sta.ListenSocket;
    return *this;
}

Network &Network::operator=(const Network &network) {
    encryptionKey = network.encryptionKey;
    server = network.server;
    return *this;
}

Network::Network(std::string encryptionKeyArg) {
    encryptionKey = encryptionKeyArg;
    server = Server(encryptionKeyArg);
}

std::string Network::RawRequest(const char *serverAddress, const char *port, const char *request) {
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL, *ptr = NULL, hints;
    const char *sendbuf = request;
    const int bufferlength = 512;
    char recvbuf[bufferlength];
    int iResult;
    std::string response;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        return "Error";
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(serverAddress, port, &hints, &result);
    if (iResult != 0) {
        WSACleanup();
        return "Error";
    }

    // Attempt to connect to an address until one succeeds
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
                               ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            WSACleanup();
            return "Error";
        }

        // Connect to server.
        iResult = connect(ConnectSocket, ptr->ai_addr, (int) ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);
    if (ConnectSocket == INVALID_SOCKET) {
        WSACleanup();
        return "Error";
    }

    // Send an initial buffer
    iResult = send(ConnectSocket, sendbuf, (int) strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR) {
        closesocket(ConnectSocket);
        WSACleanup();
        return "Error";
    }

    // Receive until the peer closes the connection
    do {

        iResult = recv(ConnectSocket, recvbuf, bufferlength, 0);
        if (iResult > 0) {
            // answer
            response.append(recvbuf);
        } else if (iResult == 0) {
            // connection closed
        } else {
            // error
        }

    } while (iResult > 0);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        closesocket(ConnectSocket);
        WSACleanup();
        return "Error";
    }

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return response;
}

bool Network::UploadInfoToRMS(const char *serverAddress, const char *port, const char *userAssociated) {
    const char *serverPort = server.getPort();
    Crypto crypto(encryptionKey);

    std::string name = getenv("COMPUTERNAME");
    name.append("/");
    name.append(getenv("USERNAME"));

    // encrypt only serverPort because name is used by the server to recognize the device
    std::string serverPortS = crypto.Encrypt(serverPort);
    //Device device = Device(name, serverPortS);
    //std::string deviceStr = "$" + device.getName() + "," + device.getServerPort() + "$";

    std::string userAssociatedS = crypto.Encrypt(userAssociated);

    std::string packet = "PUT /Richkware-Manager-Server/device?data0=" + name +
                                "&data1=" + serverPortS +
                                "&data2=" + userAssociatedS +
                                " HTTP/1.1\r\n" +
                                "Host: " + serverAddress + "\r\n" +
                                "Connection: close\r\n" +
                                "\r\n";

    RawRequest(serverAddress, port, packet.c_str());

    return true;
}

std::string Network::GetEncryptionKeyFromRMS(const char *serverAddress, const char *port, const char *userAssociated) {
    Crypto crypto(encryptionKey);
    std::string key = "";

    // create a database entry into the Richkware-Manager-Server, to obtain the encryption key server-side generated
    UploadInfoToRMS(serverAddress, port, userAssociated);

    // Primary key in RMS database.
    std::string name = getenv("COMPUTERNAME");
    name.append("/");
    name.append(getenv("USERNAME"));

    std::string nameS = crypto.Encrypt(name);

    std::string packet = "GET /Richkware-Manager-Server/encryptionKey?id=" + nameS + " HTTP/1.1\r\n"
            "Host: " + serverAddress + "\r\n" +
                         "Connection: close\r\n" +
                         "\r\n";

    key = RawRequest(serverAddress, port, packet.c_str());
    // If no matches were found, the function "find" returns string::npos
    if(key.find('$') !=  std::string::npos) {
        key = key.substr(key.find('$') + 1, (key.find('#') - key.find('$')) - 1);
        key = crypto.Decrypt(key);
    }
    //TODO server error: key not received
    return key;
}

const char *Network::ResolveAddress(const char *address) {
    const char *addressIP = "";
    WSADATA wsaData;
    struct hostent *remoteHost;
    char *host_name;
    struct in_addr addr;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    host_name = (char *) address;
    remoteHost = gethostbyname(host_name);
    if (remoteHost != NULL) {
        if (remoteHost->h_addrtype == AF_INET) {
            int i = 0;
            while (remoteHost->h_addr_list[i] != 0) {
                addr.s_addr = *(u_long *) remoteHost->h_addr_list[i++];
                addressIP = inet_ntoa(addr);
                break;
            }
        }
    }
    return addressIP;
}

void Server::Start(const char *portArg, bool encrypted) {
    DWORD dwThreadId;
    port = portArg;

    if (encrypted)
        sta.encryptionKey = encryptionKey;
    else
        sta.encryptionKey = "";

    SOCKET listenSocketTmp = INVALID_SOCKET;

    WSADATA wsaData;
    int iResult;

    struct addrinfo *result = NULL;
    struct addrinfo hints;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        //throw 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    // Resolve the server address and port
    iResult = getaddrinfo(NULL, portArg, &hints, &result);
    if (iResult != 0) {
        WSACleanup();
        //throw 1;
    }

    // Create a SOCKET for connecting to server
    listenSocketTmp = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (listenSocketTmp == INVALID_SOCKET) {
        freeaddrinfo(result);
        WSACleanup();
        //throw 1;
    }

    // Setup the TCP listening socket
    iResult = bind(listenSocketTmp, result->ai_addr, (int) result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        freeaddrinfo(result);
        closesocket(listenSocketTmp);
        WSACleanup();
        //throw 1;
    }

    freeaddrinfo(result);

    iResult = listen(listenSocketTmp, SOMAXCONN);
    if (iResult == SOCKET_ERROR) {
        closesocket(listenSocketTmp);
        WSACleanup();
        //throw 1;
    }

    listenSocket = listenSocketTmp;
    sta.ListenSocket = listenSocketTmp;

    hThread = CreateThread(0, 0, &ServerThread,
                           (void *) &sta, 0, &dwThreadId);

}

void Server::Stop() {
    port = "none";

    closesocket(listenSocket);
    WSACleanup();

    DWORD dwExit;
    GetExitCodeThread(hThread, &dwExit);
    TerminateThread(hThread, dwExit);
    //CloseHandle(hThread);
}

HANDLE Server::getHhread() {
    return hThread;
}

const char *Server::getPort() {
    return port;
}

DWORD WINAPI ServerThread(void *arg) {
    std::string encryptionKey = (std::string) ((*((ServerThreadArgs *) arg)).encryptionKey);
    SOCKET ListenSocket = (SOCKET) ((*((ServerThreadArgs *) arg)).ListenSocket);

    //HANDLE hClientThreadArray[1000];
    SOCKET ClientSocket = INVALID_SOCKET;
    while (true) {
        // Accept a client socket
        ClientSocket = accept(ListenSocket, NULL, NULL);
        if (ClientSocket == INVALID_SOCKET) {
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        } else {
            ClientSocketThreadArgs* csa = new ClientSocketThreadArgs();
            csa->ClientSocket = ClientSocket;
            csa->encryptionKey = encryptionKey;

            //hClientThreadArray[i] =
            CreateThread(0, 0, &ClientSocketThread, (void *) /*&*/csa, 0, NULL);
        }
    }
    return 0;
}

DWORD WINAPI ClientSocketThread(void *arg) {
    ClientSocketThreadArgs csta = *((ClientSocketThreadArgs *) arg);
    SOCKET ClientSocket = csta.ClientSocket;
    std::string encryptionKey = csta.encryptionKey;

    Crypto crypto(encryptionKey);
    const int bufferlength = 512;
    int iResult;

    std::string command;
    std::string response;
    int iSendResult;
    char recvbuf[bufferlength];
    std::size_t posSubStr;

    // Receive until the peer shuts down the connection
    if (encryptionKey.compare("") != 0){
        send(ClientSocket, "\nEncrypted Connection Established\n", 34, 0);
    }else{
        send(ClientSocket, "\nConnection Established\n", 24, 0);
    }

    do {
        memset(&recvbuf[0], 0, sizeof(recvbuf));
        iResult = recv(ClientSocket, recvbuf, bufferlength, 0);
        command.append(recvbuf);
        //command = recvbuf;

        // string decryption

        if (encryptionKey.compare("") != 0) {
            command.erase(command.find("\r\n"), command.length());
            command = crypto.Decrypt(command);
            command.append("\r\n");
        }

        posSubStr = command.find("\n");
        if (posSubStr != std::string::npos) {
            // erase escape characters
            //command.erase(posSubStr);

            response = CommandsDispatcher(command);

            // string encryption
            if (encryptionKey.compare("") != 0){
                std::string encResponse = (crypto.Encrypt(response) + "\n");
                iSendResult = send(ClientSocket, encResponse.c_str(),encResponse.length(), 0);
            } else{
                iSendResult = send(ClientSocket, response.c_str(),response.length(), 0);
            }

            if (iSendResult == SOCKET_ERROR) {
                closesocket(ClientSocket);
                WSACleanup();
                return 1;
            }
        }
        command = "";
        command.clear();

    } while (iResult > 0 && response.compare("***quit***") != 0);

    send(ClientSocket, "\nConnection Stopped\n", 20, 0);

    // shutdown the connection
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }
    return 0;
}

Device::Device(std::string nameArg, std::string serverPortArg) {
    name = nameArg;
    serverPort = serverPortArg;
}

Device &Device::operator=(const Device &device) {
    name = device.name;
    serverPort = device.serverPort;
    return *this;
}

std::string Device::getName() {
    return name;
}

std::string Device::getServerPort() {
    return serverPort;
}

void Device::setName(std::string nameArg) {
    name = nameArg;
}

void Device::setServerPort(std::string serverPortArg) {
    serverPort = serverPortArg;
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH
#define DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH

#include <vector>

#include <dune/common/dynmatrix.hh>
#include <dune/common/dynvector.hh>

#include <dune/stuff/common/matrix.hh>
#include <dune/stuff/la/container/interfaces.hh>

#include <dune/gdt/localoperator/interface.hh>
#include <dune/gdt/localfunctional/interface.hh>
#include <dune/gdt/space/interface.hh>

namespace Dune {
namespace GDT {
namespace LocalAssembler {

// forward, to be used in the traits
template< class LocalOperatorImp >
class Codim0Matrix;

template< class LocalOperatorImp >
class Codim0MatrixTraits
{
public:
  typedef Codim0Matrix< LocalOperatorImp > derived_type;
  typedef LocalOperator::Codim0Interface< typename LocalOperatorImp::Traits > LocalOperatorType;
}; // class LocalAssemblerCodim0MatrixTraits

template< class LocalOperatorImp >
class Codim0Matrix
{
public:
  typedef Codim0MatrixTraits< LocalOperatorImp > Traits;
  typedef typename Traits::LocalOperatorType LocalOperatorType;

  Codim0Matrix(const LocalOperatorType& op)
    : localOperator_(op)
  {}

  const LocalOperatorType& localOperator() const
  {
    return localOperator_;
  }

private:
  static const size_t numTmpObjectsRequired_ = 1;

public:
  std::vector< size_t > numTmpObjectsRequired() const
  {
    return { numTmpObjectsRequired_, localOperator_.numTmpObjectsRequired() };
  }

  /**
   *  \tparam T           Traits of the SpaceInterface implementation, representing the type of testSpace
   *  \tparam A           Traits of the SpaceInterface implementation, representing the type of ansatzSpace
   *  \tparam EntityType  A model of Dune::Entity< 0 >
   *  \tparam M           Traits of the Dune::Stuff::LA::Container::MatrixInterface implementation, representing the type of systemMatrix
   *  \tparam R           RangeFieldType, i.e. double
   */
  template< class T, class A, class EntityType, class M, class R >
  void assembleLocal(const SpaceInterface< T >& testSpace,
                     const SpaceInterface< A >& ansatzSpace,
                     const EntityType& entity,
                     Dune::Stuff::LA::MatrixInterface< M >& systemMatrix,
                     std::vector< std::vector< Dune::DynamicMatrix< R > > >& tmpLocalMatricesContainer,
                     std::vector< Dune::DynamicVector< size_t > >& tmpIndicesContainer) const
  {
    // check
    assert(tmpLocalMatricesContainer.size() >= 1);
    assert(tmpLocalMatricesContainer[0].size() >= numTmpObjectsRequired_);
    assert(tmpLocalMatricesContainer[1].size() >= localOperator_.numTmpObjectsRequired());
    assert(tmpIndicesContainer.size() >= 2);
    // get and clear matrix
    Dune::DynamicMatrix< R >& localMatrix = tmpLocalMatricesContainer[0][0];
    Dune::Stuff::Common::clear(localMatrix);
    auto& tmpOperatorMatrices = tmpLocalMatricesContainer[1];
    // apply local operator (result is in localMatrix)
    localOperator_.apply(testSpace.base_function_set(entity),
                         ansatzSpace.base_function_set(entity),
                         localMatrix,
                         tmpOperatorMatrices);
    // write local matrix to global
    Dune::DynamicVector< size_t >& globalRows = tmpIndicesContainer[0];
    Dune::DynamicVector< size_t >& globalCols = tmpIndicesContainer[1];
    const size_t rows = testSpace.mapper().numDofs(entity);
    const size_t cols = ansatzSpace.mapper().numDofs(entity);
    assert(globalRows.size() >= rows);
    assert(globalCols.size() >= cols);
    testSpace.mapper().globalIndices(entity, globalRows);
    ansatzSpace.mapper().globalIndices(entity, globalCols);
    for (size_t ii = 0; ii < rows; ++ii) {
      const auto& localRow = localMatrix[ii];
      const size_t globalII = globalRows[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        const size_t globalJJ = globalCols[jj];
        systemMatrix.add_to_entry(globalII, globalJJ, localRow[jj]);
      }
    } // write local matrix to global
  } // ... assembleLocal(...)

private:
  const LocalOperatorType& localOperator_;
}; // class LocalAssemblerCodim0Matrix

// forward, to be used in the traits
template< class LocalOperatorImp >
class Codim0Vector;

template< class LocalFunctionalImp >
class Codim0VectorTraits
{
public:
  typedef Codim0Vector< LocalFunctionalImp > derived_type;
  typedef LocalFunctional::Codim0Interface< typename LocalFunctionalImp::Traits > LocalFunctionalType;
}; // class LocalAssemblerCodim0MatrixTraits

template< class LocalFunctionalImp >
class Codim0Vector
{
public:
  typedef Codim0VectorTraits< LocalFunctionalImp > Traits;
  typedef typename Traits::LocalFunctionalType LocalFunctionalType;

  Codim0Vector(const LocalFunctionalType& func)
    : localFunctional_(func)
  {}

  const LocalFunctionalType& localFunctional() const
  {
    return localFunctional_;
  }

private:
  static const size_t numTmpObjectsRequired_ = 1;

public:
  std::vector< size_t > numTmpObjectsRequired() const
  {
    return { numTmpObjectsRequired_, localFunctional_.numTmpObjectsRequired() };
  }

  /**
   *  \tparam T           Traits of the SpaceInterface implementation, representing the type of testSpace
   *  \tparam EntityType  A model of Dune::Entity< 0 >
   *  \tparam V           Traits of the Dune::Stuff::LA::Container::VectorInterface implementation, representing the type of systemVector
   *  \tparam R           RangeFieldType, i.e. double
   */
  template< class T, class EntityType, class V, class R >
  void assembleLocal(const SpaceInterface< T >& testSpace,
                     const EntityType& entity,
                     Dune::Stuff::LA::VectorInterface< V >& systemVector,
                     std::vector< std::vector< Dune::DynamicVector< R > > >& tmpLocalVectorContainer,
                     Dune::DynamicVector< size_t >& tmpIndices) const
  {
    // check
    assert(tmpLocalVectorContainer.size() >= 1);
    assert(tmpLocalVectorContainer[0].size() >= numTmpObjectsRequired_);
    assert(tmpLocalVectorContainer[1].size() >= localFunctional_.numTmpObjectsRequired());
    // get and clear vector
    auto& localVector = tmpLocalVectorContainer[0][0];
    Dune::Stuff::Common::clear(localVector);
    auto& tmpFunctionalVectors = tmpLocalVectorContainer[1];
    // apply local functional (result is in localVector)
    localFunctional_.apply(testSpace.base_function_set(entity),
                           localVector,
                           tmpFunctionalVectors);
    // write local vector to global
    const size_t size = testSpace.mapper().numDofs(entity);
    assert(tmpIndices.size() >= size);
    testSpace.mapper().globalIndices(entity, tmpIndices);
    for (size_t ii = 0; ii < size; ++ii) {
      systemVector.add_to_entry(tmpIndices[ii], localVector[ii]);
    } // write local matrix to global
  } // ... assembleLocal(...)

private:
  const LocalFunctionalType& localFunctional_;
}; // class Codim0Vector

} // namespace LocalAssembler
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH
<commit_msg>[assembler.local.codim0] minor fix<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH
#define DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH

#include <vector>

#include <dune/common/dynmatrix.hh>
#include <dune/common/dynvector.hh>

#include <dune/stuff/common/matrix.hh>
#include <dune/stuff/la/container/interfaces.hh>

#include <dune/gdt/localoperator/interface.hh>
#include <dune/gdt/localfunctional/interface.hh>
#include <dune/gdt/space/interface.hh>

namespace Dune {
namespace GDT {
namespace LocalAssembler {

// forward, to be used in the traits
template< class LocalOperatorImp >
class Codim0Matrix;

template< class LocalOperatorImp >
class Codim0MatrixTraits
{
public:
  typedef Codim0Matrix< LocalOperatorImp > derived_type;
  typedef LocalOperator::Codim0Interface< typename LocalOperatorImp::Traits > LocalOperatorType;
}; // class LocalAssemblerCodim0MatrixTraits

template< class LocalOperatorImp >
class Codim0Matrix
{
public:
  typedef Codim0MatrixTraits< LocalOperatorImp > Traits;
  typedef typename Traits::LocalOperatorType LocalOperatorType;

  Codim0Matrix(const LocalOperatorType& op)
    : localOperator_(op)
  {}

  const LocalOperatorType& localOperator() const
  {
    return localOperator_;
  }

private:
  static const size_t numTmpObjectsRequired_ = 1;

public:
  std::vector< size_t > numTmpObjectsRequired() const
  {
    return { numTmpObjectsRequired_, localOperator_.numTmpObjectsRequired() };
  }

  /**
   *  \tparam T           Traits of the SpaceInterface implementation, representing the type of testSpace
   *  \tparam A           Traits of the SpaceInterface implementation, representing the type of ansatzSpace
   *  \tparam EntityType  A model of Dune::Entity< 0 >
   *  \tparam M           Traits of the Dune::Stuff::LA::Container::MatrixInterface implementation, representing the type of systemMatrix
   *  \tparam R           RangeFieldType, i.e. double
   */
  template< class T, class A, class EntityType, class M, class R >
  void assembleLocal(const SpaceInterface< T >& testSpace,
                     const SpaceInterface< A >& ansatzSpace,
                     const EntityType& entity,
                     Dune::Stuff::LA::MatrixInterface< M >& systemMatrix,
                     std::vector< std::vector< Dune::DynamicMatrix< R > > >& tmpLocalMatricesContainer,
                     std::vector< Dune::DynamicVector< size_t > >& tmpIndicesContainer) const
  {
    // check
    assert(tmpLocalMatricesContainer.size() >= 1);
    assert(tmpLocalMatricesContainer[0].size() >= numTmpObjectsRequired_);
    assert(tmpLocalMatricesContainer[1].size() >= localOperator_.numTmpObjectsRequired());
    assert(tmpIndicesContainer.size() >= 2);
    // get and clear matrix
    Dune::DynamicMatrix< R >& localMatrix = tmpLocalMatricesContainer[0][0];
    Dune::Stuff::Common::clear(localMatrix);
    auto& tmpOperatorMatrices = tmpLocalMatricesContainer[1];
    // apply local operator (result is in localMatrix)
    localOperator_.apply(testSpace.base_function_set(entity),
                         ansatzSpace.base_function_set(entity),
                         localMatrix,
                         tmpOperatorMatrices);
    // write local matrix to global
    Dune::DynamicVector< size_t >& globalRows = tmpIndicesContainer[0];
    Dune::DynamicVector< size_t >& globalCols = tmpIndicesContainer[1];
    const size_t rows = testSpace.mapper().numDofs(entity);
    const size_t cols = ansatzSpace.mapper().numDofs(entity);
    assert(globalRows.size() >= rows);
    assert(globalCols.size() >= cols);
    testSpace.mapper().globalIndices(entity, globalRows);
    ansatzSpace.mapper().globalIndices(entity, globalCols);
    for (size_t ii = 0; ii < rows; ++ii) {
      const auto& localRow = localMatrix[ii];
      const size_t globalII = globalRows[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        const size_t globalJJ = globalCols[jj];
        systemMatrix.add_to_entry(globalII, globalJJ, localRow[jj]);
      }
    } // write local matrix to global
  } // ... assembleLocal(...)

private:
  const LocalOperatorType& localOperator_;
}; // class LocalAssemblerCodim0Matrix

// forward, to be used in the traits
template< class LocalOperatorImp >
class Codim0Vector;

template< class LocalFunctionalImp >
class Codim0VectorTraits
{
public:
  typedef Codim0Vector< LocalFunctionalImp > derived_type;
  typedef LocalFunctional::Codim0Interface< typename LocalFunctionalImp::Traits > LocalFunctionalType;
}; // class LocalAssemblerCodim0MatrixTraits

template< class LocalFunctionalImp >
class Codim0Vector
{
public:
  typedef Codim0VectorTraits< LocalFunctionalImp > Traits;
  typedef typename Traits::LocalFunctionalType LocalFunctionalType;

  Codim0Vector(const LocalFunctionalType& func)
    : localFunctional_(func)
  {}

  const LocalFunctionalType& localFunctional() const
  {
    return localFunctional_;
  }

private:
  static const size_t numTmpObjectsRequired_ = 1;

public:
  std::vector< size_t > numTmpObjectsRequired() const
  {
    return { numTmpObjectsRequired_, localFunctional_.numTmpObjectsRequired() };
  }

  /**
   *  \tparam T           Traits of the SpaceInterface implementation, representing the type of testSpace
   *  \tparam EntityType  A model of Dune::Entity< 0 >
   *  \tparam V           Traits of the Dune::Stuff::LA::Container::VectorInterface implementation, representing the type of systemVector
   *  \tparam R           RangeFieldType, i.e. double
   */
  template< class T, class EntityType, class V, class R >
  void assembleLocal(const SpaceInterface< T >& testSpace,
                     const EntityType& entity,
                     Dune::Stuff::LA::VectorInterface< V >& systemVector,
                     std::vector< std::vector< Dune::DynamicVector< R > > >& tmpLocalVectorContainer,
                     Dune::DynamicVector< size_t >& tmpIndices) const
  {
    // check
    assert(tmpLocalVectorContainer.size() >= 2);
    assert(tmpLocalVectorContainer[0].size() >= numTmpObjectsRequired_);
    assert(tmpLocalVectorContainer[1].size() >= localFunctional_.numTmpObjectsRequired());
    // get and clear vector
    auto& localVector = tmpLocalVectorContainer[0][0];
    Dune::Stuff::Common::clear(localVector);
    auto& tmpFunctionalVectors = tmpLocalVectorContainer[1];
    // apply local functional (result is in localVector)
    localFunctional_.apply(testSpace.base_function_set(entity),
                           localVector,
                           tmpFunctionalVectors);
    // write local vector to global
    const size_t size = testSpace.mapper().numDofs(entity);
    assert(tmpIndices.size() >= size);
    testSpace.mapper().globalIndices(entity, tmpIndices);
    for (size_t ii = 0; ii < size; ++ii) {
      systemVector.add_to_entry(tmpIndices[ii], localVector[ii]);
    } // write local matrix to global
  } // ... assembleLocal(...)

private:
  const LocalFunctionalType& localFunctional_;
}; // class Codim0Vector

} // namespace LocalAssembler
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH
<|endoftext|>


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

#include "rpcserver.h"
#include "rpcclient.h"
#include "init.h"
#include "main.h"
#include "noui.h"
#include "ui_interface.h"
#include "util.h"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>

/* Introduction text for doxygen: */

/*! \mainpage Developer documentation
 *
 * \section intro_sec Introduction
 *
 * This is the developer documentation of the reference client for an experimental new digital currency called Bitcoin (http://www.bitcoin.org/),
 * which enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate
 * with no central authority: managing transactions and issuing money are carried out collectively by the network.
 *
 * The software is a community-driven open source project, released under the MIT license.
 *
 * \section Navigation
 * Use the buttons Namespaces, Classes or Files at the top of the page to start navigating the code.
 */

static bool fDaemon;

void DetectShutdownThread(boost::thread_group* threadGroup)
{
    bool fShutdown = ShutdownRequested();
    // Tell the main threads to shutdown.
    while (!fShutdown)
    {
        MilliSleep(200);
        fShutdown = ShutdownRequested();
    }
    if (threadGroup)
    {
        threadGroup->interrupt_all();
        threadGroup->join_all();
    }
}

//////////////////////////////////////////////////////////////////////////////
//
// Start
//
bool AppInit(int argc, char* argv[])
{
    boost::thread_group threadGroup;
    boost::thread* detectShutdownThread = NULL;

    bool fRet = false;
    try
    {
        //
        // Parameters
        //
        // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
        ParseParameters(argc, argv);
        if (!boost::filesystem::is_directory(GetDataDir(false)))
        {
            fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
            return false;
        }
        try
        {
            ReadConfigFile(mapArgs, mapMultiArgs);
        } catch(std::exception &e) {
            fprintf(stderr,"Error reading configuration file: %s\n", e.what());
            return false;
        }
        // Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause)
        if (!SelectParamsFromCommandLine()) {
            fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
            return false;
        }

        if (mapArgs.count("-?") || mapArgs.count("--help"))
        {
            // First part of help message is specific to bitcoind / RPC client
            std::string strUsage = _("Reddcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n\n" +
                _("Usage:") + "\n" +
                  "  reddcoind [options]                     " + _("Start Reddcoin Core Daemon") + "\n" +
                _("Usage (deprecated, use reddcoin-cli):") + "\n" +
                  "  reddcoind [options] <command> [params]  " + _("Send command to Reddcoin Core") + "\n" +
                  "  reddcoind [options] help                " + _("List commands") + "\n" +
                  "  reddcoind [options] help <command>      " + _("Get help for a command") + "\n";

            strUsage += "\n" + HelpMessage(HMM_BITCOIND);
            strUsage += "\n" + HelpMessageCli(false);

            fprintf(stdout, "%s", strUsage.c_str());
            return false;
        }

        // Command-line RPC
        bool fCommandLine = false;
        for (int i = 1; i < argc; i++)
            if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:"))
                fCommandLine = true;

        if (fCommandLine)
        {
            int ret = CommandLineRPC(argc, argv);
            exit(ret);
        }
#ifndef WIN32
        fDaemon = GetBoolArg("-daemon", false);
        if (fDaemon)
        {
            fprintf(stdout, "Reddcoin server starting\n");

            // Daemonize
            pid_t pid = fork();
            if (pid < 0)
            {
                fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
                return false;
            }
            if (pid > 0) // Parent process, pid is child process id
            {
                CreatePidFile(GetPidFile(), pid);
                return true;
            }
            // Child process falls through to rest of initialization

            pid_t sid = setsid();
            if (sid < 0)
                fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
        }
#endif
        SoftSetBoolArg("-server", true);

        detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup));
        fRet = AppInit2(threadGroup);
    }
    catch (std::exception& e) {
        PrintExceptionContinue(&e, "AppInit()");
    } catch (...) {
        PrintExceptionContinue(NULL, "AppInit()");
    }

    if (!fRet)
    {
        if (detectShutdownThread)
            detectShutdownThread->interrupt();

        threadGroup.interrupt_all();
        // threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
        // the startup-failure cases to make sure they don't result in a hang due to some
        // thread-blocking-waiting-for-another-thread-during-startup case
    }

    if (detectShutdownThread)
    {
        detectShutdownThread->join();
        delete detectShutdownThread;
        detectShutdownThread = NULL;
    }
    Shutdown();

    return fRet;
}

int main(int argc, char* argv[])
{
    SetupEnvironment();

    bool fRet = false;

    // Connect bitcoind signal handlers
    noui_connect();

    fRet = AppInit(argc, argv);

    if (fRet && fDaemon)
        return 0;

    return (fRet ? 0 : 1);
}
<commit_msg>Remove fDaemon flag checking on return from main(), which is useless and looks really strange.<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "rpcserver.h"
#include "rpcclient.h"
#include "init.h"
#include "main.h"
#include "noui.h"
#include "ui_interface.h"
#include "util.h"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>

/* Introduction text for doxygen: */

/*! \mainpage Developer documentation
 *
 * \section intro_sec Introduction
 *
 * This is the developer documentation of the reference client for an experimental new digital currency called Bitcoin (http://www.bitcoin.org/),
 * which enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate
 * with no central authority: managing transactions and issuing money are carried out collectively by the network.
 *
 * The software is a community-driven open source project, released under the MIT license.
 *
 * \section Navigation
 * Use the buttons Namespaces, Classes or Files at the top of the page to start navigating the code.
 */

static bool fDaemon;

void DetectShutdownThread(boost::thread_group* threadGroup)
{
    bool fShutdown = ShutdownRequested();
    // Tell the main threads to shutdown.
    while (!fShutdown)
    {
        MilliSleep(200);
        fShutdown = ShutdownRequested();
    }
    if (threadGroup)
    {
        threadGroup->interrupt_all();
        threadGroup->join_all();
    }
}

//////////////////////////////////////////////////////////////////////////////
//
// Start
//
bool AppInit(int argc, char* argv[])
{
    boost::thread_group threadGroup;
    boost::thread* detectShutdownThread = NULL;

    bool fRet = false;
    try
    {
        //
        // Parameters
        //
        // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
        ParseParameters(argc, argv);
        if (!boost::filesystem::is_directory(GetDataDir(false)))
        {
            fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
            return false;
        }
        try
        {
            ReadConfigFile(mapArgs, mapMultiArgs);
        } catch(std::exception &e) {
            fprintf(stderr,"Error reading configuration file: %s\n", e.what());
            return false;
        }
        // Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause)
        if (!SelectParamsFromCommandLine()) {
            fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
            return false;
        }

        if (mapArgs.count("-?") || mapArgs.count("--help"))
        {
            // First part of help message is specific to bitcoind / RPC client
            std::string strUsage = _("Reddcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n\n" +
                _("Usage:") + "\n" +
                  "  reddcoind [options]                     " + _("Start Reddcoin Core Daemon") + "\n" +
                _("Usage (deprecated, use reddcoin-cli):") + "\n" +
                  "  reddcoind [options] <command> [params]  " + _("Send command to Reddcoin Core") + "\n" +
                  "  reddcoind [options] help                " + _("List commands") + "\n" +
                  "  reddcoind [options] help <command>      " + _("Get help for a command") + "\n";

            strUsage += "\n" + HelpMessage(HMM_BITCOIND);
            strUsage += "\n" + HelpMessageCli(false);

            fprintf(stdout, "%s", strUsage.c_str());
            return false;
        }

        // Command-line RPC
        bool fCommandLine = false;
        for (int i = 1; i < argc; i++)
            if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:"))
                fCommandLine = true;

        if (fCommandLine)
        {
            int ret = CommandLineRPC(argc, argv);
            exit(ret);
        }
#ifndef WIN32
        fDaemon = GetBoolArg("-daemon", false);
        if (fDaemon)
        {
            fprintf(stdout, "Reddcoin server starting\n");

            // Daemonize
            pid_t pid = fork();
            if (pid < 0)
            {
                fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
                return false;
            }
            if (pid > 0) // Parent process, pid is child process id
            {
                CreatePidFile(GetPidFile(), pid);
                return true;
            }
            // Child process falls through to rest of initialization

            pid_t sid = setsid();
            if (sid < 0)
                fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
        }
#endif
        SoftSetBoolArg("-server", true);

        detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup));
        fRet = AppInit2(threadGroup);
    }
    catch (std::exception& e) {
        PrintExceptionContinue(&e, "AppInit()");
    } catch (...) {
        PrintExceptionContinue(NULL, "AppInit()");
    }

    if (!fRet)
    {
        if (detectShutdownThread)
            detectShutdownThread->interrupt();

        threadGroup.interrupt_all();
        // threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
        // the startup-failure cases to make sure they don't result in a hang due to some
        // thread-blocking-waiting-for-another-thread-during-startup case
    }

    if (detectShutdownThread)
    {
        detectShutdownThread->join();
        delete detectShutdownThread;
        detectShutdownThread = NULL;
    }
    Shutdown();

    return fRet;
}

int main(int argc, char* argv[])
{
    SetupEnvironment();

    // Connect bitcoind signal handlers
    noui_connect();

    return (AppInit(argc, argv) ? 0 : 1);
}
<|endoftext|>


<commit_before>// This file is part of the dune-pymor project:
//   https://github.com/pymor/dune-pymor
// Copyright holders: Stephan Rave, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_PYMOR_OPERATORS_INTERFACES_HH
#define DUNE_PYMOR_OPERATORS_INTERFACES_HH

#include <dune/stuff/common/type_utils.hh>
#include <dune/stuff/la/container/interfaces.hh>
#include <dune/stuff/la/solver.hh>
#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/common/configuration.hh>

#include <dune/pymor/common/exceptions.hh>
#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/parameters/functional.hh>

namespace Dune {
namespace Pymor {

/**
 *  \brief  Contains tags mostly needed for python bindings.
 */
namespace Tags {

class OperatorInterface {};

class AffinelyDecomposedOperatorInterface : public OperatorInterface {};

} // namespace Tags

template< class Traits >
class OperatorInterface
  : public Parametric
  , public Tags::OperatorInterface
  , public Stuff::CRTPInterface< OperatorInterface< Traits >, Traits >
{
public:
  typedef typename Traits::derived_type derived_type;
  typedef typename Traits::SourceType   SourceType;
  typedef typename Traits::RangeType    RangeType;
  typedef typename Traits::ScalarType   ScalarType;
  typedef typename Traits::FrozenType   FrozenType;
  typedef typename Traits::InverseType  InverseType;

  static_assert(std::is_base_of< Stuff::LA::VectorInterface< typename SourceType::Traits >, SourceType >::value,
                "SourceType has to be derived from Stuff::LA::VectorInterface!");
  static_assert(std::is_base_of< Stuff::LA::VectorInterface< typename RangeType::Traits >, RangeType >::value,
                "RangeType has to be derived from Stuff::LA::VectorInterface!");

  static std::string type_this() {    return Stuff::Common::Typename< derived_type >::value(); }
  static std::string type_source() {  return Stuff::Common::Typename< SourceType >::value(); }
  static std::string type_range() {   return Stuff::Common::Typename< RangeType >::value(); }
  static std::string type_scalar() {  return Stuff::Common::Typename< ScalarType >::value(); }
  static std::string type_frozen() {  return Stuff::Common::Typename< FrozenType >::value(); }
  static std::string type_inverse() { return Stuff::Common::Typename< InverseType >::value(); }

  OperatorInterface(const ParameterType mu = ParameterType())
    : Parametric(mu)
  {}

  OperatorInterface(const Parametric& other)
    : Parametric(other)
  {}

  bool linear() const
  {
    CHECK_CRTP(this->as_imp(*this).linear());
    return this->as_imp(*this).linear();
  }

  DUNE_STUFF_SSIZE_T dim_source() const
  {
    CHECK_CRTP(this->as_imp(*this).dim_source());
    return this->as_imp(*this).dim_source();
  }

  DUNE_STUFF_SSIZE_T dim_range() const
  {
    CHECK_CRTP(this->as_imp(*this).dim_range());
    return this->as_imp(*this).dim_range();
  }

  void apply(const SourceType& source, RangeType& range, const Parameter mu = Parameter()) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp(*this).apply(source, range, mu));
  }

  RangeType apply(const SourceType& source, const Parameter mu = Parameter()) const
  {
    RangeType range(dim_range());
    apply(source, range, mu);
    return range;
  }

  RangeType* apply_and_return_ptr(const SourceType& source, const Parameter mu = Parameter()) const
  {
    return new RangeType(apply(source, mu));
  }

  /**
   * \note  This default implementation of apply2 creates a temporary vector. Any derived class which can do better
   *        should implement this method!
   */
  ScalarType apply2(const RangeType& range, const SourceType& source, const Parameter mu = Parameter()) const
  {
    RangeType tmp = range.copy();
    apply(source, tmp, mu);
    return tmp.dot(range);
  }

  static std::vector< std::string > invert_options()
  {
    return derived_type::invert_options();
  }

  static Stuff::Common::Configuration invert_options(const std::string& type)
  {
    return derived_type::invert_options(type);
  }

  InverseType invert(const std::string type = invert_options()[0], const Parameter mu = Parameter()) const
  {
    return invert(invert_options(type), mu);
  }

  InverseType invert(const Stuff::Common::Configuration& option, const Parameter mu = Parameter()) const
  {
    CHECK_CRTP(this->as_imp(*this).invert(option, mu));
    return this->as_imp(*this).invert(option, mu);
  }

  InverseType* invert_and_return_ptr(const std::string type = invert_options()[0],
                                     const Parameter mu = Parameter()) const
  {
    return new InverseType(invert(type, mu));
  }

  InverseType* invert_and_return_ptr(const Stuff::Common::Configuration& option,
                                     const Parameter mu = Parameter()) const
  {
    return new InverseType(invert(option, mu));
  }

  void apply_inverse(const RangeType& range,
                     SourceType& source,
                     const std::string type = invert_options()[0],
                     const Parameter mu = Parameter()) const
  {
    invert(type, mu).apply(range, source);
  }

  void apply_inverse(const RangeType& range,
                     SourceType& source,
                     const Stuff::Common::Configuration& option,
                     const Parameter mu = Parameter()) const
  {
    invert(option, mu).apply(range, source);
  }

  SourceType apply_inverse(const RangeType& range,
                           const std::string type = invert_options()[0],
                           const Parameter mu = Parameter()) const
  {
    SourceType source(dim_source());
    apply_inverse(range, source, type, mu);
    return source;
  }

  SourceType apply_inverse(const RangeType& range,
                           const Stuff::Common::Configuration& option,
                           const Parameter mu = Parameter()) const
  {
    SourceType source(dim_source());
    apply_inverse(range, source, option, mu);
    return source;
  }

  SourceType* apply_inverse_and_return_ptr(const RangeType& range,
                                           const std::string tyep = invert_options()[0],
                                           const Parameter mu = Parameter()) const
  {
    return new SourceType(apply_inverse(range, tyep, mu));
  }

  SourceType* apply_inverse_and_return_ptr(const RangeType& range,
                                           const Stuff::Common::Configuration& option,
                                           const Parameter mu = Parameter()) const
  {
    return new SourceType(apply_inverse(range, option, mu));
  }

  /**
   * \note  May throw Exceptions::this_is_not_parametric.
   */
  FrozenType freeze_parameter(const Parameter mu = Parameter()) const
  {
    CHECK_CRTP(this->as_imp(*this).freeze_parameter(mu));
    return this->as_imp(*this).freeze_parameter(mu);
  }

  FrozenType* freeze_parameter_and_return_ptr(const Parameter mu = Parameter()) const
  {
    return new FrozenType(freeze_parameter(mu));
  }
}; // class OperatorInterface

template< class Traits >
class AffinelyDecomposedOperatorInterface
  : public OperatorInterface< Traits >
  , public Tags::AffinelyDecomposedOperatorInterface
{
  typedef Pymor::OperatorInterface< Traits > BaseType;
public:
  typedef typename Traits::derived_type   derived_type;
  typedef typename Traits::ComponentType  ComponentType;
  static_assert(std::is_base_of< Pymor::OperatorInterface< typename ComponentType::Traits >, ComponentType >::value,
                "ComponentType has to be derived from OperatorInterface");

  AffinelyDecomposedOperatorInterface(const ParameterType mu = ParameterType())
    : BaseType(mu)
  {}

  AffinelyDecomposedOperatorInterface(const Parametric& other)
    : BaseType(other)
  {}

  DUNE_STUFF_SSIZE_T num_components() const
  {
    CHECK_CRTP(this->as_imp(*this).num_components());
    return this->as_imp(*this).num_components();
  }

  /**
   * \note  May throw one of Stuff::Exceptions::requirements_not_met, Stuff::Exceptions::index_out_of_range.
   */
  ComponentType component(const DUNE_STUFF_SSIZE_T qq) const
  {
    CHECK_CRTP(this->as_imp(*this).component(qq));
    return this->as_imp(*this).component(qq);
  }

  ComponentType* component_and_return_ptr(const DUNE_STUFF_SSIZE_T qq) const
  {
    return new ComponentType(component(qq));
  }

  /**
   * \note  May throw one of Stuff::Exceptions::requirements_not_met, Stuff::Exceptions::index_out_of_range.
   */
  ParameterFunctional coefficient(const DUNE_STUFF_SSIZE_T qq) const
  {
    CHECK_CRTP(this->as_imp(*this).coefficient(qq));
    return this->as_imp(*this).coefficient(qq);
  }

  ParameterFunctional* coefficient_and_return_ptr(const DUNE_STUFF_SSIZE_T qq) const
  {
    return new ParameterFunctional(coefficient(qq));
  }

  bool has_affine_part() const
  {
    CHECK_CRTP(this->as_imp(*this).has_affine_part());
    return this->as_imp(*this).has_affine_part();
  }

  /**
   * \note  May throw Stuff::Exceptions::requirements_not_met.
   */
  ComponentType affine_part() const
  {
    CHECK_CRTP(this->as_imp(*this).affine_part());
    return this->as_imp(*this).affine_part();
  }

  ComponentType* affine_part_and_return_ptr() const
  {
    return new ComponentType(affine_part());
  }
}; // class AffinelyDecomposedOperatorInterface

} // namespace Pymor
} // namespace Dune

#endif // DUNE_PYMOR_OPERATORS_INTERFACES_HH
<commit_msg>[operators.interfaces] make some default implementations virtual<commit_after>// This file is part of the dune-pymor project:
//   https://github.com/pymor/dune-pymor
// Copyright holders: Stephan Rave, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_PYMOR_OPERATORS_INTERFACES_HH
#define DUNE_PYMOR_OPERATORS_INTERFACES_HH

#include <dune/stuff/common/type_utils.hh>
#include <dune/stuff/la/container/interfaces.hh>
#include <dune/stuff/la/solver.hh>
#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/common/configuration.hh>

#include <dune/pymor/common/exceptions.hh>
#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/parameters/functional.hh>

namespace Dune {
namespace Pymor {

/**
 *  \brief  Contains tags mostly needed for python bindings.
 */
namespace Tags {

class OperatorInterface {};

class AffinelyDecomposedOperatorInterface : public OperatorInterface {};

} // namespace Tags

template< class Traits >
class OperatorInterface
  : public Parametric
  , public Tags::OperatorInterface
  , public Stuff::CRTPInterface< OperatorInterface< Traits >, Traits >
{
public:
  typedef typename Traits::derived_type derived_type;
  typedef typename Traits::SourceType   SourceType;
  typedef typename Traits::RangeType    RangeType;
  typedef typename Traits::ScalarType   ScalarType;
  typedef typename Traits::FrozenType   FrozenType;
  typedef typename Traits::InverseType  InverseType;

  static_assert(Stuff::LA::is_vector< SourceType >::value,
                "SourceType has to be derived from Stuff::LA::VectorInterface!");
  static_assert(Stuff::LA::is_vector< RangeType >::value,
                "RangeType has to be derived from Stuff::LA::VectorInterface!");

  static std::string type_this() {    return Stuff::Common::Typename< derived_type >::value(); }
  static std::string type_source() {  return Stuff::Common::Typename< SourceType >::value(); }
  static std::string type_range() {   return Stuff::Common::Typename< RangeType >::value(); }
  static std::string type_scalar() {  return Stuff::Common::Typename< ScalarType >::value(); }
  static std::string type_frozen() {  return Stuff::Common::Typename< FrozenType >::value(); }
  static std::string type_inverse() { return Stuff::Common::Typename< InverseType >::value(); }

  OperatorInterface(const ParameterType mu = ParameterType())
    : Parametric(mu)
  {}

  OperatorInterface(const Parametric& other)
    : Parametric(other)
  {}

  virtual ~OperatorInterface() {}

  bool linear() const
  {
    CHECK_CRTP(this->as_imp(*this).linear());
    return this->as_imp(*this).linear();
  }

  DUNE_STUFF_SSIZE_T dim_source() const
  {
    CHECK_CRTP(this->as_imp(*this).dim_source());
    return this->as_imp(*this).dim_source();
  }

  DUNE_STUFF_SSIZE_T dim_range() const
  {
    CHECK_CRTP(this->as_imp(*this).dim_range());
    return this->as_imp(*this).dim_range();
  }

  void apply(const SourceType& source, RangeType& range, const Parameter mu = Parameter()) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp(*this).apply(source, range, mu));
  }

  virtual RangeType apply(const SourceType& source, const Parameter mu = Parameter()) const
  {
    RangeType range(dim_range());
    apply(source, range, mu);
    return range;
  }

  RangeType* apply_and_return_ptr(const SourceType& source, const Parameter mu = Parameter()) const
  {
    return new RangeType(apply(source, mu));
  }

  /**
   * \note  This default implementation of apply2 creates a temporary vector. Any derived class which can do better
   *        should implement this method!
   */
  virtual ScalarType apply2(const RangeType& range, const SourceType& source, const Parameter mu = Parameter()) const
  {
    RangeType tmp = range.copy();
    apply(source, tmp, mu);
    return tmp.dot(range);
  }

  static std::vector< std::string > invert_options()
  {
    return derived_type::invert_options();
  }

  static Stuff::Common::Configuration invert_options(const std::string& type)
  {
    return derived_type::invert_options(type);
  }

  InverseType invert(const std::string type = invert_options()[0], const Parameter mu = Parameter()) const
  {
    return invert(invert_options(type), mu);
  }

  InverseType invert(const Stuff::Common::Configuration& option, const Parameter mu = Parameter()) const
  {
    CHECK_CRTP(this->as_imp(*this).invert(option, mu));
    return this->as_imp(*this).invert(option, mu);
  }

  InverseType* invert_and_return_ptr(const std::string type = invert_options()[0],
                                     const Parameter mu = Parameter()) const
  {
    return new InverseType(invert(type, mu));
  }

  InverseType* invert_and_return_ptr(const Stuff::Common::Configuration& option,
                                     const Parameter mu = Parameter()) const
  {
    return new InverseType(invert(option, mu));
  }

  void apply_inverse(const RangeType& range,
                     SourceType& source,
                     const std::string type = invert_options()[0],
                     const Parameter mu = Parameter()) const
  {
    invert(type, mu).apply(range, source);
  }

  void apply_inverse(const RangeType& range,
                     SourceType& source,
                     const Stuff::Common::Configuration& option,
                     const Parameter mu = Parameter()) const
  {
    invert(option, mu).apply(range, source);
  }

  virtual SourceType apply_inverse(const RangeType& range,
                                   const std::string type = invert_options()[0],
                                   const Parameter mu = Parameter()) const
  {
    SourceType source(dim_source());
    apply_inverse(range, source, type, mu);
    return source;
  }

  virtual SourceType apply_inverse(const RangeType& range,
                                   const Stuff::Common::Configuration& option,
                                   const Parameter mu = Parameter()) const
  {
    SourceType source(dim_source());
    apply_inverse(range, source, option, mu);
    return source;
  }

  SourceType* apply_inverse_and_return_ptr(const RangeType& range,
                                           const std::string tyep = invert_options()[0],
                                           const Parameter mu = Parameter()) const
  {
    return new SourceType(apply_inverse(range, tyep, mu));
  }

  SourceType* apply_inverse_and_return_ptr(const RangeType& range,
                                           const Stuff::Common::Configuration& option,
                                           const Parameter mu = Parameter()) const
  {
    return new SourceType(apply_inverse(range, option, mu));
  }

  /**
   * \note  May throw Exceptions::this_is_not_parametric.
   */
  FrozenType freeze_parameter(const Parameter mu = Parameter()) const
  {
    CHECK_CRTP(this->as_imp(*this).freeze_parameter(mu));
    return this->as_imp(*this).freeze_parameter(mu);
  }

  FrozenType* freeze_parameter_and_return_ptr(const Parameter mu = Parameter()) const
  {
    return new FrozenType(freeze_parameter(mu));
  }
}; // class OperatorInterface

template< class Traits >
class AffinelyDecomposedOperatorInterface
  : public OperatorInterface< Traits >
  , public Tags::AffinelyDecomposedOperatorInterface
{
  typedef Pymor::OperatorInterface< Traits > BaseType;
public:
  typedef typename Traits::derived_type   derived_type;
  typedef typename Traits::ComponentType  ComponentType;
  static_assert(std::is_base_of< Pymor::OperatorInterface< typename ComponentType::Traits >, ComponentType >::value,
                "ComponentType has to be derived from OperatorInterface");

  AffinelyDecomposedOperatorInterface(const ParameterType mu = ParameterType())
    : BaseType(mu)
  {}

  AffinelyDecomposedOperatorInterface(const Parametric& other)
    : BaseType(other)
  {}

  DUNE_STUFF_SSIZE_T num_components() const
  {
    CHECK_CRTP(this->as_imp(*this).num_components());
    return this->as_imp(*this).num_components();
  }

  /**
   * \note  May throw one of Stuff::Exceptions::requirements_not_met, Stuff::Exceptions::index_out_of_range.
   */
  ComponentType component(const DUNE_STUFF_SSIZE_T qq) const
  {
    CHECK_CRTP(this->as_imp(*this).component(qq));
    return this->as_imp(*this).component(qq);
  }

  ComponentType* component_and_return_ptr(const DUNE_STUFF_SSIZE_T qq) const
  {
    return new ComponentType(component(qq));
  }

  /**
   * \note  May throw one of Stuff::Exceptions::requirements_not_met, Stuff::Exceptions::index_out_of_range.
   */
  ParameterFunctional coefficient(const DUNE_STUFF_SSIZE_T qq) const
  {
    CHECK_CRTP(this->as_imp(*this).coefficient(qq));
    return this->as_imp(*this).coefficient(qq);
  }

  ParameterFunctional* coefficient_and_return_ptr(const DUNE_STUFF_SSIZE_T qq) const
  {
    return new ParameterFunctional(coefficient(qq));
  }

  bool has_affine_part() const
  {
    CHECK_CRTP(this->as_imp(*this).has_affine_part());
    return this->as_imp(*this).has_affine_part();
  }

  /**
   * \note  May throw Stuff::Exceptions::requirements_not_met.
   */
  ComponentType affine_part() const
  {
    CHECK_CRTP(this->as_imp(*this).affine_part());
    return this->as_imp(*this).affine_part();
  }

  ComponentType* affine_part_and_return_ptr() const
  {
    return new ComponentType(affine_part());
  }
}; // class AffinelyDecomposedOperatorInterface

} // namespace Pymor
} // namespace Dune

#endif // DUNE_PYMOR_OPERATORS_INTERFACES_HH
<|endoftext|>