pax_global_header00006660000000000000000000000064145033015610014510gustar00rootroot0000000000000052 comment=e4723277ada16a9716b6185bc57da2035803391c xeus-zmq-1.1.1/000077500000000000000000000000001450330156100133015ustar00rootroot00000000000000xeus-zmq-1.1.1/.github/000077500000000000000000000000001450330156100146415ustar00rootroot00000000000000xeus-zmq-1.1.1/.github/workflows/000077500000000000000000000000001450330156100166765ustar00rootroot00000000000000xeus-zmq-1.1.1/.github/workflows/main.yml000066400000000000000000000072351450330156100203540ustar00rootroot00000000000000name: CI on: workflow_dispatch: push: branches: - main pull_request: branches: - main jobs: unix: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-20.04, ubuntu-22.04, macos-11, macos-12] xeus_static_dependencies: [0] xeus_build_shared_lib: [1] include: - os: ubuntu-20.04 xeus_static_dependencies: 1 xeus_build_shared_lib: 0 - os: ubuntu-22.04 xeus_static_dependencies: 1 xeus_build_shared_lib: 0 steps: - uses: actions/checkout@v2 - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 - name: install mamba uses: mamba-org/provision-with-micromamba@main with: environment-file: environment-dev.yml environment-name: xeus-zmq - name: install cxx compiler shell: bash -l {0} run: | $HOME/micromamba-bin/micromamba install cxx-compiler libuuid -c conda-forge -y - name: cmake configure shell: bash -l {0} run: | mkdir -p build cd build cmake .. \ -DXEUS_ZMQ_BUILD_TESTS=ON \ -DCMAKE_PREFIX_PATH=$CONDA_PREFIX \ -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX \ -DXEUS_STATIC_DEPENDENCIES=${{ matrix.xeus_static_dependencies }} \ -DXEUS_BUILD_SHARED_LIBS=${{ matrix.xeus_build_shared_lib }} - name: build shell: bash -l {0} run: | cd build make -j 2 # make -j ${{ steps.cpu-cores.outputs.count }} - name: Test xeus-zmq uses: nick-invision/retry@v2 with: timeout_minutes: 4 max_attempts: 4 shell: bash command: | cd build/test ctest --output-on-failure - name: install xeus-zmq shell: bash -l {0} run: | cd build make install win: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ windows-2019, windows-2022 ] steps: - uses: actions/checkout@v2 - name: install mamba uses: mamba-org/provision-with-micromamba@main with: environment-file: environment-dev.yml environment-name: xeus-zmq - name: micromamba shell hook shell: powershell run: | micromamba shell hook -s cmd.exe -p C:\Users\runneradmin\micromamba-root - name: Make build directory run: mkdir build - name: cmake configure shell: cmd run: | call C:\Users\runneradmin\micromamba-root\condabin\micromamba.bat activate xeus-zmq cmake .. ^ -G Ninja ^ -DCMAKE_BUILD_TYPE=Release ^ -DXEUS_ZMQ_BUILD_TESTS=ON ^ -DDEPENDENCY_SEARCH_PREFIX="%CONDA_PREFIX%\Library" ^ -DCMAKE_PREFIX_PATH="%CONDA_PREFIX%\Library" ^ -DCMAKE_INSTALL_PREFIX="%CONDA_PREFIX%" working-directory: build - name: build shell: cmd run: | call C:\Users\runneradmin\micromamba-root\condabin\micromamba.bat activate xeus-zmq set CL=/MP ninja install working-directory: build - name: ctest uses: nick-invision/retry@v2 with: timeout_minutes: 4 max_attempts: 4 shell: cmd command: | call C:\Users\runneradmin\micromamba-root\condabin\micromamba.bat activate xeus-zmq set PATH=%CONDA_PREFIX%;%CONDA_PREFIX%\\Scripts;%CONDA_PREFIX%\\Library;%CONDA_PREFIX%\\Library\\bin;%PATH% cd build ctest --output-on-failure xeus-zmq-1.1.1/.gitignore000066400000000000000000000004501450330156100152700ustar00rootroot00000000000000# Prerequisites *.d # Compiled Object files *.slo *.lo *.o *.obj # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Fortran module files *.mod *.smod # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app build/ test/__pycache__/ xeus-zmq-1.1.1/CMakeLists.txt000066400000000000000000000341211450330156100160420ustar00rootroot00000000000000############################################################################ # Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou # # Copyright (c) 2016, QuantStack # # # # Distributed under the terms of the BSD 3-Clause License. # # # # The full license is in the file LICENSE, distributed with this software. # ############################################################################ cmake_minimum_required(VERSION 3.8) project(xeus-zmq) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}") set(XEUS_ZMQ_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) set(XEUS_ZMQ_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) set(XEUS_ZMQ_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test) # Versionning # =========== # Project version file(STRINGS "${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xeus-zmq.hpp" xeus_zmq_version_defines REGEX "#define XEUS_ZMQ_VERSION_(MAJOR|MINOR|PATCH)") foreach(ver ${xeus_zmq_version_defines}) if(ver MATCHES "#define XEUS_ZMQ_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$") set(XEUS_ZMQ_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "") endif() endforeach() set(XEUS_ZMQ_VERSION ${XEUS_ZMQ_VERSION_MAJOR}.${XEUS_ZMQ_VERSION_MINOR}.${XEUS_ZMQ_VERSION_PATCH}) message(STATUS "xeus-zmq version: v${XEUS_ZMQ_VERSION}") # Binary version # See the following URL for explanations about the binary versionning # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info file(STRINGS "${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xeus-zmq.hpp" xeus_zmq_version_defines REGEX "#define XEUS_ZMQ_BINARY_(CURRENT|REVISION|AGE)") foreach(ver ${xeus_zmq_version_defines}) if(ver MATCHES "#define XEUS_ZMQ_BINARY_(CURRENT|REVISION|AGE) +([^ ]+)$") set(XEUS_ZMQ_BINARY_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "") endif() endforeach() set(XEUS_ZMQ_BINARY_VERSION ${XEUS_ZMQ_BINARY_CURRENT}.${XEUS_ZMQ_BINARY_REVISION}.${XEUS_ZMQ_BINARY_AGE}) message(STATUS "xeus-zmq binary version: v${XEUS_ZMQ_BINARY_VERSION}") # Build options # ============= # Compilation options option(XEUS_ZMQ_BUILD_SHARED_LIBS "Build xeus shared library." ON) option(XEUS_ZMQ_BUILD_STATIC_LIBS "Build xeus static library (default if BUILD_SHARED_LIBS is OFF)." ON) option(XEUS_ZMQ_STATIC_DEPENDENCIES "link statically with xeus dependencies" OFF) # Test options option(XEUS_ZMQ_BUILD_TESTS "xeus test suite" OFF) # Static build configuration # ========================== if (XEUS_ZMQ_STATIC_DEPENDENCIES) set(CPPZMQ_TARGET_NAME cppzmq-static) set(XEUS_TARGET_NAME xeus-static) set(OPENSSL_USE_STATIC_LIBS ON CACHE BOOL "Linking statically with OpenSSL") else() set(CPPZMQ_TARGET_NAME cppzmq) set(XEUS_TARGET_NAME xeus) set(OPENSSL_USE_STATIC_LIBS OFF CACHE BOOL "Not linking statically with OpenSSL") endif() # Print build configuration # ========================== message(STATUS "XEUS_ZMQ_BUILD_SHARED_LIBS: ${XEUS_ZMQ_BUILD_SHARED_LIBS}") message(STATUS "XEUS_ZMQ_BUILD_STATIC_LIBS: ${XEUS_ZMQ_BUILD_STATIC_LIBS}") message(STATUS "XEUS_ZMQ_STATIC_DEPENDENCIES: ${XEUS_ZMQ_STATIC_DEPENDENCIES}") message(STATUS "XEUS_ZMQ_BUILD_TESTS: ${XEUS_ZMQ_BUILD_TESTS}") # Dependencies # ============ set(xeus_REQUIRED_VERSION 3.1.1) set(nlohmann_json_REQUIRED_VERSION 3.2.0) set(cppzmq_REQUIRED_VERSION 4.8.1) set(zeromq_REQUIRED_VERSION 4.3.2) if (NOT TARGET xeus AND NOT TARGET xeus-static) find_package(xeus ${xeus_REQUIRED_VERSION} REQUIRED) endif () if (NOT TARGET nlohmann_json) find_package(nlohmann_json ${nlohmann_json_REQUIRED_VERSION} REQUIRED) endif () if (NOT TARGET cppzmq AND NOT TARGET cppzmq-static) find_package(cppzmq ${cppzmq_REQUIRED_VERSION} REQUIRED) endif () if (NOT TARGET libzmq AND NOT TARGET libzmq-static) if (WIN32) find_package(zeromq ${zeromq_REQUIRED_VERSION} REQUIRED) else () find_package(zeromq ${zeromq_REQUIRED_VERSION} QUIET) if (NOT ZeroMQ_FOUND) message(STATUS "CMake libzmq package not found, trying again with pkg-config") find_package(PkgConfig) pkg_check_modules(ZeroMQ libzmq>=${zeromq_REQUIRED_VERSION} REQUIRED) set(ZeroMQ_VERSION ${PC_LIBZMQ_VERSION}) find_library(ZeroMQ_LIBRARY NAMES libzmq.so libzmq.dylib libzmq.dll PATHS ${PC_LIBZMQ_LIBDIR} ${PC_LIBZMQ_LIBRARY_DIRS}) find_library(ZeroMQ_STATIC_LIBRARY NAMES libzmq-static.a libzmq.a libzmq.dll.a PATHS ${PC_LIBZMQ_LIBDIR} ${PC_LIBZMQ_LIBRARY_DIRS}) message(STATUS "STATIC_LIBRARY" {ZeroMQ_LIBRARY}) message(STATUS "STATIC_STATIC_LIBRARY" {ZeroMQ_STATIC_LIBRARY}) endif () endif () endif () find_package(OpenSSL REQUIRED) # Source files # ============ set(XEUS_ZMQ_HEADERS ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xauthentication.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xdebugger_base.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xeus-zmq.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xdap_tcp_client.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xserver_control_main.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xmiddleware.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xserver_shell_main.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xserver_zmq.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xserver_zmq_split.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xthread.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xzmq_context.hpp ${XEUS_ZMQ_INCLUDE_DIR}/xeus-zmq/xzmq_serializer.hpp ) set(XEUS_ZMQ_SOURCES ${XEUS_ZMQ_SOURCE_DIR}/xauthentication.cpp ${XEUS_ZMQ_SOURCE_DIR}/xcontrol.hpp ${XEUS_ZMQ_SOURCE_DIR}/xcontrol.cpp ${XEUS_ZMQ_SOURCE_DIR}/xdap_tcp_client.cpp ${XEUS_ZMQ_SOURCE_DIR}/xdebugger_base.cpp ${XEUS_ZMQ_SOURCE_DIR}/xheartbeat.cpp ${XEUS_ZMQ_SOURCE_DIR}/xheartbeat.hpp ${XEUS_ZMQ_SOURCE_DIR}/xmiddleware.cpp ${XEUS_ZMQ_SOURCE_DIR}/xpublisher.cpp ${XEUS_ZMQ_SOURCE_DIR}/xpublisher.hpp ${XEUS_ZMQ_SOURCE_DIR}/xserver_control_main.cpp ${XEUS_ZMQ_SOURCE_DIR}/xserver_shell_main.cpp ${XEUS_ZMQ_SOURCE_DIR}/xserver_zmq.cpp ${XEUS_ZMQ_SOURCE_DIR}/xserver_zmq_split.cpp ${XEUS_ZMQ_SOURCE_DIR}/xshell.hpp ${XEUS_ZMQ_SOURCE_DIR}/xshell.cpp ${XEUS_ZMQ_SOURCE_DIR}/xtrivial_messenger.hpp ${XEUS_ZMQ_SOURCE_DIR}/xtrivial_messenger.cpp ${XEUS_ZMQ_SOURCE_DIR}/xzmq_context.cpp ${XEUS_ZMQ_SOURCE_DIR}/xzmq_messenger.hpp ${XEUS_ZMQ_SOURCE_DIR}/xzmq_messenger.cpp ${XEUS_ZMQ_SOURCE_DIR}/xzmq_serializer.cpp ) # Targets and link # ================ include(CheckCXXCompilerFlag) string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) if (XEUS_ZMQ_STATIC_DEPENDENCIES AND NOT MSVC AND NOT APPLE) # Explicitly finds and links with libsodium.a # because it is not exported as a dependency by # the static build of libzmq. Remove this when # it is fixed upstream. set(sodium_USE_STATIC_LIBS ON) find_package(sodium REQUIRED) endif () macro(xeus_zmq_create_target target_name linkage output_name) string(TOUPPER "${linkage}" linkage_upper) if (NOT ${linkage_upper} MATCHES "^(SHARED|STATIC)$") message(FATAL_ERROR "Invalid library linkage: ${linkage}") endif () # Output # ====== add_library(${target_name} ${linkage_upper} ${XEUS_ZMQ_SOURCES} ${XEUS_ZMQ_HEADERS}) target_include_directories( ${target_name} PUBLIC $ $ ) target_link_libraries( ${target_name} PUBLIC ${CPPZMQ_TARGET_NAME} PUBLIC nlohmann_json::nlohmann_json PUBLIC OpenSSL::Crypto PUBLIC ${XEUS_TARGET_NAME} ) if (NOT MSVC) if (APPLE) target_link_libraries(${target_name} PUBLIC "-framework CoreFoundation") else () if (XEUS_ZMQ_STATIC_DEPENDENCIES) target_link_libraries(${target_name} PUBLIC ${sodium_LIBRARY_RELEASE}) endif () endif () endif () if (UNIX) # CMake does not compute the version number of so files as libtool # does on Linux. Strictly speaking, we should exclude FreeBSD and # Apple from this, but that would require having different version # numbers depending on the platform. We prefer to follow the # libtool pattern everywhere. math(EXPR XEUS_ZMQ_BINARY_COMPATIBLE "${XEUS_ZMQ_BINARY_CURRENT} - ${XEUS_ZMQ_BINARY_AGE}") set_target_properties( ${target_name} PROPERTIES PUBLIC_HEADER "${XEUS_ZMQ_HEADERS}" COMPILE_OPTIONS "-fvisibility=hidden" COMPILE_DEFINITIONS "XEUS_ZMQ_EXPORTS" PREFIX "" VERSION "${XEUS_ZMQ_BINARY_COMPATIBLE}.${XEUS_ZMQ_BINARY_REVISION}.${XEUS_ZMQ_BINARY_AGE}" SOVERSION ${XEUS_ZMQ_BINARY_COMPATIBLE} OUTPUT_NAME "lib${output_name}" ) else() set_target_properties( ${target_name} PROPERTIES PUBLIC_HEADER "${XEUS_ZMQ_HEADERS}" COMPILE_DEFINITIONS "XEUS_ZMQ_EXPORTS" PREFIX "" VERSION ${XEUS_ZMQ_BINARY_VERSION} SOVERSION ${XEUS_ZMQ_BINARY_CURRENT} OUTPUT_NAME "lib${output_name}" ) endif() # Compilation flags # ================= target_compile_features(${target_name} PRIVATE cxx_std_14) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") target_compile_options(${target_name} PUBLIC -Wunused-parameter -Wextra -Wreorder) message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") endif() if (${linkage_upper} STREQUAL "STATIC") target_compile_definitions(${target_name} PUBLIC XEUS_ZMQ_STATIC_LIB) endif () if (MSVC) target_compile_definitions(${target_name} PUBLIC -DNOMINMAX) target_compile_options(${target_name} PUBLIC /DGUID_WINDOWS /MP /bigobj) target_compile_options(${target_name} PUBLIC /wd4251 /wd4996) elseif (APPLE) target_compile_definitions(${target_name} PUBLIC -DGUID_CFUUID) else () target_compile_definitions(${target_name} PUBLIC -DGUID_LIBUUID) endif () if (XEUS_ZMQ_STATIC_DEPENDENCIES) if (CMAKE_DL_LIBS) target_link_libraries(${target_name} PRIVATE ${CMAKE_DL_LIBS}) endif () if (UNIX AND NOT APPLE) target_link_libraries(${target_name} PRIVATE util rt) endif () endif () endmacro() set(xeus_zmq_targets "") if (XEUS_ZMQ_BUILD_SHARED_LIBS) xeus_zmq_create_target(xeus-zmq SHARED xeus-zmq) if(CMAKE_TARGET_SYSTEM MATCHES "Linux" AND OPENSSL_USE_STATIC_LIBS) # Do not reexport OpenSSL symbols from xeus, for libraries # Prevents conflicts with other versions of OpenSSL # loaded in the same process namespace, which can cause # crashes if the versions are not compatible. set_target_properties(xeus-zmq PROPERTIES LINK_FLAGS "-Wl,--exclude-libs,libcrypto.a") endif() list(APPEND xeus_zmq_targets xeus-zmq) endif () if (XEUS_ZMQ_BUILD_STATIC_LIBS) # On Windows, a static library should use a different output name # to avoid the conflict with the import library of a shared one. if (CMAKE_HOST_WIN32) xeus_zmq_create_target(xeus-zmq-static STATIC xeus-zmq-static) else () xeus_zmq_create_target(xeus-zmq-static STATIC xeus-zmq) endif () list(APPEND xeus_zmq_targets xeus-zmq-static) endif () # Tests # ===== # We need to control from outside whether we enable testing or not. We cannot # rely on BUILD_TESTING since it doe snot exist until CTest is included. include(CTest) if(XEUS_ZMQ_BUILD_TESTS) set(BUILD_TESTING ON) message(STATUS "tests enabled") else () set(BUILD_TESTING OFF) message(STATUS "tests disabled") endif() if(BUILD_TESTING) add_subdirectory(test) endif() # Installation # ============ include(GNUInstallDirs) include(CMakePackageConfigHelpers) set(XEUS_ZMQ_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE STRING "install path for xeus-zmqConfig.cmake") install(TARGETS ${xeus_zmq_targets} EXPORT ${PROJECT_NAME}-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xeus-zmq) # Makes the project importable from the build directory export(EXPORT ${PROJECT_NAME}-targets FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake") # Configure 'xeusConfig.cmake' for a build tree set(XEUS_ZMQ_CONFIG_CODE "####### Expanded from \@XEUS_CONFIG_CODE\@ #######\n") set(XEUS_ZMQ_CONFIG_CODE "${XEUS_ZMQ_CONFIG_CODE}set(CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/cmake;\${CMAKE_MODULE_PATH}\")\n") set(XEUS_ZMQ_CONFIG_CODE "${XEUS_ZMQ_CONFIG_CODE}##################################################") configure_package_config_file(${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" INSTALL_DESTINATION ${PROJECT_BINARY_DIR}) # Configure 'xeusConfig.cmake' for an install tree set(XEUS_ZMQ_CONFIG_CODE "") configure_package_config_file(${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${PROJECT_NAME}Config.cmake" INSTALL_DESTINATION ${XEUS_ZMQ_CMAKECONFIG_INSTALL_DIR}) write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake VERSION ${XEUS_ZMQ_VERSION} COMPATIBILITY AnyNewerVersion) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${PROJECT_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake DESTINATION ${XEUS_ZMQ_CMAKECONFIG_INSTALL_DIR}) install(EXPORT ${PROJECT_NAME}-targets FILE ${PROJECT_NAME}Targets.cmake DESTINATION ${XEUS_ZMQ_CMAKECONFIG_INSTALL_DIR}) xeus-zmq-1.1.1/CONTRIBUTING.md000066400000000000000000000022211450330156100155270ustar00rootroot00000000000000# Contributing to Xeus Xeus is a subproject of Project Jupyter and subject to the [Jupyter governance](https://github.com/jupyter/governance) and [Code of conduct](https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md). ## General Guidelines For general documentation about contributing to Jupyter projects, see the [Project Jupyter Contributor Documentation](https://jupyter.readthedocs.io/en/latest/contributor/content-contributor.html). ## Community The Xeus team organizes public video meetings. The schedule for future meetings and minutes of past meetings can be found on our [team compass](https://jupyter-xeus.github.io/). ## Setting up a development environment First, you need to fork the project. Then setup your environment: ```bash # create a new conda environment conda create -f environment-dev.yml conda activate xeus-zmq # download Xeus from your GitHub fork git clone https://github.com//xeus-zmq.git ``` You may also want to install a C++ compiler, cmake, and pkg-config from conda if they are not available on your system. Pkg-config is required at build time for locating zeromq and OpenSSL. xeus-zmq-1.1.1/LICENSE000066400000000000000000000027601450330156100143130ustar00rootroot00000000000000BSD 3-Clause License Copyright (c) 2022, Jupyter Xeus All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. xeus-zmq-1.1.1/README.md000066400000000000000000000110301450330156100145530ustar00rootroot00000000000000# xeus-zmq [![GithubActions](https://github.com/jupyter-xeus/xeus-zmq/actions/workflows/main.yml/badge.svg)](https://github.com/jupyter-xeus/xeus-zmq/actions/workflows/main.yml) [![Join the Gitter Chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/QuantStack/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ZeroMQ-based middleware for xeus ## Introduction `xeus-zmq` provides various implementations of the [xserver](https://github.com/jupyter-xeus/xeus/blob/main/include/xeus/xserver.hpp) API from `xeus`, based on the [ZeroMQ library](https://zeromq.org/). These implementations all conform to the [Jupyter Kernel Protocol specification](https://jupyter-client.readthedocs.io/en/stable/messaging.html). ## Installation TODO ## Documentation The documentation can be found with that of xeus at http://xeus.readthedocs.io/ ## Usage `xeus-zmq` provides server building functions that can be passed to the kernel constructor: ```cpp #include #include #include "xeus/xkernel.hpp" #include "xeus/xkernel_configuration.hpp" #include "xeus-zmq/xzmq_context.hpp" #include "xeus-zmq/xserver_zmq.hpp" #include "xmock_interpreter.hpp" int main(int argc, char* argv[]) { std::string file_name = (argc == 1) ? "connection.json" : argv[2]; xeus::xconfiguration config = xeus::load_configuration(file_name); auto context = xeus::make_zmq_context(); using interpreter_ptr = std::unique_ptr; interpreter_ptr interpreter = interpreter_ptr(new my_custom_interpreter()); xeus::xkernel kernel(config, xeus::get_user_name(), std::move(context), std::move(interpreter), xeus::make_xserver_zmq); std::cout << "starting kernel" << std::endl; kernel.start(); return 0; } ``` See the [documentation](http://xeus.readthedocs.io/) for an exhaustive list of the available functions. ### Building from sources `xeus-zmq` depends on the following libraries: [xeus](https://github.com/jupyter-xeus/xeus), [`ZeroMQ`](https://github.com/zeromq/libzmq), [`cppzmq`](https://github.com/zeromq/cppzmq), [`OpenSSL`](https://github.com/openssl/openssl), and [`nlohmann_json`](https://github.com/nlohmann/json). | xeus-zmq | xeus | ZeroMQ | cppzmq | nlohmann json | OpenSSL | xtl | |----------|---------|---------|---------|---------------|---------|----------------| | master | ^3.1.1 | ^4.2.5 | ^4.8.1 | ^3.2.0 | ^3.0 | >=0.7.0,<0.8.0 | | 1.x | ^3.0.0 | ^4.2.5 | ^4.8.1 | ^3.2.0 | ^3.0 | >=0.7.0,<0.8.0 | We have packaged all these dependencies on conda-forge. The simplest way to install them is to run: ```bash mamba install cmake pkg-config zeromq cppzmq OpenSSL nlohmann_json xtl xeus -c conda-forge ``` Once you have installed the dependencies, you can build and install `xeus-zmq`: ```bash cmake -D CMAKE_BUILD_TYPE=Release make make install ``` ## Installing the Dependencies from Source The dependencies can also be installed from source. Simply clone the directories and run the following cmake (cmake >= 3.8) and make instructions. ### xeus [xeus](https://github.com/jupyter-xeus/xeus) is the core implementation of the Jupyter kernel protocol. ```bash cmake -D CMAKE_BUILD_TYPE=Rlease make make install ``` ### ZeroMQ [ZeroMQ](https://github.com/zeromq/libzmq) is the messaging library underlying the Jupyter kernel protocol. ```bash cmake -D WITH_PERF_TOOL=OFF -D ZMQ_BUILD_TESTS=OFF -D ENABLE_CPACK=OFF -D CMAKE_BUILD_TYPE=Release make make install ``` ## OpenSSL [OpenSSL](https://www.openssl.org/) is packaged for most package managers (apt-get, rpm, mamba). We recommend making use of an off-the-shelf build of OpenSSL for your system. For more information on building OpenSSL, check out the official [OpenSSL wiki](https://wiki.openssl.org/index.php/Compilation_and_Installation). ### cppzmq [cppzmq](https://github.com/zeromq/cppzmq) is a header only library: ```bash cmake -D CMAKE_BUILD_TYPE=Release make install ``` ### json for modern cpp [nlohmann_json](https://github.com/nlohmann/json) is a header only library ```bash cmake make install ``` ### xtl [xtl](https://github.com/xtensor-stack/xtl) is a header only library: ```bash cmake -D CMAKE_BUILD_TYPE make install ``` ## Contributing TODO ## License We use a shared copyright model that enables all contributors to maintain the copyright on their contributions. This software is licensed under the BSD-3-Clause license. See the [LICENSE](LICENSE) file for details. xeus-zmq-1.1.1/cmake/000077500000000000000000000000001450330156100143615ustar00rootroot00000000000000xeus-zmq-1.1.1/cmake/Findsodium.cmake000066400000000000000000000250261450330156100174710ustar00rootroot00000000000000# Written in 2016 by Henrik Steffen Gaßmann # # To the extent possible under law, the author(s) have dedicated all copyright # and related and neighboring rights to this software to the public domain # worldwide. This software is distributed without any warranty. # # You should have received a copy of the CC0 Public Domain Dedication along with # this software. If not, see # # http://creativecommons.org/publicdomain/zero/1.0/ # # ############################################################################## # Tries to find the local libsodium installation. # # On Windows the sodium_DIR environment variable is used as a default hint which # can be overridden by setting the corresponding cmake variable. # # Once done the following variables will be defined: # # sodium_FOUND sodium_INCLUDE_DIR sodium_LIBRARY_DEBUG sodium_LIBRARY_RELEASE # sodium_VERSION_STRING # # Furthermore an imported "sodium" target is created. # if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") set(_GCC_COMPATIBLE 1) endif() # static library option if(NOT DEFINED sodium_USE_STATIC_LIBS) option(sodium_USE_STATIC_LIBS "enable to statically link against sodium" OFF) endif() if(NOT (sodium_USE_STATIC_LIBS EQUAL sodium_USE_STATIC_LIBS_LAST)) unset(sodium_LIBRARY CACHE) unset(sodium_LIBRARY_DEBUG CACHE) unset(sodium_LIBRARY_RELEASE CACHE) unset(sodium_DLL_DEBUG CACHE) unset(sodium_DLL_RELEASE CACHE) set(sodium_USE_STATIC_LIBS_LAST ${sodium_USE_STATIC_LIBS} CACHE INTERNAL "internal change tracking variable") endif() # ############################################################################## # UNIX if(UNIX OR CMAKE_SYSTEM_NAME STREQUAL "Generic") # import pkg-config find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(sodium_PKG QUIET libsodium) endif() if(sodium_USE_STATIC_LIBS) if(sodium_PKG_STATIC_LIBRARIES) foreach(_libname ${sodium_PKG_STATIC_LIBRARIES}) if(NOT _libname MATCHES "^lib.*\\.a$") # ignore strings already ending # with .a list(INSERT sodium_PKG_STATIC_LIBRARIES 0 "lib${_libname}.a") endif() endforeach() list(REMOVE_DUPLICATES sodium_PKG_STATIC_LIBRARIES) else() # if pkgconfig for libsodium doesn't provide static lib info, then # override PKG_STATIC here.. set(sodium_PKG_STATIC_LIBRARIES libsodium.a) endif() set(XPREFIX sodium_PKG_STATIC) else() if(sodium_PKG_LIBRARIES STREQUAL "") set(sodium_PKG_LIBRARIES sodium) endif() set(XPREFIX sodium_PKG) endif() find_path(sodium_INCLUDE_DIR sodium.h HINTS ${${XPREFIX}_INCLUDE_DIRS}) find_library(sodium_LIBRARY_DEBUG NAMES ${${XPREFIX}_LIBRARIES} HINTS ${${XPREFIX}_LIBRARY_DIRS}) find_library(sodium_LIBRARY_RELEASE NAMES ${${XPREFIX}_LIBRARIES} HINTS ${${XPREFIX}_LIBRARY_DIRS}) # ############################################################################ # Windows elseif(WIN32) set(sodium_DIR "$ENV{sodium_DIR}" CACHE FILEPATH "sodium install directory") mark_as_advanced(sodium_DIR) find_path(sodium_INCLUDE_DIR sodium.h HINTS ${sodium_DIR} PATH_SUFFIXES include) if(MSVC) # detect target architecture file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/arch.c" [=[ #if defined _M_IX86 #error ARCH_VALUE x86_32 #elif defined _M_X64 #error ARCH_VALUE x86_64 #endif #error ARCH_VALUE unknown ]=]) try_compile(_UNUSED_VAR "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/arch.c" OUTPUT_VARIABLE _COMPILATION_LOG) string(REGEX REPLACE ".*ARCH_VALUE ([a-zA-Z0-9_]+).*" "\\1" _TARGET_ARCH "${_COMPILATION_LOG}") # construct library path if(_TARGET_ARCH STREQUAL "x86_32") string(APPEND _PLATFORM_PATH "Win32") elseif(_TARGET_ARCH STREQUAL "x86_64") string(APPEND _PLATFORM_PATH "x64") else() message( FATAL_ERROR "the ${_TARGET_ARCH} architecture is not supported by Findsodium.cmake." ) endif() string(APPEND _PLATFORM_PATH "/$$CONFIG$$") if(MSVC_VERSION LESS 1900) math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 60") else() math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 50") endif() string(APPEND _PLATFORM_PATH "/v${_VS_VERSION}") if(sodium_USE_STATIC_LIBS) string(APPEND _PLATFORM_PATH "/static") else() string(APPEND _PLATFORM_PATH "/dynamic") endif() string(REPLACE "$$CONFIG$$" "Debug" _DEBUG_PATH_SUFFIX "${_PLATFORM_PATH}") string(REPLACE "$$CONFIG$$" "Release" _RELEASE_PATH_SUFFIX "${_PLATFORM_PATH}") find_library(sodium_LIBRARY_DEBUG libsodium.lib HINTS ${sodium_DIR} PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX}) find_library(sodium_LIBRARY_RELEASE libsodium.lib HINTS ${sodium_DIR} PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX}) if(NOT sodium_USE_STATIC_LIBS) set(CMAKE_FIND_LIBRARY_SUFFIXES_BCK ${CMAKE_FIND_LIBRARY_SUFFIXES}) set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") find_library(sodium_DLL_DEBUG libsodium HINTS ${sodium_DIR} PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX}) find_library(sodium_DLL_RELEASE libsodium HINTS ${sodium_DIR} PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX}) set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BCK}) endif() elseif(_GCC_COMPATIBLE) if(sodium_USE_STATIC_LIBS) find_library(sodium_LIBRARY_DEBUG libsodium.a HINTS ${sodium_DIR} PATH_SUFFIXES lib) find_library(sodium_LIBRARY_RELEASE libsodium.a HINTS ${sodium_DIR} PATH_SUFFIXES lib) else() find_library(sodium_LIBRARY_DEBUG libsodium.dll.a HINTS ${sodium_DIR} PATH_SUFFIXES lib) find_library(sodium_LIBRARY_RELEASE libsodium.dll.a HINTS ${sodium_DIR} PATH_SUFFIXES lib) file(GLOB _DLL LIST_DIRECTORIES false RELATIVE "${sodium_DIR}/bin" "${sodium_DIR}/bin/libsodium*.dll") find_library(sodium_DLL_DEBUG ${_DLL} libsodium HINTS ${sodium_DIR} PATH_SUFFIXES bin) find_library(sodium_DLL_RELEASE ${_DLL} libsodium HINTS ${sodium_DIR} PATH_SUFFIXES bin) endif() else() message(FATAL_ERROR "this platform is not supported by FindSodium.cmake") endif() # ############################################################################ # unsupported else() message(FATAL_ERROR "this platform is not supported by FindSodium.cmake") endif() # ############################################################################## # common stuff # extract sodium version if(sodium_INCLUDE_DIR) set(_VERSION_HEADER "${sodium_INCLUDE_DIR}/sodium/version.h") if(EXISTS "${_VERSION_HEADER}") file(READ "${_VERSION_HEADER}" _VERSION_HEADER_CONTENT) string(REGEX REPLACE ".*define[ \t]+SODIUM_VERSION_STRING[^\"]+\"([^\"]+)\".*" "\\1" sodium_VERSION_STRING "${_VERSION_HEADER_CONTENT}") set(sodium_VERSION_STRING "${sodium_VERSION_STRING}") endif() endif() # communicate results include(FindPackageHandleStandardArgs) find_package_handle_standard_args(sodium REQUIRED_VARS sodium_LIBRARY_RELEASE sodium_LIBRARY_DEBUG sodium_INCLUDE_DIR VERSION_VAR sodium_VERSION_STRING) # mark file paths as advanced mark_as_advanced(sodium_INCLUDE_DIR) mark_as_advanced(sodium_LIBRARY_DEBUG) mark_as_advanced(sodium_LIBRARY_RELEASE) if(WIN32) mark_as_advanced(sodium_DLL_DEBUG) mark_as_advanced(sodium_DLL_RELEASE) endif() # create imported target if(sodium_USE_STATIC_LIBS) set(_LIB_TYPE STATIC) else() set(_LIB_TYPE SHARED) endif() add_library(sodium ${_LIB_TYPE} IMPORTED) set_target_properties(sodium PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${sodium_INCLUDE_DIR}" IMPORTED_LINK_INTERFACE_LANGUAGES "C") if(sodium_USE_STATIC_LIBS) set_target_properties(sodium PROPERTIES INTERFACE_COMPILE_DEFINITIONS "SODIUM_STATIC" IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}" IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}") else() if(UNIX) set_target_properties(sodium PROPERTIES IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}" IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}") elseif(WIN32) set_target_properties(sodium PROPERTIES IMPORTED_IMPLIB "${sodium_LIBRARY_RELEASE}" IMPORTED_IMPLIB_DEBUG "${sodium_LIBRARY_DEBUG}") if(NOT (sodium_DLL_DEBUG MATCHES ".*-NOTFOUND")) set_target_properties(sodium PROPERTIES IMPORTED_LOCATION_DEBUG "${sodium_DLL_DEBUG}") endif() if(NOT (sodium_DLL_RELEASE MATCHES ".*-NOTFOUND")) set_target_properties(sodium PROPERTIES IMPORTED_LOCATION_RELWITHDEBINFO "${sodium_DLL_RELEASE}" IMPORTED_LOCATION_MINSIZEREL "${sodium_DLL_RELEASE}" IMPORTED_LOCATION_RELEASE "${sodium_DLL_RELEASE}") endif() endif() endif() xeus-zmq-1.1.1/environment-dev.yml000066400000000000000000000006041450330156100171440ustar00rootroot00000000000000name: xeus-zmq channels: - conda-forge dependencies: # Build dependencies - cmake - cxx-compiler - pkg-config - ninja # Host dependencies - zeromq=4.3.4 - zeromq-static=4.3.4 - cppzmq=4.8.1 - xtl=0.7 - xeus>=3.1.1,<4.0 - OpenSSL=1 - libopenssl-static=1 - nlohmann_json # Test dependencies - doctest >= 2.4.6 - pytest - jupyter_kernel_test>=0.6,<0.7 xeus-zmq-1.1.1/example/000077500000000000000000000000001450330156100147345ustar00rootroot00000000000000xeus-zmq-1.1.1/example/.gitignore000066400000000000000000000000641450330156100167240ustar00rootroot00000000000000build/* share/jupyter/kernels/my_kernel/kernel.json xeus-zmq-1.1.1/example/CMakeLists.txt000066400000000000000000000053141450330156100174770ustar00rootroot00000000000000############################################################################ # Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou # # Copyright (c) 2016, QuantStack # # # # Distributed under the terms of the BSD 3-Clause License. # # # # The full license is in the file LICENSE, distributed with this software. # ############################################################################ cmake_minimum_required(VERSION 3.4.3) project(my_kernel) set(EXECUTABLE_NAME my_kernel) # Configuration # ============= include(GNUInstallDirs) # We generate the kernel.json file, given the installation prefix and the executable name configure_file ( "${CMAKE_CURRENT_SOURCE_DIR}/share/jupyter/kernels/my_kernel/kernel.json.in" "${CMAKE_CURRENT_SOURCE_DIR}/share/jupyter/kernels/my_kernel/kernel.json" ) option(XEUS_STATIC_DEPENDENCIES "link statically with xeus dependencies" OFF) if (XEUS_STATIC_DEPENDENCIES) set(xeus-zmq_target "xeus-zmq-static") else () set(xeus-zmq_target "xeus-zmq") endif () # Dependencies # ============ # Be sure to use recent versions set(xeus-zmq_REQUIRED_VERSION 1.0.2) find_package(xeus-zmq ${xeus-zmq_REQUIRED_VERSION} REQUIRED) find_package(Threads) # Flags # ===== include(CheckCXXCompilerFlag) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") CHECK_CXX_COMPILER_FLAG("-std=c++14" HAS_CPP14_FLAG) if (HAS_CPP14_FLAG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") else() message(FATAL_ERROR "Unsupported compiler -- xeus requires C++14 support!") endif() endif() # Target and link # =============== # my_kernel source files set(MY_KERNEL_SRC src/custom_interpreter.cpp src/custom_interpreter.hpp ) # My kernel executable add_executable(${EXECUTABLE_NAME} src/main.cpp ${MY_KERNEL_SRC} ) target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${xeus-zmq_target} Threads::Threads) set_target_properties(${EXECUTABLE_NAME} PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE ) # Installation # ============ # Install my_kernel install(TARGETS ${EXECUTABLE_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) # Configuration and data directories for jupyter and my_kernel set(XJUPYTER_DATA_DIR "share/jupyter" CACHE STRING "Jupyter data directory") # Install Jupyter kernelspecs set(MY_KERNELSPEC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/share/jupyter/kernels) install(DIRECTORY ${MY_KERNELSPEC_DIR} DESTINATION ${XJUPYTER_DATA_DIR} PATTERN "*.in" EXCLUDE) xeus-zmq-1.1.1/example/share/000077500000000000000000000000001450330156100160365ustar00rootroot00000000000000xeus-zmq-1.1.1/example/share/jupyter/000077500000000000000000000000001450330156100175405ustar00rootroot00000000000000xeus-zmq-1.1.1/example/share/jupyter/kernels/000077500000000000000000000000001450330156100212035ustar00rootroot00000000000000xeus-zmq-1.1.1/example/share/jupyter/kernels/my_kernel/000077500000000000000000000000001450330156100231705ustar00rootroot00000000000000xeus-zmq-1.1.1/example/share/jupyter/kernels/my_kernel/kernel.json.in000066400000000000000000000003101450330156100257420ustar00rootroot00000000000000{ "display_name": "my_kernel", "argv": [ "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/@EXECUTABLE_NAME@", "-f", "{connection_file}" ], "language": "python" } xeus-zmq-1.1.1/example/src/000077500000000000000000000000001450330156100155235ustar00rootroot00000000000000xeus-zmq-1.1.1/example/src/custom_interpreter.cpp000066400000000000000000000101511450330156100221620ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include "nlohmann/json.hpp" #include "xeus/xhelper.hpp" #include "custom_interpreter.hpp" namespace nl = nlohmann; namespace custom { nl::json custom_interpreter::execute_request_impl(int execution_counter, // Typically the cell number const std::string& /*code*/, // Code to execute bool /*silent*/, bool /*store_history*/, nl::json /*user_expressions*/, bool /*allow_stdin*/) { // You can use the C-API of your target language for executing the code, // e.g. `PyRun_String` for the Python C-API // `luaL_dostring` for the Lua C-API // Use this method for publishing the execution result to the client, // this method takes the ``execution_counter`` as first argument, // the data to publish (mime type data) as second argument and metadata // as third argument. // Replace "Hello World !!" by what you want to be displayed under the execution cell nl::json pub_data; pub_data["text/plain"] = "Hello World !!"; publish_execution_result(execution_counter, std::move(pub_data), nl::json::object()); // You can also use this method for publishing errors to the client, if the code // failed to execute // publish_execution_error(error_name, error_value, error_traceback); publish_execution_error("TypeError", "123", {"!@#$", "*(*"}); return xeus::create_successful_reply(); } void custom_interpreter::configure_impl() { // Perform some operations } nl::json custom_interpreter::complete_request_impl(const std::string& code, int cursor_pos) { // Code starts with 'H', it could be the following completion if (code[0] == 'H') { return xeus::create_complete_reply({"Hello", "Hey", "Howdy"}, 5, cursor_pos); } // No completion result else { return xeus::create_complete_reply({}, cursor_pos, cursor_pos); } } nl::json custom_interpreter::inspect_request_impl(const std::string& code, int /*cursor_pos*/, int /*detail_level*/) { nl::json result; if (code.compare("print") == 0) { return xeus::create_inspect_reply(true, {"text/plain", "Print objects to the text stream file, [...]"}); } else { return xeus::create_inspect_reply(); } } nl::json custom_interpreter::is_complete_request_impl(const std::string& /*code*/) { return xeus::create_is_complete_reply("complete"); } nl::json custom_interpreter::kernel_info_request_impl() { return xeus::create_info_reply("", "my_kernel", "0.1.0", "python", "3.7", "text/x-python", ".py"); } void custom_interpreter::shutdown_request_impl() { std::cout << "Bye!!" << std::endl; } } xeus-zmq-1.1.1/example/src/custom_interpreter.hpp000066400000000000000000000035541450330156100222000ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef CUSTOM_INTERPRETER #define CUSTOM_INTERPRETER #include "xeus/xinterpreter.hpp" #include "nlohmann/json.hpp" using xeus::xinterpreter; namespace nl = nlohmann; namespace custom { class custom_interpreter : public xinterpreter { public: custom_interpreter() = default; virtual ~custom_interpreter() = default; private: void configure_impl() override; nl::json execute_request_impl(int execution_counter, const std::string& code, bool silent, bool store_history, nl::json user_expressions, bool allow_stdin) override; nl::json complete_request_impl(const std::string& code, int cursor_pos) override; nl::json inspect_request_impl(const std::string& code, int cursor_pos, int detail_level) override; nl::json is_complete_request_impl(const std::string& code) override; nl::json kernel_info_request_impl() override; void shutdown_request_impl() override; }; } #endif xeus-zmq-1.1.1/example/src/main.cpp000066400000000000000000000026451450330156100171620ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include "xeus/xkernel.hpp" #include "xeus/xkernel_configuration.hpp" #include "xeus-zmq/xserver_zmq.hpp" #include "custom_interpreter.hpp" int main(int argc, char* argv[]) { // Load configuration file std::string file_name = (argc == 1) ? "connection.json" : argv[2]; xeus::xconfiguration config = xeus::load_configuration(file_name); auto context = xeus::make_context(); // Create interpreter instance using interpreter_ptr = std::unique_ptr; interpreter_ptr interpreter = interpreter_ptr(new custom::custom_interpreter()); // Create kernel instance and start it xeus::xkernel kernel(config, xeus::get_user_name(), std::move(context), std::move(interpreter), xeus::make_xserver_zmq); kernel.start(); return 0; } xeus-zmq-1.1.1/include/000077500000000000000000000000001450330156100147245ustar00rootroot00000000000000xeus-zmq-1.1.1/include/xeus-zmq/000077500000000000000000000000001450330156100165155ustar00rootroot00000000000000xeus-zmq-1.1.1/include/xeus-zmq/xauthentication.hpp000066400000000000000000000053171450330156100224430ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_AUTHENTICATION_HPP #define XEUS_AUTHENTICATION_HPP #include #include #include "xeus-zmq.hpp" namespace xeus { class XEUS_ZMQ_API xraw_buffer { public: xraw_buffer(const unsigned char* data, size_t size); const unsigned char* data() const; size_t size() const; private: const unsigned char* m_data; size_t m_size; }; class XEUS_ZMQ_API xauthentication { public: virtual ~xauthentication() = default; xauthentication(const xauthentication&) = delete; xauthentication& operator=(const xauthentication&) = delete; xauthentication(xauthentication&&) = delete; xauthentication& operator=(xauthentication&&) = delete; std::string sign(const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const; bool verify(const xraw_buffer& signature, const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const; protected: xauthentication() = default; private: virtual std::string sign_impl(const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const = 0; virtual bool verify_impl(const xraw_buffer& signature, const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const = 0; }; XEUS_ZMQ_API std::unique_ptr make_xauthentication(const std::string& scheme, const std::string& key); } #endif xeus-zmq-1.1.1/include/xeus-zmq/xdap_tcp_client.hpp000066400000000000000000000071571450330156100224000ustar00rootroot00000000000000#ifndef XEUS_DAP_TCP_CLIENT_HPP #define XEUS_DAP_TCP_CLIENT_HPP #include #include #include #include "zmq.hpp" #include "nlohmann/json.hpp" #include "xeus/xkernel_configuration.hpp" #include "xauthentication.hpp" #include "xeus-zmq.hpp" namespace nl = nlohmann; namespace xeus { enum class dap_tcp_type { client, server }; enum class dap_init_type { sequential, parallel }; struct XEUS_ZMQ_API xdap_tcp_configuration { dap_tcp_type m_dap_tcp_type; dap_init_type m_dap_init_type; std::string m_user_name; std::string m_session_id; xdap_tcp_configuration(dap_tcp_type adap_tcp_type, dap_init_type adap_init_type, const std::string& user_name, const std::string& session_id); }; class XEUS_ZMQ_API xdap_tcp_client { public: static constexpr const char* HEADER = "Content-Length: "; static constexpr size_t HEADER_LENGTH = 16; static constexpr const char* SEPARATOR = "\r\n\r\n"; static constexpr size_t SEPARATOR_LENGTH = 4; using event_callback = std::function; virtual ~xdap_tcp_client() = default; xdap_tcp_client(const xdap_tcp_client&) = delete; xdap_tcp_client& operator=(const xdap_tcp_client&) = delete; xdap_tcp_client(xdap_tcp_client&&) = delete; xdap_tcp_client& operator=(xdap_tcp_client&&) = delete; void start_debugger(std::string tcp_end_point, std::string publisher_end_point, std::string controller_end_point, std::string controller_header_end_point); protected: xdap_tcp_client(zmq::context_t& context, const xeus::xconfiguration& config, int socket_linger, const xdap_tcp_configuration& dap_config, const event_callback& cb); const std::string& parent_header() const; void forward_event(nl::json message); void send_dap_request(nl::json message); using message_condition = std::function; nl::json wait_for_message(const message_condition& condition); private: using queue_type = std::deque; zmq::message_t get_tcp_id() const; void init_tcp_socket(const std::string& tcp_end_point); void finalize_tcp_socket(const std::string& tcp_end_point); void handle_header_socket(); void handle_control_socket(); void handle_tcp_socket(queue_type& message_queue); void append_tcp_message(std::string& buffer); void process_message_queue(); void handle_init_sequence(); virtual void handle_event(nl::json message) = 0; zmq::socket_t m_tcp_socket; zmq::message_t m_socket_id; zmq::socket_t m_publisher; zmq::socket_t m_controller; zmq::socket_t m_controller_header; dap_tcp_type m_dap_tcp_type; dap_init_type m_dap_init_type; std::string m_user_name; std::string m_session_id; event_callback m_event_callback; using authentication_ptr = std::unique_ptr; authentication_ptr p_auth; // Saves parent header for future debug events std::string m_parent_header; bool m_request_stop; bool m_wait_attach; queue_type m_message_queue; queue_type m_stopped_queue; }; } #endif xeus-zmq-1.1.1/include/xeus-zmq/xdebugger_base.hpp000066400000000000000000000105061450330156100221760ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2018, Martin Renou, Johan Mabille, Sylvain Corlay, and * * Wolf Vollprecht * * Copyright (c) 2018, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_DEBUGGER_BASE_HPP #define XEUS_DEBUGGER_BASE_HPP #include #include #include #include #include #include #include #include "zmq.hpp" #include "nlohmann/json.hpp" #include "xeus/xdebugger.hpp" #include "xeus-zmq.hpp" namespace xeus { struct XEUS_ZMQ_API xdebugger_info { std::size_t m_hash_seed; std::string m_tmp_file_prefix; std::string m_tmp_file_suffix; bool m_rich_rendering; std::vector m_exception_paths; xdebugger_info(std::size_t hash_seed, const std::string& tmp_file_prefix, const std::string& tmp_file_suffix, bool rich_rendering = false, std::vector exception_paths = {}); }; class XEUS_ZMQ_API xdebugger_base : public xdebugger { public: virtual ~xdebugger_base() = default; protected: xdebugger_base(zmq::context_t& context); bool is_started() const; std::function get_event_callback(); /********************* * Requests handling * *********************/ using request_handler_t = std::function; void register_request_handler(const std::string& command, const request_handler_t& handler, bool require_started); nl::json debug_info_request(const nl::json& message); nl::json dump_cell_request(const nl::json& message); nl::json set_breakpoints_request(const nl::json& message); nl::json source_request(const nl::json& message); nl::json stack_trace_request(const nl::json& message); nl::json variables_request(const nl::json& message); nl::json forward_message(const nl::json& message); /******************* * Events handling * *******************/ using event_handler_t = std::function; void register_event_handler(const std::string& event, const event_handler_t& handler); void continued_event(const nl::json& message); void stopped_event(const nl::json& message); const std::set& get_stopped_threads() const; protected: virtual nl::json variables_request_impl(const nl::json& message); private: void handle_event(const nl::json& message); nl::json process_request_impl(const nl::json& header, const nl::json& message) override; virtual bool start(zmq::socket_t& header_socket, zmq::socket_t& request_socket) = 0; virtual void stop(zmq::socket_t& header_socket, zmq::socket_t& request_socket) = 0; virtual xdebugger_info get_debugger_info() const = 0; virtual std::string get_cell_temporary_file(const std::string& code) const = 0; zmq::socket_t m_header_socket; zmq::socket_t m_request_socket; using request_handler_map_t = std::map; request_handler_map_t m_started_handler; request_handler_map_t m_request_handler; using event_handler_map_t = std::map; event_handler_map_t m_event_handler; using breakpoint_list_t = std::map>; breakpoint_list_t m_breakpoint_list; std::set m_stopped_threads; std::mutex m_stopped_mutex; bool m_is_started; }; } #endif xeus-zmq-1.1.1/include/xeus-zmq/xeus-zmq.hpp000066400000000000000000000023601450330156100210200ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_ZMQ_EXPORT_HPP #define XEUS_ZMQ_EXPORT_HPP #ifdef _WIN32 #ifdef XEUS_ZMQ_STATIC_LIB #define XEUS_ZMQ_API #else #ifdef XEUS_ZMQ_EXPORTS #define XEUS_ZMQ_API __declspec(dllexport) #else #define XEUS_ZMQ_API __declspec(dllimport) #endif #endif #else #define XEUS_ZMQ_API __attribute__((visibility("default"))) #endif // Project version #define XEUS_ZMQ_VERSION_MAJOR 1 #define XEUS_ZMQ_VERSION_MINOR 1 #define XEUS_ZMQ_VERSION_PATCH 1 // Binary version #define XEUS_ZMQ_BINARY_CURRENT 3 #define XEUS_ZMQ_BINARY_REVISION 0 #define XEUS_ZMQ_BINARY_AGE 1 #endif xeus-zmq-1.1.1/include/xeus-zmq/xmiddleware.hpp000066400000000000000000000031531450330156100215350ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_MIDDLEWARE_HPP #define XEUS_MIDDLEWARE_HPP #include #include "zmq.hpp" #include "xeus-zmq.hpp" namespace xeus { XEUS_ZMQ_API std::string get_controller_end_point(const std::string& channel); XEUS_ZMQ_API std::string get_publisher_end_point(); XEUS_ZMQ_API std::string get_end_point(const std::string& transport, const std::string& ip, const std::string& port); XEUS_ZMQ_API int get_socket_linger(); XEUS_ZMQ_API void init_socket(zmq::socket_t& socket, const std::string& transport, const std::string& ip, const std::string& port); XEUS_ZMQ_API void init_socket(zmq::socket_t& socket, const std::string& end_point); XEUS_ZMQ_API std::string get_socket_port(const zmq::socket_t& socket); XEUS_ZMQ_API std::string find_free_port(std::size_t max_tries = 100, int start = 49152, int stop = 65536); } #endif xeus-zmq-1.1.1/include/xeus-zmq/xserver_control_main.hpp000066400000000000000000000030571450330156100234750ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_SERVER_CONTROL_MAIN_HPP #define XEUS_SERVER_CONTROL_MAIN_HPP #include "xeus/xcontrol_messenger.hpp" #include "xeus/xeus_context.hpp" #include "xeus/xkernel_configuration.hpp" #include "xeus-zmq.hpp" #include "xserver_zmq_split.hpp" namespace xeus { class XEUS_ZMQ_API xserver_control_main : public xserver_zmq_split { public: xserver_control_main(zmq::context_t& context, const xconfiguration& config, nl::json::error_handler_t eh); virtual ~xserver_control_main(); private: void start_server(zmq::multipart_t& wire_msg) override; }; XEUS_ZMQ_API std::unique_ptr make_xserver_control_main(xcontext& context, const xconfiguration& config, nl::json::error_handler_t eh = nl::json::error_handler_t::strict); } #endif xeus-zmq-1.1.1/include/xeus-zmq/xserver_shell_main.hpp000066400000000000000000000027641450330156100231300ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_SERVER_SHELL_MAIN_HPP #define XEUS_SERVER_SHELL_MAIN_HPP #include "xeus/xeus_context.hpp" #include "xeus/xkernel_configuration.hpp" #include "xeus-zmq.hpp" #include "xserver_zmq_split.hpp" namespace xeus { class XEUS_ZMQ_API xserver_shell_main : public xserver_zmq_split { public: xserver_shell_main(zmq::context_t& context, const xconfiguration& config, nl::json::error_handler_t he); virtual ~xserver_shell_main(); private: void start_server(zmq::multipart_t& wire_msg) override; }; XEUS_ZMQ_API std::unique_ptr make_xserver_shell_main(xcontext& context, const xconfiguration& config, nl::json::error_handler_t eh = nl::json::error_handler_t::strict); } #endif xeus-zmq-1.1.1/include/xeus-zmq/xserver_zmq.hpp000066400000000000000000000061011450330156100216110ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_SERVER_IMPL_HPP #define XEUS_SERVER_IMPL_HPP #include "zmq.hpp" #include "zmq_addon.hpp" #include "xeus/xeus_context.hpp" #include "xeus/xkernel_configuration.hpp" #include "xeus/xserver.hpp" #include "xeus-zmq.hpp" #include "xthread.hpp" namespace xeus { class xauthentication; class xpublisher; class xheartbeat; class xtrivial_messenger; class XEUS_ZMQ_API xserver_zmq : public xserver { public: using publisher_ptr = std::unique_ptr; using heartbeat_ptr = std::unique_ptr; xserver_zmq(zmq::context_t& context, const xconfiguration& config, nl::json::error_handler_t eh); ~xserver_zmq() override; zmq::multipart_t serialize_iopub(xpub_message&& msg); using xserver::notify_internal_listener; protected: xcontrol_messenger& get_control_messenger_impl() override; void send_shell_impl(xmessage msg) override; void send_control_impl(xmessage msg) override; void send_stdin_impl(xmessage msg) override; void publish_impl(xpub_message msg, channel c) override; void start_impl(xpub_message msg) override; void abort_queue_impl(const listener& l, long polling_interval) override; void stop_impl() override; void update_config_impl(xconfiguration& config) const override; void poll(long timeout); void start_publisher_thread(); void start_heartbeat_thread(); void stop_channels(); zmq::socket_t m_shell; zmq::socket_t m_controller; zmq::socket_t m_stdin; zmq::socket_t m_publisher_pub; zmq::socket_t m_publisher_controller; zmq::socket_t m_heartbeat_controller; using authentication_ptr = std::unique_ptr; authentication_ptr p_auth; publisher_ptr p_publisher; heartbeat_ptr p_heartbeat; xthread m_iopub_thread; xthread m_hb_thread; using trivial_messenger_ptr = std::unique_ptr; trivial_messenger_ptr p_messenger; nl::json::error_handler_t m_error_handler; bool m_request_stop; }; XEUS_ZMQ_API std::unique_ptr make_xserver_zmq(xcontext& context, const xconfiguration& config, nl::json::error_handler_t eh = nl::json::error_handler_t::strict); } #endif xeus-zmq-1.1.1/include/xeus-zmq/xserver_zmq_split.hpp000066400000000000000000000064471450330156100230410ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_SERVER_ZMQ_SPLIT_HPP #define XEUS_SERVER_ZMQ_SPLIT_HPP #include #include "zmq_addon.hpp" #include "xeus/xserver.hpp" #include "xeus/xkernel_configuration.hpp" #include "xeus-zmq.hpp" #include "xthread.hpp" namespace xeus { class xauthentication; class xcontrol; class xheartbeat; class xpublisher; class xshell; class XEUS_ZMQ_API xserver_zmq_split : public xserver { public: using controller_ptr = std::unique_ptr; using heartbeat_ptr = std::unique_ptr; using publisher_ptr = std::unique_ptr; using shell_ptr = std::unique_ptr; xserver_zmq_split(zmq::context_t& context, const xconfiguration& config, nl::json::error_handler_t eh); ~xserver_zmq_split() override; // The xcontrol object needs to call this method using xserver::notify_control_listener; // The xshell object needs to call these methods using xserver::notify_shell_listener; using xserver::notify_stdin_listener; zmq::multipart_t notify_internal_listener(zmq::multipart_t& wire_msg); void notify_control_stopped(); xmessage deserialize(zmq::multipart_t& wire_msg) const; zmq::multipart_t serialize_iopub(xpub_message&& msg); protected: xcontrol_messenger& get_control_messenger_impl() override; void send_shell_impl(xmessage msg) override; void send_control_impl(xmessage msg) override; void send_stdin_impl(xmessage msg) override; void publish_impl(xpub_message msg, channel c) override; void start_impl(xpub_message msg) override; void abort_queue_impl(const listener& l, long polling_interval) override; void stop_impl() override; void update_config_impl(xconfiguration& config) const override; void start_control_thread(); void start_heartbeat_thread(); void start_publisher_thread(); void start_shell_thread(); xcontrol& get_controller(); xshell& get_shell(); bool is_control_stopped() const; private: virtual void start_server(zmq::multipart_t& wire_msg) = 0; using authentication_ptr = std::unique_ptr; authentication_ptr p_auth; controller_ptr p_controller; heartbeat_ptr p_heartbeat; publisher_ptr p_publisher; shell_ptr p_shell; xthread m_control_thread; xthread m_hb_thread; xthread m_iopub_thread; xthread m_shell_thread; nl::json::error_handler_t m_error_handler; std::atomic m_control_stopped; }; } #endif xeus-zmq-1.1.1/include/xeus-zmq/xthread.hpp000066400000000000000000000060161450330156100206700ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_THREAD_HPP #define XEUS_THREAD_HPP #include #include namespace xeus { /** * Joining std::thread */ class xthread { public: using id = std::thread::id; using native_handle_type = std::thread::native_handle_type; xthread() noexcept = default; // Last arguments SFINAE out copy constructor template , xthread>::value>> explicit xthread(Function&& f, Args&&... args); ~xthread(); xthread(const xthread&) = delete; xthread& operator=(const xthread&) = delete; xthread(xthread&&) = default; xthread& operator=(xthread&&); bool joinable() const noexcept; id get_id() const noexcept; native_handle_type native_handle(); static unsigned int hardware_concurrency() noexcept; void join(); void detach(); void swap(xthread& other) noexcept; private: std::thread m_thread; }; /************************** * xthread implementation * **************************/ template inline xthread::xthread(Function&& func, Args&&... args) : m_thread{ std::forward(func), std::forward(args)... } { } inline xthread::~xthread() { if (joinable()) { join(); } } inline xthread& xthread::operator=(xthread&& rhs) { if (joinable()) { join(); } m_thread = std::move(rhs.m_thread); return *this; } inline bool xthread::joinable() const noexcept { return m_thread.joinable(); } inline xthread::id xthread::get_id() const noexcept { return m_thread.get_id(); } inline xthread::native_handle_type xthread::native_handle() { return m_thread.native_handle(); } inline unsigned int xthread::hardware_concurrency() noexcept { return std::thread::hardware_concurrency(); } inline void xthread::join() { m_thread.join(); } inline void xthread::detach() { m_thread.detach(); } inline void xthread::swap(xthread& other) noexcept { m_thread.swap(other.m_thread); } } #endif xeus-zmq-1.1.1/include/xeus-zmq/xzmq_context.hpp000066400000000000000000000003401450330156100217660ustar00rootroot00000000000000#ifndef XZMQ_CONTEXT_HPP #define XZMQ_CONTEXT_HPP #include #include "xeus/xeus_context.hpp" #include "xeus-zmq.hpp" namespace xeus { XEUS_ZMQ_API std::unique_ptr make_zmq_context(); } #endif xeus-zmq-1.1.1/include/xeus-zmq/xzmq_serializer.hpp000066400000000000000000000032341450330156100224600ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_ZMQ_SERIALIZER_HPP #define XEUS_ZMQ_SERIALIZER_HPP #include "zmq_addon.hpp" #include "xeus/xmessage.hpp" #include "xeus-zmq.hpp" #include "xauthentication.hpp" namespace xeus { class XEUS_ZMQ_API xzmq_serializer { public: static zmq::multipart_t serialize(xmessage&& msg, const xauthentication& auth, nl::json::error_handler_t error_handler = nl::json::error_handler_t::strict); static xmessage deserialize(zmq::multipart_t& wire_msg, const xauthentication& auth); static zmq::multipart_t serialize_iopub(xpub_message&& msg, const xauthentication& auth, nl::json::error_handler_t error_handler = nl::json::error_handler_t::strict); static xpub_message deserialize_iopub(zmq::multipart_t& wire_msg, const xauthentication& auth); }; } #endif xeus-zmq-1.1.1/src/000077500000000000000000000000001450330156100140705ustar00rootroot00000000000000xeus-zmq-1.1.1/src/xauthentication.cpp000066400000000000000000000250331450330156100200060ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include #include #include #include #include #if OPENSSL_VERSION_NUMBER < 0x30000000L #include #include #else #include #include #include #include #include #endif #include "xeus/xstring_utils.hpp" #include "xeus-zmq/xauthentication.hpp" namespace xeus { // xraw_buffer implementation xraw_buffer::xraw_buffer(const unsigned char* data, size_t size) : m_data(data), m_size(size) { } const unsigned char* xraw_buffer::data() const { return m_data; } size_t xraw_buffer::size() const { return m_size; } // Specialization of xauthentication using OpenSSL. class openssl_xauthentication : public xauthentication { public: openssl_xauthentication(const std::string& scheme, const std::string& key); virtual ~openssl_xauthentication(); private: std::string sign_impl(const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const override; bool verify_impl(const xraw_buffer& signature, const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const override; std::string compute_hex_signature(const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const; std::string m_key; #if OPENSSL_VERSION_NUMBER < 0x30000000L const EVP_MD* m_evp; HMAC_CTX* m_hmac; #else std::string m_hash_name; OSSL_PARAM m_ossl_params[2]; EVP_MAC* m_evp_mac; EVP_MAC_CTX* m_evp_mac_ctx; #endif mutable std::mutex m_mac_mutex; }; // Specialization of xauthentication without any signature checking. class no_xauthentication : public xauthentication { public: no_xauthentication() = default; virtual ~no_xauthentication() = default; private: std::string sign_impl(const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const override; bool verify_impl(const xraw_buffer& signature, const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const override; }; std::string xauthentication::sign(const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const { return sign_impl(header, parent_header, meta_data, content); } bool xauthentication::verify(const xraw_buffer& signature, const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const { return verify_impl(signature, header, parent_header, meta_data, content); } std::unique_ptr make_xauthentication(const std::string& scheme, const std::string& key) { if (scheme == "none") { return std::make_unique(); } else { return std::make_unique(scheme, key); } } #if OPENSSL_VERSION_NUMBER < 0x30000000L inline const EVP_MD* asevp(const std::string& scheme) { static const std::map schemes = { {"hmac-md5", EVP_md5}, {"hmac-sha1", EVP_sha1}, // MDC2 is disabled by default unless enable-mdc2 is specified // {"hmac-mdc2", EVP_mdc2}, {"hmac-ripemd160", EVP_ripemd160}, #if OPENSSL_VERSION_NUMBER >= 0x10100000L {"hmac-blake2b512", EVP_blake2b512}, {"hmac-blake2s256", EVP_blake2s256}, #endif {"hmac-sha224", EVP_sha224}, {"hmac-sha256", EVP_sha256}, {"hmac-sha384", EVP_sha384}, {"hmac-sha512", EVP_sha512} }; return schemes.at(scheme)(); } #endif openssl_xauthentication::openssl_xauthentication(const std::string& scheme, const std::string& key) : m_key(key) #if OPENSSL_VERSION_NUMBER < 0x30000000L , m_evp(asevp(scheme)) #else , m_evp_mac(nullptr) , m_evp_mac_ctx(nullptr) #endif { #if OPENSSL_VERSION_NUMBER < 0x10100000L // OpenSSL 1.0.x m_hmac = new HMAC_CTX(); HMAC_CTX_init(m_hmac); #elif OPENSSL_VERSION_NUMBER < 0x30000000L m_hmac = HMAC_CTX_new(); #else m_hash_name = scheme.substr(5); std::transform(m_hash_name.begin(), m_hash_name.end(), m_hash_name.begin(), [](unsigned char c) { return std::toupper(c); }); m_ossl_params[0] = OSSL_PARAM_construct_utf8_string("digest", const_cast(m_hash_name.c_str()), std::size_t(0)); m_ossl_params[1] = OSSL_PARAM_construct_end(); m_evp_mac = EVP_MAC_fetch(nullptr, "hmac", nullptr); if (!m_evp_mac) { throw std::runtime_error("Could not fetch evp_mac"); } m_evp_mac_ctx = EVP_MAC_CTX_new(m_evp_mac); if (!m_evp_mac_ctx) { throw std::runtime_error("Could not allocate evp_mac_ctx"); } #endif } openssl_xauthentication::~openssl_xauthentication() { #if OPENSSL_VERSION_NUMBER < 0x10100000L // OpenSSL 1.0.x HMAC_CTX_cleanup(m_hmac); #elif OPENSSL_VERSION_NUMBER < 0x30000000L HMAC_CTX_free(m_hmac); #else EVP_MAC_CTX_free(m_evp_mac_ctx); EVP_MAC_free(m_evp_mac); #endif } std::string openssl_xauthentication::sign_impl(const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const { std::lock_guard lock(m_mac_mutex); std::string hex_sig = compute_hex_signature(header, parent_header, meta_data, content); return hex_sig; } bool openssl_xauthentication::verify_impl(const xraw_buffer& signature, const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const { std::lock_guard lock(m_mac_mutex); std::string hex_sig = compute_hex_signature(header, parent_header, meta_data, content); auto cmp = CRYPTO_memcmp(reinterpret_cast(hex_sig.c_str()), signature.data(), hex_sig.size()); return cmp == 0; } std::string openssl_xauthentication::compute_hex_signature(const xraw_buffer& header, const xraw_buffer& parent_header, const xraw_buffer& meta_data, const xraw_buffer& content) const { #if OPENSSL_VERSION_NUMBER < 0x30000000L HMAC_Init_ex(m_hmac, m_key.c_str(), m_key.size(), m_evp, nullptr); HMAC_Update(m_hmac, header.data(), header.size()); HMAC_Update(m_hmac, parent_header.data(), parent_header.size()); HMAC_Update(m_hmac, meta_data.data(), meta_data.size()); HMAC_Update(m_hmac, content.data(), content.size()); auto sig = std::vector(EVP_MD_size(m_evp)); HMAC_Final(m_hmac, sig.data(), nullptr); #else EVP_MAC_init(m_evp_mac_ctx, reinterpret_cast(m_key.c_str()), m_key.size(), m_ossl_params); EVP_MAC_update(m_evp_mac_ctx, header.data(), header.size()); EVP_MAC_update(m_evp_mac_ctx, parent_header.data(), parent_header.size()); EVP_MAC_update(m_evp_mac_ctx, meta_data.data(), meta_data.size()); EVP_MAC_update(m_evp_mac_ctx, content.data(), content.size()); size_t final_size(0); // Computes the final size EVP_MAC_final(m_evp_mac_ctx, nullptr, &final_size, size_t(0)); auto sig = std::vector(final_size); EVP_MAC_final(m_evp_mac_ctx, sig.data(), &final_size, sig.size()); #endif return hex_string(sig); } std::string no_xauthentication::sign_impl(const xraw_buffer& /*header*/, const xraw_buffer& /*parent_header*/, const xraw_buffer& /*meta_data*/, const xraw_buffer& /*content*/) const { return std::string(); } bool no_xauthentication::verify_impl(const xraw_buffer& /*signature*/, const xraw_buffer& /*header*/, const xraw_buffer& /*parent_header*/, const xraw_buffer& /*meta_data*/, const xraw_buffer& /*content*/) const { return true; } } xeus-zmq-1.1.1/src/xcontrol.cpp000066400000000000000000000051071450330156100164470ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include #include "xeus-zmq/xmiddleware.hpp" #include "xeus-zmq/xserver_zmq_split.hpp" #include "xcontrol.hpp" namespace xeus { xcontrol::xcontrol(zmq::context_t& context, const std::string& transport, const std::string& ip, const std::string& control_port, xserver_zmq_split* server) : m_control(context, zmq::socket_type::router) , m_publisher_pub(context, zmq::socket_type::pub) , m_messenger(context) , p_server(server) , m_request_stop(false) { init_socket(m_control, transport, ip, control_port); m_publisher_pub.set(zmq::sockopt::linger, get_socket_linger()); m_publisher_pub.connect(get_publisher_end_point()); } xcontrol::~xcontrol() { } std::string xcontrol::get_port() const { return get_socket_port(m_control); } void xcontrol::connect_messenger() { m_messenger.connect(); } xcontrol_messenger& xcontrol::get_messenger() { return m_messenger; } void xcontrol::run() { m_request_stop = false; while (!m_request_stop) { zmq::multipart_t wire_msg; wire_msg.recv(m_control); try { xmessage msg = p_server->deserialize(wire_msg); p_server->notify_control_listener(std::move(msg)); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } } m_messenger.stop_channels(); p_server->notify_control_stopped(); } void xcontrol::stop() { m_request_stop = true; } void xcontrol::send_control(zmq::multipart_t& message) { message.send(m_control); } void xcontrol::publish(zmq::multipart_t& message) { message.send(m_publisher_pub); } } xeus-zmq-1.1.1/src/xcontrol.hpp000066400000000000000000000032321450330156100164510ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_CONTROL_HPP #define XEUS_CONTROL_HPP #include #include "zmq.hpp" #include "zmq_addon.hpp" #include "xzmq_messenger.hpp" namespace xeus { class xserver_zmq_split; class xcontrol { public: using listener = std::function; xcontrol(zmq::context_t& context, const std::string& transport, const std::string& ip, const std::string& control_port, xserver_zmq_split* server); ~xcontrol(); std::string get_port() const; void connect_messenger(); xcontrol_messenger& get_messenger(); void run(); void stop(); void send_control(zmq::multipart_t& message); void publish(zmq::multipart_t& message); private: zmq::socket_t m_control; zmq::socket_t m_publisher_pub; // Internal sockets for controlling other threads xzmq_messenger m_messenger; xserver_zmq_split* p_server; bool m_request_stop; }; } #endif xeus-zmq-1.1.1/src/xdap_tcp_client.cpp000066400000000000000000000346301450330156100177420ustar00rootroot00000000000000#include "zmq_addon.hpp" #include "nlohmann/json.hpp" #include "xeus/xmessage.hpp" #include "xeus-zmq/xzmq_serializer.hpp" #include "xeus-zmq/xdap_tcp_client.hpp" namespace xeus { /********************************* * xdap_tcp_client implemenation * *********************************/ xdap_tcp_configuration::xdap_tcp_configuration(dap_tcp_type adap_tcp_type, dap_init_type adap_init_type, const std::string& user_name, const std::string& session_id) : m_dap_tcp_type(adap_tcp_type) , m_dap_init_type(adap_init_type) , m_user_name(user_name) , m_session_id(session_id) { } xdap_tcp_client::xdap_tcp_client(zmq::context_t& context, const xeus::xconfiguration& config, int socket_linger, const xdap_tcp_configuration& dap_config, const event_callback& cb) : m_tcp_socket(context, zmq::socket_type::stream) , m_socket_id() , m_publisher(context, zmq::socket_type::pub) , m_controller(context, zmq::socket_type::rep) , m_controller_header(context, zmq::socket_type::rep) , m_dap_tcp_type(dap_config.m_dap_tcp_type) , m_dap_init_type(dap_config.m_dap_init_type) , m_user_name(dap_config.m_user_name) , m_session_id(dap_config.m_session_id) , m_event_callback(cb) , p_auth(xeus::make_xauthentication(config.m_signature_scheme, config.m_key)) , m_parent_header("") , m_request_stop(false) { m_tcp_socket.set(zmq::sockopt::linger, socket_linger); m_publisher.set(zmq::sockopt::linger, socket_linger); m_controller.set(zmq::sockopt::linger, socket_linger); m_controller_header.set(zmq::sockopt::linger, socket_linger); } const std::string& xdap_tcp_client::parent_header() const { return m_parent_header; } void xdap_tcp_client::forward_event(nl::json message) { if (message["type"] == "event" && message["event"] == "stopped" && message["body"]["allThreadsStopped"]) { int seq = message["seq"].get() + 1; nl::json req = { {"seq", seq}, {"type", "request"}, {"command", "threads"} }; send_dap_request(std::move(req)); auto rep = wait_for_message([](const nl::json& msg) { return msg["command"] == "threads"; }); nl::json new_message = message; new_message["body"]["threadList"] = nl::json::array(); for (auto& th: rep["body"]["threads"]) { new_message["body"]["threadList"].push_back(th["id"]); } m_event_callback(new_message); } else { m_event_callback(message); } nl::json header = xeus::make_header("debug_event", m_user_name, m_session_id); nl::json parent_header = m_parent_header.empty() ? nl::json::object() : nl::json::parse(m_parent_header); xeus::xpub_message msg("debug_event", std::move(header), std::move(parent_header), nl::json::object(), std::move(message), xeus::buffer_sequence()); zmq::multipart_t wire_msg = xzmq_serializer::serialize_iopub(std::move(msg), *p_auth); //std::move(msg).serialize(wire_msg, *p_auth); wire_msg.send(m_publisher); } void xdap_tcp_client::send_dap_request(nl::json message) { std::string content = message.dump(); size_t content_length = content.length(); std::string buffer = xdap_tcp_client::HEADER + std::to_string(content_length) + xdap_tcp_client::SEPARATOR + content; zmq::message_t raw_message(buffer.c_str(), buffer.length()); m_tcp_socket.send(get_tcp_id(), zmq::send_flags::sndmore); m_tcp_socket.send(raw_message, zmq::send_flags::none); } nl::json xdap_tcp_client::wait_for_message(const message_condition& condition) { bool wait_cond = true; nl::json message; // Checks if the message is not already in the message queue auto iter = std::find_if(m_message_queue.cbegin(), m_message_queue.cend(), [&condition, &message](const std::string& raw_message) { message = nl::json::parse(raw_message); return condition(message); }); if (iter != m_message_queue.cend()) { wait_cond = false; m_message_queue.erase(iter); } // Waits for additional messages while (wait_cond) { handle_tcp_socket(m_stopped_queue); while (!m_stopped_queue.empty()) { const std::string& raw_message = m_stopped_queue.front(); nl::json tmp_message = nl::json::parse(raw_message); if (condition(tmp_message)) { wait_cond = false; message = tmp_message; } else { m_message_queue.push_back(raw_message); } m_stopped_queue.pop_front(); } } return message; } void xdap_tcp_client::start_debugger(std::string tcp_end_point, std::string publisher_end_point, std::string controller_end_point, std::string controller_header_end_point) { m_publisher.connect(publisher_end_point); m_controller.connect(controller_end_point); m_controller_header.connect(controller_header_end_point); init_tcp_socket(tcp_end_point); // Tells the controller that the connection with // ptvsd has been established zmq::message_t req; (void)m_controller.recv(req); m_controller.send(zmq::message_t("ACK", 3), zmq::send_flags::none); zmq::pollitem_t items[] = { { m_controller_header, 0, ZMQ_POLLIN, 0 }, { m_controller, 0, ZMQ_POLLIN, 0 }, { m_tcp_socket, 0, ZMQ_POLLIN, 0 } }; m_request_stop = false; m_wait_attach = m_dap_init_type == dap_init_type::parallel; while(!m_request_stop) { zmq::poll(&items[0], 3, std::chrono::milliseconds(-1)); if(items[0].revents & ZMQ_POLLIN) { handle_header_socket(); } if(items[1].revents & ZMQ_POLLIN) { handle_control_socket(); } if(items[2].revents & ZMQ_POLLIN) { handle_tcp_socket(m_message_queue); } process_message_queue(); } m_request_stop = false; finalize_tcp_socket(tcp_end_point); m_controller.disconnect(controller_end_point); m_controller_header.disconnect(controller_header_end_point); m_publisher.disconnect(publisher_end_point); } zmq::message_t xdap_tcp_client::get_tcp_id() const { return zmq::message_t(m_socket_id.data(), m_socket_id.size()); } void xdap_tcp_client::init_tcp_socket(const std::string& tcp_end_point) { if (m_dap_tcp_type == dap_tcp_type::client) { m_tcp_socket.connect(tcp_end_point); size_t id_size = 256; std::string id = m_tcp_socket.get(zmq::sockopt::routing_id, id_size); m_socket_id = zmq::message_t(id); } else { m_tcp_socket.bind(tcp_end_point); (void)m_tcp_socket.recv(m_socket_id); zmq::message_t msg; (void)m_tcp_socket.recv(msg); } } void xdap_tcp_client::finalize_tcp_socket(const std::string& tcp_end_point) { if (m_dap_tcp_type == dap_tcp_type::client) { m_tcp_socket.disconnect(tcp_end_point); } else { m_tcp_socket.unbind(tcp_end_point); } } void xdap_tcp_client::handle_header_socket() { zmq::message_t message; (void)m_controller_header.recv(message); m_parent_header = std::string(message.data(), message.size()); m_controller_header.send(zmq::message_t("ACK", 3), zmq::send_flags::none); } void xdap_tcp_client::handle_control_socket() { zmq::message_t message; (void)m_controller.recv(message); if (m_wait_attach) { std::string raw_message = std::string(message.data(), message.size()); auto pos = raw_message.find(SEPARATOR); std::string to_parse = raw_message.substr(pos + SEPARATOR_LENGTH); nl::json json_message = nl::json::parse(to_parse); // Sends a ZMQ header (required for stream socket) and forwards // the message m_tcp_socket.send(get_tcp_id(), zmq::send_flags::sndmore); m_tcp_socket.send(message, zmq::send_flags::none); if (json_message["command"] == "attach") { handle_init_sequence(); m_wait_attach = false; } } else { // Sends a ZMQ header (required for stream socket) and forwards // the message m_tcp_socket.send(get_tcp_id(), zmq::send_flags::sndmore); m_tcp_socket.send(message, zmq::send_flags::none); } } void xdap_tcp_client::handle_tcp_socket(queue_type& message_queue) { using size_type = std::string::size_type; std::string buffer = ""; bool messages_received = false; size_type header_pos = std::string::npos; size_type separator_pos = std::string::npos; size_type msg_size = 0; size_type msg_pos = std::string::npos; size_type hint = 0; while(!messages_received) { while(header_pos == std::string::npos) { append_tcp_message(buffer); header_pos = buffer.find(HEADER, hint); } hint = header_pos + HEADER_LENGTH; separator_pos = buffer.find(SEPARATOR, hint); while(separator_pos == std::string::npos) { append_tcp_message(buffer); separator_pos = buffer.find(SEPARATOR, hint); } msg_size = std::stoull(buffer.substr(header_pos + HEADER_LENGTH, separator_pos)); msg_pos = separator_pos + SEPARATOR_LENGTH; // The end of the buffer does not contain a full message while(buffer.size() - msg_pos < msg_size) { append_tcp_message(buffer); } // The end of the buffer contains a full message if(buffer.size() - msg_pos == msg_size) { message_queue.push_back(buffer.substr(msg_pos)); messages_received = true; } else { // The end of the buffer contains a full message // and the beginning of a new one. We push the first // one in the queue, and loop again to get the next // one. message_queue.push_back(buffer.substr(msg_pos, msg_size)); hint = msg_pos + msg_size; header_pos = buffer.find(HEADER, hint); separator_pos = std::string::npos; } } } void xdap_tcp_client::append_tcp_message(std::string& buffer) { // First message is a ZMQ header that we discard zmq::message_t header; (void)m_tcp_socket.recv(header); zmq::message_t content; (void)m_tcp_socket.recv(content); buffer += std::string(content.data(), content.size()); } void xdap_tcp_client::process_message_queue() { while(!m_message_queue.empty()) { const std::string& raw_message = m_message_queue.front(); nl::json message = nl::json::parse(raw_message); // message is either an event or a response if(message["type"] == "event") { handle_event(std::move(message)); } else { if(message["command"] == "disconnect") { m_request_stop = true; } zmq::message_t reply(raw_message.c_str(), raw_message.size()); m_controller.send(reply, zmq::send_flags::none); } m_message_queue.pop_front(); } } void xdap_tcp_client::handle_init_sequence() { // 1] Wait for initialized event nl::json initialized = wait_for_message([](const nl::json& message) { return message["type"] == "event" && message["event"] == "initialized"; }); // 2] Sends configuration done nl::json configuration_done = { {"type", "request"}, {"seq", initialized["seq"].get() + 1}, {"command", "configurationDone"}, }; send_dap_request(configuration_done); // 3] Waits for configurationDone response nl::json config_response = wait_for_message([](const nl::json& message) { return message["type"] == "response" && message["command"] == "configurationDone"; }); // 4] Waits for attach response nl::json attach_response = wait_for_message([](const nl::json& message) { return message["type"] == "response" && message["command"] == "attach"; }); // 5] Forwards initialized event and attach_response forward_event(std::move(initialized)); std::string raw_response = attach_response.dump(); zmq::message_t reply(raw_response.c_str(), raw_response.size()); m_controller.send(reply, zmq::send_flags::none); } } xeus-zmq-1.1.1/src/xdebugger_base.cpp000066400000000000000000000334471450330156100175550ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2018, Martin Renou, Johan Mabille, Sylvain Corlay, and * * Wolf Vollprecht * * Copyright (c) 2018, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include "xeus-zmq/xdap_tcp_client.hpp" #include "xeus-zmq/xdebugger_base.hpp" #include "xeus-zmq/xmiddleware.hpp" using namespace std::placeholders; namespace xeus { xdebugger_info::xdebugger_info(std::size_t hash_seed, const std::string& tmp_file_prefix, const std::string& tmp_file_suffix, bool rich_rendering, std::vector exception_paths) : m_hash_seed(hash_seed) , m_tmp_file_prefix(tmp_file_prefix) , m_tmp_file_suffix(tmp_file_suffix) , m_rich_rendering(rich_rendering) , m_exception_paths(exception_paths) { } xdebugger_base::xdebugger_base(zmq::context_t& context) : m_header_socket(context, zmq::socket_type::req) , m_request_socket(context, zmq::socket_type::req) , m_is_started(false) { m_header_socket.set(zmq::sockopt::linger, xeus::get_socket_linger()); m_request_socket.set(zmq::sockopt::linger, xeus::get_socket_linger()); register_request_handler("debugInfo", std::bind(&xdebugger_base::debug_info_request, this, _1), false); register_request_handler("dumpCell", std::bind(&xdebugger_base::dump_cell_request, this, _1), true); register_request_handler("setBreakpoints", std::bind(&xdebugger_base::set_breakpoints_request, this, _1), true); register_request_handler("source", std::bind(&xdebugger_base::source_request, this, _1), true); register_request_handler("stackTrace", std::bind(&xdebugger_base::stack_trace_request, this, _1), true); register_request_handler("variables", std::bind(&xdebugger_base::variables_request, this, _1), true); register_event_handler("continued", std::bind(&xdebugger_base::continued_event, this, _1)); register_event_handler("stopped", std::bind(&xdebugger_base::stopped_event, this, _1)); } bool xdebugger_base::is_started() const { return m_is_started; } std::function xdebugger_base::get_event_callback() { return std::bind(&xdebugger_base::handle_event, this, _1); } /********************* * Requests handling * *********************/ void xdebugger_base::register_request_handler(const std::string& command, const request_handler_t& handler, bool require_started) { request_handler_map_t& m = require_started ? m_started_handler : m_request_handler; m[command] = handler; } nl::json xdebugger_base::debug_info_request(const nl::json& message) { nl::json breakpoint_list = nl::json::array(); if(m_is_started) { for(auto it = m_breakpoint_list.cbegin(); it != m_breakpoint_list.cend(); ++it) { breakpoint_list.push_back({{"source", it->first}, {"breakpoints", it->second}}); } } xdebugger_info info = get_debugger_info(); std::lock_guard lock(m_stopped_mutex); nl::json reply = { {"type", "response"}, {"request_seq", message["seq"]}, {"success", true}, {"command", message["command"]}, {"body", { {"isStarted", m_is_started}, {"hashMethod", "Murmur2"}, {"hashSeed", info.m_hash_seed}, {"tmpFilePrefix", info.m_tmp_file_prefix}, {"tmpFileSuffix", info.m_tmp_file_suffix}, {"breakpoints", breakpoint_list}, {"stoppedThreads", m_stopped_threads}, {"richRendering", info.m_rich_rendering}, {"exceptionPaths", info.m_exception_paths} }} }; return reply; } nl::json xdebugger_base::dump_cell_request(const nl::json& message) { std::string code; try { code = message["arguments"]["code"].get(); } catch(nl::json::type_error& e) { std::clog << e.what() << std::endl; } catch(...) { std::clog << "XDEBUGGER: Unknown issue" << std::endl; } std::string next_file_name = get_cell_temporary_file(code); std::clog << "XDEBUGGER: dumped " << next_file_name << std::endl; std::fstream fs(next_file_name, std::ios::in); if(!fs.is_open()) { fs.clear(); fs.open(next_file_name, std::ios::out); fs << code; } nl::json reply = { {"type", "response"}, {"request_seq", message["seq"]}, {"success", true}, {"command", message["command"]}, {"body", { {"sourcePath", next_file_name} }} }; return reply; } nl::json xdebugger_base::set_breakpoints_request(const nl::json& message) { std::string source = message["arguments"]["source"]["path"].get(); m_breakpoint_list.erase(source); nl::json bp_json = message["arguments"]["breakpoints"]; std::vector bp_list(bp_json.begin(), bp_json.end()); m_breakpoint_list.insert(std::make_pair(std::move(source), std::move(bp_list))); nl::json breakpoint_reply = forward_message(message); return breakpoint_reply; } nl::json xdebugger_base::source_request(const nl::json& message) { std::string sourcePath; try { sourcePath = message["arguments"]["source"]["path"].get(); } catch(nl::json::type_error& e) { std::clog << e.what() << std::endl; } catch(...) { std::clog << "XDEBUGGER: Unknown issue" << std::endl; } std::ifstream ifs(sourcePath, std::ios::in); if(!ifs.is_open()) { nl::json reply = { {"type", "response"}, {"request_seq", message["seq"]}, {"success", false}, {"command", message["command"]}, {"message", "source unavailable"}, {"body", {{}}} }; return reply; } std::string content((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); nl::json reply = { {"type", "response"}, {"request_seq", message["seq"]}, {"success", true}, {"command", message["command"]}, {"body", { {"content", content} }} }; return reply; } nl::json xdebugger_base::stack_trace_request(const nl::json& message) { nl::json reply = forward_message(message); size_t size = reply["body"]["stackFrames"].size(); for(size_t i = 0; i < size; ++i) { if(reply["body"]["stackFrames"][i]["source"]["path"] == "") { reply["body"]["stackFrames"].erase(i); break; } } #ifdef WIN32 size = reply["body"]["stackFrames"].size(); for(size_t i = 0; i < size; ++i) { std::string path = reply["body"]["stackFrames"][i]["source"]["path"]; std::replace(path.begin(), path.end(), '\\', '/'); reply["body"]["stackFrames"][i]["source"]["path"] = path; } #endif return reply; } nl::json xdebugger_base::variables_request(const nl::json& message) { return variables_request_impl(message); } nl::json xdebugger_base::forward_message(const nl::json& message) { std::string content = message.dump(); size_t content_length = content.length(); std::string buffer = xdap_tcp_client::HEADER + std::to_string(content_length) + xdap_tcp_client::SEPARATOR + content; zmq::message_t raw_message(buffer.c_str(), buffer.length()); m_request_socket.send(raw_message, zmq::send_flags::none); zmq::message_t raw_reply; (void)m_request_socket.recv(raw_reply); return nl::json::parse(std::string(raw_reply.data(), raw_reply.size())); } /******************* * Events handling * *******************/ void xdebugger_base::register_event_handler(const std::string& event, const event_handler_t& handler) { m_event_handler[event] = handler; } void xdebugger_base::continued_event(const nl::json& message) { std::lock_guard lock(m_stopped_mutex); if (message["body"]["allThreadsContinued"]) { m_stopped_threads.clear(); } else { int id = message["body"]["threadId"]; m_stopped_threads.erase(id); } } void xdebugger_base::stopped_event(const nl::json& message) { std::lock_guard lock(m_stopped_mutex); if (message["body"]["allThreadsStopped"]) { for (auto& id: message["body"]["threadList"]) { m_stopped_threads.insert(id.get()); } } else { int id = message["body"]["threadId"]; m_stopped_threads.insert(id); } } const std::set& xdebugger_base::get_stopped_threads() const { return m_stopped_threads; } nl::json xdebugger_base::variables_request_impl(const nl::json& message) { nl::json reply = forward_message(message); auto start_it = message["arguments"].find("start"); auto count_it = message["arguments"].find("count"); auto end_it = message["arguments"].end(); if(start_it != end_it || count_it != end_it) { int start = start_it != end_it ? start_it->get() : 0; int count = count_it != end_it ? count_it->get() : 0; if(start != 0 || count != 0) { int end = count == 0 ? reply["body"]["variables"].size() : start + count; nl::json old_variables_list = reply["body"]["variables"]; reply["body"].erase("variables"); nl::json variables_list; for(int i = start; i < end; ++i) { variables_list.push_back(old_variables_list.at(i)); } reply["body"]["variables"] = variables_list; } } return reply; } /************************** * Private implementation * **************************/ void xdebugger_base::handle_event(const nl::json& message) { std::string event = message["event"]; auto it = m_event_handler.find(event); if (it != m_event_handler.end()) { (it->second)(message); } } nl::json xdebugger_base::process_request_impl(const nl::json& header, const nl::json& message) { nl::json reply = nl::json::object(); if(message["command"] == "initialize") { if(m_is_started) { std::clog << "XDEBUGGER: the debugger has already started" << std::endl; } else { m_is_started = start(m_header_socket, m_request_socket); if (m_is_started) { std::clog << "XDEBUGGER: the debugger has started" << std::endl; } else { reply = { {"command", "initialize"}, {"request_seq", message["seq"]}, {"seq", 3}, {"success", false}, {"type", "response"} }; } } } auto it = m_request_handler.find(message["command"]); if (it != m_request_handler.end()) { reply = (it->second)(message); } else if (m_is_started) { std::string header_buffer = header.dump(); zmq::message_t raw_header(header_buffer.c_str(), header_buffer.length()); m_header_socket.send(raw_header, zmq::send_flags::none); // client responds with ACK message (void)m_header_socket.recv(raw_header); auto it = m_started_handler.find(message["command"]); if (it != m_started_handler.end()) { reply = (it->second)(message); } else { reply = forward_message(message); } } if (message["command"] == "disconnect") { stop(m_header_socket, m_request_socket); m_breakpoint_list.clear(); m_stopped_threads.clear(); m_is_started = false; std::clog << "XDEBUGGER: the debugger has stopped" << std::endl; } return reply; } } xeus-zmq-1.1.1/src/xheartbeat.cpp000066400000000000000000000041301450330156100167210ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include "zmq_addon.hpp" #include "xeus-zmq/xmiddleware.hpp" #include "xheartbeat.hpp" namespace xeus { xheartbeat::xheartbeat(zmq::context_t& context, const std::string& transport, const std::string& ip, const std::string& port) : m_heartbeat(context, zmq::socket_type::router) , m_controller(context, zmq::socket_type::rep) { init_socket(m_heartbeat, transport, ip, port); init_socket(m_controller, get_controller_end_point("heartbeat")); } xheartbeat::~xheartbeat() { } std::string xheartbeat::get_port() const { return get_socket_port(m_heartbeat); } void xheartbeat::run() { zmq::pollitem_t items[] = { { m_heartbeat, 0, ZMQ_POLLIN, 0 }, { m_controller, 0, ZMQ_POLLIN, 0 } }; while (true) { zmq::poll(&items[0], 2, std::chrono::milliseconds(-1)); if (items[0].revents & ZMQ_POLLIN) { zmq::multipart_t wire_msg; wire_msg.recv(m_heartbeat); wire_msg.send(m_heartbeat); } if (items[1].revents & ZMQ_POLLIN) { // stop message zmq::multipart_t wire_msg; wire_msg.recv(m_controller); wire_msg.send(m_controller); break; } } } } xeus-zmq-1.1.1/src/xheartbeat.hpp000066400000000000000000000021601450330156100167270ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_HEARTBEAT_HPP #define XEUS_HEARTBEAT_HPP #include #include "zmq.hpp" namespace xeus { class xheartbeat { public: xheartbeat(zmq::context_t& context, const std::string& transport, const std::string& ip, const std::string& port); ~xheartbeat(); std::string get_port() const; void run(); private: zmq::socket_t m_heartbeat; zmq::socket_t m_controller; }; } #endif xeus-zmq-1.1.1/src/xmiddleware.cpp000066400000000000000000000067561450330156100171170ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include "zmq_addon.hpp" #include "xeus-zmq/xmiddleware.hpp" namespace xeus { std::string get_controller_end_point(const std::string& channel) { return "inproc://" + channel + "_controller"; } std::string get_publisher_end_point() { return "inproc://publisher"; } std::string get_end_point(const std::string& transport, const std::string& ip, const std::string& port) { char sep = (transport == "tcp") ? ':' : '-'; return transport + "://" + ip + sep + port; } int get_socket_linger() { return 1000; } std::string find_free_port_impl(zmq::socket_t& socket, const std::string& transport, const std::string& ip, std::size_t max_tries, int start, int stop) { std::random_device r; std::default_random_engine generator(r()); std::uniform_int_distribution distribution(start, stop); std::size_t tries(0); std::string rd_port; do { rd_port = std::to_string(distribution(generator)); } while (++tries <= max_tries && zmq_bind(socket, get_end_point(transport, ip, rd_port).c_str()) != 0); if(tries > max_tries) { rd_port = ""; } return rd_port; } void init_socket(zmq::socket_t& socket, const std::string& transport, const std::string& ip, const std::string& port) { socket.set(zmq::sockopt::linger, get_socket_linger()); if (!port.empty()) { socket.bind(get_end_point(transport, ip, port)); } else { find_free_port_impl(socket, transport, ip, 100, 49152, 65536); } } void init_socket(zmq::socket_t& socket, const std::string& end_point) { socket.set(zmq::sockopt::linger, get_socket_linger()); socket.bind(end_point); } std::string get_socket_port(const zmq::socket_t& socket) { std::string end_point = socket.get(zmq::sockopt::last_endpoint, 32); return end_point.substr(end_point.find_last_of(":") + 1); } std::string find_free_port(std::size_t max_tries, int start, int stop) { static const std::string transport = "tcp"; static const std::string ip = "127.0.0.1"; zmq::context_t ctx; zmq::socket_t socket(ctx, zmq::socket_type::req); std::string port = find_free_port_impl(socket, transport, ip, max_tries, start, stop); socket.unbind(get_end_point(transport, ip, port)); return port; } } xeus-zmq-1.1.1/src/xpublisher.cpp000066400000000000000000000110241450330156100167570ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include "xeus-zmq/xmiddleware.hpp" #include "xpublisher.hpp" namespace xeus { xpublisher::xpublisher(zmq::context_t& context, std::function serialize_iopub_msg_cb, const std::string& transport, const std::string& ip, const std::string& port) : m_publisher(context, zmq::socket_type::xpub) , m_listener(context, zmq::socket_type::sub) , m_controller(context, zmq::socket_type::rep) , m_serialize_iopub_msg_cb(std::move(serialize_iopub_msg_cb)) { init_socket(m_publisher, transport, ip, port); // Set xpub_verbose option to 1 to pass all subscription messages (not only unique ones). m_publisher.set(zmq::sockopt::xpub_verbose, 1); m_listener.set(zmq::sockopt::subscribe, ""); m_listener.bind(get_publisher_end_point()); m_controller.set(zmq::sockopt::linger, get_socket_linger()); m_controller.bind(get_controller_end_point("publisher")); } xpublisher::~xpublisher() { } xpub_message xpublisher::create_xpub_message(const std::string& topic) { xmessage_base_data data; data.m_header = xeus::make_header("iopub_welcome", "", ""); data.m_content["subscription"] = topic; xpub_message p_msg("", std::move(data)); return p_msg; } std::string xpublisher::get_port() const { return get_socket_port(m_publisher); } void xpublisher::run() { zmq::pollitem_t items[] = { { m_listener, 0, ZMQ_POLLIN, 0 }, { m_controller, 0, ZMQ_POLLIN, 0 }, { m_publisher, 0, ZMQ_POLLIN, 0 } }; while (true) { zmq::poll(&items[0], 3, std::chrono::milliseconds(-1)); if (items[0].revents & ZMQ_POLLIN) { zmq::multipart_t wire_msg; wire_msg.recv(m_listener); wire_msg.send(m_publisher); } if (items[1].revents & ZMQ_POLLIN) { // stop message zmq::multipart_t wire_msg; wire_msg.recv(m_controller); wire_msg.send(m_controller); break; } if (items[2].revents & ZMQ_POLLIN) { // Received event: Single frame // Either `1{subscription-topic}` for subscription // or `0{subscription-topic}` for unsubscription zmq::multipart_t wire_msg; wire_msg.recv(m_publisher); // Received event should be a single frame if (wire_msg.size() != 1) { throw std::runtime_error("ERROR: Received message on XPUB is not a single frame"); } zmq::message_t frame = wire_msg.pop(); // Event is one byte 0 = unsub or 1 = sub, followed by topic uint8_t *event = (uint8_t *)frame.data(); // If subscription (unsubscription is ignored) if (event[0] == 1) { std::string topic((char *)(event + 1), frame.size() - 1); if (m_serialize_iopub_msg_cb) { // Construct the `iopub_welcome` message xpub_message p_msg = create_xpub_message(topic); zmq::multipart_t iopub_welcome_wire_msg = m_serialize_iopub_msg_cb(std::move(p_msg)); // Send the `iopub_welcome` message iopub_welcome_wire_msg.send(m_publisher); } else { throw std::runtime_error("ERROR: IOPUB serialization callback not set"); } } } } } } xeus-zmq-1.1.1/src/xpublisher.hpp000066400000000000000000000027221450330156100167710ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_PUBLISHER_HPP #define XEUS_PUBLISHER_HPP #include #include #include "zmq.hpp" #include "zmq_addon.hpp" #include "xeus/xmessage.hpp" namespace xeus { class xpublisher { public: xpublisher(zmq::context_t& context, std::function serialize_iopub_msg_cb, const std::string& transport, const std::string& ip, const std::string& port); ~xpublisher(); std::string get_port() const; void run(); private: xpub_message create_xpub_message(const std::string& topic); zmq::socket_t m_publisher; zmq::socket_t m_listener; zmq::socket_t m_controller; std::function m_serialize_iopub_msg_cb; }; } #endif xeus-zmq-1.1.1/src/xserver_control_main.cpp000066400000000000000000000036101450330156100210360ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include #include "zmq_addon.hpp" #include "xeus/xguid.hpp" #include "xeus-zmq/xserver_control_main.hpp" #include "xeus-zmq/xmiddleware.hpp" #include "xcontrol.hpp" namespace xeus { xserver_control_main::xserver_control_main(zmq::context_t& context, const xconfiguration& config, nl::json::error_handler_t eh) : xserver_zmq_split(context, config, eh) { } xserver_control_main::~xserver_control_main() { } void xserver_control_main::start_server(zmq::multipart_t& wire_msg) { xserver_zmq_split::start_publisher_thread(); xserver_zmq_split::start_heartbeat_thread(); xserver_zmq_split::start_shell_thread(); xserver_zmq_split::get_controller().publish(wire_msg); xserver_zmq_split::get_controller().run(); } std::unique_ptr make_xserver_control_main(xcontext& context, const xconfiguration& config, nl::json::error_handler_t eh) { return std::make_unique(context.get_wrapped_context(), config, eh); } } xeus-zmq-1.1.1/src/xserver_shell_main.cpp000066400000000000000000000035421450330156100204710ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include #include "zmq_addon.hpp" #include "xeus/xguid.hpp" #include "xeus-zmq/xserver_shell_main.hpp" #include "xeus-zmq/xmiddleware.hpp" #include "xshell.hpp" namespace xeus { xserver_shell_main::xserver_shell_main(zmq::context_t& context, const xconfiguration& config, nl::json::error_handler_t eh) : xserver_zmq_split(context, config, eh) { } xserver_shell_main::~xserver_shell_main() { } void xserver_shell_main::start_server(zmq::multipart_t& wire_msg) { xserver_zmq_split::start_publisher_thread(); xserver_zmq_split::start_heartbeat_thread(); xserver_zmq_split::start_control_thread(); xserver_zmq_split::get_shell().publish(wire_msg); xserver_zmq_split::get_shell().run(); } std::unique_ptr make_xserver_shell_main(xcontext& context, const xconfiguration& config, nl::json::error_handler_t eh) { return std::make_unique(context.get_wrapped_context(), config, eh); } } xeus-zmq-1.1.1/src/xserver_zmq.cpp000066400000000000000000000174341450330156100171720ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include "xeus/xguid.hpp" #include "xeus-zmq/xauthentication.hpp" #include "xeus-zmq/xserver_zmq.hpp" #include "xeus-zmq/xmiddleware.hpp" #include "xeus-zmq/xzmq_serializer.hpp" #include "xpublisher.hpp" #include "xheartbeat.hpp" #include "xtrivial_messenger.hpp" namespace xeus { xserver_zmq::xserver_zmq(zmq::context_t& context, const xconfiguration& config, nl::json::error_handler_t eh) : m_shell(context, zmq::socket_type::router) , m_controller(context, zmq::socket_type::router) , m_stdin(context, zmq::socket_type::router) , m_publisher_pub(context, zmq::socket_type::pub) , m_publisher_controller(context, zmq::socket_type::req) , m_heartbeat_controller(context, zmq::socket_type::req) , p_auth(make_xauthentication(config.m_signature_scheme, config.m_key)) , p_publisher(new xpublisher(context, std::bind(&xserver_zmq::serialize_iopub, this, std::placeholders::_1), config.m_transport, config.m_ip, config.m_iopub_port)) , p_heartbeat(new xheartbeat(context, config.m_transport, config.m_ip, config.m_hb_port)) , m_iopub_thread() , m_hb_thread() , p_messenger(new xtrivial_messenger(this)) , m_error_handler(eh) , m_request_stop(false) { init_socket(m_shell, config.m_transport, config.m_ip, config.m_shell_port); init_socket(m_controller, config.m_transport, config.m_ip, config.m_control_port); init_socket(m_stdin, config.m_transport, config.m_ip, config.m_stdin_port); m_publisher_pub.set(zmq::sockopt::linger, get_socket_linger()); m_publisher_pub.connect(get_publisher_end_point()); m_publisher_controller.set(zmq::sockopt::linger, get_socket_linger()); m_publisher_controller.connect(get_controller_end_point("publisher")); m_heartbeat_controller.set(zmq::sockopt::linger, get_socket_linger()); m_heartbeat_controller.connect(get_controller_end_point("heartbeat")); } // Has to be in the cpp because incomplete // types are used in unique_ptr in the header xserver_zmq::~xserver_zmq() = default; xcontrol_messenger& xserver_zmq::get_control_messenger_impl() { return *p_messenger; } void xserver_zmq::send_shell_impl(xmessage msg) { zmq::multipart_t wire_msg = xzmq_serializer::serialize(std::move(msg), *p_auth, m_error_handler); wire_msg.send(m_shell); } void xserver_zmq::send_control_impl(xmessage msg) { zmq::multipart_t wire_msg = xzmq_serializer::serialize(std::move(msg), *p_auth, m_error_handler); wire_msg.send(m_controller); } void xserver_zmq::send_stdin_impl(xmessage msg) { zmq::multipart_t wire_msg = xzmq_serializer::serialize(std::move(msg), *p_auth, m_error_handler); wire_msg.send(m_stdin); zmq::multipart_t wire_reply; // Block until a response to the input request is received. wire_reply.recv(m_stdin); try { xmessage reply = xzmq_serializer::deserialize(wire_reply, *p_auth); xserver::notify_stdin_listener(std::move(reply)); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } } void xserver_zmq::publish_impl(xpub_message msg, channel) { zmq::multipart_t wire_msg = xzmq_serializer::serialize_iopub(std::move(msg), *p_auth, m_error_handler); wire_msg.send(m_publisher_pub); } void xserver_zmq::start_impl(xpub_message message) { start_publisher_thread(); start_heartbeat_thread(); m_request_stop = false; publish(std::move(message), channel::SHELL); while (!m_request_stop) { poll(-1); } stop_channels(); } void xserver_zmq::start_publisher_thread() { m_iopub_thread = std::move(xthread(&xpublisher::run, p_publisher.get())); } void xserver_zmq::start_heartbeat_thread() { m_hb_thread = std::move(xthread(&xheartbeat::run, p_heartbeat.get())); } void xserver_zmq::poll(long timeout) { zmq::pollitem_t items[] = { { m_controller, 0, ZMQ_POLLIN, 0 }, { m_shell, 0, ZMQ_POLLIN, 0 } }; zmq::poll(&items[0], 2, std::chrono::milliseconds(timeout)); try { if (items[0].revents & ZMQ_POLLIN) { zmq::multipart_t wire_msg; wire_msg.recv(m_controller); xmessage msg = xzmq_serializer::deserialize(wire_msg, *p_auth); xserver::notify_control_listener(std::move(msg)); } if (!m_request_stop && (items[1].revents & ZMQ_POLLIN)) { zmq::multipart_t wire_msg; wire_msg.recv(m_shell); xmessage msg = xzmq_serializer::deserialize(wire_msg, *p_auth); xserver::notify_shell_listener(std::move(msg)); } } catch (std::exception& e) { std::cerr << e.what() << std::endl; } } void xserver_zmq::abort_queue_impl(const listener& l, long polling_interval) { while (true) { zmq::multipart_t wire_msg; bool msg = wire_msg.recv(m_shell, ZMQ_NOBLOCK); if (!msg) { return; } try { xmessage msg = xzmq_serializer::deserialize(wire_msg, *p_auth); l(std::move(msg)); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } std::this_thread::sleep_for(std::chrono::milliseconds(polling_interval)); } } void xserver_zmq::stop_impl() { m_request_stop = true; } void xserver_zmq::update_config_impl(xconfiguration& config) const { config.m_control_port = get_socket_port(m_controller); config.m_shell_port = get_socket_port(m_shell); config.m_stdin_port = get_socket_port(m_stdin); config.m_iopub_port = p_publisher->get_port(); config.m_hb_port = p_heartbeat->get_port(); } void xserver_zmq::stop_channels() { zmq::message_t stop_msg("stop", 4); zmq::message_t response; // Wait for publisher answer m_publisher_controller.send(stop_msg, zmq::send_flags::none); (void)m_publisher_controller.recv(response); // Wait for heartbeat answer m_heartbeat_controller.send(stop_msg, zmq::send_flags::none); (void)m_heartbeat_controller.recv(response); } zmq::multipart_t xserver_zmq::serialize_iopub(xpub_message&& msg) { return xzmq_serializer::serialize_iopub(std::move(msg), *p_auth, m_error_handler); } std::unique_ptr make_xserver_zmq(xcontext& context, const xconfiguration& config, nl::json::error_handler_t eh) { return std::make_unique(context.get_wrapped_context(), config, eh); } } xeus-zmq-1.1.1/src/xserver_zmq_split.cpp000066400000000000000000000133121450330156100203740ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include "zmq_addon.hpp" #include "xeus/xguid.hpp" #include "xeus-zmq/xauthentication.hpp" #include "xeus-zmq/xserver_zmq_split.hpp" #include "xeus-zmq/xmiddleware.hpp" #include "xeus-zmq/xzmq_serializer.hpp" #include "xcontrol.hpp" #include "xheartbeat.hpp" #include "xpublisher.hpp" #include "xshell.hpp" #include "xzmq_messenger.hpp" namespace xeus { xserver_zmq_split::xserver_zmq_split(zmq::context_t& context, const xconfiguration& config, nl::json::error_handler_t eh) : p_auth(make_xauthentication(config.m_signature_scheme, config.m_key)) , p_controller(new xcontrol(context, config.m_transport, config.m_ip ,config.m_control_port, this)) , p_heartbeat(new xheartbeat(context, config.m_transport, config.m_ip, config.m_hb_port)) , p_publisher(new xpublisher(context, std::bind(&xserver_zmq_split::serialize_iopub, this, std::placeholders::_1), config.m_transport, config.m_ip, config.m_iopub_port)) , p_shell(new xshell(context, config.m_transport, config.m_ip ,config.m_shell_port, config.m_stdin_port, this)) , m_control_thread() , m_hb_thread() , m_iopub_thread() , m_shell_thread() , m_error_handler(eh) , m_control_stopped(false) { p_controller->connect_messenger(); } // Has to be in the cpp because incomplete // types are used in unique_ptr in the header xserver_zmq_split::~xserver_zmq_split() = default; zmq::multipart_t xserver_zmq_split::notify_internal_listener(zmq::multipart_t& wire_msg) { nl::json msg = nl::json::parse(wire_msg.popstr()); nl::json reply = xserver::notify_internal_listener(msg); return zmq::multipart_t(reply.dump(-1, ' ', false, m_error_handler)); } void xserver_zmq_split::notify_control_stopped() { m_control_stopped = true; } xmessage xserver_zmq_split::deserialize(zmq::multipart_t& wire_msg) const { return xzmq_serializer::deserialize(wire_msg, *p_auth); } xcontrol_messenger& xserver_zmq_split::get_control_messenger_impl() { return p_controller->get_messenger(); } void xserver_zmq_split::send_shell_impl(xmessage msg) { zmq::multipart_t wire_msg = xzmq_serializer::serialize(std::move(msg), *p_auth, m_error_handler); p_shell->send_shell(wire_msg); } void xserver_zmq_split::send_control_impl(xmessage msg) { zmq::multipart_t wire_msg = xzmq_serializer::serialize(std::move(msg), *p_auth, m_error_handler); p_controller->send_control(wire_msg); } void xserver_zmq_split::send_stdin_impl(xmessage msg) { zmq::multipart_t wire_msg = xzmq_serializer::serialize(std::move(msg), *p_auth, m_error_handler); p_shell->send_stdin(wire_msg); } void xserver_zmq_split::publish_impl(xpub_message msg, channel c) { zmq::multipart_t wire_msg = xzmq_serializer::serialize_iopub(std::move(msg), *p_auth, m_error_handler); if(c == channel::SHELL) { p_shell->publish(wire_msg); } else { p_controller->publish(wire_msg); } } void xserver_zmq_split::start_impl(xpub_message msg) { zmq::multipart_t wire_msg = xzmq_serializer::serialize_iopub(std::move(msg), *p_auth, m_error_handler); start_server(wire_msg); } void xserver_zmq_split::abort_queue_impl(const listener& l, long polling_interval) { p_shell->abort_queue(l, polling_interval); } void xserver_zmq_split::stop_impl() { p_controller->stop(); } void xserver_zmq_split::update_config_impl(xconfiguration& config) const { config.m_control_port = p_controller->get_port(); config.m_shell_port = p_shell->get_shell_port(); config.m_stdin_port = p_shell->get_stdin_port(); config.m_iopub_port = p_publisher->get_port(); config.m_hb_port = p_heartbeat->get_port(); } void xserver_zmq_split::start_control_thread() { m_control_thread = std::move(xthread(&xcontrol::run, p_controller.get())); } void xserver_zmq_split::start_heartbeat_thread() { m_hb_thread = std::move(xthread(&xheartbeat::run, p_heartbeat.get())); } void xserver_zmq_split::start_publisher_thread() { m_iopub_thread = std::move(xthread(&xpublisher::run, p_publisher.get())); } void xserver_zmq_split::start_shell_thread() { m_shell_thread = std::move(xthread(&xshell::run, p_shell.get())); } xcontrol& xserver_zmq_split::get_controller() { return *p_controller; } xshell& xserver_zmq_split::get_shell() { return *p_shell; } bool xserver_zmq_split::is_control_stopped() const { return m_control_stopped; } zmq::multipart_t xserver_zmq_split::serialize_iopub(xpub_message&& msg) { return xzmq_serializer::serialize_iopub(std::move(msg), *p_auth, m_error_handler); } } xeus-zmq-1.1.1/src/xshell.cpp000066400000000000000000000111501450330156100160710ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include #include "xeus-zmq/xmiddleware.hpp" #include "xeus-zmq/xserver_zmq_split.hpp" #include "xshell.hpp" namespace xeus { xshell::xshell(zmq::context_t& context, const std::string& transport, const std::string& ip, const std::string& shell_port, const std::string& stdin_port, xserver_zmq_split* server) : m_shell(context, zmq::socket_type::router) , m_stdin(context, zmq::socket_type::router) , m_publisher_pub(context, zmq::socket_type::pub) , m_controller(context, zmq::socket_type::rep) , p_server(server) { init_socket(m_shell, transport, ip, shell_port); init_socket(m_stdin, transport, ip, stdin_port); m_publisher_pub.set(zmq::sockopt::linger, get_socket_linger()); m_publisher_pub.connect(get_publisher_end_point()); m_controller.set(zmq::sockopt::linger, get_socket_linger()); m_controller.bind(get_controller_end_point("shell")); } xshell::~xshell() { } std::string xshell::get_shell_port() const { return get_socket_port(m_shell); } std::string xshell::get_stdin_port() const { return get_socket_port(m_stdin); } void xshell::run() { zmq::pollitem_t items[] = { { m_shell, 0, ZMQ_POLLIN, 0 }, { m_controller, 0, ZMQ_POLLIN, 0 } }; while (true) { zmq::poll(&items[0], 2, std::chrono::milliseconds(-1)); if (items[0].revents & ZMQ_POLLIN) { zmq::multipart_t wire_msg; wire_msg.recv(m_shell); try { xmessage msg = p_server->deserialize(wire_msg); p_server->notify_shell_listener(std::move(msg)); } catch(std::exception& e) { std::cerr << e.what() << std::endl; } } if (items[1].revents & ZMQ_POLLIN) { // stop message zmq::multipart_t wire_msg; wire_msg.recv(m_controller); std::string msg = wire_msg.peekstr(0); if(msg == "stop") { wire_msg.send(m_controller); break; } else { zmq::multipart_t wire_reply = p_server->notify_internal_listener(wire_msg); wire_reply.send(m_controller); } } } } void xshell::send_shell(zmq::multipart_t& message) { message.send(m_shell); } void xshell::send_stdin(zmq::multipart_t& message) { message.send(m_stdin); zmq::multipart_t wire_msg; wire_msg.recv(m_stdin); try { xmessage msg = p_server->deserialize(wire_msg); p_server->notify_stdin_listener(std::move(msg)); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } } void xshell::publish(zmq::multipart_t& message) { message.send(m_publisher_pub); } void xshell::abort_queue(const listener& l, long polling_interval) { while (true) { zmq::multipart_t wire_msg; bool received = wire_msg.recv(m_shell, ZMQ_NOBLOCK); if (!received) { return; } try { xmessage msg = p_server->deserialize(wire_msg); l(std::move(msg)); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } std::this_thread::sleep_for(std::chrono::milliseconds(polling_interval)); } } void xshell::reply_to_controller(zmq::multipart_t& message) { message.send(m_controller); } } xeus-zmq-1.1.1/src/xshell.hpp000066400000000000000000000033621450330156100161040ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_SHELL_HPP #define XEUS_SHELL_HPP #include #include "zmq.hpp" #include "zmq_addon.hpp" #include "xeus/xmessage.hpp" namespace xeus { class xserver_zmq_split; class xshell { public: using listener = std::function; xshell(zmq::context_t& context, const std::string& transport, const std::string& ip, const std::string& shell_port, const std::string& sdtin_port, xserver_zmq_split* server); ~xshell(); std::string get_shell_port() const; std::string get_stdin_port() const; void run(); void send_shell(zmq::multipart_t& message); void send_stdin(zmq::multipart_t& message); void publish(zmq::multipart_t& message); void abort_queue(const listener& l, long polling_interval); void reply_to_controller(zmq::multipart_t& message); private: zmq::socket_t m_shell; zmq::socket_t m_stdin; zmq::socket_t m_publisher_pub; zmq::socket_t m_controller; xserver_zmq_split* p_server; }; } #endif xeus-zmq-1.1.1/src/xtrivial_messenger.cpp000066400000000000000000000020671450330156100205130ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include "nlohmann/json.hpp" #include "xeus-zmq/xserver_zmq.hpp" #include "xtrivial_messenger.hpp" namespace xeus { xtrivial_messenger::xtrivial_messenger(xserver_zmq* server) : p_server(server) { } xtrivial_messenger::~xtrivial_messenger() { p_server = nullptr; } nl::json xtrivial_messenger::send_to_shell_impl(const nl::json& message) { return p_server->notify_internal_listener(message); } } xeus-zmq-1.1.1/src/xtrivial_messenger.hpp000066400000000000000000000022301450330156100205100ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_TRIVIAL_MESSENGER_HPP #define XEUS_TRIVIAL_MESSENGER_HPP #include "nlohmann/json.hpp" #include "xeus/xcontrol_messenger.hpp" #include "xeus-zmq/xeus-zmq.hpp" namespace nl = nlohmann; namespace xeus { class xserver_zmq; class xtrivial_messenger : public xcontrol_messenger { public: explicit xtrivial_messenger(xserver_zmq* server); virtual ~xtrivial_messenger (); private: nl::json send_to_shell_impl(const nl::json& message) override; xserver_zmq* p_server; }; } #endif xeus-zmq-1.1.1/src/xzmq_context.cpp000066400000000000000000000003321450330156100173350ustar00rootroot00000000000000#include "zmq.hpp" #include "xeus-zmq/xzmq_context.hpp" namespace xeus { std::unique_ptr make_zmq_context() { return std::unique_ptr(new xcontext_impl()); } } xeus-zmq-1.1.1/src/xzmq_messenger.cpp000066400000000000000000000047051450330156100176510ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include "nlohmann/json.hpp" #include "xeus-zmq/xmiddleware.hpp" #include "xzmq_messenger.hpp" namespace nl = nlohmann; namespace xeus { xzmq_messenger::xzmq_messenger(zmq::context_t& context) : m_shell_controller(context, zmq::socket_type::req) , m_publisher_controller(context, zmq::socket_type::req) , m_heartbeat_controller(context, zmq::socket_type::req) { } xzmq_messenger::~xzmq_messenger() { } void xzmq_messenger::connect() { m_shell_controller.set(zmq::sockopt::linger, get_socket_linger()); m_shell_controller.connect(get_controller_end_point("shell")); m_publisher_controller.set(zmq::sockopt::linger, get_socket_linger()); m_publisher_controller.connect(get_controller_end_point("publisher")); m_heartbeat_controller.set(zmq::sockopt::linger, get_socket_linger()); m_heartbeat_controller.connect(get_controller_end_point("heartbeat")); } void xzmq_messenger::stop_channels() { zmq::message_t stop_msg("stop", 4); zmq::message_t response; // Wait for shell answer m_shell_controller.send(stop_msg, zmq::send_flags::none); (void)m_shell_controller.recv(response); // Wait for publisher answer m_publisher_controller.send(stop_msg, zmq::send_flags::none); (void)m_publisher_controller.recv(response); // Wait for heartbeat answer m_heartbeat_controller.send(stop_msg, zmq::send_flags::none); (void)m_heartbeat_controller.recv(response); } nl::json xzmq_messenger::send_to_shell_impl(const nl::json& message) { zmq::multipart_t wire_msg(message.dump()); wire_msg.send(m_shell_controller); zmq::multipart_t wire_reply; wire_reply.recv(m_shell_controller); return nl::json::parse(wire_reply.popstr()); } } xeus-zmq-1.1.1/src/xzmq_messenger.hpp000066400000000000000000000024601450330156100176520ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_ZMQ_MESSENGER_HPP #define XEUS_ZMQ_MESSENGER_HPP #include "zmq.hpp" #include "zmq_addon.hpp" #include "nlohmann/json.hpp" #include "xeus/xcontrol_messenger.hpp" #include "xeus-zmq/xeus-zmq.hpp" namespace nl = nlohmann; namespace xeus { class xzmq_messenger : public xcontrol_messenger { public: explicit xzmq_messenger(zmq::context_t& context); virtual ~xzmq_messenger(); void connect(); void stop_channels(); private: nl::json send_to_shell_impl(const nl::json& message) override; zmq::socket_t m_shell_controller; zmq::socket_t m_publisher_controller; zmq::socket_t m_heartbeat_controller; }; } #endif xeus-zmq-1.1.1/src/xzmq_serializer.cpp000066400000000000000000000172461450330156100200360ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou * * Copyright (c) 2016, QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include "xeus-zmq/xzmq_serializer.hpp" namespace xeus { namespace { const std::string DELIMITER = ""; bool is_delimiter(zmq::message_t& frame) { std::size_t frame_size = frame.size(); if (frame_size != DELIMITER.size()) { return false; } std::string check(frame.data(), frame_size); return check == DELIMITER; } xraw_buffer make_raw_buffer(zmq::message_t& msg) { return xraw_buffer(msg.data(), msg.size()); } void parse_zmq_message(const zmq::message_t& msg, nl::json& json) { const char* buf = msg.data(); json = nl::json::parse(buf, buf + msg.size()); } zmq::message_t write_zmq_message(const nl::json& json, nl::json::error_handler_t error_handler) { std::string buffer = json.dump(-1, ' ', false, error_handler); return zmq::message_t(buffer.c_str(), buffer.size()); } void serialize_message_base(xmessage_base&& msg, const xauthentication& auth, nl::json::error_handler_t error_handler, zmq::multipart_t& wire_msg) { zmq::message_t header = write_zmq_message(msg.header(), error_handler); zmq::message_t parent_header = write_zmq_message(msg.parent_header(), error_handler); zmq::message_t metadata = write_zmq_message(msg.metadata(), error_handler); zmq::message_t content = write_zmq_message(msg.content(), error_handler); std::string sig = auth.sign(make_raw_buffer(header), make_raw_buffer(parent_header), make_raw_buffer(metadata), make_raw_buffer(content)); zmq::message_t signature(sig.begin(), sig.end()); wire_msg.add(std::move(signature)); wire_msg.add(std::move(header)); wire_msg.add(std::move(parent_header)); wire_msg.add(std::move(metadata)); wire_msg.add(std::move(content)); // was not const and could only be called on rvalues. for (const binary_buffer& buffer : std::move(msg).buffers()) { wire_msg.add(zmq::message_t(buffer.data(), buffer.size())); } } xmessage_base_data deserialize_message_base(zmq::multipart_t& wire_msg, const xauthentication& auth) { zmq::message_t signature = wire_msg.pop(); zmq::message_t header = wire_msg.pop(); zmq::message_t parent_header = wire_msg.pop(); zmq::message_t metadata = wire_msg.pop(); zmq::message_t content = wire_msg.pop(); xmessage_base_data data; parse_zmq_message(header, data.m_header); parse_zmq_message(parent_header, data.m_parent_header); parse_zmq_message(metadata, data.m_metadata); parse_zmq_message(content, data.m_content); while (!wire_msg.empty()) { zmq::message_t msg = wire_msg.pop(); const char* buf = msg.data(); data.m_buffers.emplace_back(buf, buf + msg.size()); } // TODO: should we verify with buffers if (!auth.verify(make_raw_buffer(signature), make_raw_buffer(header), make_raw_buffer(parent_header), make_raw_buffer(metadata), make_raw_buffer(content))) { throw std::runtime_error("ERROR: Signatures don't match"); } return data; } void serialize_zmq_id(const xmessage& msg, zmq::multipart_t& wire_msg) { auto app = [&wire_msg](const std::string& uid) { wire_msg.add(zmq::message_t(uid.begin(), uid.end())); }; std::for_each(msg.identities().begin(), msg.identities().end(), app); wire_msg.add(zmq::message_t(DELIMITER.begin(), DELIMITER.end())); } xmessage::guid_list deserialize_zmq_id(zmq::multipart_t& wire_msg) { xmessage::guid_list zmq_id; zmq::message_t frame = wire_msg.pop(); // ZMQ identites while (!is_delimiter(frame) && wire_msg.size() != 0) { zmq_id.emplace_back(frame.data(), frame.size()); frame = wire_msg.pop(); } // if wire_msg is empty, that means frame doesn't contain if (wire_msg.size() == 0) { throw std::runtime_error("ERROR: Delimiter not present in message"); } return zmq_id; } void serialize_topic(const xpub_message& msg, zmq::multipart_t& wire_msg) { wire_msg.add(zmq::message_t(msg.topic().begin(), msg.topic().end())); wire_msg.add(zmq::message_t(DELIMITER.begin(), DELIMITER.end())); } std::string deserialize_topic(zmq::multipart_t& wire_msg) { zmq::message_t topic_msg = wire_msg.pop(); std::string topic = std::string(topic_msg.data(), topic_msg.size()); wire_msg.pop(); return topic; } } zmq::multipart_t xzmq_serializer::serialize(xmessage&& msg, const xauthentication& auth, nl::json::error_handler_t error_handler) { zmq::multipart_t wire_msg; serialize_zmq_id(msg, wire_msg); serialize_message_base(std::move(msg), auth, error_handler, wire_msg); return wire_msg; } xmessage xzmq_serializer::deserialize(zmq::multipart_t& wire_msg, const xauthentication& auth) { xmessage::guid_list zmq_id = deserialize_zmq_id(wire_msg); xmessage_base_data data = deserialize_message_base(wire_msg, auth); return xmessage(zmq_id, std::move(data)); } zmq::multipart_t xzmq_serializer::serialize_iopub(xpub_message&& msg, const xauthentication& auth, nl::json::error_handler_t error_handler) { zmq::multipart_t wire_msg; serialize_topic(msg, wire_msg); serialize_message_base(std::move(msg), auth, error_handler, wire_msg); return wire_msg; } xpub_message xzmq_serializer::deserialize_iopub(zmq::multipart_t& wire_msg, const xauthentication& auth) { std::string topic = deserialize_topic(wire_msg); xmessage_base_data data = deserialize_message_base(wire_msg, auth); return xpub_message(topic, std::move(data)); } } xeus-zmq-1.1.1/test/000077500000000000000000000000001450330156100142605ustar00rootroot00000000000000xeus-zmq-1.1.1/test/CMakeLists.txt000066400000000000000000000131041450330156100170170ustar00rootroot00000000000000############################################################################ # Copyright (c) 2016, Sylvain Corlay, Johan Mabille, Martin Renou # # Copyright (c) 2016, QuantStack # # # # Distributed under the terms of the BSD 3-Clause License. # # # # The full license is in the file LICENSE, distributed with this software. # ############################################################################ # Unit tests # ========== cmake_minimum_required(VERSION 3.1) if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) project(xeus-zmq-test) enable_testing() find_package(xeus-zmq REQUIRED CONFIG) find_package(nlohmann_json QUIET CONFIG) set(XEUS_ZMQ_TEST_DIR ${CMAKE_CURRENT_LIST_DIR}) endif () message(STATUS "Forcing tests build type to Release") set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) include(CheckCXXCompilerFlag) string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) if(nlohmann_json_FOUND) add_definitions(-DHAVE_NLOHMANN_JSON) endif() if(CMAKE_CXX_COMPILER_ID MATCHES Clang OR CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Intel) add_compile_options(-Wunused-parameter -Wextra -Wreorder -Wconversion -Wsign-conversion) CHECK_CXX_COMPILER_FLAG(-march=native HAS_MARCH_NATIVE) if (HAS_MARCH_NATIVE) add_compile_options(-march=native) endif() endif() if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) add_compile_options(/EHsc /MP /bigobj) set(CMAKE_EXE_LINKER_FLAGS /MANIFEST:NO) endif() find_package(doctest REQUIRED) find_package(Threads) find_program(PYTEST NAMES pytest-3 pytest py.test-3 py.test REQUIRED) if(nlohmann_json_FOUND) # Version up to 3.1.2 export the target `nlohmann_json` if(TARGET nlohmann_json) set(nlohmann_json_TARGET nlohmann_json) # Newer versions export the namespaced target `nlohmann_json::nlohmann_json` elseif(TARGET nlohmann_json::nlohmann_json) set(nlohmann_json_TARGET nlohmann_json::nlohmann_json) endif() endif() if (TARGET xeus-zmq) set(xeus-zmq_TARGET xeus-zmq) message("Found xeus-zmq shared library.") elseif (TARGET xeus-zmq-static) set(xeus-zmq_TARGET xeus-zmq-static) message("Found xeus-zmq static library.") endif () # Test_kernel tests # ================= set(TEST_KERNEL_SOURCES xmock_interpreter.cpp xmock_interpreter.hpp main.cpp) configure_file( "${XEUS_ZMQ_TEST_DIR}/test_kernel/kernel.json.in" "kernels/test_kernel/kernel.json" ) add_executable(test_kernel ${TEST_KERNEL_SOURCES}) target_link_libraries(test_kernel PRIVATE ${xeus-zmq_TARGET} Threads::Threads) target_compile_features(test_kernel PRIVATE cxx_std_11) set(CONNECTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/connection.json) configure_file( "${XEUS_ZMQ_TEST_DIR}/test_kernel.py" "${CMAKE_CURRENT_BINARY_DIR}/" COPYONLY) add_test(NAME test_kernel COMMAND ${PYTEST} test_kernel.py) set_tests_properties(test_kernel PROPERTIES ENVIRONMENT "JUPYTER_PATH=${CMAKE_CURRENT_BINARY_DIR}") # Test_kernel_control tests # ========================= set(TEST_KERNEL_SPLIT_SOURCES xmock_interpreter.cpp xmock_interpreter.hpp main_control.cpp) configure_file( "${XEUS_ZMQ_TEST_DIR}/test_kernel_control/kernel.json.in" "kernels/test_kernel_control/kernel.json" ) add_executable(test_kernel_control ${TEST_KERNEL_SPLIT_SOURCES}) target_link_libraries(test_kernel_control PRIVATE ${xeus-zmq_TARGET} Threads::Threads) target_compile_features(test_kernel_control PRIVATE cxx_std_11) set(CONNECTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/connection.json) configure_file( "${XEUS_ZMQ_TEST_DIR}/test_kernel_control.py" "${CMAKE_CURRENT_BINARY_DIR}/" COPYONLY) add_test(NAME test_kernel_control COMMAND ${PYTEST} test_kernel_control.py) set_tests_properties(test_kernel_control PROPERTIES ENVIRONMENT "JUPYTER_PATH=${CMAKE_CURRENT_BINARY_DIR}") # Test_kernel_shell tests # ======================= set(TEST_KERNEL_SPLIT_SOURCES xmock_interpreter.cpp xmock_interpreter.hpp main_shell.cpp) configure_file( "${XEUS_ZMQ_TEST_DIR}/test_kernel_shell/kernel.json.in" "kernels/test_kernel_shell/kernel.json" ) add_executable(test_kernel_shell ${TEST_KERNEL_SPLIT_SOURCES}) target_link_libraries(test_kernel_shell PRIVATE ${xeus-zmq_TARGET} Threads::Threads) target_compile_features(test_kernel_shell PRIVATE cxx_std_11) set(CONNECTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/connection.json) configure_file( "${XEUS_ZMQ_TEST_DIR}/test_kernel_shell.py" "${CMAKE_CURRENT_BINARY_DIR}/" COPYONLY) add_test(NAME test_kernel_shell COMMAND ${PYTEST} test_kernel_shell.py) set_tests_properties(test_kernel_shell PROPERTIES ENVIRONMENT "JUPYTER_PATH=${CMAKE_CURRENT_BINARY_DIR}") if (UNIX) # Test_kernel_ipc # =============== set(TEST_KERNEL_IPC_SOURCES xmock_interpreter.cpp xmock_interpreter.hpp main_ipc.cpp) add_executable(test_kernel_ipc ${TEST_KERNEL_IPC_SOURCES}) target_link_libraries(test_kernel_ipc PRIVATE ${xeus-zmq_TARGET} Threads::Threads) target_compile_features(test_kernel_ipc PRIVATE cxx_std_11) # Test_client_ipc # =============== set(TEST_CLIENT_IPC_SOURCES client_ipc.cpp) add_executable(test_client_ipc ${TEST_CLIENT_IPC_SOURCES}) target_link_libraries(test_client_ipc PRIVATE ${xeus-zmq_TARGET} Threads::Threads) target_compile_features(test_client_ipc PRIVATE cxx_std_11) endif (UNIX) xeus-zmq-1.1.1/test/client_ipc.cpp000066400000000000000000000035621450330156100171030ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille and Sylvain Corlay * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include "zmq_addon.hpp" #include "nlohmann/json.hpp" #include "xeus/xguid.hpp" #include "xeus/xmessage.hpp" #include "xeus-zmq/xauthentication.hpp" #include "xeus-zmq/xmiddleware.hpp" #include "xeus-zmq/xzmq_serializer.hpp" namespace nl = nlohmann; int main(int, char**) { zmq::context_t context; zmq::socket_t cli(context, zmq::socket_type::dealer); xeus::xguid socket_id = xeus::new_xguid(); //cli.set(ZMQ_IDENTITY, socket_id.c_str(), socket_id.size()); cli.set(zmq::sockopt::linger, xeus::get_socket_linger()); cli.connect(xeus::get_end_point("ipc", "localhost", "shell")); auto auth = xeus::make_xauthentication("none", ""); nl::json header = xeus::make_header("execute_request", "tester", "DAEDZFAEDE12"); std::string code = "std::cout << \"this is a test\" << std::endl;"; nl::json req = { { "code", code } }; xeus::xmessage msg( { socket_id}, header, code, nl::json::object(), nl::json::object(), xeus::buffer_sequence() ); auto wire_msg = xeus::xzmq_serializer::serialize(std::move(msg), *auth); wire_msg.send(cli); zmq::multipart_t resp_msg; resp_msg.recv(cli); auto resp = xeus::xzmq_serializer::deserialize(resp_msg, *auth); std::cout << resp.content().dump(4) << std::endl; return 0; } xeus-zmq-1.1.1/test/main.cpp000066400000000000000000000026441450330156100157160ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille and Sylvain Corlay * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include "xeus/xkernel.hpp" #include "xeus/xkernel_configuration.hpp" #include "xeus-zmq/xzmq_context.hpp" #include "xeus-zmq/xserver_zmq.hpp" #include "xmock_interpreter.hpp" int main(int argc, char* argv[]) { std::string file_name = (argc == 1) ? "connection.json" : argv[2]; xeus::xconfiguration config = xeus::load_configuration(file_name); auto context = xeus::make_zmq_context(); using interpreter_ptr = std::unique_ptr; interpreter_ptr interpreter = interpreter_ptr(new xeus::xmock_interpreter()); xeus::xkernel kernel(config, xeus::get_user_name(), std::move(context), std::move(interpreter), xeus::make_xserver_zmq); std::cout << "starting kernel" << std::endl; kernel.start(); return 0; } xeus-zmq-1.1.1/test/main_control.cpp000066400000000000000000000032341450330156100174520ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille and Sylvain Corlay * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include "xeus/xkernel.hpp" #include "xeus/xkernel_configuration.hpp" #include "xeus-zmq/xzmq_context.hpp" #include "xeus-zmq/xserver_control_main.hpp" #include "xmock_interpreter.hpp" int main(int argc, char* argv[]) { std::string file_name = (argc == 1) ? "connection.json" : argv[2]; xeus::xconfiguration config = xeus::load_configuration(file_name); using history_manager_ptr = std::unique_ptr; history_manager_ptr hist = xeus::make_in_memory_history_manager(); auto context = xeus::make_zmq_context(); using interpreter_ptr = std::unique_ptr; interpreter_ptr interpreter = interpreter_ptr(new xeus::xmock_interpreter()); xeus::xkernel kernel(config, xeus::get_user_name(), std::move(context), std::move(interpreter), xeus::make_xserver_control_main, std::move(hist), nullptr); std::cout << "starting kernel" << std::endl; kernel.start(); return 0; } xeus-zmq-1.1.1/test/main_ipc.cpp000066400000000000000000000032501450330156100165430ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille and Sylvain Corlay * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include #include "xeus/xkernel.hpp" #include "xeus/xkernel_configuration.hpp" #include "xeus-zmq/xzmq_context.hpp" #include "xeus-zmq/xserver_zmq.hpp" #include "xmock_interpreter.hpp" int main(int argc, char* argv[]) { using namespace std::chrono_literals; xeus::xconfiguration config; config.m_transport = "ipc"; config.m_ip = "localhost"; config.m_control_port = "control"; config.m_shell_port = "shell"; config.m_stdin_port = "stdin"; config.m_iopub_port = "iopub"; config.m_hb_port = "heartbeat"; config.m_signature_scheme = "none"; config.m_key = ""; auto context = xeus::make_zmq_context(); using interpreter_ptr = std::unique_ptr; interpreter_ptr interpreter = interpreter_ptr(new xeus::xmock_interpreter()); xeus::xkernel kernel(config, xeus::get_user_name(), std::move(context), std::move(interpreter), xeus::make_xserver_zmq); std::cout << "starting kernel" << std::endl; kernel.start(); return 0; } xeus-zmq-1.1.1/test/main_shell.cpp000066400000000000000000000032301450330156100170750ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille and Sylvain Corlay * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include #include "xeus/xkernel.hpp" #include "xeus/xkernel_configuration.hpp" #include "xeus-zmq/xzmq_context.hpp" #include "xeus-zmq/xserver_shell_main.hpp" #include "xmock_interpreter.hpp" int main(int argc, char* argv[]) { std::string file_name = (argc == 1) ? "connection.json" : argv[2]; xeus::xconfiguration config = xeus::load_configuration(file_name); using history_manager_ptr = std::unique_ptr; history_manager_ptr hist = xeus::make_in_memory_history_manager(); auto context = xeus::make_zmq_context(); using interpreter_ptr = std::unique_ptr; interpreter_ptr interpreter = interpreter_ptr(new xeus::xmock_interpreter()); xeus::xkernel kernel(config, xeus::get_user_name(), std::move(context), std::move(interpreter), xeus::make_xserver_shell_main, std::move(hist), nullptr); std::cout << "starting kernel" << std::endl; kernel.start(); return 0; } xeus-zmq-1.1.1/test/test_kernel.py000066400000000000000000000020751450330156100171550ustar00rootroot00000000000000import unittest import jupyter_kernel_test class XeusKernelTests(jupyter_kernel_test.KernelTests): kernel_name = "test_kernel" language_name = "cpp" code_hello_world = "hello, world" code_page_something = "?" code_execute_result = [ {'code': '6*7', 'result': '6*7'}, {'code': 'test', 'result': 'test'} ] completion_samples = [ {'text': 'a.', 'matches': ['a.test1', 'a.test2']} ] complete_code_samples = ["complete"] incomplete_code_samples = ["incomplete"] invalid_code_samples = ["invalid"] code_inspect_sample = "invalid" def test_xeus_stderr(self): reply, output_msgs = self.execute_helper(code='error') self.assertEqual(output_msgs[0]['msg_type'], 'stream') self.assertEqual(output_msgs[0]['content']['name'], 'stderr') self.assertEqual(output_msgs[0]['content']['text'], 'error') class XeusIopubWelcomeTests(jupyter_kernel_test.IopubWelcomeTests): kernel_name = "test_kernel" support_iopub_welcome = True if __name__ == '__main__': unittest.main() xeus-zmq-1.1.1/test/test_kernel/000077500000000000000000000000001450330156100165775ustar00rootroot00000000000000xeus-zmq-1.1.1/test/test_kernel/kernel.json.in000066400000000000000000000002541450330156100213600ustar00rootroot00000000000000{ "display_name": "test_kernel", "language" : "cpp", "argv": [ "@CMAKE_BINARY_DIR@/test/test_kernel", "-f", "{connection_file}" ] } xeus-zmq-1.1.1/test/test_kernel_control.py000066400000000000000000000021151450330156100207100ustar00rootroot00000000000000import unittest import jupyter_kernel_test class XeusKernelTests(jupyter_kernel_test.KernelTests): kernel_name = "test_kernel_control" language_name = "cpp" code_hello_world = "hello, world" code_page_something = "?" code_execute_result = [ {'code': '6*7', 'result': '6*7'}, {'code': 'test', 'result': 'test'} ] completion_samples = [ {'text': 'a.', 'matches': ['a.test1', 'a.test2']} ] complete_code_samples = ["complete"] incomplete_code_samples = ["incomplete"] invalid_code_samples = ["invalid"] code_inspect_sample = "invalid" def test_xeus_stderr(self): reply, output_msgs = self.execute_helper(code='error') self.assertEqual(output_msgs[0]['msg_type'], 'stream') self.assertEqual(output_msgs[0]['content']['name'], 'stderr') self.assertEqual(output_msgs[0]['content']['text'], 'error') class XeusIopubWelcomeTests(jupyter_kernel_test.IopubWelcomeTests): kernel_name = "test_kernel_control" support_iopub_welcome = True if __name__ == '__main__': unittest.main() xeus-zmq-1.1.1/test/test_kernel_control/000077500000000000000000000000001450330156100203375ustar00rootroot00000000000000xeus-zmq-1.1.1/test/test_kernel_control/kernel.json.in000066400000000000000000000002641450330156100231210ustar00rootroot00000000000000{ "display_name": "test_kernel", "language" : "cpp", "argv": [ "@CMAKE_BINARY_DIR@/test/test_kernel_control", "-f", "{connection_file}" ] } xeus-zmq-1.1.1/test/test_kernel_shell.py000066400000000000000000000021111450330156100203330ustar00rootroot00000000000000import unittest import jupyter_kernel_test class XeusKernelTests(jupyter_kernel_test.KernelTests): kernel_name = "test_kernel_shell" language_name = "cpp" code_hello_world = "hello, world" code_page_something = "?" code_execute_result = [ {'code': '6*7', 'result': '6*7'}, {'code': 'test', 'result': 'test'} ] completion_samples = [ {'text': 'a.', 'matches': ['a.test1', 'a.test2']} ] complete_code_samples = ["complete"] incomplete_code_samples = ["incomplete"] invalid_code_samples = ["invalid"] code_inspect_sample = "invalid" def test_xeus_stderr(self): reply, output_msgs = self.execute_helper(code='error') self.assertEqual(output_msgs[0]['msg_type'], 'stream') self.assertEqual(output_msgs[0]['content']['name'], 'stderr') self.assertEqual(output_msgs[0]['content']['text'], 'error') class XeusIopubWelcomeTests(jupyter_kernel_test.IopubWelcomeTests): kernel_name = "test_kernel_shell" support_iopub_welcome = True if __name__ == '__main__': unittest.main() xeus-zmq-1.1.1/test/test_kernel_shell/000077500000000000000000000000001450330156100177665ustar00rootroot00000000000000xeus-zmq-1.1.1/test/test_kernel_shell/kernel.json.in000066400000000000000000000002621450330156100225460ustar00rootroot00000000000000{ "display_name": "test_kernel", "language" : "cpp", "argv": [ "@CMAKE_BINARY_DIR@/test/test_kernel_shell", "-f", "{connection_file}" ] } xeus-zmq-1.1.1/test/xmock_interpreter.cpp000066400000000000000000000102671450330156100205360ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille and Sylvain Corlay * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include #include "nlohmann/json.hpp" #include "xmock_interpreter.hpp" #include "xeus/xhelper.hpp" #include "xeus/xguid.hpp" namespace nl = nlohmann; namespace xeus { void xmock_interpreter::configure_impl() { auto handle_comm_opened = [](xeus::xcomm&& comm, const xeus::xmessage&) { std::cout << "Comm opened for target: " << comm.target().name() << std::endl; }; comm_manager().register_comm_target("test_target", handle_comm_opened); using function_type = std::function; } nl::json xmock_interpreter::execute_request_impl(int execution_counter, const std::string& code, bool /* silent */, bool /* store_history */, nl::json /* user_expressions */, bool /* allow_stdin */) { if (code.compare("hello, world") == 0) { publish_stream("stdout", code); } if (code.compare("error") == 0) { publish_stream("stderr", code); } if (code.compare("?") == 0) { std::string html_content = R"()"; auto payload = nl::json::array(); payload[0] = nl::json::object({ {"data", { {"text/plain", "https://xeus.readthedocs.io"}, {"text/html", html_content}} }, {"source", "page"}, {"start", 0} }); return xeus::create_successful_reply(payload); } nl::json pub_data; pub_data["text/plain"] = code; publish_execution_result(execution_counter, std::move(pub_data), nl::json::object()); return xeus::create_successful_reply(); } nl::json xmock_interpreter::complete_request_impl(const std::string& /* code */, int /* cursor_pos */) { return xeus::create_complete_reply({"a.test1", "a.test2"}, 2, 6); } nl::json xmock_interpreter::inspect_request_impl(const std::string& /* code */, int /* cursor_pos */, int /* detail_level */) { return xeus::create_inspect_reply(true, {{"text/plain", ""}}, {{"text/plain", ""}}); } nl::json xmock_interpreter::is_complete_request_impl(const std::string& code) { nl::json result = xeus::create_is_complete_reply(code); if (code.compare("incomplete") == 0) { result["indent"] = " "; } return result; } nl::json xmock_interpreter::kernel_info_request_impl() { return xeus::create_info_reply("", "cpp_test", "1.0.0", "cpp", "14.0.0", "text/x-c++src", ".cpp", "", "", "", "test_kernel"); } void xmock_interpreter::shutdown_request_impl() { } } xeus-zmq-1.1.1/test/xmock_interpreter.hpp000066400000000000000000000033261450330156100205410ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille and Sylvain Corlay * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEUS_MOCK_INTERPRETER_HPP #define XEUS_MOCK_INTERPRETER_HPP #include "xeus/xinterpreter.hpp" namespace xeus { class xmock_interpreter : public xinterpreter { public: xmock_interpreter() = default; virtual ~xmock_interpreter() = default; private: void configure_impl() override; nl::json execute_request_impl(int execution_counter, const std::string& code, bool silent, bool store_history, nl::json user_expressions, bool allow_stdin) override; nl::json complete_request_impl(const std::string& code, int cursor_pos) override; nl::json inspect_request_impl(const std::string& code, int cursor_pos, int detail_level) override; nl::json is_complete_request_impl(const std::string& code) override; nl::json kernel_info_request_impl() override; void shutdown_request_impl() override; }; } #endif xeus-zmq-1.1.1/xeus-zmqConfig.cmake.in000066400000000000000000000050421450330156100176300ustar00rootroot00000000000000############################################################################ # Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Martin Renou # # Copyright (c) 2016, QuantStack # # # # Distributed under the terms of the BSD 3-Clause License. # # # # The full license is in the file LICENSE, distributed with this software. # ############################################################################ # xeus cmake module # This module sets the following variables in your project:: # # xeus_FOUND - true if xeus found on the system # xeus_INCLUDE_DIRS - the directory containing xeus headers # xeus_LIBRARY - the library for dynamic linking # xeus_STATIC_LIBRARY - the library for static linking @PACKAGE_INIT@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR};${CMAKE_MODULE_PATH}") @XEUS_ZMQ_CONFIG_CODE@ include(CMakeFindDependencyMacro) find_dependency(nlohmann_json @nlohmann_json_REQUIRED_VERSION@) find_dependency(xeus @xeus_REQUIRED_VERSION@) # On Unix platforms, ZeroMQ is built with autotools and pkg-config is # required to locate it. if (WIN32) find_dependency(ZeroMQ @zeromq_REQUIRED_VERSION@) else() # In order to not propagate the build-time requirement for pkg-config, we # do not propagate the dependency on ZeroMQ. #find_package(PkgConfig) #pkg_check_modules(ZeroMQ libzmq>=@zeromq_REQUIRED_VERSION@ REQUIRED) endif() find_dependency(cppzmq @cppzmq_REQUIRED_VERSION@) find_dependency(OpenSSL) if(NOT TARGET xeus-zmq AND NOT TARGET xeus-zmq-static) include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") if (TARGET xeus-zmq AND TARGET xeus-zmq-static) get_target_property(@PROJECT_NAME@_INCLUDE_DIR xeus-zmq INTERFACE_INCLUDE_DIRECTORIES) get_target_property(@PROJECT_NAME@_LIBRARY xeus-zmq LOCATION) get_target_property(@PROJECT_NAME@_STATIC_LIBRARY xeus-zmq-static LOCATION) elseif (TARGET xeus-zmq) get_target_property(@PROJECT_NAME@_INCLUDE_DIR xeus-zmq INTERFACE_INCLUDE_DIRECTORIES) get_target_property(@PROJECT_NAME@_LIBRARY xeus-zmq LOCATION) elseif (TARGET xeus-zmq-static) get_target_property(@PROJECT_NAME@_INCLUDE_DIR xeus-zmq-static INTERFACE_INCLUDE_DIRECTORIES) get_target_property(@PROJECT_NAME@_STATIC_LIBRARY xeus-zmq-static LOCATION) set(@PROJECT_NAME@_LIBRARY ${@PROJECT_NAME@_STATIC_LIBRARY}) endif () endif()