├── .github ├── docker │ └── debian │ │ ├── bookworm │ │ ├── amd64 │ │ │ └── Dockerfile │ │ ├── arm32v7 │ │ │ └── Dockerfile │ │ └── arm64v8 │ │ │ └── Dockerfile │ │ └── bullseye │ │ ├── amd64 │ │ └── Dockerfile │ │ ├── arm32v7 │ │ └── Dockerfile │ │ └── arm64v8 │ │ └── Dockerfile └── workflows │ ├── build.yml │ ├── ci.yml │ └── windows.yml ├── .gitignore ├── .vscode ├── c_cpp_properties.json └── settings.json ├── CMakeLists.txt ├── CODING_GUIDELINES ├── KSTest ├── CMakeLists.txt ├── KSTest.hpp ├── cases │ ├── handle.cpp │ ├── json.cpp │ ├── thread.cpp │ └── throughput.cpp └── main.cpp ├── README ├── cmake ├── AddLibBacktrace.cmake ├── FindLibM.cmake ├── FindPCRE.cmake ├── FindUUID.cmake ├── HunterGate.cmake ├── cotire.cmake ├── ksutil.cmake └── plat.cmake ├── copyright ├── libks.code-workspace ├── libks.pc.in ├── run_tests.sh ├── scan_build.sh ├── src ├── .directory ├── include │ ├── cJSON │ │ ├── cJSON.c │ │ ├── cJSON.h │ │ ├── cJSON_Utils.c │ │ └── cJSON_Utils.h │ └── libks │ │ ├── internal │ │ ├── ks_mutex.h │ │ ├── ks_pool.h │ │ └── ks_thread.h │ │ ├── ks.h │ │ ├── ks_acl.h │ │ ├── ks_atomic.h │ │ ├── ks_base64.h │ │ ├── ks_buffer.h │ │ ├── ks_config.h │ │ ├── ks_debug.h │ │ ├── ks_dso.h │ │ ├── ks_env.h │ │ ├── ks_hash.h │ │ ├── ks_json.h │ │ ├── ks_json_check.h │ │ ├── ks_log.h │ │ ├── ks_metrics.h │ │ ├── ks_platform.h │ │ ├── ks_pool.h │ │ ├── ks_printf.h │ │ ├── ks_q.h │ │ ├── ks_sb.h │ │ ├── ks_socket.h │ │ ├── ks_ssl.h │ │ ├── ks_string.h │ │ ├── ks_thread_pool.h │ │ ├── ks_threadmutex.h │ │ ├── ks_time.h │ │ ├── ks_types.h │ │ ├── ks_utf8.h │ │ ├── ks_uuid.h │ │ ├── kws.h │ │ └── simclist.h ├── ks.c ├── ks_acl.c ├── ks_base64.c ├── ks_buffer.c ├── ks_config.c ├── ks_debug.c ├── ks_dso.c ├── ks_env.c ├── ks_hash.c ├── ks_json.c ├── ks_json_check.c ├── ks_log.c ├── ks_metrics.c ├── ks_mutex.c ├── ks_pool.c ├── ks_printf.c ├── ks_q.c ├── ks_sb.c ├── ks_socket.c ├── ks_ssl.c ├── ks_string.c ├── ks_thread.c ├── ks_thread_pool.c ├── ks_time.c ├── ks_utf8.c ├── ks_uuid.c ├── kws.c └── simclist.c ├── tests ├── .gitignore ├── CMakeLists.txt ├── tap.c ├── tap.h ├── testacl.c ├── testhash.c ├── testhttp.c ├── testjson.c ├── testlog.c ├── testpolling.c ├── testpools.c ├── testq.c ├── testrealloc.c ├── testsock.c ├── testsock2.c ├── teststring.c ├── testthreadmutex.c ├── testthreadpools.c ├── testtime.c ├── testwebsock.c └── testwebsock2.c ├── uninstall.cmake.in └── win ├── .gitignore ├── basedir.props ├── build.cmd ├── buildpackages.task ├── downloadpackage.task ├── libks-version.props ├── libks.sln ├── libks.vcxproj ├── msbuild.cmd ├── openssl-version.props └── openssl.download.target /.github/docker/debian/bookworm/amd64/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BUILDER_IMAGE=debian:bookworm-20240513 2 | 3 | FROM ${BUILDER_IMAGE} AS builder 4 | 5 | ARG MAINTAINER_NAME="Andrey Volk" 6 | ARG MAINTAINER_EMAIL="andrey@signalwire.com" 7 | 8 | ARG BUILD_NUMBER=42 9 | ARG GIT_SHA=0000000000 10 | 11 | ARG DATA_DIR=/data 12 | 13 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 14 | 15 | SHELL ["/bin/bash", "-c"] 16 | 17 | ENV DEBIAN_FRONTEND=noninteractive 18 | 19 | RUN apt-get -q update \ 20 | && apt-get -y -q install \ 21 | apt-transport-https \ 22 | autoconf \ 23 | automake \ 24 | build-essential \ 25 | ca-certificates \ 26 | cmake \ 27 | curl \ 28 | debhelper \ 29 | devscripts \ 30 | dh-autoreconf \ 31 | dos2unix \ 32 | doxygen \ 33 | dpkg-dev \ 34 | git \ 35 | graphviz \ 36 | libglib2.0-dev \ 37 | libssl-dev \ 38 | lsb-release \ 39 | pkg-config \ 40 | wget 41 | 42 | RUN update-ca-certificates --fresh 43 | 44 | RUN git config --global --add safe.directory '*' \ 45 | && git config --global user.name "${MAINTAINER_NAME}" \ 46 | && git config --global user.email "${MAINTAINER_EMAIL}" 47 | 48 | # Bootstrap and Build 49 | COPY . ${DATA_DIR} 50 | WORKDIR ${DATA_DIR} 51 | 52 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 53 | -DCMAKE_BUILD_TYPE=Debug \ 54 | -DCMAKE_INSTALL_PREFIX="/usr" \ 55 | && make package \ 56 | && mkdir OUT \ 57 | && mv -v *.deb OUT/. 58 | 59 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 60 | FROM scratch 61 | COPY --from=builder /data/OUT/ / 62 | -------------------------------------------------------------------------------- /.github/docker/debian/bookworm/arm32v7/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BUILDER_IMAGE=arm32v7/debian:bookworm-20240513 2 | 3 | FROM --platform=linux/arm/v7 ${BUILDER_IMAGE} AS builder 4 | 5 | ARG MAINTAINER_NAME="Andrey Volk" 6 | ARG MAINTAINER_EMAIL="andrey@signalwire.com" 7 | 8 | ARG BUILD_NUMBER=42 9 | ARG GIT_SHA=0000000000 10 | 11 | ARG DATA_DIR=/data 12 | 13 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 14 | 15 | SHELL ["/bin/bash", "-c"] 16 | 17 | ENV DEBIAN_FRONTEND=noninteractive 18 | 19 | RUN apt-get -q update \ 20 | && apt-get -y -q install \ 21 | apt-transport-https \ 22 | autoconf \ 23 | automake \ 24 | build-essential \ 25 | ca-certificates \ 26 | cmake \ 27 | curl \ 28 | debhelper \ 29 | devscripts \ 30 | dh-autoreconf \ 31 | dos2unix \ 32 | doxygen \ 33 | dpkg-dev \ 34 | git \ 35 | graphviz \ 36 | libglib2.0-dev \ 37 | libssl-dev \ 38 | lsb-release \ 39 | pkg-config \ 40 | wget 41 | 42 | RUN update-ca-certificates --fresh 43 | 44 | RUN git config --global --add safe.directory '*' \ 45 | && git config --global user.name "${MAINTAINER_NAME}" \ 46 | && git config --global user.email "${MAINTAINER_EMAIL}" 47 | 48 | # Bootstrap and Build 49 | COPY . ${DATA_DIR} 50 | WORKDIR ${DATA_DIR} 51 | 52 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 53 | -DCMAKE_BUILD_TYPE=Debug \ 54 | -DCMAKE_INSTALL_PREFIX="/usr" \ 55 | && make package \ 56 | && mkdir OUT \ 57 | && mv -v *.deb OUT/. 58 | 59 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 60 | FROM scratch 61 | COPY --from=builder /data/OUT/ / 62 | -------------------------------------------------------------------------------- /.github/docker/debian/bookworm/arm64v8/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BUILDER_IMAGE=arm64v8/debian:bookworm-20240513 2 | 3 | FROM --platform=linux/arm64 ${BUILDER_IMAGE} AS builder 4 | 5 | ARG MAINTAINER_NAME="Andrey Volk" 6 | ARG MAINTAINER_EMAIL="andrey@signalwire.com" 7 | 8 | ARG BUILD_NUMBER=42 9 | ARG GIT_SHA=0000000000 10 | 11 | ARG DATA_DIR=/data 12 | 13 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 14 | 15 | SHELL ["/bin/bash", "-c"] 16 | 17 | ENV DEBIAN_FRONTEND=noninteractive 18 | 19 | RUN apt-get -q update \ 20 | && apt-get -y -q install \ 21 | apt-transport-https \ 22 | autoconf \ 23 | automake \ 24 | build-essential \ 25 | ca-certificates \ 26 | cmake \ 27 | curl \ 28 | debhelper \ 29 | devscripts \ 30 | dh-autoreconf \ 31 | dos2unix \ 32 | doxygen \ 33 | dpkg-dev \ 34 | git \ 35 | graphviz \ 36 | libglib2.0-dev \ 37 | libssl-dev \ 38 | lsb-release \ 39 | pkg-config \ 40 | wget 41 | 42 | RUN update-ca-certificates --fresh 43 | 44 | RUN git config --global --add safe.directory '*' \ 45 | && git config --global user.name "${MAINTAINER_NAME}" \ 46 | && git config --global user.email "${MAINTAINER_EMAIL}" 47 | 48 | # Bootstrap and Build 49 | COPY . ${DATA_DIR} 50 | WORKDIR ${DATA_DIR} 51 | 52 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 53 | -DCMAKE_BUILD_TYPE=Debug \ 54 | -DCMAKE_INSTALL_PREFIX="/usr" \ 55 | && make package \ 56 | && mkdir OUT \ 57 | && mv -v *.deb OUT/. 58 | 59 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 60 | FROM scratch 61 | COPY --from=builder /data/OUT/ / 62 | -------------------------------------------------------------------------------- /.github/docker/debian/bullseye/amd64/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BUILDER_IMAGE=debian:bullseye-20240513 2 | 3 | FROM ${BUILDER_IMAGE} AS builder 4 | 5 | ARG MAINTAINER_NAME="Andrey Volk" 6 | ARG MAINTAINER_EMAIL="andrey@signalwire.com" 7 | 8 | ARG BUILD_NUMBER=42 9 | ARG GIT_SHA=0000000000 10 | 11 | ARG DATA_DIR=/data 12 | 13 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 14 | 15 | SHELL ["/bin/bash", "-c"] 16 | 17 | ENV DEBIAN_FRONTEND=noninteractive 18 | 19 | RUN apt-get -q update \ 20 | && apt-get -y -q install \ 21 | apt-transport-https \ 22 | autoconf \ 23 | automake \ 24 | build-essential \ 25 | ca-certificates \ 26 | cmake \ 27 | curl \ 28 | debhelper \ 29 | devscripts \ 30 | dh-autoreconf \ 31 | dos2unix \ 32 | doxygen \ 33 | dpkg-dev \ 34 | git \ 35 | graphviz \ 36 | libglib2.0-dev \ 37 | libssl-dev \ 38 | lsb-release \ 39 | pkg-config \ 40 | wget 41 | 42 | RUN update-ca-certificates --fresh 43 | 44 | RUN git config --global --add safe.directory '*' \ 45 | && git config --global user.name "${MAINTAINER_NAME}" \ 46 | && git config --global user.email "${MAINTAINER_EMAIL}" 47 | 48 | # Bootstrap and Build 49 | COPY . ${DATA_DIR} 50 | WORKDIR ${DATA_DIR} 51 | 52 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 53 | -DCMAKE_BUILD_TYPE=Debug \ 54 | -DCMAKE_INSTALL_PREFIX="/usr" \ 55 | && make package \ 56 | && mkdir OUT \ 57 | && mv -v *.deb OUT/. 58 | 59 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 60 | FROM scratch 61 | COPY --from=builder /data/OUT/ / 62 | -------------------------------------------------------------------------------- /.github/docker/debian/bullseye/arm32v7/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BUILDER_IMAGE=arm32v7/debian:bullseye-20240513 2 | 3 | FROM --platform=linux/arm/v7 ${BUILDER_IMAGE} AS builder 4 | 5 | ARG MAINTAINER_NAME="Andrey Volk" 6 | ARG MAINTAINER_EMAIL="andrey@signalwire.com" 7 | 8 | ARG BUILD_NUMBER=42 9 | ARG GIT_SHA=0000000000 10 | 11 | ARG DATA_DIR=/data 12 | 13 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 14 | 15 | SHELL ["/bin/bash", "-c"] 16 | 17 | ENV DEBIAN_FRONTEND=noninteractive 18 | 19 | RUN apt-get -q update \ 20 | && apt-get -y -q install \ 21 | apt-transport-https \ 22 | autoconf \ 23 | automake \ 24 | build-essential \ 25 | ca-certificates \ 26 | cmake \ 27 | curl \ 28 | debhelper \ 29 | devscripts \ 30 | dh-autoreconf \ 31 | dos2unix \ 32 | doxygen \ 33 | dpkg-dev \ 34 | git \ 35 | graphviz \ 36 | libglib2.0-dev \ 37 | libssl-dev \ 38 | lsb-release \ 39 | pkg-config \ 40 | wget 41 | 42 | RUN update-ca-certificates --fresh 43 | 44 | RUN git config --global --add safe.directory '*' \ 45 | && git config --global user.name "${MAINTAINER_NAME}" \ 46 | && git config --global user.email "${MAINTAINER_EMAIL}" 47 | 48 | # Bootstrap and Build 49 | COPY . ${DATA_DIR} 50 | WORKDIR ${DATA_DIR} 51 | 52 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 53 | -DCMAKE_BUILD_TYPE=Debug \ 54 | -DCMAKE_INSTALL_PREFIX="/usr" \ 55 | && make package \ 56 | && mkdir OUT \ 57 | && mv -v *.deb OUT/. 58 | 59 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 60 | FROM scratch 61 | COPY --from=builder /data/OUT/ / 62 | -------------------------------------------------------------------------------- /.github/docker/debian/bullseye/arm64v8/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BUILDER_IMAGE=arm64v8/debian:bullseye-20240513 2 | 3 | FROM --platform=linux/arm64 ${BUILDER_IMAGE} AS builder 4 | 5 | ARG MAINTAINER_NAME="Andrey Volk" 6 | ARG MAINTAINER_EMAIL="andrey@signalwire.com" 7 | 8 | ARG BUILD_NUMBER=42 9 | ARG GIT_SHA=0000000000 10 | 11 | ARG DATA_DIR=/data 12 | 13 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 14 | 15 | SHELL ["/bin/bash", "-c"] 16 | 17 | ENV DEBIAN_FRONTEND=noninteractive 18 | 19 | RUN apt-get -q update \ 20 | && apt-get -y -q install \ 21 | apt-transport-https \ 22 | autoconf \ 23 | automake \ 24 | build-essential \ 25 | ca-certificates \ 26 | cmake \ 27 | curl \ 28 | debhelper \ 29 | devscripts \ 30 | dh-autoreconf \ 31 | dos2unix \ 32 | doxygen \ 33 | dpkg-dev \ 34 | git \ 35 | graphviz \ 36 | libglib2.0-dev \ 37 | libssl-dev \ 38 | lsb-release \ 39 | pkg-config \ 40 | wget 41 | 42 | RUN update-ca-certificates --fresh 43 | 44 | RUN git config --global --add safe.directory '*' \ 45 | && git config --global user.name "${MAINTAINER_NAME}" \ 46 | && git config --global user.email "${MAINTAINER_EMAIL}" 47 | 48 | # Bootstrap and Build 49 | COPY . ${DATA_DIR} 50 | WORKDIR ${DATA_DIR} 51 | 52 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 53 | -DCMAKE_BUILD_TYPE=Debug \ 54 | -DCMAKE_INSTALL_PREFIX="/usr" \ 55 | && make package \ 56 | && mkdir OUT \ 57 | && mv -v *.deb OUT/. 58 | 59 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 60 | FROM scratch 61 | COPY --from=builder /data/OUT/ / 62 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Distribute 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - release 8 | - master 9 | paths: 10 | - "**" 11 | workflow_dispatch: 12 | 13 | concurrency: 14 | group: ${{ github.head_ref || github.ref }} 15 | 16 | jobs: 17 | deb: 18 | name: 'DEB' 19 | permissions: 20 | id-token: write 21 | contents: read 22 | uses: signalwire/actions-template/.github/workflows/cicd-docker-build-and-distribute.yml@main 23 | strategy: 24 | # max-parallel: 1 25 | fail-fast: false 26 | matrix: 27 | os: 28 | - debian 29 | version: 30 | - bookworm 31 | - bullseye 32 | platform: 33 | - name: amd64 34 | runner: ubuntu-latest 35 | - name: arm32v7 36 | runner: ubuntu-24.04-arm 37 | - name: arm64v8 38 | runner: ubuntu-24.04-arm 39 | with: 40 | RUNNER: ${{ matrix.platform.runner }} 41 | ARTIFACTS_PATTERN: '.*\.(deb)$' 42 | DOCKERFILE: .github/docker/${{ matrix.os }}/${{ matrix.version }}/${{ matrix.platform.name }}/Dockerfile 43 | MAINTAINER: 'Andrey Volk ' 44 | META_FILE_PATH_PREFIX: /var/www/libks/public/unstable/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }} 45 | PLATFORM: ${{ matrix.platform.name }} 46 | TARGET_ARTIFACT_NAME: ${{ matrix.os }}-${{ matrix.version }}-${{ matrix.platform.name }}-public-unstable-artifact 47 | UPLOAD_BUILD_ARTIFACTS: ${{ github.event_name != 'pull_request' }} 48 | secrets: 49 | GH_BOT_DEPLOY_TOKEN: ${{ secrets.PAT }} 50 | HOSTNAME: ${{ secrets.HOSTNAME }} 51 | PROXY_URL: ${{ secrets.PROXY_URL }} 52 | USERNAME: ${{ secrets.USERNAME }} 53 | TELEPORT_TOKEN: ${{ secrets.TELEPORT_TOKEN }} 54 | 55 | deb-mirror: 56 | name: 'DEB-MIRROR' 57 | if: ${{ github.event_name != 'pull_request' }} 58 | needs: 59 | - deb 60 | runs-on: ubuntu-latest 61 | permissions: 62 | id-token: write 63 | contents: read 64 | strategy: 65 | # max-parallel: 1 66 | fail-fast: false 67 | matrix: 68 | os: 69 | - debian 70 | version: 71 | - bookworm 72 | - bullseye 73 | platform: 74 | - name: amd64 75 | runner: ubuntu-latest 76 | - name: arm32v7 77 | runner: ubuntu-24.04-arm 78 | - name: arm64v8 79 | runner: ubuntu-24.04-arm 80 | release: 81 | - release 82 | - unstable 83 | steps: 84 | - name: Checkout reusable actions 85 | uses: actions/checkout@v4 86 | with: 87 | repository: signalwire/actions-template 88 | ref: main 89 | fetch-depth: 1 90 | path: actions 91 | sparse-checkout: | 92 | .github/actions/teleport-local-copy/action.yml 93 | sparse-checkout-cone-mode: false 94 | 95 | - name: Mirror artifacts on remote server behind Teleport (public) 96 | uses: ./actions/.github/actions/teleport-local-copy 97 | with: 98 | SRC: '/var/www/libks/public/unstable/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }}/${{ matrix.os }}-${{ matrix.version }}-${{ matrix.platform.name }}-public-unstable-artifact.tar.gz' 99 | DST: '/var/www/libks/public/${{ matrix.release }}/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }}/${{ matrix.os }}-${{ matrix.version }}-${{ matrix.platform.name }}-public-${{ matrix.release }}-artifact.tar.gz' 100 | env: 101 | HOSTNAME: ${{ secrets.HOSTNAME }} 102 | PROXY_URL: ${{ secrets.PROXY_URL }} 103 | TOKEN: ${{ secrets.TELEPORT_TOKEN }} 104 | USERNAME: ${{ secrets.USERNAME }} 105 | 106 | - name: Mirror artifacts on remote server behind Teleport (fsa) 107 | uses: ./actions/.github/actions/teleport-local-copy 108 | with: 109 | SRC: '/var/www/libks/public/unstable/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }}/${{ matrix.os }}-${{ matrix.version }}-${{ matrix.platform.name }}-public-unstable-artifact.tar.gz' 110 | DST: '/var/www/libks/fsa/${{ matrix.release }}/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }}/${{ matrix.os }}-${{ matrix.version }}-${{ matrix.platform.name }}-fsa-${{ matrix.release }}-artifact.tar.gz' 111 | env: 112 | HOSTNAME: ${{ secrets.HOSTNAME }} 113 | PROXY_URL: ${{ secrets.PROXY_URL }} 114 | TOKEN: ${{ secrets.TELEPORT_TOKEN }} 115 | USERNAME: ${{ secrets.USERNAME }} 116 | 117 | meta: 118 | name: 'Publish build data to meta-repo' 119 | if: ${{ github.event_name != 'pull_request' }} 120 | needs: 121 | - deb 122 | - deb-mirror 123 | permissions: 124 | id-token: write 125 | contents: read 126 | uses: signalwire/actions-template/.github/workflows/meta-repo-content.yml@main 127 | with: 128 | META_CONTENT: '/var/www/libks/{fsa,public}/{release,unstable}/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }}' 129 | META_REPO: signalwire/bamboo_gha_trigger 130 | META_REPO_BRANCH: trigger/libks/${{ github.ref_name }} 131 | secrets: 132 | GH_BOT_DEPLOY_TOKEN: ${{ secrets.PAT }} 133 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | scan_build: 10 | runs-on: ubuntu-latest 11 | container: 12 | image: debian:buster 13 | steps: 14 | - name: install deps 15 | run: | 16 | apt-get update && apt-get install -yq build-essential autotools-dev lsb-release pkg-config automake autoconf libtool-bin clang-tools-7 17 | apt-get install -yq cmake uuid-dev libssl-dev 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | - run: pwd 21 | - id: scan_build 22 | run: ./scan_build.sh 23 | - name: Tar logs 24 | id: tar 25 | if: failure() 26 | env: 27 | COMPILATION_FAILED: ${{ steps.scan_build.outputs.COMPILATION_FAILED }} 28 | BUGS_FOUND: ${{ steps.scan_build.outputs.BUGS_FOUND }} 29 | run: | 30 | ls -l 31 | if [ "true" -eq $COMPILATION_FAILED ]; then 32 | tar czvf scan-build-result.tar.gz ./scan-build-result.txt; 33 | echo "ARTIFACT_PATH=/__w/libks/libks/scan-build-result.tar.gz" >> $GITHUB_OUTPUT; 34 | echo "ARTIFACT=scan-build-result" >> $GITHUB_OUTPUT; 35 | fi 36 | if [ "true" -eq $BUGS_FOUND ]; then 37 | tar czvf reports.tar.gz $REPORT; 38 | echo "ARTIFACT_PATH=/__w/libks/libks/reports.tar.gz" >> $GITHUB_OUTPUT; 39 | echo "ARTIFACT=reports" >> $GITHUB_OUTPUT; 40 | fi 41 | 42 | - name: Upload artifacts 43 | if: failure() 44 | uses: actions/upload-artifact@v4 45 | with: 46 | name: ${{ steps.tar.outputs.ARTIFACT }}-${{ github.sha }}-${{ github.run_id }} 47 | path: ${{ steps.tar.outputs.ARTIFACT_PATH }} 48 | retention-days: 5 49 | - name: notify slack 50 | if: failure() 51 | uses: signalwire/actions-template/.github/actions/slack@main 52 | with: 53 | CHANNEL: CCS2AV2H2 54 | MESSAGE: Scan-build ${{ github.repository }} > <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.run_id }}>.\n ${{ steps.scan_build.outputs.MESSAGE }}}.\nPlease check the results. 55 | env: 56 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 57 | run_tests: 58 | runs-on: ubuntu-latest 59 | container: 60 | image: debian:buster 61 | steps: 62 | - name: Checkout 63 | uses: actions/checkout@v4 64 | - name: run tests 65 | id: tests 66 | run: ./run_tests.sh 67 | - name: Upload artifacts 68 | if: failure() 69 | uses: actions/upload-artifact@v4 70 | with: 71 | name: test-artifacts-${{ github.sha }}-${{ github.run_id }}.html 72 | path: ${{ steps.tests.outputs.TEST_ARTIFACT_FILE }} 73 | retention-days: 5 74 | - name: notify slack 75 | if: failure() 76 | uses: signalwire/actions-template/.github/actions/slack@main 77 | with: 78 | CHANNEL: CCS2AV2H2 79 | MESSAGE: Test-Failure ${{ github.repository }} > <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.run_id }}>.\nPlease check the results. 80 | env: 81 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 82 | 83 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: Windows Build 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | - release 9 | pull_request: 10 | branches: 11 | - master 12 | - release 13 | 14 | jobs: 15 | build: 16 | name: Build libks Windows 17 | runs-on: windows-2019 18 | 19 | steps: 20 | - name: Checkout code 21 | uses: actions/checkout@v4 22 | with: 23 | fetch-depth: 0 24 | 25 | - name: Install build dependencies 26 | run: | 27 | choco install nasm strawberryperl -y 28 | echo "C:\Program Files\NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append 29 | echo "C:\Strawberry\perl\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append 30 | 31 | # https://learn.microsoft.com/en-us/visualstudio/releases/2019/history 32 | - name: Check available VS versions 33 | shell: cmd 34 | run: | 35 | where vswhere.exe 36 | vswhere.exe -all -prerelease -format json 37 | 38 | - name: Add msbuild to PATH 39 | uses: microsoft/setup-msbuild@v2 40 | with: 41 | msbuild-architecture: x64 42 | # https://github.com/microsoft/setup-msbuild?tab=readme-ov-file#specifying-specific-versions-of-visual-studio-optional 43 | # vs-version: "[16.11,16.12)" 44 | 45 | - name: Build All Configurations 46 | shell: cmd 47 | working-directory: win 48 | run: | 49 | CALL build.cmd 50 | 51 | - name: Upload Build Artifacts 52 | uses: actions/upload-artifact@v4 53 | with: 54 | name: libks-windows-builds 55 | path: win/out/*.zip 56 | if-no-files-found: error 57 | retention-days: 7 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | aclocal.m4 2 | CMakeCache.txt 3 | CMakeFiles 4 | CMakeCache.txt 5 | CMakeFiles/ 6 | _CPack_Packages/ 7 | CTestTestfile.cmake 8 | LibKSConfig.cmake 9 | LibKS2Config.cmake 10 | cmake_install.cmake 11 | libks2.so 12 | libks2.so.* 13 | tests/CMakeFiles/ 14 | tests/CTestTestfile.cmake 15 | tests/cmake_install.cmake 16 | tests/testthreadpools 17 | autom4te.cache 18 | configure 19 | config.status 20 | config.log 21 | libtool 22 | Makefile 23 | Makefile.in 24 | *.o 25 | *.lo 26 | *.la 27 | *.pc 28 | .libs 29 | .dirstamp 30 | .deps 31 | build 32 | tests/test_thread_pools 33 | tests/testacl 34 | tests/testrealloc 35 | tests/teststring 36 | tests/testjson 37 | tests/testhandle 38 | :w 39 | uninstall.cmake 40 | install_manifest.txt 41 | /cmake_install.cmake 42 | Testing 43 | core 44 | cotire/ 45 | *_cotire.cmake 46 | *.dylib 47 | *.vcxproj* 48 | *.dir 49 | *.sln 50 | /Debug 51 | /tests/Debug 52 | /x64 53 | /_3rdParty 54 | /external 55 | LibKS-* 56 | CPack* 57 | *.deb 58 | *manifest* 59 | changelog.Debian 60 | changelog.Debian.gz 61 | build-Win32/ 62 | build-x64/ 63 | !win/* 64 | 65 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Mac", 5 | "includePath": [ 6 | "/usr/include", 7 | "/usr/local/include", 8 | "${workspaceFolder}" 9 | ], 10 | "defines": [], 11 | "intelliSenseMode": "clang-x64", 12 | "browse": { 13 | "path": [ 14 | "/usr/include", 15 | "/usr/local/include", 16 | "${workspaceFolder}" 17 | ], 18 | "limitSymbolsToIncludedHeaders": true, 19 | "databaseFilename": "" 20 | }, 21 | "macFrameworkPath": [ 22 | "/System/Library/Frameworks", 23 | "/Library/Frameworks" 24 | ] 25 | }, 26 | { 27 | "name": "Linux", 28 | "includePath": [ 29 | "${workspaceFolder}", 30 | "/usr/include/c++/6", 31 | "/usr/include/x86_64-linux-gnu/c++/6", 32 | "/usr/include/c++/6/backward", 33 | "/usr/lib/gcc/x86_64-linux-gnu/6/include", 34 | "/usr/local/include", 35 | "/usr/lib/gcc/x86_64-linux-gnu/6/include-fixed", 36 | "/usr/include/x86_64-linux-gnu", 37 | "/usr/include", 38 | "${workspaceFolder}/src/include" 39 | ], 40 | "defines": [], 41 | "intelliSenseMode": "clang-x64", 42 | "browse": { 43 | "path": [ 44 | "${workspaceFolder}", 45 | "/usr/include/c++/6", 46 | "/usr/include/x86_64-linux-gnu/c++/6", 47 | "/usr/include/c++/6/backward", 48 | "/usr/lib/gcc/x86_64-linux-gnu/6/include", 49 | "/usr/local/include", 50 | "/usr/lib/gcc/x86_64-linux-gnu/6/include-fixed", 51 | "/usr/include/x86_64-linux-gnu", 52 | "/usr/include" 53 | ], 54 | "limitSymbolsToIncludedHeaders": true, 55 | "databaseFilename": "" 56 | }, 57 | "compilerPath": "/usr/bin/gcc", 58 | "cStandard": "c11", 59 | "cppStandard": "c++17" 60 | }, 61 | { 62 | "name": "Win32", 63 | "includePath": [ 64 | "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include", 65 | "${workspaceFolder}" 66 | ], 67 | "defines": [ 68 | "_DEBUG", 69 | "UNICODE", 70 | "_UNICODE" 71 | ], 72 | "intelliSenseMode": "msvc-x64", 73 | "browse": { 74 | "path": [ 75 | "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*", 76 | "${workspaceFolder}" 77 | ], 78 | "limitSymbolsToIncludedHeaders": true, 79 | "databaseFilename": "" 80 | } 81 | } 82 | ], 83 | "version": 4 84 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /CODING_GUIDELINES: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2017, FreeSWITCH Solutions LLC 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of the original author; nor the names of any contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 25 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /* 35 | Functions that create and destroy objects always take pointer to pointer of that type. 36 | Spaces after loop and conditional operators while, for, if etc. 37 | Newlines after one or more declarations. 38 | Newlines before and after loops. 39 | Newlines before returns. 40 | One-Line if/else sparingly only when very obvious exit from loop or return. 41 | Use brackets even when not necessary other than the one-liners above. 42 | Align the * in pointers to the type or function name (e.g char *foo, char *some_func(char *data) ) 43 | Use typedefs for structs especially public-facing. 44 | Only use // style-comments on tempory comments that will probably be removed eventually. 45 | Add the emacs/vi comment to the bottom of every file. 46 | Use Doxygen for function args. 47 | Tabs not spaces. 48 | Use flags as bitwise when possible, use arrays if going beyond 32 49 | Typedef all enums using UPPER_CASE notation for the values 50 | */ 51 | 52 | typedef enum { 53 | SOME_FLAG_X = (1 << 0), 54 | SOME_FLAG_Y = (1 << 1) 55 | } some_flag_type_t; 56 | 57 | typedef enum { 58 | SOME_TYPE_X = 1, 59 | SOME_TYPE_Y, 60 | SOME_TYPE_Z 61 | } some_type_t; 62 | 63 | 64 | KS_DECLARE(ks_status_t) function_example(somedata_t **data, ks_pool_t *pool) 65 | { 66 | int var = 3, x = 0; 67 | 68 | if (!pool) return KS_STATUS_FAIL; 69 | 70 | for (x = 0; x < 100; x++) { 71 | var += x; 72 | } 73 | 74 | if (var > 20) { 75 | var *= 2; 76 | } else { 77 | var *= 3; 78 | } 79 | 80 | while (var) { 81 | var--; 82 | } 83 | 84 | if (var) { 85 | *data = ks_pool_alloc(pool, sizeof(*data)); 86 | (*data)->pool = pool; 87 | 88 | return KS_STATUS_SUCCESS; 89 | 90 | } else { 91 | *data = NULL; 92 | 93 | return KS_STATUS_FAIL; 94 | } 95 | 96 | } 97 | 98 | 99 | /* For Emacs: 100 | * Local Variables: 101 | * mode:c 102 | * indent-tabs-mode:t 103 | * tab-width:4 104 | * c-basic-offset:4 105 | * End: 106 | * For VIM: 107 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 108 | */ 109 | -------------------------------------------------------------------------------- /KSTest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Our core file list 2 | file(GLOB KSTestDeps [LIST_DIRECTORIES false] 3 | ${CMAKE_CURRENT_LIST_DIR}/*.h 4 | ${CMAKE_CURRENT_LIST_DIR}/*.hpp 5 | ${CMAKE_CURRENT_LIST_DIR}/*.cpp 6 | ${CMAKE_CURRENT_LIST_DIR}/cases/*.cpp 7 | ${CMAKE_CURRENT_LIST_DIR}/cases/*.hpp 8 | ) 9 | 10 | source_group(TREE ${CMAKE_CURRENT_LIST_DIR} FILES ${KSTestDeps}) 11 | 12 | add_executable( 13 | KSTest 14 | ${KSTestDeps} 15 | ${KSTestExpDeps} 16 | ) 17 | 18 | # Fetch Catch2 testing framework 19 | hunter_add_package(Catch) 20 | find_package(Catch2 CONFIG REQUIRED) 21 | 22 | if (NOT TARGET LibPal) 23 | message(FATAL_ERROR "LibPal not found") 24 | endif() 25 | if (NOT TARGET Catch2::Catch) 26 | message(FATAL_ERROR "Catch2 not found") 27 | endif() 28 | 29 | # Link to ks/catch/LibPal 30 | target_link_libraries(KSTest ks2 LibPal Catch2::Catch) 31 | 32 | # Register our tests with cmake 33 | add_test(KSTest KSTest) 34 | 35 | # Inlclude our root 36 | target_include_directories( 37 | KSTest 38 | PUBLIC 39 | ${CMAKE_CURRENT_LIST_DIR} 40 | ) 41 | 42 | # Turn on the latest c++ features 43 | target_compile_features(KSTest PUBLIC cxx_std_17) 44 | 45 | # For boost on linux 46 | if (PAL_PLAT_LIN) 47 | target_compile_definitions(KSTest PRIVATE 48 | -DBOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED=1 49 | ) 50 | endif() 51 | 52 | # When debugging on windows, the cwd will be the binary dir (where the config files are) 53 | set_target_properties(KSTest PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) 54 | set(COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES 1) 55 | 56 | set_target_properties(KSTest PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE) 57 | set_target_properties(KSTest PROPERTIES COTIRE_ENABLE_PRECOMPILED_HEADER TRUE) 58 | set_target_properties(KSTest PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "KSTest.hpp") 59 | cotire(KSTest) 60 | -------------------------------------------------------------------------------- /KSTest/KSTest.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #pragma once 23 | 24 | // Include pal 25 | #define PAL_NO_NET 1 26 | #include "signalwire/pal.hpp" 27 | 28 | // Include ks 29 | #include "libks/ks.h" 30 | 31 | // Yeah.. this took longer to figure out then I would like to admit 32 | #undef init 33 | #undef inline 34 | #undef open 35 | #undef close 36 | #undef read 37 | #undef write 38 | #undef cast 39 | #undef __inline__ 40 | #undef swap 41 | 42 | // Include some handy ks utilities from pal 43 | #include "signalwire/pal/ksutil/all.hpp" 44 | -------------------------------------------------------------------------------- /KSTest/cases/throughput.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "KSTest.hpp" 24 | #include "libks/ks_atomic.h" 25 | #include "libks/internal/ks_throughput.h" 26 | #include "catch/catch.hpp" 27 | 28 | using namespace signalwire::pal; 29 | 30 | using ThroughputHandle = ksutil::KSHandle; 31 | 32 | TEST_CASE("throughput") 33 | { 34 | ThroughputHandle rate; 35 | 36 | KCHECK(ks_throughput_create_ex(&rate, 2, 1)); 37 | 38 | // Tell throughput we'll update now by hand and to use 39 | rate->static_now_sec = 1000; 40 | 41 | REQUIRE(rate->count_bucket == 0); 42 | 43 | KCHECK(ks_throughput_report(rate, 1024)); 44 | 45 | REQUIRE(rate->count_bucket == 0); 46 | REQUIRE(rate->count_bucket == 0); 47 | REQUIRE(rate->current_bucket.count == 1); 48 | REQUIRE(rate->current_bucket.size == 1024); 49 | 50 | // Advance time by one second 51 | rate->static_now_sec += 1; 52 | KCHECK(ks_throughput_update(rate)); 53 | REQUIRE(rate->count_bucket == 1); 54 | 55 | REQUIRE(rate->count_bucket == 1); 56 | 57 | REQUIRE(rate->current_bucket.count == 0); 58 | REQUIRE(rate->current_bucket.size == 0); 59 | REQUIRE(rate->buckets[0].count == 1); 60 | REQUIRE(rate->buckets[0].size == 1024); 61 | 62 | // Now we should have a rate 63 | ks_throughput_stats_t stats; 64 | KCHECK(ks_throughput_stats(rate, &stats)); 65 | REQUIRE(stats.rate_count == 1.0); 66 | REQUIRE(stats.rate_size == 1024.0); 67 | 68 | char rate_str[512]; 69 | std::cout << ks_throughput_stats_render(&stats, rate_str, sizeof(rate_str)) << std::endl; 70 | 71 | // If we report, without advancing the time, the rate shouldn't change but the first 72 | // bucket should be staged 73 | KCHECK(ks_throughput_report(rate, 1024)); 74 | 75 | KCHECK(ks_throughput_stats(rate, &stats)); 76 | REQUIRE(rate->count_bucket == 1); 77 | REQUIRE(stats.rate_count == 1.0); 78 | REQUIRE(stats.rate_size == 1024.0); 79 | 80 | // As the first bucket is still 'uncompleted' but it should be additive 81 | REQUIRE(rate->current_bucket.count == 1); 82 | REQUIRE(rate->current_bucket.size == 1024); 83 | REQUIRE(rate->buckets[0].count == 1); 84 | REQUIRE(rate->buckets[0].size == 1024); 85 | 86 | // Ok advance the clock by 1 second and update to see if it continues 87 | // to return the proper rate 88 | rate->static_now_sec += 1; 89 | KCHECK(ks_throughput_update(rate)); 90 | KCHECK(ks_throughput_stats(rate, &stats)); 91 | 92 | // Should have a new bucket at 0 with 1-2 rolled forward 93 | REQUIRE(rate->current_bucket.count == 0); 94 | REQUIRE(rate->current_bucket.size == 0); 95 | REQUIRE(rate->buckets[0].count == 1); 96 | REQUIRE(rate->buckets[0].size == 1024); 97 | REQUIRE(rate->buckets[1].count == 1); 98 | REQUIRE(rate->buckets[1].size == 1024); 99 | 100 | // Same rate as before 101 | REQUIRE(stats.rate_size == 1024.0); 102 | REQUIRE(stats.rate_count == 1.0); 103 | 104 | std::cout << ks_throughput_stats_render(&stats, rate_str, sizeof(rate_str)) << std::endl; 105 | 106 | // Now advance the time without reporting anything, we should start 107 | // seeing the rate trend downwards 108 | rate->static_now_sec += 1; 109 | KCHECK(ks_throughput_update(rate)); 110 | 111 | KCHECK(ks_throughput_stats(rate, &stats)); 112 | 113 | REQUIRE(rate->current_bucket.count == 0); 114 | REQUIRE(rate->current_bucket.size == 0); 115 | REQUIRE(rate->buckets[0].count == 0); 116 | REQUIRE(rate->buckets[0].size == 0); 117 | REQUIRE(rate->buckets[1].count == 1); 118 | REQUIRE(rate->buckets[1].size == 1024); 119 | 120 | // Rate should be cut in half 121 | REQUIRE(stats.rate_size == 1024.0 / 2); 122 | REQUIRE(stats.rate_count == 1.0 / 2); 123 | 124 | // Finally verify we can render the stats 125 | LOG(TEST, stats); 126 | } 127 | -------------------------------------------------------------------------------- /KSTest/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #include "KSTest.hpp" 23 | #define CATCH_CONFIG_MAIN // Let catch do main handling 24 | #include "catch/catch.hpp" 25 | 26 | using namespace signalwire::pal; 27 | 28 | namespace { 29 | static log::StreamBuffer s_stream("Catch"); 30 | static std::streambuf * s_oldBuffer = nullptr; 31 | } 32 | 33 | util::Scope init( 34 | [&]() 35 | { 36 | // Redirect std::cout rdbuf to go to our logger 37 | s_oldBuffer = std::cout.rdbuf(&s_stream); 38 | 39 | // Enable testing output in pal 40 | log::enableLevel("TEST"); 41 | 42 | // Initialize ks 43 | ks_init(); 44 | }, 45 | [&]() 46 | { 47 | // Restore the buffer 48 | std::cout.rdbuf(s_oldBuffer); 49 | 50 | // Deinit ks 51 | ks_shutdown(); 52 | } 53 | ); 54 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | To build use cmake (Minimum version 3.7.2): 2 | cmake . 3 | make 4 | 5 | To install: 6 | make install 7 | 8 | To un-install: 9 | make uninstall 10 | 11 | To build debug (no optimizations, symbols - this is the default): 12 | cmake . -DCMAKE_BUILD_TYPE=Debug 13 | make 14 | 15 | To build release (optimizations, symbols): 16 | cmake . -DCMAKE_BUILD_TYPE=Release 17 | make 18 | 19 | To build to a custom installation prefix (default is /usr): 20 | cmake . -DCMAKE_INSTALL_PREFIX:PATH=/usr 21 | make 22 | 23 | To build with openssl on non-standard location (e.g. on Mac): 24 | OPENSSL_ROOT_DIR=/usr/local/opt/openssl cmake . -DCMAKE_INSTALL_PREFIX:PATH=/usr/local 25 | 26 | To run tests: 27 | ctest . 28 | 29 | To build release package with build number 42: 30 | PACKAGE_RELEASE="42" cmake . -DCMAKE_BUILD_TYPE=Release && make package 31 | 32 | To buld CMAKE from source 33 | wget https://cmake.org/files/v3.7/cmake-3.7.2.tar.gz 34 | tar -zxvf cmake-3.7.2.tar.gz 35 | cd cmake-3.7.2 36 | ./bootstrap --prefix=/usr/local 37 | make 38 | make install 39 | /usr/local/bin/cmake --version 40 | 41 | Centos dependencies: 42 | - yum groupinstall "Development Tools" 43 | - yum install libuuid-devel libatomic openssl-devel 44 | 45 | -------------------------------------------------------------------------------- /cmake/AddLibBacktrace.cmake: -------------------------------------------------------------------------------- 1 | # Creates a target LibBacktrace that you can link to 2 | # and adds this project as an external one. 3 | # It will install to: 4 | # ${PROJECT_SOURCE_DIR}/external/LibBackTrace/install 5 | 6 | if (KS_PLAT_WIN) 7 | message(FATAL "LibBackTrace is only available on Gnu platforms") 8 | endif() 9 | 10 | include(ExternalProject) 11 | find_package(Git REQUIRED) 12 | 13 | ExternalProject_Add( 14 | Project_LibBacktrace 15 | PREFIX ${PROJECT_SOURCE_DIR}/external/LibBacktrace 16 | GIT_REPOSITORY https://github.com/ianlancetaylor/libbacktrace 17 | TIMEOUT 10 18 | UPDATE_COMMAND "" 19 | CONFIGURE_COMMAND ${PROJECT_SOURCE_DIR}/external/LibBacktrace/src/Project_LibBacktrace/configure --enable-host-shared --prefix=${PROJECT_SOURCE_DIR}/external/LibBacktrace/install --enable-shared=no --enable-static=yes 20 | BUILD_COMMAND make 21 | INSTALL_COMMAND make install 22 | BUILD_IN_SOURCE 1 23 | ) 24 | 25 | # Not done yet we have to make a target that is depndent on this so we can use it easily 26 | add_library(LibBacktrace STATIC IMPORTED GLOBAL) 27 | set_target_properties(LibBacktrace PROPERTIES IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/external/LibBacktrace/install/lib/libbacktrace.a") 28 | set_target_properties(LibBacktrace PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/external/LibBacktrace/install/include") 29 | 30 | add_dependencies(LibBacktrace Project_LibBacktrace) 31 | -------------------------------------------------------------------------------- /cmake/FindLibM.cmake: -------------------------------------------------------------------------------- 1 | # LIBM_INCLUDE_DIRS - where to find math.h, etc. 2 | # LIBM_LIBRARIES - List of libraries when using libm. 3 | # LIBM_FOUND - True if math library found. 4 | # 5 | # Hints 6 | # ^^^^^ 7 | # 8 | # A user may set ``LIBM_ROOT`` to a math library installation root to tell this 9 | # module where to look. 10 | 11 | find_path(LIBM_INCLUDE_DIRS 12 | NAMES math.h 13 | PATHS /usr/include /usr/local/include /usr/local/bic/include 14 | NO_DEFAULT_PATH 15 | ) 16 | find_library(LIBM_LIBRARIES m) 17 | include(FindPackageHandleStandardArgs) 18 | find_package_handle_standard_args(LibM DEFAULT_MSG LIBM_LIBRARIES LIBM_INCLUDE_DIRS) 19 | mark_as_advanced(LIBM_INCLUDE_DIRS LIBM_LIBRARIES) 20 | 21 | if(LIBM_FOUND) 22 | if(NOT TARGET LIBM::LIBM) 23 | add_library(LIBM::LIBM UNKNOWN IMPORTED) 24 | set_target_properties(LIBM::LIBM PROPERTIES 25 | IMPORTED_LOCATION "${LIBM_LIBRARIES}" 26 | INTERFACE_INCLUDE_DIRECTORIES "${LIBM_INCLUDE_DIRS}") 27 | endif() 28 | endif() 29 | -------------------------------------------------------------------------------- /cmake/FindPCRE.cmake: -------------------------------------------------------------------------------- 1 | # PCRE_FOUND 2 | # PCRE_LIBRARIES 3 | # PCRE_LIBRARY_DIRS 4 | # PCRE_LDFLAGS 5 | # PCRE_INCLUDE_DIRS 6 | # PCRE_CFLAGS 7 | 8 | if (NOT KS_PLAT_WIN) 9 | include(FindPkgConfig) 10 | 11 | if (NOT PKG_CONFIG_FOUND) 12 | message("Failed to locate pkg-config" FATAL) 13 | endif() 14 | 15 | pkg_check_modules(PCRE libpcre REQUIRED) 16 | else() 17 | # On windows we expect the build env to have a setup target already 18 | # as we just created a libpcre repo with the pre-build libs and includes 19 | if (NOT TARGET pcre) 20 | message(FATAL_ERROR "libpcre target not loaded") 21 | endif() 22 | 23 | # We just have to declare the library, since we use the interface systme 24 | # all include paths and link rules will be inherited automatically 25 | set(PCRE_LIBRARIES pcre) 26 | 27 | get_target_property(PCRE_INCLUDE_DIRS pcre SOURCE_DIR) 28 | 29 | set(PCRE_CFLAGS -DPCRE_STATIC) 30 | endif() 31 | -------------------------------------------------------------------------------- /cmake/FindUUID.cmake: -------------------------------------------------------------------------------- 1 | # UUID_FOUND 2 | # UUID_LIBRARIES 3 | # UUID_LIBRARY_DIRS 4 | # UUID_LDFLAGS 5 | # UUID_INCLUDE_DIRS 6 | # UUID_CFLAGS 7 | 8 | if (NOT KS_PLAT_WIN) 9 | include(FindPkgConfig) 10 | 11 | if (NOT PKG_CONFIG_FOUND) 12 | message("Failed to locate pkg-config" FATAL) 13 | endif() 14 | 15 | pkg_check_modules(UUID uuid REQUIRED) 16 | 17 | if(UUID_FOUND) 18 | find_library(UUID_ABS_LIB_PATH 19 | NAMES ${UUID_LIBRARIES} 20 | HINTS ${UUID_LIBRARY_DIRS} 21 | PATHS ${UUID_LIBRARY_DIRS} 22 | ) 23 | if(NOT TARGET LIBUUID::LIBUUID) 24 | add_library(LIBUUID::LIBUUID UNKNOWN IMPORTED) 25 | set_target_properties(LIBUUID::LIBUUID PROPERTIES 26 | IMPORTED_LOCATION ${UUID_ABS_LIB_PATH} 27 | INTERFACE_INCLUDE_DIRECTORIES "${UUID_INCLUDE_DIRS}") 28 | endif() 29 | 30 | message("Found UUID setup target at imported location: ${UUID_ABS_LIB_PATH}") 31 | endif() 32 | endif() 33 | -------------------------------------------------------------------------------- /cmake/plat.cmake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalwire/libks/404206ca50e2a1b6d9304ca385eec57e8e8955b2/cmake/plat.cmake -------------------------------------------------------------------------------- /libks.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | } 8 | -------------------------------------------------------------------------------- /libks.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@PC_PREFIX@ 2 | exec_prefix=${prefix} 3 | libdir=${prefix}/lib 4 | includedir=${prefix}/include/libks2 5 | definitions=@PC_DEFINITIONS@ 6 | 7 | Name: @PACKAGE_NAME@ 8 | Version: @PACKAGE_VERSION@ 9 | Description: A cross platform kitchen sink library. 10 | 11 | Cflags: -I${includedir} 12 | Libs: -L${libdir} -lks2 13 | -------------------------------------------------------------------------------- /run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apt-get update && apt-get install -yq build-essential autotools-dev lsb-release pkg-config automake autoconf libtool-bin clang-tools-7 3 | apt-get install -yq cmake uuid-dev libssl-dev colorized-logs 4 | sed -i '/cotire/d' ./CMakeLists.txt 5 | mkdir -p scan-build 6 | scan-build-7 -o ./scan-build/ cmake . 7 | mkdir -p tests/unit/logs 8 | make -j`nproc --all` |& tee ./unit-tests-build-result.txt 9 | exitstatus=${PIPESTATUS[0]} 10 | echo $exitstatus > ./build-status.txt 11 | echo 0 > tests/unit/run-tests-status.txt 12 | export TEST_ARTIFACT_FILE=/__w/libks/libks/tests/unit/logs/artifacts.html 13 | env CTEST_OUTPUT_ON_FAILURE=1 make test |& tee >(ansi2html > $TEST_ARTIFACT_FILE) 14 | exitstatus=${PIPESTATUS[0]} 15 | ls -al 16 | ls -al tests/unit/logs 17 | 18 | echo "Exist status is $exitstatus" 19 | 20 | if [ "$exitstatus" != "0" ]]; then 21 | echo "TEST_ARTIFACT_FILE=$TEST_ARTIFACT_FILE" >> $GITHUB_OUTPUT 22 | fi 23 | 24 | exit $exitstatus -------------------------------------------------------------------------------- /scan_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sed -i '/cotire/d' ./CMakeLists.txt 3 | mkdir -p scan-build 4 | scan-build-7 -o ./scan-build/ cmake . 5 | scan-build-7 -o ./scan-build/ cmake . 6 | scan-build-7 -o ./scan-build/ make -j`nproc --all` |& tee ./scan-build-result.txt 7 | exitstatus=${PIPESTATUS[0]} 8 | echo "*** Exit status is $exitstatus"; 9 | export SubString="scan-build: No bugs found"; 10 | export COMPILATION_FAILED=false; 11 | export BUGS_FOUND=false; 12 | if [ "0" -ne $exitstatus ] ; then 13 | export COMPILATION_FAILED=true; 14 | echo MESSAGE="compilation failed" >> $GITHUB_OUTPUT; 15 | fi 16 | export RESULTFILE="/__w/libks/libks/scan-build-result.txt"; 17 | cat $RESULTFILE; 18 | if ! grep -sq "$SubString" $RESULTFILE; then 19 | export BUGS_FOUND=true; 20 | echo MESSAGE="found bugs" >> $GITHUB_OUTPUT; 21 | fi 22 | echo "COMPILATION_FAILED=$COMPILATION_FAILED" >> $GITHUB_OUTPUT; 23 | echo "BUGS_FOUND=$BUGS_FOUND" >> $GITHUB_OUTPUT; 24 | if [ "0" != $exitstatus ] || ! grep -sq "$SubString" $RESULTFILE; then 25 | exit 1; 26 | fi 27 | exit 0; -------------------------------------------------------------------------------- /src/.directory: -------------------------------------------------------------------------------- 1 | [Dolphin] 2 | Timestamp=2018,4,11,17,15,45 3 | Version=3 4 | ViewMode=1 5 | -------------------------------------------------------------------------------- /src/include/cJSON/cJSON_Utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009-2017 Dave Gamble and cJSON contributors 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef cJSON_Utils__h 24 | #define cJSON_Utils__h 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | #include "cJSON.h" 32 | 33 | /* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */ 34 | CJSON_PUBLIC(kJSON *) kJSONUtils_GetPointer(kJSON * const object, const char *pointer); 35 | CJSON_PUBLIC(kJSON *) kJSONUtils_GetPointerCaseSensitive(kJSON * const object, const char *pointer); 36 | 37 | /* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */ 38 | /* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */ 39 | CJSON_PUBLIC(kJSON *) kJSONUtils_GeneratePatches(kJSON * const from, kJSON * const to); 40 | CJSON_PUBLIC(kJSON *) kJSONUtils_GeneratePatchesCaseSensitive(kJSON * const from, kJSON * const to); 41 | /* Utility for generating patch array entries. */ 42 | CJSON_PUBLIC(void) kJSONUtils_AddPatchToArray(kJSON * const array, const char * const operation, const char * const path, const kJSON * const value); 43 | /* Returns 0 for success. */ 44 | CJSON_PUBLIC(int) kJSONUtils_ApplyPatches(kJSON * const object, const kJSON * const patches); 45 | CJSON_PUBLIC(int) kJSONUtils_ApplyPatchesCaseSensitive(kJSON * const object, const kJSON * const patches); 46 | 47 | /* 48 | // Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use: 49 | //int kJSONUtils_AtomicApplyPatches(kJSON **object, kJSON *patches) 50 | //{ 51 | // kJSON *modme = kJSON_Duplicate(*object, 1); 52 | // int error = kJSONUtils_ApplyPatches(modme, patches); 53 | // if (!error) 54 | // { 55 | // kJSON_Delete(*object); 56 | // *object = modme; 57 | // } 58 | // else 59 | // { 60 | // kJSON_Delete(modme); 61 | // } 62 | // 63 | // return error; 64 | //} 65 | // Code not added to library since this strategy is a LOT slower. 66 | */ 67 | 68 | /* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */ 69 | /* target will be modified by patch. return value is new ptr for target. */ 70 | CJSON_PUBLIC(kJSON *) kJSONUtils_MergePatch(kJSON *target, const kJSON * const patch); 71 | CJSON_PUBLIC(kJSON *) kJSONUtils_MergePatchCaseSensitive(kJSON *target, const kJSON * const patch); 72 | /* generates a patch to move from -> to */ 73 | /* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */ 74 | CJSON_PUBLIC(kJSON *) kJSONUtils_GenerateMergePatch(kJSON * const from, kJSON * const to); 75 | CJSON_PUBLIC(kJSON *) kJSONUtils_GenerateMergePatchCaseSensitive(kJSON * const from, kJSON * const to); 76 | 77 | /* Given a root object and a target object, construct a pointer from one to the other. */ 78 | CJSON_PUBLIC(char *) kJSONUtils_FindPointerFromObjectTo(const kJSON * const object, const kJSON * const target); 79 | 80 | /* Sorts the members of the object into alphabetical order. */ 81 | CJSON_PUBLIC(void) kJSONUtils_SortObject(kJSON * const object); 82 | CJSON_PUBLIC(void) kJSONUtils_SortObjectCaseSensitive(kJSON * const object); 83 | 84 | #ifdef __cplusplus 85 | } 86 | #endif 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/include/libks/internal/ks_mutex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | typedef enum { 24 | KS_MUTEX_TYPE_DEFAULT, 25 | KS_MUTEX_TYPE_NON_RECURSIVE 26 | } ks_mutex_type_t; 27 | 28 | #ifdef KS_DEBUG_MUTEX 29 | typedef struct ks_mutex_lock_record_s { 30 | uint64_t owner_count; 31 | ks_pid_t owner_id; 32 | pid_t owner_unique_id; 33 | const char *owner_file; 34 | int owner_line; 35 | const char *owner_tag; 36 | } ks_mutex_lock_record_t; 37 | #endif 38 | 39 | struct ks_mutex { 40 | #ifdef WIN32 41 | CRITICAL_SECTION mutex; 42 | HANDLE handle; 43 | #else 44 | pthread_mutex_t mutex; 45 | #endif 46 | ks_mutex_type_t type; 47 | uint32_t flags; 48 | uint8_t malloc; 49 | #ifdef KS_DEBUG_MUTEX 50 | ks_mutex_lock_record_t record; 51 | #endif 52 | }; 53 | -------------------------------------------------------------------------------- /src/include/libks/internal/ks_pool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Private header definitions for memory pool. 3 | * 4 | * Copyright 1996 by Gray Watson. 5 | * 6 | * This file is part of the ks_pool package. 7 | * 8 | * Permission to use, copy, modify, and distribute this software for 9 | * any purpose and without fee is hereby granted, provided that the 10 | * above copyright notice and this permission notice appear in all 11 | * copies, and that the name of Gray Watson not be used in advertising 12 | * or publicity pertaining to distribution of the document or software 13 | * without specific, written prior permission. 14 | * 15 | * Gray Watson makes no representations about the suitability of the 16 | * software described herein for any purpose. It is provided "as is" 17 | * without express or implied warranty. 18 | * 19 | * The author may be reached via http://256.com/gray/ 20 | * 21 | * $Id: ks_mpool.c,v 1.5 2006/05/31 20:28:31 gray Exp $ 22 | */ 23 | 24 | 25 | #define KS_POOL_MAGIC 0xDEADBEEF /* magic for struct */ 26 | 27 | #define KS_POOL_PREFIX_MAGIC 0xDEADBEEF 28 | 29 | #define KS_POOL_FENCE_MAGIC0 (ks_byte_t)(0xFAU) /* 1st magic mem byte */ 30 | #define KS_POOL_FENCE_MAGIC1 (ks_byte_t)(0xD3U) /* 2nd magic mem byte */ 31 | 32 | #define KS_POOL_FENCE_SIZE 2 /* fence space */ 33 | 34 | typedef struct ks_pool_prefix_s ks_pool_prefix_t; 35 | 36 | struct ks_pool_prefix_s { 37 | ks_size_t magic1; 38 | ks_size_t size; 39 | ks_size_t magic2; 40 | ks_size_t refs; 41 | ks_pool_prefix_t *prev; 42 | ks_pool_prefix_t *next; 43 | ks_size_t magic3; 44 | #ifdef KS_DEBUG_POOL 45 | int line; 46 | const char *file; 47 | const char *tag; 48 | ks_bool_t scanned; 49 | #endif 50 | ks_pool_cleanup_callback_t cleanup_callback; 51 | void *cleanup_arg; 52 | ks_size_t magic4; 53 | ks_pool_t *pool; 54 | ks_size_t magic5; 55 | }; 56 | 57 | #define KS_POOL_PREFIX_SIZE sizeof(ks_pool_prefix_t) 58 | 59 | #define SET_POINTER(pnt, val) \ 60 | do { \ 61 | if ((pnt) != NULL) { \ 62 | (*(pnt)) = (val); \ 63 | } \ 64 | } while(0) 65 | 66 | struct ks_pool_s { 67 | ks_size_t magic1; /* magic number for struct */ 68 | ks_size_t flags; /* flags for the struct */ 69 | ks_size_t alloc_c; /* number of allocations */ 70 | ks_size_t user_alloc; /* user bytes allocated */ 71 | ks_size_t max_alloc; /* maximum user bytes allocated */ 72 | ks_pool_log_func_t log_func; /* log callback function */ 73 | ks_pool_prefix_t *first; /* first memory allocation we are using */ 74 | ks_pool_prefix_t *last; /* last memory allocation we are using */ 75 | ks_bool_t log_on_close; /* when true will log all un-released allocations on close, used for the global pool */ 76 | int line; /* line pool was allocated on (from ks_pool_open macro) */ 77 | const char *file; /* ptr to constant literal string from __FILE__ macro */ 78 | const char *tag; /* ptr to constant literal string from ks_pool_open macro */ 79 | #ifdef KS_DEBUG_POOL 80 | /* When KS_DEBUG_POOL is enabled, we can iterate pools live to diagnose them */ 81 | struct ks_pool_s *debug_first; 82 | struct ks_pool_s *debug_last; 83 | struct ks_pool_s *debug_prev; 84 | struct ks_pool_s *debug_next; 85 | #endif 86 | ks_size_t magic2; /* upper magic for overwrite sanity */ 87 | ks_mutex_t *mutex; 88 | ks_bool_t cleaning_up; 89 | }; 90 | -------------------------------------------------------------------------------- /src/include/libks/internal/ks_thread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks_atomic.h" 24 | 25 | #pragma once 26 | 27 | struct ks_thread { 28 | const char *tag; /* Must be constant literal string */ 29 | ks_pid_t id; /* The system thread id (same thing ks_thread_self_id returns) */ 30 | 31 | #ifdef KS_PLAT_WIN 32 | void *handle; 33 | #else 34 | pthread_t handle; 35 | pthread_attr_t attribute; 36 | #endif 37 | void *private_data; 38 | ks_thread_function_t function; 39 | size_t stack_size; 40 | uint32_t flags; 41 | 42 | ks_bool_t stop_requested; 43 | 44 | uint8_t priority; 45 | void *return_data; 46 | ks_pool_t *pool_to_destroy; 47 | 48 | ks_mutex_t *mutex; 49 | ks_bool_t in_use; 50 | }; 51 | -------------------------------------------------------------------------------- /src/include/libks/ks.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #pragma once 23 | 24 | #ifdef __cplusplus 25 | #define KS_BEGIN_EXTERN_C extern "C" { 26 | #define KS_END_EXTERN_C } 27 | #else 28 | #define KS_BEGIN_EXTERN_C 29 | #define KS_END_EXTERN_C 30 | #endif 31 | 32 | /* libks version as a string */ 33 | #define KS_VERSION "2.0.6" 34 | 35 | /* libks version as a number */ 36 | #define KS_VERSION_NUM 20006 37 | 38 | /* Use this to allow enabling TCP_KEEPIDLE and TCP_KEEPINTVL socket options */ 39 | //#define KS_KEEP_IDLE_INTVL 1 40 | 41 | #include "libks/ks_platform.h" 42 | #include "libks/ks_types.h" 43 | 44 | /* 45 | * bitflag tools 46 | */ 47 | #define KS_BIT_FLAG(x) (1 << (x)) 48 | #define KS_BIT_SET(v,f) ((v) |= (f)) 49 | #define KS_BIT_CLEAR(v,f) ((v) &= ~(f)) 50 | #define KS_BIT_IS_SET(v,f) ((v) & (f)) 51 | #define KS_BIT_TOGGLE(v,f) ((v) ^= (f)) 52 | 53 | KS_BEGIN_EXTERN_C 54 | 55 | KS_DECLARE(ks_status_t) ks_init(void); 56 | KS_DECLARE(ks_status_t) ks_shutdown(void); 57 | KS_DECLARE(ks_pool_t *) ks_global_pool(void); 58 | 59 | KS_END_EXTERN_C 60 | 61 | #include "libks/ks_log.h" 62 | #include "libks/ks_env.h" 63 | #include "libks/ks_string.h" 64 | #include "libks/ks_printf.h" 65 | #include "libks/ks_json.h" 66 | #include "libks/ks_json_check.h" 67 | #include "libks/ks_pool.h" 68 | #include "libks/ks_threadmutex.h" 69 | #include "libks/ks_debug.h" 70 | #include "libks/ks_json.h" 71 | #include "libks/ks_thread_pool.h" 72 | #include "libks/ks_hash.h" 73 | #include "libks/ks_config.h" 74 | #include "libks/ks_q.h" 75 | #include "libks/ks_buffer.h" 76 | #include "libks/ks_time.h" 77 | #include "libks/ks_socket.h" 78 | #include "libks/ks_dso.h" 79 | #include "libks/simclist.h" 80 | #include "libks/ks_ssl.h" 81 | #include "libks/kws.h" 82 | #include "libks/ks_uuid.h" 83 | #include "libks/ks_acl.h" 84 | #include "libks/ks_base64.h" 85 | #include "libks/ks_time.h" 86 | #include "libks/ks_sb.h" 87 | #include "libks/ks_utf8.h" 88 | #include "libks/ks_atomic.h" 89 | #include "libks/ks_metrics.h" 90 | 91 | /* For Emacs: 92 | * Local Variables: 93 | * mode:c 94 | * indent-tabs-mode:t 95 | * tab-width:4 96 | * c-basic-offset:4 97 | * End: 98 | * For VIM: 99 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 100 | */ 101 | -------------------------------------------------------------------------------- /src/include/libks/ks_acl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | 24 | #pragma once 25 | 26 | KS_BEGIN_EXTERN_C 27 | 28 | typedef union{ 29 | uint32_t v4; 30 | struct in6_addr v6; 31 | } ks_ip_t; 32 | 33 | 34 | #define switch_network_list_validate_ip(_list, _ip) switch_network_list_validate_ip_token(_list, _ip, NULL); 35 | 36 | #define switch_test_subnet(_ip, _net, _mask) (_mask ? ((_net & _mask) == (_ip & _mask)) : _net ? _net == _ip : 1) 37 | 38 | KS_DECLARE(int) ks_parse_cidr(const char *string, ks_ip_t *ip, ks_ip_t *mask, uint32_t *bitp); 39 | KS_DECLARE(ks_status_t) ks_network_list_create(ks_network_list_t **list, const char *name, ks_bool_t default_type, 40 | ks_pool_t *pool); 41 | KS_DECLARE(ks_status_t) ks_network_list_add_cidr_token(ks_network_list_t *list, const char *cidr_str, ks_bool_t ok, const char *token); 42 | #define ks_network_list_add_cidr(_list, _cidr_str, _ok) ks_network_list_add_cidr_token(_list, _cidr_str, _ok, NULL) 43 | 44 | KS_DECLARE(char *) ks_network_ipv4_mapped_ipv6_addr(const char* ip_str); 45 | KS_DECLARE(ks_status_t) ks_network_list_add_host_mask(ks_network_list_t *list, const char *host, const char *mask_str, ks_bool_t ok); 46 | KS_DECLARE(ks_bool_t) ks_network_list_validate_ip_token(ks_network_list_t *list, uint32_t ip, const char **token); 47 | KS_DECLARE(ks_bool_t) ks_network_list_validate_ip6_token(ks_network_list_t *list, ks_ip_t ip, const char **token); 48 | 49 | #define ks_network_list_validate_ip(_list, _ip) ks_network_list_validate_ip_token(_list, _ip, NULL); 50 | 51 | #define ks_test_subnet(_ip, _net, _mask) (_mask ? ((_net & _mask) == (_ip & _mask)) : _net ? _net == _ip : 1) 52 | 53 | KS_DECLARE(ks_bool_t) ks_check_network_list_ip_cidr(const char *ip_str, const char *cidr_str); 54 | KS_DECLARE(ks_bool_t) ks_check_network_list_ip_token(const char *ip_str, ks_network_list_t *list, const char **token); 55 | #define ks_check_network_list_ip(_i, _l) ks_check_network_list_ip_token(_i, _l, NULL) 56 | 57 | #define ks_inet_pton inet_pton 58 | 59 | KS_END_EXTERN_C 60 | 61 | /* For Emacs: 62 | * Local Variables: 63 | * mode:c 64 | * indent-tabs-mode:t 65 | * tab-width:4 66 | * c-basic-offset:4 67 | * End: 68 | * For VIM: 69 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 70 | */ 71 | 72 | -------------------------------------------------------------------------------- /src/include/libks/ks_atomic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #ifndef __KS_ATOMIC_H__ 24 | #define __KS_ATOMIC_H__ 25 | 26 | KS_BEGIN_EXTERN_C 27 | 28 | /** 29 | * ks_atomic_increment_* - Atomically increments the value, and returns the value before the increment ocurred. 30 | * ks_atomic_cas_* - Atomically compares, and performs an exchange on the types if they are the same. 31 | */ 32 | #ifdef KS_PLAT_WIN // Windows 33 | #pragma warning(disable:4057) 34 | 35 | static inline uint32_t ks_atomic_increment_uint32(volatile uint32_t *value) { return InterlockedIncrement(value) - 1; } 36 | 37 | static inline uint64_t ks_atomic_increment_uint64(volatile uint64_t *value) { return InterlockedIncrement64((volatile LONG64 *)value) - 1; } 38 | 39 | static inline ks_size_t ks_atomic_increment_size(volatile ks_size_t *value) { return InterlockedIncrementSizeT(value) - 1; } 40 | 41 | static inline uint32_t ks_atomic_decrement_uint32(volatile uint32_t *value) { return InterlockedDecrement(value) + 1; } 42 | 43 | static inline uint64_t ks_atomic_decrement_uint64(volatile uint64_t *value) { return InterlockedDecrement64((volatile LONG64 *)value) + 1; } 44 | 45 | static inline ks_size_t ks_atomic_decrement_size(volatile ks_size_t *value) { return InterlockedDecrementSizeT(value) + 1; } 46 | 47 | #else // GCC/CLANG 48 | 49 | static inline uint32_t ks_atomic_increment_uint32(volatile uint32_t *value) { return __atomic_fetch_add(value, 1, __ATOMIC_SEQ_CST); } 50 | 51 | static inline uint64_t ks_atomic_increment_uint64(volatile uint64_t *value) { return __atomic_fetch_add(value, 1, __ATOMIC_SEQ_CST); } 52 | 53 | static inline ks_size_t ks_atomic_increment_size(volatile ks_size_t *value) { return __atomic_fetch_add(value, 1, __ATOMIC_SEQ_CST); } 54 | 55 | static inline uint32_t ks_atomic_decrement_uint32(volatile uint32_t *value) { return __atomic_fetch_add(value, -1, __ATOMIC_SEQ_CST); } 56 | 57 | static inline uint64_t ks_atomic_decrement_uint64(volatile uint64_t *value) { return __atomic_fetch_add(value, -1, __ATOMIC_SEQ_CST); } 58 | 59 | static inline ks_size_t ks_atomic_decrement_size(volatile ks_size_t *value) { return __atomic_fetch_add(value, -1, __ATOMIC_SEQ_CST); } 60 | 61 | #endif 62 | 63 | /* Define spinlock macros */ 64 | typedef struct ks_spinlock_s 65 | { 66 | volatile uint32_t count; 67 | #if defined(KS_DEBUG_SPINLOCK) 68 | ks_pid_t owner_id; 69 | #endif 70 | } ks_spinlock_t; 71 | 72 | static inline ks_bool_t ks_spinlock_try_acquire(const ks_spinlock_t *lock) 73 | { 74 | if (ks_atomic_increment_uint32((volatile uint32_t *)&lock->count)) { 75 | ks_atomic_decrement_uint32((volatile uint32_t *)&lock->count); 76 | #if KS_DEBUG_SPINLOCK 77 | printf("SPINLOCK TRY-ACQUIRE FAIL address: %p, count: %lu\n", (void *)lock, lock->count); 78 | ks_assert(lock->owner_id != ks_thread_self_id()); 79 | #endif 80 | 81 | return KS_FALSE; 82 | } 83 | 84 | #if KS_DEBUG_SPINLOCK 85 | printf("SPINLOCK TRY-ACQUIRE address: %p, count: %lu\n", (void *)lock, lock->count); 86 | ((ks_spinlock_t *)lock)->owner_id = ks_thread_self_id(); 87 | #endif 88 | 89 | return KS_TRUE; 90 | } 91 | 92 | static inline void ks_spinlock_acquire(const ks_spinlock_t *lock) 93 | { 94 | uint64_t __wait_count = 0; 95 | while (!ks_spinlock_try_acquire(lock)) { 96 | 97 | /* Lower the priority as we wait */ 98 | __wait_count++; 99 | if (__wait_count > 100000) { 100 | ks_sleep(100); 101 | } else if (__wait_count > 10000) { 102 | ks_sleep(10); 103 | } else if (__wait_count > 1000) { 104 | ks_sleep(1); 105 | } else if (__wait_count > 100) { 106 | ks_sleep(0); 107 | } 108 | } 109 | 110 | #if KS_DEBUG_SPINLOCK 111 | printf("SPINLOCK ACQUIRE address: %p, count: %lu\n", (void *)lock, lock->count); 112 | #endif 113 | } 114 | 115 | static inline void ks_spinlock_release(const ks_spinlock_t *lock) 116 | { 117 | #if KS_DEBUG_SPINLOCK 118 | printf("SPINLOCK RELEASE address: %p, count: %lu\n", (void *)lock, lock->count); 119 | ks_assert(lock->count != 0); 120 | ((ks_spinlock_t*)lock)->owner_id = 0; 121 | #endif 122 | 123 | ks_atomic_decrement_uint32(&((ks_spinlock_t *)lock)->count); 124 | } 125 | 126 | static inline void ks_spinlock_dispatch(const ks_spinlock_t *lock, ks_time_t sleep_delay) 127 | { 128 | ks_spinlock_release(lock); 129 | ks_sleep(sleep_delay); 130 | ks_spinlock_acquire(lock); 131 | } 132 | 133 | static inline void ks_spinlock_dispatch_ms(const ks_spinlock_t *lock, ks_time_t sleep_delay) 134 | { 135 | ks_spinlock_release(lock); 136 | ks_sleep_ms(sleep_delay); 137 | ks_spinlock_acquire(lock); 138 | } 139 | 140 | KS_END_EXTERN_C 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /src/include/libks/ks_base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | 24 | #ifndef _KS_BASE64_H__ 25 | #define _KS_BASE64_H__ 26 | 27 | #include "libks/ks.h" 28 | 29 | KS_DECLARE(ks_status_t) ks_b64_encode(unsigned char *in, ks_size_t ilen, unsigned char *out, ks_size_t olen); 30 | KS_DECLARE(ks_size_t) ks_b64_decode(char *in, char *out, ks_size_t olen); 31 | 32 | #endif 33 | 34 | /* For Emacs: 35 | * Local Variables: 36 | * mode:c 37 | * indent-tabs-mode:t 38 | * tab-width:4 39 | * c-basic-offset:4 40 | * End: 41 | * For VIM: 42 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 43 | */ 44 | -------------------------------------------------------------------------------- /src/include/libks/ks_buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #ifndef KS_BUFFER_H 23 | #define KS_BUFFER_H 24 | 25 | #include "ks.h" 26 | 27 | KS_BEGIN_EXTERN_C 28 | 29 | /** 30 | * @defgroup ks_buffer Buffer Routines 31 | * @ingroup buffer 32 | * The purpose of this module is to make a plain buffering interface that can be used for read/write buffers 33 | * throughout the application. 34 | * @{ 35 | */ 36 | struct ks_buffer; 37 | typedef struct ks_buffer ks_buffer_t; 38 | 39 | /*! \brief Allocate a new dynamic ks_buffer 40 | * \param buffer returned pointer to the new buffer 41 | * \param blocksize length to realloc by as data is added 42 | * \param start_len ammount of memory to reserve initially 43 | * \param max_len length the buffer is allowed to grow to 44 | * \return status 45 | */ 46 | KS_DECLARE(ks_status_t) ks_buffer_create(ks_buffer_t **buffer, ks_size_t blocksize, ks_size_t start_len, ks_size_t max_len); 47 | 48 | /*! \brief Get the length of a ks_buffer_t 49 | * \param buffer any buffer of type ks_buffer_t 50 | * \return int size of the buffer. 51 | */ 52 | KS_DECLARE(ks_size_t) ks_buffer_len(ks_buffer_t *buffer); 53 | 54 | /*! \brief Get the freespace of a ks_buffer_t 55 | * \param buffer any buffer of type ks_buffer_t 56 | * \return int freespace in the buffer. 57 | */ 58 | KS_DECLARE(ks_size_t) ks_buffer_freespace(ks_buffer_t *buffer); 59 | 60 | /*! \brief Get the in use amount of a ks_buffer_t 61 | * \param buffer any buffer of type ks_buffer_t 62 | * \return int ammount of buffer curently in use 63 | */ 64 | KS_DECLARE(ks_size_t) ks_buffer_inuse(ks_buffer_t *buffer); 65 | 66 | /*! \brief Read data from a ks_buffer_t up to the ammount of datalen if it is available. Remove read data from buffer. 67 | * \param buffer any buffer of type ks_buffer_t 68 | * \param data pointer to the read data to be returned 69 | * \param datalen amount of data to be returned 70 | * \return int ammount of data actually read 71 | */ 72 | KS_DECLARE(ks_size_t) ks_buffer_read(ks_buffer_t *buffer, void *data, ks_size_t datalen); 73 | 74 | KS_DECLARE(ks_size_t) ks_buffer_read_packet(ks_buffer_t *buffer, void *data, ks_size_t maxlen); 75 | KS_DECLARE(ks_size_t) ks_buffer_packet_count(ks_buffer_t *buffer); 76 | 77 | /*! \brief Read data endlessly from a ks_buffer_t 78 | * \param buffer any buffer of type ks_buffer_t 79 | * \param data pointer to the read data to be returned 80 | * \param datalen amount of data to be returned 81 | * \return int ammount of data actually read 82 | * \note Once you have read all the data from the buffer it will loop around. 83 | */ 84 | KS_DECLARE(ks_size_t) ks_buffer_read_loop(ks_buffer_t *buffer, void *data, ks_size_t datalen); 85 | 86 | /*! \brief Assign a number of loops to read 87 | * \param buffer any buffer of type ks_buffer_t 88 | * \param loops the number of loops (-1 for infinite) 89 | */ 90 | KS_DECLARE(void) ks_buffer_set_loops(ks_buffer_t *buffer, int32_t loops); 91 | 92 | /*! \brief Write data into a ks_buffer_t up to the length of datalen 93 | * \param buffer any buffer of type ks_buffer_t 94 | * \param data pointer to the data to be written 95 | * \param datalen amount of data to be written 96 | * \return int amount of buffer used after the write, or 0 if no space available 97 | */ 98 | KS_DECLARE(ks_size_t) ks_buffer_write(ks_buffer_t *buffer, const void *data, ks_size_t datalen); 99 | 100 | /*! \brief Remove data from the buffer 101 | * \param buffer any buffer of type ks_buffer_t 102 | * \param datalen amount of data to be removed 103 | * \return int size of buffer, or 0 if unable to toss that much data 104 | */ 105 | KS_DECLARE(ks_size_t) ks_buffer_toss(ks_buffer_t *buffer, ks_size_t datalen); 106 | 107 | /*! \brief Remove all data from the buffer 108 | * \param buffer any buffer of type ks_buffer_t 109 | */ 110 | KS_DECLARE(void) ks_buffer_zero(ks_buffer_t *buffer); 111 | 112 | /*! \brief Destroy the buffer 113 | * \param buffer buffer to destroy 114 | * \note only neccessary on dynamic buffers (noop on pooled ones) 115 | */ 116 | KS_DECLARE(void) ks_buffer_destroy(ks_buffer_t **buffer); 117 | 118 | /*! \brief Seek to offset from the beginning of the buffer 119 | * \param buffer buffer to seek 120 | * \param datalen offset in bytes 121 | * \return new position 122 | */ 123 | KS_DECLARE(ks_size_t) ks_buffer_seek(ks_buffer_t *buffer, ks_size_t datalen); 124 | 125 | /** @} */ 126 | 127 | KS_DECLARE(ks_size_t) ks_buffer_zwrite(ks_buffer_t *buffer, const void *data, ks_size_t datalen); 128 | 129 | KS_END_EXTERN_C 130 | #endif 131 | /* For Emacs: 132 | * Local Variables: 133 | * mode:c 134 | * indent-tabs-mode:t 135 | * tab-width:4 136 | * c-basic-offset:4 137 | * End: 138 | * For VIM: 139 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 140 | */ 141 | -------------------------------------------------------------------------------- /src/include/libks/ks_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @defgroup config Config File Parser 25 | * @ingroup config 26 | * This module implements a basic interface and file format parser 27 | * 28 | *
 29 |  *
 30 |  * EXAMPLE 
 31 |  * 
 32 |  * [category1]
 33 |  * var1 => val1
 34 |  * var2 => val2
 35 |  * \# lines that begin with \# are comments
 36 |  * \#var3 => val3
 37 |  * 
38 | * @{ 39 | */ 40 | 41 | #ifndef KS_CONFIG_H 42 | #define KS_CONFIG_H 43 | 44 | KS_BEGIN_EXTERN_C 45 | 46 | #include "ks.h" 47 | 48 | #define KS_URL_SEPARATOR "://" 49 | 50 | #ifdef WIN32 51 | #define KS_PATH_SEPARATOR "\\" 52 | #ifndef KS_CONFIG_DIR 53 | #define KS_CONFIG_DIR "c:\\openks" 54 | #endif 55 | #define ks_is_file_path(file) (*(file +1) == ':' || *file == '/' || strstr(file, SWITCH_URL_SEPARATOR)) 56 | #else 57 | #define KS_PATH_SEPARATOR "/" 58 | #ifndef KS_CONFIG_DIR 59 | #define KS_CONFIG_DIR "/etc/openks" 60 | #endif 61 | #define ks_is_file_path(file) ((*file == '/') || strstr(file, SWITCH_URL_SEPARATOR)) 62 | #endif 63 | 64 | /*! 65 | \brief Evaluate the truthfullness of a string expression 66 | \param expr a string expression 67 | \return true or false 68 | */ 69 | #define ks_true(expr)\ 70 | (expr && ( !strcasecmp(expr, "yes") ||\ 71 | !strcasecmp(expr, "on") ||\ 72 | !strcasecmp(expr, "true") ||\ 73 | !strcasecmp(expr, "enabled") ||\ 74 | !strcasecmp(expr, "active") ||\ 75 | !strcasecmp(expr, "allow") ||\ 76 | atoi(expr))) ? 1 : 0 77 | 78 | /*! 79 | \brief Evaluate the falsefullness of a string expression 80 | \param expr a string expression 81 | \return true or false 82 | */ 83 | #define ks_false(expr)\ 84 | (expr && ( !strcasecmp(expr, "no") ||\ 85 | !strcasecmp(expr, "off") ||\ 86 | !strcasecmp(expr, "false") ||\ 87 | !strcasecmp(expr, "disabled") ||\ 88 | !strcasecmp(expr, "inactive") ||\ 89 | !strcasecmp(expr, "disallow") ||\ 90 | !atoi(expr))) ? 1 : 0 91 | 92 | typedef struct ks_config ks_config_t; 93 | 94 | /*! \brief A simple file handle representing an open configuration file **/ 95 | struct ks_config { 96 | /*! FILE stream buffer to the opened file */ 97 | FILE *file; 98 | /*! path to the file */ 99 | char path[512]; 100 | /*! current category */ 101 | char category[256]; 102 | /*! current section */ 103 | char section[256]; 104 | /*! buffer of current line being read */ 105 | char buf[1024]; 106 | /*! current line number in file */ 107 | int lineno; 108 | /*! current category number in file */ 109 | int catno; 110 | /*! current section number in file */ 111 | int sectno; 112 | 113 | int lockto; 114 | }; 115 | 116 | /*! 117 | \brief Open a configuration file 118 | \param cfg (ks_config_t *) config handle to use 119 | \param file_path path to the file 120 | \return 1 (true) on success 0 (false) on failure 121 | */ 122 | KS_DECLARE(int) ks_config_open_file(ks_config_t *cfg, const char *file_path); 123 | 124 | /*! 125 | \brief Close a previously opened configuration file 126 | \param cfg (ks_config_t *) config handle to use 127 | */ 128 | KS_DECLARE(void) ks_config_close_file(ks_config_t *cfg); 129 | 130 | /*! 131 | \brief Retrieve next name/value pair from configuration file 132 | \param cfg (ks_config_t *) config handle to use 133 | \param var pointer to aim at the new variable name 134 | \param val pointer to aim at the new value 135 | */ 136 | KS_DECLARE(int) ks_config_next_pair(ks_config_t *cfg, char **var, char **val); 137 | 138 | /*! 139 | \brief Retrieve the CAS bits from a configuration string value 140 | \param strvalue pointer to the configuration string value (expected to be in format whatever:xxxx) 141 | \param outbits pointer to aim at the CAS bits 142 | */ 143 | KS_DECLARE(int) ks_config_get_cas_bits(char *strvalue, unsigned char *outbits); 144 | 145 | 146 | /** @} */ 147 | 148 | KS_END_EXTERN_C 149 | #endif /* defined(KS_CONFIG_H) */ 150 | /* For Emacs: 151 | * Local Variables: 152 | * mode:c 153 | * indent-tabs-mode:t 154 | * tab-width:4 155 | * c-basic-offset:4 156 | * End: 157 | * For VIM: 158 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 159 | */ 160 | -------------------------------------------------------------------------------- /src/include/libks/ks_debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #ifndef _KS_DEBUG_H_ 24 | #define _KS_DEBUG_H_ 25 | 26 | KS_BEGIN_EXTERN_C 27 | 28 | #define ks_abort_fmt(fmt, ...) \ 29 | do { \ 30 | const char *msg = ks_thr_sprintf(fmt, __VA_ARGS__); \ 31 | ks_log(KS_LOG_CRIT, "\n\nABORT: (%s)\nLOCATION:%s %s:%d\nTHREAD ID: %8.8lx\n\n", msg, __KS_FUNC__, __FILE__, __LINE__, ks_thread_self_id()); \ 32 | ks_log(KS_LOG_CRIT, "BACKTRACE:"); \ 33 | ks_debug_dump_backtrace(); \ 34 | abort(); \ 35 | } while (KS_FALSE) 36 | 37 | #define ks_abort(msg) \ 38 | do { \ 39 | ks_log(KS_LOG_CRIT, "\n\nABORT: (%s)\nLOCATION:%s %s:%d\nTHREAD ID: %8.8lx\n\n", msg, __KS_FUNC__, __FILE__, __LINE__, ks_thread_self_id()); \ 40 | ks_log(KS_LOG_CRIT, "BACKTRACE:"); \ 41 | ks_debug_dump_backtrace(); \ 42 | abort(); \ 43 | } while (KS_FALSE) 44 | 45 | #define ks_assertd(expr) \ 46 | do { \ 47 | if (!(expr)) { \ 48 | ks_abort_fmt( \ 49 | "ASSERTION FAILURE '%s'", \ 50 | #expr \ 51 | ); \ 52 | } \ 53 | } while (KS_FALSE) 54 | 55 | #if NDEBUG 56 | #define ks_assert(expr) 57 | #else 58 | #define ks_assert(expr) ks_assertd(expr) 59 | #endif 60 | 61 | KS_DECLARE(void) ks_debug_dump_backtrace(void); 62 | 63 | KS_DECLARE(void) ks_debug_break(void); 64 | 65 | KS_END_EXTERN_C 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/include/libks/ks_dso.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "ks.h" 24 | 25 | #ifndef _KS_DSO_H 26 | #define _KS_DSO_H 27 | 28 | KS_BEGIN_EXTERN_C 29 | 30 | //typedef void (*ks_func_ptr_t) (void); 31 | typedef void * ks_dso_lib_t; 32 | typedef struct ks_dso_s ks_dso_t; 33 | typedef struct ks_dso_callbacks_s ks_dso_callbacks_t; 34 | 35 | struct ks_dso_s { 36 | ks_dso_lib_t lib; 37 | char *name; 38 | ks_dso_callbacks_t *callbacks; 39 | ks_pool_t *pool; 40 | void *data1; 41 | void *data2; 42 | }; 43 | 44 | #define KS_DSO_CALLBACK_ARGS (ks_dso_t *dso) 45 | 46 | typedef ks_status_t (*ks_dso_callback_t) KS_DSO_CALLBACK_ARGS; 47 | 48 | struct ks_dso_callbacks_s { 49 | ks_dso_callback_t load; 50 | ks_dso_callback_t unload; 51 | }; 52 | 53 | #define KS_DSO_LOAD_FUNCTION(name) ks_status_t name KS_DSO_CALLBACK_ARGS 54 | #define KS_DSO_UNLOAD_FUNCTION(name) ks_status_t name KS_DSO_CALLBACK_ARGS 55 | 56 | 57 | #define KS_DSO_DEFINITION(name, load, unload) \ 58 | KS_DECLARE_DATA ks_dso_callbacks_t name##_dso_callbacks = { \ 59 | load, \ 60 | unload \ 61 | } 62 | 63 | KS_DECLARE(void) ks_dso_shutdown(void); 64 | 65 | KS_DECLARE(ks_status_t) ks_dso_destroy(ks_dso_lib_t *lib); 66 | KS_DECLARE(ks_dso_lib_t) ks_dso_open(const char *path, char **err); 67 | KS_DECLARE(void *) ks_dso_get_sym(ks_dso_lib_t lib, const char *sym, char **err); 68 | //KS_DECLARE(char *) ks_build_dso_path(const char *name, char *path, ks_size_t len); 69 | 70 | KS_DECLARE(ks_status_t) ks_dso_load(const char *name, void *data1, void *data2); 71 | KS_DECLARE(ks_status_t) ks_dso_unload(const char *name); 72 | 73 | KS_END_EXTERN_C 74 | 75 | #endif 76 | 77 | /* For Emacs: 78 | * Local Variables: 79 | * mode:c 80 | * indent-tabs-mode:t 81 | * tab-width:4 82 | * c-basic-offset:4 83 | * End: 84 | * For VIM: 85 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 86 | */ 87 | 88 | -------------------------------------------------------------------------------- /src/include/libks/ks_env.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | KS_BEGIN_EXTERN_C 26 | 27 | KS_DECLARE(int) ks_env_cpu_count(void); 28 | 29 | KS_END_EXTERN_C 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/include/libks/ks_log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #pragma once 23 | 24 | KS_BEGIN_EXTERN_C 25 | 26 | KS_DECLARE(void) ks_log_init(void); 27 | KS_DECLARE(void) ks_log_shutdown(void); 28 | 29 | KS_DECLARE(void) ks_log(const char *file, const char *func, int line, int level, const char *fmt, ...); 30 | 31 | KS_DECLARE(ks_size_t) ks_log_format_output(char *buf, ks_size_t bufSize, const char *file, const char *func, int line, int level, const char *fmt, va_list ap); 32 | 33 | /*! Gets the log level from a string name, returns -1 if invalid */ 34 | KS_DECLARE(int) ks_log_level_by_name(const char *name); 35 | /*! Sets the logger for libks. Default is the null_logger */ 36 | KS_DECLARE(void) ks_global_set_logger(ks_logger_t logger); 37 | /*! Sets the default log prefix for libks */ 38 | KS_DECLARE(void) ks_global_set_default_logger_prefix(ks_log_prefix_t prefix); 39 | /*! Sets the global console log level */ 40 | KS_DECLARE(void) ks_global_set_log_level(int level); 41 | /*! Enable json based log output */ 42 | KS_DECLARE(void) ks_log_jsonify(void); 43 | /*! Sanitizes output strings */ 44 | KS_DECLARE(void) ks_log_sanitize_string(char *str); 45 | /*! Enclose the JSON logs into an object with the given name */ 46 | KS_DECLARE(void) ks_log_json_set_enclosing_name(char const*name); 47 | 48 | KS_END_EXTERN_C 49 | -------------------------------------------------------------------------------- /src/include/libks/ks_metrics.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | KS_BEGIN_EXTERN_C 26 | 27 | KS_DECLARE(ks_status_t) ks_metrics_cpu(double *cpu, int samples, int interval); 28 | 29 | KS_END_EXTERN_C 30 | 31 | /* For Emacs: 32 | * Local Variables: 33 | * mode:c 34 | * indent-tabs-mode:t 35 | * tab-width:4 36 | * c-basic-offset:4 37 | * End: 38 | * For VIM: 39 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 40 | */ 41 | 42 | -------------------------------------------------------------------------------- /src/include/libks/ks_printf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2001 September 22 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | */ 13 | #ifndef KS_PRINTF_H 14 | #define KS_PRINTF_H 15 | 16 | #include "ks.h" 17 | 18 | KS_BEGIN_EXTERN_C 19 | 20 | /** 21 | * This routine is a variant of the "sprintf()" from the 22 | * standard C library. The resulting string is written into memory 23 | * obtained from malloc() so that there is never a possiblity of buffer 24 | * overflow. This routine also implement some additional formatting 25 | * options that are useful for constructing SQL statements. 26 | * 27 | * The strings returned by this routine should be freed by calling 28 | * free(). 29 | * 30 | * All of the usual printf formatting options apply. In addition, there 31 | * is a "%q" option. %q works like %s in that it substitutes a null-terminated 32 | * string from the argument list. But %q also doubles every '\'' character. 33 | * %q is designed for use inside a string literal. By doubling each '\'' 34 | * character it escapes that character and allows it to be inserted into 35 | * the string. 36 | * 37 | * For example, so some string variable contains text as follows: 38 | * 39 | * char *zText = "It's a happy day!"; 40 | * 41 | * We can use this text in an SQL statement as follows: 42 | * 43 | * char *z = ks_mprintf("INSERT INTO TABLES('%q')", zText); 44 | * ks_core_db_exec(db, z, callback1, 0, 0); 45 | * free(z); 46 | * 47 | * Because the %q format string is used, the '\'' character in zText 48 | * is escaped and the SQL generated is as follows: 49 | * 50 | * INSERT INTO table1 VALUES('It''s a happy day!') 51 | * 52 | * This is correct. Had we used %s instead of %q, the generated SQL 53 | * would have looked like this: 54 | * 55 | * INSERT INTO table1 VALUES('It's a happy day!'); 56 | * 57 | * This second example is an SQL syntax error. As a general rule you 58 | * should always use %q instead of %s when inserting text into a string 59 | * literal. 60 | */ 61 | KS_DECLARE(char *) ks_mprintf(const char *zFormat, ...); 62 | KS_DECLARE(char *) ks_vmprintf(const char *zFormat, va_list ap); 63 | KS_DECLARE(char *) ks_vsnprintfv(char *zBuf, int n, const char *zFormat, va_list ap); 64 | KS_DECLARE(char *) ks_snprintfv(char *zBuf, int n, const char *zFormat, ...); 65 | KS_DECLARE(char *) ks_vsnprintf(char *zbuf, int n, const char *zFormat, va_list ap); 66 | 67 | /* We define these this way to capture the context in which they were allocated */ 68 | KS_DECLARE(char *) __ks_vpprintf(ks_pool_t *pool, const char *zFormat, va_list ap, const char *file, int line, const char *tag); 69 | KS_DECLARE(char *) __ks_pprintf(const char *file, int line, const char *tag, ks_pool_t *pool, const char *zFormat, ...); 70 | 71 | #define ks_vpprintf(pool, zFormat, ap) __ks_vpprintf(pool, zFormat, ap, __FILE__, __LINE__, __KS_FUNC__) 72 | #define ks_pprintf(pool, zFormat, ...) __ks_pprintf(__FILE__, __LINE__, __KS_FUNC__, pool, zFormat, __VA_ARGS__) 73 | 74 | KS_END_EXTERN_C 75 | 76 | #endif /* KS_PRINTF_H */ 77 | 78 | /* For Emacs: 79 | * Local Variables: 80 | * mode:c 81 | * indent-tabs-mode:t 82 | * tab-width:4 83 | * c-basic-offset:4 84 | * End: 85 | * For VIM: 86 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 87 | */ 88 | -------------------------------------------------------------------------------- /src/include/libks/ks_q.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #ifndef _KS_Q_H_ 24 | #define _KS_Q_H_ 25 | 26 | #include "ks.h" 27 | 28 | KS_BEGIN_EXTERN_C 29 | 30 | KS_DECLARE(ks_status_t) ks_q_pop_timeout(ks_q_t *q, void **ptr, uint32_t timeout); 31 | KS_DECLARE(ks_status_t) ks_q_wake(ks_q_t *q); 32 | KS_DECLARE(ks_status_t) ks_q_flush(ks_q_t *q); 33 | KS_DECLARE(ks_status_t) ks_q_set_flush_fn(ks_q_t *q, ks_flush_fn_t fn, void *flush_data); 34 | KS_DECLARE(ks_status_t) ks_q_wait(ks_q_t *q); 35 | KS_DECLARE(ks_size_t) ks_q_term(ks_q_t *q); 36 | KS_DECLARE(ks_size_t) ks_q_size(ks_q_t *q); 37 | KS_DECLARE(ks_size_t) ks_q_maxlen(ks_q_t *q); 38 | KS_DECLARE(ks_status_t) ks_q_destroy(ks_q_t **qP); 39 | KS_DECLARE(ks_status_t) ks_q_create(ks_q_t **qP, ks_pool_t *pool, ks_size_t maxlen); 40 | KS_DECLARE(ks_status_t) ks_q_push(ks_q_t *q, void *ptr); 41 | KS_DECLARE(ks_status_t) ks_q_trypush(ks_q_t *q, void *ptr); 42 | KS_DECLARE(ks_status_t) ks_q_pop(ks_q_t *q, void **ptr); 43 | KS_DECLARE(ks_status_t) ks_q_trypop(ks_q_t *q, void **ptr); 44 | KS_DECLARE(ks_status_t) ks_q_trypeek(ks_q_t *q, void **ptr); 45 | 46 | KS_END_EXTERN_C 47 | 48 | #endif /* defined(_KS_Q_H_) */ 49 | 50 | /* For Emacs: 51 | * Local Variables: 52 | * mode:c 53 | * indent-tabs-mode:t 54 | * tab-width:4 55 | * c-basic-offset:4 56 | * End: 57 | * For VIM: 58 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 59 | */ 60 | -------------------------------------------------------------------------------- /src/include/libks/ks_sb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #ifndef __KS_SB_H__ 23 | #define __KS_SB_H__ 24 | 25 | #include "ks.h" 26 | 27 | KS_BEGIN_EXTERN_C 28 | 29 | typedef struct ks_sb_s ks_sb_t; 30 | 31 | KS_DECLARE(ks_status_t) ks_sb_create(ks_sb_t **sbP, ks_pool_t *pool, ks_size_t preallocated); 32 | KS_DECLARE(ks_status_t) ks_sb_destroy(ks_sb_t **sbP); 33 | KS_DECLARE(const char *) ks_sb_cstr(ks_sb_t *sb); 34 | KS_DECLARE(ks_size_t) ks_sb_length(ks_sb_t *sb); 35 | KS_DECLARE(ks_status_t) ks_sb_accommodate(ks_sb_t *sb, ks_size_t len); 36 | KS_DECLARE(ks_status_t) ks_sb_append(ks_sb_t *sb, const char *str); 37 | KS_DECLARE(ks_status_t) ks_sb_append_ex(ks_sb_t *sb, const char *str, ks_size_t len); 38 | KS_DECLARE(ks_status_t) ks_sb_printf(ks_sb_t *sb, const char *fmt, ...); 39 | KS_DECLARE(ks_status_t) ks_sb_json(ks_sb_t *sb, ks_json_t *json); 40 | 41 | KS_END_EXTERN_C 42 | 43 | #endif 44 | 45 | /* For Emacs: 46 | * Local Variables: 47 | * mode:c 48 | * indent-tabs-mode:t 49 | * tab-width:4 50 | * c-basic-offset:4 51 | * End: 52 | * For VIM: 53 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 54 | */ 55 | -------------------------------------------------------------------------------- /src/include/libks/ks_socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #ifndef _KS_SOCKET_H_ 24 | #define _KS_SOCKET_H_ 25 | 26 | #include "ks.h" 27 | 28 | #ifndef WIN32 29 | #include 30 | #endif 31 | 32 | KS_BEGIN_EXTERN_C 33 | 34 | #define KS_SO_NONBLOCK 2999 35 | 36 | #ifdef WIN32 37 | #define SHUT_RDWR SD_BOTH 38 | 39 | static __inline int ks_errno(void) 40 | { 41 | return WSAGetLastError(); 42 | } 43 | 44 | static __inline int ks_errno_is_blocking(int errcode) 45 | { 46 | return errcode == WSAEWOULDBLOCK || errcode == WSAEINPROGRESS || errcode == 35 || errcode == 730035; 47 | } 48 | 49 | static __inline int ks_errno_is_interupt(int errcode) 50 | { 51 | return 0; 52 | } 53 | 54 | #else 55 | 56 | static inline int ks_errno(void) 57 | { 58 | return errno; 59 | } 60 | 61 | static inline int ks_errno_is_blocking(int errcode) 62 | { 63 | return errcode == EAGAIN || errcode == EWOULDBLOCK || errcode == EINPROGRESS || errcode == EINTR || errcode == ETIMEDOUT || errcode == 35 || errcode == 730035; 64 | } 65 | 66 | static inline int ks_errno_is_interupt(int errcode) 67 | { 68 | return errcode == EINTR; 69 | } 70 | 71 | #endif 72 | 73 | static __inline int ks_socket_valid(ks_socket_t s) { 74 | return s != KS_SOCK_INVALID; 75 | } 76 | 77 | #define KS_SA_INIT {AF_INET}; 78 | 79 | KS_DECLARE(ks_status_t) ks_socket_send(ks_socket_t sock, void *data, ks_size_t *datalen); 80 | KS_DECLARE(ks_status_t) ks_socket_recv(ks_socket_t sock, void *data, ks_size_t *datalen); 81 | KS_DECLARE(ks_status_t) ks_socket_sendto(ks_socket_t sock, void *data, ks_size_t *datalen, ks_sockaddr_t *addr); 82 | KS_DECLARE(ks_status_t) ks_socket_recvfrom(ks_socket_t sock, void *data, ks_size_t *datalen, ks_sockaddr_t *addr); 83 | 84 | typedef struct pollfd *ks_ppollfd_t; 85 | KS_DECLARE(int) ks_poll(ks_ppollfd_t fds, uint32_t nfds, int timeout); 86 | KS_DECLARE(ks_status_t) ks_socket_option(ks_socket_t socket, int option_name, ks_bool_t enabled); 87 | KS_DECLARE(ks_status_t) ks_socket_sndbuf(ks_socket_t socket, int bufsize); 88 | KS_DECLARE(ks_status_t) ks_socket_rcvbuf(ks_socket_t socket, int bufsize); 89 | KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags); 90 | 91 | KS_DECLARE(ks_socket_t) ks_socket_connect(int type, int protocol, ks_sockaddr_t *addr); 92 | KS_DECLARE(ks_socket_t) ks_socket_connect_ex(int type, int protocol, ks_sockaddr_t *addr, uint32_t nb_timeout); 93 | KS_DECLARE(ks_status_t) ks_addr_bind(ks_socket_t server_sock, const ks_sockaddr_t *addr); 94 | KS_DECLARE(const char *) ks_addr_get_host(ks_sockaddr_t *addr); 95 | KS_DECLARE(ks_port_t) ks_addr_get_port(ks_sockaddr_t *addr); 96 | KS_DECLARE(int) ks_addr_cmp(const ks_sockaddr_t *sa1, const ks_sockaddr_t *sa2); 97 | KS_DECLARE(ks_status_t) ks_addr_copy(ks_sockaddr_t *addr, const ks_sockaddr_t *src_addr); 98 | KS_DECLARE(ks_status_t) ks_addr_set(ks_sockaddr_t *addr, const char *host, ks_port_t port, int family); 99 | KS_DECLARE(ks_status_t) ks_addr_set_raw(ks_sockaddr_t *addr, const void *data, ks_port_t port, int family); 100 | KS_DECLARE(ks_status_t) ks_addr_raw_data(const ks_sockaddr_t *addr, void **data, ks_size_t *datalen); 101 | KS_DECLARE(ks_status_t) ks_listen(const char *host, ks_port_t port, int family, int backlog, ks_listen_callback_t callback, void *user_data); 102 | KS_DECLARE(ks_status_t) ks_socket_shutdown(ks_socket_t sock, int how); 103 | KS_DECLARE(ks_status_t) ks_socket_close(ks_socket_t *sock); 104 | KS_DECLARE(ks_status_t) ks_ip_route(char *buf, int len, const char *route_ip); 105 | KS_DECLARE(ks_status_t) ks_find_local_ip(char *buf, int len, int *mask, int family, const char *route_ip); 106 | KS_DECLARE(ks_status_t) ks_listen_sock(ks_socket_t server_sock, ks_sockaddr_t *addr, int backlog, ks_listen_callback_t callback, void *user_data); 107 | KS_DECLARE(ks_status_t) ks_addr_getbyname(const char *name, ks_port_t port, int family, ks_sockaddr_t *result); 108 | 109 | KS_END_EXTERN_C 110 | 111 | #endif /* defined(_KS_SOCKET_H_) */ 112 | 113 | /* For Emacs: 114 | * Local Variables: 115 | * mode:c 116 | * indent-tabs-mode:t 117 | * tab-width:4 118 | * c-basic-offset:4 119 | * End: 120 | * For VIM: 121 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 122 | */ 123 | -------------------------------------------------------------------------------- /src/include/libks/ks_ssl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | KS_BEGIN_EXTERN_C 30 | 31 | KS_DECLARE(void) ks_ssl_init_skip(ks_bool_t skip); 32 | KS_DECLARE(void) ks_ssl_init_ssl_locks(void); 33 | KS_DECLARE(void) ks_ssl_destroy_ssl_locks(void); 34 | KS_DECLARE(int) ks_gen_cert(const char *dir, const char *file); 35 | 36 | KS_END_EXTERN_C 37 | 38 | /* For Emacs: 39 | * Local Variables: 40 | * mode:c 41 | * indent-tabs-mode:t 42 | * tab-width:4 43 | * c-basic-offset:4 44 | * End: 45 | * For VIM: 46 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 47 | */ 48 | -------------------------------------------------------------------------------- /src/include/libks/ks_string.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | KS_BEGIN_EXTERN_C 26 | 27 | KS_DECLARE(size_t) ks_url_encode(const char *url, char *buf, size_t len); 28 | KS_DECLARE(char *) ks_url_decode(char *s); 29 | KS_DECLARE(const char *) ks_stristr(const char *instr, const char *str); 30 | KS_DECLARE(int) ks_toupper(int c); 31 | KS_DECLARE(int) ks_tolower(int c); 32 | KS_DECLARE(char *) ks_copy_string(char *from_str, const char *to_str, ks_size_t from_str_len); 33 | KS_DECLARE(int) ks_snprintf(char *buffer, size_t count, const char *fmt, ...); 34 | KS_DECLARE(unsigned int) ks_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen); 35 | KS_DECLARE(unsigned int) ks_separate_string(char *buf, char delim, char **array, unsigned int arraylen); 36 | KS_DECLARE(char *) ks_hex_string(const unsigned char *data, ks_size_t len, char *buffer); 37 | KS_DECLARE(char*) ks_human_readable_size(ks_size_t size, int max_precision, ks_size_t len, char *buffer); 38 | KS_DECLARE(char*) ks_human_readable_size_double(double size, int max_precision, ks_size_t len, char *buffer); 39 | KS_DECLARE(void) ks_random_string(char *buf, uint16_t len, char *set); 40 | KS_DECLARE(const char *) ks_thr_sprintf(const char *fmt, ...); 41 | KS_DECLARE(int) ks_vasprintf(char **ret, const char *fmt, va_list ap); 42 | 43 | #define ks_str_nil(s) (s ? s : "") 44 | #define ks_zstr_buf(s) (*(s) == '\0') 45 | #define ks_set_string(_x, _y) ks_copy_string(_x, _y, sizeof(_x)) 46 | 47 | static __inline__ int ks_safe_strcasecmp(const char *s1, const char *s2) { 48 | if (!(s1 && s2)) { 49 | return 1; 50 | } 51 | 52 | return strcasecmp(s1, s2); 53 | } 54 | 55 | /*! 56 | \brief Test for NULL or zero length string 57 | \param s the string to test 58 | \return true value if the string is NULL or zero length 59 | */ 60 | _Check_return_ static __inline int _ks_zstr(_In_opt_z_ const char *s) 61 | { 62 | return !s || *s == '\0'; 63 | } 64 | 65 | #ifdef _PREFAST_ 66 | #define ks_zstr(x) (_ks_zstr(x) ? 1 : __analysis_assume(x),0) 67 | #else 68 | #define ks_zstr(x) _ks_zstr(x) 69 | #endif 70 | #define ks_strlen_zero(x) ks_zstr(x) 71 | #define ks_strlen_zero_buf(x) ks_zstr_buf(x) 72 | 73 | KS_END_EXTERN_C 74 | 75 | /* For Emacs: 76 | * Local Variables: 77 | * mode:c 78 | * indent-tabs-mode:t 79 | * tab-width:4 80 | * c-basic-offset:4 81 | * End: 82 | * For VIM: 83 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 84 | */ 85 | 86 | -------------------------------------------------------------------------------- /src/include/libks/ks_thread_pool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #pragma once 23 | 24 | KS_BEGIN_EXTERN_C 25 | KS_DECLARE(ks_status_t) ks_thread_pool_create(ks_thread_pool_t **tp, uint32_t min, uint32_t max, size_t stack_size, 26 | ks_thread_priority_t priority, uint32_t idle_sec); 27 | KS_DECLARE(ks_status_t) ks_thread_pool_destroy(ks_thread_pool_t **tp); 28 | KS_DECLARE(ks_status_t) ks_thread_pool_add_job(ks_thread_pool_t *tp, ks_thread_function_t func, void *data); 29 | KS_DECLARE(ks_size_t) ks_thread_pool_backlog(ks_thread_pool_t *tp); 30 | 31 | KS_END_EXTERN_C 32 | 33 | /* For Emacs: 34 | * Local Variables: 35 | * mode:c 36 | * indent-tabs-mode:t 37 | * tab-width:4 38 | * c-basic-offset:4 39 | * End: 40 | * For VIM: 41 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 42 | */ 43 | -------------------------------------------------------------------------------- /src/include/libks/ks_time.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #ifndef _KS_TIME_H_ 24 | #define _KS_TIME_H_ 25 | 26 | #include "ks.h" 27 | 28 | KS_BEGIN_EXTERN_C 29 | 30 | #define KS_USEC_PER_SEC 1000000 /* number of micro seconds in a second */ 31 | #define KS_USEC_PER_MSEC 1000 /* number of micro seconds in a millisecond */ 32 | 33 | #define ks_time_sec(time) ((time) / KS_USEC_PER_SEC) 34 | #define ks_time_ms(time) ((time) / KS_USEC_PER_MSEC) 35 | #define ks_time_usec(time) ((time) % KS_USEC_PER_SEC) 36 | #define ks_time_nsec(time) (((time) % KS_USEC_PER_SEC) * 1000) 37 | #define ks_sleep_ms(_t) ks_sleep(_t * 1000) 38 | 39 | KS_DECLARE(void) ks_time_init(void); 40 | KS_DECLARE(ks_time_t) ks_time_now(void); 41 | KS_DECLARE(ks_time_t) ks_time_now_sec(void); 42 | KS_DECLARE(void) ks_sleep(ks_time_t microsec); 43 | 44 | KS_END_EXTERN_C 45 | 46 | #endif /* defined(_KS_TIME_H_) */ 47 | 48 | /* For Emacs: 49 | * Local Variables: 50 | * mode:c 51 | * indent-tabs-mode:t 52 | * tab-width:4 53 | * c-basic-offset:4 54 | * End: 55 | * For VIM: 56 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 57 | */ 58 | -------------------------------------------------------------------------------- /src/include/libks/ks_utf8.h: -------------------------------------------------------------------------------- 1 | /* 2 | Basic UTF-8 manipulation routines 3 | by Jeff Bezanson 4 | placed in the public domain Fall 2005 5 | 6 | This code is designed to provide the utilities you need to manipulate 7 | UTF-8 as an internal string encoding. These functions do not perform the 8 | error checking normally needed when handling UTF-8 data, so if you happen 9 | to be from the Unicode Consortium you will want to flay me alive. 10 | I do this because error checking can be performed at the boundaries (I/O), 11 | with these routines reserved for higher performance on data known to be 12 | valid. 13 | */ 14 | 15 | #include "libks/ks.h" 16 | 17 | /* is c the start of a utf8 sequence? */ 18 | #define isutf(c) (((c)&0xC0)!=0x80) 19 | 20 | /* convert UTF-8 data to wide character */ 21 | KS_DECLARE(int) ks_u8_toucs(uint32_t *dest, int sz, char *src, int srcsz); 22 | 23 | /* the opposite conversion */ 24 | KS_DECLARE(int) ks_u8_toutf8(char *dest, int sz, uint32_t *src, int srcsz); 25 | 26 | /* single character to UTF-8 */ 27 | KS_DECLARE(int) ks_u8_wc_toutf8(char *dest, uint32_t ch); 28 | 29 | /* character number to byte offset */ 30 | KS_DECLARE(int) ks_u8_offset(char *str, int charnum); 31 | 32 | /* byte offset to character number */ 33 | KS_DECLARE(int) ks_u8_charnum(char *s, int offset); 34 | 35 | /* return next character, updating an index variable */ 36 | KS_DECLARE(uint32_t) ks_u8_nextchar(char *s, int *i); 37 | 38 | /* move to next character */ 39 | KS_DECLARE(void) ks_u8_inc(char *s, int *i); 40 | 41 | /* move to previous character */ 42 | KS_DECLARE(void) ks_u8_dec(char *s, int *i); 43 | 44 | /* returns length of next utf-8 sequence */ 45 | KS_DECLARE(int) ks_u8_seqlen(char *s); 46 | 47 | /* assuming src points to the character after a backslash, read an 48 | escape sequence, storing the result in dest and returning the number of 49 | input characters processed */ 50 | KS_DECLARE(int) ks_u8_read_escape_sequence(char *src, uint32_t *dest); 51 | 52 | /* given a wide character, convert it to an ASCII escape sequence stored in 53 | buf, where buf is "sz" bytes. returns the number of characters output.*/ 54 | KS_DECLARE(int) ks_u8_escape_wchar(char *buf, int sz, uint32_t ch); 55 | 56 | /* convert a string "src" containing escape sequences to UTF-8 */ 57 | KS_DECLARE(int) ks_u8_unescape(char *buf, int sz, char *src); 58 | 59 | /* convert UTF-8 "src" to ASCII with escape sequences. 60 | if escape_quotes is nonzero, quote characters will be preceded by 61 | backslashes as well. */ 62 | KS_DECLARE(int) ks_u8_escape(char *buf, int sz, char *src, int escape_quotes); 63 | 64 | /* utility predicates used by the above */ 65 | KS_DECLARE(int) octal_digit(char c); 66 | KS_DECLARE(int) hex_digit(char c); 67 | 68 | /* return a pointer to the first occurrence of ch in s, or NULL if not 69 | found. character index of found character returned in *charn. */ 70 | KS_DECLARE(char *) ks_u8_strchr(char *s, uint32_t ch, int *charn); 71 | 72 | /* same as the above, but searches a buffer of a given size instead of 73 | a NUL-terminated string. */ 74 | KS_DECLARE(char *) ks_u8_memchr(char *s, uint32_t ch, size_t sz, int *charn); 75 | 76 | /* count the number of characters in a UTF-8 string */ 77 | KS_DECLARE(int) ks_u8_strlen(char *s); 78 | 79 | KS_DECLARE(int) ks_u8_is_locale_utf8(char *locale); 80 | 81 | KS_DECLARE(uint32_t) ks_u8_get_char(char *s, int *i); 82 | -------------------------------------------------------------------------------- /src/include/libks/ks_uuid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | KS_BEGIN_EXTERN_C 26 | 27 | KS_DECLARE(ks_uuid_t *) ks_uuid(ks_uuid_t *uuid); 28 | 29 | KS_DECLARE(char *) __ks_uuid_str(ks_pool_t *pool, ks_uuid_t *uuid, const char *file, int line, const char *tag); 30 | #define ks_uuid_str(pool, uuid) __ks_uuid_str(pool, uuid, __FILE__, __LINE__, __KS_FUNC__) 31 | 32 | KS_DECLARE(const char *) __ks_uuid_null_str(ks_pool_t *pool, const char *file, int line, const char *tag); 33 | #define ks_uuid_null_str(pool) __ks_uuid_null_str(pool, __FILE__, __LINE__, __KS_FUNC__) 34 | 35 | KS_DECLARE(ks_uuid_t) ks_uuid_from_str(const char * const string); 36 | KS_DECLARE(ks_bool_t) ks_uuid_is_null(const ks_uuid_t *uuid); 37 | KS_DECLARE(const char *) ks_uuid_null_thr_str(void); 38 | KS_DECLARE(ks_uuid_t) ks_uuid_null(void); 39 | KS_DECLARE(ks_uuid_t *) ks_uuid_dup(ks_pool_t *pool, ks_uuid_t *uuid); 40 | KS_DECLARE(const char *) ks_uuid_thr_str(const ks_uuid_t *uuid); 41 | 42 | #define ks_uuid_cmp(x, y) memcmp(x, y, sizeof(ks_uuid_t)) 43 | 44 | KS_END_EXTERN_C 45 | -------------------------------------------------------------------------------- /src/include/libks/kws.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #define WEBSOCKET_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 26 | #define B64BUFFLEN 1024 27 | #define KWS_MAX_HEADERS 64 28 | 29 | KS_BEGIN_EXTERN_C 30 | 31 | typedef enum { 32 | WS_NONE = 0, 33 | WS_RECV_CLOSE = 1000, 34 | WS_PROTO_ERR = 1002, 35 | WS_DATA_TOO_BIG = 1009 36 | } kws_cause_t; 37 | 38 | #define WS_NORMAL_CLOSE 1000 39 | 40 | typedef enum { 41 | WSOC_CONTINUATION = 0x0, 42 | WSOC_TEXT = 0x1, 43 | WSOC_BINARY = 0x2, 44 | WSOC_CLOSE = 0x8, 45 | WSOC_PING = 0x9, 46 | WSOC_PONG = 0xA, 47 | WSOC_INVALID = 0xF /* Per the rfc this is the highest reserved valuel treat it as invalid */ 48 | } kws_opcode_t; 49 | 50 | typedef enum { 51 | KWS_CLIENT, 52 | KWS_SERVER 53 | } kws_type_t; 54 | 55 | typedef enum { 56 | KWS_NONE = 0, 57 | KWS_CLOSE_SOCK = (1 << 0), 58 | KWS_BLOCK = (1 << 1), 59 | KWS_STAY_OPEN = (1 << 2), 60 | KWS_FLAG_DONTMASK = (1 << 3), 61 | KWS_HTTP = (1 << 4) /* fallback to HTTP */ 62 | } kws_flag_t; 63 | 64 | typedef struct kws_request_s { 65 | const char *method; /* GET POST PUT DELETE OPTIONS PATCH HEAD */ 66 | const char *uri; 67 | const char *qs; /* query string*/ 68 | const char *host; 69 | ks_port_t port; 70 | const char *from; 71 | const char *user_agent; 72 | const char *referer; 73 | const char *user; 74 | ks_bool_t keepalive; 75 | const char *content_type; 76 | const char *authorization; 77 | ks_size_t content_length; 78 | ks_size_t bytes_header; 79 | ks_size_t bytes_read; 80 | ks_size_t bytes_buffered; 81 | const char *headers_k[KWS_MAX_HEADERS]; 82 | const char *headers_v[KWS_MAX_HEADERS]; 83 | ks_size_t total_headers; 84 | void *user_data; /* private user data */ 85 | 86 | /* private members used by the parser internally */ 87 | char *_buffer; 88 | } kws_request_t; 89 | 90 | 91 | struct kws_s; 92 | typedef struct kws_s kws_t; 93 | 94 | typedef void (*kws_init_callback_t)(kws_t *kws, SSL* ssl); 95 | 96 | KS_DECLARE(ks_ssize_t) kws_read_frame(kws_t *kws, kws_opcode_t *oc, uint8_t **data); 97 | KS_DECLARE(ks_ssize_t) kws_write_frame(kws_t *kws, kws_opcode_t oc, const void *data, ks_size_t bytes); 98 | KS_DECLARE(ks_ssize_t) kws_raw_read(kws_t *kws, void *data, ks_size_t bytes, int block); 99 | KS_DECLARE(ks_ssize_t) kws_raw_write(kws_t *kws, void *data, ks_size_t bytes); 100 | KS_DECLARE(ks_status_t) kws_init_ex(kws_t **kwsP, ks_socket_t sock, SSL_CTX *ssl_ctx, const char *client_data, kws_flag_t flags, ks_pool_t *pool, ks_json_t *params); 101 | #define kws_init(kwsP, sock, ssl_ctx, client_data, flags, pool) kws_init_ex(kwsP, sock, ssl_ctx, client_data, flags, pool, NULL) 102 | KS_DECLARE(ks_ssize_t) kws_string_read(kws_t *kws, char *str_buffer, ks_size_t buffer_size, int block); 103 | KS_DECLARE(ks_ssize_t) kws_close(kws_t *kws, int16_t reason); 104 | KS_DECLARE(ks_status_t) kws_create(kws_t **kwsP, ks_pool_t *pool); 105 | KS_DECLARE(void) kws_destroy(kws_t **kwsP); 106 | KS_DECLARE(void) kws_set_init_callback(kws_t *kws, kws_init_callback_t callback); 107 | KS_DECLARE(ks_status_t) kws_connect(kws_t **kwsP, ks_json_t *params, kws_flag_t flags, ks_pool_t *pool); 108 | KS_DECLARE(ks_status_t) kws_connect_ex(kws_t **kwsP, ks_json_t *params, kws_flag_t flags, ks_pool_t *pool, SSL_CTX *ssl_ctx, uint32_t timeout_ms); 109 | KS_DECLARE(ks_status_t) kws_get_buffer(kws_t *kws, char **bufP, ks_size_t *buflen); 110 | KS_DECLARE(ks_status_t) kws_get_cipher_name(kws_t *kws, char *name, ks_size_t name_len); 111 | KS_DECLARE(ks_bool_t) kws_certified_client(kws_t *kws); 112 | KS_DECLARE(ks_size_t) kws_sans_count(kws_t *kws); 113 | KS_DECLARE(const char *) kws_sans_get(kws_t *kws, ks_size_t index); 114 | KS_DECLARE(int) kws_wait_sock(kws_t *kws, uint32_t ms, ks_poll_t flags); 115 | KS_DECLARE(int) kws_test_flag(kws_t *kws, kws_flag_t); 116 | KS_DECLARE(int) kws_set_flag(kws_t *kws, kws_flag_t); 117 | KS_DECLARE(int) kws_clear_flag(kws_t *kws, kws_flag_t); 118 | /** 119 | * parse http headers in a buffer 120 | * return status of success or not 121 | * \param[in] buffer the buffer start from the very begining of the http request, e.g. 'GET ' 122 | * \param[in] datalen the buffer length 123 | * \param[out] the http request pointer or null, need destroy later if got non-NULL pointer 124 | * \return SWITCH_STATUS_SUCCESS | SWITCH_STATUS_FALSE 125 | */ 126 | KS_DECLARE(ks_status_t) kws_parse_header(kws_t *kws, kws_request_t **request); 127 | KS_DECLARE(void) kws_request_free(kws_request_t **request); 128 | KS_DECLARE(void) kws_request_reset(kws_request_t *request); 129 | /** 130 | * \param[in] request the request 131 | * \return the returned pointer must be freed externally 132 | */ 133 | KS_DECLARE(char *) kws_request_dump(kws_request_t *request); 134 | KS_DECLARE(ks_status_t) kws_parse_qs(kws_request_t *request, char *qs); 135 | KS_DECLARE(ks_ssize_t) kws_read_buffer(kws_t *kws, uint8_t **data, ks_size_t bytes, int block); 136 | KS_DECLARE(ks_status_t) kws_keepalive(kws_t *kws); 137 | KS_DECLARE(const char *) kws_request_get_header(kws_request_t *request, const char *key); 138 | 139 | KS_END_EXTERN_C 140 | 141 | /* For Emacs: 142 | * Local Variables: 143 | * mode:c 144 | * indent-tabs-mode:t 145 | * tab-width:4 146 | * c-basic-offset:4 147 | * End: 148 | * For VIM: 149 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 150 | */ 151 | -------------------------------------------------------------------------------- /src/ks.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | #include "libks/ks_atomic.h" 25 | 26 | /* The one and only global pool */ 27 | static ks_pool_t *g_pool; 28 | 29 | /* This keeps track of the number of calls to init, since we allow layered inits 30 | * we will null up the 2+ inits until the loaded count drops to zero on deinit. */ 31 | static ks_size_t g_init_count; 32 | 33 | /* We must lock to ensure we don't let secondary initializers return prior to the first 34 | * being ready */ 35 | static ks_spinlock_t g_init_lock; 36 | 37 | KS_DECLARE(ks_status_t) ks_init(void) 38 | { 39 | unsigned int pid = 0; 40 | 41 | /* Lock to atomically check init count, and to prevent returning before 42 | * a threaded first initer gets finishes */ 43 | ks_spinlock_acquire(&g_init_lock); 44 | 45 | /* If we're not first, done */ 46 | ks_assert(g_init_count >= 0); 47 | if (++g_init_count != 1) goto done; 48 | 49 | #if !defined(KS_PLAT_WIN) 50 | signal(SIGPIPE, SIG_IGN); 51 | #endif 52 | 53 | ks_time_init(); 54 | ks_log_init(); 55 | 56 | #ifdef __WINDOWS__ 57 | pid = _getpid(); 58 | #else 59 | pid = getpid(); 60 | #endif 61 | srand(pid * (unsigned int)(intptr_t)&g_pool + (unsigned int)time(NULL)); 62 | ks_global_pool(); 63 | ks_ssl_init_ssl_locks(); 64 | 65 | #ifdef __WINDOWS__ 66 | WSADATA wsaData; 67 | WORD wVersionRequested = MAKEWORD(2, 2); 68 | if (WSAStartup(wVersionRequested, &wsaData)) { 69 | abort(); 70 | } 71 | #endif 72 | 73 | done: 74 | ks_spinlock_release(&g_init_lock); 75 | 76 | return KS_STATUS_SUCCESS; 77 | } 78 | 79 | KS_DECLARE(ks_status_t) ks_shutdown(void) 80 | { 81 | ks_status_t status = KS_STATUS_SUCCESS; 82 | 83 | ks_spinlock_acquire(&g_init_lock); 84 | 85 | /* If we're not last, done */ 86 | ks_assert(g_init_count != 0); 87 | if (--g_init_count != 0) goto done; 88 | 89 | ks_dso_shutdown(); 90 | 91 | #ifdef __WINDOWS__ 92 | WSACleanup(); 93 | #endif 94 | 95 | ks_ssl_destroy_ssl_locks(); 96 | 97 | if (g_pool) { 98 | status = ks_pool_close(&g_pool); 99 | } 100 | 101 | ks_log_shutdown(); 102 | 103 | done: 104 | 105 | ks_spinlock_release(&g_init_lock); 106 | 107 | return status; 108 | } 109 | 110 | KS_DECLARE(ks_pool_t *) ks_global_pool(void) 111 | { 112 | ks_status_t status; 113 | 114 | if (!g_pool) { 115 | 116 | static ks_spinlock_t pool_alloc_lock; 117 | 118 | ks_spinlock_acquire(&pool_alloc_lock); 119 | 120 | if (!g_pool) { 121 | 122 | if ((status = ks_pool_open(&g_pool)) != KS_STATUS_SUCCESS) { 123 | abort(); 124 | } 125 | 126 | /* Since we are the global pool, any allocations left in it on shutdown 127 | * should be concerning, and will get logged */ 128 | ks_pool_log_on_close(g_pool); 129 | } 130 | 131 | ks_spinlock_release(&pool_alloc_lock); 132 | } 133 | 134 | return g_pool; 135 | } 136 | 137 | KS_ENUM_NAMES(STATUS_NAMES, STATUS_STRINGS) 138 | KS_STR2ENUM(ks_str2ks_status, ks_status2str, ks_status_t, STATUS_NAMES, KS_STATUS_COUNT) 139 | 140 | /* For Emacs: 141 | * Local Variables: 142 | * mode:c 143 | * indent-tabs-mode:t 144 | * tab-width:4 145 | * c-basic-offset:4 146 | * End: 147 | * For VIM: 148 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 149 | */ 150 | -------------------------------------------------------------------------------- /src/ks_base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #include "libks/ks_base64.h" 23 | 24 | static const char ks_b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 25 | 26 | 27 | KS_DECLARE(ks_status_t) ks_b64_encode(unsigned char *in, ks_size_t ilen, unsigned char *out, ks_size_t olen) 28 | { 29 | int y = 0, bytes = 0; 30 | size_t x = 0; 31 | unsigned int b = 0, l = 0; 32 | 33 | for (x = 0; x < ilen; x++) { 34 | b = (b << 8) + in[x]; 35 | l += 8; 36 | 37 | while (l >= 6) { 38 | out[bytes++] = ks_b64_table[(b >> (l -= 6)) % 64]; 39 | if (bytes >= (int)olen - 1) { 40 | goto end; 41 | } 42 | if (++y != 72) { 43 | continue; 44 | } 45 | /* out[bytes++] = '\n'; */ 46 | y = 0; 47 | } 48 | } 49 | 50 | if (l > 0) { 51 | out[bytes++] = ks_b64_table[((b % 16) << (6 - l)) % 64]; 52 | } 53 | if (l != 0) { 54 | while (l < 6 && bytes < (int)olen - 1) { 55 | out[bytes++] = '=', l += 2; 56 | } 57 | } 58 | 59 | end: 60 | 61 | out[bytes] = '\0'; 62 | 63 | return KS_STATUS_SUCCESS; 64 | } 65 | 66 | KS_DECLARE(ks_size_t) ks_b64_decode(char *in, char *out, ks_size_t olen) 67 | { 68 | 69 | char l64[256]; 70 | int b = 0, c, l = 0, i; 71 | char *ip, *op = out; 72 | size_t ol = 0; 73 | 74 | for (i = 0; i < 256; i++) { 75 | l64[i] = -1; 76 | } 77 | 78 | for (i = 0; i < 64; i++) { 79 | l64[(int) ks_b64_table[i]] = (char) i; 80 | } 81 | 82 | for (ip = in; ip && *ip; ip++) { 83 | c = l64[(int) *ip]; 84 | if (c == -1) { 85 | continue; 86 | } 87 | 88 | b = (b << 6) + c; 89 | l += 6; 90 | 91 | while (l >= 8) { 92 | op[ol++] = (char) ((b >> (l -= 8)) % 256); 93 | if (ol >= olen - 2) { 94 | goto end; 95 | } 96 | } 97 | } 98 | 99 | end: 100 | 101 | op[ol++] = '\0'; 102 | 103 | return ol; 104 | } 105 | 106 | 107 | /* For Emacs: 108 | * Local Variables: 109 | * mode:c 110 | * indent-tabs-mode:t 111 | * tab-width:4 112 | * c-basic-offset:4 113 | * End: 114 | * For VIM: 115 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 116 | */ 117 | -------------------------------------------------------------------------------- /src/ks_config.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | 25 | KS_DECLARE(int) ks_config_open_file(ks_config_t *cfg, const char *file_path) 26 | { 27 | FILE *f; 28 | const char *path = NULL; 29 | char path_buf[1024]; 30 | 31 | if (file_path[0] == '/') { 32 | path = file_path; 33 | } else { 34 | ks_snprintf(path_buf, sizeof(path_buf), "%s%s%s", KS_CONFIG_DIR, KS_PATH_SEPARATOR, file_path); 35 | path = path_buf; 36 | } 37 | 38 | if (!path) { 39 | return 0; 40 | } 41 | 42 | memset(cfg, 0, sizeof(*cfg)); 43 | cfg->lockto = -1; 44 | ks_log(KS_LOG_DEBUG, "Configuration file is %s.\n", path); 45 | f = fopen(path, "r"); 46 | 47 | if (!f) { 48 | if (file_path[0] != '/') { 49 | int last = -1; 50 | char *var, *val; 51 | 52 | ks_snprintf(path_buf, sizeof(path_buf), "%s%sopenks.conf", KS_CONFIG_DIR, KS_PATH_SEPARATOR); 53 | path = path_buf; 54 | 55 | if ((f = fopen(path, "r")) == 0) { 56 | return 0; 57 | } 58 | 59 | cfg->file = f; 60 | ks_set_string(cfg->path, path); 61 | 62 | while (ks_config_next_pair(cfg, &var, &val)) { 63 | if ((cfg->sectno != last) && !strcmp(cfg->section, file_path)) { 64 | cfg->lockto = cfg->sectno; 65 | return 1; 66 | } 67 | } 68 | 69 | ks_config_close_file(cfg); 70 | memset(cfg, 0, sizeof(*cfg)); 71 | return 0; 72 | } 73 | 74 | return 0; 75 | } else { 76 | cfg->file = f; 77 | ks_set_string(cfg->path, path); 78 | return 1; 79 | } 80 | } 81 | 82 | KS_DECLARE(void) ks_config_close_file(ks_config_t *cfg) 83 | { 84 | 85 | if (cfg->file) { 86 | fclose(cfg->file); 87 | } 88 | 89 | memset(cfg, 0, sizeof(*cfg)); 90 | } 91 | 92 | 93 | 94 | KS_DECLARE(int) ks_config_next_pair(ks_config_t *cfg, char **var, char **val) 95 | { 96 | int ret = 0; 97 | char *p, *end; 98 | 99 | *var = *val = NULL; 100 | 101 | if (!cfg || !cfg->file) { 102 | return 0; 103 | } 104 | 105 | for (;;) { 106 | cfg->lineno++; 107 | 108 | if (!fgets(cfg->buf, sizeof(cfg->buf), cfg->file)) { 109 | ret = 0; 110 | break; 111 | } 112 | *var = cfg->buf; 113 | 114 | if (**var == '[' && (end = strchr(*var, ']')) != 0) { 115 | *end = '\0'; 116 | (*var)++; 117 | if (**var == '+') { 118 | (*var)++; 119 | ks_copy_string(cfg->section, *var, sizeof(cfg->section)); 120 | cfg->sectno++; 121 | 122 | if (cfg->lockto > -1 && cfg->sectno != cfg->lockto) { 123 | break; 124 | } 125 | cfg->catno = 0; 126 | cfg->lineno = 0; 127 | *var = (char *) ""; 128 | *val = (char *) ""; 129 | return 1; 130 | } else { 131 | ks_copy_string(cfg->category, *var, sizeof(cfg->category)); 132 | cfg->catno++; 133 | } 134 | continue; 135 | } 136 | 137 | 138 | 139 | if (**var == '#' || **var == ';' || **var == '\n' || **var == '\r') { 140 | continue; 141 | } 142 | 143 | if (!strncmp(*var, "__END__", 7)) { 144 | break; 145 | } 146 | 147 | 148 | if ((end = strchr(*var, ';')) && *(end + 1) == *end) { 149 | *end = '\0'; 150 | end--; 151 | } else if ((end = strchr(*var, '\n')) != 0) { 152 | if (*(end - 1) == '\r') { 153 | end--; 154 | } 155 | *end = '\0'; 156 | } 157 | 158 | p = *var; 159 | while ((*p == ' ' || *p == '\t') && p != end) { 160 | *p = '\0'; 161 | p++; 162 | } 163 | *var = p; 164 | 165 | 166 | if ((*val = strchr(*var, '=')) == 0) { 167 | ret = -1; 168 | /* log_printf(0, server.log, "Invalid syntax on %s: line %d\n", cfg->path, cfg->lineno); */ 169 | continue; 170 | } else { 171 | p = *val - 1; 172 | *(*val) = '\0'; 173 | (*val)++; 174 | if (*(*val) == '>') { 175 | *(*val) = '\0'; 176 | (*val)++; 177 | } 178 | 179 | while ((*p == ' ' || *p == '\t') && p != *var) { 180 | *p = '\0'; 181 | p--; 182 | } 183 | 184 | p = *val; 185 | while ((*p == ' ' || *p == '\t') && p != end) { 186 | *p = '\0'; 187 | p++; 188 | } 189 | *val = p; 190 | ret = 1; 191 | break; 192 | } 193 | } 194 | 195 | 196 | return ret; 197 | 198 | } 199 | 200 | KS_DECLARE(int) ks_config_get_cas_bits(char *strvalue, unsigned char *outbits) 201 | { 202 | char cas_bits[5]; 203 | unsigned char bit = 0x8; 204 | char *double_colon = strchr(strvalue, ':'); 205 | int x = 0; 206 | 207 | if (!double_colon) { 208 | ks_log(KS_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon); 209 | return -1; 210 | } 211 | 212 | double_colon++; 213 | *outbits = 0; 214 | cas_bits[4] = 0; 215 | 216 | if (sscanf(double_colon, "%c%c%c%c", &cas_bits[0], &cas_bits[1], &cas_bits[2], &cas_bits[3]) != 4) { 217 | ks_log(KS_LOG_ERROR, "Invalid CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon); 218 | return -1; 219 | } 220 | 221 | ks_log(KS_LOG_DEBUG, "CAS bits specification found: %s\n", cas_bits); 222 | 223 | for (; cas_bits[x]; x++) { 224 | if ('1' == cas_bits[x]) { 225 | *outbits |= bit; 226 | } else if ('0' != cas_bits[x]) { 227 | ks_log(KS_LOG_ERROR, "Invalid CAS pattern specified: %s, just 0 or 1 allowed for each bit\n", cas_bits); 228 | return -1; 229 | } 230 | bit >>= 1; 231 | } 232 | return 0; 233 | } 234 | 235 | /* For Emacs: 236 | * Local Variables: 237 | * mode:c 238 | * indent-tabs-mode:t 239 | * tab-width:4 240 | * c-basic-offset:4 241 | * End: 242 | * For VIM: 243 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 244 | */ 245 | -------------------------------------------------------------------------------- /src/ks_debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | 25 | #if KS_PLAT_MAC 26 | #include 27 | #endif 28 | 29 | #if defined(HAVE_LIBBACKTRACE) 30 | #include "backtrace.h" 31 | 32 | static int __full_callback(void *data __attribute__((unused)), uintptr_t pc, const char *filename, int lineno, const char *function) 33 | { 34 | ks_log(KS_LOG_CRIT, "0x%lx %s \t%s:%d\n", (unsigned long) pc, 35 | function == NULL ? "???" : function , 36 | function == NULL ? "???" : filename, lineno); 37 | 38 | return strcmp(function, "main") == 0 ? 1 : 0; 39 | } 40 | 41 | static void __error_callback(void *data, const char *msg, int errnum) 42 | { 43 | ks_log(KS_LOG_CRIT, "Something went wrong in libbacktrace: %s\n", msg); 44 | } 45 | 46 | /** 47 | * ks_debug_dump_backtrace - Dumps the current callstack to a critical log 48 | * with ks_log. 49 | */ 50 | KS_DECLARE(void) ks_debug_dump_backtrace(void) 51 | { 52 | struct backtrace_state *lbstate; 53 | lbstate = backtrace_create_state(NULL, 1, __error_callback, NULL); 54 | backtrace_full(lbstate, 0, __full_callback, __error_callback, 0); 55 | } 56 | #else 57 | KS_DECLARE(void) ks_debug_dump_backtrace(void) { } 58 | #endif 59 | 60 | /** 61 | * This function will cause an attached debugger to break. In the case of 62 | * windows, it may cause a JIT debug session. 63 | */ 64 | KS_DECLARE(void) ks_debug_break(void) 65 | { 66 | #if KS_PLAT_WIN 67 | DebugBreak(); 68 | #else 69 | kill(getpid(), SIGINT); 70 | #endif 71 | } 72 | -------------------------------------------------------------------------------- /src/ks_env.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | 25 | KS_DECLARE(int) ks_env_cpu_count(void) 26 | { 27 | int cpu_count; 28 | 29 | #ifndef WIN32 30 | cpu_count = sysconf (_SC_NPROCESSORS_ONLN); 31 | #else 32 | { 33 | SYSTEM_INFO sysinfo; 34 | GetSystemInfo( &sysinfo ); 35 | cpu_count = sysinfo.dwNumberOfProcessors; 36 | } 37 | #endif 38 | 39 | return cpu_count; 40 | } 41 | -------------------------------------------------------------------------------- /src/ks_metrics.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | 25 | KS_DECLARE(ks_status_t) ks_metrics_cpu(double *cpu, int samples, int interval) 26 | { 27 | ks_status_t ret = KS_STATUS_SUCCESS; 28 | #ifdef KS_PLAT_WIN 29 | ret = KS_STATUS_NOT_ALLOWED; 30 | *cpu = 0; 31 | #else 32 | int64_t firstSum = 0; 33 | int64_t firstIdle = 0; 34 | int64_t totalSum = 0; 35 | int64_t totalIdle = 0; 36 | int totalSamples = 0; 37 | 38 | ks_assert(cpu); 39 | ks_assert(samples >= 2); 40 | ks_assert(interval >= 1); 41 | 42 | while(samples > 0) { 43 | char line[256]; 44 | char* token; 45 | int tokenIndex = 0; 46 | FILE* fp = fopen("/proc/stat", "r"); 47 | int64_t sum = 0; 48 | int64_t idle = 0; 49 | 50 | if (!fp) { 51 | ret = KS_STATUS_NOT_FOUND; 52 | *cpu = 0; 53 | goto done; 54 | } 55 | 56 | fgets(line, 256, fp); 57 | fclose(fp); 58 | 59 | // skip first token "cpu" 60 | token = strtok(line, " "); 61 | 62 | // add remaining tokens 63 | while(token != NULL) { 64 | token = strtok(NULL, " "); 65 | if(token != NULL) { 66 | if(tokenIndex == 3) idle = atoll(token); 67 | else sum += atoll(token); 68 | 69 | tokenIndex++; 70 | } 71 | } 72 | 73 | if (firstSum == 0) firstSum = sum; 74 | if (firstIdle == 0) firstIdle = idle; 75 | 76 | sum -= firstSum; 77 | idle -= firstIdle; 78 | 79 | totalSum += sum; 80 | totalIdle += idle; 81 | 82 | samples--; 83 | totalSamples++; 84 | if (samples == 0 && totalSum == 0) ++samples; 85 | } 86 | 87 | *cpu = ((double)totalSum / (totalIdle + totalSum)) * 100; 88 | done: 89 | #endif 90 | return ret; 91 | } 92 | 93 | /* For Emacs: 94 | * Local Variables: 95 | * mode:c 96 | * indent-tabs-mode:t 97 | * tab-width:4 98 | * c-basic-offset:4 99 | * End: 100 | * For VIM: 101 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 102 | */ 103 | -------------------------------------------------------------------------------- /src/ks_sb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #include "libks/ks.h" 23 | #include "libks/ks_sb.h" 24 | 25 | struct ks_sb_s { 26 | ks_bool_t pool_owner; 27 | char *data; 28 | ks_size_t size; 29 | ks_size_t used; 30 | }; 31 | 32 | static void ks_sb_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t type) 33 | { 34 | ks_sb_t *sb = (ks_sb_t *)ptr; 35 | 36 | switch(action) { 37 | case KS_MPCL_ANNOUNCE: 38 | break; 39 | case KS_MPCL_TEARDOWN: 40 | if (!sb->pool_owner && sb->data) ks_pool_free(&sb->data); 41 | break; 42 | case KS_MPCL_DESTROY: 43 | break; 44 | } 45 | 46 | } 47 | 48 | KS_DECLARE(ks_status_t) ks_sb_create(ks_sb_t **sbP, ks_pool_t *pool, ks_size_t preallocated) 49 | { 50 | ks_sb_t *sb = NULL; 51 | ks_bool_t pool_owner = KS_FALSE; 52 | 53 | ks_assert(sbP); 54 | 55 | if ((pool_owner = !pool)) ks_pool_open(&pool); 56 | if (preallocated == 0) preallocated = KS_PRINT_BUF_SIZE * 2; 57 | 58 | sb = ks_pool_alloc(pool, sizeof(ks_sb_t)); 59 | sb->pool_owner = pool_owner; 60 | sb->data = ks_pool_alloc(pool, preallocated); 61 | sb->size = preallocated; 62 | sb->used = 1; 63 | 64 | ks_pool_set_cleanup(sb, NULL, ks_sb_cleanup); 65 | 66 | *sbP = sb; 67 | 68 | return KS_STATUS_SUCCESS; 69 | } 70 | 71 | KS_DECLARE(ks_status_t) ks_sb_destroy(ks_sb_t **sbP) 72 | { 73 | ks_sb_t *sb = NULL; 74 | 75 | ks_assert(sbP); 76 | ks_assert(*sbP); 77 | 78 | sb = *sbP; 79 | *sbP = NULL; 80 | 81 | if (sb->pool_owner) { 82 | ks_pool_t *pool = ks_pool_get(sb); 83 | ks_pool_close(&pool); 84 | } else ks_pool_free(&sb); 85 | 86 | return KS_STATUS_SUCCESS; 87 | } 88 | 89 | KS_DECLARE(const char *) ks_sb_cstr(ks_sb_t *sb) 90 | { 91 | ks_assert(sb); 92 | return sb->data; 93 | } 94 | 95 | KS_DECLARE(ks_size_t) ks_sb_length(ks_sb_t *sb) 96 | { 97 | ks_assert(sb); 98 | return sb->used - 1; 99 | } 100 | 101 | KS_DECLARE(ks_status_t) ks_sb_accommodate(ks_sb_t *sb, ks_size_t len) 102 | { 103 | ks_status_t ret = KS_STATUS_SUCCESS; 104 | 105 | ks_assert(sb); 106 | 107 | if (len == 0) goto done; 108 | 109 | if ((sb->used + len) > sb->size) { 110 | ks_size_t needed = (sb->used + len) - sb->size; 111 | if (needed < KS_PRINT_BUF_SIZE) needed = KS_PRINT_BUF_SIZE; 112 | sb->size += needed; 113 | if (!sb->data) sb->data = ks_pool_alloc(ks_pool_get(sb), sb->size); 114 | else { 115 | sb->data = ks_pool_resize(sb->data, sb->size); 116 | if (!sb->data) ret = KS_STATUS_FAIL; 117 | } 118 | } 119 | 120 | done: 121 | return ret; 122 | } 123 | 124 | KS_DECLARE(ks_status_t) ks_sb_append(ks_sb_t *sb, const char *str) 125 | { 126 | ks_status_t ret = KS_STATUS_SUCCESS; 127 | 128 | ks_assert(sb); 129 | 130 | if (str) ret = ks_sb_append_ex(sb, str, strlen(str)); 131 | 132 | return ret; 133 | } 134 | 135 | KS_DECLARE(ks_status_t) ks_sb_append_ex(ks_sb_t *sb, const char *str, ks_size_t len) 136 | { 137 | ks_status_t ret = KS_STATUS_SUCCESS; 138 | 139 | ks_assert(sb); 140 | 141 | if (!str || len == 0) goto done; 142 | 143 | if (ks_sb_accommodate(sb, len) != KS_STATUS_SUCCESS) { 144 | ret = KS_STATUS_FAIL; 145 | goto done; 146 | } 147 | 148 | memcpy(sb->data + (sb->used - 1), str, len + 1); 149 | sb->used += len; 150 | 151 | done: 152 | 153 | return ret; 154 | } 155 | 156 | KS_DECLARE(ks_status_t) ks_sb_printf(ks_sb_t *sb, const char *fmt, ...) 157 | { 158 | ks_status_t ret = KS_STATUS_SUCCESS; 159 | va_list ap; 160 | ks_size_t used = 0; 161 | char *result = NULL; 162 | 163 | ks_assert(sb); 164 | ks_assert(fmt); 165 | 166 | used = sb->used - 1; 167 | 168 | if (ks_sb_accommodate(sb, KS_PRINT_BUF_SIZE) != KS_STATUS_SUCCESS) { 169 | ret = KS_STATUS_FAIL; 170 | goto done; 171 | } 172 | 173 | va_start(ap, fmt); 174 | result = ks_vsnprintfv(sb->data + used, (int)(sb->size - used), fmt, ap); 175 | va_end(ap); 176 | 177 | sb->used += strlen(result); 178 | 179 | done: 180 | return ret; 181 | } 182 | 183 | KS_DECLARE(ks_status_t) ks_sb_json(ks_sb_t *sb, ks_json_t *json) 184 | { 185 | ks_status_t ret = KS_STATUS_SUCCESS; 186 | char *str = NULL; 187 | 188 | ks_assert(sb); 189 | ks_assert(json); 190 | 191 | str = ks_json_print(json); 192 | if (!str) { 193 | ret = KS_STATUS_FAIL; 194 | goto done; 195 | } 196 | 197 | ks_sb_append(sb, str); 198 | 199 | done: 200 | if (str) ks_pool_free(&str); 201 | 202 | return ret; 203 | } 204 | 205 | 206 | /* For Emacs: 207 | * Local Variables: 208 | * mode:c 209 | * indent-tabs-mode:t 210 | * tab-width:4 211 | * c-basic-offset:4 212 | * End: 213 | * For VIM: 214 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 215 | */ 216 | -------------------------------------------------------------------------------- /src/ks_uuid.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | 25 | KS_DECLARE(ks_uuid_t *) ks_uuid(ks_uuid_t *uuid) 26 | { 27 | #ifdef KS_PLAT_WIN 28 | UuidCreate(uuid); 29 | #else 30 | uuid_generate_random((unsigned char *)uuid); 31 | #endif 32 | return uuid; 33 | } 34 | 35 | KS_DECLARE(char *) __ks_uuid_str(ks_pool_t *pool, ks_uuid_t *uuid, const char *file, int line, const char *tag) 36 | { 37 | #ifdef KS_PLAT_WIN 38 | unsigned char *str, *uuidstr; 39 | UuidToStringA(uuid, &str); 40 | uuidstr = __ks_pstrdup(pool, (const char *)str, file, line, tag); 41 | RpcStringFreeA(&str); 42 | return uuidstr; 43 | #else 44 | char str[37] = { 0 }; 45 | uuid_unparse((unsigned char *)uuid, str); 46 | return __ks_pstrdup(pool, str, file, line, tag); 47 | #endif 48 | } 49 | 50 | KS_DECLARE(ks_uuid_t *) ks_uuid_dup(ks_pool_t *pool, ks_uuid_t *uuid) 51 | { 52 | ks_uuid_t *clone; 53 | 54 | if (!(clone = ks_pool_alloc(pool, sizeof(ks_uuid_t)))) 55 | return NULL; 56 | 57 | memcpy(clone, uuid, sizeof(ks_uuid_t)); 58 | return clone; 59 | } 60 | 61 | KS_DECLARE(ks_bool_t) ks_uuid_is_null(const ks_uuid_t *uuid) { 62 | static ks_uuid_t null_uuid = {0}; 63 | return memcmp(uuid, &null_uuid, sizeof(ks_uuid_t)) == 0; 64 | } 65 | 66 | KS_DECLARE(const char *) __ks_uuid_null_str(ks_pool_t *pool, const char *file, int line, const char *tag) 67 | { 68 | static ks_uuid_t null_uuid = {0}; 69 | return __ks_uuid_str(pool, &null_uuid, file, line, tag); 70 | } 71 | 72 | KS_DECLARE(const char *) ks_uuid_null_thr_str(void) 73 | { 74 | static ks_uuid_t null_uuid = {0}; 75 | return ks_uuid_thr_str(&null_uuid); 76 | } 77 | 78 | KS_DECLARE(const char *) ks_uuid_thr_str(const ks_uuid_t *uuid) 79 | { 80 | static KS_THREAD_LOCAL char uuid_str[37]; 81 | 82 | #ifdef KS_PLAT_WIN 83 | unsigned char *str; 84 | UuidToStringA(uuid, &str); 85 | strncpy(uuid_str, str, sizeof(uuid_str)); 86 | RpcStringFreeA(&str); 87 | return uuid_str; 88 | #else 89 | uuid_unparse((unsigned char *)uuid, uuid_str); 90 | return uuid_str; 91 | #endif 92 | } 93 | 94 | KS_DECLARE(ks_uuid_t) ks_uuid_from_str(const char * const string) 95 | { 96 | ks_uuid_t uuid = {0}; 97 | #ifdef KS_PLAT_WIN 98 | if (UuidFromStringA((unsigned char *)string, &uuid) != RPC_S_OK) { 99 | return uuid; /* Null uuid indicates failure */ 100 | } 101 | return uuid; 102 | #else 103 | if (uuid_parse(string, (unsigned char *)&uuid) != 0) { 104 | return uuid; /* Null uuid indicates failure */ 105 | } 106 | #endif 107 | return uuid; 108 | } 109 | 110 | KS_DECLARE(ks_uuid_t) ks_uuid_null(void) 111 | { 112 | ks_uuid_t uuid = {0}; 113 | return uuid; 114 | } 115 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.trs 3 | table_file 4 | testpools 5 | testtable 6 | testthreadmutex 7 | testtime 8 | testhash 9 | testq 10 | testsock 11 | testsock2 12 | testwebsock 13 | testwebsock2 14 | testdht 15 | testlog 16 | testdht_net 17 | testdht_msg 18 | dht_example 19 | testhttp 20 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ksutil_add_test(pools) 2 | ksutil_add_test(realloc) 3 | ksutil_add_test(acl) 4 | ksutil_add_test(threadpools) 5 | ksutil_add_test(threadmutex) 6 | ksutil_add_test(time) 7 | ksutil_add_test(q) 8 | ksutil_add_test(hash) 9 | ksutil_add_test(sock) 10 | ksutil_add_test(sock2) 11 | ksutil_add_test(websock) 12 | ksutil_add_test(websock2) 13 | ksutil_add_test(http) 14 | ksutil_add_test(string) 15 | ksutil_add_test(log) 16 | ksutil_add_test(json) 17 | -------------------------------------------------------------------------------- /tests/tap.h: -------------------------------------------------------------------------------- 1 | /* 2 | libtap - Write tests in C 3 | Copyright 2012 Jake Gelbman 4 | This file is licensed under the LGPL 5 | */ 6 | 7 | #ifndef __TAP_H__ 8 | #define __TAP_H__ 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #ifndef va_copy 15 | #ifdef __va_copy 16 | #define va_copy __va_copy 17 | #else 18 | #define va_copy(d, s) ((d) = (s)) 19 | #endif 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | int vok_at_loc (const char *file, int line, int test, const char *fmt, 27 | va_list args); 28 | int ok_at_loc (const char *file, int line, int test, const char *fmt, 29 | ...); 30 | int is_at_loc (const char *file, int line, const char *got, 31 | const char *expected, const char *fmt, ...); 32 | int isnt_at_loc (const char *file, int line, const char *got, 33 | const char *expected, const char *fmt, ...); 34 | int cmp_ok_at_loc (const char *file, int line, int a, const char *op, 35 | int b, const char *fmt, ...); 36 | int cmp_mem_at_loc (const char *file, int line, const void *got, 37 | const void *expected, size_t n, const char *fmt, ...); 38 | int bail_out (int ignore, const char *fmt, ...); 39 | void tap_plan (int tests, const char *fmt, ...); 40 | int diag (const char *fmt, ...); 41 | int exit_status (void); 42 | void tap_skip (int n, const char *fmt, ...); 43 | void tap_todo (int ignore, const char *fmt, ...); 44 | void tap_end_todo (void); 45 | 46 | #define NO_PLAN -1 47 | #define SKIP_ALL -2 48 | #define ok(...) ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 49 | #define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 50 | #define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 51 | #define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 52 | #define cmp_mem(...) cmp_mem_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL); 53 | #define plan(...) tap_plan(__VA_ARGS__, NULL) 54 | #define done_testing() return exit_status() 55 | #define BAIL_OUT(...) bail_out(0, "" __VA_ARGS__, NULL) 56 | #define pass(...) ok(1, "" __VA_ARGS__) 57 | #define fail(...) ok(0, "" __VA_ARGS__) 58 | 59 | #define skip(test, ...) do {if (test) {tap_skip(__VA_ARGS__, NULL); break;} 60 | #define end_skip } while (0) 61 | 62 | #define todo(...) tap_todo(0, "" __VA_ARGS__, NULL) 63 | #define end_todo tap_end_todo() 64 | 65 | #define dies_ok(...) dies_ok_common(1, __VA_ARGS__) 66 | #define lives_ok(...) dies_ok_common(0, __VA_ARGS__) 67 | 68 | #ifdef _WIN32 69 | #define like(...) tap_skip(1, "like is not implemented on Windows") 70 | #define unlike tap_skip(1, "unlike is not implemented on Windows") 71 | #define dies_ok_common(...) \ 72 | tap_skip(1, "Death detection is not supported on Windows") 73 | #else 74 | #define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL) 75 | #define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL) 76 | int like_at_loc (int for_match, const char *file, int line, 77 | const char *got, const char *expected, 78 | const char *fmt, ...); 79 | #include 80 | #include 81 | #include 82 | int tap_test_died (int status); 83 | #define dies_ok_common(for_death, code, ...) \ 84 | do { \ 85 | int cpid; \ 86 | int it_died; \ 87 | tap_test_died(1); \ 88 | cpid = fork(); \ 89 | switch (cpid) { \ 90 | case -1: \ 91 | perror("fork error"); \ 92 | exit(1); \ 93 | case 0: \ 94 | close(1); \ 95 | close(2); \ 96 | code \ 97 | tap_test_died(0); \ 98 | exit(0); \ 99 | } \ 100 | if (waitpid(cpid, NULL, 0) < 0) { \ 101 | perror("waitpid error"); \ 102 | exit(1); \ 103 | } \ 104 | it_died = tap_test_died(0); \ 105 | if (!it_died) \ 106 | {code} \ 107 | ok(for_death ? it_died : !it_died, "" __VA_ARGS__); \ 108 | } while (0) 109 | #endif 110 | 111 | #ifdef __cplusplus 112 | } 113 | #endif 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /tests/testacl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include "tap.h" 29 | 30 | int main(int argc, char **argv) 31 | { 32 | ks_pool_t *pool; 33 | ks_network_list_t *list = NULL; 34 | ks_bool_t match; 35 | 36 | ks_init(); 37 | 38 | plan(8); 39 | 40 | ks_pool_open(&pool); 41 | 42 | ks_network_list_create(&list, "test", KS_FALSE, pool); 43 | 44 | 45 | ks_network_list_add_cidr(list, "10.0.0.0/8", KS_TRUE); 46 | ks_network_list_add_cidr(list, "172.16.0.0/12", KS_TRUE); 47 | ks_network_list_add_cidr(list, "192.168.0.0/16", KS_TRUE); 48 | ks_network_list_add_cidr(list, "fe80::/10", KS_TRUE); 49 | 50 | 51 | match = ks_check_network_list_ip("192.168.1.1", list); 52 | ok(match); 53 | 54 | match = ks_check_network_list_ip("208.34.128.7", list); 55 | ok (!match); 56 | 57 | match = ks_check_network_list_ip_cidr("192.168.1.1", "192.168.0.0/16"); 58 | ok(match); 59 | 60 | match = ks_check_network_list_ip_cidr("208.34.128.7", "192.168.0.0/16"); 61 | ok (!match); 62 | 63 | 64 | ks_pool_free(&list); 65 | 66 | 67 | ks_network_list_create(&list, "test", KS_TRUE, pool); 68 | 69 | ks_network_list_add_cidr(list, "0.0.0.0/0", KS_FALSE); 70 | ks_network_list_add_cidr(list, "fe80::/10", KS_FALSE); 71 | 72 | 73 | match = ks_check_network_list_ip("2637:f368:1281::10", list); 74 | ok(match); 75 | 76 | match = ks_check_network_list_ip("fe80::18b7:53b3:51d8:f5cf", list); 77 | ok(!match); 78 | 79 | match = ks_check_network_list_ip_cidr("fe80::18b7:53b3:51d8:f5cf", "fe80::/10"); 80 | ok(match); 81 | 82 | match = ks_check_network_list_ip_cidr("2637:f368:1281::10", "fe80::/10"); 83 | ok(!match); 84 | 85 | ks_pool_free(&list); 86 | 87 | ks_pool_close(&pool); 88 | 89 | ks_shutdown(); 90 | 91 | done_testing(); 92 | } 93 | -------------------------------------------------------------------------------- /tests/testhash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | #include "tap.h" 25 | 26 | int test1(void) 27 | { 28 | ks_pool_t *pool; 29 | ks_hash_t *hash; 30 | int i, sum1 = 0, sum2 = 0; 31 | 32 | ks_pool_open(&pool); 33 | ks_hash_create(&hash, KS_HASH_MODE_DEFAULT, KS_HASH_FREE_BOTH | KS_HASH_FLAG_RWLOCK, pool); 34 | 35 | for (i = 1; i < 1001; i++) { 36 | char *key = ks_pprintf(pool, "KEY %d", i); 37 | char *val = ks_pprintf(pool, "%d", i); 38 | ks_hash_insert(hash, key, val); 39 | sum1 += i; 40 | } 41 | 42 | 43 | 44 | ks_hash_iterator_t *itt; 45 | 46 | ks_hash_write_lock(hash); 47 | for (itt = ks_hash_first(hash, KS_UNLOCKED); itt; ) { 48 | const void *key; 49 | void *val; 50 | 51 | ks_hash_this(itt, &key, NULL, &val); 52 | 53 | printf("%s=%s\n", (char *)key, (char *)val); 54 | sum2 += atoi(val); 55 | 56 | itt = ks_hash_next(&itt); 57 | ks_hash_remove(hash, (char *)key); 58 | } 59 | ks_hash_write_unlock(hash); 60 | 61 | ks_hash_destroy(&hash); 62 | 63 | ks_pool_close(&pool); 64 | 65 | return (sum1 == sum2); 66 | } 67 | 68 | #define MAX 100 69 | 70 | static void *test2_thread(ks_thread_t *thread, void *data) 71 | { 72 | ks_hash_iterator_t *itt; 73 | ks_hash_t *hash = (ks_hash_t *) data; 74 | 75 | while(!ks_thread_stop_requested(thread)) { 76 | for (itt = ks_hash_first(hash, KS_READLOCKED); itt; itt = ks_hash_next(&itt)) { 77 | const void *key; 78 | void *val; 79 | 80 | ks_hash_this(itt, &key, NULL, &val); 81 | 82 | printf("%u ITT %s=%s\n", (int)ks_thread_self_id(), (char *)key, (char *)val); 83 | } 84 | ks_sleep(100000); 85 | } 86 | 87 | 88 | return NULL; 89 | } 90 | 91 | int test2(void) 92 | { 93 | ks_thread_t *threads[MAX]; 94 | int ttl = 5; 95 | int runs = 5; 96 | ks_pool_t *pool; 97 | ks_hash_t *hash; 98 | int i; 99 | ks_hash_iterator_t *itt; 100 | 101 | ks_pool_open(&pool); 102 | ks_hash_create(&hash, KS_HASH_MODE_DEFAULT, KS_HASH_FREE_BOTH | KS_HASH_FLAG_RWLOCK, pool); 103 | 104 | for (i = 0; i < ttl; i++) { 105 | ks_thread_create(&threads[i], test2_thread, hash, pool); 106 | } 107 | 108 | for(i = 0; i < runs; i++) { 109 | int x = rand() % 5; 110 | int j; 111 | 112 | for (j = 0; j < 100; j++) { 113 | char *key = ks_pprintf(pool, "KEY %d", j); 114 | char *val = ks_pprintf(pool, "%d", j); 115 | ks_hash_insert(hash, key, val); 116 | } 117 | 118 | ks_sleep(x * 1000000); 119 | 120 | ks_hash_write_lock(hash); 121 | for (itt = ks_hash_first(hash, KS_UNLOCKED); itt; ) { 122 | const void *key; 123 | void *val; 124 | 125 | ks_hash_this(itt, &key, NULL, &val); 126 | 127 | printf("DEL %s=%s\n", (char *)key, (char *)val); 128 | 129 | itt = ks_hash_next(&itt); 130 | ks_hash_remove(hash, (char *)key); 131 | } 132 | ks_hash_write_unlock(hash); 133 | 134 | } 135 | 136 | for (i = 0; i < ttl; i++) { 137 | ks_thread_destroy(&threads[i]); 138 | } 139 | 140 | 141 | ks_hash_destroy(&hash); 142 | ks_pool_close(&pool); 143 | 144 | return 1; 145 | } 146 | 147 | #define TEST3_SIZE 20 148 | int test3(void) 149 | { 150 | ks_pool_t *pool; 151 | ks_hash_t *hash; 152 | ks_byte_t data[TEST3_SIZE] = { 52, 116, 29, 120, 56, 135, 31, 196, 165, 219, 102, 169, 217, 228, 24, 163, 203, 93, 98, 71 }; 153 | ks_byte_t data2[TEST3_SIZE] = { 248, 96, 216, 171, 94, 116, 77, 48, 114, 0, 49, 61, 93, 229, 224, 10, 6, 8, 112, 248 }; 154 | ks_byte_t data3[TEST3_SIZE] = { 171, 58, 43, 4, 49, 222, 42, 253, 18, 122, 230, 51, 180, 66, 154, 130, 114, 117, 172, 193 }; 155 | char *A, *B, *C; 156 | 157 | ks_pool_open(&pool); 158 | ks_hash_create(&hash, KS_HASH_MODE_ARBITRARY, KS_HASH_FLAG_NOLOCK, pool); 159 | ks_hash_set_keysize(hash, TEST3_SIZE); 160 | 161 | ks_hash_insert(hash, data, "FOO"); 162 | ks_hash_insert(hash, data2, "BAR"); 163 | ks_hash_insert(hash, data3, "BAZ"); 164 | 165 | 166 | A = (char *)ks_hash_search(hash, data, KS_UNLOCKED); 167 | B = (char *)ks_hash_search(hash, data2, KS_UNLOCKED); 168 | C = (char *)ks_hash_search(hash, data3, KS_UNLOCKED); 169 | 170 | 171 | printf("RESULT [%s][%s][%s]\n", A, B, C); 172 | 173 | ks_hash_destroy(&hash); 174 | 175 | ks_pool_close(&pool); 176 | 177 | return !strcmp(A, "FOO") && !strcmp(B, "BAR") && !strcmp(C, "BAZ"); 178 | 179 | } 180 | 181 | 182 | int main(int argc, char **argv) 183 | { 184 | 185 | ks_init(); 186 | ks_global_set_log_level(KS_LOG_LEVEL_DEBUG); 187 | 188 | plan(3); 189 | 190 | ok(test1()); 191 | ok(test2()); 192 | ok(test3()); 193 | 194 | ks_shutdown(); 195 | 196 | done_testing(); 197 | } 198 | -------------------------------------------------------------------------------- /tests/testjson.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #include "libks/ks.h" 23 | 24 | #include 25 | #include 26 | #include 27 | #include "tap.h" 28 | 29 | int main(int argc, char **argv) 30 | { 31 | ks_json_t *json = ks_json_create_object(); 32 | const char *value; 33 | 34 | ks_init(); 35 | 36 | plan(2); 37 | 38 | value = ks_json_get_object_string(json, "key", NULL); 39 | ok(value == NULL); 40 | 41 | value = ks_json_get_object_string(json, "key", "value"); 42 | ok(strcmp(value, "value") == 0); 43 | 44 | ks_shutdown(); 45 | 46 | done_testing(); 47 | } 48 | -------------------------------------------------------------------------------- /tests/testlog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | 25 | #include "tap.h" 26 | 27 | int main(int argc, char **argv) 28 | { 29 | char a[8196 * 5]; 30 | memset(a, 'a', sizeof(a)); 31 | a[sizeof(a) - 1] = '\0'; 32 | ks_init(); 33 | ks_global_set_log_level(KS_LOG_LEVEL_DEBUG); 34 | ks_log(a, a, 9999999, KS_LOG_LEVEL_DEBUG, a); 35 | ks_log(a, a, 9999999, KS_LOG_LEVEL_INFO, a); 36 | ks_log(a, a, 9999999, KS_LOG_LEVEL_WARNING, a); 37 | ks_log(a, a, 9999999, KS_LOG_LEVEL_ERROR, a); 38 | ks_log(a, a, 9999999, KS_LOG_LEVEL_CRIT, a); 39 | ks_log(a, a, 9999999, KS_LOG_LEVEL_ALERT, a); 40 | ks_log(a, a, 9999999, KS_LOG_LEVEL_EMERG, a); 41 | } 42 | -------------------------------------------------------------------------------- /tests/testpolling.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include "tap.h" 29 | 30 | ks_socket_t start_listen(ks_sockaddr_t *addr) 31 | { 32 | ks_socket_t listener = KS_SOCK_INVALID; 33 | ks_status_t ret = KS_STATUS_SUCCESS; 34 | 35 | ks_assert(addr); 36 | 37 | if ((listener = socket(addr->family, SOCK_STREAM, IPPROTO_TCP)) == KS_SOCK_INVALID) { 38 | ks_log(KS_LOG_DEBUG, "listener == KS_SOCK_INVALID\n"); 39 | ret = KS_STATUS_FAIL; 40 | goto done; 41 | } 42 | 43 | ks_socket_option(listener, SO_REUSEADDR, KS_TRUE); 44 | ks_socket_option(listener, TCP_NODELAY, KS_TRUE); 45 | if (addr->family == AF_INET6) ks_socket_option(listener, IPV6_V6ONLY, KS_TRUE); 46 | 47 | if (ks_addr_bind(listener, addr) != KS_STATUS_SUCCESS) { 48 | ks_log(KS_LOG_DEBUG, "ks_addr_bind(listener, addr) != KS_STATUS_SUCCESS\n"); 49 | ret = KS_STATUS_FAIL; 50 | goto done; 51 | } 52 | 53 | if (listen(listener, 4) != 0) { 54 | ks_log(KS_LOG_DEBUG, "listen(listener, backlog) != 0\n"); 55 | ret = KS_STATUS_FAIL; 56 | goto done; 57 | } 58 | 59 | done: 60 | if (ret != KS_STATUS_SUCCESS) { 61 | if (listener != KS_SOCK_INVALID) { 62 | ks_socket_shutdown(listener, SHUT_RDWR); 63 | ks_socket_close(&listener); 64 | listener = KS_SOCK_INVALID; 65 | } 66 | } 67 | return listener; 68 | } 69 | 70 | int main(int argc, char **argv) 71 | { 72 | ks_pool_t *pool = NULL; 73 | struct pollfd *listeners_poll = NULL; 74 | int32_t listeners_count = 0; 75 | int32_t listener_index = -1; 76 | ks_sockaddr_t addr; 77 | ks_socket_t listener = KS_SOCK_INVALID; 78 | ks_socket_t sock = KS_SOCK_INVALID; 79 | 80 | ks_init(); 81 | 82 | plan(2); 83 | 84 | ks_pool_open(&pool); 85 | 86 | ks_addr_set(&addr, "0.0.0.0", 1234, AF_INET); 87 | 88 | listener = start_listen(&addr); 89 | listener_index = listeners_count++; 90 | listeners_poll = (struct pollfd *)ks_pool_alloc(pool, sizeof(struct pollfd) * listeners_count); 91 | ok(listeners_poll != NULL); 92 | 93 | listeners_poll[listener_index].fd = listener; 94 | listeners_poll[listener_index].events = POLLIN; 95 | 96 | while (1) { 97 | int p = ks_poll(listeners_poll, listeners_count, 100); 98 | if (p > 0) { 99 | printf("POLL event occurred\n"); 100 | for (int32_t index = 0; index < listeners_count; ++index) { 101 | if (listeners_poll[index].revents & POLLERR) { 102 | printf("POLLERR on index %d\n", index); 103 | break; 104 | } 105 | if (!(listeners_poll[index].revents & POLLIN)) continue; 106 | 107 | printf("POLLIN on index %d\n", index); 108 | 109 | if ((sock = accept(listeners_poll[index].fd, NULL, NULL)) == KS_SOCK_INVALID) { 110 | printf("Accept failed on index %d\n", index); 111 | continue; 112 | } 113 | 114 | printf("Accept success on index %d\n", index); 115 | } 116 | break; 117 | } else if (p < 0) { 118 | printf("Polling socket error %d\n", WSAGetLastError()); 119 | } 120 | } 121 | 122 | ok(sock != KS_SOCK_INVALID); 123 | 124 | if (sock != KS_SOCK_INVALID) ks_socket_close(&sock); 125 | 126 | for (int index = 0; index < listeners_count; ++index) { 127 | listener = listeners_poll[index].fd; 128 | ks_socket_close(&listener); 129 | } 130 | ks_pool_free(&listeners_poll); 131 | 132 | ks_pool_close(&pool); 133 | 134 | ks_shutdown(); 135 | 136 | done_testing(); 137 | } 138 | -------------------------------------------------------------------------------- /tests/testq.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | #include "tap.h" 25 | #define MAX 200 26 | 27 | #ifndef MIN 28 | #define MIN(a, b) ((a)<(b)?(a):(b)) 29 | #endif 30 | 31 | static void *test1_thread(ks_thread_t *thread, void *data) 32 | { 33 | ks_q_t *q = (ks_q_t *) data; 34 | void *pop; 35 | 36 | while(ks_q_pop(q, &pop) == KS_STATUS_SUCCESS) { 37 | //int *i = (int *)pop; 38 | //printf("POP %d\n", *i); 39 | ks_pool_free(&pop); 40 | } 41 | 42 | return NULL; 43 | } 44 | 45 | static void do_flush(ks_q_t *q, void *ptr, void *flush_data) 46 | { 47 | //ks_pool_t *pool = (ks_pool_t *)flush_data; 48 | ks_pool_free(&ptr); 49 | 50 | } 51 | 52 | int qtest1(int loops) 53 | { 54 | ks_thread_t *thread; 55 | ks_q_t *q; 56 | ks_pool_t *pool; 57 | int i; 58 | int r = 1; 59 | void *pop; 60 | 61 | ks_pool_open(&pool); 62 | ks_q_create(&q, pool, loops); 63 | 64 | ks_thread_create(&thread, test1_thread, q, pool); 65 | 66 | if (ks_q_pop_timeout(q, &pop, 500) != KS_STATUS_TIMEOUT) { 67 | r = 0; 68 | goto end; 69 | } 70 | 71 | for (i = 0; i < 10000; i++) { 72 | int *val = (int *)ks_pool_alloc(pool, sizeof(int)); 73 | *val = i; 74 | ks_q_push(q, val); 75 | } 76 | 77 | ks_q_wait(q); 78 | 79 | ks_q_term(q); 80 | ks_thread_join(thread); 81 | 82 | ks_q_destroy(&q); 83 | 84 | ks_q_create(&q, pool, loops); 85 | ks_q_set_flush_fn(q, do_flush, pool); 86 | 87 | for (i = 0; i < loops; i++) { 88 | int *val = (int *)ks_pool_alloc(pool, sizeof(int)); 89 | *val = i; 90 | ks_q_push(q, val); 91 | } 92 | 93 | end: 94 | 95 | ks_q_destroy(&q); 96 | 97 | ks_pool_close(&pool); 98 | 99 | return r; 100 | 101 | } 102 | 103 | struct test2_data { 104 | ks_q_t *q; 105 | int try; 106 | int ready; 107 | int running; 108 | }; 109 | 110 | static void *test2_thread(ks_thread_t *thread, void *data) 111 | { 112 | struct test2_data *t2 = (struct test2_data *) data; 113 | void *pop; 114 | ks_status_t status; 115 | int popped = 0; 116 | 117 | while (t2->running && (t2->try && !t2->ready)) { 118 | ks_sleep(10000); 119 | continue; 120 | } 121 | 122 | while (t2->running || ks_q_size(t2->q)) { 123 | if (t2->try) { 124 | status = ks_q_trypop(t2->q, &pop); 125 | } else { 126 | status = ks_q_pop(t2->q, &pop); 127 | } 128 | 129 | if (status == KS_STATUS_SUCCESS) { 130 | //int *i = (int *)pop; 131 | //printf("%p POP %d\n", (void *)pthread_self(), *i); 132 | popped++; 133 | ks_pool_free(&pop); 134 | } else if (status == KS_STATUS_INACTIVE) { 135 | break; 136 | } else if (t2->try && ks_q_size(t2->q)) { 137 | int s = rand() % 100; 138 | ks_sleep(s * 1000); 139 | } 140 | } 141 | 142 | return (void *) (intptr_t)popped; 143 | } 144 | 145 | ks_size_t qtest2(int ttl, int try, int loops) 146 | { 147 | ks_thread_t *threads[MAX]; 148 | ks_q_t *q; 149 | ks_pool_t *pool; 150 | int i; 151 | struct test2_data t2 = { 0 }; 152 | ks_size_t r; 153 | int dropped = 0; 154 | int qlen = loops / 2; 155 | int total_popped = 0; 156 | 157 | ks_pool_open(&pool); 158 | ks_q_create(&q, pool, qlen); 159 | 160 | t2.q = q; 161 | t2.try = try; 162 | t2.running = 1; 163 | 164 | for (i = 0; i < ttl; i++) { 165 | ks_thread_create(&threads[i], test2_thread, &t2, pool); 166 | } 167 | 168 | //ks_sleep(loops00); 169 | 170 | for (i = 0; i < loops; i++) { 171 | int *val = (int *)ks_pool_alloc(pool, sizeof(int)); 172 | *val = i; 173 | if (try > 1) { 174 | if (ks_q_trypush(q, val) != KS_STATUS_SUCCESS) { 175 | dropped++; 176 | } 177 | } else { 178 | ks_q_push(q, val); 179 | } 180 | if (i > qlen / 2) { 181 | t2.ready = 1; 182 | } 183 | } 184 | 185 | t2.running = 0; 186 | 187 | if (!try) { 188 | ks_q_wait(q); 189 | ks_q_term(q); 190 | } 191 | 192 | for (i = 0; i < ttl; i++) { 193 | int popped; 194 | ks_thread_join(threads[i]); 195 | popped = (int)(intptr_t)ks_thread_get_return_data(threads[i]); 196 | if (popped) { 197 | printf("%d/%d POPPED %d\n", i, ttl, popped); 198 | } 199 | total_popped += popped; 200 | } 201 | 202 | r = ks_q_size(q); 203 | ks_assert(r == 0); 204 | 205 | ks_q_destroy(&q); 206 | 207 | 208 | 209 | printf("TOTAL POPPED: %d DROPPED %d SUM: %d\n", total_popped, dropped, total_popped + dropped);fflush(stdout); 210 | 211 | if (try < 2) { 212 | ks_assert(total_popped == loops); 213 | } else { 214 | ks_assert(total_popped + dropped == loops); 215 | } 216 | 217 | ks_pool_close(&pool); 218 | 219 | return r; 220 | 221 | } 222 | 223 | ks_status_t qtest3() 224 | { 225 | ks_q_t *q = NULL; 226 | ks_pool_t *pool = NULL; 227 | ks_status_t status = KS_STATUS_SUCCESS; 228 | 229 | ks_pool_open(&pool); 230 | ks_q_create(&q, pool, 0); 231 | 232 | int *val = (int*)ks_pool_alloc(pool, sizeof(int)); 233 | int *tmp = NULL; 234 | 235 | if ((status = ks_q_trypeek(q, (void **)&tmp)) != KS_STATUS_BREAK) return KS_STATUS_FAIL; 236 | if ((status = ks_q_trypush(q, val)) != KS_STATUS_SUCCESS) return status; 237 | if (ks_q_size(q) != 1) return KS_STATUS_FAIL; 238 | if (ks_q_trypeek(q, (void **)&tmp) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL; 239 | if (tmp != val) return KS_STATUS_FAIL; 240 | if (ks_q_size(q) != 1) return KS_STATUS_FAIL; 241 | 242 | ks_q_destroy(&q); 243 | ks_pool_close(&pool); 244 | } 245 | 246 | int main(int argc, char **argv) 247 | { 248 | int ttl; 249 | int size = 100000; 250 | int runs = 1; 251 | int i; 252 | 253 | ks_init(); 254 | 255 | plan(4 * runs + 1); 256 | 257 | ttl = ks_env_cpu_count() * 5; 258 | //ttl = 5; 259 | ttl = MIN(MAX, ttl); 260 | 261 | 262 | ok(qtest3() == KS_STATUS_SUCCESS); 263 | for(i = 0; i < runs; i++) { 264 | ok(qtest1(size)); 265 | ok(qtest2(ttl, 0, size) == 0); 266 | ok(qtest2(ttl, 1, size) == 0); 267 | ok(qtest2(ttl, 2, size) == 0); 268 | } 269 | 270 | printf("TTL %d RUNS %d\n", ttl, runs); 271 | 272 | ks_shutdown(); 273 | 274 | done_testing(); 275 | } 276 | -------------------------------------------------------------------------------- /tests/testrealloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #include "libks/ks.h" 23 | 24 | #include 25 | #include 26 | #include 27 | #include "tap.h" 28 | 29 | int main(int argc, char **argv) 30 | { 31 | ks_pool_t *pool; 32 | uint32_t *buf = NULL; 33 | intptr_t ptr = 0; 34 | 35 | ks_init(); 36 | 37 | plan(4); 38 | 39 | ks_pool_open(&pool); 40 | 41 | buf = (uint32_t *)ks_pool_alloc(pool, sizeof(uint32_t) * 1); 42 | ok(buf != NULL); 43 | 44 | ptr = (intptr_t)buf; 45 | 46 | buf = (uint32_t *)ks_pool_resize(buf, sizeof(uint32_t) * 1); 47 | ok(buf != NULL); 48 | 49 | ok((intptr_t)buf == ptr); 50 | 51 | buf = (uint32_t *)ks_pool_resize(buf, sizeof(uint32_t) * 2); 52 | ok(buf != NULL); 53 | 54 | ks_pool_free(&buf); 55 | 56 | ks_pool_close(&pool); 57 | 58 | ks_shutdown(); 59 | 60 | done_testing(); 61 | } 62 | -------------------------------------------------------------------------------- /tests/testsock2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #include "libks/ks.h" 23 | #include 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | char ip[80] = ""; 28 | 29 | ks_init(); 30 | 31 | if (argc > 1) { 32 | ks_ip_route(ip, sizeof(ip), argv[1]); 33 | printf("IPS [%s]\n", ip); 34 | } else { 35 | fprintf(stderr, "Missing arg \n"); 36 | } 37 | 38 | ks_shutdown(); 39 | 40 | done_testing(); 41 | } 42 | -------------------------------------------------------------------------------- /tests/teststring.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | #include "libks/ks.h" 23 | 24 | #include 25 | #include 26 | #include 27 | #include "tap.h" 28 | 29 | struct human_test_entry_s { 30 | ks_size_t size; 31 | int max_precision; 32 | const char *value; 33 | }; 34 | 35 | static void test_human_size() 36 | { 37 | static const struct human_test_entry_s entries[] = { 38 | { 1024ull, 1, "1.0kB" }, 39 | { 1024ull * 1024, 1, "1.0MB" }, 40 | { 1024ull * 1024 * 1024, 1, "1.0GB" }, 41 | { 1024ull * 1024 * 1024 * 1024, 1, "1.0TB" }, 42 | { 1024ull * 1024 * 1024 * 1024 * 1024, 1, "1.0PB" }, 43 | { 1024ull * 1024 * 1024 * 1024 * 1024 * 1024, 1, "1.0EB" }, 44 | // { 1024ull * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, 1, "1.0ZB" }, 45 | // { 1024ull * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, 1, "1.0YB" }, 46 | 47 | { 1024ull, 0, "1kB" }, 48 | { 1024ull * 1024, 0, "1MB" }, 49 | { 1024ull * 1024 * 1024, 0, "1GB" }, 50 | { 1024ull * 1024 * 1024 * 1024, 0, "1TB" }, 51 | { 1024ull * 1024 * 1024 * 1024 * 1024, 0, "1PB" }, 52 | // { 1024ull * 1024 * 1024 * 1024 * 1024 * 1024, 0, "1EB" }, 53 | // { 1024ull * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, 0, "1ZB" }, 54 | // { 1024ull * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, 0, "1YB" }, 55 | 56 | {0} 57 | }; 58 | 59 | for (int32_t index = 0; entries[index].size != 0; index++) { 60 | 61 | char workspace[1024]; 62 | 63 | ks_human_readable_size(entries[index].size, 64 | entries[index].max_precision, sizeof(workspace), workspace); 65 | 66 | printf("Checking if: %s == %s\n", workspace, entries[index].value); 67 | ok(!strcmp(workspace, entries[index].value)); 68 | } 69 | } 70 | 71 | int main(int argc, char **argv) 72 | { 73 | ks_init(); 74 | test_human_size(); 75 | } 76 | -------------------------------------------------------------------------------- /tests/testthreadpools.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include "tap.h" 29 | 30 | typedef struct ks_dht_nodeid_s { uint8_t id[20]; } ks_dht_nodeid_t; 31 | 32 | struct x { 33 | int i; 34 | ks_pool_t *pool; 35 | }; 36 | 37 | static void *test1_thread(ks_thread_t *thread, void *data) 38 | { 39 | struct x *mydata = (struct x *) data; 40 | 41 | ks_log(KS_LOG_DEBUG, "Thread %d\n", mydata->i); 42 | ks_sleep(100000); 43 | ks_pool_free(&mydata); 44 | return NULL; 45 | } 46 | 47 | static int test1() 48 | { 49 | ks_pool_t *pool; 50 | ks_thread_pool_t *tp = NULL; 51 | int i = 0; 52 | 53 | ks_pool_open(&pool); 54 | 55 | ks_thread_pool_create(&tp, 2, 10, KS_THREAD_DEFAULT_STACK, KS_PRI_DEFAULT, 5); 56 | 57 | for (i = 0; i < 500; i++) { 58 | struct x *data = ks_pool_alloc(pool, sizeof(*data)); 59 | data->i = i; 60 | data->pool = pool; 61 | ks_sleep(1); 62 | ks_thread_pool_add_job(tp, test1_thread, data); 63 | } 64 | 65 | 66 | while(ks_thread_pool_backlog(tp)) { 67 | ks_sleep(100000); 68 | } 69 | 70 | // ks_sleep(10000000); 71 | 72 | ks_thread_pool_destroy(&tp); 73 | ks_pool_close(&pool); 74 | 75 | return 1; 76 | } 77 | 78 | int main(int argc, char **argv) 79 | { 80 | ks_init(); 81 | 82 | plan(1); 83 | 84 | ok(test1()); 85 | 86 | ks_shutdown(); 87 | 88 | done_testing(); 89 | } 90 | -------------------------------------------------------------------------------- /tests/testtime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 SignalWire, Inc 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "libks/ks.h" 24 | #include "tap.h" 25 | 26 | int main(int argc, char **argv) 27 | { 28 | int64_t now, then; 29 | int diff; 30 | int i; 31 | 32 | ks_init(); 33 | 34 | plan(2); 35 | 36 | then = ks_time_now(); 37 | 38 | ks_sleep(2000000); 39 | 40 | now = ks_time_now(); 41 | 42 | diff = (int)((now - then) / 1000); 43 | printf("DIFF %ums\n", diff); 44 | 45 | 46 | ok( diff > 1990 && diff < 2010 ); 47 | 48 | then = ks_time_now(); 49 | 50 | for (i = 0; i < 100; i++) { 51 | ks_sleep(20000); 52 | } 53 | 54 | now = ks_time_now(); 55 | 56 | diff = (int)((now - then) / 1000); 57 | printf("DIFF %ums\n", diff); 58 | 59 | #if KS_PLAT_MAC 60 | /* the clock on osx seems to be particularly bad at being accurate, we need a bit more room for error*/ 61 | ok( diff > 1900 && diff < 2500 ); 62 | #else 63 | ok( diff > 1950 && diff < 2050 ); 64 | #endif 65 | ks_shutdown(); 66 | done_testing(); 67 | } 68 | -------------------------------------------------------------------------------- /uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") 2 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") 3 | endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") 4 | 5 | file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) 6 | string(REGEX REPLACE "\n" ";" files "${files}") 7 | foreach(file ${files}) 8 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}") 9 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 10 | exec_program( 11 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 12 | OUTPUT_VARIABLE rm_out 13 | RETURN_VALUE rm_retval 14 | ) 15 | if(NOT "${rm_retval}" STREQUAL 0) 16 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") 17 | endif(NOT "${rm_retval}" STREQUAL 0) 18 | else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 19 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.") 20 | endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 21 | endforeach(file) 22 | -------------------------------------------------------------------------------- /win/.gitignore: -------------------------------------------------------------------------------- 1 | .vs/* 2 | libks.2017.VC.db 3 | Win32/* 4 | x64/* 5 | out/* 6 | 7za*.exe 7 | openssl-*.zip 8 | openssl-*/ 9 | Debug/ 10 | Release/ -------------------------------------------------------------------------------- /win/basedir.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildThisFileDirectory) 5 | 6 | 7 | true 8 | 9 | -------------------------------------------------------------------------------- /win/build.cmd: -------------------------------------------------------------------------------- 1 | @REM check and set Visual Studio environment 2 | CALL msbuild.cmd 3 | echo %msbuild% 4 | cmd /C %msbuild% libks.sln /p:Configuration=Debug /p:Platform=Win32 /t:Build 5 | cmd /C %msbuild% libks.sln /p:Configuration=Debug /p:Platform=x64 /t:Build 6 | cmd /C %msbuild% libks.sln /p:Configuration=Release /p:Platform=Win32 /t:Build 7 | cmd /C %msbuild% libks.sln /p:Configuration=Release /p:Platform=x64 /t:Build 8 | echo Done! Packages (zip files) were placed to the "out" folder. -------------------------------------------------------------------------------- /win/buildpackages.task: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 92 | 93 | 94 | 95 | 96 | 97 | true 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /win/libks-version.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 2.0.6 8 | 1 9 | $(BaseDir)../ 10 | 11 | 12 | true 13 | 14 | 15 | 16 | 17 | 18 | $(libksVersion) 19 | 20 | 21 | -------------------------------------------------------------------------------- /win/libks.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2048 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libks", "libks.vcxproj", "{EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8}.Debug|Win32.Build.0 = Debug|Win32 18 | {EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8}.Debug|x64.ActiveCfg = Debug|x64 19 | {EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8}.Debug|x64.Build.0 = Debug|x64 20 | {EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8}.Release|Win32.ActiveCfg = Release|Win32 21 | {EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8}.Release|Win32.Build.0 = Release|Win32 22 | {EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8}.Release|x64.ActiveCfg = Release|x64 23 | {EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {2C121C7E-6CC8-4DCA-8D78-24089711F2A7} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /win/libks.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | libks 23 | libks 24 | Win32Proj 25 | {EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8} 26 | 27 | 28 | 29 | $(DefaultPlatformToolset) 30 | x86 31 | 32 | 33 | $(DefaultPlatformToolset) 34 | x64 35 | 36 | 37 | $(DefaultPlatformToolset) 38 | x86 39 | 40 | 41 | $(DefaultPlatformToolset) 42 | x64 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /win/msbuild.cmd: -------------------------------------------------------------------------------- 1 | @REM check and set Visual Studio environment 2 | rem There is vswhere.exe starting VS2017U2 3 | if "%VSWHERE%"=="" set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" 4 | 5 | rem Use %ProgramFiles% in a 32-bit program prior to Windows 10) 6 | If Not Exist "%VSWHERE%" set "VSWHERE=%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" 7 | 8 | If Not Exist "%VSWHERE%" ( 9 | echo "WARNING: Can't find vswhere.exe. It is a part of VS 2017 version 15.2 or later. Trying known path..." 10 | set "InstallDir=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community" 11 | ) ELSE ( 12 | for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -latest -products * -requires Microsoft.Component.MSBuild -property installationPath`) do ( 13 | set InstallDir=%%i 14 | ) 15 | ) 16 | 17 | echo Install dir is "%InstallDir%" 18 | if exist "%InstallDir%\MSBuild\Current\Bin\MSBuild.exe" ( 19 | set msbuild="%InstallDir%\MSBuild\Current\Bin\MSBuild.exe" 20 | ) 21 | -------------------------------------------------------------------------------- /win/openssl-version.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 3.4.0 8 | $(BaseDir)openssl-$(OpenSSLVersion) 9 | 10 | 11 | true 12 | 13 | 14 | 15 | 16 | 17 | $(OpenSSLVersion) 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /win/openssl.download.target: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 26 | 27 | 28 | 35 | 36 | 37 | 44 | 45 | 46 | 47 | true 48 | 49 | 50 | --------------------------------------------------------------------------------