<commit_before>//=============================================================================
// ■ init.cpp
//-----------------------------------------------------------------------------
//   所有初始化相关的代码都被放置在这里。
//=============================================================================

#include "global.hpp"

//-----------------------------------------------------------------------------
// ● 设置视口
//-----------------------------------------------------------------------------
void setup_viewport() {
	int width, height;
	glfwGetFramebufferSize(window, &width, &height);
	glViewport(0, 0, width, height);
}

//-----------------------------------------------------------------------------
// ● GL数据查询
//-----------------------------------------------------------------------------
void GL_info() {
	log("==========================");
	log("OpenGL Info:");
	GLint a, b;
	glGetIntegerv(GL_MAJOR_VERSION, &a);
	glGetIntegerv(GL_MINOR_VERSION, &b);
	log("Supproted GL Version %d.%d", a, b);
	log("==========================");
	glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &a);
	log("Maximum vertex attributes: %d", a);
	glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &a);
	log("Maximum vertex output components: %d", a);
	glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &a);
	log("Maximum fragment shader storage blocks: %d", a);
	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &a);
	log("Maximum texture size: %d", a);
	glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &a);
	log("Maximum texture unit: %d", a);
	log("==========================");
}

//-----------------------------------------------------------------------------
// ● 检查GL是否有错误
//-----------------------------------------------------------------------------
void check_gl_error() {
	GLenum error;
	int count = 0;
	while ((error = glGetError())) switch (count++, error) {
	#define case(x) case x: log("GL error: %s", #x); break
	case(GL_INVALID_ENUM);
	case(GL_INVALID_VALUE);
	case(GL_INVALID_OPERATION);
	case(GL_INVALID_FRAMEBUFFER_OPERATION);
	case(GL_OUT_OF_MEMORY);
	default:
		log("unknown GL error: %d", error);
		break;
	#undef case
	}
	if (count) error("These are all the errors from glGetError().");
}

//-----------------------------------------------------------------------------
// ● 初始化图形
//-----------------------------------------------------------------------------
void init_graphics(int w, int h, const char* title) {
	init_vmde(w, h);

	// GLFW库初始化
	glfwSetErrorCallback(glfw_error_callback);
	if (!glfwInit()) {
		log("glfwInit() failed");
		return;
	}

	// OpenGL 向前&向后兼容，使用GL 3.3 Core Profile，窗口大小不可变
	// 如果有更高版本就利用
	// 指定版本后便无需再检查是否支持指定版本，因为GLFW会处理此问题
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

	window = glfwCreateWindow(VMDE->width, VMDE->height, title, NULL, NULL);
	if (!window) {
		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
		window = glfwCreateWindow(VMDE->width, VMDE->height, title, NULL, NULL);
		VMDE->gl_ver = GL_33;
		if (!window) {
			glfwTerminate();
			error("glfwCreateWindow() (GLFW Window Creation) failed. Your computer need OpenGL 3.3.");
			return;
		}
		log("OpenGL API: 3.3");
	} else {
		VMDE->gl_ver = GL_43;
		log("OpenGL API: 4.3");
	}

	VMSC::init_graphics_state();

	setup_viewport();

	// Query GL info
	GL_info();

	// Setup API constants
	PostProcessingManager::init();
	glDepthRange(0.0f, 1.0f);
	glDepthMask(GL_TRUE);
	glClearDepth(1.0f);

	glDepthFunc(GL_LEQUAL);

	glFrontFace(GL_CCW);
	VMStateControl::enable_depth_test();
	VMStateControl::enable_cullface();
}

//-----------------------------------------------------------------------------
// ● 初始化引擎
//-----------------------------------------------------------------------------
void init_engine(int w, int h, const char* title) {
	Util::init();
	log("initializing the engine");
	srand(time(NULL));
	log("The system is %s-endian.", is_little_endian() ? "little" : "big");

	init_vmde(w, h);
	init_graphics(w, h, title);
	Audio::init();

	log("initialized the engine");
}

//-----------------------------------------------------------------------------
// ● 初始化VMDE结构体
//-----------------------------------------------------------------------------
void init_vmde(int w, int h) {
	VMDE = new struct VMDE;
	VMDE->state.frozen = false;
	VMDE->state.brightness = 1.0;
	VMDE->frame_count = 0;
	VMDE->fps = 0;
	VMDE->width = w;
	VMDE->height = h;
	VMDE->done = false;
}
<commit_msg>GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS is not available in GL 3<commit_after>//=============================================================================
// ■ init.cpp
//-----------------------------------------------------------------------------
//   所有初始化相关的代码都被放置在这里。
//=============================================================================

#include "global.hpp"

//-----------------------------------------------------------------------------
// ● 设置视口
//-----------------------------------------------------------------------------
void setup_viewport() {
	int width, height;
	glfwGetFramebufferSize(window, &width, &height);
	glViewport(0, 0, width, height);
}

//-----------------------------------------------------------------------------
// ● GL数据查询
//-----------------------------------------------------------------------------
void GL_info() {
	log("==========================");
	log("OpenGL Info:");
	GLint a, b;
	glGetIntegerv(GL_MAJOR_VERSION, &a);
	glGetIntegerv(GL_MINOR_VERSION, &b);
	log("Supproted GL Version %d.%d", a, b);
	log("==========================");
	glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &a);
	log("Maximum vertex attributes: %d", a);
	glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &a);
	if (VMDE->gl_ver == GL_43) {
		log("Maximum vertex output components: %d", a);
		glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &a);
	}
	log("Maximum fragment shader storage blocks: %d", a);
	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &a);
	log("Maximum texture size: %d", a);
	glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &a);
	log("Maximum texture unit: %d", a);
	log("==========================");
}

//-----------------------------------------------------------------------------
// ● 检查GL是否有错误
//-----------------------------------------------------------------------------
void check_gl_error() {
	GLenum error;
	int count = 0;
	while ((error = glGetError())) switch (count++, error) {
	#define case(x) case x: log("GL error: %s", #x); break
	case(GL_INVALID_ENUM);
	case(GL_INVALID_VALUE);
	case(GL_INVALID_OPERATION);
	case(GL_INVALID_FRAMEBUFFER_OPERATION);
	case(GL_OUT_OF_MEMORY);
	default:
		log("unknown GL error: %d", error);
		break;
	#undef case
	}
	if (count) error("These are all the errors from glGetError().");
}

//-----------------------------------------------------------------------------
// ● 初始化图形
//-----------------------------------------------------------------------------
void init_graphics(int w, int h, const char* title) {
	init_vmde(w, h);

	// GLFW库初始化
	glfwSetErrorCallback(glfw_error_callback);
	if (!glfwInit()) {
		log("glfwInit() failed");
		return;
	}

	// OpenGL 向前&向后兼容，使用GL 3.3 Core Profile，窗口大小不可变
	// 如果有更高版本就利用
	// 指定版本后便无需再检查是否支持指定版本，因为GLFW会处理此问题
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

	window = glfwCreateWindow(VMDE->width, VMDE->height, title, NULL, NULL);
	if (!window) {
		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
		window = glfwCreateWindow(VMDE->width, VMDE->height, title, NULL, NULL);
		VMDE->gl_ver = GL_33;
		if (!window) {
			glfwTerminate();
			error("glfwCreateWindow() (GLFW Window Creation) failed. Your computer need OpenGL 3.3.");
			return;
		}
		log("OpenGL API: 3.3");
	} else {
		VMDE->gl_ver = GL_43;
		log("OpenGL API: 4.3");
	}

	VMSC::init_graphics_state();

	setup_viewport();

	// Query GL info
	GL_info();

	// Setup API constants
	PostProcessingManager::init();
	glDepthRange(0.0f, 1.0f);
	glDepthMask(GL_TRUE);
	glClearDepth(1.0f);

	glDepthFunc(GL_LEQUAL);

	glFrontFace(GL_CCW);
	VMStateControl::enable_depth_test();
	VMStateControl::enable_cullface();
}

//-----------------------------------------------------------------------------
// ● 初始化引擎
//-----------------------------------------------------------------------------
void init_engine(int w, int h, const char* title) {
	Util::init();
	log("initializing the engine");
	srand(time(NULL));
	log("The system is %s-endian.", is_little_endian() ? "little" : "big");

	init_vmde(w, h);
	init_graphics(w, h, title);
	Audio::init();

	log("initialized the engine");
}

//-----------------------------------------------------------------------------
// ● 初始化VMDE结构体
//-----------------------------------------------------------------------------
void init_vmde(int w, int h) {
	VMDE = new struct VMDE;
	VMDE->state.frozen = false;
	VMDE->state.brightness = 1.0;
	VMDE->frame_count = 0;
	VMDE->fps = 0;
	VMDE->width = w;
	VMDE->height = h;
	VMDE->done = false;
}
<|endoftext|>


<commit_before>#include "VmbCamera.h"

// Frame buffer size
const int VmbCamera::frame_buffer_size = 5;

// Initialize Vimba and the camera
void VmbCamera::Startup() {
	// Initialize Vimba
	VmbStartup();
	// Send discovery packet to GigE cameras
	VmbFeatureCommandRun( gVimbaHandle, "GeVDiscoveryAllOnce" );
	// Get the first known camera
	VmbCameraInfo_t camera;
	VmbUint32_t count;
	VmbCamerasList( &camera, 1, &count, sizeof(VmbCameraInfo_t) );
	// Connect to the camera
	VmbCameraOpen( camera.cameraIdString, VmbAccessModeFull, &handle );
	// Adjust packet size automatically
	VmbFeatureCommandRun( handle, "GVSPAdjustPacketSize" );
	// Get image parameters
	VmbInt64_t width;
	VmbInt64_t height;
	VmbInt64_t payload_size;
	VmbFeatureIntGet( handle, "Width", &width );
	VmbFeatureIntGet( handle, "Height", &height );
	VmbFeatureIntGet( handle, "PayloadSize", &payload_size );
	// Create the Qt image (grayscale)
	image = QImage( width, height, QImage::Format_Indexed8 );
	// Create an indexed color table for the Qt image
	image.setColorCount( 256 );
	for( int i=0; i<256; i++ ) {
		image.setColor( i, qRgb(i, i, i) );
	}
	// Initialize the frame buffer
	frame_buffer = (VmbFrame_t*)malloc( frame_buffer_size * sizeof(VmbFrame_t) );
	// Allocate the frames
	for( int i=0; i<frame_buffer_size; i++ ) {
		// Allocate accordingly
		frame_buffer[i].buffer = (VmbUchar_t*)malloc( (VmbUint32_t)payload_size );
		frame_buffer[i].bufferSize = (VmbUint32_t)payload_size;
		// Register this object in the frame context
		frame_buffer[i].context[0] = this;
	}
}

// Shutdown the camera and Vimba
void VmbCamera::Shutdown() {
	// Close the camera
	VmbCameraClose( handle );
	// Shutdown Vimba
	VmbShutdown();
	// Free the frame buffer
	for( int i=0; i<frame_buffer_size; i++ ) {
		free( frame_buffer[i].buffer );
	}
	free( frame_buffer );
}

// Start acquisition
void VmbCamera::StartCapture() const {
	// Announce the frames
	for( int i=0; i<frame_buffer_size; i++ ) {
		VmbFrameAnnounce( handle, &frame_buffer[i], sizeof( VmbFrame_t ) );
	}
	// Start capture engine
	VmbCaptureStart( handle );
	// Queue frames and register callback
	for( int i=0; i<frame_buffer_size; i++ ) {
		VmbCaptureFrameQueue( handle, &frame_buffer[i], &FrameDoneCallback );
	}
	// Start acquisition
	VmbFeatureCommandRun( handle, "AcquisitionStart" );
}

// Stop acquisition
void VmbCamera::StopCapture() const {
	// Stop acquisition
	VmbFeatureCommandRun( handle, "AcquisitionStop" );
	// Flush the frame queue
	VmbCaptureQueueFlush( handle );
	// Stop capture engine
	VmbCaptureEnd( handle );
	// Revoke the frames
	VmbFrameRevokeAll( handle );
}

// Get the camera exposure time in microseconds
double VmbCamera::Exposure() const {
	double exposure;
	VmbFeatureFloatGet( handle, "ExposureTimeAbs", &exposure );
	return exposure;
}

// Set the camera exposure time in microseconds
void VmbCamera::SetExposure( double exposure ) const {
	VmbFeatureFloatSet( handle, "ExposureTimeAbs", exposure );
}

// Get the camera image
const QImage& VmbCamera::Image() const {
	return image;
}

// The callback that gets executed on every filled frame
void VMB_CALL VmbCamera::FrameDoneCallback( const VmbHandle_t camera_handle, VmbFrame_t* frame_pointer ) {
	// Check frame status
	if( frame_pointer->receiveStatus == VmbFrameStatusComplete ) {
		// Get the camera object in the frame context
		VmbCamera* camera = (VmbCamera*)frame_pointer->context[0];
		// Copy the camera frame buffer to the Qt image
		memcpy( camera->image.bits(), frame_pointer->buffer, frame_pointer->bufferSize );
		// Emit the image ready signal
		emit camera->ImageReady();
	}
	// Requeue the frame
	VmbCaptureFrameQueue( camera_handle , frame_pointer , &FrameDoneCallback );
}
<commit_msg>Remove for loop blocks.<commit_after>#include "VmbCamera.h"

// Frame buffer size
const int VmbCamera::frame_buffer_size = 5;

// Initialize Vimba and the camera
void VmbCamera::Startup() {
	// Initialize Vimba
	VmbStartup();
	// Send discovery packet to GigE cameras
	VmbFeatureCommandRun( gVimbaHandle, "GeVDiscoveryAllOnce" );
	// Get the first known camera
	VmbCameraInfo_t camera;
	VmbUint32_t count;
	VmbCamerasList( &camera, 1, &count, sizeof(VmbCameraInfo_t) );
	// Connect to the camera
	VmbCameraOpen( camera.cameraIdString, VmbAccessModeFull, &handle );
	// Adjust packet size automatically
	VmbFeatureCommandRun( handle, "GVSPAdjustPacketSize" );
	// Get image parameters
	VmbInt64_t width;
	VmbInt64_t height;
	VmbInt64_t payload_size;
	VmbFeatureIntGet( handle, "Width", &width );
	VmbFeatureIntGet( handle, "Height", &height );
	VmbFeatureIntGet( handle, "PayloadSize", &payload_size );
	// Create the Qt image (grayscale)
	image = QImage( width, height, QImage::Format_Indexed8 );
	// Create an indexed color table for the Qt image
	image.setColorCount( 256 );
	for( int i=0; i<256; i++ )
		image.setColor( i, qRgb(i, i, i) );
	// Initialize the frame buffer
	frame_buffer = (VmbFrame_t*)malloc( frame_buffer_size * sizeof(VmbFrame_t) );
	// Allocate the frames
	for( int i=0; i<frame_buffer_size; i++ ) {
		// Allocate accordingly
		frame_buffer[i].buffer = (VmbUchar_t*)malloc( (VmbUint32_t)payload_size );
		frame_buffer[i].bufferSize = (VmbUint32_t)payload_size;
		// Register this object in the frame context
		frame_buffer[i].context[0] = this;
	}
}

// Shutdown the camera and Vimba
void VmbCamera::Shutdown() {
	// Close the camera
	VmbCameraClose( handle );
	// Shutdown Vimba
	VmbShutdown();
	// Free the frame buffer
	for( int i=0; i<frame_buffer_size; i++ )
		free( frame_buffer[i].buffer );
	free( frame_buffer );
}

// Start acquisition
void VmbCamera::StartCapture() const {
	// Announce the frames
	for( int i=0; i<frame_buffer_size; i++ )
		VmbFrameAnnounce( handle, &frame_buffer[i], sizeof(VmbFrame_t) );
	// Start capture engine
	VmbCaptureStart( handle );
	// Queue frames and register callback
	for( int i=0; i<frame_buffer_size; i++ )
		VmbCaptureFrameQueue( handle, &frame_buffer[i], &FrameDoneCallback );
	// Start acquisition
	VmbFeatureCommandRun( handle, "AcquisitionStart" );
}

// Stop acquisition
void VmbCamera::StopCapture() const {
	// Stop acquisition
	VmbFeatureCommandRun( handle, "AcquisitionStop" );
	// Flush the frame queue
	VmbCaptureQueueFlush( handle );
	// Stop capture engine
	VmbCaptureEnd( handle );
	// Revoke the frames
	VmbFrameRevokeAll( handle );
}

// Get the camera exposure time in microseconds
double VmbCamera::Exposure() const {
	double exposure;
	VmbFeatureFloatGet( handle, "ExposureTimeAbs", &exposure );
	return exposure;
}

// Set the camera exposure time in microseconds
void VmbCamera::SetExposure( double exposure ) const {
	VmbFeatureFloatSet( handle, "ExposureTimeAbs", exposure );
}

// Get the camera image
const QImage& VmbCamera::Image() const {
	return image;
}

// The callback that gets executed on every filled frame
void VMB_CALL VmbCamera::FrameDoneCallback( const VmbHandle_t camera_handle, VmbFrame_t* frame_pointer ) {
	// Check frame status
	if( frame_pointer->receiveStatus == VmbFrameStatusComplete ) {
		// Get the camera object in the frame context
		VmbCamera* camera = (VmbCamera*)frame_pointer->context[0];
		// Copy the camera frame buffer to the Qt image
		memcpy( camera->image.bits(), frame_pointer->buffer, frame_pointer->bufferSize );
		// Emit the image ready signal
		emit camera->ImageReady();
	}
	// Requeue the frame
	VmbCaptureFrameQueue( camera_handle , frame_pointer , &FrameDoneCallback );
}
<|endoftext|>


<commit_before>#include <sstream>
#include <iostream>
#include "execution.h"

const int size = 3;

int field[size][size];

bool diag1(int xo)
{
    for (int i = 0 ; i < size ; ++i)
    {
        if (field[i][i] != xo)
            return false;
    }
    return true;
}

bool diag2(int xo)
{
    for (int i = 0 ; i < size ; ++i)
    {
        if (field[i][size - i - 1] != xo)
            return false;
    }
    return true;
}

bool horz(int xo, int i)
{
    for (int j = 0 ; j < size ; ++j)
        if (field[i][j] != xo)
            return false;
    return true;
}

bool vert(int xo, int i)
{
    for (int j = 0 ; j < size ; ++j)
        if (field[j][i] != xo)
            return false;
    return true;
}

void saveField()
{
	std::ostringstream outs;
	for (int i = 0 ; i < size ; ++i)
	{
		for (int j = 0 ; j < size ; ++j)
			outs << field[i][j] << " ";
		outs << "\n";
	}
	printField(outs.str());
}

int main(int argc, char **argv)
{
    if (argc != 3)
    {
        std::cout << "Usage: XO_tester <program1> <program2>\n";
        return 1;
    }
    const char *program1 = argv[1];
    const char *program2 = argv[2];

    //initLog(program1, program2);

	// save field and score before the first move
	saveField();

    ExecutionResult result = ER_OK;
    for (int move = 0 ; move < size * size ; ++move)
    {
        bool first = move % 2 == 0;
        std::ostringstream outs;
		outs << !first + 1 << "\n";
        for (int i = 0 ; i < size ; ++i)
        {
            for (int j = 0 ; j < size ; ++j)
            {
                outs << field[i][j] << " ";
            }
            outs << "\n";
        }
        std::string output;
        result = runProcess(first ? program1 : program2,
            outs.str(), output, 1000, 64000);
        if (result == ER_OK)
        {
            std::istringstream ins(output);
            int x, y;
            ins >> y >> x;
            if (x >= 1 && x <= size && y >= 1 && y <= size
                && !field[y-1][x-1])
            {
                printLog(first, result, output);

                int xo = first ? 1 : 2;
                field[y-1][x-1] = xo;

				saveField();

				// check win
                if (diag1(xo) || diag2(xo) || horz(xo, y - 1) || vert(xo, x - 1))
                {
                    result = ER_WIN;
                    printLog(first, result, output);
                    break;
                }
            }
            else
            {
                result = ER_IM;
                printLog(first, result, output);
                break;
            }
        }
        else
        {
            printLog(first, result, "");
            break;
        }
    }

    if (result == ER_OK)
    {
        result = ER_TIE;
        printLog(false, result, "");
    }

    return 0;
}
<commit_msg>added bugged XO tester with strange exceptions on template functions<commit_after>#include <sstream>
#include <iostream>
#include "execution.h"
#include "testlib.h"

const int size = 3;

int field[size][size];

bool diag1(int xo)
{
    for (int i = 0 ; i < size ; ++i)
    {
        if (field[i][i] != xo)
            return false;
    }
    return true;
}

bool diag2(int xo)
{
    for (int i = 0 ; i < size ; ++i)
    {
        if (field[i][size - i - 1] != xo)
            return false;
    }
    return true;
}

bool horz(int xo, int i)
{
    for (int j = 0 ; j < size ; ++j)
        if (field[i][j] != xo)
            return false;
    return true;
}

bool vert(int xo, int i)
{
    for (int j = 0 ; j < size ; ++j)
        if (field[j][i] != xo)
            return false;
    return true;
}

void saveField()
{
	std::ostringstream outs;
	for (int i = 0 ; i < size ; ++i)
	{
		for (int j = 0 ; j < size ; ++j)
			outs << field[i][j] << " ";
		outs << "\n";
	}
	printField(outs.str());
}

int main(int argc, char **argv)
{
    if (argc != 3)
    {
        std::cout << "Usage: XO_tester <program1> <program2>\n";
        return 1;
    }
    const char *program1 = argv[1];
    const char *program2 = argv[2];

    //initLog(program1, program2);

	// save field and score before the first move
	saveField();

    ExecutionResult result = ER_OK;
    for (int move = 0 ; move < size * size ; ++move)
    {
        bool first = move % 2 == 0;
        std::ostringstream outs;
		outs << !first + 1 << "\n";
        for (int i = 0 ; i < size ; ++i)
        {
            for (int j = 0 ; j < size ; ++j)
            {
                outs << field[i][j] << " ";
            }
            outs << "\n";
        }
        std::string output;
        result = runProcess(first ? program1 : program2,
            outs.str(), output, 1000, 64000);
        if (result == ER_OK)
        {

            //std::istringstream ins(output);
            InStream ins(output);
            try
            {
                int x, y;
                ins >> ValueInBounds<int>(y, 1, size) >> ValueInBounds<int>(x, 1, size);

                if (!field[y-1][x-1])
                {
                    printLog(first, result, output);

                    int xo = first ? 1 : 2;
                    field[y-1][x-1] = xo;

                    saveField();

                    // check win
                    if (diag1(xo) || diag2(xo) || horz(xo, y - 1) || vert(xo, x - 1))
                    {
                        result = ER_WIN;
                        printLog(first, result, output);
                        break;
                    }
                }
                else
                {
                    result = ER_IM;
                    printLog(first, result, output);
                    break;
                }

            }
            catch (ReadCheckerException &exception)
            {
                result = ER_IM;
                std::ostringstream out;
                out << output << "\n" << exception.getReadResultText() << ": " << exception.what() << std::endl;
                printLog(first, result, out.str());
                return 0;
            }
        }
        else
        {
            printLog(first, result, "");
            break;
        }
    }

    if (result == ER_OK)
    {
        result = ER_TIE;
        printLog(false, result, "");
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "CobraProcess.h"
#include "RouterInitializer.h"

#include <common/SFLogger.h>
#include <la-manager/LAPool.h>
#include <license-manager/LicenseManager.h>

#include <bundles/querylog/QueryLogBundleConfiguration.h>
#include <bundles/querylog/QueryLogBundleActivator.h>

#include <OnSignal.h>
#include <common/XmlConfigParser.h>
#include <common/CollectionManager.h>
#include <controllers/CollectionHandler.h>
#include <controllers/Sf1Controller.h>

#include <util/ustring/UString.h>
#include <util/driver/IPRestrictor.h>
#include <util/driver/DriverConnectionFirewall.h>
#include <util/singleton.h>

#include <question-answering/QuestionAnalysis.h>

#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/shared_ptr.hpp>

#include <iostream>
#include <sstream>
#include <string>
#include <set>
#include <vector>
#include <map>

using namespace sf1r;
using namespace boost::filesystem;
using namespace izenelib::util;
using namespace izenelib::driver;

namespace bfs = boost::filesystem;

#define ipRestrictor ::izenelib::driver::IPRestrictor::getInstance()

bool CobraProcess::initialize(const std::string& configFileDir)
{
    if( !exists(configFileDir) || !is_directory(configFileDir) ) return false;
    bfs::path logPath(bfs::path(".") / "log" / "COBRA");
    if( !sflog->init( logPath.string() ) ) return false;
    try
    {
        configDir_ = configFileDir;
        boost::filesystem::path p(configFileDir);
        SF1Config::get()->setHomeDirectory(p.string());
        if( !SF1Config::get()->parseConfigFile( bfs::path(p/"sf1config.xml").string() ) )
        {
            return false;
        }
    }
    catch ( izenelib::util::ticpp::Exception & e )
    {
        cerr << e.what() << endl;
        return false;
    }

    if(!initLAManager()) return false;

    if(!initFireWall()) return false;

    if(!initLicenseManager()) return false;

    initDriverServer();

    return true;
}

bool CobraProcess::initLAManager()
{
    LAManagerConfig laConfig;
    SF1Config::get()->getLAManagerConfig(laConfig);

    ///TODO
    /// Ugly here, to be optimized through better configuration
    LAConfigUnit config2;
    config2.setId( "la_sia" );
    config2.setAnalysis( "korean" );
    config2.setMode( "label" );
    config2.setDictionaryPath( laConfig.kma_path_ ); // defined macro

    laConfig.addLAConfig(config2);

    AnalysisInfo analysisInfo2;
    analysisInfo2.analyzerId_ = "la_sia";
    analysisInfo2.tokenizerNameList_.insert("tok_divide");
    laConfig.addAnalysisPair(analysisInfo2);

    if (! LAPool::getInstance()->init(laConfig))
        return false;

    atexit(&LAPool::destroy);

    return true;
}

QueryLogSearchService* CobraProcess::initQuery()
{
    ilplib::qa::QuestionAnalysis* pQA = Singleton<ilplib::qa::QuestionAnalysis>::get();
    std::string qahome = SF1Config::get()->getResourceDir();
    bfs::path path(bfs::path(qahome) / "qa" / "questionwords.txt");
    std::string qaPath = path.string();
    if( boost::filesystem::exists(qaPath) )
    {
        pQA->load(qaPath);
    }

    ///create QueryLogBundle
    boost::shared_ptr<QueryLogBundleConfiguration> queryLogBundleConfig
    (new QueryLogBundleConfiguration(SF1Config::get()->queryLogBundleConfig_));
    std::string bundleName = "QueryLogBundle";
    OSGILauncher& launcher = CollectionManager::get()->getOSGILauncher();
    launcher.start(queryLogBundleConfig);
    QueryLogSearchService* service = static_cast<QueryLogSearchService*>(launcher.getService(bundleName, "QueryLogSearchService"));

    //addExitHook(boost::bind(&OSGILauncher::stop, launcher));

    return service;
}

bool CobraProcess::initLicenseManager()
{
#ifdef COBRA_RESTRICT
    boost::shared_ptr<LicenseManager> licenseManager;
    // license manager initialization.
    char* home = getenv("HOME");
    std::string licenseDir = home; licenseDir += "/sf1-license/";
    try { // If license directory is not exist, create it.
        if ( !boost::filesystem::exists(licenseDir) ) {
            std::cout << "[Warning] : " << licenseDir << " is Created." << std::endl;
            boost::filesystem::create_directories(licenseDir);
        }
    } catch (boost::filesystem::filesystem_error& e) {
        std::cerr << "Error : " << e.what() << std::endl;
        return false;
    }
    std::string path = licenseDir + LicenseManager::LICENSE_KEY_FILENAME;
    licenseManager.reset( new LicenseManager("1.0.0", path, false) );

    path = licenseDir + LicenseManager::LICENSE_REQUEST_FILENAME;
    if ( !licenseManager->createLicenseRequestFile(path) )
    {
        sflog->error(SFL_INIT, "License Request File is failed to generated. Please check if you're a sudoer");
        return false;
    }

    if ( !licenseManager->validateLicenseFile() )
    {
        std::cerr << "[Warning] : license is invalid. Now sf1 will be worked on trial mode." << std::endl;
        sflog->error(SFL_INIT, "license is invalid. Now sf1 will be worked on trial mode.");
        LicenseManager::continueIndex_ = false;
    }

#endif // COBRA_RESTRICT
    return true;
}

bool CobraProcess::initFireWall()
{
    const FirewallConfig& fwConfig = SF1Config::get()->getFirewallConfig();
    std::vector<std::string>::const_iterator iter;
    for(iter = fwConfig.allowIPList_.begin(); iter != fwConfig.allowIPList_.end(); iter++)
        if ( !ipRestrictor->registerAllowIP( *iter ) )
            return false;
    for(iter = fwConfig.denyIPList_.begin(); iter != fwConfig.denyIPList_.end(); iter++)
        if ( !ipRestrictor->registerDenyIP( *iter ) )
            return false;
    return true;
}

bool CobraProcess::initDriverServer()
{
    const BrokerAgentConfig& baConfig = SF1Config::get()->getBrokerAgentConfig();
    std::size_t threadPoolSize = baConfig.threadNum_;
    bool enableTest = baConfig.enableTest_;
    unsigned int port = baConfig.port_;

    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(),port);

    // init Router
    router_.reset(new ::izenelib::driver::Router);
    QueryLogSearchService* service = initQuery();
    initializeDriverRouter(*router_, service, enableTest);

    boost::shared_ptr<DriverConnectionFactory> factory(
        new DriverConnectionFactory(router_)
    );
    factory->setFirewall(DriverConnectionFirewall());

    driverServer_.reset(
        new DriverServer(endpoint, factory, threadPoolSize)
    );

    addExitHook(boost::bind(&CobraProcess::stopDriver, this));

    return true;
}

void CobraProcess::stopDriver()
{
    if (driverServer_)
    {
        driverServer_->stop();
    }
}

int CobraProcess::run()
{
    setupDefaultSignalHandlers();

    bool caughtException = false;

    try
    {
        bfs::directory_iterator iter(configDir_), end_iter;
        for(; iter!= end_iter; ++iter)
        {
            if(bfs::is_regular_file(*iter))
            {
                if(iter->filename().rfind(".xml") == (iter->filename().length() - std::string(".xml").length()))
                    if(iter->filename() != "sf1config.xml")
                    {
                        std::string collectionName = iter->filename().substr(0,iter->filename().rfind(".xml"));
                        CollectionManager::get()->startCollection(collectionName, iter->string());
                    }
            }
        }

#ifdef  EXIST_LICENSE
            char* home = getenv("HOME");
            std::string licenseDir = home; licenseDir += "/sf1-license/";

            {
                std::string filePath = licenseDir + LicenseManager::TOKEN_FILENAME;
                std::string token("");
                if ( !LicenseManager::extract_token_from(filePath, token) )
                {
                    return false;
                }

                ///Insert the extracted token into the deny control lists for all collections
                std::map<std::string, CollectionMeta>&
                    collectionMetaMap = SF1Config::get()->mutableCollectionMetaMap();
                std::map<std::string, CollectionMeta>::iterator
                    collectionIter = collectionMetaMap.begin();

                for(; collectionIter != collectionMetaMap.end(); collectionIter++)
                {
                    CollectionMeta& collectionMeta = collectionIter->second;
                    collectionMeta.aclDeny(token);
                }
            }
#endif

        driverServer_->run();
    }
    catch (const std::exception& e)
    {
        caughtException = true;
        std::cout << "Caught std exception:  "
                  << e.what() << std::endl;
    }
    catch (...)
    {
        caughtException = true;
        cout<<"Exit, catch exception here"<<endl;
    }

    return caughtException ? 1 : 0;
}

<commit_msg>when the sf1 server starts for the first time ,the token.dat does not exist, it can provide service normally<commit_after>#include "CobraProcess.h"
#include "RouterInitializer.h"

#include <common/SFLogger.h>
#include <la-manager/LAPool.h>
#include <license-manager/LicenseManager.h>

#include <bundles/querylog/QueryLogBundleConfiguration.h>
#include <bundles/querylog/QueryLogBundleActivator.h>

#include <OnSignal.h>
#include <common/XmlConfigParser.h>
#include <common/CollectionManager.h>
#include <controllers/CollectionHandler.h>
#include <controllers/Sf1Controller.h>

#include <util/ustring/UString.h>
#include <util/driver/IPRestrictor.h>
#include <util/driver/DriverConnectionFirewall.h>
#include <util/singleton.h>

#include <question-answering/QuestionAnalysis.h>

#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/shared_ptr.hpp>

#include <iostream>
#include <sstream>
#include <string>
#include <set>
#include <vector>
#include <map>

using namespace sf1r;
using namespace boost::filesystem;
using namespace izenelib::util;
using namespace izenelib::driver;

namespace bfs = boost::filesystem;

#define ipRestrictor ::izenelib::driver::IPRestrictor::getInstance()

bool CobraProcess::initialize(const std::string& configFileDir)
{
    if( !exists(configFileDir) || !is_directory(configFileDir) ) return false;
    bfs::path logPath(bfs::path(".") / "log" / "COBRA");
    if( !sflog->init( logPath.string() ) ) return false;
    try
    {
        configDir_ = configFileDir;
        boost::filesystem::path p(configFileDir);
        SF1Config::get()->setHomeDirectory(p.string());
        if( !SF1Config::get()->parseConfigFile( bfs::path(p/"sf1config.xml").string() ) )
        {
            return false;
        }
    }
    catch ( izenelib::util::ticpp::Exception & e )
    {
        cerr << e.what() << endl;
        return false;
    }

    if(!initLAManager()) return false;

    if(!initFireWall()) return false;

    if(!initLicenseManager()) return false;

    initDriverServer();

    return true;
}

bool CobraProcess::initLAManager()
{
    LAManagerConfig laConfig;
    SF1Config::get()->getLAManagerConfig(laConfig);

    ///TODO
    /// Ugly here, to be optimized through better configuration
    LAConfigUnit config2;
    config2.setId( "la_sia" );
    config2.setAnalysis( "korean" );
    config2.setMode( "label" );
    config2.setDictionaryPath( laConfig.kma_path_ ); // defined macro

    laConfig.addLAConfig(config2);

    AnalysisInfo analysisInfo2;
    analysisInfo2.analyzerId_ = "la_sia";
    analysisInfo2.tokenizerNameList_.insert("tok_divide");
    laConfig.addAnalysisPair(analysisInfo2);

    if (! LAPool::getInstance()->init(laConfig))
        return false;

    atexit(&LAPool::destroy);

    return true;
}

QueryLogSearchService* CobraProcess::initQuery()
{
    ilplib::qa::QuestionAnalysis* pQA = Singleton<ilplib::qa::QuestionAnalysis>::get();
    std::string qahome = SF1Config::get()->getResourceDir();
    bfs::path path(bfs::path(qahome) / "qa" / "questionwords.txt");
    std::string qaPath = path.string();
    if( boost::filesystem::exists(qaPath) )
    {
        pQA->load(qaPath);
    }

    ///create QueryLogBundle
    boost::shared_ptr<QueryLogBundleConfiguration> queryLogBundleConfig
    (new QueryLogBundleConfiguration(SF1Config::get()->queryLogBundleConfig_));
    std::string bundleName = "QueryLogBundle";
    OSGILauncher& launcher = CollectionManager::get()->getOSGILauncher();
    launcher.start(queryLogBundleConfig);
    QueryLogSearchService* service = static_cast<QueryLogSearchService*>(launcher.getService(bundleName, "QueryLogSearchService"));

    //addExitHook(boost::bind(&OSGILauncher::stop, launcher));

    return service;
}

bool CobraProcess::initLicenseManager()
{
#ifdef COBRA_RESTRICT
    boost::shared_ptr<LicenseManager> licenseManager;
    // license manager initialization.
    char* home = getenv("HOME");
    std::string licenseDir = home; licenseDir += "/sf1-license/";
    try { // If license directory is not exist, create it.
        if ( !boost::filesystem::exists(licenseDir) ) {
            std::cout << "[Warning] : " << licenseDir << " is Created." << std::endl;
            boost::filesystem::create_directories(licenseDir);
        }
    } catch (boost::filesystem::filesystem_error& e) {
        std::cerr << "Error : " << e.what() << std::endl;
        return false;
    }
    std::string path = licenseDir + LicenseManager::LICENSE_KEY_FILENAME;
    licenseManager.reset( new LicenseManager("1.0.0", path, false) );

    path = licenseDir + LicenseManager::LICENSE_REQUEST_FILENAME;
    if ( !licenseManager->createLicenseRequestFile(path) )
    {
        sflog->error(SFL_INIT, "License Request File is failed to generated. Please check if you're a sudoer");
        return false;
    }

    if ( !licenseManager->validateLicenseFile() )
    {
        std::cerr << "[Warning] : license is invalid. Now sf1 will be worked on trial mode." << std::endl;
        sflog->error(SFL_INIT, "license is invalid. Now sf1 will be worked on trial mode.");
        LicenseManager::continueIndex_ = false;
    }

#endif // COBRA_RESTRICT
    return true;
}

bool CobraProcess::initFireWall()
{
    const FirewallConfig& fwConfig = SF1Config::get()->getFirewallConfig();
    std::vector<std::string>::const_iterator iter;
    for(iter = fwConfig.allowIPList_.begin(); iter != fwConfig.allowIPList_.end(); iter++)
        if ( !ipRestrictor->registerAllowIP( *iter ) )
            return false;
    for(iter = fwConfig.denyIPList_.begin(); iter != fwConfig.denyIPList_.end(); iter++)
        if ( !ipRestrictor->registerDenyIP( *iter ) )
            return false;
    return true;
}

bool CobraProcess::initDriverServer()
{
    const BrokerAgentConfig& baConfig = SF1Config::get()->getBrokerAgentConfig();
    std::size_t threadPoolSize = baConfig.threadNum_;
    bool enableTest = baConfig.enableTest_;
    unsigned int port = baConfig.port_;

    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(),port);

    // init Router
    router_.reset(new ::izenelib::driver::Router);
    QueryLogSearchService* service = initQuery();
    initializeDriverRouter(*router_, service, enableTest);

    boost::shared_ptr<DriverConnectionFactory> factory(
        new DriverConnectionFactory(router_)
    );
    factory->setFirewall(DriverConnectionFirewall());

    driverServer_.reset(
        new DriverServer(endpoint, factory, threadPoolSize)
    );

    addExitHook(boost::bind(&CobraProcess::stopDriver, this));

    return true;
}

void CobraProcess::stopDriver()
{
    if (driverServer_)
    {
        driverServer_->stop();
    }
}

int CobraProcess::run()
{
    setupDefaultSignalHandlers();

    bool caughtException = false;

    try
    {
        bfs::directory_iterator iter(configDir_), end_iter;
        for(; iter!= end_iter; ++iter)
        {
            if(bfs::is_regular_file(*iter))
            {
                if(iter->filename().rfind(".xml") == (iter->filename().length() - std::string(".xml").length()))
                    if(iter->filename() != "sf1config.xml")
                    {
                        std::string collectionName = iter->filename().substr(0,iter->filename().rfind(".xml"));
                        CollectionManager::get()->startCollection(collectionName, iter->string());
                    }
            }
        }

#ifdef  EXIST_LICENSE
            char* home = getenv("HOME");
            std::string licenseDir = home; licenseDir += "/sf1-license/";

            {
                std::string filePath = licenseDir + LicenseManager::TOKEN_FILENAME;
                if( boost::filesystem::exists(filePath) )
                {
                    std::string token("");
                    LicenseManager::extract_token_from(filePath, token);

                    ///Insert the extracted token into the deny control lists for all collections
                    std::map<std::string, CollectionMeta>&
                        collectionMetaMap = SF1Config::get()->mutableCollectionMetaMap();
                    std::map<std::string, CollectionMeta>::iterator
                        collectionIter = collectionMetaMap.begin();

                    for(; collectionIter != collectionMetaMap.end(); collectionIter++)
                    {
                        CollectionMeta& collectionMeta = collectionIter->second;
                        collectionMeta.aclDeny(token);
                    }
                }
            }
#endif

        driverServer_->run();
    }
    catch (const std::exception& e)
    {
        caughtException = true;
        std::cout << "Caught std exception:  "
                  << e.what() << std::endl;
    }
    catch (...)
    {
        caughtException = true;
        cout<<"Exit, catch exception here"<<endl;
    }

    return caughtException ? 1 : 0;
}

<|endoftext|>


<commit_before>//
// Aspia Project
// Copyright (C) 2020 Dmitry Chapyshev <dmitry@aspia.ru>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

#include "relay/pending_session.h"

#include "base/endian_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/net/tcp_keep_alive.h"
#include "base/strings/unicode.h"

#include <asio/read.hpp>

namespace relay {

namespace {

constexpr std::chrono::seconds kTimeout{ 30 };
constexpr uint32_t kMaxMessageSize = 1 * 1024 * 1024; // 1 MB

} // namespace

PendingSession::PendingSession(std::shared_ptr<base::TaskRunner> task_runner,
                               asio::ip::tcp::socket&& socket,
                               Delegate* delegate)
    : delegate_(delegate),
      timer_(base::WaitableTimer::Type::SINGLE_SHOT, std::move(task_runner)),
      socket_(std::move(socket))
{
    // Nothing
}

PendingSession::~PendingSession()
{
    stop();
}

void PendingSession::start()
{
    LOG(LS_INFO) << "Starting pending session";

    asio::ip::tcp::no_delay option(true);
    asio::error_code error_code;

    socket_.set_option(option, error_code);
    if (error_code)
    {
        LOG(LS_ERROR) << "Failed to disable Nagle's algorithm: "
                      << base::utf16FromLocal8Bit(error_code.message());
    }

    base::setTcpKeepAlive(
        socket_.native_handle(), true, std::chrono::seconds(30), std::chrono::seconds(5));

    timer_.start(kTimeout, std::bind(
        &PendingSession::onErrorOccurred, this, FROM_HERE, std::error_code()));
    PendingSession::doReadMessage(this);
}

void PendingSession::stop()
{
    if (!delegate_)
        return;

    delegate_ = nullptr;
    timer_.stop();

    std::error_code ignored_code;
    socket_.cancel(ignored_code);
    socket_.close(ignored_code);
}

void PendingSession::setIdentify(uint32_t key_id, const base::ByteArray& secret)
{
    secret_ = secret;
    key_id_ = key_id;
}

bool PendingSession::isPeerFor(const PendingSession& other) const
{
    if (&other == this)
        return false;

    if (secret_.empty() || other.secret_.empty())
        return false;

    return key_id_ == other.key_id_ && base::equals(secret_, other.secret_);
}

asio::ip::tcp::socket PendingSession::takeSocket()
{
    return std::move(socket_);
}

// static
void PendingSession::doReadMessage(PendingSession* session)
{
    asio::async_read(session->socket_,
                     asio::buffer(&session->buffer_size_, sizeof(uint32_t)),
                     [session](const std::error_code& error_code, size_t bytes_transferred)
    {
        if (error_code)
        {
            if (error_code != asio::error::operation_aborted)
                session->onErrorOccurred(FROM_HERE, error_code);
            return;
        }

        if (bytes_transferred != sizeof(uint32_t))
        {
            session->onErrorOccurred(FROM_HERE, std::error_code());
            return;
        }

        session->buffer_size_ = base::EndianUtil::fromBig(session->buffer_size_);
        if (!session->buffer_size_ || session->buffer_size_ > kMaxMessageSize)
        {
            session->onErrorOccurred(FROM_HERE, std::error_code());
            return;
        }

        session->buffer_.resize(session->buffer_size_);

        asio::async_read(session->socket_,
                         asio::buffer(session->buffer_.data(), session->buffer_.size()),
                         [session](const std::error_code& error_code, size_t bytes_transferred)
        {
            if (error_code)
            {
                if (error_code != asio::error::operation_aborted)
                    session->onErrorOccurred(FROM_HERE, error_code);
                return;
            }

            if (bytes_transferred != session->buffer_.size())
            {
                session->onErrorOccurred(FROM_HERE, std::error_code());
                return;
            }

            session->onMessage();
        });
    });
}

void PendingSession::onErrorOccurred(
    const base::Location& location, const std::error_code& error_code)
{
    LOG(LS_ERROR) << "Connection error: " << base::utf16FromLocal8Bit(error_code.message())
                  << " (" << location.toString() << ")";
    if (delegate_)
        delegate_->onPendingSessionFailed(this);

    stop();
}

void PendingSession::onMessage()
{
    proto::PeerToRelay message;
    if (!message.ParseFromArray(buffer_.data(), buffer_.size()))
    {
        onErrorOccurred(FROM_HERE, std::error_code());
        return;
    }

    if (delegate_)
        delegate_->onPendingSessionReady(this, message);
}

} // namespace relay
<commit_msg>Remove TCP keep alive usage.<commit_after>//
// Aspia Project
// Copyright (C) 2020 Dmitry Chapyshev <dmitry@aspia.ru>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

#include "relay/pending_session.h"

#include "base/endian_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/strings/unicode.h"

#include <asio/read.hpp>

namespace relay {

namespace {

constexpr std::chrono::seconds kTimeout{ 30 };
constexpr uint32_t kMaxMessageSize = 1 * 1024 * 1024; // 1 MB

} // namespace

PendingSession::PendingSession(std::shared_ptr<base::TaskRunner> task_runner,
                               asio::ip::tcp::socket&& socket,
                               Delegate* delegate)
    : delegate_(delegate),
      timer_(base::WaitableTimer::Type::SINGLE_SHOT, std::move(task_runner)),
      socket_(std::move(socket))
{
    // Nothing
}

PendingSession::~PendingSession()
{
    stop();
}

void PendingSession::start()
{
    LOG(LS_INFO) << "Starting pending session";

    asio::ip::tcp::no_delay option(true);
    asio::error_code error_code;

    socket_.set_option(option, error_code);
    if (error_code)
    {
        LOG(LS_ERROR) << "Failed to disable Nagle's algorithm: "
                      << base::utf16FromLocal8Bit(error_code.message());
    }

    timer_.start(kTimeout, std::bind(
        &PendingSession::onErrorOccurred, this, FROM_HERE, std::error_code()));
    PendingSession::doReadMessage(this);
}

void PendingSession::stop()
{
    if (!delegate_)
        return;

    delegate_ = nullptr;
    timer_.stop();

    std::error_code ignored_code;
    socket_.cancel(ignored_code);
    socket_.close(ignored_code);
}

void PendingSession::setIdentify(uint32_t key_id, const base::ByteArray& secret)
{
    secret_ = secret;
    key_id_ = key_id;
}

bool PendingSession::isPeerFor(const PendingSession& other) const
{
    if (&other == this)
        return false;

    if (secret_.empty() || other.secret_.empty())
        return false;

    return key_id_ == other.key_id_ && base::equals(secret_, other.secret_);
}

asio::ip::tcp::socket PendingSession::takeSocket()
{
    return std::move(socket_);
}

// static
void PendingSession::doReadMessage(PendingSession* session)
{
    asio::async_read(session->socket_,
                     asio::buffer(&session->buffer_size_, sizeof(uint32_t)),
                     [session](const std::error_code& error_code, size_t bytes_transferred)
    {
        if (error_code)
        {
            if (error_code != asio::error::operation_aborted)
                session->onErrorOccurred(FROM_HERE, error_code);
            return;
        }

        if (bytes_transferred != sizeof(uint32_t))
        {
            session->onErrorOccurred(FROM_HERE, std::error_code());
            return;
        }

        session->buffer_size_ = base::EndianUtil::fromBig(session->buffer_size_);
        if (!session->buffer_size_ || session->buffer_size_ > kMaxMessageSize)
        {
            session->onErrorOccurred(FROM_HERE, std::error_code());
            return;
        }

        session->buffer_.resize(session->buffer_size_);

        asio::async_read(session->socket_,
                         asio::buffer(session->buffer_.data(), session->buffer_.size()),
                         [session](const std::error_code& error_code, size_t bytes_transferred)
        {
            if (error_code)
            {
                if (error_code != asio::error::operation_aborted)
                    session->onErrorOccurred(FROM_HERE, error_code);
                return;
            }

            if (bytes_transferred != session->buffer_.size())
            {
                session->onErrorOccurred(FROM_HERE, std::error_code());
                return;
            }

            session->onMessage();
        });
    });
}

void PendingSession::onErrorOccurred(
    const base::Location& location, const std::error_code& error_code)
{
    LOG(LS_ERROR) << "Connection error: " << base::utf16FromLocal8Bit(error_code.message())
                  << " (" << location.toString() << ")";
    if (delegate_)
        delegate_->onPendingSessionFailed(this);

    stop();
}

void PendingSession::onMessage()
{
    proto::PeerToRelay message;
    if (!message.ParseFromArray(buffer_.data(), buffer_.size()))
    {
        onErrorOccurred(FROM_HERE, std::error_code());
        return;
    }

    if (delegate_)
        delegate_->onPendingSessionReady(this, message);
}

} // namespace relay
<|endoftext|>


<commit_before>#include <node.h>
#include <v8.h>
#include <systemd/sd-journal.h>
#include <stdlib.h>

using namespace std;
using namespace v8;

/**
 * Log string messages to the journal. Type checking of the arguments is performed
 * in the journald.js module.
 */
Handle<Value> SdJournalSend(const Arguments& args) {
  HandleScope scope;
  int argc = args.Length();
  struct iovec *iov = NULL;

  iov = (iovec*) malloc(argc * sizeof(struct iovec));
  if (!iov) {
    return ThrowException(String::New("Out of memory"));
  }

  // Iterate through the JS arguments and fill the iovector.
  for (int i = 0; i < argc; ++i) {
    Local<String> v8str = args[i]->ToString();

    iov[i].iov_len = v8str->Length();
    iov[i].iov_base = (char*) malloc(v8str->Length() + 1);

    v8str->WriteAscii((char*)iov[i].iov_base, 0, iov[i].iov_len);
  }

  sd_journal_sendv(iov, argc);

  for (int i = 0; i < argc; ++i) {
    free(iov[i].iov_base);
  }
  free(iov);

  return scope.Close(Integer::New(1));
}

void init(Handle<Object> target) {
  target->Set(String::NewSymbol("send"), FunctionTemplate::New(SdJournalSend)->GetFunction());
}

NODE_MODULE(journald_lib, init)
<commit_msg>Return undefined from the send function<commit_after>#include <node.h>
#include <v8.h>
#include <systemd/sd-journal.h>
#include <stdlib.h>

using namespace std;
using namespace v8;

/**
 * Log string messages to the journal. Type checking of the arguments is performed
 * in the journald.js module.
 */
Handle<Value> SdJournalSend(const Arguments& args) {
  HandleScope scope;
  int argc = args.Length();
  struct iovec *iov = NULL;

  iov = (iovec*) malloc(argc * sizeof(struct iovec));
  if (!iov) {
    return ThrowException(String::New("Out of memory"));
  }

  // Iterate through the JS arguments and fill the iovector.
  for (int i = 0; i < argc; ++i) {
    Local<String> v8str = args[i]->ToString();

    iov[i].iov_len = v8str->Length();
    iov[i].iov_base = (char*) malloc(v8str->Length() + 1);

    v8str->WriteAscii((char*)iov[i].iov_base, 0, iov[i].iov_len);
  }

  sd_journal_sendv(iov, argc);

  for (int i = 0; i < argc; ++i) {
    free(iov[i].iov_base);
  }
  free(iov);

  return scope.Close(Undefined());
}

void init(Handle<Object> target) {
  target->Set(String::NewSymbol("send"), FunctionTemplate::New(SdJournalSend)->GetFunction());
}

NODE_MODULE(journald_lib, init)
<|endoftext|>


<commit_before>/**
 * \file
 * \brief ThisThread namespace implementation
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-10-23
 */

#include "distortos/scheduler/ThisThread.hpp"

#include "distortos/scheduler/schedulerInstance.hpp"
#include "distortos/scheduler/Scheduler.hpp"

namespace distortos
{

namespace scheduler
{

namespace ThisThread
{

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

uint8_t getPriority()
{
	return schedulerInstance.getCurrentThreadControlBlock().getPriority();
}

void setPriority(const uint8_t priority, const bool alwaysBehind)
{
	schedulerInstance.getCurrentThreadControlBlock().setPriority(priority);
}

void sleepFor(const TickClock::duration duration)
{
	sleepUntil(TickClock::now() + duration + TickClock::duration{1});
}

void sleepUntil(const TickClock::time_point timePoint)
{
	ThreadControlBlockList sleepingList {schedulerInstance.getThreadControlBlockListAllocator(),
			ThreadControlBlock::State::Sleeping};
	schedulerInstance.blockUntil(sleepingList, timePoint);
}

void yield()
{
	schedulerInstance.yield();
}

}	// namespace ThisThread

}	// namespace scheduler

}	// namespace distortos
<commit_msg>ThisThread: actually use alwaysBehind parameter in ThisThread::setPriority<commit_after>/**
 * \file
 * \brief ThisThread namespace implementation
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-10-24
 */

#include "distortos/scheduler/ThisThread.hpp"

#include "distortos/scheduler/schedulerInstance.hpp"
#include "distortos/scheduler/Scheduler.hpp"

namespace distortos
{

namespace scheduler
{

namespace ThisThread
{

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

uint8_t getPriority()
{
	return schedulerInstance.getCurrentThreadControlBlock().getPriority();
}

void setPriority(const uint8_t priority, const bool alwaysBehind)
{
	schedulerInstance.getCurrentThreadControlBlock().setPriority(priority, alwaysBehind);
}

void sleepFor(const TickClock::duration duration)
{
	sleepUntil(TickClock::now() + duration + TickClock::duration{1});
}

void sleepUntil(const TickClock::time_point timePoint)
{
	ThreadControlBlockList sleepingList {schedulerInstance.getThreadControlBlockListAllocator(),
			ThreadControlBlock::State::Sleeping};
	schedulerInstance.blockUntil(sleepingList, timePoint);
}

void yield()
{
	schedulerInstance.yield();
}

}	// namespace ThisThread

}	// namespace scheduler

}	// namespace distortos
<|endoftext|>


<commit_before>#include <Step/SPFFunctions.h>
#include <Step/BaseSPFWriter.h>
#include "../../tests.h"

#include <sstream>
#include <cassert>

#pragma execution_character_set("utf-8");

class MySPFWriter : public Step::BaseSPFWriter
{
public:

    MySPFWriter() : Step::BaseSPFWriter(0) {}

    virtual ~MySPFWriter() {}

    virtual bool write(std::ostream& ) { return true; }

    virtual std::string toSPF(Step::Real d)
    {
        std::ostringstream out;
        m_out = &out;
        writeAttribute(d);
        return out.str();
    }
};

/// testing Real Output

#define NB_TEST 12

double input[NB_TEST]={
    100000000,
    1e8,
    1e15,
    -100000000,
    -1e8,
    -1e15,
    1e-15,
    -1e-15,
    0,
    .5,
    1e30,
    1e98,
};

std::string expected_result[NB_TEST]={
    "100000000.",
    "100000000.",
    "1000000000000000.",
    "-100000000.",
    "-100000000.",
    "-1000000000000000.",
    "0.000000000000001",
    "-0.000000000000001",
    "0.",
    "0.5",
    "1.E+30",
    "1.E+98",
};

void test_Real()
{
    std::cerr << "test_Real" << std::endl;

    MySPFWriter writer;

    TEST_ASSERT(writer.toSPF(100000000) == "100000000.");
    TEST_ASSERT(writer.toSPF(1e8) == "100000000.");
    TEST_ASSERT(writer.toSPF(1e15) == "1000000000000000.");
    TEST_ASSERT(writer.toSPF(-100000000) == "-100000000.");
    TEST_ASSERT(writer.toSPF(-1e8) == "-100000000.");
    TEST_ASSERT(writer.toSPF(-1e15) == "-1000000000000000.");

    for(int i=0;i<NB_TEST;++i) {
        std::cerr << " input           = " << input[i] << std::endl <<
                     " expected_result = " << expected_result[i] << std::endl;
        std::string SPFResult = writer.toSPF(input[i]);

        std::cerr << " SPFResult       = " << SPFResult << std::endl;
        TEST_ASSERT(expected_result[i] == SPFResult);

        Step::Real result = Step::spfToReal(SPFResult);

        std::cerr << " result          = " << result << std::endl <<
                     " expected_result = " << input[i] << std::endl;
        TEST_ASSERT(input[i] == result);
        std::cerr << std::endl;
    }
}

void testTime()
{
    MySPFWriter writer;

    time_t start;
    time_t end;
    time(&start);

    int failures =0;

    for (double i=0; i < 5e11 ; i+=150000.57)
    {
        std::string SPFResult = writer.toSPF(i);
        Step::Real result = Step::spfToReal(SPFResult);
        if (i != result)
        {
            ++failures;
        }
    }
    time(&end);
    std::cerr << "testTime = " <<  difftime(end, start) << std::endl;

    TEST_ASSERT(failures==0)
}

int main (int , char **)
{
    test_Real();
    testTime();
    std::cerr << std::endl << "Failure : " << failure_results << " Success : " << success_results << std::endl;

    return failure_results;
}
<commit_msg>corrected WIN32 Spf exp output<commit_after>#include <Step/SPFFunctions.h>
#include <Step/BaseSPFWriter.h>
#include "../../tests.h"

#include <sstream>
#include <cassert>

#pragma execution_character_set("utf-8");

class MySPFWriter : public Step::BaseSPFWriter
{
public:

    MySPFWriter() : Step::BaseSPFWriter(0) {}

    virtual ~MySPFWriter() {}

    virtual bool write(std::ostream& ) { return true; }

    virtual std::string toSPF(Step::Real d)
    {
        std::ostringstream out;
        m_out = &out;
        writeAttribute(d);
        return out.str();
    }
};

/// testing Real Output

#define NB_TEST 12

double input[NB_TEST]={
    100000000,
    1e8,
    1e15,
    -100000000,
    -1e8,
    -1e15,
    1e-15,
    -1e-15,
    0,
    .5,
    1e30,
    1e98,
};

std::string expected_result[NB_TEST]={
    "100000000.",
    "100000000.",
    "1000000000000000.",
    "-100000000.",
    "-100000000.",
    "-1000000000000000.",
    "0.000000000000001",
    "-0.000000000000001",
    "0.",
    "0.5",
#ifdef WIN32
    "1.E+030",
    "1.E+098",
#else
    "1.E+30",
    "1.E+98",
#endif
};

void test_Real()
{
    std::cerr << "test_Real" << std::endl;

    MySPFWriter writer;

    TEST_ASSERT(writer.toSPF(100000000) == "100000000.");
    TEST_ASSERT(writer.toSPF(1e8) == "100000000.");
    TEST_ASSERT(writer.toSPF(1e15) == "1000000000000000.");
    TEST_ASSERT(writer.toSPF(-100000000) == "-100000000.");
    TEST_ASSERT(writer.toSPF(-1e8) == "-100000000.");
    TEST_ASSERT(writer.toSPF(-1e15) == "-1000000000000000.");

    for(int i=0;i<NB_TEST;++i) {
        std::cerr << " input           = " << input[i] << std::endl <<
                     " expected_result = " << expected_result[i] << std::endl;
        std::string SPFResult = writer.toSPF(input[i]);

        std::cerr << " SPFResult       = " << SPFResult << std::endl;
        TEST_ASSERT(expected_result[i] == SPFResult);

        Step::Real result = Step::spfToReal(SPFResult);

        std::cerr << " result          = " << result << std::endl <<
                     " expected_result = " << input[i] << std::endl;
        TEST_ASSERT(input[i] == result);
        std::cerr << std::endl;
    }
}

void testTime()
{
    MySPFWriter writer;

    time_t start;
    time_t end;
    time(&start);

    int failures =0;

    for (double i=0; i < 5e11 ; i+=150000.57)
    {
        std::string SPFResult = writer.toSPF(i);
        Step::Real result = Step::spfToReal(SPFResult);
        if (i != result)
        {
            ++failures;
        }
    }
    time(&end);
    std::cerr << "testTime = " <<  difftime(end, start) << std::endl;

    TEST_ASSERT(failures==0)
}

int main (int , char **)
{
    test_Real();
    testTime();
    std::cerr << std::endl << "Failure : " << failure_results << " Success : " << success_results << std::endl;

    return failure_results;
}
<|endoftext|>


<commit_before>#include "AnimSprLoader.h"

#include <sprite2/AnimSprite.h>
#include <sprite2/SprTreePath.h>
#include <simp/from_int.h>
#include <simp/NodeAnimationSpr.h>

namespace gum
{

AnimSprLoader::AnimSprLoader(s2::AnimSprite* spr)
	: m_spr(spr)
{
	if (m_spr) {
		m_spr->AddReference();
	}
}

AnimSprLoader::~AnimSprLoader()
{
	if (m_spr) {
		m_spr->RemoveReference();
	}
}

void AnimSprLoader::LoadJson(const Json::Value& val, const std::string& dir)
{
	if (!m_spr || !val.isMember("animation")) {
		return;
	}

	const Json::Value& anim_val = val["animation"];

	m_spr->SetLoop(anim_val["loop"].asBool());
	m_spr->SetInterval(anim_val["interval"].asDouble());

	m_spr->SetFPS(anim_val["fps"].asInt());

	m_spr->SetStartRandom(anim_val["start_random"].asBool(), NULL);

	if (anim_val.isMember("active")) {
		m_spr->SetActive(anim_val["active"].asBool(), NULL);
	}
}

void AnimSprLoader::LoadBin(const simp::NodeAnimationSpr* node)
{
	if (!m_spr) {
		return;
	}

	m_spr->SetLoop(simp::int2bool(node->loop));
	m_spr->SetInterval(simp::int2float(node->interval, 1024));

	m_spr->SetFPS(node->fps);
}

}<commit_msg>[CHANGED] up for s2<commit_after>#include "AnimSprLoader.h"

#include <sprite2/AnimSprite.h>
#include <sprite2/SprTreePath.h>
#include <sprite2/UpdateParams.h>
#include <simp/from_int.h>
#include <simp/NodeAnimationSpr.h>

namespace gum
{

AnimSprLoader::AnimSprLoader(s2::AnimSprite* spr)
	: m_spr(spr)
{
	if (m_spr) {
		m_spr->AddReference();
	}
}

AnimSprLoader::~AnimSprLoader()
{
	if (m_spr) {
		m_spr->RemoveReference();
	}
}

void AnimSprLoader::LoadJson(const Json::Value& val, const std::string& dir)
{
	if (!m_spr || !val.isMember("animation")) {
		return;
	}

	const Json::Value& anim_val = val["animation"];

	m_spr->SetLoop(anim_val["loop"].asBool());
	m_spr->SetInterval(anim_val["interval"].asDouble());

	m_spr->SetFPS(anim_val["fps"].asInt());

	m_spr->SetStartRandom(s2::UpdateParams(), anim_val["start_random"].asBool());

	if (anim_val.isMember("active")) {
		m_spr->SetActive(anim_val["active"].asBool(), NULL);
	}
}

void AnimSprLoader::LoadBin(const simp::NodeAnimationSpr* node)
{
	if (!m_spr) {
		return;
	}

	m_spr->SetLoop(simp::int2bool(node->loop));
	m_spr->SetInterval(simp::int2float(node->interval, 1024));

	m_spr->SetFPS(node->fps);
}

}<|endoftext|>


<commit_before>#include <Windows.h>
#include <stdio.h>
#include <detourxs.h>

#include "overlay.h"
#include <OvRender.h>
#include "render.h"
#include "thread.h"
#include "menu.h"
#include "kbhook.h"

CHAR *pszModuleName;
PUSH_SHARED_MEMORY   *PushSharedMemory;
void* PushImageEvent;
BOOLEAN dxgiHooked              = FALSE;
BOOLEAN g_DXGI                  = FALSE;
ThreadMonitor* PushThreadMonitor;
HANDLE PushProcessHeap;
CRITICAL_SECTION OvCriticalSection;
extern HANDLE RenderThreadHandle;

VOID Log(const wchar_t* Format, ...)
{
    wchar_t buffer[260];
    wchar_t output[260] = L"[OVRENDER] ";
    va_list _Arglist;

    _crt_va_start(_Arglist, Format);
    _vswprintf_c_l(buffer, 260, Format, NULL, _Arglist);
    _crt_va_end(_Arglist);

    wcsncat(output, buffer, 260);
    OutputDebugStringW(output);
}

VOID
PushRefreshThreadMonitor()
{
    if (PushThreadMonitor == NULL)
        PushThreadMonitor = new ThreadMonitor();

    PushThreadMonitor->Refresh();
}

UINT8
PushGetMaxThreadUsage()
{
    return PushThreadMonitor->GetMaxThreadUsage();
}

VOID CreateOverlay()
{
    Log(L"CreateOverlay()");
    OV_HOOK_PARAMS hookParams = { 0 };

    hookParams.RenderFunction = RnRender;

    if (PushSharedMemory->VsyncOverrideMode == PUSH_VSYNC_FORCE_ON)
    {
        Log(L"VSYNC_FORCE_ON");
        hookParams.VsyncOverrideMode = VSYNC_FORCE_ON;
    }

    else if (PushSharedMemory->VsyncOverrideMode == PUSH_VSYNC_FORCE_OFF)
        hookParams.VsyncOverrideMode = VSYNC_FORCE_OFF;
    else
    {
        Log(L"VSYNC_FORCE_UNC");
    }

    OvCreateOverlayEx(&hookParams);
}

extern HHOOK KeyboardHookHandle;

ULONG __stdcall MonitorThread( LPVOID Params )
{
    while (!RenderThreadHandle)
    {
        Sleep(500);
    }

    Log(L"RenderThreadId %i", GetThreadId(RenderThreadHandle));

    if (PushSharedMemory->KeyboardHookType == KEYBOARD_HOOK_AUTO)
    {
        Keyboard_Hook(KEYBOARD_HOOK_MESSAGE);

        if (GetModuleHandleW(L"dinput8.dll"))
        {
            Keyboard_Hook(KEYBOARD_HOOK_RAW);
        }
    }
    else
    {
        Keyboard_Hook(PushSharedMemory->KeyboardHookType);
    }

    return NULL;
}

ULONG __stdcall ImageMonitorThread(LPVOID Params)
{
    while (PushImageEvent)
    {
        WaitForSingleObject(PushImageEvent, INFINITE);

        Log(L"new image event!");
        CreateOverlay();
    }

    return NULL;
}

VOID* DetourApi( WCHAR* dllName, CHAR* apiName, BYTE* NewFunction )
{
    BYTE *functionStart = NULL;
    HMODULE moduleHandle;
    DWORD address = 0;
    DetourXS *detour;

    // Get the API address
    moduleHandle = GetModuleHandleW(dllName);
    address = (DWORD)GetProcAddress(moduleHandle, apiName);

    if (!address || !NewFunction)
        return NULL;

    functionStart = (BYTE*)address;
    detour = new DetourXS(functionStart, NewFunction);

     return detour->GetTrampoline();
}

VOID CallPipe( WCHAR* Command, UINT16* Output )
{
    static HANDLE pipeHandle = INVALID_HANDLE_VALUE;
    DWORD dwWritten;

    if (pipeHandle == INVALID_HANDLE_VALUE)
    {
        pipeHandle = CreateFile(TEXT("\\\\.\\pipe\\Push"),
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            OPEN_EXISTING,
            0,
            NULL);
    }

    if (pipeHandle != INVALID_HANDLE_VALUE)
    {
        DWORD bytesRead;

        WriteFile(
            pipeHandle,
            Command,
            (wcslen(Command) + 1) * sizeof(WCHAR),
            &dwWritten,
            NULL
            );

        if (Output)
        {
            //DebugBreak();
            ReadFile(pipeHandle, Output, 2, &bytesRead, NULL);
        }

        //CloseHandle(pipeHandle);
    }
    else
    {
        Log(L"CallPipe failed!");
    }
}

VOID* OpenSection( WCHAR* SectionName, SIZE_T SectionSize )
{
    void *sectionHandle;

    sectionHandle = OpenFileMappingW(
        FILE_MAP_ALL_ACCESS,
        FALSE,
        SectionName
        );

    return MapViewOfFile(
        sectionHandle,
        FILE_MAP_ALL_ACCESS,
        NULL,
        NULL,
        SectionSize
        );
}

BOOL __stdcall DllMain(
    _In_ HINSTANCE Instance,
    _In_ ULONG fdwReason,
    _In_ LPVOID lpReserved
    )
{
    switch(fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        {

            DEVMODE devMode;

            PushSharedMemory = (PUSH_SHARED_MEMORY *)OpenSection(
                PUSH_SECTION_NAME,
                sizeof(PUSH_SHARED_MEMORY)
                );

            PushImageEvent = OpenEventW(
                SYNCHRONIZE,
                FALSE,
                L"Global\\"
                PUSH_IMAGE_EVENT_NAME
                );

            InitializeCriticalSection(&OvCriticalSection);
            CreateOverlay();

            CreateThread(0, 0, &MonitorThread, 0, 0, 0);
            CreateThread(0, 0, &ImageMonitorThread, 0, 0, 0);

            EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);

            PushRefreshRate = devMode.dmDisplayFrequency;
            AcceptableFps = PushRefreshRate - 5;
            PushProcessHeap = GetProcessHeap();

        } break;

    case DLL_PROCESS_DETACH:
        {

        } break;
    }

    return TRUE;
}
<commit_msg>fix keyboard hook<commit_after>#include <Windows.h>
#include <stdio.h>
#include <detourxs.h>

#include "overlay.h"
#include <OvRender.h>
#include "render.h"
#include "thread.h"
#include "menu.h"
#include "kbhook.h"

CHAR *pszModuleName;
PUSH_SHARED_MEMORY   *PushSharedMemory;
void* PushImageEvent;
BOOLEAN dxgiHooked              = FALSE;
BOOLEAN g_DXGI                  = FALSE;
ThreadMonitor* PushThreadMonitor;
HANDLE PushProcessHeap;
CRITICAL_SECTION OvCriticalSection;
extern HANDLE RenderThreadHandle;

VOID Log(const wchar_t* Format, ...)
{
    wchar_t buffer[260];
    wchar_t output[260] = L"[OVRENDER] ";
    va_list _Arglist;

    _crt_va_start(_Arglist, Format);
    _vswprintf_c_l(buffer, 260, Format, NULL, _Arglist);
    _crt_va_end(_Arglist);

    wcsncat(output, buffer, 260);
    OutputDebugStringW(output);
}

VOID
PushRefreshThreadMonitor()
{
    if (PushThreadMonitor == NULL)
        PushThreadMonitor = new ThreadMonitor();

    PushThreadMonitor->Refresh();
}

UINT8
PushGetMaxThreadUsage()
{
    return PushThreadMonitor->GetMaxThreadUsage();
}

VOID CreateOverlay()
{
    Log(L"CreateOverlay()");
    OV_HOOK_PARAMS hookParams = { 0 };

    hookParams.RenderFunction = RnRender;

    if (PushSharedMemory->VsyncOverrideMode == PUSH_VSYNC_FORCE_ON)
    {
        Log(L"VSYNC_FORCE_ON");
        hookParams.VsyncOverrideMode = VSYNC_FORCE_ON;
    }

    else if (PushSharedMemory->VsyncOverrideMode == PUSH_VSYNC_FORCE_OFF)
        hookParams.VsyncOverrideMode = VSYNC_FORCE_OFF;
    else
    {
        Log(L"VSYNC_FORCE_UNC");
    }

    OvCreateOverlayEx(&hookParams);
}

extern HHOOK KeyboardHookHandle;

ULONG __stdcall MonitorThread( LPVOID Params )
{
    while (!RenderThreadHandle)
    {
        Sleep(500);
    }

    Log(L"RenderThreadId %i", GetThreadId(RenderThreadHandle));

    if (PushSharedMemory->KeyboardHookType == KEYBOARD_HOOK_AUTO)
    {
        Keyboard_Hook(KEYBOARD_HOOK_MESSAGE);

        if (GetModuleHandleW(L"dinput8.dll"))
        {
            Keyboard_Hook(KEYBOARD_HOOK_RAW);
        }
    }
    else
    {
        Keyboard_Hook(PushSharedMemory->KeyboardHookType);
    }

    // Thread can't end or keyboard hook won't work.
    Sleep(INFINITE);

    return NULL;
}

ULONG __stdcall ImageMonitorThread(LPVOID Params)
{
    while (PushImageEvent)
    {
        WaitForSingleObject(PushImageEvent, INFINITE);

        Log(L"new image event!");
        CreateOverlay();
    }

    return NULL;
}

VOID* DetourApi( WCHAR* dllName, CHAR* apiName, BYTE* NewFunction )
{
    BYTE *functionStart = NULL;
    HMODULE moduleHandle;
    DWORD address = 0;
    DetourXS *detour;

    // Get the API address
    moduleHandle = GetModuleHandleW(dllName);
    address = (DWORD)GetProcAddress(moduleHandle, apiName);

    if (!address || !NewFunction)
        return NULL;

    functionStart = (BYTE*)address;
    detour = new DetourXS(functionStart, NewFunction);

     return detour->GetTrampoline();
}

VOID CallPipe( WCHAR* Command, UINT16* Output )
{
    static HANDLE pipeHandle = INVALID_HANDLE_VALUE;
    DWORD dwWritten;

    if (pipeHandle == INVALID_HANDLE_VALUE)
    {
        pipeHandle = CreateFile(TEXT("\\\\.\\pipe\\Push"),
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            OPEN_EXISTING,
            0,
            NULL);
    }

    if (pipeHandle != INVALID_HANDLE_VALUE)
    {
        DWORD bytesRead;

        WriteFile(
            pipeHandle,
            Command,
            (wcslen(Command) + 1) * sizeof(WCHAR),
            &dwWritten,
            NULL
            );

        if (Output)
        {
            //DebugBreak();
            ReadFile(pipeHandle, Output, 2, &bytesRead, NULL);
        }

        //CloseHandle(pipeHandle);
    }
    else
    {
        Log(L"CallPipe failed!");
    }
}

VOID* OpenSection( WCHAR* SectionName, SIZE_T SectionSize )
{
    void *sectionHandle;

    sectionHandle = OpenFileMappingW(
        FILE_MAP_ALL_ACCESS,
        FALSE,
        SectionName
        );

    return MapViewOfFile(
        sectionHandle,
        FILE_MAP_ALL_ACCESS,
        NULL,
        NULL,
        SectionSize
        );
}

BOOL __stdcall DllMain(
    _In_ HINSTANCE Instance,
    _In_ ULONG fdwReason,
    _In_ LPVOID lpReserved
    )
{
    switch(fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        {

            DEVMODE devMode;

            PushSharedMemory = (PUSH_SHARED_MEMORY *)OpenSection(
                PUSH_SECTION_NAME,
                sizeof(PUSH_SHARED_MEMORY)
                );

            PushImageEvent = OpenEventW(
                SYNCHRONIZE,
                FALSE,
                L"Global\\"
                PUSH_IMAGE_EVENT_NAME
                );

            InitializeCriticalSection(&OvCriticalSection);
            CreateOverlay();

            CreateThread(0, 0, &MonitorThread, 0, 0, 0);
            CreateThread(0, 0, &ImageMonitorThread, 0, 0, 0);

            EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);

            PushRefreshRate = devMode.dmDisplayFrequency;
            AcceptableFps = PushRefreshRate - 5;
            PushProcessHeap = GetProcessHeap();

        } break;

    case DLL_PROCESS_DETACH:
        {

        } break;
    }

    return TRUE;
}
<|endoftext|>


<commit_before>/*
Copyright c1997-2011 Trygve Isaacson. All rights reserved.
This file is part of the Code Vault version 3.3
http://www.bombaydigital.com/
*/

/** @file */

#include "vsocket.h"
#include "vtypes_internal.h"

#include "vexception.h"

#ifdef VCOMPILER_MSVC
    #pragma warning(disable: 6386)  // the library file doesn't past muster
#endif
#include <ws2tcpip.h> // For the WSA calls in enumerateNetworkInterfaces()
#ifdef VCOMPILER_MSVC
    #pragma warning(default: 6386)
#endif

V_STATIC_INIT_TRACE

// This is to force our staticInit to be called at startup.
bool VSocket::gStaticInited = VSocket::staticInit();

bool VSocket::staticInit() {
    bool    success = true;
    WORD    versionRequested;
    WSADATA wsaData;
    int     err;

    versionRequested = MAKEWORD(2, 0);

    err = ::WSAStartup(versionRequested, &wsaData);

    success = (err == 0);

    assert(success);

    return success;
}

VNetworkInterfaceList VSocketBase::enumerateNetworkInterfaces() {
    VNetworkInterfaceList interfaces;

    SOCKET sock = ::WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
    if (sock == SOCKET_ERROR) {
        throw VException(VSTRING_FORMAT("VSocketBase::enumerateNetworkInterfaces: WSASocket failed with error code %d.", ::WSAGetLastError()));
    }

    INTERFACE_INFO interfaceInfo[20];
    unsigned long numBytesReturned;
    int result = ::WSAIoctl(sock, SIO_GET_INTERFACE_LIST, 0, 0, &interfaceInfo, sizeof(interfaceInfo), &numBytesReturned, 0, 0);
    if (result == SOCKET_ERROR) {
        throw VException(VSTRING_FORMAT("VSocketBase::enumerateNetworkInterfaces: WSAIoctl failed with error code %d.", ::WSAGetLastError()));
    }

    int numInterfaces = numBytesReturned / sizeof(INTERFACE_INFO);
    for (int i = 0; i < numInterfaces; ++i) {
        // Filter out 127.x.x.x (loopback addresses).
        VString address(::inet_ntoa(((sockaddr_in*) &(interfaceInfo[i].iiAddress))->sin_addr));
        if (! address.startsWith("127.")) {
            VNetworkInterfaceInfo info;
            info.mAddress = address;
            interfaces.push_back(info);
        }
    }

    return interfaces;
}

VSocket::VSocket(VSocketID id)
    : VSocketBase(id)
    {
}

VSocket::VSocket(const VString& hostName, int portNumber)
    : VSocketBase(hostName, portNumber)
    {
}

VSocket::~VSocket() {
    // Note: base class destructor does a close() of the socket if it is open.
}

void VSocket::_connect() {
    int                 length;
    struct sockaddr_in  address;
    VSocketID           socketID;

    ::memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_port = (u_short) V_BYTESWAP_HTON_S16_GET(static_cast<Vs16>(mPortNumber));
    address.sin_addr.s_addr = ::inet_addr(mHostName);
    length = sizeof(struct sockaddr_in);

    socketID = ::socket(AF_INET, SOCK_STREAM, 0);

    if (socketID != kNoSocketID) {
        if (::connect(socketID, (const sockaddr*) &address, length) != 0) {
            // failure
            ::closesocket(socketID);
            throw VException(VSTRING_FORMAT("VSocket::connect was unable to connect to %s:%d -- socket %d, errno=%s", mHostName.chars(), mPortNumber, socketID, ::strerror(errno)));
        }
    }

    mSocketID = socketID;
}

void VSocket::_listen(const VString& bindAddress, int backlog) {
    VSocketID           listenSockID = kNoSocketID;
    struct sockaddr_in  info;
    int                 infoLength = sizeof(info);
    const int           on = 1;
    int                 result;

    ::memset(&info, 0, sizeof(info));
    info.sin_family = AF_INET;
    info.sin_port = (u_short) V_BYTESWAP_HTON_S16_GET(static_cast<Vs16>(mPortNumber));

    if (bindAddress.isEmpty()) {
        info.sin_addr.s_addr = INADDR_ANY;
    } else {
        info.sin_addr.s_addr = inet_addr(bindAddress);
    }

    listenSockID = ::socket(AF_INET, SOCK_STREAM, 0);
    if (listenSockID <= 0) {
        throw VException(VSTRING_FORMAT("VSocket::listen socket() failed with id %d, errno=%d", listenSockID, ::WSAGetLastError()));
    }

    result = ::setsockopt(listenSockID, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof(on));
    if (result != 0) {
        throw VException(VSTRING_FORMAT("VSocket::listen setsockopt() failed -- socket id %d, result %d, errno=%d", listenSockID, result, ::WSAGetLastError()));
    }

    result = ::bind(listenSockID, (const sockaddr*) &info, infoLength);
    if (result != 0) {
        // Bind failed.
        ::closesocket(listenSockID);
        throw VException(VSTRING_FORMAT("VSocket::listen bind() for port %d failed -- socket id %d, errno=%d", mPortNumber, listenSockID, ::WSAGetLastError()));
    }

    result = ::listen(listenSockID, backlog);
    if (result != 0) {
        throw VException(VSTRING_FORMAT("VSocket::listen listen() for port %d failed -- socket id %d, result %d, errno=%d", mPortNumber, listenSockID, result, ::WSAGetLastError()));
    }

    mSocketID = listenSockID;
}

int VSocket::available() {
    u_long numBytesAvailable = 0;

    int result = ::ioctlsocket(mSocketID, FIONREAD, &numBytesAvailable);

    if (result != 0) {
        throw VException(::WSAGetLastError(), VSTRING_FORMAT("VSocket::available failed on socket %d, result=%d, error=%s.", mSocketID, result, ::strerror(errno)));
    }

    if (numBytesAvailable == 0) {
        //set the socket to be non blocking.
        u_long argp = 1;
        ::ioctlsocket(mSocketID, FIONBIO, &argp);

        //See if there is any data in the buffer.
        char recvBuffer[4]; // It's unclear if NULL buffer parameter is runtime safe, even with 0 length parameter. Provide valid buffer pointer to be sure.
        result = ::recv(mSocketID, recvBuffer, 0 , MSG_PEEK);
        int theSocketError = ::WSAGetLastError();

        //restore the blocking
        argp = 1;
        ::ioctlsocket(mSocketID, FIONBIO, &argp);

        switch (result) {
            case 0:
                throw VEOFException("VSocket::available: Peer closed connection gracefully.");
                break;
            case SOCKET_ERROR:
                if (theSocketError == WSAECONNRESET)
                    throw VEOFException("VSocket::available: WSAECONNRESET: socket is no longer available.");
                else
                    throw VException(theSocketError, VSTRING_FORMAT("VSocket::available failed on socket %d, result=%d, error=%d.", mSocketID, result, theSocketError));
                break;
            default:
                numBytesAvailable = result;
                break;
        }
    }

    return (int) numBytesAvailable;
}

int VSocket::read(Vu8* buffer, int numBytesToRead) {
    if (mSocketID == kNoSocketID) {
        throw VException(VSTRING_FORMAT("VSocket::read with invalid mSocketID %d", mSocketID));
    }

    int     bytesRemainingToRead = numBytesToRead;
    Vu8*    nextBufferPositionPtr = buffer;
    int     result;
    int     numBytesRead = 0;
    fd_set  readset;

    while (bytesRemainingToRead > 0) {
        if (mSocketID <= FD_SETSIZE) { // FD_SETSIZE is max num open sockets, sockid over that is sign of a big problem
            FD_ZERO(&readset);
            FD_SET(mSocketID, &readset);
            result = ::select((int)(mSocketID + 1), &readset, NULL, NULL, (mReadTimeOutActive ? &mReadTimeOut : NULL));

            if (result < 0) {
                if (errno == EINTR) {
                    // Debug message: read was interrupted but we will cycle around and try again...
                    continue;
                }

                throw VException(VSTRING_FORMAT("VSocket::read select failed on socket %d, result=%d, error=%s.", mSocketID, result, ::strerror(errno)));
            } else if (result == 0) {
                throw VException(VSTRING_FORMAT("VSocket::read select timed out on socket %d.", mSocketID));
            }

            if (!FD_ISSET(mSocketID, &readset)) {
                throw VException(VSTRING_FORMAT("VSocket::read select got FD_ISSET false on socket %d, errno=%s.", mSocketID, ::strerror(errno)));
            }

        }

        numBytesRead = ::recv(mSocketID, (char*) nextBufferPositionPtr, bytesRemainingToRead, 0);

        if (numBytesRead < 0) {
            throw VException(VSTRING_FORMAT("VSocket::read recv failed on socket %d, result=%d, errno=%s.", mSocketID, numBytesRead, ::strerror(errno)));
        } else if (numBytesRead == 0) {
            if (mRequireReadAll) {
                throw VEOFException(VSTRING_FORMAT("VSocket::read: reached EOF unexpectedly on socket %d, recv of length %d returned 0, errno=%s.", mSocketID, bytesRemainingToRead, ::strerror(errno)));
            } else {
                break;    // got successful but partial read, caller will have to keep reading
            }
        }

        bytesRemainingToRead -= numBytesRead;
        nextBufferPositionPtr += numBytesRead;

        mNumBytesRead += numBytesRead;
    }

    mLastEventTime.setNow();

    return (numBytesToRead - bytesRemainingToRead);
}

int VSocket::write(const Vu8* buffer, int numBytesToWrite) {
    if (mSocketID == kNoSocketID) {
        throw VException(VSTRING_FORMAT("VSocket::write with invalid mSocketID %d", mSocketID));
    }

    const Vu8*  nextBufferPositionPtr = buffer;
    int         bytesRemainingToWrite = numBytesToWrite;
    int         numBytesWritten;
    int         result;
    fd_set      writeset;

    while (bytesRemainingToWrite > 0) {
        if (mSocketID <= FD_SETSIZE) { // FD_SETSIZE is max num open sockets, sockid over that is sign of a big problem
            FD_ZERO(&writeset);
            FD_SET(mSocketID, &writeset);
            result = ::select((int)(mSocketID + 1), NULL, &writeset, NULL, (mWriteTimeOutActive ? &mWriteTimeOut : NULL));

            if (result < 0) {
                if (errno == EINTR) {
                    // Debug message: write was interrupted but we will cycle around and try again...
                    continue;
                }

                throw VException(::WSAGetLastError(), VSTRING_FORMAT("VSocket::write select failed on socket %d, result=%d, errno=%d.", mSocketID, result, ::WSAGetLastError() ));
            } else if (result == 0) {
                throw VException(VSTRING_FORMAT("VSocket::write select timed out on socket %d", mSocketID));
            }

        }

        numBytesWritten = ::send(mSocketID, (const char*) nextBufferPositionPtr, bytesRemainingToWrite, 0);

        if (numBytesWritten <= 0) {
            throw VException(::WSAGetLastError(), VSTRING_FORMAT("VSocket::write send failed on socket %d, errno=%d.", mSocketID, ::WSAGetLastError()));
        } else if (numBytesWritten != bytesRemainingToWrite) {
            // Debug message: write was only partially completed so we will cycle around and write the rest...
        } else {
            // This is where you could put debug/trace-mode socket write logging output....
        }

        bytesRemainingToWrite -= numBytesWritten;
        nextBufferPositionPtr += numBytesWritten;

        mNumBytesWritten += numBytesWritten;
    }

    return (numBytesToWrite - bytesRemainingToWrite);
}

void VSocket::discoverHostAndPort() {
    VSocklenT           namelen = sizeof(struct sockaddr_in);
    struct sockaddr_in  info;

    ::getpeername(mSocketID, (struct sockaddr*) &info, &namelen);

    int portNumber = (int) V_BYTESWAP_NTOH_S16_GET(static_cast<Vs16>(info.sin_port));
    const char* name = ::inet_ntoa(info.sin_addr);

    this->setHostAndPort(VSTRING_COPY(name), portNumber);
}

void VSocket::closeRead() {
    int result = ::shutdown(mSocketID, SHUT_RD);

    if (result < 0) {
        throw VException(VSTRING_FORMAT("VSocket::closeRead unable to shut down socket %d.", mSocketID));
    }
}

void VSocket::closeWrite() {
    int result = ::shutdown(mSocketID, SHUT_WR);

    if (result < 0) {
        throw VException(VSTRING_FORMAT("VSocket::closeWrite unable to shut down socket %d.", mSocketID));
    }
}

void VSocket::setSockOpt(int level, int name, void* valuePtr, int valueLength) {
    ::setsockopt(mSocketID, level, name, (char*) valuePtr, valueLength);
}

<commit_msg>VAULT-0023 [trygve] Fix Winsock timeout issue for sockids greater than 64.<commit_after>/*
Copyright c1997-2011 Trygve Isaacson. All rights reserved.
This file is part of the Code Vault version 3.3
http://www.bombaydigital.com/
*/

/** @file */

#include "vsocket.h"
#include "vtypes_internal.h"

#include "vexception.h"

#ifdef VCOMPILER_MSVC
    #pragma warning(disable: 6386)  // the library file doesn't past muster
#endif
#include <ws2tcpip.h> // For the WSA calls in enumerateNetworkInterfaces()
#ifdef VCOMPILER_MSVC
    #pragma warning(default: 6386)
#endif

V_STATIC_INIT_TRACE

// This is to force our staticInit to be called at startup.
bool VSocket::gStaticInited = VSocket::staticInit();

bool VSocket::staticInit() {
    bool    success = true;
    WORD    versionRequested;
    WSADATA wsaData;
    int     err;

    versionRequested = MAKEWORD(2, 0);

    err = ::WSAStartup(versionRequested, &wsaData);

    success = (err == 0);

    assert(success);

    return success;
}

VNetworkInterfaceList VSocketBase::enumerateNetworkInterfaces() {
    VNetworkInterfaceList interfaces;

    SOCKET sock = ::WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
    if (sock == SOCKET_ERROR) {
        throw VException(VSTRING_FORMAT("VSocketBase::enumerateNetworkInterfaces: WSASocket failed with error code %d.", ::WSAGetLastError()));
    }

    INTERFACE_INFO interfaceInfo[20];
    unsigned long numBytesReturned;
    int result = ::WSAIoctl(sock, SIO_GET_INTERFACE_LIST, 0, 0, &interfaceInfo, sizeof(interfaceInfo), &numBytesReturned, 0, 0);
    if (result == SOCKET_ERROR) {
        throw VException(VSTRING_FORMAT("VSocketBase::enumerateNetworkInterfaces: WSAIoctl failed with error code %d.", ::WSAGetLastError()));
    }

    int numInterfaces = numBytesReturned / sizeof(INTERFACE_INFO);
    for (int i = 0; i < numInterfaces; ++i) {
        // Filter out 127.x.x.x (loopback addresses).
        VString address(::inet_ntoa(((sockaddr_in*) &(interfaceInfo[i].iiAddress))->sin_addr));
        if (! address.startsWith("127.")) {
            VNetworkInterfaceInfo info;
            info.mAddress = address;
            interfaces.push_back(info);
        }
    }

    return interfaces;
}

VSocket::VSocket(VSocketID id)
    : VSocketBase(id)
    {
}

VSocket::VSocket(const VString& hostName, int portNumber)
    : VSocketBase(hostName, portNumber)
    {
}

VSocket::~VSocket() {
    // Note: base class destructor does a close() of the socket if it is open.
}

void VSocket::_connect() {
    int                 length;
    struct sockaddr_in  address;
    VSocketID           socketID;

    ::memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_port = (u_short) V_BYTESWAP_HTON_S16_GET(static_cast<Vs16>(mPortNumber));
    address.sin_addr.s_addr = ::inet_addr(mHostName);
    length = sizeof(struct sockaddr_in);

    socketID = ::socket(AF_INET, SOCK_STREAM, 0);

    if (socketID != kNoSocketID) {
        if (::connect(socketID, (const sockaddr*) &address, length) != 0) {
            // failure
            ::closesocket(socketID);
            throw VException(VSTRING_FORMAT("VSocket::connect was unable to connect to %s:%d -- socket %d, errno=%s", mHostName.chars(), mPortNumber, socketID, ::strerror(errno)));
        }
    }

    mSocketID = socketID;
}

void VSocket::_listen(const VString& bindAddress, int backlog) {
    VSocketID           listenSockID = kNoSocketID;
    struct sockaddr_in  info;
    int                 infoLength = sizeof(info);
    const int           on = 1;
    int                 result;

    ::memset(&info, 0, sizeof(info));
    info.sin_family = AF_INET;
    info.sin_port = (u_short) V_BYTESWAP_HTON_S16_GET(static_cast<Vs16>(mPortNumber));

    if (bindAddress.isEmpty()) {
        info.sin_addr.s_addr = INADDR_ANY;
    } else {
        info.sin_addr.s_addr = inet_addr(bindAddress);
    }

    listenSockID = ::socket(AF_INET, SOCK_STREAM, 0);
    if (listenSockID <= 0) {
        throw VException(VSTRING_FORMAT("VSocket::listen socket() failed with id %d, errno=%d", listenSockID, ::WSAGetLastError()));
    }

    result = ::setsockopt(listenSockID, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof(on));
    if (result != 0) {
        throw VException(VSTRING_FORMAT("VSocket::listen setsockopt() failed -- socket id %d, result %d, errno=%d", listenSockID, result, ::WSAGetLastError()));
    }

    result = ::bind(listenSockID, (const sockaddr*) &info, infoLength);
    if (result != 0) {
        // Bind failed.
        ::closesocket(listenSockID);
        throw VException(VSTRING_FORMAT("VSocket::listen bind() for port %d failed -- socket id %d, errno=%d", mPortNumber, listenSockID, ::WSAGetLastError()));
    }

    result = ::listen(listenSockID, backlog);
    if (result != 0) {
        throw VException(VSTRING_FORMAT("VSocket::listen listen() for port %d failed -- socket id %d, result %d, errno=%d", mPortNumber, listenSockID, result, ::WSAGetLastError()));
    }

    mSocketID = listenSockID;
}

int VSocket::available() {
    u_long numBytesAvailable = 0;

    int result = ::ioctlsocket(mSocketID, FIONREAD, &numBytesAvailable);

    if (result != 0) {
        throw VException(::WSAGetLastError(), VSTRING_FORMAT("VSocket::available failed on socket %d, result=%d, error=%s.", mSocketID, result, ::strerror(errno)));
    }

    if (numBytesAvailable == 0) {
        //set the socket to be non blocking.
        u_long argp = 1;
        ::ioctlsocket(mSocketID, FIONBIO, &argp);

        //See if there is any data in the buffer.
        char recvBuffer[4]; // It's unclear if NULL buffer parameter is runtime safe, even with 0 length parameter. Provide valid buffer pointer to be sure.
        result = ::recv(mSocketID, recvBuffer, 0 , MSG_PEEK);
        int theSocketError = ::WSAGetLastError();

        //restore the blocking
        argp = 1;
        ::ioctlsocket(mSocketID, FIONBIO, &argp);

        switch (result) {
            case 0:
                throw VEOFException("VSocket::available: Peer closed connection gracefully.");
                break;
            case SOCKET_ERROR:
                if (theSocketError == WSAECONNRESET)
                    throw VEOFException("VSocket::available: WSAECONNRESET: socket is no longer available.");
                else
                    throw VException(theSocketError, VSTRING_FORMAT("VSocket::available failed on socket %d, result=%d, error=%d.", mSocketID, result, theSocketError));
                break;
            default:
                numBytesAvailable = result;
                break;
        }
    }

    return (int) numBytesAvailable;
}

int VSocket::read(Vu8* buffer, int numBytesToRead) {
    if (mSocketID == kNoSocketID) {
        throw VException(VSTRING_FORMAT("VSocket::read with invalid mSocketID %d", mSocketID));
    }

    int     bytesRemainingToRead = numBytesToRead;
    Vu8*    nextBufferPositionPtr = buffer;
    int     result;
    int     numBytesRead = 0;
    fd_set  readset;

    while (bytesRemainingToRead > 0) {
        // Note that unlike on Unix, verifying mSocketID <= FD_SETSIZE here is inappropriate because
        // of different Winsock fd_set internals, ID range, and select() API behavior. mSocketID may well be
        // larger than FD_SETSIZE, and that is OK.

        FD_ZERO(&readset);
        FD_SET(mSocketID, &readset);
        result = ::select((int)(mSocketID + 1), &readset, NULL, NULL, (mReadTimeOutActive ? &mReadTimeOut : NULL));

        if (result < 0) {
            if (errno == EINTR) {
                // Debug message: read was interrupted but we will cycle around and try again...
                continue;
            }

            throw VException(VSTRING_FORMAT("VSocket::read select failed on socket %d, result=%d, error=%s.", mSocketID, result, ::strerror(errno)));
        } else if (result == 0) {
            throw VException(VSTRING_FORMAT("VSocket::read select timed out on socket %d.", mSocketID));
        }

        if (!FD_ISSET(mSocketID, &readset)) {
            throw VException(VSTRING_FORMAT("VSocket::read select got FD_ISSET false on socket %d, errno=%s.", mSocketID, ::strerror(errno)));
        }

        numBytesRead = ::recv(mSocketID, (char*) nextBufferPositionPtr, bytesRemainingToRead, 0);

        if (numBytesRead < 0) {
            throw VException(VSTRING_FORMAT("VSocket::read recv failed on socket %d, result=%d, errno=%s.", mSocketID, numBytesRead, ::strerror(errno)));
        } else if (numBytesRead == 0) {
            if (mRequireReadAll) {
                throw VEOFException(VSTRING_FORMAT("VSocket::read: reached EOF unexpectedly on socket %d, recv of length %d returned 0, errno=%s.", mSocketID, bytesRemainingToRead, ::strerror(errno)));
            } else {
                break;    // got successful but partial read, caller will have to keep reading
            }
        }

        bytesRemainingToRead -= numBytesRead;
        nextBufferPositionPtr += numBytesRead;

        mNumBytesRead += numBytesRead;
    }

    mLastEventTime.setNow();

    return (numBytesToRead - bytesRemainingToRead);
}

int VSocket::write(const Vu8* buffer, int numBytesToWrite) {
    if (mSocketID == kNoSocketID) {
        throw VException(VSTRING_FORMAT("VSocket::write with invalid mSocketID %d", mSocketID));
    }

    const Vu8*  nextBufferPositionPtr = buffer;
    int         bytesRemainingToWrite = numBytesToWrite;
    int         numBytesWritten;
    int         result;
    fd_set      writeset;

    while (bytesRemainingToWrite > 0) {
        // See comment at same location in read() above, regarding mSocketID and FD_SETSIZE.

        FD_ZERO(&writeset);
        FD_SET(mSocketID, &writeset);
        result = ::select((int)(mSocketID + 1), NULL, &writeset, NULL, (mWriteTimeOutActive ? &mWriteTimeOut : NULL));

        if (result < 0) {
            if (errno == EINTR) {
                // Debug message: write was interrupted but we will cycle around and try again...
                continue;
            }

            throw VException(::WSAGetLastError(), VSTRING_FORMAT("VSocket::write select failed on socket %d, result=%d, errno=%d.", mSocketID, result, ::WSAGetLastError() ));
        } else if (result == 0) {
            throw VException(VSTRING_FORMAT("VSocket::write select timed out on socket %d", mSocketID));
        }

        numBytesWritten = ::send(mSocketID, (const char*) nextBufferPositionPtr, bytesRemainingToWrite, 0);

        if (numBytesWritten <= 0) {
            throw VException(::WSAGetLastError(), VSTRING_FORMAT("VSocket::write send failed on socket %d, errno=%d.", mSocketID, ::WSAGetLastError()));
        } else if (numBytesWritten != bytesRemainingToWrite) {
            // Debug message: write was only partially completed so we will cycle around and write the rest...
        } else {
            // This is where you could put debug/trace-mode socket write logging output....
        }

        bytesRemainingToWrite -= numBytesWritten;
        nextBufferPositionPtr += numBytesWritten;

        mNumBytesWritten += numBytesWritten;
    }

    return (numBytesToWrite - bytesRemainingToWrite);
}

void VSocket::discoverHostAndPort() {
    VSocklenT           namelen = sizeof(struct sockaddr_in);
    struct sockaddr_in  info;

    ::getpeername(mSocketID, (struct sockaddr*) &info, &namelen);

    int portNumber = (int) V_BYTESWAP_NTOH_S16_GET(static_cast<Vs16>(info.sin_port));
    const char* name = ::inet_ntoa(info.sin_addr);

    this->setHostAndPort(VSTRING_COPY(name), portNumber);
}

void VSocket::closeRead() {
    int result = ::shutdown(mSocketID, SHUT_RD);

    if (result < 0) {
        throw VException(VSTRING_FORMAT("VSocket::closeRead unable to shut down socket %d.", mSocketID));
    }
}

void VSocket::closeWrite() {
    int result = ::shutdown(mSocketID, SHUT_WR);

    if (result < 0) {
        throw VException(VSTRING_FORMAT("VSocket::closeWrite unable to shut down socket %d.", mSocketID));
    }
}

void VSocket::setSockOpt(int level, int name, void* valuePtr, int valueLength) {
    ::setsockopt(mSocketID, level, name, (char*) valuePtr, valueLength);
}

<|endoftext|>