<commit_before>#include "ovpCBoxAlgorithmOpenALSoundPlayer.h"

#if defined TARGET_HAS_ThirdPartyOpenAL

using namespace OpenViBE;
using namespace OpenViBE::Kernel;
using namespace OpenViBE::Plugins;

using namespace OpenViBEPlugins;
using namespace OpenViBEPlugins::Stimulation;

using namespace std;

#define boolean OpenViBE::boolean

#define BUFFER_SIZE 32768
#define UNIQUE_SOURCE 1

boolean CBoxAlgorithmOpenALSoundPlayer::initialize(void)
{

	m_pStreamDecoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationStreamDecoder));
	m_pStreamDecoder->initialize();

	m_pStreamEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationStreamEncoder));
	m_pStreamEncoder->initialize();
	ip_pStimulationSet.initialize(m_pStreamEncoder->getInputParameter(OVP_GD_Algorithm_StimulationStreamEncoder_InputParameterId_StimulationSet));
	op_pMemoryBuffer.initialize(m_pStreamEncoder->getOutputParameter(OVP_GD_Algorithm_StimulationStreamEncoder_OutputParameterId_EncodedMemoryBuffer));

	m_ui64PlayTrigger = FSettingValueAutoCast(*this->getBoxAlgorithmContext(),0);
	m_ui64StopTrigger = FSettingValueAutoCast(*this->getBoxAlgorithmContext(),1);
	m_sFileName = FSettingValueAutoCast(*this->getBoxAlgorithmContext(),2);
	m_bLoop = FSettingValueAutoCast(*this->getBoxAlgorithmContext(),3);

	m_ui64LastOutputChunkDate = -1;
	m_bStartOfSoundSent = false;
	m_bEndOfSoundSent = false;

	if(alutInit(NULL,NULL) != AL_TRUE)
	{
		if(alutGetError () == ALUT_ERROR_INVALID_OPERATION)
		{
			this->getLogManager() << LogLevel_Trace << "ALUT already initialized.\n";
		}
		else
		{
			this->getLogManager() << LogLevel_Error << "ALUT initialization returned a bad status.\n";
			this->getLogManager() << LogLevel_Error << "ALUT ERROR:\n"<<alutGetErrorString(alutGetError ())<<"\n";
			return false;
		}
	}

	m_iFileFormat = FILE_FORMAT_UNSUPPORTED;

	string l_sFile((const char *)m_sFileName);
	if(l_sFile.find(".wav") !=string::npos)
	{
		m_iFileFormat = FILE_FORMAT_WAV;
	}
	if(l_sFile.find(".ogg") !=string::npos)
	{
		m_iFileFormat = FILE_FORMAT_OGG;
	}
	return openSoundFile();
}

boolean CBoxAlgorithmOpenALSoundPlayer::uninitialize(void)
{
	m_pStreamDecoder->uninitialize();
	getAlgorithmManager().releaseAlgorithm(*m_pStreamDecoder);
	m_pStreamEncoder->uninitialize();
	getAlgorithmManager().releaseAlgorithm(*m_pStreamEncoder);

	boolean l_bStatus = stopSound();

#if UNIQUE_SOURCE
	alDeleteSources(1, &m_uiSourceHandle);
#endif
	alDeleteBuffers(1, &m_uiSoundBufferHandle);

	if(alutExit() != AL_TRUE)
	{
		if(alutGetError () == ALUT_ERROR_INVALID_OPERATION)
		{
			this->getLogManager() << LogLevel_Trace << "ALUT already exited.\n";
		}
		else
		{
			this->getLogManager() << LogLevel_Error << "ALUT uninitialization returned a bad status.\n";
			this->getLogManager() << LogLevel_Error << "ALUT ERROR:\n"<<alutGetErrorString(alutGetError ())<<"\n";
			return false;
		}
	}

	return l_bStatus;

}
boolean CBoxAlgorithmOpenALSoundPlayer::processClock(OpenViBE::CMessageClock& rMessageClock)
{
	getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();

	return true;
}

boolean CBoxAlgorithmOpenALSoundPlayer::process(void)
{
	IBoxIO& l_rDynamicBoxContext=this->getDynamicBoxContext();

	op_pMemoryBuffer=l_rDynamicBoxContext.getOutputChunk(0);

	if(m_ui64LastOutputChunkDate == -1)
	{
		m_ui64LastOutputChunkDate = this->getPlayerContext().getCurrentTime();
		m_pStreamEncoder->process(OVP_GD_Algorithm_StimulationStreamEncoder_InputTriggerId_EncodeHeader);
		l_rDynamicBoxContext.markOutputAsReadyToSend(0, 0, m_ui64LastOutputChunkDate);
	}

	for(uint32 i=0; i<l_rDynamicBoxContext.getInputChunkCount(0); i++)
	{
		TParameterHandler < const IMemoryBuffer* > l_ipMemoryBuffer(m_pStreamDecoder->getInputParameter(OVP_GD_Algorithm_StimulationStreamDecoder_InputParameterId_MemoryBufferToDecode));
		l_ipMemoryBuffer=l_rDynamicBoxContext.getInputChunk(0, i);
		m_pStreamDecoder->process();
		if(m_pStreamDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationStreamDecoder_OutputTriggerId_ReceivedHeader))
		{
		}
		if(m_pStreamDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationStreamDecoder_OutputTriggerId_ReceivedBuffer))
		{
			TParameterHandler < IStimulationSet* > l_opStimulationSet(m_pStreamDecoder->getOutputParameter(OVP_GD_Algorithm_StimulationStreamDecoder_OutputParameterId_StimulationSet));
			for(uint32 j=0; j<l_opStimulationSet->getStimulationCount(); j++)
			{
				if(l_opStimulationSet->getStimulationIdentifier(j) == m_ui64PlayTrigger)
				{
					playSound();
					m_bEndOfSoundSent = false;
				}
				if(l_opStimulationSet->getStimulationIdentifier(j) == m_ui64StopTrigger)
				{
					stopSound();
					m_bStartOfSoundSent = false;
				}
			}
		}
		if(m_pStreamDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationStreamDecoder_OutputTriggerId_ReceivedEnd))
		{
			m_pStreamEncoder->process(OVP_GD_Algorithm_StimulationStreamEncoder_InputTriggerId_EncodeEnd);
			l_rDynamicBoxContext.markOutputAsReadyToSend(0, l_rDynamicBoxContext.getInputChunkStartTime(0, i), l_rDynamicBoxContext.getInputChunkEndTime(0, i));
		}

		l_rDynamicBoxContext.markInputAsDeprecated(0, i);
	}

	ALint l_uiStatus;
	alGetSourcei(m_uiSourceHandle, AL_SOURCE_STATE, &l_uiStatus);
	if(l_uiStatus == AL_STOPPED && !m_bEndOfSoundSent)
	{
		ip_pStimulationSet->clear();
		ip_pStimulationSet->appendStimulation(
			m_ui64StopTrigger,
			m_ui64LastOutputChunkDate,
			0);
		m_pStreamEncoder->process(OVP_GD_Algorithm_StimulationStreamEncoder_InputTriggerId_EncodeBuffer);
		l_rDynamicBoxContext.markOutputAsReadyToSend(0, m_ui64LastOutputChunkDate, this->getPlayerContext().getCurrentTime());
		m_bEndOfSoundSent = true;
	}
	if(l_uiStatus == AL_PLAYING && !m_bStartOfSoundSent)
	{
		ip_pStimulationSet->clear();
		ip_pStimulationSet->appendStimulation(
			m_ui64PlayTrigger,
			m_ui64LastOutputChunkDate,
			0);
		m_pStreamEncoder->process(OVP_GD_Algorithm_StimulationStreamEncoder_InputTriggerId_EncodeBuffer);
		l_rDynamicBoxContext.markOutputAsReadyToSend(0, m_ui64LastOutputChunkDate, this->getPlayerContext().getCurrentTime());
		m_bStartOfSoundSent = true;
	}

	m_ui64LastOutputChunkDate = this->getPlayerContext().getCurrentTime();

	return true;
}

boolean CBoxAlgorithmOpenALSoundPlayer::openSoundFile()
{
	switch(m_iFileFormat)
	{
		case FILE_FORMAT_WAV:
		{
			this->getLogManager() << LogLevel_Trace << "Buffering WAV file (this step may take some times for long files).\n";
			m_uiSoundBufferHandle = alutCreateBufferFromFile(m_sFileName);
			this->getLogManager() << LogLevel_Trace << "WAV file buffered.\n";
			if(m_uiSoundBufferHandle == AL_NONE)
			{
				this->getLogManager() << LogLevel_Error << "ALUT can't create buffer from file "<<m_sFileName<<"\n";
				this->getLogManager() << LogLevel_Error << "ALUT ERROR:\n"<<alutGetErrorString(alutGetError ())<<"\n";
				return false;
			}
			break;
		}
		case FILE_FORMAT_OGG:
		{
			// On windows using fopen+ov_open can lead to failure, as stated in the vorbis official documentation:
			//http://xiph.org/vorbis/doc/vorbisfile/ov_open.html
			// using ov_fopen instead.
			//m_oOggVorbisStream.File = fopen((const char *)m_sFileName, "rb");
			//if (m_oOggVorbisStream.File == NULL)
			//{
			//	this->getLogManager() << LogLevel_Error << "Can't open file "<<m_sFileName<<": IO error\n.";
			//	return false;
			//}

#if defined OVP_OS_Windows
			if(ov_fopen(const_cast<char*>(m_sFileName.toASCIIString()), &m_oOggVorbisStream.Stream) < 0)
#elif defined OVP_OS_Linux
			if((m_oOggVorbisStream.File = fopen((const char *)m_sFileName, "rb")) == NULL)
			{
				this->getLogManager() << LogLevel_Error << "Can't open file "<<m_sFileName<<": IO error\n.";
				return false;
			}
			if(ov_open(m_oOggVorbisStream.File, &(m_oOggVorbisStream.Stream), NULL, 0) < 0)
#else
#error "Please port this code"
#endif
			{
				this->getLogManager() << LogLevel_Error << "Can't open file "<<m_sFileName<<": OGG VORBIS stream error\n";
				return false;
			}

			vorbis_info* l_pInfos = ov_info(&m_oOggVorbisStream.Stream, -1);
			m_oOggVorbisStream.Format     = l_pInfos->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
			m_oOggVorbisStream.SampleRate = l_pInfos->rate;

			//Now we fill the raw buffer (good for small piece of sound... use buffering for big files)
			this->getLogManager() << LogLevel_Trace << "Buffering OGG file (this step may take some times for long files).\n";
			int32 l_iBytesRead;
			int32 bitStream;
			char l_pBuffer[BUFFER_SIZE];
			do {
				// Read up to a buffer's worth of decoded sound data
				l_iBytesRead = ov_read(&m_oOggVorbisStream.Stream, l_pBuffer, BUFFER_SIZE, 0, 2, 1, &bitStream);
				// Append to end of buffer
				m_vRawOggBufferFromFile.insert(m_vRawOggBufferFromFile.end(), l_pBuffer, l_pBuffer + l_iBytesRead);
			} while (l_iBytesRead > 0);
			this->getLogManager() << LogLevel_Trace << "OGG file buffered.\n";

			//we have decoded all the file. we drop the decoder (file is closed for us).
			ov_clear(&m_oOggVorbisStream.Stream);

			//create empty buffer
			alGenBuffers(1, &m_uiSoundBufferHandle);
			//fill it with raw data
			alBufferData(m_uiSoundBufferHandle, m_oOggVorbisStream.Format, &m_vRawOggBufferFromFile[0], static_cast < ALsizei > (m_vRawOggBufferFromFile.size()), m_oOggVorbisStream.SampleRate);

			break;
		}
		default:
		{
			this->getLogManager() << LogLevel_Error << "Unsupported file format. Please use only WAV or OGG files.\n";
			return false;
		}
	}

#if UNIQUE_SOURCE
	alGenSources(1, &m_uiSourceHandle);
	alSourcei (m_uiSourceHandle, AL_BUFFER, m_uiSoundBufferHandle);
	alSourcei (m_uiSourceHandle, AL_LOOPING, (m_bLoop?AL_TRUE:AL_FALSE));
#endif
	return true;
}
boolean CBoxAlgorithmOpenALSoundPlayer::playSound()
{
	switch(m_iFileFormat)
	{
		case FILE_FORMAT_WAV:
		case FILE_FORMAT_OGG:
		{
#if UNIQUE_SOURCE
			ALint l_uiStatus;
			alGetSourcei(m_uiSourceHandle, AL_SOURCE_STATE, &l_uiStatus);
			if(l_uiStatus == AL_PLAYING)
			{
				alSourceStop(m_uiSourceHandle);
			}
			alSourcePlay(m_uiSourceHandle);
#else
			ALuint l_uiSource;
			alGenSources(1, &l_uiSource);
			m_vOpenALSources.push_back(l_uiSource);
			alSourcei (l_uiSource, AL_BUFFER, m_uiSoundBufferHandle);
			alSourcei (l_uiSource, AL_LOOPING, (m_bLoop?AL_TRUE:AL_FALSE));
			alSourcePlay(l_uiSource);
#endif
			break;
		}
		default:
		{
			this->getLogManager() << LogLevel_Error << "Unsupported file format. Please use only WAV or OGG files.\n";
			return false;
		}
	}
	return true;
}
boolean CBoxAlgorithmOpenALSoundPlayer::stopSound()
{
	switch(m_iFileFormat)
	{
		case FILE_FORMAT_WAV:
		case FILE_FORMAT_OGG:
		{

#if UNIQUE_SOURCE
			alSourceStop(m_uiSourceHandle);
#else
			for(uint32 i = 0;i<m_vOpenALSources.size();i++)
			{
				//stop all sources
				alSourceStop(m_vOpenALSources[i]);
				alDeleteSources(1, &m_vOpenALSources[i]);
			}
			m_vOpenALSources.clear();
#endif
			break;
		}
		default:
		{
			this->getLogManager() << LogLevel_Error << "Unsupported file format. Please use only WAV or OGG files.\n";
			return false;
		}
	}

	return true;
}

#endif //TARGET_HAS_ThirdPartyOpenAL
<commit_msg>openvibe-plugins/stimulations: * ovpCBoxAlgorithmOpenALSoundPlayer.cpp : fixed a bug with "play" output stimulation not being sent under certain conditions.<commit_after>#include "ovpCBoxAlgorithmOpenALSoundPlayer.h"

#if defined TARGET_HAS_ThirdPartyOpenAL

using namespace OpenViBE;
using namespace OpenViBE::Kernel;
using namespace OpenViBE::Plugins;

using namespace OpenViBEPlugins;
using namespace OpenViBEPlugins::Stimulation;

using namespace std;

#define boolean OpenViBE::boolean

#define BUFFER_SIZE 32768
#define UNIQUE_SOURCE 1

boolean CBoxAlgorithmOpenALSoundPlayer::initialize(void)
{

	m_pStreamDecoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationStreamDecoder));
	m_pStreamDecoder->initialize();

	m_pStreamEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationStreamEncoder));
	m_pStreamEncoder->initialize();
	ip_pStimulationSet.initialize(m_pStreamEncoder->getInputParameter(OVP_GD_Algorithm_StimulationStreamEncoder_InputParameterId_StimulationSet));
	op_pMemoryBuffer.initialize(m_pStreamEncoder->getOutputParameter(OVP_GD_Algorithm_StimulationStreamEncoder_OutputParameterId_EncodedMemoryBuffer));

	m_ui64PlayTrigger = FSettingValueAutoCast(*this->getBoxAlgorithmContext(),0);
	m_ui64StopTrigger = FSettingValueAutoCast(*this->getBoxAlgorithmContext(),1);
	m_sFileName = FSettingValueAutoCast(*this->getBoxAlgorithmContext(),2);
	m_bLoop = FSettingValueAutoCast(*this->getBoxAlgorithmContext(),3);

	m_ui64LastOutputChunkDate = -1;
	m_bStartOfSoundSent = false;
	m_bEndOfSoundSent = false;

	if(alutInit(NULL,NULL) != AL_TRUE)
	{
		if(alutGetError () == ALUT_ERROR_INVALID_OPERATION)
		{
			this->getLogManager() << LogLevel_Trace << "ALUT already initialized.\n";
		}
		else
		{
			this->getLogManager() << LogLevel_Error << "ALUT initialization returned a bad status.\n";
			this->getLogManager() << LogLevel_Error << "ALUT ERROR:\n"<<alutGetErrorString(alutGetError ())<<"\n";
			return false;
		}
	}

	m_iFileFormat = FILE_FORMAT_UNSUPPORTED;

	string l_sFile((const char *)m_sFileName);
	if(l_sFile.find(".wav") !=string::npos)
	{
		m_iFileFormat = FILE_FORMAT_WAV;
	}
	if(l_sFile.find(".ogg") !=string::npos)
	{
		m_iFileFormat = FILE_FORMAT_OGG;
	}
	return openSoundFile();
}

boolean CBoxAlgorithmOpenALSoundPlayer::uninitialize(void)
{
	m_pStreamDecoder->uninitialize();
	getAlgorithmManager().releaseAlgorithm(*m_pStreamDecoder);
	m_pStreamEncoder->uninitialize();
	getAlgorithmManager().releaseAlgorithm(*m_pStreamEncoder);

	boolean l_bStatus = stopSound();

#if UNIQUE_SOURCE
	alDeleteSources(1, &m_uiSourceHandle);
#endif
	alDeleteBuffers(1, &m_uiSoundBufferHandle);

	if(alutExit() != AL_TRUE)
	{
		if(alutGetError () == ALUT_ERROR_INVALID_OPERATION)
		{
			this->getLogManager() << LogLevel_Trace << "ALUT already exited.\n";
		}
		else
		{
			this->getLogManager() << LogLevel_Error << "ALUT uninitialization returned a bad status.\n";
			this->getLogManager() << LogLevel_Error << "ALUT ERROR:\n"<<alutGetErrorString(alutGetError ())<<"\n";
			return false;
		}
	}

	return l_bStatus;

}
boolean CBoxAlgorithmOpenALSoundPlayer::processClock(OpenViBE::CMessageClock& rMessageClock)
{
	getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();

	return true;
}

boolean CBoxAlgorithmOpenALSoundPlayer::process(void)
{
	IBoxIO& l_rDynamicBoxContext=this->getDynamicBoxContext();

	op_pMemoryBuffer=l_rDynamicBoxContext.getOutputChunk(0);

	if(m_ui64LastOutputChunkDate == -1)
	{
		m_ui64LastOutputChunkDate = this->getPlayerContext().getCurrentTime();
		m_pStreamEncoder->process(OVP_GD_Algorithm_StimulationStreamEncoder_InputTriggerId_EncodeHeader);
		l_rDynamicBoxContext.markOutputAsReadyToSend(0, 0, m_ui64LastOutputChunkDate);
	}

	for(uint32 i=0; i<l_rDynamicBoxContext.getInputChunkCount(0); i++)
	{
		TParameterHandler < const IMemoryBuffer* > l_ipMemoryBuffer(m_pStreamDecoder->getInputParameter(OVP_GD_Algorithm_StimulationStreamDecoder_InputParameterId_MemoryBufferToDecode));
		l_ipMemoryBuffer=l_rDynamicBoxContext.getInputChunk(0, i);
		m_pStreamDecoder->process();
		if(m_pStreamDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationStreamDecoder_OutputTriggerId_ReceivedHeader))
		{
		}
		if(m_pStreamDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationStreamDecoder_OutputTriggerId_ReceivedBuffer))
		{
			TParameterHandler < IStimulationSet* > l_opStimulationSet(m_pStreamDecoder->getOutputParameter(OVP_GD_Algorithm_StimulationStreamDecoder_OutputParameterId_StimulationSet));
			for(uint32 j=0; j<l_opStimulationSet->getStimulationCount(); j++)
			{
				if(l_opStimulationSet->getStimulationIdentifier(j) == m_ui64PlayTrigger)
				{
					playSound();
					m_bEndOfSoundSent = false;
					m_bStartOfSoundSent = false;
				}
				if(l_opStimulationSet->getStimulationIdentifier(j) == m_ui64StopTrigger)
				{
					stopSound();
				}
			}
		}
		if(m_pStreamDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationStreamDecoder_OutputTriggerId_ReceivedEnd))
		{
			m_pStreamEncoder->process(OVP_GD_Algorithm_StimulationStreamEncoder_InputTriggerId_EncodeEnd);
			l_rDynamicBoxContext.markOutputAsReadyToSend(0, l_rDynamicBoxContext.getInputChunkStartTime(0, i), l_rDynamicBoxContext.getInputChunkEndTime(0, i));
		}

		l_rDynamicBoxContext.markInputAsDeprecated(0, i);
	}

	ALint l_uiStatus;
	alGetSourcei(m_uiSourceHandle, AL_SOURCE_STATE, &l_uiStatus);
	if(l_uiStatus == AL_STOPPED && !m_bEndOfSoundSent)
	{
		ip_pStimulationSet->clear();
		ip_pStimulationSet->appendStimulation(
			m_ui64StopTrigger,
			m_ui64LastOutputChunkDate,
			0);
		m_pStreamEncoder->process(OVP_GD_Algorithm_StimulationStreamEncoder_InputTriggerId_EncodeBuffer);
		l_rDynamicBoxContext.markOutputAsReadyToSend(0, m_ui64LastOutputChunkDate, this->getPlayerContext().getCurrentTime());
		m_bEndOfSoundSent = true;
	}
	if(l_uiStatus == AL_PLAYING && !m_bStartOfSoundSent)
	{
		ip_pStimulationSet->clear();
		ip_pStimulationSet->appendStimulation(
			m_ui64PlayTrigger,
			m_ui64LastOutputChunkDate,
			0);
		m_pStreamEncoder->process(OVP_GD_Algorithm_StimulationStreamEncoder_InputTriggerId_EncodeBuffer);
		l_rDynamicBoxContext.markOutputAsReadyToSend(0, m_ui64LastOutputChunkDate, this->getPlayerContext().getCurrentTime());
		m_bStartOfSoundSent = true;
	}

	m_ui64LastOutputChunkDate = this->getPlayerContext().getCurrentTime();

	return true;
}

boolean CBoxAlgorithmOpenALSoundPlayer::openSoundFile()
{
	switch(m_iFileFormat)
	{
		case FILE_FORMAT_WAV:
		{
			this->getLogManager() << LogLevel_Trace << "Buffering WAV file (this step may take some times for long files).\n";
			m_uiSoundBufferHandle = alutCreateBufferFromFile(m_sFileName);
			this->getLogManager() << LogLevel_Trace << "WAV file buffered.\n";
			if(m_uiSoundBufferHandle == AL_NONE)
			{
				this->getLogManager() << LogLevel_Error << "ALUT can't create buffer from file "<<m_sFileName<<"\n";
				this->getLogManager() << LogLevel_Error << "ALUT ERROR:\n"<<alutGetErrorString(alutGetError ())<<"\n";
				return false;
			}
			break;
		}
		case FILE_FORMAT_OGG:
		{
			// On windows using fopen+ov_open can lead to failure, as stated in the vorbis official documentation:
			//http://xiph.org/vorbis/doc/vorbisfile/ov_open.html
			// using ov_fopen instead.
			//m_oOggVorbisStream.File = fopen((const char *)m_sFileName, "rb");
			//if (m_oOggVorbisStream.File == NULL)
			//{
			//	this->getLogManager() << LogLevel_Error << "Can't open file "<<m_sFileName<<": IO error\n.";
			//	return false;
			//}

#if defined OVP_OS_Windows
			if(ov_fopen(const_cast<char*>(m_sFileName.toASCIIString()), &m_oOggVorbisStream.Stream) < 0)
#elif defined OVP_OS_Linux
			if((m_oOggVorbisStream.File = fopen((const char *)m_sFileName, "rb")) == NULL)
			{
				this->getLogManager() << LogLevel_Error << "Can't open file "<<m_sFileName<<": IO error\n.";
				return false;
			}
			if(ov_open(m_oOggVorbisStream.File, &(m_oOggVorbisStream.Stream), NULL, 0) < 0)
#else
#error "Please port this code"
#endif
			{
				this->getLogManager() << LogLevel_Error << "Can't open file "<<m_sFileName<<": OGG VORBIS stream error\n";
				return false;
			}

			vorbis_info* l_pInfos = ov_info(&m_oOggVorbisStream.Stream, -1);
			m_oOggVorbisStream.Format     = l_pInfos->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
			m_oOggVorbisStream.SampleRate = l_pInfos->rate;

			//Now we fill the raw buffer (good for small piece of sound... use buffering for big files)
			this->getLogManager() << LogLevel_Trace << "Buffering OGG file (this step may take some times for long files).\n";
			int32 l_iBytesRead;
			int32 bitStream;
			char l_pBuffer[BUFFER_SIZE];
			do {
				// Read up to a buffer's worth of decoded sound data
				l_iBytesRead = ov_read(&m_oOggVorbisStream.Stream, l_pBuffer, BUFFER_SIZE, 0, 2, 1, &bitStream);
				// Append to end of buffer
				m_vRawOggBufferFromFile.insert(m_vRawOggBufferFromFile.end(), l_pBuffer, l_pBuffer + l_iBytesRead);
			} while (l_iBytesRead > 0);
			this->getLogManager() << LogLevel_Trace << "OGG file buffered.\n";

			//we have decoded all the file. we drop the decoder (file is closed for us).
			ov_clear(&m_oOggVorbisStream.Stream);

			//create empty buffer
			alGenBuffers(1, &m_uiSoundBufferHandle);
			//fill it with raw data
			alBufferData(m_uiSoundBufferHandle, m_oOggVorbisStream.Format, &m_vRawOggBufferFromFile[0], static_cast < ALsizei > (m_vRawOggBufferFromFile.size()), m_oOggVorbisStream.SampleRate);

			break;
		}
		default:
		{
			this->getLogManager() << LogLevel_Error << "Unsupported file format. Please use only WAV or OGG files.\n";
			return false;
		}
	}

#if UNIQUE_SOURCE
	alGenSources(1, &m_uiSourceHandle);
	alSourcei (m_uiSourceHandle, AL_BUFFER, m_uiSoundBufferHandle);
	alSourcei (m_uiSourceHandle, AL_LOOPING, (m_bLoop?AL_TRUE:AL_FALSE));
#endif
	return true;
}
boolean CBoxAlgorithmOpenALSoundPlayer::playSound()
{
	switch(m_iFileFormat)
	{
		case FILE_FORMAT_WAV:
		case FILE_FORMAT_OGG:
		{
#if UNIQUE_SOURCE
			ALint l_uiStatus;
			alGetSourcei(m_uiSourceHandle, AL_SOURCE_STATE, &l_uiStatus);
			if(l_uiStatus == AL_PLAYING)
			{
				alSourceStop(m_uiSourceHandle);
			}
			alSourcePlay(m_uiSourceHandle);
#else
			ALuint l_uiSource;
			alGenSources(1, &l_uiSource);
			m_vOpenALSources.push_back(l_uiSource);
			alSourcei (l_uiSource, AL_BUFFER, m_uiSoundBufferHandle);
			alSourcei (l_uiSource, AL_LOOPING, (m_bLoop?AL_TRUE:AL_FALSE));
			alSourcePlay(l_uiSource);
#endif
			break;
		}
		default:
		{
			this->getLogManager() << LogLevel_Error << "Unsupported file format. Please use only WAV or OGG files.\n";
			return false;
		}
	}
	return true;
}
boolean CBoxAlgorithmOpenALSoundPlayer::stopSound()
{
	switch(m_iFileFormat)
	{
		case FILE_FORMAT_WAV:
		case FILE_FORMAT_OGG:
		{

#if UNIQUE_SOURCE
			alSourceStop(m_uiSourceHandle);
#else
			for(uint32 i = 0;i<m_vOpenALSources.size();i++)
			{
				//stop all sources
				alSourceStop(m_vOpenALSources[i]);
				alDeleteSources(1, &m_vOpenALSources[i]);
			}
			m_vOpenALSources.clear();
#endif
			break;
		}
		default:
		{
			this->getLogManager() << LogLevel_Error << "Unsupported file format. Please use only WAV or OGG files.\n";
			return false;
		}
	}

	return true;
}

#endif //TARGET_HAS_ThirdPartyOpenAL
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 */

#include "payload_processor.h"

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

#include "logging.h"
#include "params.h"
#include "util/posix.h"
#include "util/string.h"

namespace {

const size_t kConsumerBuffer = 10 * 1024 * 1024;  // 10 MB

}

namespace receiver {

FileInfo::FileInfo()
  : total_size(0),
    current_size(0),
    hash_context(),
    hash_buffer(),
    skip(false)
{}

FileInfo::FileInfo(const ObjectPackBuild::Event& event)
  : temp_path(),
    total_size(event.size),
    current_size(0),
    hash_context(shash::ContextPtr(event.id.algorithm)),
    hash_buffer(hash_context.size, 0),
    skip(false)
{
  hash_context.buffer = &hash_buffer[0];
  shash::Init(hash_context);
}

FileInfo::FileInfo(const FileInfo& other)
  : temp_path(other.temp_path),
    total_size(other.total_size),
    current_size(other.current_size),
    hash_context(other.hash_context),
    hash_buffer(other.hash_buffer),
    skip(other.skip)
{
  hash_context.buffer = &hash_buffer[0];
}

FileInfo& FileInfo::operator=(const FileInfo& other) {
  temp_path = other.temp_path;
  total_size = other.total_size;
  current_size = other.current_size;
  hash_context = other.hash_context;
  hash_buffer = other.hash_buffer;
  hash_context.buffer = &hash_buffer[0];
  skip = other.skip;

  return *this;
}

PayloadProcessor::PayloadProcessor()
    : pending_files_(),
      current_repo_(),
      spooler_(),
      temp_dir_(),
      num_errors_(0) {}

PayloadProcessor::~PayloadProcessor() {}

PayloadProcessor::Result PayloadProcessor::Process(
    int fdin, const std::string& header_digest, const std::string& path,
    uint64_t header_size) {
  LogCvmfs(kLogReceiver, kLogSyslog,
           "PayloadProcessor - lease_path: %s, header digest: %s, header "
           "size: %ld",
           path.c_str(), header_digest.c_str(), header_size);

  const size_t first_slash_idx = path.find('/', 0);

  current_repo_ = path.substr(0, first_slash_idx);

  Result init_result = Initialize();
  if (init_result != kSuccess) {
    return init_result;
  }

  // Set up object pack deserialization
  shash::Any digest = shash::MkFromHexPtr(shash::HexPtr(header_digest));

  ObjectPackConsumer deserializer(digest, header_size);
  deserializer.RegisterListener(&PayloadProcessor::ConsumerEventCallback, this);

  int nb = 0;
  ObjectPackBuild::State consumer_state = ObjectPackBuild::kStateContinue;
  std::vector<unsigned char> buffer(kConsumerBuffer, 0);
  do {
    nb = read(fdin, &buffer[0], buffer.size());
    consumer_state = deserializer.ConsumeNext(nb, &buffer[0]);
    if (consumer_state != ObjectPackBuild::kStateContinue &&
        consumer_state != ObjectPackBuild::kStateDone) {
      LogCvmfs(kLogReceiver, kLogSyslogErr,
               "PayloadProcessor - error: %d encountered when consuming object "
               "pack.",
               consumer_state);
      break;
    }
  } while (nb > 0 && consumer_state != ObjectPackBuild::kStateDone);

  assert(pending_files_.empty());

  Result res = Finalize();

  deserializer.UnregisterListeners();

  return res;
}

void PayloadProcessor::ConsumerEventCallback(
    const ObjectPackBuild::Event& event) {
  std::string path("");

  if (event.object_type == ObjectPack::kCas) {
    path = event.id.MakePath();
  } else if (event.object_type == ObjectPack::kNamed) {
    path = event.object_name;
  } else {
    // kEmpty - this is an error.
    LogCvmfs(kLogReceiver, kLogSyslogErr,
             "PayloadProcessor - error: Event received with unknown object.");
    num_errors_++;
    return;
  }

  FileIterator it = pending_files_.find(event.id);
  if (it == pending_files_.end()) {
    FileInfo info(event);

    // If the file already exists in the repository, don't create a temp file,
    // mark it to be skipped in the FileInfo, but keep track of the number of
    // bytes currently written
    if (spooler_->Peek("data/" + path)) {
      LogCvmfs(
          kLogReceiver, kLogSyslog,
          "PayloadProcessor - file %s already exists at destination. "
          "Marking it to be skipped.",
          path.c_str());
      info.skip = true;
    } else {
      // New file to unpack
      const std::string tmp_path =
          CreateTempPath(temp_dir_->dir() + "/payload", 0666);
      if (tmp_path.empty()) {
        LogCvmfs(kLogReceiver, kLogSyslogErr,
                "PayloadProcessor - error: Unable to create temporary path.");
        num_errors_++;
        return;
      }
      info.temp_path = tmp_path;
    }

    pending_files_[event.id] = info;
  }

  FileInfo& info = pending_files_[event.id];

  if (!info.skip) {
    int fdout =
        open(info.temp_path.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0600);
    if (fdout == -1) {
      LogCvmfs(
          kLogReceiver, kLogSyslogErr,
          "PayloadProcessor - error: Unable to open temporary output file: %s",
          info.temp_path.c_str());
      return;
    }

    if (!WriteFile(fdout, event.buf, event.buf_size)) {
      LogCvmfs(kLogReceiver, kLogSyslogErr,
               "PayloadProcessor - error: Unable to write %s",
               info.temp_path.c_str());
      num_errors_++;
      unlink(info.temp_path.c_str());
      close(fdout);
      return;
    }
    close(fdout);

    shash::Update(static_cast<const unsigned char*>(event.buf),
                  event.buf_size,
                  info.hash_context);
  }

  info.current_size += event.buf_size;

  if (info.current_size == info.total_size) {
    if (!info.skip) {
      shash::Any file_hash(event.id.algorithm);
      shash::Final(info.hash_context, &file_hash);

      if (file_hash != event.id) {
        LogCvmfs(
            kLogReceiver, kLogSyslogErr,
            "PayloadProcessor - error: Hash mismatch for unpacked file: event "
            "size: %ld, file size: %ld, event hash: %s, file hash: %s",
            event.size, GetFileSize(info.temp_path),
            event.id.ToString(true).c_str(), file_hash.ToString(true).c_str());
        num_errors_++;
        return;
      }

      Upload(info.temp_path, "data/" + path);
    }

    pending_files_.erase(event.id);
  }
}

PayloadProcessor::Result PayloadProcessor::Initialize() {
  Params params;
  if (!GetParamsFromFile(current_repo_, &params)) {
    LogCvmfs(
        kLogReceiver, kLogSyslogErr,
        "PayloadProcessor - error: Could not get configuration parameters.");
    return kOtherError;
  }

  const std::string spooler_temp_dir =
      GetSpoolerTempDir(params.spooler_configuration);
  assert(!spooler_temp_dir.empty());
  assert(MkdirDeep(spooler_temp_dir + "/receiver", 0666, true));
  temp_dir_ =
      RaiiTempDir::Create(spooler_temp_dir + "/receiver/payload_processor");

  upload::SpoolerDefinition definition(
      params.spooler_configuration, params.hash_alg, params.compression_alg,
      params.generate_legacy_bulk_chunks, params.use_file_chunking,
      params.min_chunk_size, params.avg_chunk_size, params.max_chunk_size,
      "dummy_token", "dummy_key");

  spooler_.Destroy();
  spooler_ = upload::Spooler::Construct(definition);

  return kSuccess;
}

PayloadProcessor::Result PayloadProcessor::Finalize() {
  spooler_->WaitForUpload();
  temp_dir_.Destroy();

  const unsigned num_spooler_errors = spooler_->GetNumberOfErrors();
  if (num_spooler_errors > 0) {
    LogCvmfs(kLogReceiver, kLogSyslogErr,
             "PayloadProcessor - error: Spooler - %d upload(s) failed.",
             num_spooler_errors);
    return kSpoolerError;
  }

  if (GetNumErrors() > 0) {
    LogCvmfs(kLogReceiver, kLogSyslogErr,
             "PayloadProcessor - error: % unpacking error(s).", GetNumErrors());
    return kOtherError;
  }

  return kSuccess;
}

void PayloadProcessor::Upload(const std::string& source,
                              const std::string& dest) {
  spooler_->Upload(source, dest);
}

bool PayloadProcessor::WriteFile(int fd, const void* const buf,
                                 size_t buf_size) {
  return SafeWrite(fd, buf, buf_size);
}

}  // namespace receiver
<commit_msg>lower log verbosity when files are skipped in gateway<commit_after>/**
 * This file is part of the CernVM File System.
 */

#include "payload_processor.h"

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

#include "logging.h"
#include "params.h"
#include "util/posix.h"
#include "util/string.h"

namespace {

const size_t kConsumerBuffer = 10 * 1024 * 1024;  // 10 MB

}

namespace receiver {

FileInfo::FileInfo()
  : total_size(0),
    current_size(0),
    hash_context(),
    hash_buffer(),
    skip(false)
{}

FileInfo::FileInfo(const ObjectPackBuild::Event& event)
  : temp_path(),
    total_size(event.size),
    current_size(0),
    hash_context(shash::ContextPtr(event.id.algorithm)),
    hash_buffer(hash_context.size, 0),
    skip(false)
{
  hash_context.buffer = &hash_buffer[0];
  shash::Init(hash_context);
}

FileInfo::FileInfo(const FileInfo& other)
  : temp_path(other.temp_path),
    total_size(other.total_size),
    current_size(other.current_size),
    hash_context(other.hash_context),
    hash_buffer(other.hash_buffer),
    skip(other.skip)
{
  hash_context.buffer = &hash_buffer[0];
}

FileInfo& FileInfo::operator=(const FileInfo& other) {
  temp_path = other.temp_path;
  total_size = other.total_size;
  current_size = other.current_size;
  hash_context = other.hash_context;
  hash_buffer = other.hash_buffer;
  hash_context.buffer = &hash_buffer[0];
  skip = other.skip;

  return *this;
}

PayloadProcessor::PayloadProcessor()
    : pending_files_(),
      current_repo_(),
      spooler_(),
      temp_dir_(),
      num_errors_(0) {}

PayloadProcessor::~PayloadProcessor() {}

PayloadProcessor::Result PayloadProcessor::Process(
    int fdin, const std::string& header_digest, const std::string& path,
    uint64_t header_size) {
  LogCvmfs(kLogReceiver, kLogSyslog,
           "PayloadProcessor - lease_path: %s, header digest: %s, header "
           "size: %ld",
           path.c_str(), header_digest.c_str(), header_size);

  const size_t first_slash_idx = path.find('/', 0);

  current_repo_ = path.substr(0, first_slash_idx);

  Result init_result = Initialize();
  if (init_result != kSuccess) {
    return init_result;
  }

  // Set up object pack deserialization
  shash::Any digest = shash::MkFromHexPtr(shash::HexPtr(header_digest));

  ObjectPackConsumer deserializer(digest, header_size);
  deserializer.RegisterListener(&PayloadProcessor::ConsumerEventCallback, this);

  int nb = 0;
  ObjectPackBuild::State consumer_state = ObjectPackBuild::kStateContinue;
  std::vector<unsigned char> buffer(kConsumerBuffer, 0);
  do {
    nb = read(fdin, &buffer[0], buffer.size());
    consumer_state = deserializer.ConsumeNext(nb, &buffer[0]);
    if (consumer_state != ObjectPackBuild::kStateContinue &&
        consumer_state != ObjectPackBuild::kStateDone) {
      LogCvmfs(kLogReceiver, kLogSyslogErr,
               "PayloadProcessor - error: %d encountered when consuming object "
               "pack.",
               consumer_state);
      break;
    }
  } while (nb > 0 && consumer_state != ObjectPackBuild::kStateDone);

  assert(pending_files_.empty());

  Result res = Finalize();

  deserializer.UnregisterListeners();

  return res;
}

void PayloadProcessor::ConsumerEventCallback(
    const ObjectPackBuild::Event& event) {
  std::string path("");

  if (event.object_type == ObjectPack::kCas) {
    path = event.id.MakePath();
  } else if (event.object_type == ObjectPack::kNamed) {
    path = event.object_name;
  } else {
    // kEmpty - this is an error.
    LogCvmfs(kLogReceiver, kLogSyslogErr,
             "PayloadProcessor - error: Event received with unknown object.");
    num_errors_++;
    return;
  }

  FileIterator it = pending_files_.find(event.id);
  if (it == pending_files_.end()) {
    FileInfo info(event);

    // If the file already exists in the repository, don't create a temp file,
    // mark it to be skipped in the FileInfo, but keep track of the number of
    // bytes currently written
    if (spooler_->Peek("data/" + path)) {
      LogCvmfs(
          kLogReceiver, kLogDebug,
          "PayloadProcessor - file %s already exists at destination. "
          "Marking it to be skipped.",
          path.c_str());
      info.skip = true;
    } else {
      // New file to unpack
      const std::string tmp_path =
          CreateTempPath(temp_dir_->dir() + "/payload", 0666);
      if (tmp_path.empty()) {
        LogCvmfs(kLogReceiver, kLogSyslogErr,
                "PayloadProcessor - error: Unable to create temporary path.");
        num_errors_++;
        return;
      }
      info.temp_path = tmp_path;
    }

    pending_files_[event.id] = info;
  }

  FileInfo& info = pending_files_[event.id];

  if (!info.skip) {
    int fdout =
        open(info.temp_path.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0600);
    if (fdout == -1) {
      LogCvmfs(
          kLogReceiver, kLogSyslogErr,
          "PayloadProcessor - error: Unable to open temporary output file: %s",
          info.temp_path.c_str());
      return;
    }

    if (!WriteFile(fdout, event.buf, event.buf_size)) {
      LogCvmfs(kLogReceiver, kLogSyslogErr,
               "PayloadProcessor - error: Unable to write %s",
               info.temp_path.c_str());
      num_errors_++;
      unlink(info.temp_path.c_str());
      close(fdout);
      return;
    }
    close(fdout);

    shash::Update(static_cast<const unsigned char*>(event.buf),
                  event.buf_size,
                  info.hash_context);
  }

  info.current_size += event.buf_size;

  if (info.current_size == info.total_size) {
    if (!info.skip) {
      shash::Any file_hash(event.id.algorithm);
      shash::Final(info.hash_context, &file_hash);

      if (file_hash != event.id) {
        LogCvmfs(
            kLogReceiver, kLogSyslogErr,
            "PayloadProcessor - error: Hash mismatch for unpacked file: event "
            "size: %ld, file size: %ld, event hash: %s, file hash: %s",
            event.size, GetFileSize(info.temp_path),
            event.id.ToString(true).c_str(), file_hash.ToString(true).c_str());
        num_errors_++;
        return;
      }

      Upload(info.temp_path, "data/" + path);
    }

    pending_files_.erase(event.id);
  }
}

PayloadProcessor::Result PayloadProcessor::Initialize() {
  Params params;
  if (!GetParamsFromFile(current_repo_, &params)) {
    LogCvmfs(
        kLogReceiver, kLogSyslogErr,
        "PayloadProcessor - error: Could not get configuration parameters.");
    return kOtherError;
  }

  const std::string spooler_temp_dir =
      GetSpoolerTempDir(params.spooler_configuration);
  assert(!spooler_temp_dir.empty());
  assert(MkdirDeep(spooler_temp_dir + "/receiver", 0666, true));
  temp_dir_ =
      RaiiTempDir::Create(spooler_temp_dir + "/receiver/payload_processor");

  upload::SpoolerDefinition definition(
      params.spooler_configuration, params.hash_alg, params.compression_alg,
      params.generate_legacy_bulk_chunks, params.use_file_chunking,
      params.min_chunk_size, params.avg_chunk_size, params.max_chunk_size,
      "dummy_token", "dummy_key");

  spooler_.Destroy();
  spooler_ = upload::Spooler::Construct(definition);

  return kSuccess;
}

PayloadProcessor::Result PayloadProcessor::Finalize() {
  spooler_->WaitForUpload();
  temp_dir_.Destroy();

  const unsigned num_spooler_errors = spooler_->GetNumberOfErrors();
  if (num_spooler_errors > 0) {
    LogCvmfs(kLogReceiver, kLogSyslogErr,
             "PayloadProcessor - error: Spooler - %d upload(s) failed.",
             num_spooler_errors);
    return kSpoolerError;
  }

  if (GetNumErrors() > 0) {
    LogCvmfs(kLogReceiver, kLogSyslogErr,
             "PayloadProcessor - error: % unpacking error(s).", GetNumErrors());
    return kOtherError;
  }

  return kSuccess;
}

void PayloadProcessor::Upload(const std::string& source,
                              const std::string& dest) {
  spooler_->Upload(source, dest);
}

bool PayloadProcessor::WriteFile(int fd, const void* const buf,
                                 size_t buf_size) {
  return SafeWrite(fd, buf, buf_size);
}

}  // namespace receiver
<|endoftext|>


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

#include <coins.h>
#include <consensus/tx_check.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <core_memusage.h>
#include <policy/policy.h>
#include <policy/settings.h>
#include <primitives/transaction.h>
#include <streams.h>
#include <test/fuzz/fuzz.h>
#include <util/rbf.h>
#include <validation.h>
#include <version.h>

#include <cassert>

void test_one_input(const std::vector<uint8_t>& buffer)
{
    CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
    try {
        int nVersion;
        ds >> nVersion;
        ds.SetVersion(nVersion);
    } catch (const std::ios_base::failure&) {
        return;
    }
    bool valid_tx = true;
    const CTransaction tx = [&] {
        try {
            return CTransaction(deserialize, ds);
        } catch (const std::ios_base::failure&) {
            valid_tx = false;
            return CTransaction();
        }
    }();
    bool valid_mutable_tx = true;
    CDataStream ds_mtx(buffer, SER_NETWORK, INIT_PROTO_VERSION);
    CMutableTransaction mutable_tx;
    try {
        int nVersion;
        ds_mtx >> nVersion;
        ds_mtx.SetVersion(nVersion);
        ds_mtx >> mutable_tx;
    } catch (const std::ios_base::failure&) {
        valid_mutable_tx = false;
    }
    assert(valid_tx == valid_mutable_tx);
    if (!valid_tx) {
        return;
    }

    TxValidationState state_with_dupe_check;
    (void)CheckTransaction(tx, state_with_dupe_check);

    const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
    std::string reason;
    const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
    const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
    if (is_standard_without_permit_bare_multisig) {
        assert(is_standard_with_permit_bare_multisig);
    }

    (void)tx.GetHash();
    (void)tx.GetTotalSize();
    try {
        (void)tx.GetValueOut();
    } catch (const std::runtime_error&) {
    }
    (void)tx.GetWitnessHash();
    (void)tx.HasWitness();
    (void)tx.IsCoinBase();
    (void)tx.IsNull();
    (void)tx.ToString();

    (void)EncodeHexTx(tx);
    (void)GetLegacySigOpCount(tx);
    (void)GetTransactionWeight(tx);
    (void)GetVirtualTransactionSize(tx);
    (void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024);
    (void)IsStandardTx(tx, reason);
    (void)RecursiveDynamicUsage(tx);
    (void)SignalsOptInRBF(tx);
}
<commit_msg>tests: Fuzz additional functions in the transaction fuzzing harness<commit_after>// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chainparams.h>
#include <coins.h>
#include <consensus/tx_check.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <core_memusage.h>
#include <policy/policy.h>
#include <policy/settings.h>
#include <primitives/transaction.h>
#include <streams.h>
#include <test/fuzz/fuzz.h>
#include <univalue.h>
#include <util/rbf.h>
#include <validation.h>
#include <version.h>

#include <cassert>

void initialize()
{
    SelectParams(CBaseChainParams::REGTEST);
}

void test_one_input(const std::vector<uint8_t>& buffer)
{
    CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
    try {
        int nVersion;
        ds >> nVersion;
        ds.SetVersion(nVersion);
    } catch (const std::ios_base::failure&) {
        return;
    }
    bool valid_tx = true;
    const CTransaction tx = [&] {
        try {
            return CTransaction(deserialize, ds);
        } catch (const std::ios_base::failure&) {
            valid_tx = false;
            return CTransaction();
        }
    }();
    bool valid_mutable_tx = true;
    CDataStream ds_mtx(buffer, SER_NETWORK, INIT_PROTO_VERSION);
    CMutableTransaction mutable_tx;
    try {
        int nVersion;
        ds_mtx >> nVersion;
        ds_mtx.SetVersion(nVersion);
        ds_mtx >> mutable_tx;
    } catch (const std::ios_base::failure&) {
        valid_mutable_tx = false;
    }
    assert(valid_tx == valid_mutable_tx);
    if (!valid_tx) {
        return;
    }

    TxValidationState state_with_dupe_check;
    (void)CheckTransaction(tx, state_with_dupe_check);

    const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
    std::string reason;
    const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
    const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
    if (is_standard_without_permit_bare_multisig) {
        assert(is_standard_with_permit_bare_multisig);
    }

    (void)tx.GetHash();
    (void)tx.GetTotalSize();
    try {
        (void)tx.GetValueOut();
    } catch (const std::runtime_error&) {
    }
    (void)tx.GetWitnessHash();
    (void)tx.HasWitness();
    (void)tx.IsCoinBase();
    (void)tx.IsNull();
    (void)tx.ToString();

    (void)EncodeHexTx(tx);
    (void)GetLegacySigOpCount(tx);
    (void)GetTransactionWeight(tx);
    (void)GetVirtualTransactionSize(tx);
    (void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024);
    (void)IsStandardTx(tx, reason);
    (void)RecursiveDynamicUsage(tx);
    (void)SignalsOptInRBF(tx);

    CCoinsView coins_view;
    const CCoinsViewCache coins_view_cache(&coins_view);
    (void)AreInputsStandard(tx, coins_view_cache);
    (void)IsWitnessStandard(tx, coins_view_cache);

    UniValue u(UniValue::VOBJ);
    // ValueFromAmount(i) not defined when i == std::numeric_limits<int64_t>::min()
    bool skip_tx_to_univ = false;
    for (const CTxOut& txout : tx.vout) {
        if (txout.nValue == std::numeric_limits<int64_t>::min()) {
            skip_tx_to_univ = true;
        }
    }
    if (!skip_tx_to_univ) {
        TxToUniv(tx, /* hashBlock */ {}, u);
    }
}
<|endoftext|>


<commit_before>
#include "common_headers.h"

#include "tests/common.h"
#include "term.h"
#include "term_list.h"
#include "term_namespace.h"
#include "term_set.h"

namespace circa {
namespace container_tests {

void test_set()
{
    TermSet set;

    Term* term1 = new Term();

    test_assert(!set.contains(term1));
    test_assert(set.count() == 0);

    set.add(term1);

    test_assert(set.contains(term1));
    test_assert(set.count() == 1);

    set.add(term1);

    test_assert(set.contains(term1));
    test_assert(set.count() == 1);

    Term* term2 = new Term();
    set.add(term2);

    test_assert(set.contains(term2));
    test_assert(set.count() == 2);

    set.remove(term1);

    test_assert(!set.contains(term1));
    test_assert(set.count() == 1);

    set.remove(term2);

    test_assert(!set.contains(term2));
    test_assert(set.count() == 0);

    set.add(term1);
    test_assert(set.contains(term1));
    test_assert(set.count() == 1);

    /*TermMap remap;
    remap[term1] = term2;
    set.remapPointers(remap);
    test_assert(set.contains(term2));
    test_assert(set.count() == 1);*/
}

void test_namespace()
{
    TermNamespace nspace;
    Term *term = new Term();

    nspace.bind(term, "a");
    test_assert(nspace.contains("a"));
    test_assert(nspace["a"] == term);

    Term *term2 = new Term();
    TermMap remap;
    remap[term] = term2;
    nspace.remapPointers(remap);
    test_assert(nspace["a"] == term2);

    test_assert(nspace.contains("a"));
    remap[term2] = NULL;
    nspace.remapPointers(remap);
    test_assert(!nspace.contains("a"));
}

} // namespace container_tests

void register_container_tests()
{
    REGISTER_TEST_CASE(container_tests::test_set);
    REGISTER_TEST_CASE(container_tests::test_namespace);
}

} // namespace circa
<commit_msg>Add some container tests<commit_after>
#include "common_headers.h"

#include "tests/common.h"
#include "term.h"
#include "term_list.h"
#include "term_namespace.h"
#include "term_set.h"

namespace circa {
namespace container_tests {

void test_set()
{
    TermSet set;

    Term* term1 = new Term();

    test_assert(!set.contains(term1));
    test_assert(set.count() == 0);

    set.add(term1);

    test_assert(set.contains(term1));
    test_assert(set.count() == 1);

    set.add(term1);

    test_assert(set.contains(term1));
    test_assert(set.count() == 1);

    Term* term2 = new Term();
    set.add(term2);

    test_assert(set.contains(term2));
    test_assert(set.count() == 2);

    set.remove(term1);

    test_assert(!set.contains(term1));
    test_assert(set.count() == 1);

    set.remove(term2);

    test_assert(!set.contains(term2));
    test_assert(set.count() == 0);

    set.add(term1);
    test_assert(set.contains(term1));
    test_assert(set.count() == 1);

    /*TermMap remap;
    remap[term1] = term2;
    set.remapPointers(remap);
    test_assert(set.contains(term2));
    test_assert(set.count() == 1);*/
}

void test_namespace()
{
    TermNamespace nspace;
    Term *term = new Term();

    nspace.bind(term, "a");
    test_assert(nspace.contains("a"));
    test_assert(nspace["a"] == term);

    Term *term2 = new Term();
    TermMap remap;
    remap[term] = term2;
    nspace.remapPointers(remap);
    test_assert(nspace["a"] == term2);

    test_assert(nspace.contains("a"));
    remap[term2] = NULL;
    nspace.remapPointers(remap);
    test_assert(!nspace.contains("a"));
}

void test_list()
{
    TermList list;
    Term* term = new Term();
    Term* term2 = new Term();

    test_assert(list.count() == 0);

    list.append(term);
    list.append(term2);
    test_assert(list.count() == 2);
    test_assert(list[0] == term);
    test_assert(list[1] == term2);

    Term* term3 = new Term();
    TermMap remap;
    remap[term] = term3;
    list.remapPointers(remap);
    test_assert(list.count() == 2);
    test_assert(list[0] == term3);
    test_assert(list[1] == term2);

    list.clear();

    test_assert(list.count() == 0);
}

} // namespace container_tests

void register_container_tests()
{
    REGISTER_TEST_CASE(container_tests::test_set);
    REGISTER_TEST_CASE(container_tests::test_namespace);
    REGISTER_TEST_CASE(container_tests::test_list);
}

} // namespace circa
<|endoftext|>


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

/*
 *  This file is part of the WSF Staff project.
 *  Please, visit http://code.google.com/p/staff for more information.
 */

#include <staff/sqlite3/sqlite3.h>
#include <rise/xml/XMLDocument.h>
#include <rise/common/ExceptionTemplate.h>
#include <rise/common/MutablePtr.h>
#include <rise/string/String.h>
#include <staff/common/Runtime.h>
#include <staff/common/DataObject.h>
#include <staff/common/Value.h>
#include <staff/das/common/DataSource.h>
#include <staff/das/common/Executor.h>
#include "Sqlite.h"

namespace staff
{
namespace das
{

  class SqliteProvider::SqliteImpl
  {
  public:
    SqliteImpl():
      m_pConn(NULL)
    {
    }

  public:
    static const std::string m_sName;
    static const std::string m_sDescr;

    sqlite3* m_pConn;
    std::string m_sDataBase;
  };

  const std::string SqliteProvider::SqliteImpl::m_sName = "staff.das.Sqlite";
  const std::string SqliteProvider::SqliteImpl::m_sDescr = "Sqlite data access provider";

  //  ---------------------------------------------------------------

  class SqliteQueryExecutor: public IQueryExecutor
  {
  public:
    SqliteQueryExecutor(SqliteProvider* pProvider):
      m_pProvider(pProvider), m_pResult(NULL), m_nLastStepStatus(0), m_nFieldsCount(0)
    {
    }

    virtual ~SqliteQueryExecutor()
    {
      Reset();
    }

    virtual void Reset()
    {
      if (m_pResult)
      {
        sqlite3_finalize(m_pResult);
        m_pResult = NULL;
        m_nFieldsCount = 0;
      }
    }

    virtual void Execute(const std::string& sExecute)
    {
      RISE_ASSERTS(m_pProvider != NULL && m_pProvider->m_pImpl->m_pConn != NULL, "Not Initialized");

      Reset();

      int nResult = sqlite3_prepare_v2(m_pProvider->m_pImpl->m_pConn, sExecute.c_str(), sExecute.size(), &m_pResult, NULL);
      RISE_ASSERTS(nResult == SQLITE_OK, "error #" + rise::ToStr(nResult) + ": "
                   + std::string(sqlite3_errmsg(m_pProvider->m_pImpl->m_pConn))
                   + "\nWhile executing query: \n----------\n" + sExecute + "\n----------\n");

      m_nLastStepStatus = sqlite3_step(m_pResult);
      if (m_nLastStepStatus == SQLITE_ROW)
      {
        m_nFieldsCount = static_cast<unsigned>(sqlite3_column_count(m_pResult));
      }
    }

    virtual void GetFieldsNames(StringList& rNames)
    {
      RISE_ASSERTS(m_pResult, "Execute was not called");

      if (rNames.size() != m_nFieldsCount)
      {
        rNames.resize(m_nFieldsCount);
      }

      const char* szFieldName = NULL;
      int nField = 0;
      for (StringList::iterator itItem = rNames.begin();
          itItem != rNames.end(); ++itItem, ++nField)
      {
        szFieldName = sqlite3_column_name(m_pResult, nField);
        RISE_ASSERTS(szFieldName, "Error while getting field name");
        *itItem = szFieldName;
      }
    }

    virtual bool GetNextResult(StringList& rResult)
    {
      RISE_ASSERTS(m_pResult, "Execute was not called");

      if (m_nLastStepStatus != SQLITE_ROW)
      {
        return false;
      }

      if (rResult.size() != m_nFieldsCount)
      {
        rResult.resize(m_nFieldsCount);
      }

      int nField = 0;
      const char* szResult = NULL;
      for (StringList::iterator itItem = rResult.begin();
          itItem != rResult.end(); ++itItem, ++nField)
      {
        szResult = reinterpret_cast<const char*>(sqlite3_column_text(m_pResult, nField));
        *itItem = szResult ? szResult : "(NULL)";
      }

      m_nLastStepStatus = sqlite3_step(m_pResult);

      return true;
    }

  private:
    SqliteProvider* m_pProvider;
    sqlite3_stmt* m_pResult;
    int m_nLastStepStatus;
    unsigned m_nFieldsCount;
  };

  SqliteProvider::SqliteProvider()
  {
    m_pImpl = new SqliteImpl;
  }

  SqliteProvider::~SqliteProvider()
  {
    Deinit();
    delete m_pImpl;
  }

  void SqliteProvider::Init(const rise::xml::CXMLNode& rConfig)
  {
    // initialize connection
    const rise::xml::CXMLNode& rConnection = rConfig.Subnode("connection");

    m_pImpl->m_sDataBase = rConnection["db"].AsString();

    // replace env variable to full path
    std::string::size_type nPosStart = 0;
    std::string::size_type nPosEnd = 0;

    while ((nPosStart = m_pImpl->m_sDataBase.find("$(", nPosEnd)) != std::string::npos)
    {
      nPosEnd = m_pImpl->m_sDataBase.find(')', nPosStart);
      RISE_ASSERTS(nPosEnd != std::string::npos, "Invalid Env var declaration: " + m_pImpl->m_sDataBase);
      const std::string& sVar = m_pImpl->m_sDataBase.substr(nPosStart + 2, nPosEnd - nPosStart - 2);
      const std::string& sValue = staff::Runtime::Inst().GetEnv(sVar);
      m_pImpl->m_sDataBase.replace(nPosStart, nPosEnd - nPosStart + 1, sValue);
      nPosEnd = nPosStart + sValue.size();
    }

    RISE_ASSERTS(m_pImpl->m_pConn == NULL, "Already connected");
    sqlite3_enable_shared_cache(1);

    // open db
    int nResult = sqlite3_open(m_pImpl->m_sDataBase.c_str(), &m_pImpl->m_pConn);
    RISE_ASSERTS(nResult == SQLITE_OK, "Failed to open database: " + m_pImpl->m_sDataBase);

    sqlite3_stmt* pStmt = NULL;

    nResult = sqlite3_prepare_v2(m_pImpl->m_pConn, "PRAGMA foreign_keys = ON;", -1, &pStmt, NULL);
    RISE_ASSERTS(nResult == SQLITE_OK, sqlite3_errmsg(m_pImpl->m_pConn));

    try
    {
      RISE_ASSERTS(sqlite3_step(pStmt) == SQLITE_DONE, "Failed to enable foreign keys: "
                   + std::string(sqlite3_errmsg(m_pImpl->m_pConn)));
    }
    catch(...)
    {
      sqlite3_finalize(pStmt);
      throw;
    }

    RISE_ASSERTS(sqlite3_finalize(pStmt) == SQLITE_OK, sqlite3_errmsg(m_pImpl->m_pConn));
  }

  void SqliteProvider::Deinit()
  {
    if (m_pImpl->m_pConn)
    {
      // free all prepared ops
      sqlite3_stmt* pStmt = NULL;
      while ((pStmt = sqlite3_next_stmt(m_pImpl->m_pConn, 0)) != NULL)
      {
        sqlite3_finalize(pStmt);
      }

      // close db
      int nResult = sqlite3_close(m_pImpl->m_pConn);
      if (nResult != SQLITE_OK)
      {
        rise::LogWarning() << "Failed to close database";
      }
      m_pImpl->m_pConn = NULL;
    }
  }

  const std::string& SqliteProvider::GetName() const
  {
    return SqliteImpl::m_sName;
  }

  const std::string& SqliteProvider::GetDescr() const
  {
    return SqliteImpl::m_sDescr;
  }

  PExecutor SqliteProvider::GetExecutor()
  {
    return new SqliteQueryExecutor(this);
  }

}
}

<commit_msg>das: sqlite: fixed sqlite step checking (will throw error on constraint failure)<commit_after>/*
 *  Copyright 2010 Utkin Dmitry
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*
 *  This file is part of the WSF Staff project.
 *  Please, visit http://code.google.com/p/staff for more information.
 */

#include <staff/sqlite3/sqlite3.h>
#include <rise/xml/XMLDocument.h>
#include <rise/common/ExceptionTemplate.h>
#include <rise/common/MutablePtr.h>
#include <rise/string/String.h>
#include <staff/common/Runtime.h>
#include <staff/common/DataObject.h>
#include <staff/common/Value.h>
#include <staff/das/common/DataSource.h>
#include <staff/das/common/Executor.h>
#include "Sqlite.h"

namespace staff
{
namespace das
{

  class SqliteProvider::SqliteImpl
  {
  public:
    SqliteImpl():
      m_pConn(NULL)
    {
    }

  public:
    static const std::string m_sName;
    static const std::string m_sDescr;

    sqlite3* m_pConn;
    std::string m_sDataBase;
  };

  const std::string SqliteProvider::SqliteImpl::m_sName = "staff.das.Sqlite";
  const std::string SqliteProvider::SqliteImpl::m_sDescr = "Sqlite data access provider";

  //  ---------------------------------------------------------------

  class SqliteQueryExecutor: public IQueryExecutor
  {
  public:
    SqliteQueryExecutor(SqliteProvider* pProvider):
      m_pProvider(pProvider), m_pResult(NULL), m_nLastStepStatus(0), m_nFieldsCount(0)
    {
    }

    virtual ~SqliteQueryExecutor()
    {
      Reset();
    }

    virtual void Reset()
    {
      if (m_pResult)
      {
        sqlite3_finalize(m_pResult);
        m_pResult = NULL;
        m_nFieldsCount = 0;
      }
    }

    virtual void Execute(const std::string& sExecute)
    {
      RISE_ASSERTS(m_pProvider != NULL && m_pProvider->m_pImpl->m_pConn != NULL, "Not Initialized");

      Reset();

      int nResult = sqlite3_prepare_v2(m_pProvider->m_pImpl->m_pConn, sExecute.c_str(), sExecute.size(), &m_pResult, NULL);
      RISE_ASSERTS(nResult == SQLITE_OK, "error #" + rise::ToStr(nResult) + ": "
                   + std::string(sqlite3_errmsg(m_pProvider->m_pImpl->m_pConn))
                   + "\nWhile executing query: \n----------\n" + sExecute + "\n----------\n");

      m_nLastStepStatus = sqlite3_step(m_pResult);
      if (m_nLastStepStatus == SQLITE_ROW)
      {
        m_nFieldsCount = static_cast<unsigned>(sqlite3_column_count(m_pResult));
      }
      else
      {
        RISE_ASSERTS(m_nLastStepStatus == SQLITE_DONE || m_nLastStepStatus == SQLITE_OK,
                     "error #" + rise::ToStr(m_nLastStepStatus) + ": "
                      + std::string(sqlite3_errmsg(m_pProvider->m_pImpl->m_pConn))
                      + "\nWhile executing query: \n----------\n" + sExecute + "\n----------\n");
      }
    }

    virtual void GetFieldsNames(StringList& rNames)
    {
      RISE_ASSERTS(m_pResult, "Execute was not called");

      if (rNames.size() != m_nFieldsCount)
      {
        rNames.resize(m_nFieldsCount);
      }

      const char* szFieldName = NULL;
      int nField = 0;
      for (StringList::iterator itItem = rNames.begin();
          itItem != rNames.end(); ++itItem, ++nField)
      {
        szFieldName = sqlite3_column_name(m_pResult, nField);
        RISE_ASSERTS(szFieldName, "Error while getting field name");
        *itItem = szFieldName;
      }
    }

    virtual bool GetNextResult(StringList& rResult)
    {
      RISE_ASSERTS(m_pResult, "Execute was not called");

      if (m_nLastStepStatus != SQLITE_ROW)
      {
        return false;
      }

      if (rResult.size() != m_nFieldsCount)
      {
        rResult.resize(m_nFieldsCount);
      }

      int nField = 0;
      const char* szResult = NULL;
      for (StringList::iterator itItem = rResult.begin();
          itItem != rResult.end(); ++itItem, ++nField)
      {
        szResult = reinterpret_cast<const char*>(sqlite3_column_text(m_pResult, nField));
        *itItem = szResult ? szResult : "(NULL)";
      }

      m_nLastStepStatus = sqlite3_step(m_pResult);

      return true;
    }

  private:
    SqliteProvider* m_pProvider;
    sqlite3_stmt* m_pResult;
    int m_nLastStepStatus;
    unsigned m_nFieldsCount;
  };

  SqliteProvider::SqliteProvider()
  {
    m_pImpl = new SqliteImpl;
  }

  SqliteProvider::~SqliteProvider()
  {
    Deinit();
    delete m_pImpl;
  }

  void SqliteProvider::Init(const rise::xml::CXMLNode& rConfig)
  {
    // initialize connection
    const rise::xml::CXMLNode& rConnection = rConfig.Subnode("connection");

    m_pImpl->m_sDataBase = rConnection["db"].AsString();

    // replace env variable to full path
    std::string::size_type nPosStart = 0;
    std::string::size_type nPosEnd = 0;

    while ((nPosStart = m_pImpl->m_sDataBase.find("$(", nPosEnd)) != std::string::npos)
    {
      nPosEnd = m_pImpl->m_sDataBase.find(')', nPosStart);
      RISE_ASSERTS(nPosEnd != std::string::npos, "Invalid Env var declaration: " + m_pImpl->m_sDataBase);
      const std::string& sVar = m_pImpl->m_sDataBase.substr(nPosStart + 2, nPosEnd - nPosStart - 2);
      const std::string& sValue = staff::Runtime::Inst().GetEnv(sVar);
      m_pImpl->m_sDataBase.replace(nPosStart, nPosEnd - nPosStart + 1, sValue);
      nPosEnd = nPosStart + sValue.size();
    }

    RISE_ASSERTS(m_pImpl->m_pConn == NULL, "Already connected");
    sqlite3_enable_shared_cache(1);

    // open db
    int nResult = sqlite3_open(m_pImpl->m_sDataBase.c_str(), &m_pImpl->m_pConn);
    RISE_ASSERTS(nResult == SQLITE_OK, "Failed to open database: " + m_pImpl->m_sDataBase);

    sqlite3_stmt* pStmt = NULL;

    nResult = sqlite3_prepare_v2(m_pImpl->m_pConn, "PRAGMA foreign_keys = ON;", -1, &pStmt, NULL);
    RISE_ASSERTS(nResult == SQLITE_OK, sqlite3_errmsg(m_pImpl->m_pConn));

    try
    {
      RISE_ASSERTS(sqlite3_step(pStmt) == SQLITE_DONE, "Failed to enable foreign keys: "
                   + std::string(sqlite3_errmsg(m_pImpl->m_pConn)));
    }
    catch(...)
    {
      sqlite3_finalize(pStmt);
      throw;
    }

    RISE_ASSERTS(sqlite3_finalize(pStmt) == SQLITE_OK, sqlite3_errmsg(m_pImpl->m_pConn));
  }

  void SqliteProvider::Deinit()
  {
    if (m_pImpl->m_pConn)
    {
      // free all prepared ops
      sqlite3_stmt* pStmt = NULL;
      while ((pStmt = sqlite3_next_stmt(m_pImpl->m_pConn, 0)) != NULL)
      {
        sqlite3_finalize(pStmt);
      }

      // close db
      int nResult = sqlite3_close(m_pImpl->m_pConn);
      if (nResult != SQLITE_OK)
      {
        rise::LogWarning() << "Failed to close database";
      }
      m_pImpl->m_pConn = NULL;
    }
  }

  const std::string& SqliteProvider::GetName() const
  {
    return SqliteImpl::m_sName;
  }

  const std::string& SqliteProvider::GetDescr() const
  {
    return SqliteImpl::m_sDescr;
  }

  PExecutor SqliteProvider::GetExecutor()
  {
    return new SqliteQueryExecutor(this);
  }

}
}

<|endoftext|>


<commit_before>// MIT License

// Copyright (c) 2017 Zhuhao Wang

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#define BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS

#include "nekit/transport/tcp_listener.h"
#include "nekit/transport/tcp_socket.h"
#include "nekit/utils/boost_error.h"

namespace nekit {
namespace transport {
TcpListener::TcpListener(boost::asio::io_service &io)
    : acceptor_(io), socket_(io) {}

std::error_code TcpListener::Bind(std::string ip, uint16_t port) {
  return Bind(boost::asio::ip::address::from_string(ip), port);
}

std::error_code TcpListener::Bind(boost::asio::ip::address ip, uint16_t port) {
  boost::system::error_code ec;
  boost::asio::ip::tcp::endpoint endpoint(ip, port);

  acceptor_.open(endpoint.protocol(), ec);
  if (ec) {
    return std::make_error_code(ec);
  }

  acceptor_.bind(endpoint, ec);
  if (ec) {
    return std::make_error_code(ec);
  }

  return ErrorCode::NoError;
}

void TcpListener::Accept(EventHandler &&handler) {
  acceptor_.async_accept(socket_, [ this, handler{std::move(handler)} ](
                                      const boost::system::error_code &ec) {
    if (ec) {
      handler(nullptr, std::make_error_code(ec));
      return;
    }

    // Can't use `make_unique` since the constructor is a private friend.
    TcpSocket *socket = new TcpSocket(std::move(socket_));
    handler(std::unique_ptr<TcpSocket>(socket),
            TcpListener::ErrorCode::NoError);
  });
}

namespace {
struct TcpListenerErrorCategory : std::error_category {
  const char *name() const noexcept override { return "TCP listener"; }

  std::string message(int ev) const override {
    switch (static_cast<TcpListener::ErrorCode>(ev)) {
      case TcpListener::ErrorCode::NoError:
        return "no error";
    }
  }
};

const TcpListenerErrorCategory tcpListenerErrorCategory{};

}  // namespace

std::error_code make_error_code(TcpListener::ErrorCode ec) {
  return {static_cast<int>(ec), tcpListenerErrorCategory};
}
}  // namespace transport
}  // namespace nekit
<commit_msg>FIX: Set listener in to listen state when asked<commit_after>// MIT License

// Copyright (c) 2017 Zhuhao Wang

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#define BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS

#include "nekit/transport/tcp_listener.h"
#include "nekit/transport/tcp_socket.h"
#include "nekit/utils/boost_error.h"

namespace nekit {
namespace transport {
TcpListener::TcpListener(boost::asio::io_service &io)
    : acceptor_(io), socket_(io) {}

std::error_code TcpListener::Bind(std::string ip, uint16_t port) {
  return Bind(boost::asio::ip::address::from_string(ip), port);
}

std::error_code TcpListener::Bind(boost::asio::ip::address ip, uint16_t port) {
  boost::system::error_code ec;
  boost::asio::ip::tcp::endpoint endpoint(ip, port);

  acceptor_.open(endpoint.protocol(), ec);
  if (ec) {
    return std::make_error_code(ec);
  }

  acceptor_.bind(endpoint, ec);
  if (ec) {
    return std::make_error_code(ec);
  }

  acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), ec);
  if (ec) {
    return std::make_error_code(ec);
  }

  acceptor_.listen(8, ec);
  if (ec) {
    return std::make_error_code(ec);
  }

  return ErrorCode::NoError;
}

void TcpListener::Accept(EventHandler &&handler) {
  acceptor_.async_accept(socket_, [ this, handler{std::move(handler)} ](
                                      const boost::system::error_code &ec) {
    if (ec) {
      handler(nullptr, std::make_error_code(ec));
      return;
    }

    // Can't use `make_unique` since the constructor is a private friend.
    TcpSocket *socket = new TcpSocket(std::move(socket_));
    handler(std::unique_ptr<TcpSocket>(socket),
            TcpListener::ErrorCode::NoError);
  });
}

namespace {
struct TcpListenerErrorCategory : std::error_category {
  const char *name() const noexcept override { return "TCP listener"; }

  std::string message(int ev) const override {
    switch (static_cast<TcpListener::ErrorCode>(ev)) {
      case TcpListener::ErrorCode::NoError:
        return "no error";
    }
  }
};

const TcpListenerErrorCategory tcpListenerErrorCategory{};

}  // namespace

std::error_code make_error_code(TcpListener::ErrorCode ec) {
  return {static_cast<int>(ec), tcpListenerErrorCategory};
}
}  // namespace transport
}  // namespace nekit
<|endoftext|>


<commit_before>//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

// GuidFromName

// Algorithm from Internet Draft document "UUIDs and GUIDs"
// By Paul J. Leach and Rich Sals, February 4, 1998.

// This function has been adapted from the routines in the document
//  uuid_create_from_name and format_uuid_v3

// Changes from documented routines:
// 1. Changed all instances of uuid_t to GUID.
//      uuid_t field time_low is GUID field Data1.
//      uuid_t field time_mid is GUID field Data2.
//      uuid_t field time_hi_and_version is GUID field Data3.
//      uuid_t field clock_seq_hi_and_reserved is GUID field Data4[0].
//      uuid_t field clock_seq_low is GUID field Data4[1].
//      uuid_t field node[6] is GUID field Data4[2] through Data4[8].
//
// 2. Use a c++ implementation of the md5 cryptographic hash function.
//
// 3. Implemented the htonl, htons, ntohl, ntohs socket routines as inlines.
//
// 4. Renamed variables and types to suit my biases.

/*
** Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
** Digital Equipment Corporation, Maynard, Mass.
** To anyone who acknowledges that this file is provided "AS IS"
** without any express or implied warranty: permission to use, copy,
** modify, and distribute this file for any purpose is hereby
** granted without fee, provided that the above copyright notices and
** this notice appears in all source code copies, and that none of
** the names of Open Software Foundation, Inc., Hewlett-Packard
** Company, or Digital Equipment Corporation be used in advertising
** or publicity pertaining to distribution of the software without
** specific, written prior permission.  Neither Open Software
** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital Equipment
** Corporation makes any representations about the suitability of
** this software for any purpose.
*/

#include "stdafx.h"

#include "md5.h"                // cryptographic hash function
#include "guidfromname.h"       // verify our function signature
#include "contract.h"

#if BIGENDIAN
#define BigEndian() true
#else
#define BigEndian() false
#endif

//=============================================================================
// htons, htonl, ntohs, ntohl equivalents copied and adapted from socket library.
//=============================================================================

// HostToNetworkLong converts a 32-bit long to network byte order

inline ULONG HostToNetworkLong(ULONG hostlong)
{
    LIMITED_METHOD_CONTRACT;

    if (BigEndian())
        return hostlong;
    else
        return  ( (hostlong >> 24) & 0x000000FFL) |
                ( (hostlong >>  8) & 0x0000FF00L) |
                ( (hostlong <<  8) & 0x00FF0000L) |
                ( (hostlong << 24) & 0xFF000000L);
}

// HostToNetworkLong converts a 16-bit short to network byte order

inline USHORT HostToNetworkShort(USHORT hostshort)
{
    LIMITED_METHOD_CONTRACT;

    if (BigEndian())
        return hostshort;
    else
        return ((hostshort >> 8) & 0x00FF) | ((hostshort << 8) & 0xFF00);
}

// NetworkToHostLong converts a 32-bit long to local host byte order

inline ULONG NetworkToHostLong(ULONG netlong)
{
    LIMITED_METHOD_CONTRACT;

    if (BigEndian())
        return netlong;
    else
        return  ( (netlong >> 24) & 0x000000FFL) |
                ( (netlong >>  8) & 0x0000FF00L) |
                ( (netlong <<  8) & 0x00FF0000L) |
                ( (netlong << 24) & 0xFF000000L);
}

// NetworkToHostShort converts a 16-bit short to local host byte order

inline USHORT NetworkToHostShort(USHORT netshort)
{
    LIMITED_METHOD_CONTRACT;

    if (BigEndian())
        return netshort;
    else
        return ((netshort >> 8) & 0x00FF) | ((netshort << 8) & 0xFF00);
}

//=============================================================================
// GuidFromName(GUID * pGuidResult, REFGUID refGuidNsid,
//              const void * pvName, DWORD dwcbName);
//=============================================================================

void GuidFromName
(
    GUID *  pGuidResult,        // resulting GUID
    REFGUID refGuidNsid,        // Name Space GUID, so identical names from
                                // different name spaces generate different GUIDs
    const void * pvName,        // the name from which to generate a GUID
    DWORD dwcbName              // name length in bytes
)
{
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_GC_NOTRIGGER;

    MD5         md5;            // Cryptographic hash class instance
    MD5HASHDATA md5HashData;    // 128-bit hash result
    GUID        guidNsid;       // context NameSpace GUID in network byte order

    GUID        guidTemp;

    // put name space ID in network byte order so it hashes the same
    // no matter what endian machine we're on
    guidNsid = refGuidNsid;

    // The sample code in the IETF draft document discards the result of
    // htonl and htons.  I've implemented what I think is meant and I've
    // sent a note to the author asking for confirmation that this is
    // his intent.
    if (!BigEndian())   // evaluated at compile time in retail builds
    {
        guidNsid.Data1 = HostToNetworkLong (guidNsid.Data1);
        guidNsid.Data2 = HostToNetworkShort(guidNsid.Data2);
        guidNsid.Data3 = HostToNetworkShort(guidNsid.Data3);
    }

    md5.Init();
    md5.HashMore(&guidNsid, sizeof(GUID));
    md5.HashMore(pvName, dwcbName);
    md5.GetHashValue(&md5HashData);

    // the hash is in network byte order at this point
    memcpy(&guidTemp, &md5HashData, sizeof(GUID));

    // Remainder adapted from function "format_uuid_v3" in IETF draft document
    // Construct a version 3 uuid with the pseudo-random number plus a few constants.
    // convert GUID from network order to local byte order
    if (!BigEndian())   // evaluated at compile time in retail builds
    {
        guidTemp.Data1 = NetworkToHostLong (guidTemp.Data1);
        guidTemp.Data2 = NetworkToHostShort(guidTemp.Data2);
        guidTemp.Data3 = NetworkToHostShort(guidTemp.Data3);
    }

    // set version number
    guidTemp.Data3 &= 0x0FFF;   // clear version number nibble
    guidTemp.Data3 |= (3 << 12);// set version 3 = name-based

    // set variant field
    guidTemp.Data4[0] &= 0x3F;  // clear variant bits
    guidTemp.Data4[0] |= 0x80;  // set variant = 100b

    // If two GuidFromName calls were made from different threads with the same parameters,
    // we may get incorrect result even though the expected result is the same, because
    // GuidFromName is operating on the same pGuidResult buffer.
    // Fix this problem by using a temp GUID buffer and then copy to the pGuidResult buffer.
    memcpy(pGuidResult, &guidTemp, sizeof(GUID));
}

// This guid is used for calling GuidFromName function as COM+ runtime uniqualifier
//
// {69F9CBC9-DA05-11d1-9408-0000F8083460}
static const GUID COMPLUS_RUNTIME_GUID = {0x69f9cbc9, 0xda05, 0x11d1,
        {0x94, 0x8, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60}};

void CorGuidFromNameW
(
    GUID *  pGuidResult,        // resulting GUID
    LPCWSTR wzName,             // the unicode name from which to generate a GUID
    SIZE_T  cchName             // name length in count of unicode character
)
{
    WRAPPER_NO_CONTRACT;

    GuidFromName(
        pGuidResult,
        COMPLUS_RUNTIME_GUID,
        wzName,
        (DWORD)((cchName == (SIZE_T) -1 ? (lstrlenW(wzName)+1) : cchName) * sizeof(WCHAR)));
}
<commit_msg>Correct attribution for UUIDs and GUIDs<commit_after>//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

// GuidFromName

/**

Algorithm from Internet Draft document "UUIDs and GUIDs"
By Paul J. Leach and Rich Sals, February 4, 1998.

This function has been adapted from the routines in the document
 uuid_create_from_name and format_uuid_v3

Changes from documented routines:
1. Changed all instances of uuid_t to GUID.
     uuid_t field time_low is GUID field Data1.
     uuid_t field time_mid is GUID field Data2.
     uuid_t field time_hi_and_version is GUID field Data3.
     uuid_t field clock_seq_hi_and_reserved is GUID field Data4[0].
     uuid_t field clock_seq_low is GUID field Data4[1].
     uuid_t field node[6] is GUID field Data4[2] through Data4[8].

2. Use a c++ implementation of the md5 cryptographic hash function.

3. Implemented the htonl, htons, ntohl, ntohs socket routines as inlines.

4. Renamed variables and types to suit my biases.

Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
Digital Equipment Corporation, Maynard, Mass.
To anyone who acknowledges that this file is provided "AS IS"
without any express or implied warranty: permission to use, copy,
modify, and distribute this file for any purpose is hereby
granted without fee, provided that the above copyright notices and
this notice appears in all source code copies, and that none of
the names of Open Software Foundation, Inc., Hewlett-Packard
Company, or Digital Equipment Corporation be used in advertising
or publicity pertaining to distribution of the software without
specific, written prior permission.  Neither Open Software
Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital Equipment
Corporation makes any representations about the suitability of
this software for any purpose.

Copyright(C) The Internet Society 1997. All Rights Reserved.

This document and translations of it may be copied and furnished to others,
and derivative works that comment on or otherwise explain it or assist in
its implementation may be prepared, copied, published and distributed, in
whole or in part, without restriction of any kind, provided that the above
copyright notice and this paragraph are included on all such copies and
derivative works.However, this document itself may not be modified in any
way, such as by removing the copyright notice or references to the Internet
Society or other Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for copyrights
defined in the Internet Standards process must be followed, or as required
to translate it into languages other than English.

The limited permissions granted above are perpetual and will not be revoked
by the Internet Society or its successors or assigns.

This document and the information contained herein is provided on an "AS IS"
basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE
DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY
RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
PARTICULAR PURPOSE.

*/

#include "stdafx.h"

#include "md5.h"                // cryptographic hash function
#include "guidfromname.h"       // verify our function signature
#include "contract.h"

#if BIGENDIAN
#define BigEndian() true
#else
#define BigEndian() false
#endif

//=============================================================================
// htons, htonl, ntohs, ntohl equivalents copied and adapted from socket library.
//=============================================================================

// HostToNetworkLong converts a 32-bit long to network byte order

inline ULONG HostToNetworkLong(ULONG hostlong)
{
    LIMITED_METHOD_CONTRACT;

    if (BigEndian())
        return hostlong;
    else
        return  ( (hostlong >> 24) & 0x000000FFL) |
                ( (hostlong >>  8) & 0x0000FF00L) |
                ( (hostlong <<  8) & 0x00FF0000L) |
                ( (hostlong << 24) & 0xFF000000L);
}

// HostToNetworkLong converts a 16-bit short to network byte order

inline USHORT HostToNetworkShort(USHORT hostshort)
{
    LIMITED_METHOD_CONTRACT;

    if (BigEndian())
        return hostshort;
    else
        return ((hostshort >> 8) & 0x00FF) | ((hostshort << 8) & 0xFF00);
}

// NetworkToHostLong converts a 32-bit long to local host byte order

inline ULONG NetworkToHostLong(ULONG netlong)
{
    LIMITED_METHOD_CONTRACT;

    if (BigEndian())
        return netlong;
    else
        return  ( (netlong >> 24) & 0x000000FFL) |
                ( (netlong >>  8) & 0x0000FF00L) |
                ( (netlong <<  8) & 0x00FF0000L) |
                ( (netlong << 24) & 0xFF000000L);
}

// NetworkToHostShort converts a 16-bit short to local host byte order

inline USHORT NetworkToHostShort(USHORT netshort)
{
    LIMITED_METHOD_CONTRACT;

    if (BigEndian())
        return netshort;
    else
        return ((netshort >> 8) & 0x00FF) | ((netshort << 8) & 0xFF00);
}

//=============================================================================
// GuidFromName(GUID * pGuidResult, REFGUID refGuidNsid,
//              const void * pvName, DWORD dwcbName);
//=============================================================================

void GuidFromName
(
    GUID *  pGuidResult,        // resulting GUID
    REFGUID refGuidNsid,        // Name Space GUID, so identical names from
                                // different name spaces generate different GUIDs
    const void * pvName,        // the name from which to generate a GUID
    DWORD dwcbName              // name length in bytes
)
{
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_GC_NOTRIGGER;

    MD5         md5;            // Cryptographic hash class instance
    MD5HASHDATA md5HashData;    // 128-bit hash result
    GUID        guidNsid;       // context NameSpace GUID in network byte order

    GUID        guidTemp;

    // put name space ID in network byte order so it hashes the same
    // no matter what endian machine we're on
    guidNsid = refGuidNsid;

    // The sample code in the IETF draft document discards the result of
    // htonl and htons.  I've implemented what I think is meant and I've
    // sent a note to the author asking for confirmation that this is
    // his intent.
    if (!BigEndian())   // evaluated at compile time in retail builds
    {
        guidNsid.Data1 = HostToNetworkLong (guidNsid.Data1);
        guidNsid.Data2 = HostToNetworkShort(guidNsid.Data2);
        guidNsid.Data3 = HostToNetworkShort(guidNsid.Data3);
    }

    md5.Init();
    md5.HashMore(&guidNsid, sizeof(GUID));
    md5.HashMore(pvName, dwcbName);
    md5.GetHashValue(&md5HashData);

    // the hash is in network byte order at this point
    memcpy(&guidTemp, &md5HashData, sizeof(GUID));

    // Remainder adapted from function "format_uuid_v3" in IETF draft document
    // Construct a version 3 uuid with the pseudo-random number plus a few constants.
    // convert GUID from network order to local byte order
    if (!BigEndian())   // evaluated at compile time in retail builds
    {
        guidTemp.Data1 = NetworkToHostLong (guidTemp.Data1);
        guidTemp.Data2 = NetworkToHostShort(guidTemp.Data2);
        guidTemp.Data3 = NetworkToHostShort(guidTemp.Data3);
    }

    // set version number
    guidTemp.Data3 &= 0x0FFF;   // clear version number nibble
    guidTemp.Data3 |= (3 << 12);// set version 3 = name-based

    // set variant field
    guidTemp.Data4[0] &= 0x3F;  // clear variant bits
    guidTemp.Data4[0] |= 0x80;  // set variant = 100b

    // If two GuidFromName calls were made from different threads with the same parameters,
    // we may get incorrect result even though the expected result is the same, because
    // GuidFromName is operating on the same pGuidResult buffer.
    // Fix this problem by using a temp GUID buffer and then copy to the pGuidResult buffer.
    memcpy(pGuidResult, &guidTemp, sizeof(GUID));
}

// This guid is used for calling GuidFromName function as COM+ runtime uniqualifier
//
// {69F9CBC9-DA05-11d1-9408-0000F8083460}
static const GUID COMPLUS_RUNTIME_GUID = {0x69f9cbc9, 0xda05, 0x11d1,
        {0x94, 0x8, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60}};

void CorGuidFromNameW
(
    GUID *  pGuidResult,        // resulting GUID
    LPCWSTR wzName,             // the unicode name from which to generate a GUID
    SIZE_T  cchName             // name length in count of unicode character
)
{
    WRAPPER_NO_CONTRACT;

    GuidFromName(
        pGuidResult,
        COMPLUS_RUNTIME_GUID,
        wzName,
        (DWORD)((cchName == (SIZE_T) -1 ? (lstrlenW(wzName)+1) : cchName) * sizeof(WCHAR)));
}
<|endoftext|>