├── .github ├── docker │ └── debian │ │ ├── bookworm │ │ ├── amd64 │ │ │ └── Dockerfile │ │ ├── arm32v7 │ │ │ └── Dockerfile │ │ └── arm64v8 │ │ │ └── Dockerfile │ │ └── bullseye │ │ ├── amd64 │ │ └── Dockerfile │ │ ├── arm32v7 │ │ └── Dockerfile │ │ └── arm64v8 │ │ └── Dockerfile └── workflows │ ├── build.yml │ ├── ci.yml │ ├── macos.yml │ └── windows.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── README ├── cmake ├── FindLibKS.cmake ├── HunterGate.cmake └── cotire.cmake ├── copyright ├── examples └── client │ ├── .gitignore │ ├── CMakeLists.txt │ ├── README │ └── main.c ├── inc └── signalwire-client-c │ ├── JSON │ └── macros.h │ ├── blade │ ├── authenticate.h │ ├── authority.h │ ├── blade.h │ ├── broadcast.h │ ├── connect.h │ ├── disconnect.h │ ├── execute.h │ ├── identity.h │ ├── netcast.h │ ├── ping.h │ ├── protocol.h │ ├── register.h │ ├── subscription.h │ ├── type.h │ └── util.h │ ├── client.h │ ├── command.h │ ├── config.h │ ├── connection.h │ ├── export.h │ ├── identity.h │ ├── init.h │ ├── internal │ └── config.h │ ├── nodestore.h │ ├── pmethod.h │ ├── session.h │ ├── signalwire │ ├── provisioning.h │ └── signalwire.h │ ├── ssl.h │ ├── subscription.h │ ├── transport │ ├── frame.h │ └── websocket.h │ └── version.h.in ├── scan_build.sh ├── signalwire_client.pc.in ├── src ├── command.c ├── config.c ├── connection.c ├── identity.c ├── init.c ├── nodestore.c ├── session.c ├── ssl.c ├── subscription.c └── transport │ ├── frame.c │ └── websocket.c ├── swclient.code-workspace ├── swclt_test.cfg ├── swclt_test ├── CMakeLists.txt ├── cases │ ├── command.c │ ├── connection.c │ ├── execute.c │ ├── json.c │ ├── nodestore.c │ ├── session.c │ └── uncert.c ├── cfg │ ├── swclt_test.cfg │ ├── swclt_test_bad.cfg │ └── swclt_testuncert.cfg ├── main.c ├── swclt_test.h └── util │ └── ssl.h ├── swclt_test_bad.cfg ├── swclt_testuncert.cfg ├── uninstall.cmake.in └── win ├── .gitignore ├── basedir.props ├── build.cmd ├── buildpackages.task ├── downloadpackage.task ├── libks-version.props ├── libks.props ├── msbuild.cmd ├── openssl-version.props ├── openssl.download.target ├── signalwire-client-c-version.props ├── signalwire-client-c.sln └── signalwire-client-c.vcxproj /.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 CODENAME=bookworm 9 | ARG ARCH=amd64 10 | 11 | # Credentials 12 | ARG REPO_DOMAIN=freeswitch.signalwire.com 13 | ARG REPO_USERNAME=user 14 | 15 | ARG BUILD_NUMBER=42 16 | ARG GIT_SHA=0000000000 17 | 18 | ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg" 19 | 20 | ARG DATA_DIR=/data 21 | 22 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 23 | 24 | SHELL ["/bin/bash", "-c"] 25 | 26 | ENV DEBIAN_FRONTEND=noninteractive 27 | 28 | RUN apt-get -q update \ 29 | && apt-get -y -q install \ 30 | apt-transport-https \ 31 | autoconf \ 32 | automake \ 33 | build-essential \ 34 | ca-certificates \ 35 | cmake \ 36 | curl \ 37 | debhelper \ 38 | devscripts \ 39 | dh-autoreconf \ 40 | dos2unix \ 41 | doxygen \ 42 | dpkg-dev \ 43 | git \ 44 | gnupg2 \ 45 | graphviz \ 46 | libglib2.0-dev \ 47 | libssl-dev \ 48 | lsb-release \ 49 | pkg-config \ 50 | unzip \ 51 | wget 52 | 53 | RUN update-ca-certificates --fresh 54 | 55 | RUN echo "export CODENAME=${CODENAME}" | tee ~/.env \ 56 | && echo "export ARCH=${ARCH}" | tee -a ~/.env \ 57 | && chmod +x ~/.env 58 | 59 | RUN . ~/.env && cat < /etc/apt/sources.list.d/freeswitch.list 60 | deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${CODENAME} main 61 | deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${CODENAME} main 62 | EOF 63 | 64 | RUN git config --global --add safe.directory '*' \ 65 | && git config --global user.name "${MAINTAINER_NAME}" \ 66 | && git config --global user.email "${MAINTAINER_EMAIL}" 67 | 68 | RUN --mount=type=secret,id=REPO_PASSWORD,required=true \ 69 | printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \ 70 | printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \ 71 | printf "password " >> /etc/apt/auth.conf && \ 72 | cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \ 73 | sha512sum /run/secrets/REPO_PASSWORD && \ 74 | curl \ 75 | --fail \ 76 | --netrc-file /etc/apt/auth.conf \ 77 | --output ${GPG_KEY} \ 78 | https://${REPO_DOMAIN}/repo/deb/debian-release/signalwire-freeswitch-repo.gpg && \ 79 | file ${GPG_KEY} && \ 80 | apt-get --quiet update && \ 81 | apt-get --yes --quiet install \ 82 | libks2 \ 83 | && rm -f /etc/apt/auth.conf 84 | 85 | # Bootstrap and Build 86 | COPY . ${DATA_DIR} 87 | WORKDIR ${DATA_DIR} 88 | 89 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 90 | -DCMAKE_BUILD_TYPE=Debug \ 91 | -DCMAKE_INSTALL_PREFIX="/usr" \ 92 | && make package \ 93 | && mkdir OUT \ 94 | && mv -v *.deb OUT/. 95 | 96 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 97 | FROM scratch 98 | COPY --from=builder /data/OUT/ / 99 | -------------------------------------------------------------------------------- /.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 CODENAME=bookworm 9 | ARG ARCH=arm32 10 | 11 | # Credentials 12 | ARG REPO_DOMAIN=freeswitch.signalwire.com 13 | ARG REPO_USERNAME=user 14 | 15 | ARG BUILD_NUMBER=42 16 | ARG GIT_SHA=0000000000 17 | 18 | ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg" 19 | 20 | ARG DATA_DIR=/data 21 | 22 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 23 | 24 | SHELL ["/bin/bash", "-c"] 25 | 26 | ENV DEBIAN_FRONTEND=noninteractive 27 | 28 | RUN apt-get -q update \ 29 | && apt-get -y -q install \ 30 | apt-transport-https \ 31 | autoconf \ 32 | automake \ 33 | build-essential \ 34 | ca-certificates \ 35 | cmake \ 36 | curl \ 37 | debhelper \ 38 | devscripts \ 39 | dh-autoreconf \ 40 | dos2unix \ 41 | doxygen \ 42 | dpkg-dev \ 43 | git \ 44 | gnupg2 \ 45 | graphviz \ 46 | libglib2.0-dev \ 47 | libssl-dev \ 48 | lsb-release \ 49 | pkg-config \ 50 | unzip \ 51 | wget 52 | 53 | RUN update-ca-certificates --fresh 54 | 55 | RUN echo "export CODENAME=${CODENAME}" | tee ~/.env \ 56 | && echo "export ARCH=${ARCH}" | tee -a ~/.env \ 57 | && chmod +x ~/.env 58 | 59 | RUN . ~/.env && cat < /etc/apt/sources.list.d/freeswitch.list 60 | deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/rpi/debian-release ${CODENAME} main 61 | deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/rpi/debian-release ${CODENAME} main 62 | EOF 63 | 64 | RUN git config --global --add safe.directory '*' \ 65 | && git config --global user.name "${MAINTAINER_NAME}" \ 66 | && git config --global user.email "${MAINTAINER_EMAIL}" 67 | 68 | RUN --mount=type=secret,id=REPO_PASSWORD,required=true \ 69 | printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \ 70 | printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \ 71 | printf "password " >> /etc/apt/auth.conf && \ 72 | cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \ 73 | sha512sum /run/secrets/REPO_PASSWORD && \ 74 | curl \ 75 | --fail \ 76 | --netrc-file /etc/apt/auth.conf \ 77 | --output ${GPG_KEY} \ 78 | https://${REPO_DOMAIN}/repo/deb/rpi/debian-release/signalwire-freeswitch-repo.gpg && \ 79 | file ${GPG_KEY} && \ 80 | apt-get --quiet update && \ 81 | apt-get --yes --quiet install \ 82 | libks2 \ 83 | && rm -f /etc/apt/auth.conf 84 | 85 | # Bootstrap and Build 86 | COPY . ${DATA_DIR} 87 | WORKDIR ${DATA_DIR} 88 | 89 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 90 | -DCMAKE_BUILD_TYPE=Debug \ 91 | -DCMAKE_INSTALL_PREFIX="/usr" \ 92 | && make package \ 93 | && mkdir OUT \ 94 | && mv -v *.deb OUT/. 95 | 96 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 97 | FROM scratch 98 | COPY --from=builder /data/OUT/ / 99 | -------------------------------------------------------------------------------- /.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 CODENAME=bookworm 9 | ARG ARCH=arm64 10 | 11 | # Credentials 12 | ARG REPO_DOMAIN=freeswitch.signalwire.com 13 | ARG REPO_USERNAME=user 14 | 15 | ARG BUILD_NUMBER=42 16 | ARG GIT_SHA=0000000000 17 | 18 | ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg" 19 | 20 | ARG DATA_DIR=/data 21 | 22 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 23 | 24 | SHELL ["/bin/bash", "-c"] 25 | 26 | ENV DEBIAN_FRONTEND=noninteractive 27 | 28 | RUN apt-get -q update \ 29 | && apt-get -y -q install \ 30 | apt-transport-https \ 31 | autoconf \ 32 | automake \ 33 | build-essential \ 34 | ca-certificates \ 35 | cmake \ 36 | curl \ 37 | debhelper \ 38 | devscripts \ 39 | dh-autoreconf \ 40 | dos2unix \ 41 | doxygen \ 42 | dpkg-dev \ 43 | git \ 44 | gnupg2 \ 45 | graphviz \ 46 | libglib2.0-dev \ 47 | libssl-dev \ 48 | lsb-release \ 49 | pkg-config \ 50 | unzip \ 51 | wget 52 | 53 | RUN update-ca-certificates --fresh 54 | 55 | RUN echo "export CODENAME=${CODENAME}" | tee ~/.env \ 56 | && echo "export ARCH=${ARCH}" | tee -a ~/.env \ 57 | && chmod +x ~/.env 58 | 59 | RUN . ~/.env && cat < /etc/apt/sources.list.d/freeswitch.list 60 | deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${CODENAME} main 61 | deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${CODENAME} main 62 | EOF 63 | 64 | RUN git config --global --add safe.directory '*' \ 65 | && git config --global user.name "${MAINTAINER_NAME}" \ 66 | && git config --global user.email "${MAINTAINER_EMAIL}" 67 | 68 | RUN --mount=type=secret,id=REPO_PASSWORD,required=true \ 69 | printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \ 70 | printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \ 71 | printf "password " >> /etc/apt/auth.conf && \ 72 | cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \ 73 | sha512sum /run/secrets/REPO_PASSWORD && \ 74 | curl \ 75 | --fail \ 76 | --netrc-file /etc/apt/auth.conf \ 77 | --output ${GPG_KEY} \ 78 | https://${REPO_DOMAIN}/repo/deb/debian-release/signalwire-freeswitch-repo.gpg && \ 79 | file ${GPG_KEY} && \ 80 | apt-get --quiet update && \ 81 | apt-get --yes --quiet install \ 82 | libks2 \ 83 | && rm -f /etc/apt/auth.conf 84 | 85 | # Bootstrap and Build 86 | COPY . ${DATA_DIR} 87 | WORKDIR ${DATA_DIR} 88 | 89 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 90 | -DCMAKE_BUILD_TYPE=Debug \ 91 | -DCMAKE_INSTALL_PREFIX="/usr" \ 92 | && make package \ 93 | && mkdir OUT \ 94 | && mv -v *.deb OUT/. 95 | 96 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 97 | FROM scratch 98 | COPY --from=builder /data/OUT/ / 99 | -------------------------------------------------------------------------------- /.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 CODENAME=bullseye 9 | ARG ARCH=amd64 10 | 11 | # Credentials 12 | ARG REPO_DOMAIN=freeswitch.signalwire.com 13 | ARG REPO_USERNAME=user 14 | 15 | ARG BUILD_NUMBER=42 16 | ARG GIT_SHA=0000000000 17 | 18 | ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg" 19 | 20 | ARG DATA_DIR=/data 21 | 22 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 23 | 24 | SHELL ["/bin/bash", "-c"] 25 | 26 | ENV DEBIAN_FRONTEND=noninteractive 27 | 28 | RUN apt-get -q update \ 29 | && apt-get -y -q install \ 30 | apt-transport-https \ 31 | autoconf \ 32 | automake \ 33 | build-essential \ 34 | ca-certificates \ 35 | cmake \ 36 | curl \ 37 | debhelper \ 38 | devscripts \ 39 | dh-autoreconf \ 40 | dos2unix \ 41 | doxygen \ 42 | dpkg-dev \ 43 | git \ 44 | gnupg2 \ 45 | graphviz \ 46 | libglib2.0-dev \ 47 | libssl-dev \ 48 | lsb-release \ 49 | pkg-config \ 50 | unzip \ 51 | wget 52 | 53 | RUN update-ca-certificates --fresh 54 | 55 | RUN echo "export CODENAME=${CODENAME}" | tee ~/.env \ 56 | && echo "export ARCH=${ARCH}" | tee -a ~/.env \ 57 | && chmod +x ~/.env 58 | 59 | RUN . ~/.env && cat < /etc/apt/sources.list.d/freeswitch.list 60 | deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${CODENAME} main 61 | deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${CODENAME} main 62 | EOF 63 | 64 | RUN git config --global --add safe.directory '*' \ 65 | && git config --global user.name "${MAINTAINER_NAME}" \ 66 | && git config --global user.email "${MAINTAINER_EMAIL}" 67 | 68 | RUN --mount=type=secret,id=REPO_PASSWORD,required=true \ 69 | printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \ 70 | printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \ 71 | printf "password " >> /etc/apt/auth.conf && \ 72 | cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \ 73 | sha512sum /run/secrets/REPO_PASSWORD && \ 74 | curl \ 75 | --fail \ 76 | --netrc-file /etc/apt/auth.conf \ 77 | --output ${GPG_KEY} \ 78 | https://${REPO_DOMAIN}/repo/deb/debian-release/signalwire-freeswitch-repo.gpg && \ 79 | file ${GPG_KEY} && \ 80 | apt-get --quiet update && \ 81 | apt-get --yes --quiet install \ 82 | libks2 \ 83 | && rm -f /etc/apt/auth.conf 84 | 85 | # Bootstrap and Build 86 | COPY . ${DATA_DIR} 87 | WORKDIR ${DATA_DIR} 88 | 89 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 90 | -DCMAKE_BUILD_TYPE=Debug \ 91 | -DCMAKE_INSTALL_PREFIX="/usr" \ 92 | && make package \ 93 | && mkdir OUT \ 94 | && mv -v *.deb OUT/. 95 | 96 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 97 | FROM scratch 98 | COPY --from=builder /data/OUT/ / 99 | -------------------------------------------------------------------------------- /.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 CODENAME=bullseye 9 | ARG ARCH=arm32 10 | 11 | # Credentials 12 | ARG REPO_DOMAIN=freeswitch.signalwire.com 13 | ARG REPO_USERNAME=user 14 | 15 | ARG BUILD_NUMBER=42 16 | ARG GIT_SHA=0000000000 17 | 18 | ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg" 19 | 20 | ARG DATA_DIR=/data 21 | 22 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 23 | 24 | SHELL ["/bin/bash", "-c"] 25 | 26 | ENV DEBIAN_FRONTEND=noninteractive 27 | 28 | RUN apt-get -q update \ 29 | && apt-get -y -q install \ 30 | apt-transport-https \ 31 | autoconf \ 32 | automake \ 33 | build-essential \ 34 | ca-certificates \ 35 | cmake \ 36 | curl \ 37 | debhelper \ 38 | devscripts \ 39 | dh-autoreconf \ 40 | dos2unix \ 41 | doxygen \ 42 | dpkg-dev \ 43 | git \ 44 | gnupg2 \ 45 | graphviz \ 46 | libglib2.0-dev \ 47 | libssl-dev \ 48 | lsb-release \ 49 | pkg-config \ 50 | unzip \ 51 | wget 52 | 53 | RUN update-ca-certificates --fresh 54 | 55 | RUN echo "export CODENAME=${CODENAME}" | tee ~/.env \ 56 | && echo "export ARCH=${ARCH}" | tee -a ~/.env \ 57 | && chmod +x ~/.env 58 | 59 | RUN . ~/.env && cat < /etc/apt/sources.list.d/freeswitch.list 60 | deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/rpi/debian-release ${CODENAME} main 61 | deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/rpi/debian-release ${CODENAME} main 62 | EOF 63 | 64 | RUN git config --global --add safe.directory '*' \ 65 | && git config --global user.name "${MAINTAINER_NAME}" \ 66 | && git config --global user.email "${MAINTAINER_EMAIL}" 67 | 68 | RUN --mount=type=secret,id=REPO_PASSWORD,required=true \ 69 | printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \ 70 | printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \ 71 | printf "password " >> /etc/apt/auth.conf && \ 72 | cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \ 73 | sha512sum /run/secrets/REPO_PASSWORD && \ 74 | curl \ 75 | --fail \ 76 | --netrc-file /etc/apt/auth.conf \ 77 | --output ${GPG_KEY} \ 78 | https://${REPO_DOMAIN}/repo/deb/rpi/debian-release/signalwire-freeswitch-repo.gpg && \ 79 | file ${GPG_KEY} && \ 80 | apt-get --quiet update && \ 81 | apt-get --yes --quiet install \ 82 | libks2 \ 83 | && rm -f /etc/apt/auth.conf 84 | 85 | # Bootstrap and Build 86 | COPY . ${DATA_DIR} 87 | WORKDIR ${DATA_DIR} 88 | 89 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 90 | -DCMAKE_BUILD_TYPE=Debug \ 91 | -DCMAKE_INSTALL_PREFIX="/usr" \ 92 | && make package \ 93 | && mkdir OUT \ 94 | && mv -v *.deb OUT/. 95 | 96 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 97 | FROM scratch 98 | COPY --from=builder /data/OUT/ / 99 | -------------------------------------------------------------------------------- /.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 CODENAME=bullseye 9 | ARG ARCH=arm64 10 | 11 | # Credentials 12 | ARG REPO_DOMAIN=freeswitch.signalwire.com 13 | ARG REPO_USERNAME=user 14 | 15 | ARG BUILD_NUMBER=42 16 | ARG GIT_SHA=0000000000 17 | 18 | ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg" 19 | 20 | ARG DATA_DIR=/data 21 | 22 | LABEL maintainer="${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>" 23 | 24 | SHELL ["/bin/bash", "-c"] 25 | 26 | ENV DEBIAN_FRONTEND=noninteractive 27 | 28 | RUN apt-get -q update \ 29 | && apt-get -y -q install \ 30 | apt-transport-https \ 31 | autoconf \ 32 | automake \ 33 | build-essential \ 34 | ca-certificates \ 35 | cmake \ 36 | curl \ 37 | debhelper \ 38 | devscripts \ 39 | dh-autoreconf \ 40 | dos2unix \ 41 | doxygen \ 42 | dpkg-dev \ 43 | git \ 44 | gnupg2 \ 45 | graphviz \ 46 | libglib2.0-dev \ 47 | libssl-dev \ 48 | lsb-release \ 49 | pkg-config \ 50 | unzip \ 51 | wget 52 | 53 | RUN update-ca-certificates --fresh 54 | 55 | RUN echo "export CODENAME=${CODENAME}" | tee ~/.env \ 56 | && echo "export ARCH=${ARCH}" | tee -a ~/.env \ 57 | && chmod +x ~/.env 58 | 59 | RUN . ~/.env && cat < /etc/apt/sources.list.d/freeswitch.list 60 | deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${CODENAME} main 61 | deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${CODENAME} main 62 | EOF 63 | 64 | RUN git config --global --add safe.directory '*' \ 65 | && git config --global user.name "${MAINTAINER_NAME}" \ 66 | && git config --global user.email "${MAINTAINER_EMAIL}" 67 | 68 | RUN --mount=type=secret,id=REPO_PASSWORD,required=true \ 69 | printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \ 70 | printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \ 71 | printf "password " >> /etc/apt/auth.conf && \ 72 | cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \ 73 | sha512sum /run/secrets/REPO_PASSWORD && \ 74 | curl \ 75 | --fail \ 76 | --netrc-file /etc/apt/auth.conf \ 77 | --output ${GPG_KEY} \ 78 | https://${REPO_DOMAIN}/repo/deb/debian-release/signalwire-freeswitch-repo.gpg && \ 79 | file ${GPG_KEY} && \ 80 | apt-get --quiet update && \ 81 | apt-get --yes --quiet install \ 82 | libks2 \ 83 | && rm -f /etc/apt/auth.conf 84 | 85 | # Bootstrap and Build 86 | COPY . ${DATA_DIR} 87 | WORKDIR ${DATA_DIR} 88 | 89 | RUN PACKAGE_RELEASE="${BUILD_NUMBER}.${GIT_SHA}" cmake . \ 90 | -DCMAKE_BUILD_TYPE=Debug \ 91 | -DCMAKE_INSTALL_PREFIX="/usr" \ 92 | && make package \ 93 | && mkdir OUT \ 94 | && mv -v *.deb OUT/. 95 | 96 | # Artifacts image (mandatory part, the resulting image must have a single filesystem layer) 97 | FROM scratch 98 | COPY --from=builder /data/OUT/ / 99 | -------------------------------------------------------------------------------- /.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/signalwire-c/public/unstable/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }} 45 | PLATFORM: ${{ matrix.platform.name }} 46 | REPO_DOMAIN: freeswitch.signalwire.com 47 | TARGET_ARTIFACT_NAME: ${{ matrix.os }}-${{ matrix.version }}-${{ matrix.platform.name }}-public-unstable-artifact 48 | UPLOAD_BUILD_ARTIFACTS: ${{ github.event_name != 'pull_request' }} 49 | secrets: 50 | GH_BOT_DEPLOY_TOKEN: ${{ secrets.PAT }} 51 | HOSTNAME: ${{ secrets.HOSTNAME }} 52 | PROXY_URL: ${{ secrets.PROXY_URL }} 53 | USERNAME: ${{ secrets.USERNAME }} 54 | TELEPORT_TOKEN: ${{ secrets.TELEPORT_TOKEN }} 55 | REPO_USERNAME: 'signalwire' 56 | REPO_PASSWORD: ${{ secrets.REPOTOKEN }} 57 | 58 | deb-mirror: 59 | name: 'DEB-MIRROR' 60 | if: ${{ github.event_name != 'pull_request' }} 61 | needs: 62 | - deb 63 | runs-on: ubuntu-latest 64 | permissions: 65 | id-token: write 66 | contents: read 67 | strategy: 68 | # max-parallel: 1 69 | fail-fast: false 70 | matrix: 71 | os: 72 | - debian 73 | version: 74 | - bookworm 75 | - bullseye 76 | platform: 77 | - name: amd64 78 | runner: ubuntu-latest 79 | - name: arm32v7 80 | runner: ubuntu-24.04-arm 81 | - name: arm64v8 82 | runner: ubuntu-24.04-arm 83 | release: 84 | - release 85 | - unstable 86 | steps: 87 | - name: Checkout reusable actions 88 | uses: actions/checkout@v4 89 | with: 90 | repository: signalwire/actions-template 91 | ref: main 92 | fetch-depth: 1 93 | path: actions 94 | sparse-checkout: | 95 | .github/actions/teleport-local-copy/action.yml 96 | sparse-checkout-cone-mode: false 97 | 98 | - name: Mirror artifacts on remote server behind Teleport (public) 99 | uses: ./actions/.github/actions/teleport-local-copy 100 | with: 101 | SRC: '/var/www/signalwire-c/public/unstable/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }}/${{ matrix.os }}-${{ matrix.version }}-${{ matrix.platform.name }}-public-unstable-artifact.tar.gz' 102 | DST: '/var/www/signalwire-c/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' 103 | env: 104 | HOSTNAME: ${{ secrets.HOSTNAME }} 105 | PROXY_URL: ${{ secrets.PROXY_URL }} 106 | TOKEN: ${{ secrets.TELEPORT_TOKEN }} 107 | USERNAME: ${{ secrets.USERNAME }} 108 | 109 | - name: Mirror artifacts on remote server behind Teleport (fsa) 110 | uses: ./actions/.github/actions/teleport-local-copy 111 | with: 112 | SRC: '/var/www/signalwire-c/public/unstable/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }}/${{ matrix.os }}-${{ matrix.version }}-${{ matrix.platform.name }}-public-unstable-artifact.tar.gz' 113 | DST: '/var/www/signalwire-c/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' 114 | env: 115 | HOSTNAME: ${{ secrets.HOSTNAME }} 116 | PROXY_URL: ${{ secrets.PROXY_URL }} 117 | TOKEN: ${{ secrets.TELEPORT_TOKEN }} 118 | USERNAME: ${{ secrets.USERNAME }} 119 | 120 | meta: 121 | name: 'Publish build data to meta-repo' 122 | if: ${{ github.event_name != 'pull_request' }} 123 | needs: 124 | - deb 125 | - deb-mirror 126 | permissions: 127 | id-token: write 128 | contents: read 129 | uses: signalwire/actions-template/.github/workflows/meta-repo-content.yml@main 130 | with: 131 | META_CONTENT: '/var/www/signalwire-c/{fsa,public}/{release,unstable}/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }}' 132 | META_REPO: signalwire/bamboo_gha_trigger 133 | META_REPO_BRANCH: trigger/signalwire-c/${{ github.ref_name }} 134 | secrets: 135 | GH_BOT_DEPLOY_TOKEN: ${{ secrets.PAT }} 136 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | types: [synchronize, opened] 6 | branches: 7 | - "master" 8 | push: 9 | branches: 10 | - "master" 11 | 12 | jobs: 13 | scan_build: 14 | runs-on: ubuntu-latest 15 | container: 16 | image: debian:buster 17 | steps: 18 | - name: install deps 19 | run: | 20 | apt-get update && apt-get install -yq build-essential autotools-dev lsb-release pkg-config automake autoconf libtool-bin clang-tools-7 21 | apt-get install -yq cmake uuid-dev libssl-dev 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | - run: pwd 25 | - name: clone libks 26 | uses: actions/checkout@v4 27 | with: 28 | repository: signalwire/libks 29 | ref: v2.0 30 | path: /__w/signalwire-c/signalwire-c/libks 31 | - name: build libks 32 | run: cd /__w/signalwire-c/signalwire-c/libks && cmake . -DCMAKE_BUILD_TYPE=Release && make && make install && cd .. 33 | - id: scan_build 34 | run: /__w/signalwire-c/signalwire-c/scan_build.sh 35 | - name: Tar logs 36 | id: tar 37 | if: failure() 38 | env: 39 | COMPILATION_FAILED: ${{ steps.scan_build.outputs.COMPILATION_FAILED }} 40 | BUGS_FOUND: ${{ steps.scan_build.outputs.BUGS_FOUND }} 41 | run: | 42 | cd /__w/signalwire-c/signalwire-c 43 | ls -l 44 | if [ "true" -eq $COMPILATION_FAILED ]; then 45 | tar czvf scan-build-result.tar.gz ./scan-build-result.txt; 46 | echo "ARTIFACT_PATH=scan-build-result.tar.gz" >> $GITHUB_OUTPUT; 47 | echo "ARTIFACT=scan-build-result" >> $GITHUB_OUTPUT; 48 | fi 49 | if [ "true" -eq $BUGS_FOUND ]; then 50 | tar czvf reports.tar.gz $REPORT; 51 | echo "ARTIFACT_PATH=reports.tar.gz" >> $GITHUB_OUTPUT; 52 | echo "ARTIFACT=reports" >> $GITHUB_OUTPUT; 53 | fi 54 | - name: Upload artifacts 55 | if: failure() 56 | uses: actions/upload-artifact@v4 57 | with: 58 | name: ${{ steps.tar.outputs.ARTIFACT }}-${{ github.sha }}-${{ github.run_id }} 59 | path: ${{ steps.tar.outputs.ARTIFACT_PATH }} 60 | retention-days: 5 61 | - name: comment on PR 62 | if: ${{ failure() && github.event_name == 'pull_request' }} 63 | uses: thollander/actions-comment-pull-request@v3 64 | with: 65 | message: | 66 | scan_build _*failed*_. 67 | Please checkout the results. 68 | Action Run: [${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) 69 | pr_number: 123 # This will comment on pull request #123 70 | - name: notify slack 71 | if: ${{ failure() && github.event_name == 'push' }} 72 | uses: signalwire/actions-template/.github/actions/slack@main 73 | with: 74 | CHANNEL: ${{ secrets.SLACK_CHANNEL_ID }} 75 | 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. 76 | env: 77 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 78 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: MacOS 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 signalwire-c MacOS 17 | runs-on: macos-latest 18 | 19 | steps: 20 | - name: Checkout code 21 | uses: actions/checkout@v4 22 | with: 23 | fetch-depth: 0 24 | 25 | - name: Install dependencies 26 | run: | 27 | brew update 28 | brew install ossp-uuid signalwire/homebrew-signalwire/libks2 29 | brew reinstall openssl@3 30 | 31 | - name: Configure with CMake 32 | run: | 33 | cmake . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install 34 | 35 | - name: Build 36 | run: | 37 | make 38 | 39 | - name: Install to local folder 40 | run: | 41 | make install 42 | 43 | # - name: Debug - List all files 44 | # run: | 45 | # find . -type f | sort 46 | 47 | - name: Upload build artifacts 48 | uses: actions/upload-artifact@v4 49 | if: always() 50 | with: 51 | name: signalwire-c-macos-build 52 | path: | 53 | install/ 54 | -------------------------------------------------------------------------------- /.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 signalwire-c 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: signalwire-c-windows-builds 55 | path: win/out/*.zip 56 | if-no-files-found: error 57 | retention-days: 7 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeCache.txt 2 | CMakeFiles 3 | signalwire_client_C_cotire.cmake 4 | /Testing 5 | CTestTestfile.cmake 6 | Makefile 7 | *_cotire.cmake 8 | cmake_install.cmake 9 | libsignalwire_client2.so* 10 | testclient 11 | /cotire 12 | /build 13 | Testing/ 14 | core 15 | swclt_test/cotire/ 16 | swclt_test/swclt_test 17 | /install_manifest.txt 18 | /libsignalwire_client.dylib 19 | /signalwire_client2.pc 20 | /uninstall.cmake 21 | build-Win32/ 22 | build-x64/ 23 | CPackConfig.cmake 24 | CPackSourceConfig.cmake 25 | changelog.Debian.gz 26 | libsignalwire_client.so.1 27 | inc/signalwire-client-c/version.h 28 | _CPack_Packages/ 29 | install_manifest_runtime.txt 30 | *.deb -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/libbacktrace"] 2 | path = deps/libbacktrace 3 | url = https://github.com/ianlancetaylor/libbacktrace 4 | -------------------------------------------------------------------------------- /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 build release package with build number 42: 27 | PACKAGE_RELEASE="42" cmake . -DCMAKE_BUILD_TYPE=Release && make package 28 | 29 | To buld CMAKE from source 30 | wget https://cmake.org/files/v3.7/cmake-3.7.2.tar.gz 31 | tar -zxvf cmake-3.7.2.tar.gz 32 | cd cmake-3.7.2 33 | ./bootstrap --prefix=/usr/local 34 | make 35 | make install 36 | /usr/local/bin/cmake --version 37 | 38 | Centos dependencies: 39 | - yum groupinstall "Development Tools" 40 | - yum install libuuid-devel libatomic openssl-devel 41 | -------------------------------------------------------------------------------- /cmake/FindLibKS.cmake: -------------------------------------------------------------------------------- 1 | # LIBKS_FOUND 2 | # LIBKS_LIBRARIES 3 | # LIBKS_LIBRARY_DIRS 4 | # LIBKS_LDFLAGS 5 | # LIBKS_INCLUDE_DIRS 6 | # LIBKS_CFLAGS 7 | # LIBKS_CMAKE_DIR 8 | 9 | if (NOT TARGET ks) 10 | if (NOT WIN32) 11 | include(FindPkgConfig) 12 | 13 | # Use the pkg-config system to locate our libks configs 14 | pkg_check_modules(LIBKS libks2 REQUIRED) 15 | 16 | # From here we can bootstrap into cmake stuff 17 | set(LIBKS_CMAKE_DIR ${LIBKS_INCLUDE_DIRS}/libks/cmake) 18 | else() 19 | if ("${LIBKS_INCLUDE_DIRS}" STREQUAL "") 20 | message(FATAL_ERROR "Can't find Libks. Try setting LIBKS_INCLUDE_DIRS.") 21 | endif() 22 | 23 | # From here we can bootstrap into cmake stuff 24 | set(LIBKS_CMAKE_DIR ${LIBKS_INCLUDE_DIRS}/cmake) 25 | endif() 26 | 27 | # Load ks utils for our build macros 28 | include(${LIBKS_CMAKE_DIR}/ksutil.cmake) 29 | 30 | # Now load the package with a hint on where to look 31 | set(LibKS2_DIR ${LIBKS_CMAKE_DIR}) 32 | 33 | if (NOT WIN32) 34 | find_package(LibKS2 REQUIRED VERSION) 35 | else() 36 | if(LIBKS_INCLUDE_DIRS AND EXISTS "${LIBKS_INCLUDE_DIRS}/CMakeLists.txt") 37 | file(STRINGS "${LIBKS_INCLUDE_DIRS}/CMakeLists.txt" libks_version_str 38 | REGEX "^[\t ]*project[\t (]*LibKS2[\t ]+VERSION[\t ]+([0-9a-fA-F]\.[0-9a-fA-F]).*") 39 | 40 | string(COMPARE EQUAL "${libks_version_str}" "" _is_empty) 41 | if(_is_empty) 42 | message( 43 | FATAL_ERROR 44 | "Incorrect LibKS VERSION in project command of LibKS's CMakeLists.txt" 45 | ": ${LIBKS_INCLUDE_DIRS}/CMakeLists.txt") 46 | endif() 47 | string(REGEX REPLACE "^[\t ]*project[\t (]*LibKS2[\t ]+VERSION[\t ]+([0-9a-fA-F]\.[0-9a-fA-F]).*$" 48 | "\\1;" LIBKS_VERSION_LIST "${libks_version_str}") 49 | list(GET LIBKS_VERSION_LIST 0 LIBKS_VERSION) 50 | endif() 51 | endif() 52 | 53 | message("Found LibKS2 ${LIBKS_VERSION} package at path ${LIBKS_INCLUDE_DIRS}") 54 | if (${LIBKS_VERSION} VERSION_LESS 2.0) 55 | message(FATAL "Libks version 2.0 or greater is required") 56 | endif() 57 | else() 58 | get_target_property(KS_SOURCE_DIR ks2 SOURCE_DIR) 59 | message("Switchblade ${KS_SOURCE_DIR}") 60 | set(LIBKS_CMAKE_DIR ${KS_SOURCE_DIR}/cmake) 61 | 62 | # Load ks utils for our build macros 63 | include(${LIBKS_CMAKE_DIR}/ksutil.cmake) 64 | endif() 65 | 66 | # Let ks define some fundamentals across all cmake setups 67 | ksutil_setup_platform() 68 | 69 | # We'll need to load openssl as well 70 | if (KS_PLAT_MAC) 71 | set(OPENSSL_ROOT_DIR /usr/local/opt/openssl) 72 | endif() 73 | 74 | if (WIN32) 75 | include(FindOpenSSL) 76 | endif() 77 | 78 | find_package(OpenSSL REQUIRED Crypto SSL) 79 | -------------------------------------------------------------------------------- /copyright: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 SignalWire, Inc 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/client/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /examples/client/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7.2) 2 | 3 | # Right now we can setup the example 4 | add_executable(test main.c) 5 | target_link_libraries(test signalwire_client2) 6 | -------------------------------------------------------------------------------- /examples/client/README: -------------------------------------------------------------------------------- 1 | To build: 2 | cmake . 3 | make 4 | -------------------------------------------------------------------------------- /examples/client/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 "signalwire-client-c/client.h" 24 | 25 | int main(int argc, char **argv) 26 | { 27 | swclt_init(KS_LOG_LEVEL_DEBUG); 28 | swclt_shutdown(); 29 | } 30 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/authenticate.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalwire/signalwire-c/52bc927e819ba6cb332b9c67dabbea1fd0d20610/inc/signalwire-client-c/blade/authenticate.h -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/authority.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalwire/signalwire-c/52bc927e819ba6cb332b9c67dabbea1fd0d20610/inc/signalwire-client-c/blade/authority.h -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/blade.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | #define SWCLT_BLADE_VERSION_MAJOR 2 25 | #define SWCLT_BLADE_VERSION_MINOR 4 26 | #define SWCLT_BLADE_VERSION_REVISION 1 27 | 28 | /* Define the default time to live amount for all blade commands */ 29 | #define BLADE_DEFAULT_CMD_TTL_MS 10000 30 | 31 | #include "signalwire-client-c/blade/type.h" 32 | #include "signalwire-client-c/blade/connect.h" 33 | #include "signalwire-client-c/blade/disconnect.h" 34 | #include "signalwire-client-c/blade/authenticate.h" 35 | #include "signalwire-client-c/blade/authority.h" 36 | #include "signalwire-client-c/blade/broadcast.h" 37 | #include "signalwire-client-c/blade/execute.h" 38 | #include "signalwire-client-c/blade/identity.h" 39 | #include "signalwire-client-c/blade/ping.h" 40 | #include "signalwire-client-c/blade/protocol.h" 41 | #include "signalwire-client-c/blade/register.h" 42 | #include "signalwire-client-c/blade/subscription.h" 43 | #include "signalwire-client-c/blade/netcast.h" 44 | #include "signalwire-client-c/blade/util.h" 45 | 46 | /* For Emacs: 47 | * Local Variables: 48 | * mode:c 49 | * indent-tabs-mode:t 50 | * tab-width:4 51 | * c-basic-offset:4 52 | * End: 53 | * For VIM: 54 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 55 | */ 56 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/broadcast.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | /* The method name for a broadcast request */ 25 | #define BLADE_BROADCAST_METHOD "blade.broadcast" 26 | 27 | /* Flags for the command, in our case we don't get replies */ 28 | #define BLADE_BROADCAST_FLAGS SWCLT_CMD_FLAG_NOREPLY 29 | 30 | /* Default time to live for broadcast */ 31 | #define BLADE_BROADCAST_TTL_MS BLADE_DEFAULT_CMD_TTL_MS 32 | 33 | /* Create our broadcast request template */ 34 | typedef struct blade_broadcast_rqu_s { 35 | const char *protocol; 36 | const char *channel; 37 | const char *event; 38 | const char *broadcaster_nodeid; 39 | ks_json_t *params; 40 | } blade_broadcast_rqu_t; 41 | 42 | SWCLT_JSON_MARSHAL_BEG(BLADE_BROADCAST_RQU, blade_broadcast_rqu_t) 43 | SWCLT_JSON_MARSHAL_STRING(protocol) 44 | SWCLT_JSON_MARSHAL_STRING(channel) 45 | SWCLT_JSON_MARSHAL_STRING(event) 46 | SWCLT_JSON_MARSHAL_STRING(broadcaster_nodeid) 47 | SWCLT_JSON_MARSHAL_ITEM(params) 48 | SWCLT_JSON_MARSHAL_END() 49 | 50 | SWCLT_JSON_DESTROY_BEG(BLADE_BROADCAST_RQU, blade_broadcast_rqu_t) 51 | SWCLT_JSON_DESTROY_STRING(protocol) 52 | SWCLT_JSON_DESTROY_STRING(channel) 53 | SWCLT_JSON_DESTROY_STRING(event) 54 | SWCLT_JSON_DESTROY_STRING(broadcaster_nodeid) 55 | SWCLT_JSON_DESTROY_ITEM(params) 56 | SWCLT_JSON_DESTROY_END() 57 | 58 | SWCLT_JSON_PARSE_BEG(BLADE_BROADCAST_RQU, blade_broadcast_rqu_t) 59 | SWCLT_JSON_PARSE_STRING(protocol) 60 | SWCLT_JSON_PARSE_STRING(channel) 61 | SWCLT_JSON_PARSE_STRING(event) 62 | SWCLT_JSON_PARSE_STRING(broadcaster_nodeid) 63 | SWCLT_JSON_PARSE_ITEM(params) 64 | SWCLT_JSON_PARSE_END() 65 | 66 | /** 67 | * CREATE_BLADE_BROADCAST_CMD_ASYNC - Creates a command with a request 68 | * in it setup to submit a broadcast method to blade. 69 | */ 70 | static inline swclt_cmd_t *CREATE_BLADE_BROADCAST_CMD_ASYNC( 71 | swclt_cmd_cb_t cb, 72 | void *cb_data, 73 | const char *protocol, 74 | const char *channel, 75 | const char *event, 76 | const char *broadcast_nodeid, 77 | ks_json_t **params) 78 | { 79 | ks_json_t *obj = NULL; 80 | blade_broadcast_rqu_t broadcast_rqu; 81 | swclt_cmd_t *cmd = NULL; 82 | 83 | /* Fill in the broadcast request then marshal it, it will create copies 84 | * of all the fields so caller doesn't lose ownership here */ 85 | broadcast_rqu.protocol = protocol; 86 | broadcast_rqu.channel = channel; 87 | broadcast_rqu.event = event; 88 | broadcast_rqu.broadcaster_nodeid = broadcast_nodeid; 89 | broadcast_rqu.params = (!params || !*params) ? ks_json_create_object() : *params; 90 | 91 | if (!(obj = BLADE_BROADCAST_RQU_MARSHAL(&broadcast_rqu))) { 92 | 93 | /* Since params is last, on error here we can be sure params was 94 | * not freed so do not set the callers params to NULL */ 95 | return cmd; 96 | } 97 | 98 | /* We now own the callers params, null it to indicate ownership transfer */ 99 | if (params) 100 | *params = NULL; 101 | 102 | /* Now give it to the new command */ 103 | if (swclt_cmd_create_ex( 104 | &cmd, 105 | cb, 106 | cb_data, 107 | BLADE_BROADCAST_METHOD, 108 | &obj, 109 | BLADE_BROADCAST_TTL_MS, 110 | BLADE_BROADCAST_FLAGS, 111 | ks_uuid_null())) 112 | goto done; 113 | 114 | done: 115 | ks_json_delete(&obj); 116 | return cmd; 117 | } 118 | 119 | static inline swclt_cmd_t *CREATE_BLADE_BROADCAST_CMD( 120 | const char *protocol, 121 | const char *channel, 122 | const char *event, 123 | const char *broadcast_nodeid, 124 | ks_json_t **params) 125 | { 126 | return CREATE_BLADE_BROADCAST_CMD_ASYNC( 127 | NULL, 128 | NULL, 129 | protocol, 130 | channel, 131 | event, 132 | broadcast_nodeid, 133 | params); 134 | } 135 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/connect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | /* The method name for a connect request */ 26 | #define BLADE_CONNECT_METHOD "blade.connect" 27 | 28 | /* Flags for the command */ 29 | #define BLADE_CONNECT_FLAGS 0 30 | 31 | /* Default time to live for connect */ 32 | #define BLADE_CONNECT_TTL_MS BLADE_DEFAULT_CMD_TTL_MS 33 | 34 | /* Setup the target blade version we will support */ 35 | #define BLADE_VERSION_MAJOR 2 36 | #define BLADE_VERSION_MINOR 0 37 | #define BLADE_VERSION_REVISION 0 38 | 39 | /* Define our request structure */ 40 | typedef struct blade_connect_rqu_s { 41 | blade_version_t *version; 42 | ks_uuid_t sessionid; 43 | ks_json_t *authentication; 44 | const char *agent; 45 | const char *identity; 46 | ks_json_t *network; 47 | } blade_connect_rqu_t; 48 | 49 | SWCLT_JSON_MARSHAL_BEG(BLADE_CONNECT_RQU, blade_connect_rqu_t) 50 | SWCLT_JSON_MARSHAL_CUSTOM(BLADE_VERSION, version) 51 | SWCLT_JSON_MARSHAL_UUID(sessionid) 52 | SWCLT_JSON_MARSHAL_ITEM_OPT(authentication) 53 | SWCLT_JSON_MARSHAL_STRING_OPT(agent) 54 | SWCLT_JSON_MARSHAL_STRING_OPT(identity) 55 | SWCLT_JSON_MARSHAL_ITEM_OPT(network) 56 | SWCLT_JSON_MARSHAL_END() 57 | 58 | SWCLT_JSON_DESTROY_BEG(BLADE_CONNECT_RQU, blade_connect_rqu_t) 59 | SWCLT_JSON_DESTROY_CUSTOM(BLADE_VERSION, version) 60 | SWCLT_JSON_DESTROY_UUID(sessionid) 61 | SWCLT_JSON_DESTROY_STRING(agent) 62 | SWCLT_JSON_DESTROY_STRING(identity) 63 | SWCLT_JSON_DESTROY_ITEM(network) 64 | SWCLT_JSON_DESTROY_END() 65 | 66 | SWCLT_JSON_ALLOC_BEG(BLADE_CONNECT_RQU, blade_connect_rqu_t) 67 | SWCLT_JSON_ALLOC_CUSTOM(BLADE_VERSION, version) 68 | SWCLT_JSON_ALLOC_END() 69 | 70 | SWCLT_JSON_PARSE_BEG(BLADE_CONNECT_RQU, blade_connect_rqu_t) 71 | SWCLT_JSON_PARSE_CUSTOM(BLADE_VERSION, version) 72 | SWCLT_JSON_PARSE_UUID(sessionid) 73 | SWCLT_JSON_PARSE_ITEM_OPT(authentication) 74 | SWCLT_JSON_PARSE_STRING_OPT(agent) 75 | SWCLT_JSON_PARSE_STRING_OPT(identity) 76 | SWCLT_JSON_PARSE_ITEM_OPT(network) 77 | SWCLT_JSON_PARSE_END() 78 | 79 | /* Define our reply structure */ 80 | typedef struct blade_connect_rpl_s { 81 | ks_bool_t session_restored; 82 | ks_uuid_t sessionid; 83 | const char *nodeid; 84 | const char *master_nodeid; 85 | ks_json_t *authorization; 86 | ks_json_t *routes; 87 | ks_json_t *protocols; 88 | ks_json_t *subscriptions; 89 | ks_json_t *authorities; 90 | ks_json_t *protocols_uncertified; 91 | } blade_connect_rpl_t; 92 | 93 | SWCLT_JSON_MARSHAL_BEG(BLADE_CONNECT_RPL, blade_connect_rpl_t) 94 | SWCLT_JSON_MARSHAL_BOOL(session_restored) 95 | SWCLT_JSON_MARSHAL_UUID(sessionid) 96 | SWCLT_JSON_MARSHAL_STRING(nodeid) 97 | SWCLT_JSON_MARSHAL_STRING(master_nodeid) 98 | SWCLT_JSON_MARSHAL_ITEM_OPT(authorization) 99 | SWCLT_JSON_MARSHAL_ITEM_OPT(routes) 100 | SWCLT_JSON_MARSHAL_ITEM_OPT(protocols) 101 | SWCLT_JSON_MARSHAL_ITEM_OPT(subscriptions) 102 | SWCLT_JSON_MARSHAL_ITEM_OPT(authorities) 103 | SWCLT_JSON_MARSHAL_ITEM_OPT(protocols_uncertified) 104 | SWCLT_JSON_MARSHAL_END() 105 | 106 | SWCLT_JSON_DESTROY_BEG(BLADE_CONNECT_RPL, blade_connect_rpl_t) 107 | SWCLT_JSON_DESTROY_BOOL(session_restored) 108 | SWCLT_JSON_DESTROY_UUID(sessionid) 109 | SWCLT_JSON_DESTROY_STRING(nodeid) 110 | SWCLT_JSON_DESTROY_STRING(master_nodeid) 111 | SWCLT_JSON_DESTROY_ITEM(authorization) 112 | SWCLT_JSON_DESTROY_ITEM(routes) 113 | SWCLT_JSON_DESTROY_ITEM(protocols) 114 | SWCLT_JSON_DESTROY_ITEM(subscriptions) 115 | SWCLT_JSON_DESTROY_ITEM(authorities) 116 | SWCLT_JSON_DESTROY_ITEM(protocols_uncertified) 117 | SWCLT_JSON_DESTROY_END() 118 | 119 | SWCLT_JSON_PARSE_BEG(BLADE_CONNECT_RPL, blade_connect_rpl_t) 120 | SWCLT_JSON_PARSE_BOOL(session_restored) 121 | SWCLT_JSON_PARSE_UUID(sessionid) 122 | SWCLT_JSON_PARSE_STRING(nodeid) 123 | SWCLT_JSON_PARSE_STRING(master_nodeid) 124 | SWCLT_JSON_PARSE_ITEM_OPT(authorization) 125 | SWCLT_JSON_PARSE_ITEM_OPT(routes) 126 | SWCLT_JSON_PARSE_ITEM_OPT(protocols) 127 | SWCLT_JSON_PARSE_ITEM_OPT(subscriptions) 128 | SWCLT_JSON_PARSE_ITEM_OPT(authorities) 129 | SWCLT_JSON_PARSE_ITEM_OPT(protocols_uncertified) 130 | SWCLT_JSON_PARSE_END() 131 | 132 | /** 133 | * CREATE_BLADE_CONNECT_CMD_ASYNC - Creates a command which holds 134 | * and owns the request json for a connect request. 135 | */ 136 | static inline swclt_cmd_t *CREATE_BLADE_CONNECT_CMD_ASYNC( 137 | ks_pool_t *pool, 138 | ks_uuid_t previous_sessionid, 139 | ks_json_t **authentication, 140 | const char *agent, 141 | const char *identity, 142 | ks_json_t *network, 143 | swclt_cmd_cb_t cb, 144 | void *cb_data) 145 | { 146 | blade_connect_rqu_t *connect_rqu = NULL; 147 | swclt_cmd_t *cmd = NULL; 148 | ks_json_t *obj = NULL; 149 | 150 | if (BLADE_CONNECT_RQU_ALLOC(pool, &connect_rqu)) 151 | goto done; 152 | 153 | connect_rqu->sessionid = previous_sessionid; 154 | connect_rqu->agent = agent; 155 | connect_rqu->identity = identity; 156 | connect_rqu->network = ks_json_duplicate(network, KS_TRUE); 157 | if (authentication && *authentication) { 158 | connect_rqu->authentication = *authentication; 159 | *authentication = NULL; 160 | } 161 | 162 | if (!(obj = BLADE_CONNECT_RQU_MARSHAL(connect_rqu))) 163 | goto done; 164 | 165 | if (swclt_cmd_create_ex( 166 | &cmd, 167 | cb, 168 | cb_data, 169 | BLADE_CONNECT_METHOD, 170 | &obj, 171 | BLADE_CONNECT_TTL_MS, 172 | BLADE_CONNECT_FLAGS, 173 | ks_uuid_null())) 174 | goto done; 175 | 176 | done: 177 | // These are not owned by the request, don't destroy them 178 | if (connect_rqu) { 179 | connect_rqu->agent = NULL; 180 | connect_rqu->identity = NULL; 181 | 182 | BLADE_CONNECT_RQU_DESTROY(&connect_rqu); 183 | } 184 | 185 | ks_json_delete(&obj); 186 | 187 | return cmd; 188 | } 189 | 190 | static inline swclt_cmd_t *CREATE_BLADE_CONNECT_CMD(ks_pool_t *pool, 191 | ks_uuid_t previous_sessionid, 192 | ks_json_t **authentication, 193 | const char *agent, 194 | const char *identity, 195 | ks_json_t *network) 196 | { 197 | return CREATE_BLADE_CONNECT_CMD_ASYNC(pool, previous_sessionid, authentication, agent, identity, network, NULL, NULL); 198 | } 199 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/disconnect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | /* The method name for a disconnect request */ 25 | #define BLADE_DISCONNECT_METHOD "blade.disconnect" 26 | 27 | /* Flags for the command, in our case we don't get replies */ 28 | #define BLADE_DISCONNECT_FLAGS SWCLT_CMD_FLAG_NOREPLY 29 | 30 | /* Default time to live for disconnect */ 31 | #define BLADE_DISCONNECT_TTL_MS BLADE_DEFAULT_CMD_TTL_MS 32 | 33 | /* Create our disconnect request template */ 34 | typedef struct blade_disconnect_rqu_s { 35 | int unused; 36 | } blade_disconnect_rqu_t; 37 | 38 | SWCLT_JSON_MARSHAL_BEG(BLADE_DISCONNECT_RQU, blade_disconnect_rqu_t) 39 | SWCLT_JSON_MARSHAL_END() 40 | 41 | SWCLT_JSON_DESTROY_BEG(BLADE_DISCONNECT_RQU, blade_disconnect_rqu_t) 42 | SWCLT_JSON_DESTROY_END() 43 | 44 | SWCLT_JSON_PARSE_BEG(BLADE_DISCONNECT_RQU, blade_disconnect_rqu_t) 45 | SWCLT_JSON_PARSE_END() 46 | 47 | /** 48 | * CREATE_BLADE_DISCONNECT_CMD_ASYNC - Creates a command with a request 49 | * in it setup to submit a disconnect method to blade. 50 | */ 51 | static inline swclt_cmd_t *CREATE_BLADE_DISCONNECT_CMD_ASYNC( 52 | swclt_cmd_cb_t cb, 53 | void *cb_data) 54 | { 55 | ks_json_t *obj = NULL; 56 | blade_disconnect_rqu_t disconnect_rqu; 57 | swclt_cmd_t *cmd = NULL; 58 | 59 | /* Fill in the disconnect request then marshal it, it will create copies 60 | * of all the fields so caller doesn't lose ownership here */ 61 | 62 | if (!(obj = BLADE_DISCONNECT_RQU_MARSHAL(&disconnect_rqu))) { 63 | 64 | /* Since params is last, on error here we can be sure params was 65 | * not freed so do not set the callers params to NULL */ 66 | return cmd; 67 | } 68 | 69 | /* Now give it to the new command */ 70 | if (swclt_cmd_create_ex( 71 | &cmd, 72 | cb, 73 | cb_data, 74 | BLADE_DISCONNECT_METHOD, 75 | &obj, 76 | BLADE_DISCONNECT_TTL_MS, 77 | BLADE_DISCONNECT_FLAGS, 78 | ks_uuid_null())) 79 | goto done; 80 | 81 | done: 82 | ks_json_delete(&obj); 83 | return cmd; 84 | } 85 | 86 | static inline swclt_cmd_t *CREATE_BLADE_DISCONNECT_CMD(void) 87 | { 88 | return CREATE_BLADE_DISCONNECT_CMD_ASYNC( 89 | NULL, 90 | NULL); 91 | } 92 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/execute.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-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 | 23 | #pragma once 24 | 25 | /* The method name for a protocol request */ 26 | #define BLADE_EXECUTE_METHOD "blade.execute" 27 | 28 | /* Flags for the command */ 29 | #define BLADE_EXECUTE_FLAGS 0 30 | 31 | /* Default time to live for protocol */ 32 | #define BLADE_EXECUTE_TTL_MS BLADE_DEFAULT_CMD_TTL_MS 33 | 34 | typedef struct blade_execute_m_rqu_s { 35 | const char *requester_nodeid; 36 | const char *responder_nodeid; 37 | const char *protocol; 38 | const char *method; 39 | ks_json_t **params; 40 | } blade_execute_m_rqu_t; 41 | 42 | typedef struct blade_execute_rqu_s { 43 | const char *requester_nodeid; 44 | const char *responder_nodeid; 45 | const char *protocol; 46 | const char *method; 47 | ks_json_t *params; 48 | } blade_execute_rqu_t; 49 | 50 | SWCLT_JSON_DESTROY_BEG(BLADE_EXECUTE_RQU, blade_execute_rqu_t) 51 | SWCLT_JSON_DESTROY_STRING(requester_nodeid) 52 | SWCLT_JSON_DESTROY_STRING(responder_nodeid) 53 | SWCLT_JSON_DESTROY_STRING(protocol) 54 | SWCLT_JSON_DESTROY_STRING(method) 55 | SWCLT_JSON_DESTROY_ITEM(params) 56 | SWCLT_JSON_DESTROY_END() 57 | 58 | SWCLT_JSON_PARSE_BEG(BLADE_EXECUTE_RQU, blade_execute_rqu_t) 59 | SWCLT_JSON_PARSE_STRING(requester_nodeid) 60 | SWCLT_JSON_PARSE_STRING(responder_nodeid) 61 | SWCLT_JSON_PARSE_STRING(protocol) 62 | SWCLT_JSON_PARSE_STRING(method) 63 | SWCLT_JSON_PARSE_ITEM(params) 64 | SWCLT_JSON_PARSE_END() 65 | 66 | typedef struct blade_execute_rpl_s { 67 | const char *requester_nodeid; 68 | const char *responder_nodeid; 69 | ks_json_t *result; 70 | } blade_execute_rpl_t; 71 | 72 | SWCLT_JSON_MARSHAL_BEG(BLADE_EXECUTE_RPL, blade_execute_rpl_t) 73 | SWCLT_JSON_MARSHAL_STRING(requester_nodeid) 74 | SWCLT_JSON_MARSHAL_STRING(responder_nodeid) 75 | SWCLT_JSON_MARSHAL_ITEM(result) 76 | SWCLT_JSON_MARSHAL_END() 77 | 78 | SWCLT_JSON_DESTROY_BEG(BLADE_EXECUTE_RPL, blade_execute_rpl_t) 79 | SWCLT_JSON_DESTROY_STRING(requester_nodeid) 80 | SWCLT_JSON_DESTROY_STRING(responder_nodeid) 81 | SWCLT_JSON_DESTROY_ITEM(result) 82 | SWCLT_JSON_DESTROY_END() 83 | 84 | SWCLT_JSON_PARSE_BEG(BLADE_EXECUTE_RPL, blade_execute_rpl_t) 85 | SWCLT_JSON_PARSE_STRING(requester_nodeid) 86 | SWCLT_JSON_PARSE_STRING(responder_nodeid) 87 | SWCLT_JSON_PARSE_ITEM(result) 88 | SWCLT_JSON_PARSE_END() 89 | 90 | typedef struct blade_execute_err_s { 91 | const char *requester_nodeid; 92 | const char *responder_nodeid; 93 | int code; 94 | const char *message; 95 | } blade_execute_err_t; 96 | 97 | SWCLT_JSON_MARSHAL_BEG(BLADE_EXECUTE_ERR, blade_execute_err_t) 98 | SWCLT_JSON_MARSHAL_STRING(requester_nodeid) 99 | SWCLT_JSON_MARSHAL_STRING(responder_nodeid) 100 | SWCLT_JSON_MARSHAL_INT(code) 101 | SWCLT_JSON_MARSHAL_STRING(message) 102 | SWCLT_JSON_MARSHAL_END() 103 | 104 | SWCLT_JSON_DESTROY_BEG(BLADE_EXECUTE_ERR, blade_execute_err_t) 105 | SWCLT_JSON_DESTROY_STRING(requester_nodeid) 106 | SWCLT_JSON_DESTROY_STRING(responder_nodeid) 107 | SWCLT_JSON_DESTROY_INT(code) 108 | SWCLT_JSON_DESTROY_STRING(message) 109 | SWCLT_JSON_DESTROY_END() 110 | 111 | SWCLT_JSON_PARSE_BEG(BLADE_EXECUTE_ERR, blade_execute_err_t) 112 | SWCLT_JSON_PARSE_STRING(requester_nodeid) 113 | SWCLT_JSON_PARSE_STRING(responder_nodeid) 114 | SWCLT_JSON_PARSE_INT(code) 115 | SWCLT_JSON_PARSE_STRING(message) 116 | SWCLT_JSON_PARSE_END() 117 | 118 | /** 119 | * CREATE_BLADE_EXECUTE_CMD_ASYNC - Creates a command which holds 120 | * and owns the request json for an execute request. 121 | */ 122 | static inline swclt_cmd_t *CREATE_BLADE_EXECUTE_CMD_ASYNC( 123 | swclt_cmd_cb_t cb, 124 | void *cb_data, 125 | const char *id, 126 | const char *responder, 127 | const char *protocol, 128 | const char *method, 129 | ks_json_t **params) 130 | { 131 | swclt_cmd_t *cmd = NULL; 132 | ks_status_t status; 133 | ks_json_t *request; 134 | ks_uuid_t msgid = ks_uuid_null(); 135 | 136 | if (id) msgid = ks_uuid_from_str(id); 137 | request = ks_json_create_object(); 138 | if (responder) ks_json_add_string_to_object(request, "responder_nodeid", responder); 139 | ks_json_add_string_to_object(request, "protocol", protocol); 140 | ks_json_add_string_to_object(request, "method", method); 141 | ks_json_add_item_to_object(request, "params", *params); 142 | 143 | /* Clear callers ptr */ 144 | *params = NULL; 145 | 146 | /* Now hand it to the command, it will take ownership of it if successful 147 | * and null out our ptr */ 148 | if ((status = swclt_cmd_create_ex( 149 | &cmd, 150 | cb, 151 | cb_data, 152 | BLADE_EXECUTE_METHOD, 153 | &request, 154 | BLADE_EXECUTE_TTL_MS, 155 | BLADE_EXECUTE_FLAGS, 156 | msgid))) { 157 | ks_log(KS_LOG_WARNING, "Failed to allocate execute cmd: %lu", status); 158 | 159 | /* Safe to free this or at least attempt to, cmd will have set it to null if it 160 | * took ownership of it */ 161 | ks_json_delete(&request); 162 | return NULL; 163 | } 164 | 165 | /* Phew, successfully allocated the command */ 166 | return cmd; 167 | } 168 | 169 | static inline swclt_cmd_t *CREATE_BLADE_EXECUTE_CMD( 170 | const char *id, 171 | const char *responder, 172 | const char *protocol, 173 | const char *method, 174 | ks_json_t **params) 175 | { 176 | return CREATE_BLADE_EXECUTE_CMD_ASYNC( 177 | NULL, 178 | NULL, 179 | id, 180 | responder, 181 | protocol, 182 | method, 183 | params); 184 | } 185 | 186 | 187 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/identity.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | /* The method name for an identity request */ 26 | #define BLADE_IDENTITY_METHOD "blade.identity" 27 | 28 | /* Flags for the command */ 29 | #define BLADE_IDENTITY_FLAGS 0 30 | 31 | /* Default time to live for identity */ 32 | #define BLADE_IDENTITY_TTL_MS BLADE_DEFAULT_CMD_TTL_MS 33 | 34 | #define BLADE_IDENTITY_CMD_ADD "add" 35 | #define BLADE_IDENTITY_CMD_REMOVE "remove" 36 | 37 | typedef struct blade_identity_rqu_s { 38 | const char *command; 39 | ks_json_t *identities; 40 | } blade_identity_rqu_t; 41 | 42 | SWCLT_JSON_MARSHAL_BEG(BLADE_IDENTITY_RQU, blade_identity_rqu_t) 43 | SWCLT_JSON_MARSHAL_STRING(command) 44 | SWCLT_JSON_MARSHAL_ITEM(identities) 45 | SWCLT_JSON_MARSHAL_END() 46 | 47 | SWCLT_JSON_DESTROY_BEG(BLADE_IDENTITY_RQU, blade_identity_rqu_t) 48 | SWCLT_JSON_DESTROY_STRING(command) 49 | SWCLT_JSON_DESTROY_ITEM(identities) 50 | SWCLT_JSON_DESTROY_END() 51 | 52 | SWCLT_JSON_PARSE_BEG(BLADE_IDENTITY_RQU, blade_identity_rqu_t) 53 | SWCLT_JSON_PARSE_STRING(command) 54 | SWCLT_JSON_PARSE_ITEM(identities) 55 | SWCLT_JSON_PARSE_END() 56 | 57 | /** 58 | * CREATE_BLADE_IDENTITY_CMD_ASYNC - Creates a command which holds 59 | * and owns the request json for an identity request. 60 | */ 61 | static inline swclt_cmd_t *CREATE_BLADE_IDENTITY_CMD_ASYNC( 62 | swclt_cmd_cb_t cb, 63 | void *cb_data, 64 | const char *command, 65 | const char *identity) 66 | { 67 | swclt_cmd_t *cmd = NULL; 68 | ks_status_t status; 69 | ks_json_t *identities; 70 | ks_json_t *request; 71 | 72 | /* Serialize the identity into an array */ 73 | if (!(identities = ks_json_create_array())) { 74 | ks_log(KS_LOG_WARNING, "Failed to allocate blade identity array"); 75 | return cmd; 76 | } 77 | ks_json_add_string_to_array(identities, identity); 78 | 79 | if (!(request = BLADE_IDENTITY_RQU_MARSHAL( 80 | &(blade_identity_rqu_t){ 81 | command, 82 | identities}))) { 83 | ks_log(KS_LOG_WARNING, "Failed to allocate identity request"); 84 | return cmd; 85 | } 86 | 87 | /* Now hand it to the command, it will take ownership of it if successful 88 | * and null out our ptr */ 89 | if ((status = swclt_cmd_create_ex( 90 | &cmd, 91 | cb, 92 | cb_data, 93 | BLADE_IDENTITY_METHOD, 94 | &request, 95 | BLADE_IDENTITY_TTL_MS, 96 | BLADE_IDENTITY_FLAGS, 97 | ks_uuid_null()))) { 98 | ks_log(KS_LOG_WARNING, "Failed to allocate identity cmd: %lu", status); 99 | 100 | /* Safe to free this or at least attempt to, cmd will have set it to null if it 101 | * took ownership of it */ 102 | ks_json_delete(&request); 103 | return NULL; 104 | } 105 | 106 | /* Phew, successfully allocated the command */ 107 | return cmd; 108 | } 109 | 110 | static inline swclt_cmd_t *CREATE_BLADE_IDENTITY_CMD( 111 | const char *command, 112 | const char *identity) 113 | { 114 | return CREATE_BLADE_IDENTITY_CMD_ASYNC( 115 | NULL, 116 | NULL, 117 | command, 118 | identity); 119 | } 120 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/ping.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | /* The method name for a ping request */ 25 | #define BLADE_PING_METHOD "blade.ping" 26 | 27 | /* Flags for the command, in our case we don't get replies */ 28 | #define BLADE_PING_FLAGS SWCLT_CMD_FLAG_NOREPLY 29 | 30 | /* Default time to live for ping */ 31 | #define BLADE_PING_TTL_MS BLADE_DEFAULT_CMD_TTL_MS 32 | 33 | /* Create our ping request template */ 34 | typedef struct blade_ping_rqu_s { 35 | double timestamp; 36 | const char *payload; 37 | } blade_ping_rqu_t; 38 | 39 | SWCLT_JSON_MARSHAL_BEG(BLADE_PING_RQU, blade_ping_rqu_t) 40 | SWCLT_JSON_MARSHAL_DOUBLE(timestamp) 41 | SWCLT_JSON_MARSHAL_STRING_OPT(payload) 42 | SWCLT_JSON_MARSHAL_END() 43 | 44 | SWCLT_JSON_DESTROY_BEG(BLADE_PING_RQU, blade_ping_rqu_t) 45 | SWCLT_JSON_DESTROY_DOUBLE(timestamp) 46 | SWCLT_JSON_DESTROY_STRING(payload) 47 | SWCLT_JSON_DESTROY_END() 48 | 49 | SWCLT_JSON_PARSE_BEG(BLADE_PING_RQU, blade_ping_rqu_t) 50 | SWCLT_JSON_PARSE_DOUBLE_OPT(timestamp) 51 | SWCLT_JSON_PARSE_STRING_OPT(payload) 52 | SWCLT_JSON_PARSE_END() 53 | 54 | typedef struct blade_ping_rpl_s { 55 | double timestamp; 56 | const char *payload; 57 | } blade_ping_rpl_t; 58 | 59 | SWCLT_JSON_MARSHAL_BEG(BLADE_PING_RPL, blade_ping_rpl_t) 60 | SWCLT_JSON_MARSHAL_DOUBLE(timestamp) 61 | SWCLT_JSON_MARSHAL_STRING_OPT(payload) 62 | SWCLT_JSON_MARSHAL_END() 63 | 64 | SWCLT_JSON_DESTROY_BEG(BLADE_PING_RPL, blade_ping_rpl_t) 65 | SWCLT_JSON_DESTROY_DOUBLE(timestamp) 66 | SWCLT_JSON_DESTROY_STRING(payload) 67 | SWCLT_JSON_DESTROY_END() 68 | 69 | SWCLT_JSON_PARSE_BEG(BLADE_PING_RPL, blade_ping_rpl_t) 70 | SWCLT_JSON_PARSE_DOUBLE_OPT(timestamp) 71 | SWCLT_JSON_PARSE_STRING_OPT(payload) 72 | SWCLT_JSON_PARSE_END() 73 | 74 | /** 75 | * CREATE_BLADE_PING_CMD_ASYNC - Creates a command with a request 76 | * in it setup to submit a ping method to blade. 77 | */ 78 | static inline swclt_cmd_t *CREATE_BLADE_PING_CMD_ASYNC( 79 | swclt_cmd_cb_t cb, 80 | void *cb_data, 81 | double timestamp, 82 | const char *payload) 83 | { 84 | ks_json_t *obj = NULL; 85 | swclt_cmd_t *cmd = NULL; 86 | 87 | 88 | /* Fill in the ping request then marshal it, it will create copies 89 | * of all the fields so caller doesn't lose ownership here */ 90 | 91 | if (!(obj = BLADE_PING_RQU_MARSHAL(&(blade_ping_rqu_t){ 92 | timestamp, 93 | payload}))) { 94 | 95 | /* Since params is last, on error here we can be sure params was 96 | * not freed so do not set the callers params to NULL */ 97 | return cmd; 98 | } 99 | 100 | /* Now give it to the new command */ 101 | if (swclt_cmd_create_ex( 102 | &cmd, 103 | cb, 104 | cb_data, 105 | BLADE_PING_METHOD, 106 | &obj, 107 | BLADE_PING_TTL_MS, 108 | BLADE_PING_FLAGS, 109 | ks_uuid_null())) 110 | goto done; 111 | 112 | done: 113 | ks_json_delete(&obj); 114 | return cmd; 115 | } 116 | 117 | static inline swclt_cmd_t *CREATE_BLADE_PING_CMD(double timestamp, const char *payload) 118 | { 119 | return CREATE_BLADE_PING_CMD_ASYNC( 120 | NULL, 121 | NULL, 122 | timestamp, 123 | payload); 124 | } 125 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/register.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalwire/signalwire-c/52bc927e819ba6cb332b9c67dabbea1fd0d20610/inc/signalwire-client-c/blade/register.h -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/subscription.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | #define BLADE_SUBSCRIPTION_CMD_ADD "add" 28 | #define BLADE_SUBSCRIPTION_CMD_REMOVE "remove" 29 | 30 | /* The method name for a subscription request */ 31 | #define BLADE_SUBSCRIPTION_METHOD "blade.subscription" 32 | 33 | /* Flags for the command */ 34 | #define BLADE_SUBSCRIPTION_FLAGS 0 35 | 36 | /* Default ttl for subscription cmd */ 37 | #define BLADE_SUBSCRIPTION_TTL_MS BLADE_DEFAULT_CMD_TTL_MS 38 | 39 | typedef struct blade_subscription_rpl_s { 40 | const char *command; 41 | const char *protocol; 42 | ks_json_t *failed_channels; 43 | ks_json_t *subscribe_channels; 44 | } blade_subscription_rpl_t; 45 | 46 | SWCLT_JSON_DESTROY_BEG(BLADE_SUBSCRIPTION_RPL, blade_subscription_rpl_t) 47 | SWCLT_JSON_DESTROY_STRING(command) 48 | SWCLT_JSON_DESTROY_STRING(protocol) 49 | SWCLT_JSON_DESTROY_ITEM(failed_channels) 50 | SWCLT_JSON_DESTROY_ITEM(subscribe_channels) 51 | SWCLT_JSON_DESTROY_END() 52 | 53 | SWCLT_JSON_PARSE_BEG(BLADE_SUBSCRIPTION_RPL, blade_subscription_rpl_t) 54 | SWCLT_JSON_PARSE_STRING(command) 55 | SWCLT_JSON_PARSE_STRING(protocol) 56 | SWCLT_JSON_PARSE_ITEM_OPT(failed_channels) 57 | SWCLT_JSON_PARSE_ITEM_OPT(subscribe_channels) 58 | SWCLT_JSON_PARSE_END() 59 | 60 | typedef struct blade_subscription_rqu_s { 61 | const char *command; 62 | const char *protocol; 63 | ks_json_t *channels; 64 | } blade_subscription_rqu_t; 65 | 66 | SWCLT_JSON_MARSHAL_BEG(BLADE_SUBSCRIPTION_RQU, blade_subscription_rqu_t) 67 | SWCLT_JSON_MARSHAL_STRING(command) 68 | SWCLT_JSON_MARSHAL_STRING(protocol) 69 | SWCLT_JSON_MARSHAL_ITEM(channels) 70 | SWCLT_JSON_MARSHAL_END() 71 | 72 | SWCLT_JSON_DESTROY_BEG(BLADE_SUBSCRIPTION_RQU, blade_subscription_rqu_t) 73 | SWCLT_JSON_DESTROY_STRING(command) 74 | SWCLT_JSON_DESTROY_STRING(protocol) 75 | SWCLT_JSON_DESTROY_ITEM(channels) 76 | SWCLT_JSON_DESTROY_END() 77 | 78 | SWCLT_JSON_PARSE_BEG(BLADE_SUBSCRIPTION_RQU, blade_subscription_rqu_t) 79 | SWCLT_JSON_PARSE_STRING(command) 80 | SWCLT_JSON_PARSE_STRING(protocol) 81 | SWCLT_JSON_PARSE_ITEM(channels) 82 | SWCLT_JSON_PARSE_END() 83 | 84 | /** 85 | * CREATE_BLADE_SUBSCRIPTION_CMD_ASYNC - Creates a command which holds 86 | * and owns the request json for a subscription request. 87 | */ 88 | static inline swclt_cmd_t *CREATE_BLADE_SUBSCRIPTION_CMD_ASYNC( 89 | swclt_cmd_cb_t cb, 90 | void *cb_data, 91 | const char *command, 92 | const char *protocol, 93 | const char *channel) 94 | { 95 | ks_json_t *request_obj; 96 | ks_status_t status; 97 | swclt_cmd_t *cmd = NULL; 98 | 99 | ks_json_t *channels = ks_json_create_array(); 100 | 101 | /* Create a blade subscription request structure then marshal it */ 102 | blade_subscription_rqu_t request = { 103 | command, 104 | protocol, 105 | channels, 106 | }; 107 | 108 | ks_json_add_string_to_array(channels, channel); 109 | 110 | if (!(request_obj = BLADE_SUBSCRIPTION_RQU_MARSHAL(&request))) { 111 | ks_log(KS_LOG_WARNING, "Failed to create subscription request"); 112 | 113 | /* Don't forget to free the channels we instantiated inline above */ 114 | ks_json_delete(&request.channels); 115 | return cmd; 116 | } 117 | 118 | /* Request object has been created, channels will now reside in it */ 119 | 120 | /* Now wrap it in a command */ 121 | if ((status = swclt_cmd_create_ex( 122 | &cmd, 123 | cb, 124 | cb_data, 125 | BLADE_SUBSCRIPTION_METHOD, 126 | &request_obj, 127 | BLADE_SUBSCRIPTION_TTL_MS, 128 | BLADE_SUBSCRIPTION_FLAGS, 129 | ks_uuid_null()))) { 130 | ks_log(KS_LOG_WARNING, "Failed to allocate subscription command: %lu", status); 131 | ks_json_delete(&request_obj); 132 | return cmd; 133 | } 134 | 135 | /* Success */ 136 | return cmd; 137 | } 138 | 139 | static inline swclt_cmd_t *CREATE_BLADE_SUBSCRIPTION_CMD( 140 | const char *command, 141 | const char *protocol, 142 | const char *channel) 143 | { 144 | return CREATE_BLADE_SUBSCRIPTION_CMD_ASYNC( 145 | NULL, 146 | NULL, 147 | command, 148 | protocol, 149 | channel); 150 | } 151 | 152 | /* Creates a subscription request */ 153 | static inline ks_json_t *BLADE_SUBSCRIPTION_RQU( 154 | const char * const command, 155 | const char * const protocol, 156 | const char * const channel, 157 | blade_access_control_t broadcast_access, 158 | blade_access_control_t subscribe_access) 159 | { 160 | ks_json_t *request = ks_json_create_object(); 161 | ks_json_t *channels = ks_json_add_array_to_object(request, "channels"); 162 | ks_json_add_string_to_object(request, "command", command); 163 | ks_json_add_string_to_object(request, "protocol", protocol); 164 | ks_json_add_string_to_array(channels, channel); 165 | (void)(broadcast_access); // unused 166 | (void)(subscribe_access); // unused 167 | return request; 168 | } 169 | 170 | KS_END_EXTERN_C 171 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/type.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | typedef enum { 28 | BLADE_ACL_NONE = -1, 29 | BLADE_ACL_SYSTEM = 0, /* Only certified nodes */ 30 | BLADE_ACL_PUBLIC = 1, /* Anyone */ 31 | BLADE_ACL_RESTRICTED = 2, /* Some uncertified nodes, depending on implementation of authenticator */ 32 | } blade_access_control_t; 33 | 34 | typedef struct blade_channel_s { 35 | const char * name; 36 | blade_access_control_t broadcast_access; 37 | blade_access_control_t subscribe_access; 38 | } blade_channel_t; 39 | 40 | SWCLT_JSON_MARSHAL_BEG(BLADE_CHANNEL, blade_channel_t) 41 | SWCLT_JSON_MARSHAL_STRING(name) 42 | SWCLT_JSON_MARSHAL_INT(broadcast_access) 43 | SWCLT_JSON_MARSHAL_INT(subscribe_access) 44 | SWCLT_JSON_MARSHAL_END() 45 | 46 | SWCLT_JSON_DESTROY_BEG(BLADE_CHANNEL, blade_channel_t) 47 | SWCLT_JSON_DESTROY_STRING(name) 48 | SWCLT_JSON_DESTROY_INT(broadcast_access) 49 | SWCLT_JSON_DESTROY_INT(subscribe_access) 50 | SWCLT_JSON_DESTROY_END() 51 | 52 | SWCLT_JSON_PARSE_BEG(BLADE_CHANNEL, blade_channel_t) 53 | SWCLT_JSON_PARSE_STRING(name) 54 | SWCLT_JSON_PARSE_INT(broadcast_access) 55 | SWCLT_JSON_PARSE_INT(subscribe_access) 56 | SWCLT_JSON_PARSE_END() 57 | 58 | /* Define our version structure */ 59 | typedef struct blade_version_s { 60 | uint32_t major; 61 | uint32_t minor; 62 | uint32_t revision; 63 | } blade_version_t; 64 | 65 | SWCLT_JSON_MARSHAL_BEG(BLADE_VERSION, blade_version_t) 66 | SWCLT_JSON_MARSHAL_INT(major) 67 | SWCLT_JSON_MARSHAL_INT(minor) 68 | SWCLT_JSON_MARSHAL_INT(revision) 69 | SWCLT_JSON_MARSHAL_END() 70 | 71 | SWCLT_JSON_DESTROY_BEG(BLADE_VERSION, blade_version_t) 72 | SWCLT_JSON_DESTROY_INT(major) 73 | SWCLT_JSON_DESTROY_INT(minor) 74 | SWCLT_JSON_DESTROY_INT(revision) 75 | SWCLT_JSON_DESTROY_END() 76 | 77 | SWCLT_JSON_ALLOC_BEG(BLADE_VERSION, blade_version_t) 78 | SWCLT_JSON_ALLOC_DEFAULT(major, SWCLT_BLADE_VERSION_MAJOR) 79 | SWCLT_JSON_ALLOC_DEFAULT(minor, SWCLT_BLADE_VERSION_MINOR) 80 | SWCLT_JSON_ALLOC_DEFAULT(revision, SWCLT_BLADE_VERSION_REVISION) 81 | SWCLT_JSON_ALLOC_END() 82 | 83 | SWCLT_JSON_PARSE_BEG(BLADE_VERSION, blade_version_t) 84 | SWCLT_JSON_PARSE_INT(major) 85 | SWCLT_JSON_PARSE_INT(minor) 86 | SWCLT_JSON_PARSE_INT(revision) 87 | SWCLT_JSON_PARSE_END() 88 | 89 | typedef struct blade_node_s { 90 | const char *nodeid; 91 | ks_bool_t certified; 92 | } blade_node_t; 93 | 94 | SWCLT_JSON_MARSHAL_BEG(BLADE_NODE, blade_node_t) 95 | SWCLT_JSON_MARSHAL_STRING(nodeid) 96 | SWCLT_JSON_MARSHAL_BOOL(certified) 97 | SWCLT_JSON_MARSHAL_END() 98 | 99 | SWCLT_JSON_DESTROY_BEG(BLADE_NODE, blade_node_t) 100 | SWCLT_JSON_DESTROY_STRING(nodeid) 101 | SWCLT_JSON_DESTROY_BOOL(certified) 102 | SWCLT_JSON_DESTROY_END() 103 | 104 | SWCLT_JSON_PARSE_BEG(BLADE_NODE, blade_node_t) 105 | SWCLT_JSON_PARSE_STRING(nodeid) 106 | SWCLT_JSON_PARSE_BOOL_OPT(certified) 107 | SWCLT_JSON_PARSE_END() 108 | 109 | typedef struct blade_provider_s { 110 | const char *nodeid; 111 | ks_json_t *identities; /* list of identity uri's string's */ 112 | int rank; 113 | ks_json_t *data; 114 | } blade_provider_t; 115 | 116 | SWCLT_JSON_MARSHAL_BEG(BLADE_PROVIDER, blade_provider_t) 117 | SWCLT_JSON_MARSHAL_STRING(nodeid) 118 | SWCLT_JSON_MARSHAL_ITEM_OPT(identities) 119 | SWCLT_JSON_MARSHAL_INT(rank) 120 | SWCLT_JSON_MARSHAL_ITEM_OPT(data) 121 | SWCLT_JSON_MARSHAL_END() 122 | 123 | SWCLT_JSON_DESTROY_BEG(BLADE_PROVIDER, blade_provider_t) 124 | SWCLT_JSON_DESTROY_STRING(nodeid) 125 | SWCLT_JSON_DESTROY_ITEM(identities) 126 | SWCLT_JSON_DESTROY_INT(rank) 127 | SWCLT_JSON_DESTROY_ITEM(data) 128 | SWCLT_JSON_DESTROY_END() 129 | 130 | SWCLT_JSON_PARSE_BEG(BLADE_PROVIDER, blade_provider_t) 131 | SWCLT_JSON_PARSE_STRING(nodeid) 132 | SWCLT_JSON_PARSE_ITEM_OPT(identities) 133 | SWCLT_JSON_PARSE_INT_OPT_DEF(rank, 1) 134 | SWCLT_JSON_PARSE_ITEM_OPT(data) 135 | SWCLT_JSON_PARSE_END() 136 | 137 | typedef struct blade_subscription_s { 138 | const char *protocol; 139 | const char *channel; 140 | ks_json_t *subscribers; /* list of identities */ 141 | } blade_subscription_t; 142 | 143 | SWCLT_JSON_MARSHAL_BEG(BLADE_SUBSCRIPTION, blade_subscription_t) 144 | SWCLT_JSON_MARSHAL_STRING(protocol) 145 | SWCLT_JSON_MARSHAL_STRING(channel) 146 | SWCLT_JSON_MARSHAL_ITEM(subscribers) 147 | SWCLT_JSON_MARSHAL_END() 148 | 149 | SWCLT_JSON_DESTROY_BEG(BLADE_SUBSCRIPTION, blade_subscription_t) 150 | SWCLT_JSON_DESTROY_STRING(protocol) 151 | SWCLT_JSON_DESTROY_STRING(channel) 152 | SWCLT_JSON_DESTROY_ITEM(subscribers) 153 | SWCLT_JSON_DESTROY_END() 154 | 155 | SWCLT_JSON_PARSE_BEG(BLADE_SUBSCRIPTION, blade_subscription_t) 156 | SWCLT_JSON_PARSE_STRING(protocol) 157 | SWCLT_JSON_PARSE_STRING(channel) 158 | SWCLT_JSON_PARSE_ITEM(subscribers) 159 | SWCLT_JSON_PARSE_END() 160 | 161 | typedef struct blade_protocol_s { 162 | const char *name; 163 | uint32_t default_method_execute_access; 164 | uint32_t default_channel_broadcast_access; 165 | uint32_t default_channel_subscribe_access; 166 | ks_json_t *providers; /* list of blade_provider_t's */ 167 | ks_json_t *channels; /* list of blade_channel_t's */ 168 | } blade_protocol_t; 169 | 170 | SWCLT_JSON_MARSHAL_BEG(BLADE_PROTOCOL, blade_protocol_t) 171 | SWCLT_JSON_MARSHAL_STRING(name) 172 | SWCLT_JSON_MARSHAL_INT(default_method_execute_access) 173 | SWCLT_JSON_MARSHAL_INT(default_channel_broadcast_access) 174 | SWCLT_JSON_MARSHAL_INT(default_channel_subscribe_access) 175 | SWCLT_JSON_MARSHAL_ITEM(providers) 176 | SWCLT_JSON_MARSHAL_ITEM(channels) 177 | SWCLT_JSON_MARSHAL_END() 178 | 179 | SWCLT_JSON_DESTROY_BEG(BLADE_PROTOCOL, blade_protocol_t) 180 | SWCLT_JSON_DESTROY_STRING(name) 181 | SWCLT_JSON_DESTROY_INT(default_method_execute_access) 182 | SWCLT_JSON_DESTROY_INT(default_channel_broadcast_access) 183 | SWCLT_JSON_DESTROY_INT(default_channel_subscribe_access) 184 | SWCLT_JSON_DESTROY_ITEM(providers) 185 | SWCLT_JSON_DESTROY_ITEM(channels) 186 | SWCLT_JSON_DESTROY_END() 187 | 188 | SWCLT_JSON_PARSE_BEG(BLADE_PROTOCOL, blade_protocol_t) 189 | SWCLT_JSON_PARSE_STRING(name) 190 | SWCLT_JSON_PARSE_INT(default_method_execute_access) 191 | SWCLT_JSON_PARSE_INT(default_channel_broadcast_access) 192 | SWCLT_JSON_PARSE_INT(default_channel_subscribe_access) 193 | SWCLT_JSON_PARSE_ITEM(providers) 194 | SWCLT_JSON_PARSE_ITEM(channels) 195 | SWCLT_JSON_PARSE_END() 196 | 197 | KS_END_EXTERN_C 198 | 199 | /* For Emacs: 200 | * Local Variables: 201 | * mode:c 202 | * indent-tabs-mode:t 203 | * tab-width:4 204 | * c-basic-offset:4 205 | * End: 206 | * For VIM: 207 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 208 | */ 209 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/blade/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | /** 28 | * Given a method, will return the command flags appropriate for the method. 29 | */ 30 | static inline uint32_t BLADE_METHOD_FLAGS(const char * const method) 31 | { 32 | ks_assertd(method != NULL); 33 | if (!strcmp(method, BLADE_BROADCAST_METHOD)) 34 | return BLADE_BROADCAST_FLAGS; 35 | else if (!strcmp(method, BLADE_DISCONNECT_METHOD)) 36 | return BLADE_DISCONNECT_FLAGS; 37 | else if (!strcmp(method, BLADE_NETCAST_METHOD)) 38 | return BLADE_NETCAST_FLAGS; 39 | else if (!strcmp(method, BLADE_PROTOCOL_METHOD)) 40 | return BLADE_PROTOCOL_FLAGS; 41 | else if (!strcmp(method, BLADE_IDENTITY_METHOD)) 42 | return BLADE_IDENTITY_FLAGS; 43 | else if (!strcmp(method, BLADE_EXECUTE_METHOD)) 44 | return BLADE_EXECUTE_FLAGS; 45 | else if (!strcmp(method, BLADE_SUBSCRIPTION_METHOD)) 46 | return BLADE_SUBSCRIPTION_FLAGS; 47 | else if (!strcmp(method, BLADE_PING_METHOD)) 48 | return BLADE_PING_FLAGS; 49 | else { 50 | ks_log(KS_LOG_WARNING, "Unsupported blade method: %s", method); 51 | return 0; 52 | } 53 | } 54 | 55 | KS_END_EXTERN_C 56 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 "libks/ks.h" 26 | #include "libks/ks_atomic.h" 27 | 28 | #include "signalwire-client-c/export.h" 29 | #include "signalwire-client-c/init.h" 30 | #include "signalwire-client-c/transport/frame.h" 31 | #include "signalwire-client-c/command.h" 32 | #include "signalwire-client-c/transport/websocket.h" 33 | #include "signalwire-client-c/JSON/macros.h" 34 | #include "signalwire-client-c/blade/blade.h" 35 | #include "signalwire-client-c/signalwire/signalwire.h" 36 | #include "signalwire-client-c/identity.h" 37 | #include "signalwire-client-c/config.h" 38 | #include "signalwire-client-c/connection.h" 39 | #include "signalwire-client-c/subscription.h" 40 | #include "signalwire-client-c/pmethod.h" 41 | #include "signalwire-client-c/nodestore.h" 42 | #include "signalwire-client-c/session.h" 43 | #include "signalwire-client-c/version.h" 44 | 45 | /* Utility */ 46 | #include "signalwire-client-c/ssl.h" 47 | 48 | 49 | /* For Emacs: 50 | * Local Variables: 51 | * mode:c 52 | * indent-tabs-mode:t 53 | * tab-width:4 54 | * c-basic-offset:4 55 | * End: 56 | * For VIM: 57 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 58 | */ 59 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/command.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2022 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 | /* A command is one of three types, request, result, error */ 26 | typedef enum { 27 | SWCLT_CMD_TYPE_INVALID, 28 | SWCLT_CMD_TYPE_ERROR, /* Remote responded with an error */ 29 | SWCLT_CMD_TYPE_REQUEST, /* Initial state, constructed from a request, ready to submit */ 30 | SWCLT_CMD_TYPE_RESULT, /* Remote responded with a non error result */ 31 | SWCLT_CMD_TYPE_FAILURE, /* A failure ocurred that prevented remote from responding */ 32 | } SWCLT_CMD_TYPE; 33 | 34 | typedef struct swclt_cmd swclt_cmd_t; 35 | 36 | /* Flags control aspects of the command such as whether a reply is expected */ 37 | #define SWCLT_CMD_FLAG_NOREPLY KS_BIT_FLAG(0) 38 | #define SWCLT_CMD_FLAG_MAX 1 39 | 40 | struct swclt_cmd_reply { 41 | ks_pool_t *pool; 42 | ks_json_t *json; 43 | SWCLT_CMD_TYPE type; 44 | ks_status_t failure_status; 45 | char *failure_reason; 46 | }; 47 | 48 | typedef struct swclt_cmd_reply swclt_cmd_reply_t; 49 | typedef struct swclt_cmd_future swclt_cmd_future_t; 50 | 51 | typedef ks_status_t (*swclt_cmd_parse_cb_t)(ks_pool_t *pool, ks_json_t * const payload, void **structure); 52 | typedef void (*swclt_cmd_cb_t)(swclt_cmd_reply_t *cmd_reply, void *cb_data); 53 | 54 | /* Ths client command context represents a commands state */ 55 | struct swclt_cmd { 56 | ks_pool_t *pool; 57 | /* When a command completes it calls the callback */ 58 | swclt_cmd_cb_t cb; 59 | void *cb_data; 60 | 61 | /* The request ids, generated once on allocation */ 62 | ks_uuid_t id; 63 | char *id_str; 64 | 65 | /* CMD flags e.g. whether we expect a reply or not */ 66 | uint32_t flags : SWCLT_CMD_FLAG_MAX; 67 | 68 | /* Our method, established on construction */ 69 | char *method; 70 | 71 | /* The request, a command always has one, as it is born from a request */ 72 | ks_json_t *json; 73 | 74 | /* The command type can be request (when constructed) result (when remote replied 75 | * with no error) and error (when remove replies with an error */ 76 | SWCLT_CMD_TYPE type; 77 | 78 | /* This is the time to live value, when non zero, the command will fail if the 79 | * response is not received within the appropriate window. */ 80 | uint32_t response_ttl_ms; 81 | }; 82 | 83 | static inline const char * swclt_cmd_type_str(SWCLT_CMD_TYPE type) 84 | { 85 | switch (type) { 86 | case SWCLT_CMD_TYPE_INVALID: 87 | return "Invalid"; 88 | case SWCLT_CMD_TYPE_ERROR: 89 | return "Error"; 90 | case SWCLT_CMD_TYPE_REQUEST: 91 | return "Request"; 92 | case SWCLT_CMD_TYPE_RESULT: 93 | return "Result"; 94 | case SWCLT_CMD_TYPE_FAILURE: 95 | return "Failure"; 96 | default: 97 | ks_debug_break(); 98 | return "Unknown"; 99 | } 100 | } 101 | 102 | KS_BEGIN_EXTERN_C 103 | 104 | SWCLT_DECLARE(ks_status_t) swclt_cmd_set_cb(swclt_cmd_t *cmd, swclt_cmd_cb_t cb, void *cb_data); 105 | 106 | SWCLT_DECLARE(ks_status_t) swclt_cmd_future_create(swclt_cmd_future_t **future, swclt_cmd_t *cmd); 107 | SWCLT_DECLARE(ks_status_t) swclt_cmd_future_get(swclt_cmd_future_t *future, swclt_cmd_reply_t **reply); 108 | SWCLT_DECLARE(ks_uuid_t) swclt_cmd_future_get_id(swclt_cmd_future_t *future); 109 | SWCLT_DECLARE(ks_status_t) swclt_cmd_future_destroy(swclt_cmd_future_t **future); 110 | 111 | SWCLT_DECLARE(ks_status_t) swclt_cmd_reply_create(swclt_cmd_reply_t **reply); 112 | SWCLT_DECLARE(ks_status_t) swclt_cmd_reply_ok(swclt_cmd_reply_t *reply); 113 | SWCLT_DECLARE(ks_status_t) swclt_cmd_reply_parse(swclt_cmd_reply_t *reply, ks_pool_t *pool, swclt_cmd_parse_cb_t parse_cb, void **structure); 114 | SWCLT_DECLARE(ks_status_t) swclt_cmd_reply_destroy(swclt_cmd_reply_t **reply); 115 | 116 | /* Create a command from a request, mandatory caller pool */ 117 | SWCLT_DECLARE(ks_status_t) swclt_cmd_create(swclt_cmd_t **cmd, const char * const method, ks_json_t **request, 118 | uint32_t response_ttl_ms, uint32_t flags); 119 | 120 | /* Create a command from a request, and set a callback for async handling, mandatory caller pool */ 121 | SWCLT_DECLARE(ks_status_t) swclt_cmd_create_ex(swclt_cmd_t **cmd, swclt_cmd_cb_t cb, void *cb_data, 122 | const char * const method, ks_json_t **request, uint32_t response_ttl_ms, uint32_t flags, ks_uuid_t id); 123 | 124 | /* Create a request from a frame w/optional callback */ 125 | SWCLT_DECLARE(ks_status_t) swclt_cmd_create_frame( 126 | swclt_cmd_t **cmd, 127 | swclt_cmd_cb_t cb, 128 | void *cb_data, 129 | swclt_frame_t *frame, 130 | uint32_t response_ttl_ms, 131 | uint32_t flags); 132 | 133 | /* Duplicate a command, excluding its callback data */ 134 | SWCLT_DECLARE(swclt_cmd_t *) swclt_cmd_duplicate(swclt_cmd_t *cmd); 135 | SWCLT_DECLARE(ks_status_t) swclt_cmd_destroy(swclt_cmd_t **cmd); 136 | SWCLT_DECLARE(char *) swclt_cmd_describe(swclt_cmd_t *cmd); 137 | SWCLT_DECLARE(ks_status_t) swclt_cmd_print(swclt_cmd_t *cmd, ks_pool_t *pool, char **string); 138 | SWCLT_DECLARE(ks_status_t) swclt_cmd_set_result(swclt_cmd_t *cmd, ks_json_t **result); 139 | SWCLT_DECLARE(ks_status_t) swclt_cmd_set_error(swclt_cmd_t *cmd, ks_json_t **result); 140 | SWCLT_DECLARE(ks_status_t) swclt_cmd_set_ttl(swclt_cmd_t *cmd, uint32_t response_ttl_ms); 141 | SWCLT_DECLARE(ks_status_t) swclt_cmd_parse_reply_frame(swclt_cmd_t *cmd, swclt_frame_t *frame); 142 | 143 | SWCLT_DECLARE(ks_status_t) swclt_cmd_report_failure_fmt(swclt_cmd_t *cmd, ks_status_t failure_status, const char *failure_fmt, ...); 144 | SWCLT_DECLARE(ks_status_t) swclt_cmd_report_failure(swclt_cmd_t *cmd, ks_status_t failure_status, const char *failure_description); 145 | 146 | KS_END_EXTERN_C 147 | 148 | /* For Emacs: 149 | * Local Variables: 150 | * mode:c 151 | * indent-tabs-mode:t 152 | * tab-width:4 153 | * c-basic-offset:4 154 | * End: 155 | * For VIM: 156 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 157 | */ 158 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | /* Obfuscate our config internals */ 28 | typedef struct swclt_config_s swclt_config_t; 29 | 30 | SWCLT_DECLARE(ks_status_t) swclt_config_create(swclt_config_t **config); 31 | SWCLT_DECLARE(ks_status_t) swclt_config_destroy(swclt_config_t **config); 32 | 33 | SWCLT_DECLARE(ks_status_t) swclt_config_load_from_json(swclt_config_t *config, ks_json_t *json); 34 | SWCLT_DECLARE(ks_status_t) swclt_config_load_from_env(swclt_config_t *config); 35 | 36 | SWCLT_DECLARE(const char *) swclt_config_get_private_key_path(swclt_config_t *config); 37 | SWCLT_DECLARE(ks_status_t) swclt_config_set_private_key_path(swclt_config_t *config, const char *value); 38 | SWCLT_DECLARE(const char *) swclt_config_get_client_cert_path(swclt_config_t *config); 39 | SWCLT_DECLARE(ks_status_t) swclt_config_set_client_cert_path(swclt_config_t *config, const char *value); 40 | SWCLT_DECLARE(const char *) swclt_config_get_cert_chain_path(swclt_config_t *config); 41 | SWCLT_DECLARE(ks_status_t) swclt_config_set_cert_chain_path(swclt_config_t *config, const char *value); 42 | SWCLT_DECLARE(const char *) swclt_config_get_authentication(swclt_config_t *config); 43 | SWCLT_DECLARE(ks_status_t) swclt_config_set_authentication(swclt_config_t *config, const char *value); 44 | SWCLT_DECLARE(const char *) swclt_config_get_agent(swclt_config_t *config); 45 | SWCLT_DECLARE(ks_status_t) swclt_config_set_agent(swclt_config_t *config, const char *value); 46 | SWCLT_DECLARE(const char *) swclt_config_get_identity(swclt_config_t *config); 47 | SWCLT_DECLARE(ks_status_t) swclt_config_set_identity(swclt_config_t *config, const char *value); 48 | 49 | SWCLT_DECLARE(ks_status_t) swclt_config_set_default_network(swclt_config_t *config, ks_bool_t allData); 50 | SWCLT_DECLARE(ks_bool_t) swclt_config_get_network_route_data(swclt_config_t *config); 51 | SWCLT_DECLARE(void) swclt_config_set_network_route_data(swclt_config_t *config, ks_bool_t value); 52 | SWCLT_DECLARE(ks_bool_t) swclt_config_get_network_route_add(swclt_config_t *config); 53 | SWCLT_DECLARE(void) swclt_config_set_network_route_add(swclt_config_t *config, ks_bool_t value); 54 | SWCLT_DECLARE(ks_bool_t) swclt_config_get_network_route_remove(swclt_config_t *config); 55 | SWCLT_DECLARE(void) swclt_config_set_network_route_remove(swclt_config_t *config, ks_bool_t value); 56 | SWCLT_DECLARE(ks_bool_t) swclt_config_get_network_authority_data(swclt_config_t *config); 57 | SWCLT_DECLARE(void) swclt_config_set_network_authority_data(swclt_config_t *config, ks_bool_t value); 58 | SWCLT_DECLARE(ks_bool_t) swclt_config_get_network_authority_add(swclt_config_t *config); 59 | SWCLT_DECLARE(void) swclt_config_set_network_authority_add(swclt_config_t *config, ks_bool_t value); 60 | SWCLT_DECLARE(ks_bool_t) swclt_config_get_network_authority_remove(swclt_config_t *config); 61 | SWCLT_DECLARE(void) swclt_config_set_network_authority_remove(swclt_config_t *config, ks_bool_t value); 62 | SWCLT_DECLARE(ks_bool_t) swclt_config_get_network_filtered_protocols(swclt_config_t *config); 63 | SWCLT_DECLARE(void) swclt_config_set_network_filtered_protocols(swclt_config_t *config, ks_bool_t value); 64 | SWCLT_DECLARE(void) swclt_config_add_network_protocol(swclt_config_t *config, const char *value); 65 | SWCLT_DECLARE(void) swclt_config_remove_network_protocol(swclt_config_t *config, const char *value); 66 | 67 | KS_END_EXTERN_C 68 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/connection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2022 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 | typedef struct swclt_ttl_tracker swclt_ttl_tracker_t; 28 | 29 | typedef struct swclt_conn swclt_conn_t; 30 | 31 | typedef ks_status_t (*swclt_conn_incoming_cmd_cb_t)(swclt_conn_t *conn, swclt_cmd_t *cmd, void *cb_data); 32 | typedef ks_status_t (*swclt_conn_connect_cb_t)(swclt_conn_t *conn, ks_json_t *error, blade_connect_rpl_t *connect_rpl, void *cb_data); 33 | typedef ks_status_t (*swclt_conn_failed_cb_t)(swclt_conn_t *conn, void *cb_data); 34 | 35 | /* Information about this connection */ 36 | typedef struct swclt_conn_info_s { 37 | /* We also store a copy of the wss's info structure */ 38 | swclt_wss_info_t wss; 39 | 40 | /* Pulled from the blade connect result */ 41 | ks_uuid_t sessionid; 42 | const char *nodeid; 43 | const char *master_nodeid; 44 | } swclt_conn_info_t; 45 | 46 | /* Ths client connection context represents a connections state */ 47 | struct swclt_conn { 48 | 49 | ks_pool_t *pool; 50 | 51 | /* When we receive an incoming request we call this callback with the prepared command */ 52 | swclt_conn_incoming_cmd_cb_t incoming_cmd_cb; 53 | void *incoming_cmd_cb_data; 54 | 55 | /* Optional callbacks for getting the initial connect result payload */ 56 | swclt_conn_connect_cb_t connect_cb; 57 | void *connect_cb_data; 58 | 59 | /* Optional callbacks for getting notified of connection failure */ 60 | swclt_conn_failed_cb_t failed_cb; 61 | void *failed_cb_data; 62 | 63 | /* Connection failed state */ 64 | int failed; 65 | 66 | ks_mutex_t *failed_mutex; 67 | 68 | /* Our websocket transport, basically our connection to blade */ 69 | swclt_wss_t *wss; 70 | 71 | /* Basic connection info that the caller can examine, contains 72 | * our sessionid, nodeid, and master_nodeid variables returned from 73 | * a connect result from blade, including our connected address and 74 | * ssl context ptr (from websocket info) */ 75 | swclt_conn_info_t info; 76 | 77 | /* The result of our last connect, kept around for reference */ 78 | blade_connect_rpl_t *blade_connect_rpl; 79 | 80 | /* A hash of outstanding commands, keyed by their request ids. 81 | * This is the outgoing queue for requests born from the client or 82 | * requests which have been sent from blade. Since the uuids are 83 | * globally unique we can just use one hash for both */ 84 | ks_hash_t *outstanding_requests; 85 | 86 | /* TTLs to expire */ 87 | swclt_ttl_tracker_t *ttl; 88 | 89 | /* pool to process incoming websocket frames */ 90 | ks_thread_pool_t *incoming_frame_pool; 91 | 92 | /* when last stats were published */ 93 | ks_time_t last_stats_update; 94 | swclt_wss_stats_t last_stats; 95 | }; 96 | 97 | SWCLT_DECLARE(void) swclt_conn_destroy(swclt_conn_t **conn); 98 | SWCLT_DECLARE(ks_status_t) swclt_conn_connect( 99 | swclt_conn_t **conn, 100 | swclt_conn_incoming_cmd_cb_t incoming_command_callback, 101 | void *incoming_command_cb_data, 102 | swclt_ident_t *ident, 103 | ks_json_t **authentication, 104 | const char *agent, 105 | const char *identity, 106 | ks_json_t *network, 107 | const SSL_CTX *ssl); 108 | 109 | SWCLT_DECLARE(ks_status_t) swclt_conn_connect_ex( 110 | swclt_conn_t **conn, 111 | swclt_conn_incoming_cmd_cb_t incoming_command_callback, 112 | void *incoming_command_cb_data, 113 | swclt_conn_connect_cb_t connect_callback, 114 | void *connect_cb_data, 115 | swclt_conn_failed_cb_t failed_callback, 116 | void *failed_cb_data, 117 | swclt_ident_t *ident, 118 | ks_uuid_t previous_sessionid, 119 | ks_json_t **authentication, 120 | const char *agent, 121 | const char *identity, 122 | ks_json_t *network, 123 | const SSL_CTX *ssl); 124 | 125 | SWCLT_DECLARE(ks_status_t) swclt_conn_submit_request(swclt_conn_t *conn, swclt_cmd_t **cmd, swclt_cmd_future_t **future); 126 | SWCLT_DECLARE(ks_status_t) swclt_conn_submit_result(swclt_conn_t *conn, swclt_cmd_t *cmd); 127 | SWCLT_DECLARE(ks_status_t) swclt_conn_cancel_request(swclt_conn_t *conn, swclt_cmd_future_t **future); 128 | ks_status_t swclt_conn_info(swclt_conn_t *conn, swclt_conn_info_t *info); 129 | SWCLT_DECLARE(char *) swclt_conn_describe(swclt_conn_t *conn); 130 | 131 | KS_END_EXTERN_C 132 | 133 | /* For Emacs: 134 | * Local Variables: 135 | * mode:c 136 | * indent-tabs-mode:t 137 | * tab-width:4 138 | * c-basic-offset:4 139 | * End: 140 | * For VIM: 141 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 142 | */ 143 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/export.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | #if KS_PLAT_WIN 26 | #if defined(SWCLT_EXPORTS) 27 | #define SWCLT_DECLARE(type) __declspec(dllexport) type __stdcall 28 | #else 29 | #define SWCLT_DECLARE(type) __declspec(dllimport) type __stdcall 30 | #endif 31 | #else // !KS_PLAT_WIN 32 | #define SWCLT_DECLARE(type) __attribute__((visibility("default"))) type 33 | #endif 34 | 35 | /* For Emacs: 36 | * Local Variables: 37 | * mode:c 38 | * indent-tabs-mode:t 39 | * tab-width:4 40 | * c-basic-offset:4 41 | * End: 42 | * For VIM: 43 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 44 | */ 45 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/identity.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | typedef enum { 28 | SWCLT_IDENT_TOSTRING_SCHEME = KS_BIT_FLAG(0), 29 | SWCLT_IDENT_TOSTRING_USER = KS_BIT_FLAG(1), 30 | SWCLT_IDENT_TOSTRING_HOST = KS_BIT_FLAG(2), 31 | SWCLT_IDENT_TOSTRING_PORT = KS_BIT_FLAG(3), 32 | SWCLT_IDENT_TOSTRING_PATH = KS_BIT_FLAG(4), 33 | SWCLT_IDENT_TOSTRING_PARAMETERS = KS_BIT_FLAG(5), 34 | } swclt_ident_to_str_flags_t; 35 | 36 | typedef struct swclt_ident_s { 37 | const char *uri; 38 | const char *components; 39 | const char *scheme; 40 | const char *user; 41 | const char *host; 42 | const char *port; 43 | const char *path; 44 | 45 | ks_port_t portnum; 46 | ks_hash_t *parameters; 47 | } swclt_ident_t; 48 | 49 | SWCLT_DECLARE(ks_status_t) swclt_ident_from_str(swclt_ident_t *ident, ks_pool_t *pool, const char *uri); 50 | SWCLT_DECLARE(void) swclt_ident_to_str(swclt_ident_t *ident, ks_pool_t *pool, char **str, swclt_ident_to_str_flags_t flags); 51 | SWCLT_DECLARE(void) swclt_ident_destroy(swclt_ident_t *ident); 52 | 53 | KS_END_EXTERN_C 54 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/init.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | SWCLT_DECLARE(ks_status_t) swclt_init(int default_log_level); 28 | SWCLT_DECLARE(ks_status_t) swclt_shutdown(void); 29 | SWCLT_DECLARE(void) swclt_enable_log_output(int default_log_level); 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 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/internal/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | typedef struct swclt_config_s { 28 | const char *private_key_path; 29 | const char *client_cert_path; 30 | const char *cert_chain_path; 31 | const char *authentication; 32 | const char *agent; 33 | const char *identity; 34 | ks_json_t *network; 35 | } swclt_config_t; 36 | 37 | KS_END_EXTERN_C 38 | 39 | /* For Emacs: 40 | * Local Variables: 41 | * mode:c 42 | * indent-tabs-mode:t 43 | * tab-width:4 44 | * c-basic-offset:4 45 | * End: 46 | * For VIM: 47 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 48 | */ 49 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/nodestore.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | struct swclt_store { 28 | ks_pool_t *pool; 29 | 30 | // callbacks keyed by netcast command, pointing to value of callback to call 31 | ks_hash_t *callbacks; 32 | 33 | /* Hash of nodes keyed by their nodeid. They point to a Node 34 | * class which contains their certified status. */ 35 | ks_hash_t *routes; 36 | 37 | /* Hash keyed by identity mapped to nodeid */ 38 | ks_hash_t *identities; 39 | 40 | /* Last index position we selected for random protocol gathering */ 41 | uint32_t last_random_protocol_idx; 42 | 43 | /* Hash of protocols, keyed by the protocol name, each protocol 44 | * contains channels. */ 45 | ks_hash_t *protocols; 46 | 47 | /* Hash of Subscription objects, keyed by their protocol name. */ 48 | ks_hash_t *subscriptions; 49 | 50 | /* Hash of authorities, keyed by their node uuid. */ 51 | ks_hash_t *authorities; 52 | 53 | /* Hash of protocols available to uncertified clients only, keyed by protocol name */ 54 | ks_hash_t *protocols_uncertified; 55 | 56 | swclt_sess_t *sess; 57 | }; 58 | 59 | typedef struct swclt_store swclt_store_t; 60 | 61 | typedef void (*swclt_store_cb_protocol_add_t)(swclt_sess_t *sess, 62 | const char *protocol); 63 | 64 | typedef void (*swclt_store_cb_protocol_remove_t)(swclt_sess_t *sess, 65 | const char *protocol); 66 | 67 | typedef void (*swclt_store_cb_protocol_provider_add_t)(swclt_sess_t *sess, 68 | const blade_netcast_rqu_t *rqu, 69 | const blade_netcast_protocol_provider_add_param_t *params); 70 | 71 | typedef void (*swclt_store_cb_protocol_provider_remove_t)( 72 | swclt_sess_t *sess, 73 | const blade_netcast_rqu_t* rqu, 74 | const blade_netcast_protocol_provider_remove_param_t *params); 75 | 76 | typedef void (*swclt_store_cb_protocol_provider_rank_update_t)(swclt_sess_t *sess, 77 | const blade_netcast_rqu_t *rqu, 78 | const blade_netcast_protocol_provider_rank_update_param_t *params); 79 | 80 | typedef void (*swclt_store_cb_protocol_provider_data_update_t)(swclt_sess_t *sess, 81 | const blade_netcast_rqu_t *rqu, 82 | const blade_netcast_protocol_provider_data_update_param_t *params); 83 | 84 | typedef void (*swclt_store_cb_route_add_t)(swclt_sess_t *sess, 85 | const blade_netcast_rqu_t *rqu, 86 | const blade_netcast_route_add_param_t *params); 87 | 88 | typedef void (*swclt_store_cb_route_remove_t)( 89 | swclt_sess_t *sess, 90 | const blade_netcast_rqu_t* rqu, 91 | const blade_netcast_route_remove_param_t *params); 92 | 93 | typedef void (*swclt_store_cb_authority_add_t)(swclt_sess_t *sess, 94 | const blade_netcast_rqu_t *rqu, 95 | const blade_netcast_authority_add_param_t *params); 96 | 97 | typedef void (*swclt_store_cb_authority_remove_t)( 98 | swclt_sess_t *sess, 99 | const blade_netcast_rqu_t* rqu, 100 | const blade_netcast_authority_remove_param_t *params); 101 | 102 | typedef void (*swclt_store_cb_subscription_add_t)(swclt_sess_t *sess, 103 | const blade_netcast_rqu_t *rqu, 104 | const blade_netcast_subscription_add_param_t *params); 105 | 106 | typedef void (*swclt_store_cb_subscription_remove_t)( 107 | swclt_sess_t *sess, 108 | const blade_netcast_rqu_t* rqu, 109 | const blade_netcast_subscription_remove_param_t *params); 110 | 111 | typedef void (*swclt_store_cb_identity_add_t)(swclt_sess_t *sess, 112 | const blade_netcast_rqu_t *rqu, 113 | const blade_netcast_identity_add_param_t *params); 114 | 115 | typedef void (*swclt_store_cb_identity_remove_t)( 116 | swclt_sess_t *sess, 117 | const blade_netcast_rqu_t* rqu, 118 | const blade_netcast_identity_remove_param_t *params); 119 | 120 | SWCLT_DECLARE(ks_status_t) swclt_store_create(swclt_store_t **store); 121 | SWCLT_DECLARE(ks_status_t) swclt_store_destroy(swclt_store_t **store); 122 | SWCLT_DECLARE(char *) swclt_store_describe(swclt_store_t *store); 123 | SWCLT_DECLARE(ks_status_t) swclt_store_reset(swclt_store_t *store); 124 | SWCLT_DECLARE(ks_status_t) swclt_store_populate(swclt_store_t *store, const blade_connect_rpl_t *connect_rpl); 125 | SWCLT_DECLARE(ks_status_t) swclt_store_update(swclt_store_t *store, const blade_netcast_rqu_t *netcast_rqu); 126 | SWCLT_DECLARE(ks_status_t) swclt_store_get_node_identities(swclt_store_t *store, const char *nodeid, ks_pool_t *pool, ks_hash_t **identities); 127 | SWCLT_DECLARE(ks_status_t) swclt_store_get_protocols(swclt_store_t *store, ks_json_t **protocols); 128 | SWCLT_DECLARE(ks_status_t) swclt_store_check_protocol(swclt_store_t *store, const char *name); 129 | 130 | SWCLT_DECLARE(ks_status_t) swclt_store_select_random_protocol_provider( 131 | swclt_store_t *store, 132 | const char *name, 133 | ks_pool_t *pool, 134 | char **providerid); 135 | 136 | SWCLT_DECLARE(ks_status_t) swclt_store_get_protocol_providers( 137 | swclt_store_t *store, 138 | const char *name, 139 | ks_json_t **providers); 140 | 141 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_route_add(swclt_store_t *store, swclt_store_cb_route_add_t cb); 142 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_route_remove(swclt_store_t *store, swclt_store_cb_route_remove_t cb); 143 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_identity_add(swclt_store_t *store, swclt_store_cb_identity_add_t cb); 144 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_identity_remove(swclt_store_t *store, swclt_store_cb_identity_remove_t cb); 145 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_protocol_add(swclt_store_t *store, swclt_store_cb_protocol_add_t cb); 146 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_protocol_remove(swclt_store_t *store, swclt_store_cb_protocol_remove_t cb); 147 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_protocol_provider_add(swclt_store_t *store, swclt_store_cb_protocol_provider_add_t cb); 148 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_protocol_provider_remove(swclt_store_t *store, swclt_store_cb_protocol_provider_remove_t cb); 149 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_protocol_provider_rank_update(swclt_store_t *store, swclt_store_cb_protocol_provider_rank_update_t cb); 150 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_protocol_provider_data_update(swclt_store_t *store, swclt_store_cb_protocol_provider_data_update_t cb); 151 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_authority_add(swclt_store_t *store, swclt_store_cb_authority_add_t cb); 152 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_authority_remove(swclt_store_t *store, swclt_store_cb_authority_remove_t cb); 153 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_subscription_add(swclt_store_t *store, swclt_store_cb_subscription_add_t cb); 154 | SWCLT_DECLARE(ks_status_t) swclt_store_cb_subscription_remove(swclt_store_t *store, swclt_store_cb_subscription_remove_t cb); 155 | 156 | KS_END_EXTERN_C 157 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/pmethod.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | /** 26 | * A pmethod is a registered execution handler bound to a protocol and channel. 27 | * Unlike some other aspects of protocols, an execution handler need not register 28 | * the protocol as a provider, nor does the protocol need to exist. Two nodes 29 | * may execute between eachother without either of these constructs in place. 30 | */ 31 | 32 | KS_BEGIN_EXTERN_C 33 | 34 | typedef ks_status_t (*swclt_pmethod_cb_t)( 35 | swclt_sess_t *sess, 36 | swclt_cmd_t *cmd, 37 | const blade_execute_rqu_t *rqu, void *cb_data); 38 | 39 | /** 40 | * swclt_pmethod_cb_t - This context structure is held in a session and is keyed by the protocol 41 | * and channel. 42 | */ 43 | typedef struct swclt_pmethod_ctx_s { 44 | swclt_pmethod_cb_t cb; 45 | void *cb_data; 46 | } swclt_pmethod_ctx_t; 47 | 48 | KS_END_EXTERN_C 49 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/signalwire/provisioning.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | typedef struct signalwire_provisioning_configure_response_s { 26 | ks_json_t *configuration; 27 | } signalwire_provisioning_configure_response_t; 28 | 29 | SWCLT_JSON_MARSHAL_BEG(SIGNALWIRE_PROVISIONING_CONFIGURE_RESPONSE, signalwire_provisioning_configure_response_t) 30 | SWCLT_JSON_MARSHAL_ITEM(configuration) 31 | SWCLT_JSON_MARSHAL_END() 32 | 33 | SWCLT_JSON_DESTROY_BEG(SIGNALWIRE_PROVISIONING_CONFIGURE_RESPONSE, signalwire_provisioning_configure_response_t) 34 | SWCLT_JSON_DESTROY_ITEM(configuration) 35 | SWCLT_JSON_DESTROY_END() 36 | 37 | SWCLT_JSON_PARSE_BEG(SIGNALWIRE_PROVISIONING_CONFIGURE_RESPONSE, signalwire_provisioning_configure_response_t) 38 | SWCLT_JSON_PARSE_ITEM(configuration) 39 | SWCLT_JSON_PARSE_END() 40 | 41 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/signalwire/signalwire.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 "signalwire-client-c/signalwire/provisioning.h" 26 | 27 | /* For Emacs: 28 | * Local Variables: 29 | * mode:c 30 | * indent-tabs-mode:t 31 | * tab-width:4 32 | * c-basic-offset:4 33 | * End: 34 | * For VIM: 35 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 36 | */ 37 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/ssl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | SWCLT_DECLARE(ks_status_t) swclt_ssl_create_context(const char *private_key_path, const char *client_cert_path, const char *cert_chain_path, SSL_CTX **sslP); 28 | SWCLT_DECLARE(void) swclt_ssl_destroy_context(SSL_CTX **ctx); 29 | 30 | KS_END_EXTERN_C 31 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/subscription.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | typedef struct swclt_sess swclt_sess_t; 28 | 29 | typedef struct swclt_sub swclt_sub_t; 30 | 31 | typedef void (*swclt_sub_cb_t)( 32 | swclt_sess_t *sess, 33 | blade_broadcast_rqu_t *rqu, 34 | void *cb_data); 35 | 36 | /* A subscription represents a logical registration of 37 | * a listener on a channel */ 38 | struct swclt_sub { 39 | const char *protocol; 40 | const char *channel; 41 | 42 | swclt_sub_cb_t cb; 43 | 44 | void *cb_data; 45 | }; 46 | 47 | 48 | SWCLT_DECLARE(ks_status_t) swclt_sub_create( 49 | swclt_sub_t **sub, 50 | ks_pool_t *pool, 51 | const char * const protocol, 52 | const char * const channel, 53 | swclt_sub_cb_t cb, 54 | void *data); 55 | 56 | SWCLT_DECLARE(ks_status_t) swclt_sub_invoke(swclt_sub_t *sub, swclt_sess_t *sess, blade_broadcast_rqu_t *broadcast_rqu); 57 | SWCLT_DECLARE(char *) swclt_sub_describe(swclt_sub_t *sub); 58 | SWCLT_DECLARE(ks_status_t) swclt_sub_destroy(swclt_sub_t **sub); 59 | 60 | KS_END_EXTERN_C 61 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/transport/frame.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | typedef struct swclt_frame { 26 | /* Raw data read from the socket */ 27 | ks_size_t len; 28 | uint8_t *data; 29 | 30 | /* The operation code for the socket */ 31 | kws_opcode_t opcode; 32 | } swclt_frame_t; 33 | 34 | KS_BEGIN_EXTERN_C 35 | 36 | SWCLT_DECLARE(ks_status_t) swclt_frame_alloc(swclt_frame_t **frame, ks_pool_t *pool); 37 | 38 | SWCLT_DECLARE(ks_status_t) swclt_frame_to_json(swclt_frame_t *frame, ks_json_t **json); 39 | 40 | SWCLT_DECLARE(ks_status_t) swclt_frame_copy_data(swclt_frame_t *frame, ks_pool_t *pool, void *data, ks_size_t len, kws_opcode_t opcode); 41 | SWCLT_DECLARE(ks_status_t) swclt_frame_get_data(swclt_frame_t *frame, void **data, ks_size_t *len, kws_opcode_t *opcode); 42 | 43 | KS_END_EXTERN_C 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 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/transport/websocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 | typedef struct swclt_wss swclt_wss_t; 28 | 29 | typedef ks_status_t (*swclt_wss_incoming_frame_cb_t)(swclt_wss_t *wss, swclt_frame_t **frame, void *cb_data); 30 | typedef ks_status_t (*swclt_wss_failed_cb_t)(swclt_wss_t *wss, void *cb_data); 31 | 32 | /* Define our info structure */ 33 | typedef struct swclt_wss_info_s { 34 | char address[128]; /* tcp address string (no port) */ 35 | char cipher[128]; /* negotiated ssl cipher name */ 36 | uint16_t port; /* port we are connected to */ 37 | char path[128]; /* endpoint path */ 38 | uint32_t connect_timeout_ms; /* our connect timeout */ 39 | SSL_CTX *ssl; /* ssl context handed to us at first connect attempt */ 40 | } swclt_wss_info_t; 41 | 42 | typedef struct swclt_wss_stats { 43 | int64_t read_frames; 44 | int64_t write_frames; 45 | } swclt_wss_stats_t; 46 | 47 | struct swclt_wss { 48 | 49 | ks_pool_t *pool; 50 | 51 | int failed; 52 | 53 | /* Callback for when the reader reads a new frame */ 54 | swclt_wss_incoming_frame_cb_t incoming_frame_cb; 55 | void *incoming_frame_cb_data; 56 | 57 | /* Callback for when the websocket fails */ 58 | swclt_wss_failed_cb_t failed_cb; 59 | void *failed_cb_data; 60 | 61 | /* Information concerning our connection */ 62 | swclt_wss_info_t info; 63 | 64 | /* Raw socket from libks */ 65 | ks_socket_t socket; 66 | 67 | /* Resolved address structure */ 68 | ks_sockaddr_t addr; 69 | 70 | /* Web socket from libks */ 71 | kws_t *wss; 72 | 73 | /* Ping management */ 74 | ks_time_t ping_next_time_sec; 75 | 76 | /* We keep a read frame around and re-use its data buffer */ 77 | swclt_frame_t *read_frame; 78 | 79 | /* Our final status for our read thread, and its thread context 80 | * for thread control (e.g. stop requests) */ 81 | ks_status_t reader_status; 82 | ks_thread_t *reader_thread; 83 | 84 | ks_mutex_t *wss_mutex; 85 | swclt_wss_stats_t stats; 86 | }; 87 | 88 | SWCLT_DECLARE(ks_status_t) swclt_wss_connect( 89 | swclt_wss_t **wss, 90 | swclt_wss_incoming_frame_cb_t incoming_frame_cb, 91 | void *incoming_frame_cb_data, 92 | swclt_wss_failed_cb_t failed_cb, 93 | void *failed_cb_data, 94 | const char *address, 95 | short port, 96 | const char *path, 97 | uint32_t timeout_ms, 98 | const SSL_CTX *ssl); 99 | 100 | SWCLT_DECLARE(void) swclt_wss_destroy(swclt_wss_t **wss); 101 | 102 | SWCLT_DECLARE(ks_status_t) swclt_wss_write(swclt_wss_t *wss, char *data); 103 | SWCLT_DECLARE(ks_status_t) swclt_wss_get_info(swclt_wss_t *wss, swclt_wss_info_t *info); 104 | SWCLT_DECLARE(char *) swclt_wss_describe(swclt_wss_t *ctx); 105 | SWCLT_DECLARE(void) swclt_wss_get_stats(swclt_wss_t *ctx, swclt_wss_stats_t *stats); 106 | 107 | KS_END_EXTERN_C 108 | 109 | /* For Emacs: 110 | * Local Variables: 111 | * mode:c 112 | * indent-tabs-mode:t 113 | * tab-width:4 114 | * c-basic-offset:4 115 | * End: 116 | * For VIM: 117 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 118 | */ 119 | -------------------------------------------------------------------------------- /inc/signalwire-client-c/version.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 SIGNALWIRE_CLIENT_C_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ 26 | #define SIGNALWIRE_CLIENT_C_VERSION_MINOR @PROJECT_VERSION_MINOR@ 27 | 28 | 29 | /* For Emacs: 30 | * Local Variables: 31 | * mode:c 32 | * indent-tabs-mode:t 33 | * tab-width:4 34 | * c-basic-offset:4 35 | * End: 36 | * For VIM: 37 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 38 | */ 39 | -------------------------------------------------------------------------------- /scan_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd /__w/signalwire-c/signalwire-c 3 | sed -i '/cotire/d' ./CMakeLists.txt 4 | sed -i '/cotire/d' ./swclt_test/CMakeLists.txt 5 | mkdir -p scan-build 6 | scan-build-7 -o ./scan-build/ cmake . 7 | scan-build-7 -o ./scan-build/ make -j`nproc --all` |& tee ./scan-build-result.txt 8 | exitstatus=${PIPESTATUS[0]} 9 | echo "*** Exit status is $exitstatus"; 10 | export SubString="scan-build: No bugs found"; 11 | export COMPILATION_FAILED=false; 12 | export BUGS_FOUND=false; 13 | if [ "0" -ne $exitstatus ] ; then 14 | export COMPILATION_FAILED=true; 15 | echo MESSAGE="compilation failed" >> $GITHUB_OUTPUT; 16 | fi 17 | export RESULTFILE="/__w/signalwire-c/signalwire-c/scan-build-result.txt"; 18 | cat $RESULTFILE; 19 | if ! grep -sq "$SubString" $RESULTFILE; then 20 | export BUGS_FOUND=true; 21 | echo MESSAGE="found bugs" >> $GITHUB_OUTPUT; 22 | fi 23 | echo "COMPILATION_FAILED=$COMPILATION_FAILED" >> $GITHUB_OUTPUT; 24 | echo "BUGS_FOUND=$BUGS_FOUND" >> $GITHUB_OUTPUT; 25 | if [ "0" -ne $exitstatus ] || ! grep -sq "$SubString" $RESULTFILE; then 26 | exit 1; 27 | fi 28 | exit 0; -------------------------------------------------------------------------------- /signalwire_client.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@PC_PREFIX@ 2 | exec_prefix=${prefix} 3 | libdir=${prefix}/lib 4 | includedir=${prefix}/include/signalwire-client-c2 5 | definitions=@PC_DEFINITIONS@ 6 | 7 | Name: @PACKAGE_NAME@ 8 | Version: @PACKAGE_VERSION@ 9 | Description: SignalWire C Client SDK 10 | 11 | Cflags: -I${includedir} 12 | Libs: -L${libdir} -lsignalwire_client2 13 | -------------------------------------------------------------------------------- /src/init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 "signalwire-client-c/client.h" 24 | 25 | SWCLT_DECLARE(ks_status_t) swclt_init(int default_log_level) 26 | { 27 | ks_status_t status; 28 | 29 | if (status = ks_init()) 30 | return status; 31 | 32 | swclt_enable_log_output(default_log_level); 33 | 34 | return status; 35 | } 36 | 37 | SWCLT_DECLARE(ks_status_t) swclt_shutdown(void) 38 | { 39 | return ks_shutdown(); 40 | } 41 | 42 | SWCLT_DECLARE(void) swclt_enable_log_output(int default_log_level) 43 | { 44 | ks_global_set_log_level(default_log_level); 45 | } 46 | -------------------------------------------------------------------------------- /src/ssl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 "signalwire-client-c/client.h" 24 | 25 | SWCLT_DECLARE(ks_status_t) swclt_ssl_create_context(const char *private_key_path, const char *client_cert_path, const char *cert_chain_path, SSL_CTX **sslP) 26 | { 27 | const SSL_METHOD *method = NULL; 28 | SSL_CTX *ssl; 29 | 30 | #if OPENSSL_VERSION_NUMBER >= 0x10100000 31 | method = TLS_client_method(); 32 | #else 33 | method = TLSv1_2_client_method(); 34 | #endif 35 | if (!method) { 36 | ks_log(KS_LOG_ERROR, "Failed to allocate method, returning status: %lu", KS_STATUS_NO_MEM); 37 | return KS_STATUS_NO_MEM; 38 | } 39 | 40 | if (!(ssl = SSL_CTX_new(method))) { 41 | ks_log(KS_LOG_ERROR, "Failed to allocate ssl context returning status: %lu", KS_STATUS_NO_MEM); 42 | return KS_STATUS_NO_MEM; 43 | } 44 | 45 | SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2); 46 | SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3); 47 | SSL_CTX_set_options(ssl, SSL_OP_NO_TLSv1); 48 | SSL_CTX_set_options(ssl, SSL_OP_NO_TLSv1_1); 49 | 50 | SSL_CTX_set_options(ssl, SSL_OP_NO_COMPRESSION); 51 | 52 | if (cert_chain_path) { 53 | if (!SSL_CTX_use_certificate_chain_file(ssl, cert_chain_path)) { 54 | SSL_CTX_free(ssl); 55 | ks_log(KS_LOG_WARNING, "Failed to load ssl certificate chain: %s", cert_chain_path); 56 | return KS_STATUS_INVALID_ARGUMENT; 57 | } 58 | if (!SSL_CTX_load_verify_locations(ssl, cert_chain_path, NULL)) { 59 | ks_log(KS_LOG_WARNING, "Failed to verify ssl certificate chain: %s", cert_chain_path); 60 | SSL_CTX_free(ssl); 61 | return KS_STATUS_INVALID_ARGUMENT; 62 | } 63 | } 64 | 65 | if (private_key_path && client_cert_path) { 66 | if (!SSL_CTX_use_certificate_file(ssl, client_cert_path, SSL_FILETYPE_PEM)) { 67 | ks_log(KS_LOG_ERROR, "SSL certificate file error: %s", client_cert_path); 68 | SSL_CTX_free(ssl); 69 | return KS_STATUS_INVALID_ARGUMENT; 70 | } 71 | 72 | if (!SSL_CTX_use_PrivateKey_file(ssl, private_key_path, SSL_FILETYPE_PEM)) { 73 | ks_log(KS_LOG_ERROR, "SSL private key file error: %s", private_key_path); 74 | SSL_CTX_free(ssl); 75 | return KS_STATUS_INVALID_ARGUMENT; 76 | } 77 | 78 | if (!SSL_CTX_check_private_key(ssl)) { 79 | ks_log(KS_LOG_ERROR, "SSL failed to verify private key file error: %s", private_key_path); 80 | SSL_CTX_free(ssl); 81 | return KS_STATUS_INVALID_ARGUMENT; 82 | } 83 | 84 | SSL_CTX_set_cipher_list(ssl,"HIGH:!DSS:!aNULL@STRENGTH"); 85 | } 86 | 87 | *sslP = ssl; 88 | 89 | ks_log(KS_LOG_DEBUG, "Successfully created ssl context"); 90 | 91 | return KS_STATUS_SUCCESS; 92 | } 93 | 94 | SWCLT_DECLARE(void) swclt_ssl_destroy_context(SSL_CTX **ctx) 95 | { 96 | if (!ctx || !*ctx) 97 | return; 98 | 99 | SSL_CTX_free(*ctx); 100 | *ctx = NULL; 101 | } 102 | -------------------------------------------------------------------------------- /src/subscription.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 "signalwire-client-c/client.h" 24 | 25 | SWCLT_DECLARE(ks_status_t) swclt_sub_destroy(swclt_sub_t **subP) 26 | { 27 | if (subP && *subP) { 28 | swclt_sub_t *sub = *subP; 29 | *subP = NULL; 30 | ks_pool_free(&sub->protocol); 31 | ks_pool_free(&sub->channel); 32 | } 33 | return KS_STATUS_SUCCESS; 34 | } 35 | 36 | SWCLT_DECLARE(char *) swclt_sub_describe(swclt_sub_t *sub) 37 | { 38 | return ks_psprintf(NULL, "SWCLT Subscription to protocol: %s channel: %s", sub->protocol, sub->channel); 39 | } 40 | 41 | SWCLT_DECLARE(ks_status_t) swclt_sub_create( 42 | swclt_sub_t **subP, 43 | ks_pool_t *pool, 44 | const char * const protocol, 45 | const char * const channel, 46 | swclt_sub_cb_t cb, 47 | void *cb_data) 48 | { 49 | ks_status_t status = KS_STATUS_SUCCESS; 50 | 51 | swclt_sub_t *sub = ks_pool_alloc(pool, sizeof(swclt_sub_t)); 52 | *subP = sub; 53 | 54 | if (!(sub->protocol = ks_pstrdup(NULL, protocol))) { 55 | status = KS_STATUS_NO_MEM; 56 | goto done; 57 | } 58 | 59 | if (!(sub->channel = ks_pstrdup(NULL, channel))) { 60 | status = KS_STATUS_NO_MEM; 61 | goto done; 62 | } 63 | 64 | sub->cb = cb; 65 | sub->cb_data = cb_data; 66 | 67 | done: 68 | if (status) { 69 | swclt_sub_destroy(subP); 70 | } 71 | 72 | return status; 73 | } 74 | 75 | SWCLT_DECLARE(ks_status_t) swclt_sub_invoke( 76 | swclt_sub_t *sub, 77 | swclt_sess_t *sess, 78 | blade_broadcast_rqu_t *broadcast_rqu) 79 | { 80 | sub->cb(sess, broadcast_rqu, sub->cb_data); 81 | return KS_STATUS_SUCCESS; 82 | } 83 | -------------------------------------------------------------------------------- /src/transport/frame.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-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 | 23 | #include "signalwire-client-c/client.h" 24 | 25 | 26 | static ks_status_t __to_json(swclt_frame_t *frame, ks_json_t **json) 27 | { 28 | if (!(*json = ks_json_parse(frame->data))) { 29 | ks_log(KS_LOG_WARNING, "Failed to parse json"); 30 | return KS_STATUS_INVALID_ARGUMENT; 31 | } 32 | 33 | return KS_STATUS_SUCCESS; 34 | } 35 | 36 | static ks_status_t __copy_data(swclt_frame_t *frame, ks_pool_t *pool, void *data, ks_size_t len, kws_opcode_t opcode) 37 | { 38 | if (!data || opcode == WSOC_INVALID) { 39 | ks_log(KS_LOG_ERROR, "Unable to copy data because: len = %lu, opcode = %d\n", len, opcode); 40 | return KS_STATUS_INVALID_ARGUMENT; 41 | } 42 | 43 | frame->len = 0; 44 | frame->opcode = -1; 45 | 46 | // Note kws returns a size that does not include the final null so account for that here 47 | if (len > 0) { 48 | if (frame->data) { 49 | if (!(frame->data = ks_pool_resize(frame->data, len + 1))) 50 | return KS_STATUS_NO_MEM; 51 | } else { 52 | if (!pool) pool = ks_pool_get(frame); 53 | if (!(frame->data = ks_pool_alloc(pool, len + 1))) 54 | return KS_STATUS_NO_MEM; 55 | } 56 | memcpy(frame->data, data, len + 1); 57 | } 58 | 59 | frame->opcode = opcode; 60 | frame->len = len; 61 | return KS_STATUS_SUCCESS; 62 | } 63 | 64 | static void swclt_frame_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t type) 65 | { 66 | swclt_frame_t *frame = (swclt_frame_t *)ptr; 67 | if (frame->data) ks_pool_free(&frame->data); 68 | } 69 | 70 | /** 71 | * Allocates a frame, wrapped in a handle. A frame is a context used 72 | * for reading and writing into a kws socket. 73 | */ 74 | SWCLT_DECLARE(ks_status_t) swclt_frame_alloc(swclt_frame_t **frame, ks_pool_t *pool) 75 | { 76 | if (frame) { 77 | *frame = ks_pool_alloc(pool, sizeof(swclt_frame_t)); 78 | ks_pool_set_cleanup(*frame, NULL, swclt_frame_cleanup); 79 | return KS_STATUS_SUCCESS; 80 | } 81 | return KS_STATUS_INVALID_ARGUMENT; 82 | } 83 | 84 | /** 85 | * swclt_frame_to_json - Converts the json in the frame, and returns a copy which 86 | * the owner must release. 87 | */ 88 | SWCLT_DECLARE(ks_status_t) swclt_frame_to_json(swclt_frame_t *frame, ks_json_t **json) 89 | { 90 | return __to_json(frame, json); 91 | } 92 | 93 | SWCLT_DECLARE(ks_status_t) swclt_frame_copy_data(swclt_frame_t *frame, ks_pool_t *pool, void *data, ks_size_t len, kws_opcode_t opcode) 94 | { 95 | return __copy_data(frame, pool, data, len, opcode); 96 | } 97 | 98 | SWCLT_DECLARE(ks_status_t) swclt_frame_get_data(swclt_frame_t *frame, void **data, ks_size_t *len, kws_opcode_t *opcode) 99 | { 100 | *data = frame->data; 101 | *len = frame->len; 102 | *opcode = frame->opcode; 103 | return KS_STATUS_SUCCESS; 104 | } 105 | 106 | /* For Emacs: 107 | * Local Variables: 108 | * mode:c 109 | * indent-tabs-mode:t 110 | * tab-width:4 111 | * c-basic-offset:4 112 | * End: 113 | * For VIM: 114 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 115 | */ 116 | -------------------------------------------------------------------------------- /swclient.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": {} 8 | } -------------------------------------------------------------------------------- /swclt_test.cfg: -------------------------------------------------------------------------------- 1 | test: 2 | { 3 | target_identity = "blade://switchblade:2100"; 4 | }; 5 | 6 | signalwire_client: 7 | { 8 | transport: 9 | { 10 | wss: 11 | { 12 | ssl: 13 | { 14 | key = "./ca/intermediate/private/controller@freeswitch-upstream.key.pem"; 15 | cert = "./ca/intermediate/certs/controller@freeswitch-upstream.cert.pem"; 16 | chain = "./ca/intermediate/certs/ca-chain.cert.pem"; 17 | }; 18 | }; 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /swclt_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Our core file list 2 | file(GLOB swclt_test_deps [LIST_DIRECTORIES false] 3 | ${CMAKE_CURRENT_LIST_DIR}/*.h 4 | ${CMAKE_CURRENT_LIST_DIR}/*.c 5 | ${CMAKE_CURRENT_LIST_DIR}/cases/*.c 6 | ${CMAKE_CURRENT_LIST_DIR}/cases/*.h 7 | ${CMAKE_CURRENT_LIST_DIR}/util/*.h 8 | ) 9 | 10 | if (KS_PLAT_WIN) 11 | source_group(TREE ${CMAKE_CURRENT_LIST_DIR} FILES ${swclt_test_deps}) 12 | endif() 13 | 14 | add_executable( 15 | swclt_test 16 | ${swclt_test_deps} 17 | ) 18 | 19 | # Link to signal-wire-client/catch/LibPal 20 | target_link_libraries(swclt_test signalwire_client2) 21 | 22 | # Define our exports symbol to key any definitions to toggle the visibility type 23 | set_target_properties(signalwire_client2 PROPERTIES DEFINE_SYMBOL SWCLT_EXPORTS) 24 | 25 | # Register our tests with cmake 26 | add_test(swclt_test swclt_test) 27 | 28 | # Include our root 29 | target_include_directories( 30 | swclt_test 31 | PUBLIC 32 | ${CMAKE_CURRENT_LIST_DIR} 33 | ) 34 | 35 | # Copy the config files to the build dir 36 | # configure_file(cfg/swclt_test.cfg ${CMAKE_BINARY_DIR}/swclt_test.cfg COPYONLY) 37 | 38 | # When debugging on windows, the cwd will be the binary dir (where the config files are) 39 | set_target_properties(swclt_test PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) 40 | set(COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES 1) 41 | 42 | set_target_properties(swclt_test PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE) 43 | set_target_properties(swclt_test PROPERTIES COTIRE_ENABLE_PRECOMPILED_HEADER TRUE) 44 | set_target_properties(swclt_test PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "swclt_test.h") 45 | cotire(swclt_test) 46 | -------------------------------------------------------------------------------- /swclt_test/cases/command.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 "swclt_test.h" 24 | 25 | void test_command_properties(ks_pool_t *pool) 26 | { 27 | swclt_cmd_t *cmd; 28 | uint32_t flags; 29 | const char *method; 30 | SWCLT_CMD_TYPE type; 31 | ks_json_t *request; 32 | 33 | request = ks_json_create_object(); 34 | ks_json_add_string_to_object(request, "bobo_key", "bobo_val"); 35 | REQUIRE(request != NULL); 36 | 37 | REQUIRE(!swclt_cmd_create(&cmd, "bobo_method", &request, 5000, 5)); 38 | REQUIRE(cmd); 39 | REQUIRE(cmd->flags == 1); /* bitfields will imit it to known values */ 40 | 41 | REQUIRE(cmd->method); 42 | REQUIRE(!strcmp(cmd->method, "bobo_method")); 43 | 44 | REQUIRE(cmd->type == SWCLT_CMD_TYPE_REQUEST); 45 | swclt_cmd_destroy(&cmd); 46 | } 47 | 48 | void test_command(ks_pool_t *pool) 49 | { 50 | test_command_properties(pool); 51 | } 52 | -------------------------------------------------------------------------------- /swclt_test/cases/connection.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 "swclt_test.h" 24 | 25 | #include "../../src/connection.c" 26 | 27 | static uint32_t g_protocol_response_cb_called; 28 | 29 | static ks_status_t __on_incoming_cmd(swclt_conn_t *conn, swclt_cmd_t *cmd, void *cb_data) 30 | { 31 | printf("ON INCOMING COMMAND\n"); 32 | return KS_STATUS_SUCCESS; 33 | } 34 | 35 | static void __on_protocol_timeout_response(swclt_cmd_reply_t *reply, void *cb_data) 36 | { 37 | REQUIRE(reply); 38 | REQUIRE(reply->type == SWCLT_CMD_TYPE_FAILURE); 39 | REQUIRE(reply->failure_reason); 40 | REQUIRE(reply->failure_status == KS_STATUS_TIMEOUT); 41 | printf("Validated failure code, message: %s\n", reply->failure_reason); 42 | swclt_cmd_reply_destroy(&reply); 43 | g_protocol_response_cb_called++; 44 | } 45 | 46 | static void __on_protocol_result_response(swclt_cmd_reply_t *reply, void *cb_data) 47 | { 48 | REQUIRE(swclt_cmd_reply_ok(reply) == KS_STATUS_SUCCESS); 49 | swclt_cmd_reply_destroy(&reply); 50 | g_protocol_response_cb_called++; 51 | } 52 | 53 | void test_async(ks_pool_t *pool) 54 | { 55 | swclt_cmd_t *cmd; 56 | SSL_CTX *ssl = create_ssl_context(); 57 | swclt_conn_t *conn; 58 | ks_json_t *channels; 59 | int i; 60 | 61 | REQUIRE(!swclt_conn_connect(&conn, __on_incoming_cmd, NULL, &g_target_ident, NULL, NULL, NULL, NULL, ssl)); 62 | 63 | channels = ks_json_create_array(); 64 | ks_json_add_item_to_array(channels, BLADE_CHANNEL_MARSHAL(&(blade_channel_t){"a_channel", 0, 0})); 65 | 66 | /* Create an async command (bogus command but will generate a reply at least) */ 67 | REQUIRE(cmd = CREATE_BLADE_PROTOCOL_PROVIDER_ADD_CMD_ASYNC( 68 | __on_protocol_result_response, 69 | NULL, 70 | "a_protocol", 71 | 0, 72 | 0, 73 | 0, 74 | NULL, 75 | &channels, 76 | 1, 77 | NULL)); 78 | 79 | /* And submit it */ 80 | REQUIRE(!swclt_conn_submit_request(conn, &cmd, NULL)); 81 | 82 | /* Wait for it to respond */ 83 | for (i = 0; i < 5 && g_protocol_response_cb_called == 0; i++) { 84 | ks_sleep_ms(1000); 85 | } 86 | REQUIRE(g_protocol_response_cb_called == 1); 87 | swclt_cmd_destroy(&cmd); 88 | swclt_conn_destroy(&conn); 89 | swclt_ssl_destroy_context(&ssl); 90 | } 91 | 92 | void test_ttl(ks_pool_t *pool) 93 | { 94 | SSL_CTX *ssl = create_ssl_context(); 95 | swclt_conn_t *conn; 96 | swclt_cmd_t *cmd; 97 | SWCLT_CMD_TYPE cmd_type; 98 | ks_json_t *channels; 99 | int i; 100 | 101 | g_protocol_response_cb_called = 0; 102 | 103 | REQUIRE(!swclt_conn_connect(&conn, __on_incoming_cmd, NULL, &g_target_ident, NULL, NULL, NULL, NULL, ssl)); 104 | 105 | channels = ks_json_create_array(); 106 | ks_json_add_item_to_array(channels, BLADE_CHANNEL_MARSHAL(&(blade_channel_t){"b_channel", 0, 0})); 107 | REQUIRE(cmd = CREATE_BLADE_PROTOCOL_PROVIDER_ADD_CMD_ASYNC( 108 | __on_protocol_timeout_response, 109 | NULL, 110 | "b_protocol", 111 | 0, 112 | 0, 113 | 0, 114 | NULL, 115 | &channels, 116 | 1, 117 | NULL)); 118 | 119 | /* Lock the reader so we never get a response, forcing a timeout */ 120 | REQUIRE(cmd->response_ttl_ms == BLADE_PROTOCOL_TTL_MS); 121 | REQUIRE(cmd->flags == BLADE_PROTOCOL_FLAGS); 122 | REQUIRE(!ks_mutex_lock(conn->wss->wss_mutex)); 123 | 124 | /* And submit it */ 125 | REQUIRE(!swclt_conn_submit_request(conn, &cmd, NULL)); 126 | 127 | /* Wait for it to respond */ 128 | for (i = 0; i < 7 && g_protocol_response_cb_called == 0; i++) { 129 | ks_sleep_ms(1000); 130 | } 131 | 132 | REQUIRE(g_protocol_response_cb_called == 1); 133 | 134 | /* Don't forget to unlock the poor websocket reader */ 135 | REQUIRE(!ks_mutex_unlock(conn->wss->wss_mutex)); 136 | 137 | swclt_cmd_destroy(&cmd); 138 | swclt_conn_destroy(&conn); 139 | swclt_ssl_destroy_context(&ssl); 140 | } 141 | 142 | void test_ttl_heap(ks_pool_t *pool) 143 | { 144 | swclt_ttl_tracker_t *ttl = NULL; 145 | ttl_tracker_create(pool, &ttl, NULL); 146 | if (ttl->thread) { 147 | ks_thread_request_stop(ttl->thread); 148 | ks_thread_join(ttl->thread); 149 | ks_thread_destroy(&ttl->thread); // don't want it 150 | } 151 | 152 | int i; 153 | int min = INT_MAX; 154 | for (i = 0; i < 100; i++) { 155 | ks_uuid_t uuid = { 0 }; 156 | ks_uuid(&uuid); 157 | int expiry = rand(); 158 | if (expiry < min) { 159 | min = expiry; 160 | } 161 | if (ttl_heap_insert(ttl, expiry, uuid) != KS_STATUS_SUCCESS) { 162 | printf("Failed to insert UUID = %s, TTL = %d, min = %d, root = %d, count = %d\n", ks_uuid_thr_str(&uuid), expiry, min, ttl->heap[TTL_HEAP_ROOT].expiry, ttl->count); 163 | } else { 164 | printf("Insert UUID = %s, TTL = %d, min = %d, root = %d, count = %d\n", ks_uuid_thr_str(&uuid), expiry, min, ttl->heap[TTL_HEAP_ROOT].expiry, ttl->count); 165 | } 166 | REQUIRE(ttl->heap[TTL_HEAP_ROOT].expiry == min); 167 | } 168 | 169 | min = 0; 170 | while (ttl->count) { 171 | REQUIRE(ttl->heap[TTL_HEAP_ROOT].expiry > 0); 172 | printf("Remove UUID = %s, TTL = %d, count = %d\n", ks_uuid_thr_str(&ttl->heap[TTL_HEAP_ROOT].id), ttl->heap[TTL_HEAP_ROOT].expiry, ttl->count); 173 | REQUIRE(ttl->heap[TTL_HEAP_ROOT].expiry >= min); 174 | min = ttl->heap[TTL_HEAP_ROOT].expiry; 175 | ttl_heap_remove(ttl); 176 | } 177 | 178 | ttl_tracker_destroy(&ttl); 179 | } 180 | 181 | void test_connection(ks_pool_t *pool) 182 | { 183 | test_async(pool); 184 | test_ttl(pool); 185 | test_ttl_heap(pool); 186 | } 187 | -------------------------------------------------------------------------------- /swclt_test/cases/execute.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2022 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 "swclt_test.h" 24 | 25 | static void __on_session_state_provider(swclt_sess_t *sess, void *condV) 26 | { 27 | ks_cond_t *cond = (ks_cond_t *)condV; 28 | if (sess->state == SWCLT_STATE_ONLINE) { 29 | ks_json_t *channels = ks_json_create_array(); 30 | swclt_sess_protocol_provider_add(sess, 31 | "test", 32 | BLADE_ACL_SYSTEM, // rpc execute 33 | BLADE_ACL_SYSTEM, // channel subscribe 34 | BLADE_ACL_SYSTEM, // channel broadcast 35 | NULL, // method access overrides 36 | &channels, 37 | 3, 38 | NULL, 39 | NULL); 40 | 41 | swclt_sess_metric_register(sess, "test", 30, 9); 42 | } else if (sess->state == SWCLT_STATE_OFFLINE) { 43 | // Disconnected 44 | } 45 | 46 | /* Notify the waiting test of the state change */ 47 | ks_cond_lock(cond); 48 | ks_cond_broadcast(cond); 49 | ks_cond_unlock(cond); 50 | } 51 | 52 | static void __on_session_state(swclt_sess_t *sess, void *condV) 53 | { 54 | /* Notify the waiting test of the state change */ 55 | ks_cond_t *cond = (ks_cond_t *)condV; 56 | ks_cond_lock(cond); 57 | ks_cond_broadcast(cond); 58 | ks_cond_unlock(cond); 59 | } 60 | 61 | static ks_status_t __on_incoming_test_execute_rqu(swclt_sess_t *sess, swclt_cmd_t *cmd, const blade_execute_rqu_t *rqu, void *data) 62 | { 63 | /* Formulate a response */ 64 | ks_cond_t *cond = (ks_cond_t *)data; 65 | ks_json_t *result = ks_json_create_object(); 66 | ks_json_add_string_to_object(result, "reply", "i got it!"); 67 | 68 | ks_json_t *cmd_result = BLADE_EXECUTE_RPL_MARSHAL( 69 | &(blade_execute_rpl_t){ 70 | rqu->requester_nodeid, 71 | rqu->responder_nodeid, 72 | result}); 73 | 74 | REQUIRE(!swclt_cmd_set_result(cmd, &cmd_result)); 75 | 76 | return KS_STATUS_SUCCESS; 77 | } 78 | 79 | 80 | static ks_status_t __on_incoming_test_execute_rqu_slow(swclt_sess_t *sess, swclt_cmd_t *cmd, const blade_execute_rqu_t *rqu, void *data) 81 | { 82 | /* Formulate a response */ 83 | ks_cond_t *cond = (ks_cond_t *)data; 84 | ks_json_t *result = ks_json_create_object(); 85 | ks_json_add_string_to_object(result, "reply", "pong!"); 86 | 87 | ks_json_t *cmd_result = BLADE_EXECUTE_RPL_MARSHAL( 88 | &(blade_execute_rpl_t){ 89 | rqu->requester_nodeid, 90 | rqu->responder_nodeid, 91 | result}); 92 | 93 | ks_sleep_ms(1000); 94 | 95 | REQUIRE(!swclt_cmd_set_result(cmd, &cmd_result)); 96 | 97 | return KS_STATUS_SUCCESS; 98 | } 99 | 100 | static void __on_outgoing_test_execute_rpl(swclt_cmd_reply_t *reply, void *cond) 101 | { 102 | ks_cond_broadcast((ks_cond_t *)cond); 103 | } 104 | 105 | void test_execute(ks_pool_t *pool) 106 | { 107 | swclt_sess_t *sess1 = NULL, *sess2 = NULL; 108 | char *nodeid1, *nodeid2; 109 | ks_cond_t *cond; 110 | const char *ident; 111 | 112 | REQUIRE(!ks_cond_create(&cond, pool)); 113 | ks_cond_lock(cond); 114 | 115 | /* Create two sessions to blade */ 116 | REQUIRE(!swclt_sess_create(&sess1, g_target_ident_str, g_certified_config)); 117 | REQUIRE(!swclt_sess_create(&sess2, g_target_ident_str, g_certified_config)); 118 | 119 | /* Get called back when they're connected */ 120 | REQUIRE(!swclt_sess_set_state_change_cb(sess1, __on_session_state, cond)); 121 | REQUIRE(!swclt_sess_set_state_change_cb(sess2, __on_session_state_provider, cond)); 122 | 123 | /* On the second session register a execute handler we'll communicate with */ 124 | REQUIRE(!swclt_sess_register_protocol_method(sess2, "test", "test.method", __on_incoming_test_execute_rqu, cond)); 125 | REQUIRE(!swclt_sess_register_protocol_method(sess2, "test", "test.slow_method", __on_incoming_test_execute_rqu_slow, cond)); 126 | 127 | /* Initiate the connect */ 128 | REQUIRE(!swclt_sess_connect(sess1)); 129 | REQUIRE(!swclt_sess_connect(sess2)); 130 | 131 | int i = 15; 132 | while (i-- > 0 && (!swclt_sess_connected(sess1) || !swclt_sess_connected(sess2))) { 133 | ks_cond_timedwait(cond, 1000); 134 | } 135 | REQUIRE(swclt_sess_connected(sess1)); 136 | REQUIRE(swclt_sess_connected(sess2)); 137 | 138 | ks_cond_unlock(cond); 139 | 140 | /* Load our nodeids for both */ 141 | REQUIRE(!swclt_sess_info(sess1, pool, NULL, &nodeid1, NULL)); 142 | REQUIRE(!swclt_sess_info(sess2, pool, NULL, &nodeid2, NULL)); 143 | 144 | /* Now execute from the first session to the second session */ 145 | ks_json_t *params = ks_json_create_object(); 146 | REQUIRE(params); 147 | ks_json_add_string_to_object(params, "arg", "value"); 148 | swclt_cmd_future_t *future = NULL; 149 | REQUIRE(!swclt_sess_execute_async(sess1, nodeid2, "test", "test.method", ¶ms, NULL, NULL, &future)); 150 | REQUIRE(future); 151 | swclt_cmd_reply_t *reply = NULL; 152 | REQUIRE(!swclt_sess_wait_for_cmd_reply(sess1, &future, &reply)); 153 | swclt_cmd_reply_destroy(&reply); 154 | 155 | /* repeat, but this time don't wait for any response */ 156 | params = ks_json_create_object(); 157 | REQUIRE(params); 158 | ks_json_add_string_to_object(params, "arg", "value"); 159 | REQUIRE(!swclt_sess_execute_async(sess1, nodeid2, "test", "test.method", ¶ms, NULL, NULL, NULL)); 160 | 161 | ks_sleep_ms(5000); 162 | 163 | /* Now execute from the first session to the second session forcing a disconnect before the response is delivered */ 164 | params = ks_json_create_object(); 165 | REQUIRE(params); 166 | ks_json_add_string_to_object(params, "arg", "value"); 167 | future = NULL; 168 | REQUIRE(!swclt_sess_execute_async(sess1, nodeid2, "test", "test.slow_method", ¶ms, NULL, NULL, &future)); 169 | REQUIRE(future); 170 | 171 | ks_sleep_ms(200); 172 | 173 | /* Disconnect server */ 174 | swclt_sess_disconnect(sess2); 175 | 176 | ks_sleep_ms(2000); 177 | 178 | /* Reconnect server */ 179 | swclt_sess_connect(sess2); 180 | 181 | reply = NULL; 182 | REQUIRE(!swclt_sess_wait_for_cmd_reply(sess1, &future, &reply)); 183 | swclt_cmd_reply_destroy(&reply); 184 | 185 | swclt_sess_destroy(&sess1); 186 | swclt_sess_destroy(&sess2); 187 | ks_cond_destroy(&cond); 188 | } 189 | -------------------------------------------------------------------------------- /swclt_test/cases/json.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 "swclt_test.h" 24 | 25 | static blade_netcast_rqu_t __netcast_protocol_provider_add_request(ks_pool_t *pool, const char *protocol, ks_uuid_t nodeid, const char *channel) 26 | { 27 | blade_netcast_rqu_t request; 28 | request.command = BLADE_NETCAST_CMD_PROTOCOL_PROVIDER_ADD; 29 | request.certified_only = KS_TRUE; 30 | request.netcaster_nodeid = ks_uuid_null_thr_str(); 31 | 32 | /* Fill in the params too */ 33 | blade_netcast_protocol_provider_add_param_t params = {0}; 34 | params.protocol = protocol; 35 | params.nodeid = ks_uuid_str(NULL, &nodeid); 36 | params.channels = ks_json_create_array(); 37 | ks_json_add_item_to_array(params.channels, BLADE_CHANNEL_MARSHAL(&(blade_channel_t){channel, BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC})); 38 | 39 | /* Marshal it into its parent request */ 40 | request.params = BLADE_NETCAST_PROTOCOL_PROVIDER_ADD_PARAM_MARSHAL(¶ms); 41 | 42 | return request; 43 | } 44 | 45 | static void test_blade_execute(ks_pool_t *pool) 46 | { 47 | ks_json_t *params = ks_json_create_object(); 48 | ks_json_add_string_to_object(params, "tag", "hi"); 49 | swclt_cmd_t *cmd = CREATE_BLADE_EXECUTE_CMD( 50 | NULL, 51 | "responder_a", 52 | "test.protocol", 53 | "test.method", 54 | ¶ms); 55 | REQUIRE(!params); 56 | 57 | char *desc; 58 | REQUIRE(!swclt_cmd_print(cmd, NULL, &desc)); 59 | ks_log(KS_LOG_INFO, "Created command: %s", desc); 60 | 61 | REQUIRE(!strcmp(ks_json_get_object_string(cmd->json, "responder_nodeid", ""), "responder_a")); 62 | REQUIRE(!strcmp(ks_json_get_object_string(cmd->json, "protocol", ""), "test.protocol")); 63 | REQUIRE(!strcmp(ks_json_get_object_string(cmd->json, "method", ""), "test.method")); 64 | REQUIRE(!strcmp(ks_json_get_object_string(ks_json_get_object_item(cmd->json, "params"), "tag", ""), "hi")); 65 | 66 | ks_pool_free(&desc); 67 | swclt_cmd_destroy(&cmd); 68 | } 69 | 70 | static void test_blade_execute_with_id(ks_pool_t *pool) 71 | { 72 | ks_json_t *params = ks_json_create_object(); 73 | ks_json_add_string_to_object(params, "tag", "hi"); 74 | swclt_cmd_t *cmd = CREATE_BLADE_EXECUTE_CMD( 75 | "a6786101-4c6e-4d1a-ac22-1c5dcbbd3c48", 76 | "responder_a", 77 | "test.protocol", 78 | "test.method", 79 | ¶ms); 80 | REQUIRE(!params); 81 | 82 | char *desc; 83 | REQUIRE(!swclt_cmd_print(cmd, NULL, &desc)); 84 | ks_log(KS_LOG_INFO, "Created command: %s", desc); 85 | 86 | REQUIRE(!strcmp(cmd->id_str, "a6786101-4c6e-4d1a-ac22-1c5dcbbd3c48")); 87 | REQUIRE(!strcmp(ks_json_get_object_string(cmd->json, "responder_nodeid", ""), "responder_a")); 88 | REQUIRE(!strcmp(ks_json_get_object_string(cmd->json, "protocol", ""), "test.protocol")); 89 | REQUIRE(!strcmp(ks_json_get_object_string(cmd->json, "method", ""), "test.method")); 90 | REQUIRE(!strcmp(ks_json_get_object_string(ks_json_get_object_item(cmd->json, "params"), "tag", ""), "hi")); 91 | 92 | ks_pool_free(&desc); 93 | swclt_cmd_destroy(&cmd); 94 | } 95 | 96 | static void test_blade_channel(ks_pool_t *pool) 97 | { 98 | ks_json_t *obj = BLADE_CHANNEL_MARSHAL(&(blade_channel_t){"bobo", BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC}); 99 | ks_json_delete(&obj); 100 | } 101 | 102 | void test_json(ks_pool_t *pool) 103 | { 104 | test_blade_channel(pool); 105 | test_blade_execute(pool); 106 | test_blade_execute_with_id(pool); 107 | } 108 | -------------------------------------------------------------------------------- /swclt_test/cases/nodestore.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 "swclt_test.h" 24 | 25 | ks_uuid_t g_route_nodeid_1, g_route_nodeid_2, g_sessionid; 26 | 27 | blade_netcast_rqu_t __netcast_protocol_provider_add_request(ks_pool_t *pool, const char *protocol, ks_uuid_t nodeid, const char *channel) 28 | { 29 | blade_netcast_rqu_t request = { 0 }; 30 | request.command = BLADE_NETCAST_CMD_PROTOCOL_PROVIDER_ADD; 31 | request.certified_only = KS_TRUE; 32 | request.netcaster_nodeid = ks_uuid_null_str(pool); 33 | 34 | /* Fill in the params too */ 35 | blade_netcast_protocol_provider_add_param_t params = { 0 }; 36 | params.protocol = protocol; 37 | params.nodeid = ks_uuid_str(pool, &nodeid); 38 | params.channels = ks_json_create_array(); 39 | ks_json_add_item_to_array(params.channels, BLADE_CHANNEL_MARSHAL(&(blade_channel_t){channel, BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC})); 40 | 41 | /* Marshal it into its parent request */ 42 | request.params = BLADE_NETCAST_PROTOCOL_PROVIDER_ADD_PARAM_MARSHAL(¶ms); 43 | 44 | return request; 45 | } 46 | 47 | blade_netcast_rqu_t __netcast_route_add_request(ks_pool_t *pool, const char *nodeid, ks_bool_t certified) 48 | { 49 | blade_netcast_rqu_t request = { 0 }; 50 | request.command = BLADE_NETCAST_CMD_ROUTE_ADD; 51 | request.certified_only = KS_TRUE; 52 | request.netcaster_nodeid = ks_uuid_null_str(pool); 53 | 54 | /* Fill in the params too */ 55 | blade_netcast_route_add_param_t params = { 0 }; 56 | params.certified = certified; 57 | params.nodeid = nodeid; 58 | 59 | /* Marshal it into its parent request */ 60 | request.params = BLADE_NETCAST_ROUTE_ADD_PARAM_MARSHAL(¶ms); 61 | 62 | return request; 63 | } 64 | 65 | blade_netcast_rqu_t __netcast_route_remove_request(ks_pool_t *pool, const char *nodeid) 66 | { 67 | blade_netcast_rqu_t request = { 0 }; 68 | request.command = BLADE_NETCAST_CMD_ROUTE_REMOVE; 69 | request.certified_only = KS_TRUE; 70 | request.netcaster_nodeid = ks_uuid_null_str(pool); 71 | 72 | /* Fill in the params too */ 73 | blade_netcast_route_remove_param_t params = { 0 }; 74 | params.nodeid = nodeid; 75 | params.certified = KS_TRUE; 76 | 77 | /* Marshal it into its parent request */ 78 | request.params = BLADE_NETCAST_ROUTE_REMOVE_PARAM_MARSHAL(¶ms); 79 | 80 | return request; 81 | } 82 | 83 | blade_connect_rpl_t *__connect_reply(ks_pool_t *pool) 84 | { 85 | ks_json_t *routes = ks_json_create_array(); 86 | ks_json_t *protocols = ks_json_create_array(); 87 | ks_json_t *subscriptions = ks_json_create_array(); 88 | 89 | /* Add a couple routes */ 90 | ks_json_add_item_to_array(routes, BLADE_NODE_MARSHAL(&(blade_node_t){ks_uuid_str(pool, &g_route_nodeid_1)})); 91 | ks_json_add_item_to_array(routes, BLADE_NODE_MARSHAL(&(blade_node_t){ks_uuid_str(pool, &g_route_nodeid_2)})); 92 | 93 | /* Add a couple protocols each with one provider and one channel */ 94 | ks_json_t *channels = ks_json_create_array(); 95 | ks_json_add_item_to_array(channels, BLADE_CHANNEL_MARSHAL(&(blade_channel_t){"bobo_channel_1", BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC})); 96 | ks_json_t *providers = ks_json_create_array(); 97 | ks_json_add_item_to_array(providers, BLADE_PROVIDER_MARSHAL(&(blade_provider_t){ks_uuid_str(pool, &g_route_nodeid_1), ks_json_create_array()})); 98 | ks_json_add_item_to_array(protocols, 99 | BLADE_PROTOCOL_MARSHAL(&(blade_protocol_t){ 100 | "bobo_protocol_1", BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC, 101 | providers, 102 | channels, 103 | })); 104 | 105 | channels = ks_json_create_array(); 106 | ks_json_add_item_to_array(channels, BLADE_CHANNEL_MARSHAL(&(blade_channel_t){"bobo_channel_2", BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC})); 107 | providers = ks_json_create_array(); 108 | ks_json_add_item_to_array(providers, BLADE_PROVIDER_MARSHAL(&(blade_provider_t){ks_uuid_str(pool, &g_route_nodeid_2), ks_json_create_array()})); 109 | ks_json_add_item_to_array(protocols, 110 | BLADE_PROTOCOL_MARSHAL(&(blade_protocol_t){ 111 | "bobo_protocol_2", BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC, 112 | providers, 113 | channels, 114 | })); 115 | 116 | /* Have the second node be subscribed to the first */ 117 | ks_json_t *nodeids = ks_json_create_array(); 118 | ks_json_add_string_to_array(nodeids, ks_uuid_str(pool, &g_route_nodeid_2)); 119 | ks_json_add_item_to_array(subscriptions, 120 | BLADE_SUBSCRIPTION_MARSHAL(&(blade_subscription_t){ 121 | "bobo_protocol_1", 122 | "bobo_channel_1", 123 | nodeids, 124 | })); 125 | 126 | /* Now compose it altogether in a connect result */ 127 | blade_connect_rpl_t reply_s = (blade_connect_rpl_t){ 128 | KS_FALSE, 129 | *ks_uuid(&g_sessionid), 130 | ks_uuid_str(pool, &g_route_nodeid_1), 131 | ks_uuid_null_str(pool), 132 | NULL, 133 | routes, 134 | protocols, 135 | subscriptions, 136 | ks_json_create_array() 137 | }; 138 | blade_connect_rpl_t *reply = ks_pool_alloc(pool, sizeof (*reply)); 139 | memcpy(reply, &reply_s, sizeof(blade_connect_rpl_t)); // copy to struct allocated off of pool so it can be destroyed 140 | return reply; 141 | } 142 | 143 | void test_nodestore_update(ks_pool_t *pool) 144 | { 145 | blade_connect_rpl_t *connect_rpl = __connect_reply(pool); 146 | swclt_store_t *store = NULL; 147 | ks_uuid_t new_route_nodeid = { 0 }; 148 | const char *new_route_nodeid_str; 149 | 150 | ks_uuid(&new_route_nodeid); 151 | new_route_nodeid_str = ks_uuid_str(pool, &new_route_nodeid); 152 | 153 | REQUIRE(!swclt_store_create(&store)); 154 | REQUIRE(!swclt_store_populate(store, connect_rpl)); 155 | 156 | /* The store should properly render the types */ 157 | REQUIRE(ks_hash_count(store->protocols) == 2); 158 | REQUIRE(ks_hash_count(store->subscriptions) == 1); 159 | REQUIRE(ks_hash_count(store->routes) == 2); 160 | REQUIRE(ks_hash_count(store->authorities) == 0); 161 | 162 | /* Now update with a new node */ 163 | blade_netcast_rqu_t netcast_rqu = __netcast_route_add_request(pool, new_route_nodeid_str, KS_TRUE); 164 | REQUIRE(!swclt_store_update(store, &netcast_rqu)); 165 | REQUIRE(ks_hash_count(store->routes) == 3); 166 | REQUIRE(((blade_node_t *)ks_hash_search(store->routes, new_route_nodeid_str, KS_UNLOCKED))->certified == KS_TRUE); 167 | ks_json_delete(&netcast_rqu.params); 168 | 169 | /* And a new provider with a new provider + channel */ 170 | netcast_rqu = __netcast_protocol_provider_add_request(pool, "bobo_protocol_new", new_route_nodeid, "bobo_channel_new"); 171 | REQUIRE(!swclt_store_update(store, &netcast_rqu)); 172 | REQUIRE(ks_hash_count(store->protocols) == 3); 173 | { 174 | blade_protocol_t *protocol = (blade_protocol_t *)ks_hash_search(store->protocols, "bobo_protocol_new", KS_UNLOCKED); 175 | REQUIRE(!strcmp(protocol->name, "bobo_protocol_new")); 176 | 177 | /* Should have one channel in it called something silly */ 178 | REQUIRE(ks_json_get_array_size(protocol->channels) == 1); 179 | 180 | { 181 | blade_channel_t *channel; 182 | REQUIRE(!BLADE_CHANNEL_PARSE(pool, ks_json_get_array_item(protocol->channels, 0), &channel)); 183 | REQUIRE(!strcmp(channel->name, "bobo_channel_new")); 184 | BLADE_CHANNEL_DESTROY(&channel); 185 | } 186 | } 187 | ks_json_delete(&netcast_rqu.params); 188 | 189 | /* And remove it, should also remove the protocol */ 190 | netcast_rqu = __netcast_route_remove_request(pool, new_route_nodeid_str); 191 | REQUIRE(!swclt_store_update(store, &netcast_rqu)); 192 | REQUIRE(ks_hash_count(store->routes) == 2); 193 | REQUIRE(ks_hash_count(store->protocols) == 2); 194 | ks_json_delete(&netcast_rqu.params); 195 | 196 | swclt_store_destroy(&store); 197 | BLADE_CONNECT_RPL_DESTROY(&connect_rpl); 198 | } 199 | 200 | void test_nodestore_protocol_select(ks_pool_t *pool) 201 | { 202 | 203 | } 204 | 205 | void test_nodestore(ks_pool_t *pool) 206 | { 207 | ks_uuid(&g_route_nodeid_1); 208 | ks_uuid(&g_route_nodeid_2); 209 | ks_uuid(&g_sessionid); 210 | 211 | test_nodestore_update(pool); 212 | test_nodestore_protocol_select(pool); 213 | } 214 | -------------------------------------------------------------------------------- /swclt_test/cases/session.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2022 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 "swclt_test.h" 23 | 24 | static ks_cond_t *g_cond; 25 | 26 | static void __on_sess_state_event(swclt_sess_t *sess, void *cb_data) 27 | { 28 | REQUIRE(!strcmp((char *)cb_data, "foo")); 29 | ks_cond_lock(g_cond); 30 | ks_cond_broadcast(g_cond); 31 | ks_cond_unlock(g_cond); 32 | } 33 | 34 | void test_session(ks_pool_t *pool) 35 | { 36 | swclt_sess_t *sess = NULL; 37 | 38 | REQUIRE(!ks_cond_create(&g_cond, NULL)); 39 | 40 | /* Load the config we expect session to load */ 41 | REQUIRE(swclt_config_get_private_key_path(g_certified_config)); 42 | REQUIRE(swclt_config_get_client_cert_path(g_certified_config)); 43 | REQUIRE(swclt_config_get_cert_chain_path(g_certified_config)); 44 | 45 | REQUIRE(!swclt_sess_create(&sess, g_target_ident_str, g_certified_config)); 46 | 47 | /* Register a monitor to get to know when session comes online successfully */ 48 | REQUIRE(!swclt_sess_set_state_change_cb(sess, __on_sess_state_event, "foo")); 49 | 50 | ks_cond_lock(g_cond); 51 | 52 | /* Now take the session onine */ 53 | REQUIRE(!swclt_sess_connect(sess)); 54 | int i = 5; 55 | while (i-- > 0 && !swclt_sess_connected(sess)) { 56 | ks_cond_timedwait(g_cond, 1000); 57 | } 58 | REQUIRE(swclt_sess_connected(sess)); 59 | 60 | /* Now disconnect the session */ 61 | REQUIRE(!swclt_sess_disconnect(sess)); 62 | i = 5; 63 | while (i-- > 0 && swclt_sess_connected(sess)) { 64 | ks_cond_timedwait(g_cond, 1000); 65 | } 66 | REQUIRE(!swclt_sess_connected(sess)); 67 | 68 | /* Go online again */ 69 | REQUIRE(!swclt_sess_connect(sess)); 70 | i = 5; 71 | while (i-- > 0 && !swclt_sess_connected(sess)) { 72 | ks_cond_timedwait(g_cond, 1000); 73 | } 74 | REQUIRE(swclt_sess_connected(sess)); 75 | 76 | ks_cond_unlock(g_cond); 77 | 78 | swclt_sess_destroy(&sess); 79 | 80 | /* Ok we're done */ 81 | ks_cond_destroy(&g_cond); 82 | } 83 | -------------------------------------------------------------------------------- /swclt_test/cases/uncert.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 "swclt_test.h" 24 | 25 | static ks_cond_t *g_cond; 26 | 27 | static void __on_sess_state_event(swclt_sess_t *sess, void *cb_data) 28 | { 29 | REQUIRE(!strcmp((char *)cb_data, "bobo")); 30 | ks_cond_lock(g_cond); 31 | ks_cond_broadcast(g_cond); 32 | ks_cond_unlock(g_cond); 33 | } 34 | 35 | void test_uncert_exp(ks_pool_t *pool) 36 | { 37 | swclt_sess_t *sess; 38 | 39 | REQUIRE(!ks_cond_create(&g_cond, NULL)); 40 | 41 | /* Load the config we expect session to load */ 42 | REQUIRE(swclt_config_get_authentication(g_uncertified_config)); 43 | 44 | REQUIRE(!swclt_sess_create(&sess, g_target_ident_str, g_uncertified_config)); 45 | 46 | /* Register a monitor to get to know when session comes online successfully */ 47 | REQUIRE(!swclt_sess_set_state_change_cb(sess, __on_sess_state_event, "bobo")); 48 | 49 | ks_cond_lock(g_cond); 50 | 51 | /* Now take the session onine */ 52 | REQUIRE(!swclt_sess_connect(sess)); 53 | int i = 5; 54 | while (i-- > 0 && !swclt_sess_connected(sess)) { 55 | ks_cond_timedwait(g_cond, 1000); 56 | } 57 | REQUIRE(swclt_sess_connected(sess)); 58 | 59 | /* Now disconnect the session */ 60 | REQUIRE(!swclt_sess_disconnect(sess)); 61 | i = 5; 62 | while (i-- > 0 && swclt_sess_connected(sess)) { 63 | ks_cond_timedwait(g_cond, 1000); 64 | } 65 | REQUIRE(!swclt_sess_connected(sess)); 66 | 67 | /* Go online again */ 68 | REQUIRE(!swclt_sess_connect(sess)); 69 | i = 5; 70 | while (i-- > 0 && !swclt_sess_connected(sess)) { 71 | ks_cond_timedwait(g_cond, 1000); 72 | } 73 | REQUIRE(swclt_sess_connected(sess)); 74 | 75 | ks_cond_unlock(g_cond); 76 | 77 | swclt_sess_destroy(&sess); 78 | 79 | /* Ok we're done */ 80 | ks_cond_destroy(&g_cond); 81 | } 82 | -------------------------------------------------------------------------------- /swclt_test/cfg/swclt_test.cfg: -------------------------------------------------------------------------------- 1 | test: 2 | { 3 | target_identity = "blade://switchblade:2100"; 4 | }; 5 | 6 | signalwire_client: 7 | { 8 | transport: 9 | { 10 | wss: 11 | { 12 | ssl: 13 | { 14 | key = "./ca/intermediate/private/controller@freeswitch-upstream.key.pem"; 15 | cert = "./ca/intermediate/certs/controller@freeswitch-upstream.cert.pem"; 16 | chain = "./ca/intermediate/certs/ca-chain.cert.pem"; 17 | }; 18 | }; 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /swclt_test/cfg/swclt_test_bad.cfg: -------------------------------------------------------------------------------- 1 | test: 2 | { 3 | target_identity = "blade://switchblade:2100"; 4 | }; 5 | 6 | signalwire_client_bad: 7 | { 8 | transport: 9 | { 10 | wss: 11 | { 12 | ssl: 13 | { 14 | key = "./ca/intermediate/private/controller@freeswitch-upstream.key.pem"; 15 | cert = "./ca/intermediate/certs/controller@freeswitch-upstream.cert.pem"; 16 | chain = "./ca/intermediate/certs/ca-chain.cert.pem"; 17 | }; 18 | }; 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /swclt_test/cfg/swclt_testuncert.cfg: -------------------------------------------------------------------------------- 1 | test: 2 | { 3 | target_identity = "blade://switchblade:2100"; 4 | }; 5 | 6 | signalwire_client: 7 | { 8 | authentication: "{ \"project\": \"06f784c6-6bd5-47fb-9897-407d66551333\", \"token\": \"PT2eddbccd77832e761d191513df8945d4e1bf70e8f3f74aaa\" }"; 9 | transport: 10 | { 11 | wss: 12 | { 13 | ssl: 14 | { 15 | chain = "./ca/intermediate/certs/ca-chain.cert.pem"; 16 | }; 17 | }; 18 | }; 19 | }; 20 | -------------------------------------------------------------------------------- /swclt_test/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 "swclt_test.h" 23 | 24 | DECLARE_TEST(json); 25 | DECLARE_TEST(command); 26 | DECLARE_TEST(execute); 27 | DECLARE_TEST(connection); 28 | DECLARE_TEST(session); 29 | DECLARE_TEST(nodestore); 30 | DECLARE_TEST(uncert_exp); 31 | 32 | test_entry_t g_test_methods[] = { 33 | TEST_ENTRY(json), 34 | TEST_ENTRY(command), 35 | TEST_ENTRY(execute), 36 | TEST_ENTRY(connection), 37 | TEST_ENTRY(session), 38 | TEST_ENTRY(nodestore), 39 | TEST_ENTRY(uncert_exp), 40 | }; 41 | 42 | static ks_spinlock_t g_log_lock; 43 | const test_entry_t *g_current_test; 44 | swclt_config_t *g_certified_config; 45 | swclt_config_t *g_uncertified_config; 46 | swclt_ident_t g_target_ident; 47 | const char *g_target_ident_str; 48 | 49 | static void __set_current_test(const test_entry_t *test_entry) 50 | { 51 | ks_spinlock_acquire(&g_log_lock); 52 | g_current_test = test_entry; 53 | ks_spinlock_release(&g_log_lock); 54 | } 55 | 56 | static void __test_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) 57 | { 58 | va_list ap; 59 | char *data; 60 | static char log_line[1024]; 61 | 62 | va_start(ap, fmt); 63 | 64 | ks_vasprintf(&data, fmt, ap); 65 | 66 | ks_spinlock_acquire(&g_log_lock); 67 | if (g_current_test) 68 | ks_snprintf(log_line, sizeof(log_line) - 2, "[TEST - %s] %s", g_current_test->name, data); 69 | else 70 | ks_snprintf(log_line, sizeof(log_line) - 2, "%s", data); 71 | 72 | if (log_line[strlen(log_line) - 1] != '\n') 73 | strcat(log_line, "\n"); 74 | 75 | printf("%s", log_line); 76 | #if KS_PLAT_WIN 77 | OutputDebugStringA(log_line); 78 | #endif 79 | fflush(stdout); 80 | 81 | free(data); 82 | 83 | ks_spinlock_release(&g_log_lock); 84 | 85 | va_end(ap); 86 | } 87 | 88 | void execute_test(const test_entry_t *entry) 89 | { 90 | __set_current_test(entry); 91 | 92 | ks_pool_t *pool; 93 | REQUIRE(!ks_pool_open(&pool)); 94 | 95 | entry->method(pool); 96 | 97 | REQUIRE(!ks_pool_close(&pool)); 98 | 99 | __set_current_test(NULL); 100 | } 101 | 102 | void list_tests() 103 | { 104 | printf("\n"); 105 | for (int i = 0; i < sizeof(g_test_methods) / sizeof(test_entry_t); i++) { 106 | printf(" %s\n", g_test_methods[i].name); 107 | } 108 | printf("\n"); 109 | } 110 | 111 | void execute_named_test(const char *name) 112 | { 113 | for (int i = 0; i < sizeof(g_test_methods) / sizeof(test_entry_t); i++) { 114 | if (strcmp(name, g_test_methods[i].name)) 115 | continue; 116 | execute_test(&g_test_methods[i]); 117 | } 118 | } 119 | 120 | void test_assertion(const char *assertion, const char *file, int line, const char *tag) 121 | { 122 | ks_abort_fmt("Test: %s failed to assert: %s at: %s:%lu (%s)", 123 | g_current_test->name, assertion, file, line, tag); 124 | } 125 | 126 | int main(int argc, char **argv) 127 | { 128 | ks_status_t status; 129 | ks_json_t *certified_config = NULL; 130 | ks_json_t *uncertified_config = NULL; 131 | 132 | if (argc == 2 && !strcmp(argv[1], "--list")) { 133 | list_tests(); 134 | exit(0); 135 | } 136 | 137 | swclt_init(KS_LOG_LEVEL_DEBUG); 138 | ks_global_set_logger(__test_logger); 139 | 140 | certified_config = ks_json_create_object(); 141 | uncertified_config = ks_json_create_object(); 142 | 143 | ks_json_add_string_to_object(certified_config, "private_key_path", "./ca/intermediate/private/controller@freeswitch-upstream.key.pem"); 144 | ks_json_add_string_to_object(certified_config, "client_cert_path", "./ca/intermediate/certs/controller@freeswitch-upstream.cert.pem"); 145 | ks_json_add_string_to_object(certified_config, "cert_chain_path", "./ca/intermediate/certs/ca-chain.cert.pem"); 146 | 147 | swclt_config_create(&g_certified_config); 148 | swclt_config_load_from_json(g_certified_config, certified_config); 149 | 150 | ks_json_add_string_to_object(uncertified_config, "authentication", "{ \"project\": \"06f784c6-6bd5-47fb-9897-407d66551333\", \"token\": \"PT2eddbccd77832e761d191513df8945d4e1bf70e8f3f74aaa\" }"); 151 | 152 | swclt_config_create(&g_uncertified_config); 153 | swclt_config_load_from_json(g_uncertified_config, uncertified_config); 154 | 155 | ks_json_delete(&certified_config); 156 | ks_json_delete(&uncertified_config); 157 | 158 | g_target_ident_str = "blade://switchblade:2100"; 159 | if (status = swclt_ident_from_str(&g_target_ident, NULL, g_target_ident_str)) { 160 | goto done; 161 | } 162 | 163 | if (argc > 1) { 164 | for (int test_selection = 1; test_selection < argc; test_selection++) { 165 | execute_named_test(argv[test_selection]); 166 | } 167 | } else { 168 | for (int i = 0; i < sizeof(g_test_methods) / sizeof(test_entry_t); i++) { 169 | const char *tail = strrchr(g_test_methods[i].name, '_'); 170 | if (tail && !strcmp(tail, "_exp")) continue; 171 | 172 | execute_test(&g_test_methods[i]); 173 | } 174 | } 175 | 176 | ks_log(KS_LOG_INFO, "ALL TESTS PASS"); 177 | 178 | done: 179 | swclt_ident_destroy(&g_target_ident); 180 | swclt_config_destroy(&g_uncertified_config); 181 | swclt_config_destroy(&g_certified_config); 182 | 183 | if (swclt_shutdown()) { 184 | printf("WARNING Shutdown was ungraceful\n"); 185 | ks_debug_break(); 186 | } 187 | return status; 188 | } 189 | -------------------------------------------------------------------------------- /swclt_test/swclt_test.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 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 signalwire-client-c */ 26 | #include "signalwire-client-c/client.h" 27 | 28 | #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L 29 | #define noreturn _Noreturn 30 | #elif defined(__GNUC__) 31 | #define noreturn __attribute__((noreturn)) 32 | #else 33 | #define noreturn __declspec(noreturn) 34 | #endif 35 | 36 | extern swclt_config_t *g_certified_config; 37 | extern swclt_config_t *g_uncertified_config; 38 | extern swclt_ident_t g_target_ident; 39 | extern const char *g_target_ident_str; 40 | 41 | noreturn void test_assertion(const char *assertion, const char *file, int line, const char *tag); 42 | 43 | #define REQUIRE(x) \ 44 | do { if (!(x)) test_assertion(#x, __FILE__, __LINE__, __PRETTY_FUNCTION__); } while (0) 45 | 46 | #define FAIL(msg) test_assertion(msg, __FILE__, __LINE__, __PRETTY_FUNCTION__) 47 | 48 | typedef void (*test_method_t)(ks_pool_t *pool); 49 | 50 | typedef struct test_entry_s { 51 | const char *name; 52 | test_method_t method; 53 | } test_entry_t; 54 | 55 | #define DECLARE_TEST(name) extern void test_##name(ks_pool_t *) 56 | #define TEST_ENTRY(name) {#name, test_##name} 57 | 58 | /* Load some utils */ 59 | #include "util/ssl.h" 60 | -------------------------------------------------------------------------------- /swclt_test/util/ssl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 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 | static inline SSL_CTX * create_ssl_context() 26 | { 27 | static const char *key = "ca/intermediate/private/client@freeswitch-upstream.key.pem"; 28 | static const char *cert = "ca/intermediate/certs/client@freeswitch-upstream.cert.pem"; 29 | static const char *chain = "ca/intermediate/certs/ca-chain.cert.pem"; 30 | SSL_CTX *ssl; 31 | 32 | REQUIRE(!swclt_ssl_create_context(key, cert, chain, &ssl)); 33 | 34 | return ssl; 35 | } 36 | -------------------------------------------------------------------------------- /swclt_test_bad.cfg: -------------------------------------------------------------------------------- 1 | test: 2 | { 3 | target_identity = "blade://switchblade:2100"; 4 | }; 5 | 6 | signalwire_client_bad: 7 | { 8 | transport: 9 | { 10 | wss: 11 | { 12 | ssl: 13 | { 14 | key = "./ca/intermediate/private/controller@freeswitch-upstream.key.pem"; 15 | cert = "./ca/intermediate/certs/controller@freeswitch-upstream.cert.pem"; 16 | chain = "./ca/intermediate/certs/ca-chain.cert.pem"; 17 | }; 18 | }; 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /swclt_testuncert.cfg: -------------------------------------------------------------------------------- 1 | test: 2 | { 3 | target_identity = "blade://switchblade:2100"; 4 | }; 5 | 6 | signalwire_client: 7 | { 8 | authentication: "{ \"project\": \"06f784c6-6bd5-47fb-9897-407d66551333\", \"token\": \"PT2eddbccd77832e761d191513df8945d4e1bf70e8f3f74aaa\" }"; 9 | transport: 10 | { 11 | wss: 12 | { 13 | ssl: 14 | { 15 | chain = "./ca/intermediate/certs/ca-chain.cert.pem"; 16 | }; 17 | }; 18 | }; 19 | }; 20 | -------------------------------------------------------------------------------- /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 | signalwire-client-c.2017.VC.db 3 | Win32/* 4 | x64/* 5 | out/* 6 | libks-*.zip 7 | libks-*/ 8 | 7za*.exe 9 | openssl-*.zip 10 | openssl-*/ 11 | Debug/ 12 | 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% signalwire-client-c.sln /p:Configuration=Debug /p:Platform=Win32 /t:Build 5 | cmd /C %msbuild% signalwire-client-c.sln /p:Configuration=Debug /p:Platform=x64 /t:Build 6 | cmd /C %msbuild% signalwire-client-c.sln /p:Configuration=Release /p:Platform=Win32 /t:Build 7 | cmd /C %msbuild% signalwire-client-c.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 | 87 | 88 | 89 | 90 | 91 | 92 | true 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /win/libks-version.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2.0.6 8 | 1 9 | 10 | 11 | true 12 | 13 | 14 | 15 | 16 | 17 | $(libksVersion) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /win/libks.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | true 10 | 11 | 12 | 13 | libks-$(libksVersion) 14 | 15 | 16 | 17 | 36 | 37 | 38 | 45 | 46 | 47 | 54 | 55 | 56 | 57 | 58 | $(libksDir)\libks\src\include;%(AdditionalIncludeDirectories) 59 | __KS_FUNC__=__FUNCSIG__;WIN32;_WINDOWS;SWCLT_VERSION_MAJOR=1;SWCLT_VERSION_MINOR=0;SWCLT_VERSION_REVISION=0;_WIN32_WINNT=0x0600;_WINSOCK_DEPRECATED_NO_WARNINGS=1;WIN32_LEAN_AND_MEAN=1;KS_PLAT_WIN=1;NOMAXMIN=1;_CRT_SECURE_NO_WARNINGS=1;SWCLT_EXPORTS;%(PreprocessorDefinitions) 60 | 61 | 62 | $(libksDir)\binaries\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories) 63 | ks.lib;%(AdditionalDependencies) 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /win/signalwire-client-c-version.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 2.0.1 8 | 1 9 | $(BaseDir)../ 10 | 11 | 12 | true 13 | 14 | 15 | 16 | 17 | 18 | $(signalwire-client-cVersion) 19 | 20 | 21 | -------------------------------------------------------------------------------- /win/signalwire-client-c.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}") = "signalwire-client-c", "signalwire-client-c.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/signalwire-client-c.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 | signalwire-client-c 23 | signalwire-client-c 24 | Win32Proj 25 | 10.0.17134.0 26 | {EFFC9BFD-DE46-47E7-9EF1-564DC87E89A8} 27 | 28 | 29 | 30 | $(DefaultPlatformToolset) 31 | x86 32 | 33 | 34 | $(DefaultPlatformToolset) 35 | x64 36 | 37 | 38 | $(DefaultPlatformToolset) 39 | x86 40 | 41 | 42 | $(DefaultPlatformToolset) 43 | x64 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | --------------------------------------------------------------------------------