├── .DEREK.yml ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── build.yaml │ └── publish.yaml ├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── docs ├── index.yaml └── mqtt-connector-0.3.1.tgz ├── go.mod ├── go.sum ├── main.go └── vendor ├── github.com ├── eclipse │ └── paho.mqtt.golang │ │ ├── .gitignore │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE │ │ ├── NOTICE.md │ │ ├── README.md │ │ ├── client.go │ │ ├── components.go │ │ ├── edl-v10 │ │ ├── epl-v20 │ │ ├── filestore.go │ │ ├── memstore.go │ │ ├── memstore_ordered.go │ │ ├── message.go │ │ ├── messageids.go │ │ ├── net.go │ │ ├── netconn.go │ │ ├── oops.go │ │ ├── options.go │ │ ├── options_reader.go │ │ ├── packets │ │ ├── connack.go │ │ ├── connect.go │ │ ├── disconnect.go │ │ ├── packets.go │ │ ├── pingreq.go │ │ ├── pingresp.go │ │ ├── puback.go │ │ ├── pubcomp.go │ │ ├── publish.go │ │ ├── pubrec.go │ │ ├── pubrel.go │ │ ├── suback.go │ │ ├── subscribe.go │ │ ├── unsuback.go │ │ └── unsubscribe.go │ │ ├── ping.go │ │ ├── router.go │ │ ├── store.go │ │ ├── token.go │ │ ├── topic.go │ │ ├── trace.go │ │ └── websocket.go ├── gorilla │ └── websocket │ │ ├── .gitignore │ │ ├── AUTHORS │ │ ├── LICENSE │ │ ├── README.md │ │ ├── client.go │ │ ├── client_clone.go │ │ ├── client_clone_legacy.go │ │ ├── compression.go │ │ ├── conn.go │ │ ├── conn_write.go │ │ ├── conn_write_legacy.go │ │ ├── doc.go │ │ ├── join.go │ │ ├── json.go │ │ ├── mask.go │ │ ├── mask_safe.go │ │ ├── prepared.go │ │ ├── proxy.go │ │ ├── server.go │ │ ├── trace.go │ │ ├── trace_17.go │ │ ├── util.go │ │ └── x_net_proxy.go └── openfaas │ ├── connector-sdk │ ├── LICENSE │ └── types │ │ ├── controller.go │ │ ├── credentials.go │ │ ├── function_list_builder.go │ │ ├── invoker.go │ │ ├── make_client.go │ │ ├── response_printer.go │ │ ├── response_subscriber.go │ │ └── topic_map.go │ └── faas-provider │ ├── LICENSE │ ├── auth │ ├── basic_auth.go │ └── credentials.go │ └── types │ ├── config.go │ ├── function_deployment.go │ ├── function_status.go │ ├── queue.go │ ├── read_config.go │ ├── requests.go │ └── secret.go ├── golang.org └── x │ ├── net │ ├── LICENSE │ ├── PATENTS │ ├── internal │ │ └── socks │ │ │ ├── client.go │ │ │ └── socks.go │ └── proxy │ │ ├── dial.go │ │ ├── direct.go │ │ ├── per_host.go │ │ ├── proxy.go │ │ └── socks5.go │ └── sync │ ├── AUTHORS │ ├── CONTRIBUTORS │ ├── LICENSE │ ├── PATENTS │ └── semaphore │ └── semaphore.go └── modules.txt /.DEREK.yml: -------------------------------------------------------------------------------- 1 | redirect: https://raw.githubusercontent.com/openfaas/faas/master/.DEREK.yml 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## My actions before raising this issue 4 | - [ ] Followed the [troubleshooting guide](https://docs.openfaas.com/deployment/troubleshooting/) 5 | - [ ] Read/searched [the docs](https://docs.openfaas.com/) 6 | - [ ] Searched [past issues](/issues) 7 | 8 | 9 | 10 | 11 | ## Expected Behaviour 12 | 13 | 14 | 15 | 16 | ## Current Behaviour 17 | 18 | 19 | 20 | 21 | ## Possible Solution 22 | 23 | 24 | 25 | 26 | ## Steps to Reproduce (for bugs) 27 | 28 | 29 | 1. 30 | 2. 31 | 3. 32 | 4. 33 | 34 | ## Context 35 | 36 | 37 | 38 | 39 | ## Your Environment 40 | 41 | * FaaS-CLI version ( Full output from: `faas-cli version` ): 42 | 43 | * Docker version `docker version` (e.g. Docker 17.0.05 ): 44 | 45 | * Are you using Docker Swarm or Kubernetes (FaaS-netes)? 46 | 47 | * Operating System and version (e.g. Linux, Windows, MacOS): 48 | 49 | * Code example or link to GitHub repo or gist to reproduce problem: 50 | 51 | * Other diagnostic information / logs from [troubleshooting guide](https://docs.openfaas.com/deployment/troubleshooting) 52 | 53 | ## Next steps 54 | 55 | You may [join Slack](https://docs.openfaas.com/community) for community support. 56 | 57 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description 4 | 5 | 6 | ## Motivation and Context 7 | 8 | 9 | - [ ] I have raised an issue to propose this change ([required](https://github.com/openfaas/faas/blob/master/CONTRIBUTING.md)) 10 | - [ ] My issue has received approval from the maintainers or lead with the `design/approved` label 11 | 12 | 13 | ## How Has This Been Tested? 14 | 15 | 16 | 17 | 18 | 19 | ## Types of changes 20 | 21 | - [ ] Bug fix (non-breaking change which fixes an issue) 22 | - [ ] New feature (non-breaking change which adds functionality) 23 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 24 | 25 | 26 | ## Checklist: 27 | 28 | 29 | - [ ] My code follows the code style of this project. 30 | - [ ] My change requires a change to the documentation. 31 | - [ ] I have updated the documentation accordingly. 32 | - [ ] I've read the [CONTRIBUTION](https://github.com/openfaas/faas/blob/master/CONTRIBUTING.md) guide 33 | - [ ] I have signed-off my commits with `git commit -s` 34 | - [ ] I have added tests to cover my changes. 35 | - [ ] All new and existing tests passed. 36 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [ '*' ] 6 | pull_request: 7 | branches: [ '*' ] 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | go-version: [1.18.x] 14 | os: [ubuntu-latest] 15 | runs-on: ${{ matrix.os }} 16 | steps: 17 | - uses: actions/checkout@master 18 | - name: Install Go 19 | uses: actions/setup-go@v2 20 | with: 21 | go-version: ${{ matrix.go-version }} 22 | - name: Set up QEMU 23 | uses: docker/setup-qemu-action@v1 24 | - name: Set up Docker Buildx 25 | uses: docker/setup-buildx-action@v1 26 | 27 | - name: Get public key 28 | id: get_pub_key 29 | run: echo "PUB_KEY=$(cat key.pub | base64 --wrap 0)" >> $GITHUB_ENV 30 | - name: Get git commit 31 | id: get_git_commit 32 | run: echo "GIT_COMMIT=$(git rev-parse HEAD)" >> $GITHUB_ENV 33 | - name: Get version 34 | id: get_version 35 | run: echo "VERSION=$(git describe --tags --dirty)" >> $GITHUB_ENV 36 | 37 | - name: Build x86_64 container into library 38 | uses: docker/build-push-action@v2 39 | with: 40 | context: . 41 | file: ./Dockerfile 42 | outputs: "type=docker,push=false" 43 | platforms: linux/amd64 44 | build-args: | 45 | GIT_COMMIT=${{env.GIT_COMMIT}} 46 | VERSION=${{env.VERSION}} 47 | tags: | 48 | ghcr.io/openfaas/mqtt-connector:${{ github.sha }} 49 | 50 | - name: Build multi-arch containers for validation only 51 | uses: docker/build-push-action@v2 52 | with: 53 | context: . 54 | file: ./Dockerfile 55 | outputs: "type=image,push=false" 56 | platforms: linux/amd64,linux/arm/v7,linux/arm64 57 | build-args: | 58 | GIT_COMMIT=${{env.GIT_COMMIT}} 59 | VERSION=${{env.VERSION}} 60 | tags: | 61 | ghcr.io/openfaas/mqtt-connector:${{ github.sha }} -------------------------------------------------------------------------------- /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: publish 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | publish: 10 | strategy: 11 | matrix: 12 | go-version: [1.18.x] 13 | os: [ubuntu-latest] 14 | runs-on: ${{ matrix.os }} 15 | steps: 16 | - uses: actions/checkout@master 17 | - name: Install Go 18 | uses: actions/setup-go@v2 19 | with: 20 | go-version: ${{ matrix.go-version }} 21 | - name: Set up QEMU 22 | uses: docker/setup-qemu-action@v1 23 | - name: Set up Docker Buildx 24 | uses: docker/setup-buildx-action@v1 25 | - name: Get TAG 26 | id: get_tag 27 | run: echo ::set-output name=TAG::${GITHUB_REF#refs/tags/} 28 | 29 | - name: Get public key 30 | id: get_pub_key 31 | run: echo "PUB_KEY=$(cat key.pub | base64 --wrap 0)" >> $GITHUB_ENV 32 | - name: Get git commit 33 | id: get_git_commit 34 | run: echo "GIT_COMMIT=$(git rev-parse HEAD)" >> $GITHUB_ENV 35 | - name: Get version 36 | id: get_version 37 | run: echo "VERSION=$(git describe --tags --dirty)" >> $GITHUB_ENV 38 | 39 | - name: Set up Docker Buildx 40 | uses: docker/setup-buildx-action@v1 41 | - name: Login to Docker Registry 42 | uses: docker/login-action@v1 43 | with: 44 | username: ${{ secrets.DOCKER_USERNAME }} 45 | password: ${{ secrets.DOCKER_PASSWORD }} 46 | registry: ghcr.io 47 | - name: Push containers 48 | uses: docker/build-push-action@v2 49 | with: 50 | context: . 51 | file: ./Dockerfile 52 | outputs: "type=registry,push=true" 53 | platforms: linux/amd64,linux/arm/v7,linux/arm64 54 | build-args: | 55 | GIT_COMMIT=${{env.GIT_COMMIT}} 56 | VERSION=${{env.VERSION}} 57 | tags: | 58 | ghcr.io/openfaas/mqtt-connector:${{ github.sha }} 59 | ghcr.io/openfaas/mqtt-connector:${{ steps.get_tag.outputs.TAG }} 60 | ghcr.io/openfaas/mqtt-connector:latest 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /mqtt-connector 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/openfaas/license-check:0.4.0 as license-check 2 | 3 | FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.18 as build 4 | 5 | ARG GIT_COMMIT 6 | ARG VERSION 7 | 8 | ARG TARGETPLATFORM 9 | ARG BUILDPLATFORM 10 | ARG TARGETOS 11 | ARG TARGETARCH 12 | 13 | ENV CGO_ENABLED=0 14 | ENV GO111MODULE=on 15 | ENV GOFLAGS=-mod=vendor 16 | 17 | 18 | COPY --from=license-check /license-check /usr/bin/ 19 | 20 | WORKDIR /go/src/github.com/openfaas/mqtt-connector 21 | COPY . . 22 | 23 | RUN license-check -path /go/src/github.com/openfaas/mqtt-connector/ --verbose=false "Alex Ellis" "OpenFaaS Author(s)" 24 | RUN gofmt -l -d $(find . -type f -name '*.go' -not -path "./vendor/*") 25 | RUN CGO_ENABLED=${CGO_ENABLED} GOOS=${TARGETOS} GOARCH=${TARGETARCH} go test -v ./... 26 | 27 | RUN echo ${GIT_COMMIT} ${VERSION} 28 | RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=${CGO_ENABLED} go build \ 29 | -mod=vendor \ 30 | --ldflags "-s -w -X 'github.com/openfaas/mqtt-connector/version.GitCommit=${GIT_COMMIT}' -X 'github.com/openfaas/mqtt-connector/version.Version=${VERSION}'" \ 31 | -a -installsuffix cgo -o mqtt-connector 32 | 33 | FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine:3.14 as ship 34 | LABEL org.label-schema.license="MIT" \ 35 | org.label-schema.vcs-url="https://github.com/openfaas/mqtt-connector" \ 36 | org.label-schema.vcs-type="Git" \ 37 | org.label-schema.name="openfaas/mqtt-connector-pro" \ 38 | org.label-schema.vendor="openfaas" \ 39 | org.label-schema.docker.schema-version="1.0" 40 | 41 | RUN apk --no-cache add \ 42 | ca-certificates 43 | 44 | RUN addgroup -S app \ 45 | && adduser -S -g app app 46 | 47 | WORKDIR /home/app 48 | 49 | ENV http_proxy "" 50 | ENV https_proxy "" 51 | 52 | COPY --from=build /go/src/github.com/openfaas/mqtt-connector/mqtt-connector /usr/bin/ 53 | RUN chown -R app:app ./ 54 | 55 | USER app 56 | 57 | CMD ["/usr/bin/mqtt-connector"] 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 OpenFaaS Author(s) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build push manifest test verify-codegen charts 2 | TAG?=latest 3 | NAMESPACE?=openfaas 4 | 5 | # docker manifest command will work with Docker CLI 18.03 or newer 6 | # but for now it's still experimental feature so we need to enable that 7 | export DOCKER_CLI_EXPERIMENTAL=enabled 8 | 9 | build: 10 | docker build -t $(NAMESPACE)/mqtt-connector:$(TAG)-amd64 . -f Dockerfile 11 | docker build --build-arg OPTS="GOARCH=arm64" -t $(NAMESPACE)/mqtt-connector:$(TAG)-arm64 . -f Dockerfile 12 | docker build --build-arg OPTS="GOARCH=arm GOARM=6" -t $(NAMESPACE)/mqtt-connector:$(TAG)-armhf . -f Dockerfile 13 | 14 | push: 15 | docker push $(NAMESPACE)/mqtt-connector:$(TAG)-amd64 16 | docker push $(NAMESPACE)/mqtt-connector:$(TAG)-arm64 17 | docker push $(NAMESPACE)/mqtt-connector:$(TAG)-armhf 18 | 19 | manifest: 20 | docker manifest create --amend $(NAMESPACE)/mqtt-connector:$(TAG) \ 21 | $(NAMESPACE)/mqtt-connector:$(TAG)-amd64 \ 22 | $(NAMESPACE)/mqtt-connector:$(TAG)-arm64 \ 23 | $(NAMESPACE)/mqtt-connector:$(TAG)-armhf 24 | docker manifest annotate $(NAMESPACE)/mqtt-connector:$(TAG) $(NAMESPACE)/mqtt-connector:$(TAG)-arm64 --os linux --arch arm64 25 | docker manifest annotate $(NAMESPACE)/mqtt-connector:$(TAG) $(NAMESPACE)/mqtt-connector:$(TAG)-armhf --os linux --arch arm --variant v6 26 | docker manifest push -p $(NAMESPACE)/mqtt-connector:$(TAG) 27 | 28 | test: 29 | go test ./... 30 | 31 | charts: 32 | cd chart && helm package mqtt-connector 33 | mv chart/*.tgz docs/ 34 | helm repo index docs --url https://openfaas.github.io/mqtt-connector/ --merge ./docs/index.yaml 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## mqtt-connector 2 | 3 | This is an MQTT connector for OpenFaaS. 4 | 5 | [![build](https://github.com/openfaas/mqtt-connector/actions/workflows/build.yaml/badge.svg)](https://github.com/openfaas/mqtt-connector/actions/workflows/build.yaml) 6 | 7 | ## About 8 | 9 | Once configured and deployed it will deliver messages from selected topics to OpenFaaS functions. 10 | 11 | There are various other connectors available for OpenFaaS which form ["triggers"](https://docs.openfaas.com/reference/triggers/) for event-driven architectures. 12 | 13 | Prior work: 14 | 15 | This is inspired by prior work by [Alex Ellis](https://www.alexellis.io): [Collect, plot and analyse sensor readings from your IoT devices with OpenFaaS](https://github.com/alexellis/iot-sensors-mqtt-openfaas) 16 | 17 | Component parts: 18 | 19 | * [connector-sdk](https://github.com/openfaas/connector-sdk/blob/) from OpenFaaS 20 | * The Eclipse provides [a test broker](https://mosquitto.org) 21 | * Eclipse's [paho.mqtt.golang package](https://github.com/eclipse/paho.mqtt.golang) provides the connection to MQTT. 22 | 23 | ## Deploy in-cluster with Kubernetes 24 | 25 | See [helm chart](https://github.com/openfaas/faas-netes/tree/master/chart/mqtt-connector) for deployment instructions. Then continue at "Test the connector". 26 | 27 | ```sh 28 | export TAG=0.3.1 29 | 30 | make build push 31 | ``` 32 | 33 | ## Deploy out of cluster 34 | 35 | ```sh 36 | go build 37 | 38 | export GATEWAY_PASSWORD="" 39 | export BROKER="tcp://test.mosquitto.org:1883" 40 | export TOPIC="openfaas-sensor-data" 41 | 42 | ./mqtt-connector --gateway http://127.0.0.1:8080 \ 43 | --broker $BROKER \ 44 | --gw-username admin \ 45 | --gw-password $GATEWAY_PASSWORD \ 46 | --topic $TOPIC 47 | ``` 48 | 49 | Deploy a function: 50 | 51 | ```bash 52 | faas-cli deploy --name echo --image ghcr.io/openfaas/alpine:latest \ 53 | --fprocess=cat \ 54 | --annotation topic="openfaas-sensor-data" 55 | ```` 56 | 57 | ## Test the connector 58 | 59 | Annotate a function with the annotation `topic: $TOPIC` <- where `$TOPIC` is the MQTT topic you care about. 60 | 61 | ```sh 62 | 2019/12/03 16:43:26 Topic: topic Broker: tcp://test.mosquitto.org:1883 63 | 2019/12/03 16:43:29 Invoking (http://192.168.0.35:8080) on topic: "topic", value: "{\"sensor\": \"s1\", \"humidity\": \"52.09\", \"temp\": \"23.200\", \"ip\": \"192.168.0.40\", \"vdd33\": \"65535\", \"rssi\": -45}" 64 | 2019/12/03 16:43:29 Invoke function: print-out 65 | Send: "{\"sensor\": \"s1\", \"humidity\": \"52.09\", \"temp\": \"23.200\", \"ip\": \"192.168.0.40\", \"vdd33\": \"65535\", \"rssi\": -45}" 66 | 2019/12/03 16:43:29 connector-sdk got result: [200] topic => print-out (24) bytes 67 | [200] topic => print-out 68 | {"temperature":"23.200"} 69 | 2019/12/03 16:43:29 tester got result: [200] topic => print-out (24) bytes 70 | ``` 71 | 72 | This data was generated on the topic `topic` by my NodeMCU device which publishes sensor data. 73 | 74 | A `node12` function named `print-out` returned the temperature as reported. 75 | 76 | ## License 77 | 78 | MIT 79 | -------------------------------------------------------------------------------- /docs/index.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | entries: 3 | mqtt-connector: 4 | - apiVersion: v1 5 | created: "2020-05-27T14:30:56.405111+01:00" 6 | description: Connect OpenFaaS functions to MQTT 7 | digest: c3c03ec97ffeb8875e3a61d2eeb2da6629c4ea421e5ad5f249200f18f4374437 8 | home: https://www.openfaas.com 9 | icon: https://raw.githubusercontent.com/openfaas/media/master/OpenFaaS_logo_stacked_opaque.png 10 | keywords: 11 | - functions 12 | - service 13 | - kafka 14 | maintainers: 15 | - email: alex@openfaas.com 16 | name: alexellis 17 | - email: roesler.lucas@gmail.com 18 | name: lucasroesler 19 | name: mqtt-connector 20 | sources: 21 | - https://github.com/openfaas/mqtt-connector 22 | urls: 23 | - https://openfaas.github.io/mqtt-connector/mqtt-connector-0.3.1.tgz 24 | version: 0.3.1 25 | generated: "2020-05-27T14:30:56.404181+01:00" 26 | -------------------------------------------------------------------------------- /docs/mqtt-connector-0.3.1.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openfaas/mqtt-connector/a89941d89b08ab7ccd24b5661720f10cf269872d/docs/mqtt-connector-0.3.1.tgz -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/openfaas/mqtt-connector 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/eclipse/paho.mqtt.golang v1.4.1 7 | github.com/openfaas/connector-sdk v0.6.7 8 | github.com/openfaas/faas-provider v0.19.0 9 | ) 10 | 11 | require ( 12 | github.com/gorilla/websocket v1.4.2 // indirect 13 | golang.org/x/net v0.7.0 // indirect 14 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s) 2019. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package main 5 | 6 | import ( 7 | "flag" 8 | "fmt" 9 | "log" 10 | "net/http" 11 | "os" 12 | "strings" 13 | "time" 14 | 15 | MQTT "github.com/eclipse/paho.mqtt.golang" 16 | "github.com/openfaas/connector-sdk/types" 17 | "github.com/openfaas/faas-provider/auth" 18 | ) 19 | 20 | func main() { 21 | var ( 22 | gatewayUsername string 23 | gatewayPassword string 24 | gatewayFlag string 25 | trimChannelKey bool 26 | asyncInvoke bool 27 | topic string 28 | broker string 29 | ) 30 | 31 | flag.StringVar(&gatewayUsername, "gw-username", "admin", "Username for the gateway") 32 | flag.StringVar(&gatewayPassword, "gw-password", "", "Password for gateway") 33 | flag.StringVar(&gatewayFlag, "gateway", "", "gateway") 34 | flag.BoolVar(&trimChannelKey, "trim-channel-key", false, "Trim channel key when using emitter.io MQTT broker") 35 | flag.BoolVar(&asyncInvoke, "async-invoke", false, "Invoke via queueing using NATS and the function's async endpoint") 36 | flag.StringVar(&topic, "topic", "", "The topic name to/from which to publish/subscribe") 37 | flag.StringVar(&broker, "broker", "tcp://test.mosquitto.org:1883", "The broker URI. ex: tcp://test.mosquitto.org:1883") 38 | 39 | password := flag.String("password", "", "The password (optional)") 40 | user := flag.String("user", "", "The User (optional)") 41 | id := flag.String("id", "testgoid", "The ClientID (optional)") 42 | cleansess := flag.Bool("clean", false, "Set Clean Session (default false)") 43 | qos := flag.Int("qos", 0, "The Quality of Service 0,1,2 (default 0)") 44 | 45 | flag.Parse() 46 | 47 | var creds *auth.BasicAuthCredentials 48 | if len(gatewayPassword) > 0 { 49 | creds = &auth.BasicAuthCredentials{ 50 | User: gatewayUsername, 51 | Password: gatewayPassword, 52 | } 53 | } else { 54 | creds = types.GetCredentials() 55 | } 56 | 57 | contentType := "application/json" 58 | if v, exists := os.LookupEnv("content_type"); exists && len(v) > 0 { 59 | contentType = v 60 | } 61 | 62 | gatewayURL := os.Getenv("gateway_url") 63 | 64 | if len(gatewayFlag) > 0 { 65 | gatewayURL = gatewayFlag 66 | } 67 | 68 | if len(gatewayURL) == 0 { 69 | log.Panicln(`a value must be set for env "gatewayURL" or via the -gateway flag for your OpenFaaS gateway`) 70 | return 71 | } 72 | 73 | config := &types.ControllerConfig{ 74 | RebuildInterval: time.Millisecond * 1000, 75 | GatewayURL: gatewayURL, 76 | PrintResponse: true, 77 | PrintResponseBody: true, 78 | TopicAnnotationDelimiter: ",", 79 | AsyncFunctionInvocation: asyncInvoke, 80 | ContentType: contentType, 81 | } 82 | 83 | log.Printf("Topic: %q\tBroker: %q\n", topic, broker) 84 | log.Printf("Gateway: %s\tAsync: %v\n", gatewayURL, asyncInvoke) 85 | 86 | controller := types.NewController(creds, config) 87 | 88 | receiver := ResponseReceiver{} 89 | controller.Subscribe(&receiver) 90 | 91 | controller.BeginMapBuilder() 92 | 93 | opts := MQTT.NewClientOptions() 94 | opts.AddBroker(broker) 95 | opts.SetClientID(*id) 96 | opts.SetUsername(*user) 97 | opts.SetPassword(*password) 98 | opts.SetCleanSession(*cleansess) 99 | 100 | receiveCount := 0 101 | msgCh := make(chan [2]string) 102 | 103 | opts.SetDefaultPublishHandler(func(client MQTT.Client, msg MQTT.Message) { 104 | log.Printf("Message incoming") 105 | msgCh <- [2]string{msg.Topic(), string(msg.Payload())} 106 | }) 107 | 108 | opts.SetOnConnectHandler(func(client MQTT.Client) { 109 | log.Printf("Connected to %s", broker) 110 | 111 | if token := client.Subscribe(topic, byte(*qos), nil); token.Wait() && token.Error() != nil { 112 | fmt.Println(token.Error()) 113 | os.Exit(1) 114 | } 115 | log.Printf("Subscribed to topic: %s", topic) 116 | }) 117 | 118 | client := MQTT.NewClient(opts) 119 | if token := client.Connect(); token.Wait() && token.Error() != nil { 120 | panic(token.Error()) 121 | } 122 | log.Printf("Connection requested for broker: %s", broker) 123 | 124 | go func() { 125 | for { 126 | incoming := <-msgCh 127 | 128 | topic := incoming[0] 129 | data := []byte(incoming[1]) 130 | 131 | if trimChannelKey { 132 | log.Printf("Topic before trim: %s", topic) 133 | index := strings.Index(topic, "/") 134 | topic = topic[index+1:] 135 | } 136 | 137 | log.Printf("Invoking (%s) on topic: %q, value: %q", gatewayURL, topic, data) 138 | 139 | controller.Invoke(topic, &data, http.Header{}) 140 | 141 | receiveCount++ 142 | } 143 | 144 | client.Disconnect(1250) 145 | }() 146 | 147 | select {} 148 | } 149 | 150 | // ResponseReceiver enables connector to receive results from the 151 | // function invocation 152 | type ResponseReceiver struct { 153 | } 154 | 155 | // Response is triggered by the controller when a message is 156 | // received from the function invocation 157 | func (ResponseReceiver) Response(res types.InvokerResponse) { 158 | if res.Error != nil { 159 | log.Printf("tester got error: %s", res.Error.Error()) 160 | } else { 161 | log.Printf("tester got result: [%d] %s => %s (%d) bytes", res.Status, res.Topic, res.Function, len(*res.Body)) 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | 24 | *.msg 25 | *.lok 26 | 27 | samples/trivial 28 | samples/trivial2 29 | samples/sample 30 | samples/reconnect 31 | samples/ssl 32 | samples/custom_store 33 | samples/simple 34 | samples/stdinpub 35 | samples/stdoutsub 36 | samples/routing -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to Paho 2 | ==================== 3 | 4 | Thanks for your interest in this project. 5 | 6 | Project description: 7 | -------------------- 8 | 9 | The Paho project has been created to provide scalable open-source implementations of open and standard messaging protocols aimed at new, existing, and emerging applications for Machine-to-Machine (M2M) and Internet of Things (IoT). 10 | Paho reflects the inherent physical and cost constraints of device connectivity. Its objectives include effective levels of decoupling between devices and applications, designed to keep markets open and encourage the rapid growth of scalable Web and Enterprise middleware and applications. Paho is being kicked off with MQTT publish/subscribe client implementations for use on embedded platforms, along with corresponding server support as determined by the community. 11 | 12 | - https://projects.eclipse.org/projects/technology.paho 13 | 14 | Developer resources: 15 | -------------------- 16 | 17 | Information regarding source code management, builds, coding standards, and more. 18 | 19 | - https://projects.eclipse.org/projects/technology.paho/developer 20 | 21 | Contributor License Agreement: 22 | ------------------------------ 23 | 24 | Before your contribution can be accepted by the project, you need to create and electronically sign the Eclipse Foundation Contributor License Agreement (CLA). 25 | 26 | - http://www.eclipse.org/legal/CLA.php 27 | 28 | Contributing Code: 29 | ------------------ 30 | 31 | The Go client is developed in Github, see their documentation on the process of forking and pull requests; https://help.github.com/categories/collaborating-on-projects-using-pull-requests/ 32 | 33 | Git commit messages should follow the style described here; 34 | 35 | http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html 36 | 37 | Contact: 38 | -------- 39 | 40 | Contact the project developers via the project's "dev" list. 41 | 42 | - https://dev.eclipse.org/mailman/listinfo/paho-dev 43 | 44 | Search for bugs: 45 | ---------------- 46 | 47 | This project uses Github issues to track ongoing development and issues. 48 | 49 | - https://github.com/eclipse/paho.mqtt.golang/issues 50 | 51 | Create a new bug: 52 | ----------------- 53 | 54 | Be sure to search for existing bugs before you create another one. Remember that contributions are always welcome! 55 | 56 | - https://github.com/eclipse/paho.mqtt.golang/issues 57 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/NOTICE.md: -------------------------------------------------------------------------------- 1 | # Notices for paho.mqtt.golang 2 | 3 | This content is produced and maintained by the Eclipse Paho project. 4 | 5 | * Project home: https://www.eclipse.org/paho/ 6 | 7 | Note that a [separate mqtt v5 client](https://github.com/eclipse/paho.golang) also exists (this is a full rewrite 8 | and deliberately incompatible with this library). 9 | 10 | ## Trademarks 11 | 12 | Eclipse Mosquitto trademarks of the Eclipse Foundation. Eclipse, and the 13 | Eclipse Logo are registered trademarks of the Eclipse Foundation. 14 | 15 | Paho is a trademark of the Eclipse Foundation. Eclipse, and the Eclipse Logo are 16 | registered trademarks of the Eclipse Foundation. 17 | 18 | ## Copyright 19 | 20 | All content is the property of the respective authors or their employers. 21 | For more information regarding authorship of content, please consult the 22 | listed source code repository logs. 23 | 24 | ## Declared Project Licenses 25 | 26 | This program and the accompanying materials are made available under the terms of the 27 | Eclipse Public License v2.0 and Eclipse Distribution License v1.0 which accompany this 28 | distribution. 29 | 30 | The Eclipse Public License is available at 31 | https://www.eclipse.org/legal/epl-2.0/ 32 | and the Eclipse Distribution License is available at 33 | http://www.eclipse.org/org/documents/edl-v10.php. 34 | 35 | For an explanation of what dual-licensing means to you, see: 36 | https://www.eclipse.org/legal/eplfaq.php#DUALLIC 37 | 38 | SPDX-License-Identifier: EPL-2.0 or BSD-3-Clause 39 | 40 | ## Source Code 41 | 42 | The project maintains the following source code repositories: 43 | 44 | * https://github.com/eclipse/paho.mqtt.golang 45 | 46 | ## Third-party Content 47 | 48 | This project makes use of the follow third party projects. 49 | 50 | Go Programming Language and Standard Library 51 | 52 | * License: BSD-style license (https://golang.org/LICENSE) 53 | * Project: https://golang.org/ 54 | 55 | Go Networking 56 | 57 | * License: BSD 3-Clause style license and patent grant. 58 | * Project: https://cs.opensource.google/go/x/net 59 | 60 | Go Sync 61 | 62 | * License: BSD 3-Clause style license and patent grant. 63 | * Project: https://cs.opensource.google/go/x/sync/ 64 | 65 | Gorilla Websockets v1.4.2 66 | 67 | * License: BSD 2-Clause "Simplified" License 68 | * Project: https://github.com/gorilla/websocket 69 | 70 | ## Cryptography 71 | 72 | Content may contain encryption software. The country in which you are currently 73 | may have restrictions on the import, possession, and use, and/or re-export to 74 | another country, of encryption software. BEFORE using any encryption software, 75 | please check the country's laws, regulations and policies concerning the import, 76 | possession, or use, and re-export of encryption software, to see if this is 77 | permitted. -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/components.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | */ 18 | 19 | package mqtt 20 | 21 | type component string 22 | 23 | // Component names for debug output 24 | const ( 25 | NET component = "[net] " 26 | PNG component = "[pinger] " 27 | CLI component = "[client] " 28 | DEC component = "[decode] " 29 | MES component = "[message] " 30 | STR component = "[store] " 31 | MID component = "[msgids] " 32 | TST component = "[test] " 33 | STA component = "[state] " 34 | ERR component = "[error] " 35 | ROU component = "[router] " 36 | ) 37 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/edl-v10: -------------------------------------------------------------------------------- 1 | 2 | Eclipse Distribution License - v 1.0 3 | 4 | Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. 5 | 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 9 | 10 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 11 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 15 | 16 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/memstore.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | */ 18 | 19 | package mqtt 20 | 21 | import ( 22 | "sync" 23 | 24 | "github.com/eclipse/paho.mqtt.golang/packets" 25 | ) 26 | 27 | // MemoryStore implements the store interface to provide a "persistence" 28 | // mechanism wholly stored in memory. This is only useful for 29 | // as long as the client instance exists. 30 | type MemoryStore struct { 31 | sync.RWMutex 32 | messages map[string]packets.ControlPacket 33 | opened bool 34 | } 35 | 36 | // NewMemoryStore returns a pointer to a new instance of 37 | // MemoryStore, the instance is not initialized and ready to 38 | // use until Open() has been called on it. 39 | func NewMemoryStore() *MemoryStore { 40 | store := &MemoryStore{ 41 | messages: make(map[string]packets.ControlPacket), 42 | opened: false, 43 | } 44 | return store 45 | } 46 | 47 | // Open initializes a MemoryStore instance. 48 | func (store *MemoryStore) Open() { 49 | store.Lock() 50 | defer store.Unlock() 51 | store.opened = true 52 | DEBUG.Println(STR, "memorystore initialized") 53 | } 54 | 55 | // Put takes a key and a pointer to a Message and stores the 56 | // message. 57 | func (store *MemoryStore) Put(key string, message packets.ControlPacket) { 58 | store.Lock() 59 | defer store.Unlock() 60 | if !store.opened { 61 | ERROR.Println(STR, "Trying to use memory store, but not open") 62 | return 63 | } 64 | store.messages[key] = message 65 | } 66 | 67 | // Get takes a key and looks in the store for a matching Message 68 | // returning either the Message pointer or nil. 69 | func (store *MemoryStore) Get(key string) packets.ControlPacket { 70 | store.RLock() 71 | defer store.RUnlock() 72 | if !store.opened { 73 | ERROR.Println(STR, "Trying to use memory store, but not open") 74 | return nil 75 | } 76 | mid := mIDFromKey(key) 77 | m := store.messages[key] 78 | if m == nil { 79 | CRITICAL.Println(STR, "memorystore get: message", mid, "not found") 80 | } else { 81 | DEBUG.Println(STR, "memorystore get: message", mid, "found") 82 | } 83 | return m 84 | } 85 | 86 | // All returns a slice of strings containing all the keys currently 87 | // in the MemoryStore. 88 | func (store *MemoryStore) All() []string { 89 | store.RLock() 90 | defer store.RUnlock() 91 | if !store.opened { 92 | ERROR.Println(STR, "Trying to use memory store, but not open") 93 | return nil 94 | } 95 | var keys []string 96 | for k := range store.messages { 97 | keys = append(keys, k) 98 | } 99 | return keys 100 | } 101 | 102 | // Del takes a key, searches the MemoryStore and if the key is found 103 | // deletes the Message pointer associated with it. 104 | func (store *MemoryStore) Del(key string) { 105 | store.Lock() 106 | defer store.Unlock() 107 | if !store.opened { 108 | ERROR.Println(STR, "Trying to use memory store, but not open") 109 | return 110 | } 111 | mid := mIDFromKey(key) 112 | m := store.messages[key] 113 | if m == nil { 114 | WARN.Println(STR, "memorystore del: message", mid, "not found") 115 | } else { 116 | delete(store.messages, key) 117 | DEBUG.Println(STR, "memorystore del: message", mid, "was deleted") 118 | } 119 | } 120 | 121 | // Close will disallow modifications to the state of the store. 122 | func (store *MemoryStore) Close() { 123 | store.Lock() 124 | defer store.Unlock() 125 | if !store.opened { 126 | ERROR.Println(STR, "Trying to close memory store, but not open") 127 | return 128 | } 129 | store.opened = false 130 | DEBUG.Println(STR, "memorystore closed") 131 | } 132 | 133 | // Reset eliminates all persisted message data in the store. 134 | func (store *MemoryStore) Reset() { 135 | store.Lock() 136 | defer store.Unlock() 137 | if !store.opened { 138 | ERROR.Println(STR, "Trying to reset memory store, but not open") 139 | } 140 | store.messages = make(map[string]packets.ControlPacket) 141 | WARN.Println(STR, "memorystore wiped") 142 | } 143 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/memstore_ordered.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | * Matt Brittan 18 | */ 19 | 20 | package mqtt 21 | 22 | import ( 23 | "sort" 24 | "sync" 25 | "time" 26 | 27 | "github.com/eclipse/paho.mqtt.golang/packets" 28 | ) 29 | 30 | // OrderedMemoryStore uses a map internally so the order in which All() returns packets is 31 | // undefined. OrderedMemoryStore resolves this by storing the time the message is added 32 | // and sorting based upon this. 33 | 34 | // storedMessage encapsulates a message and the time it was initially stored 35 | type storedMessage struct { 36 | ts time.Time 37 | msg packets.ControlPacket 38 | } 39 | 40 | // OrderedMemoryStore implements the store interface to provide a "persistence" 41 | // mechanism wholly stored in memory. This is only useful for 42 | // as long as the client instance exists. 43 | type OrderedMemoryStore struct { 44 | sync.RWMutex 45 | messages map[string]storedMessage 46 | opened bool 47 | } 48 | 49 | // NewOrderedMemoryStore returns a pointer to a new instance of 50 | // OrderedMemoryStore, the instance is not initialized and ready to 51 | // use until Open() has been called on it. 52 | func NewOrderedMemoryStore() *OrderedMemoryStore { 53 | store := &OrderedMemoryStore{ 54 | messages: make(map[string]storedMessage), 55 | opened: false, 56 | } 57 | return store 58 | } 59 | 60 | // Open initializes a OrderedMemoryStore instance. 61 | func (store *OrderedMemoryStore) Open() { 62 | store.Lock() 63 | defer store.Unlock() 64 | store.opened = true 65 | DEBUG.Println(STR, "OrderedMemoryStore initialized") 66 | } 67 | 68 | // Put takes a key and a pointer to a Message and stores the 69 | // message. 70 | func (store *OrderedMemoryStore) Put(key string, message packets.ControlPacket) { 71 | store.Lock() 72 | defer store.Unlock() 73 | if !store.opened { 74 | ERROR.Println(STR, "Trying to use memory store, but not open") 75 | return 76 | } 77 | store.messages[key] = storedMessage{ts: time.Now(), msg: message} 78 | } 79 | 80 | // Get takes a key and looks in the store for a matching Message 81 | // returning either the Message pointer or nil. 82 | func (store *OrderedMemoryStore) Get(key string) packets.ControlPacket { 83 | store.RLock() 84 | defer store.RUnlock() 85 | if !store.opened { 86 | ERROR.Println(STR, "Trying to use memory store, but not open") 87 | return nil 88 | } 89 | mid := mIDFromKey(key) 90 | m, ok := store.messages[key] 91 | if !ok || m.msg == nil { 92 | CRITICAL.Println(STR, "OrderedMemoryStore get: message", mid, "not found") 93 | } else { 94 | DEBUG.Println(STR, "OrderedMemoryStore get: message", mid, "found") 95 | } 96 | return m.msg 97 | } 98 | 99 | // All returns a slice of strings containing all the keys currently 100 | // in the OrderedMemoryStore. 101 | func (store *OrderedMemoryStore) All() []string { 102 | store.RLock() 103 | defer store.RUnlock() 104 | if !store.opened { 105 | ERROR.Println(STR, "Trying to use memory store, but not open") 106 | return nil 107 | } 108 | type tsAndKey struct { 109 | ts time.Time 110 | key string 111 | } 112 | 113 | tsKeys := make([]tsAndKey, 0, len(store.messages)) 114 | for k, v := range store.messages { 115 | tsKeys = append(tsKeys, tsAndKey{ts: v.ts, key: k}) 116 | } 117 | sort.Slice(tsKeys, func(a int, b int) bool { return tsKeys[a].ts.Before(tsKeys[b].ts) }) 118 | 119 | keys := make([]string, len(tsKeys)) 120 | for i := range tsKeys { 121 | keys[i] = tsKeys[i].key 122 | } 123 | return keys 124 | } 125 | 126 | // Del takes a key, searches the OrderedMemoryStore and if the key is found 127 | // deletes the Message pointer associated with it. 128 | func (store *OrderedMemoryStore) Del(key string) { 129 | store.Lock() 130 | defer store.Unlock() 131 | if !store.opened { 132 | ERROR.Println(STR, "Trying to use memory store, but not open") 133 | return 134 | } 135 | mid := mIDFromKey(key) 136 | _, ok := store.messages[key] 137 | if !ok { 138 | WARN.Println(STR, "OrderedMemoryStore del: message", mid, "not found") 139 | } else { 140 | delete(store.messages, key) 141 | DEBUG.Println(STR, "OrderedMemoryStore del: message", mid, "was deleted") 142 | } 143 | } 144 | 145 | // Close will disallow modifications to the state of the store. 146 | func (store *OrderedMemoryStore) Close() { 147 | store.Lock() 148 | defer store.Unlock() 149 | if !store.opened { 150 | ERROR.Println(STR, "Trying to close memory store, but not open") 151 | return 152 | } 153 | store.opened = false 154 | DEBUG.Println(STR, "OrderedMemoryStore closed") 155 | } 156 | 157 | // Reset eliminates all persisted message data in the store. 158 | func (store *OrderedMemoryStore) Reset() { 159 | store.Lock() 160 | defer store.Unlock() 161 | if !store.opened { 162 | ERROR.Println(STR, "Trying to reset memory store, but not open") 163 | } 164 | store.messages = make(map[string]storedMessage) 165 | WARN.Println(STR, "OrderedMemoryStore wiped") 166 | } 167 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/message.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | */ 18 | 19 | package mqtt 20 | 21 | import ( 22 | "net/url" 23 | "sync" 24 | 25 | "github.com/eclipse/paho.mqtt.golang/packets" 26 | ) 27 | 28 | // Message defines the externals that a message implementation must support 29 | // these are received messages that are passed to the callbacks, not internal 30 | // messages 31 | type Message interface { 32 | Duplicate() bool 33 | Qos() byte 34 | Retained() bool 35 | Topic() string 36 | MessageID() uint16 37 | Payload() []byte 38 | Ack() 39 | } 40 | 41 | type message struct { 42 | duplicate bool 43 | qos byte 44 | retained bool 45 | topic string 46 | messageID uint16 47 | payload []byte 48 | once sync.Once 49 | ack func() 50 | } 51 | 52 | func (m *message) Duplicate() bool { 53 | return m.duplicate 54 | } 55 | 56 | func (m *message) Qos() byte { 57 | return m.qos 58 | } 59 | 60 | func (m *message) Retained() bool { 61 | return m.retained 62 | } 63 | 64 | func (m *message) Topic() string { 65 | return m.topic 66 | } 67 | 68 | func (m *message) MessageID() uint16 { 69 | return m.messageID 70 | } 71 | 72 | func (m *message) Payload() []byte { 73 | return m.payload 74 | } 75 | 76 | func (m *message) Ack() { 77 | m.once.Do(m.ack) 78 | } 79 | 80 | func messageFromPublish(p *packets.PublishPacket, ack func()) Message { 81 | return &message{ 82 | duplicate: p.Dup, 83 | qos: p.Qos, 84 | retained: p.Retain, 85 | topic: p.TopicName, 86 | messageID: p.MessageID, 87 | payload: p.Payload, 88 | ack: ack, 89 | } 90 | } 91 | 92 | func newConnectMsgFromOptions(options *ClientOptions, broker *url.URL) *packets.ConnectPacket { 93 | m := packets.NewControlPacket(packets.Connect).(*packets.ConnectPacket) 94 | 95 | m.CleanSession = options.CleanSession 96 | m.WillFlag = options.WillEnabled 97 | m.WillRetain = options.WillRetained 98 | m.ClientIdentifier = options.ClientID 99 | 100 | if options.WillEnabled { 101 | m.WillQos = options.WillQos 102 | m.WillTopic = options.WillTopic 103 | m.WillMessage = options.WillPayload 104 | } 105 | 106 | username := options.Username 107 | password := options.Password 108 | if broker.User != nil { 109 | username = broker.User.Username() 110 | if pwd, ok := broker.User.Password(); ok { 111 | password = pwd 112 | } 113 | } 114 | if options.CredentialsProvider != nil { 115 | username, password = options.CredentialsProvider() 116 | } 117 | 118 | if username != "" { 119 | m.UsernameFlag = true 120 | m.Username = username 121 | // mustn't have password without user as well 122 | if password != "" { 123 | m.PasswordFlag = true 124 | m.Password = []byte(password) 125 | } 126 | } 127 | 128 | m.Keepalive = uint16(options.KeepAlive) 129 | 130 | return m 131 | } 132 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/messageids.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | * Matt Brittan 18 | */ 19 | 20 | package mqtt 21 | 22 | import ( 23 | "fmt" 24 | "sync" 25 | "time" 26 | ) 27 | 28 | // MId is 16 bit message id as specified by the MQTT spec. 29 | // In general, these values should not be depended upon by 30 | // the client application. 31 | type MId uint16 32 | 33 | type messageIds struct { 34 | sync.RWMutex 35 | index map[uint16]tokenCompletor 36 | 37 | lastIssuedID uint16 // The most recently issued ID. Used so we cycle through ids rather than immediately reusing them (can make debugging easier) 38 | } 39 | 40 | const ( 41 | midMin uint16 = 1 42 | midMax uint16 = 65535 43 | ) 44 | 45 | // cleanup clears the message ID map; completes all token types and sets error on PUB, SUB and UNSUB tokens. 46 | func (mids *messageIds) cleanUp() { 47 | mids.Lock() 48 | for _, token := range mids.index { 49 | switch token.(type) { 50 | case *PublishToken: 51 | token.setError(fmt.Errorf("connection lost before Publish completed")) 52 | case *SubscribeToken: 53 | token.setError(fmt.Errorf("connection lost before Subscribe completed")) 54 | case *UnsubscribeToken: 55 | token.setError(fmt.Errorf("connection lost before Unsubscribe completed")) 56 | case nil: // should not be any nil entries 57 | continue 58 | } 59 | token.flowComplete() 60 | } 61 | mids.index = make(map[uint16]tokenCompletor) 62 | mids.Unlock() 63 | DEBUG.Println(MID, "cleaned up") 64 | } 65 | 66 | // cleanUpSubscribe removes all SUBSCRIBE and UNSUBSCRIBE tokens (setting error) 67 | // This may be called when the connection is lost, and we will not be resending SUB/UNSUB packets 68 | func (mids *messageIds) cleanUpSubscribe() { 69 | mids.Lock() 70 | for mid, token := range mids.index { 71 | switch token.(type) { 72 | case *SubscribeToken: 73 | token.setError(fmt.Errorf("connection lost before Subscribe completed")) 74 | delete(mids.index, mid) 75 | case *UnsubscribeToken: 76 | token.setError(fmt.Errorf("connection lost before Unsubscribe completed")) 77 | delete(mids.index, mid) 78 | } 79 | } 80 | mids.Unlock() 81 | DEBUG.Println(MID, "cleaned up subs") 82 | } 83 | 84 | func (mids *messageIds) freeID(id uint16) { 85 | mids.Lock() 86 | delete(mids.index, id) 87 | mids.Unlock() 88 | } 89 | 90 | func (mids *messageIds) claimID(token tokenCompletor, id uint16) { 91 | mids.Lock() 92 | defer mids.Unlock() 93 | if _, ok := mids.index[id]; !ok { 94 | mids.index[id] = token 95 | } else { 96 | old := mids.index[id] 97 | old.flowComplete() 98 | mids.index[id] = token 99 | } 100 | if id > mids.lastIssuedID { 101 | mids.lastIssuedID = id 102 | } 103 | } 104 | 105 | // getID will return an available id or 0 if none available 106 | // The id will generally be the previous id + 1 (because this makes tracing messages a bit simpler) 107 | func (mids *messageIds) getID(t tokenCompletor) uint16 { 108 | mids.Lock() 109 | defer mids.Unlock() 110 | i := mids.lastIssuedID // note: the only situation where lastIssuedID is 0 the map will be empty 111 | looped := false // uint16 will loop from 65535->0 112 | for { 113 | i++ 114 | if i == 0 { // skip 0 because its not a valid id (Control Packets MUST contain a non-zero 16-bit Packet Identifier [MQTT-2.3.1-1]) 115 | i++ 116 | looped = true 117 | } 118 | if _, ok := mids.index[i]; !ok { 119 | mids.index[i] = t 120 | mids.lastIssuedID = i 121 | return i 122 | } 123 | if (looped && i == mids.lastIssuedID) || (mids.lastIssuedID == 0 && i == midMax) { // lastIssuedID will be 0 at startup 124 | return 0 // no free ids 125 | } 126 | } 127 | } 128 | 129 | func (mids *messageIds) getToken(id uint16) tokenCompletor { 130 | mids.RLock() 131 | defer mids.RUnlock() 132 | if token, ok := mids.index[id]; ok { 133 | return token 134 | } 135 | return &DummyToken{id: id} 136 | } 137 | 138 | type DummyToken struct { 139 | id uint16 140 | } 141 | 142 | // Wait implements the Token Wait method. 143 | func (d *DummyToken) Wait() bool { 144 | return true 145 | } 146 | 147 | // WaitTimeout implements the Token WaitTimeout method. 148 | func (d *DummyToken) WaitTimeout(t time.Duration) bool { 149 | return true 150 | } 151 | 152 | // Done implements the Token Done method. 153 | func (d *DummyToken) Done() <-chan struct{} { 154 | ch := make(chan struct{}) 155 | close(ch) 156 | return ch 157 | } 158 | 159 | func (d *DummyToken) flowComplete() { 160 | ERROR.Printf("A lookup for token %d returned nil\n", d.id) 161 | } 162 | 163 | func (d *DummyToken) Error() error { 164 | return nil 165 | } 166 | 167 | func (d *DummyToken) setError(e error) {} 168 | 169 | // PlaceHolderToken does nothing and was implemented to allow a messageid to be reserved 170 | // it differs from DummyToken in that calling flowComplete does not generate an error (it 171 | // is expected that flowComplete will be called when the token is overwritten with a real token) 172 | type PlaceHolderToken struct { 173 | id uint16 174 | } 175 | 176 | // Wait implements the Token Wait method. 177 | func (p *PlaceHolderToken) Wait() bool { 178 | return true 179 | } 180 | 181 | // WaitTimeout implements the Token WaitTimeout method. 182 | func (p *PlaceHolderToken) WaitTimeout(t time.Duration) bool { 183 | return true 184 | } 185 | 186 | // Done implements the Token Done method. 187 | func (p *PlaceHolderToken) Done() <-chan struct{} { 188 | ch := make(chan struct{}) 189 | close(ch) 190 | return ch 191 | } 192 | 193 | func (p *PlaceHolderToken) flowComplete() { 194 | } 195 | 196 | func (p *PlaceHolderToken) Error() error { 197 | return nil 198 | } 199 | 200 | func (p *PlaceHolderToken) setError(e error) {} 201 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/netconn.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | * MAtt Brittan 18 | */ 19 | 20 | package mqtt 21 | 22 | import ( 23 | "crypto/tls" 24 | "errors" 25 | "net" 26 | "net/http" 27 | "net/url" 28 | "os" 29 | "time" 30 | 31 | "golang.org/x/net/proxy" 32 | ) 33 | 34 | // 35 | // This just establishes the network connection; once established the type of connection should be irrelevant 36 | // 37 | 38 | // openConnection opens a network connection using the protocol indicated in the URL. 39 | // Does not carry out any MQTT specific handshakes. 40 | func openConnection(uri *url.URL, tlsc *tls.Config, timeout time.Duration, headers http.Header, websocketOptions *WebsocketOptions, dialer *net.Dialer) (net.Conn, error) { 41 | switch uri.Scheme { 42 | case "ws": 43 | conn, err := NewWebsocket(uri.String(), nil, timeout, headers, websocketOptions) 44 | return conn, err 45 | case "wss": 46 | conn, err := NewWebsocket(uri.String(), tlsc, timeout, headers, websocketOptions) 47 | return conn, err 48 | case "mqtt", "tcp": 49 | allProxy := os.Getenv("all_proxy") 50 | if len(allProxy) == 0 { 51 | conn, err := dialer.Dial("tcp", uri.Host) 52 | if err != nil { 53 | return nil, err 54 | } 55 | return conn, nil 56 | } 57 | proxyDialer := proxy.FromEnvironment() 58 | 59 | conn, err := proxyDialer.Dial("tcp", uri.Host) 60 | if err != nil { 61 | return nil, err 62 | } 63 | return conn, nil 64 | case "unix": 65 | var conn net.Conn 66 | var err error 67 | 68 | // this check is preserved for compatibility with older versions 69 | // which used uri.Host only (it works for local paths, e.g. unix://socket.sock in current dir) 70 | if len(uri.Host) > 0 { 71 | conn, err = dialer.Dial("unix", uri.Host) 72 | } else { 73 | conn, err = dialer.Dial("unix", uri.Path) 74 | } 75 | 76 | if err != nil { 77 | return nil, err 78 | } 79 | return conn, nil 80 | case "ssl", "tls", "mqtts", "mqtt+ssl", "tcps": 81 | allProxy := os.Getenv("all_proxy") 82 | if len(allProxy) == 0 { 83 | conn, err := tls.DialWithDialer(dialer, "tcp", uri.Host, tlsc) 84 | if err != nil { 85 | return nil, err 86 | } 87 | return conn, nil 88 | } 89 | proxyDialer := proxy.FromEnvironment() 90 | conn, err := proxyDialer.Dial("tcp", uri.Host) 91 | if err != nil { 92 | return nil, err 93 | } 94 | 95 | tlsConn := tls.Client(conn, tlsc) 96 | 97 | err = tlsConn.Handshake() 98 | if err != nil { 99 | _ = conn.Close() 100 | return nil, err 101 | } 102 | 103 | return tlsConn, nil 104 | } 105 | return nil, errors.New("unknown protocol") 106 | } 107 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/oops.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | */ 18 | 19 | package mqtt 20 | 21 | func chkerr(e error) { 22 | if e != nil { 23 | panic(e) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/options_reader.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | */ 18 | 19 | package mqtt 20 | 21 | import ( 22 | "crypto/tls" 23 | "net/http" 24 | "net/url" 25 | "time" 26 | ) 27 | 28 | // ClientOptionsReader provides an interface for reading ClientOptions after the client has been initialized. 29 | type ClientOptionsReader struct { 30 | options *ClientOptions 31 | } 32 | 33 | // Servers returns a slice of the servers defined in the clientoptions 34 | func (r *ClientOptionsReader) Servers() []*url.URL { 35 | s := make([]*url.URL, len(r.options.Servers)) 36 | 37 | for i, u := range r.options.Servers { 38 | nu := *u 39 | s[i] = &nu 40 | } 41 | 42 | return s 43 | } 44 | 45 | // ResumeSubs returns true if resuming stored (un)sub is enabled 46 | func (r *ClientOptionsReader) ResumeSubs() bool { 47 | s := r.options.ResumeSubs 48 | return s 49 | } 50 | 51 | // ClientID returns the set client id 52 | func (r *ClientOptionsReader) ClientID() string { 53 | s := r.options.ClientID 54 | return s 55 | } 56 | 57 | // Username returns the set username 58 | func (r *ClientOptionsReader) Username() string { 59 | s := r.options.Username 60 | return s 61 | } 62 | 63 | // Password returns the set password 64 | func (r *ClientOptionsReader) Password() string { 65 | s := r.options.Password 66 | return s 67 | } 68 | 69 | // CleanSession returns whether Cleansession is set 70 | func (r *ClientOptionsReader) CleanSession() bool { 71 | s := r.options.CleanSession 72 | return s 73 | } 74 | 75 | func (r *ClientOptionsReader) Order() bool { 76 | s := r.options.Order 77 | return s 78 | } 79 | 80 | func (r *ClientOptionsReader) WillEnabled() bool { 81 | s := r.options.WillEnabled 82 | return s 83 | } 84 | 85 | func (r *ClientOptionsReader) WillTopic() string { 86 | s := r.options.WillTopic 87 | return s 88 | } 89 | 90 | func (r *ClientOptionsReader) WillPayload() []byte { 91 | s := r.options.WillPayload 92 | return s 93 | } 94 | 95 | func (r *ClientOptionsReader) WillQos() byte { 96 | s := r.options.WillQos 97 | return s 98 | } 99 | 100 | func (r *ClientOptionsReader) WillRetained() bool { 101 | s := r.options.WillRetained 102 | return s 103 | } 104 | 105 | func (r *ClientOptionsReader) ProtocolVersion() uint { 106 | s := r.options.ProtocolVersion 107 | return s 108 | } 109 | 110 | func (r *ClientOptionsReader) TLSConfig() *tls.Config { 111 | s := r.options.TLSConfig 112 | return s 113 | } 114 | 115 | func (r *ClientOptionsReader) KeepAlive() time.Duration { 116 | s := time.Duration(r.options.KeepAlive * int64(time.Second)) 117 | return s 118 | } 119 | 120 | func (r *ClientOptionsReader) PingTimeout() time.Duration { 121 | s := r.options.PingTimeout 122 | return s 123 | } 124 | 125 | func (r *ClientOptionsReader) ConnectTimeout() time.Duration { 126 | s := r.options.ConnectTimeout 127 | return s 128 | } 129 | 130 | func (r *ClientOptionsReader) MaxReconnectInterval() time.Duration { 131 | s := r.options.MaxReconnectInterval 132 | return s 133 | } 134 | 135 | func (r *ClientOptionsReader) AutoReconnect() bool { 136 | s := r.options.AutoReconnect 137 | return s 138 | } 139 | 140 | // ConnectRetryInterval returns the delay between retries on the initial connection (if ConnectRetry true) 141 | func (r *ClientOptionsReader) ConnectRetryInterval() time.Duration { 142 | s := r.options.ConnectRetryInterval 143 | return s 144 | } 145 | 146 | // ConnectRetry returns whether the initial connection request will be retried until connection established 147 | func (r *ClientOptionsReader) ConnectRetry() bool { 148 | s := r.options.ConnectRetry 149 | return s 150 | } 151 | 152 | func (r *ClientOptionsReader) WriteTimeout() time.Duration { 153 | s := r.options.WriteTimeout 154 | return s 155 | } 156 | 157 | func (r *ClientOptionsReader) MessageChannelDepth() uint { 158 | s := r.options.MessageChannelDepth 159 | return s 160 | } 161 | 162 | func (r *ClientOptionsReader) HTTPHeaders() http.Header { 163 | h := r.options.HTTPHeaders 164 | return h 165 | } 166 | 167 | // WebsocketOptions returns the currently configured WebSocket options 168 | func (r *ClientOptionsReader) WebsocketOptions() *WebsocketOptions { 169 | s := r.options.WebsocketOptions 170 | return s 171 | } 172 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/connack.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "io" 23 | ) 24 | 25 | // ConnackPacket is an internal representation of the fields of the 26 | // Connack MQTT packet 27 | type ConnackPacket struct { 28 | FixedHeader 29 | SessionPresent bool 30 | ReturnCode byte 31 | } 32 | 33 | func (ca *ConnackPacket) String() string { 34 | return fmt.Sprintf("%s sessionpresent: %t returncode: %d", ca.FixedHeader, ca.SessionPresent, ca.ReturnCode) 35 | } 36 | 37 | func (ca *ConnackPacket) Write(w io.Writer) error { 38 | var body bytes.Buffer 39 | var err error 40 | 41 | body.WriteByte(boolToByte(ca.SessionPresent)) 42 | body.WriteByte(ca.ReturnCode) 43 | ca.FixedHeader.RemainingLength = 2 44 | packet := ca.FixedHeader.pack() 45 | packet.Write(body.Bytes()) 46 | _, err = packet.WriteTo(w) 47 | 48 | return err 49 | } 50 | 51 | // Unpack decodes the details of a ControlPacket after the fixed 52 | // header has been read 53 | func (ca *ConnackPacket) Unpack(b io.Reader) error { 54 | flags, err := decodeByte(b) 55 | if err != nil { 56 | return err 57 | } 58 | ca.SessionPresent = 1&flags > 0 59 | ca.ReturnCode, err = decodeByte(b) 60 | 61 | return err 62 | } 63 | 64 | // Details returns a Details struct containing the Qos and 65 | // MessageID of this ControlPacket 66 | func (ca *ConnackPacket) Details() Details { 67 | return Details{Qos: 0, MessageID: 0} 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/connect.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "io" 23 | ) 24 | 25 | // ConnectPacket is an internal representation of the fields of the 26 | // Connect MQTT packet 27 | type ConnectPacket struct { 28 | FixedHeader 29 | ProtocolName string 30 | ProtocolVersion byte 31 | CleanSession bool 32 | WillFlag bool 33 | WillQos byte 34 | WillRetain bool 35 | UsernameFlag bool 36 | PasswordFlag bool 37 | ReservedBit byte 38 | Keepalive uint16 39 | 40 | ClientIdentifier string 41 | WillTopic string 42 | WillMessage []byte 43 | Username string 44 | Password []byte 45 | } 46 | 47 | func (c *ConnectPacket) String() string { 48 | var password string 49 | if len(c.Password) > 0 { 50 | password = "" 51 | } 52 | return fmt.Sprintf("%s protocolversion: %d protocolname: %s cleansession: %t willflag: %t WillQos: %d WillRetain: %t Usernameflag: %t Passwordflag: %t keepalive: %d clientId: %s willtopic: %s willmessage: %s Username: %s Password: %s", c.FixedHeader, c.ProtocolVersion, c.ProtocolName, c.CleanSession, c.WillFlag, c.WillQos, c.WillRetain, c.UsernameFlag, c.PasswordFlag, c.Keepalive, c.ClientIdentifier, c.WillTopic, c.WillMessage, c.Username, password) 53 | } 54 | 55 | func (c *ConnectPacket) Write(w io.Writer) error { 56 | var body bytes.Buffer 57 | var err error 58 | 59 | body.Write(encodeString(c.ProtocolName)) 60 | body.WriteByte(c.ProtocolVersion) 61 | body.WriteByte(boolToByte(c.CleanSession)<<1 | boolToByte(c.WillFlag)<<2 | c.WillQos<<3 | boolToByte(c.WillRetain)<<5 | boolToByte(c.PasswordFlag)<<6 | boolToByte(c.UsernameFlag)<<7) 62 | body.Write(encodeUint16(c.Keepalive)) 63 | body.Write(encodeString(c.ClientIdentifier)) 64 | if c.WillFlag { 65 | body.Write(encodeString(c.WillTopic)) 66 | body.Write(encodeBytes(c.WillMessage)) 67 | } 68 | if c.UsernameFlag { 69 | body.Write(encodeString(c.Username)) 70 | } 71 | if c.PasswordFlag { 72 | body.Write(encodeBytes(c.Password)) 73 | } 74 | c.FixedHeader.RemainingLength = body.Len() 75 | packet := c.FixedHeader.pack() 76 | packet.Write(body.Bytes()) 77 | _, err = packet.WriteTo(w) 78 | 79 | return err 80 | } 81 | 82 | // Unpack decodes the details of a ControlPacket after the fixed 83 | // header has been read 84 | func (c *ConnectPacket) Unpack(b io.Reader) error { 85 | var err error 86 | c.ProtocolName, err = decodeString(b) 87 | if err != nil { 88 | return err 89 | } 90 | c.ProtocolVersion, err = decodeByte(b) 91 | if err != nil { 92 | return err 93 | } 94 | options, err := decodeByte(b) 95 | if err != nil { 96 | return err 97 | } 98 | c.ReservedBit = 1 & options 99 | c.CleanSession = 1&(options>>1) > 0 100 | c.WillFlag = 1&(options>>2) > 0 101 | c.WillQos = 3 & (options >> 3) 102 | c.WillRetain = 1&(options>>5) > 0 103 | c.PasswordFlag = 1&(options>>6) > 0 104 | c.UsernameFlag = 1&(options>>7) > 0 105 | c.Keepalive, err = decodeUint16(b) 106 | if err != nil { 107 | return err 108 | } 109 | c.ClientIdentifier, err = decodeString(b) 110 | if err != nil { 111 | return err 112 | } 113 | if c.WillFlag { 114 | c.WillTopic, err = decodeString(b) 115 | if err != nil { 116 | return err 117 | } 118 | c.WillMessage, err = decodeBytes(b) 119 | if err != nil { 120 | return err 121 | } 122 | } 123 | if c.UsernameFlag { 124 | c.Username, err = decodeString(b) 125 | if err != nil { 126 | return err 127 | } 128 | } 129 | if c.PasswordFlag { 130 | c.Password, err = decodeBytes(b) 131 | if err != nil { 132 | return err 133 | } 134 | } 135 | 136 | return nil 137 | } 138 | 139 | // Validate performs validation of the fields of a Connect packet 140 | func (c *ConnectPacket) Validate() byte { 141 | if c.PasswordFlag && !c.UsernameFlag { 142 | return ErrRefusedBadUsernameOrPassword 143 | } 144 | if c.ReservedBit != 0 { 145 | // Bad reserved bit 146 | return ErrProtocolViolation 147 | } 148 | if (c.ProtocolName == "MQIsdp" && c.ProtocolVersion != 3) || (c.ProtocolName == "MQTT" && c.ProtocolVersion != 4) { 149 | // Mismatched or unsupported protocol version 150 | return ErrRefusedBadProtocolVersion 151 | } 152 | if c.ProtocolName != "MQIsdp" && c.ProtocolName != "MQTT" { 153 | // Bad protocol name 154 | return ErrProtocolViolation 155 | } 156 | if len(c.ClientIdentifier) > 65535 || len(c.Username) > 65535 || len(c.Password) > 65535 { 157 | // Bad size field 158 | return ErrProtocolViolation 159 | } 160 | if len(c.ClientIdentifier) == 0 && !c.CleanSession { 161 | // Bad client identifier 162 | return ErrRefusedIDRejected 163 | } 164 | return Accepted 165 | } 166 | 167 | // Details returns a Details struct containing the Qos and 168 | // MessageID of this ControlPacket 169 | func (c *ConnectPacket) Details() Details { 170 | return Details{Qos: 0, MessageID: 0} 171 | } 172 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/disconnect.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "io" 21 | ) 22 | 23 | // DisconnectPacket is an internal representation of the fields of the 24 | // Disconnect MQTT packet 25 | type DisconnectPacket struct { 26 | FixedHeader 27 | } 28 | 29 | func (d *DisconnectPacket) String() string { 30 | return d.FixedHeader.String() 31 | } 32 | 33 | func (d *DisconnectPacket) Write(w io.Writer) error { 34 | packet := d.FixedHeader.pack() 35 | _, err := packet.WriteTo(w) 36 | 37 | return err 38 | } 39 | 40 | // Unpack decodes the details of a ControlPacket after the fixed 41 | // header has been read 42 | func (d *DisconnectPacket) Unpack(b io.Reader) error { 43 | return nil 44 | } 45 | 46 | // Details returns a Details struct containing the Qos and 47 | // MessageID of this ControlPacket 48 | func (d *DisconnectPacket) Details() Details { 49 | return Details{Qos: 0, MessageID: 0} 50 | } 51 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/pingreq.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "io" 21 | ) 22 | 23 | // PingreqPacket is an internal representation of the fields of the 24 | // Pingreq MQTT packet 25 | type PingreqPacket struct { 26 | FixedHeader 27 | } 28 | 29 | func (pr *PingreqPacket) String() string { 30 | return pr.FixedHeader.String() 31 | } 32 | 33 | func (pr *PingreqPacket) Write(w io.Writer) error { 34 | packet := pr.FixedHeader.pack() 35 | _, err := packet.WriteTo(w) 36 | 37 | return err 38 | } 39 | 40 | // Unpack decodes the details of a ControlPacket after the fixed 41 | // header has been read 42 | func (pr *PingreqPacket) Unpack(b io.Reader) error { 43 | return nil 44 | } 45 | 46 | // Details returns a Details struct containing the Qos and 47 | // MessageID of this ControlPacket 48 | func (pr *PingreqPacket) Details() Details { 49 | return Details{Qos: 0, MessageID: 0} 50 | } 51 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/pingresp.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "io" 21 | ) 22 | 23 | // PingrespPacket is an internal representation of the fields of the 24 | // Pingresp MQTT packet 25 | type PingrespPacket struct { 26 | FixedHeader 27 | } 28 | 29 | func (pr *PingrespPacket) String() string { 30 | return pr.FixedHeader.String() 31 | } 32 | 33 | func (pr *PingrespPacket) Write(w io.Writer) error { 34 | packet := pr.FixedHeader.pack() 35 | _, err := packet.WriteTo(w) 36 | 37 | return err 38 | } 39 | 40 | // Unpack decodes the details of a ControlPacket after the fixed 41 | // header has been read 42 | func (pr *PingrespPacket) Unpack(b io.Reader) error { 43 | return nil 44 | } 45 | 46 | // Details returns a Details struct containing the Qos and 47 | // MessageID of this ControlPacket 48 | func (pr *PingrespPacket) Details() Details { 49 | return Details{Qos: 0, MessageID: 0} 50 | } 51 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/puback.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "fmt" 21 | "io" 22 | ) 23 | 24 | // PubackPacket is an internal representation of the fields of the 25 | // Puback MQTT packet 26 | type PubackPacket struct { 27 | FixedHeader 28 | MessageID uint16 29 | } 30 | 31 | func (pa *PubackPacket) String() string { 32 | return fmt.Sprintf("%s MessageID: %d", pa.FixedHeader, pa.MessageID) 33 | } 34 | 35 | func (pa *PubackPacket) Write(w io.Writer) error { 36 | var err error 37 | pa.FixedHeader.RemainingLength = 2 38 | packet := pa.FixedHeader.pack() 39 | packet.Write(encodeUint16(pa.MessageID)) 40 | _, err = packet.WriteTo(w) 41 | 42 | return err 43 | } 44 | 45 | // Unpack decodes the details of a ControlPacket after the fixed 46 | // header has been read 47 | func (pa *PubackPacket) Unpack(b io.Reader) error { 48 | var err error 49 | pa.MessageID, err = decodeUint16(b) 50 | 51 | return err 52 | } 53 | 54 | // Details returns a Details struct containing the Qos and 55 | // MessageID of this ControlPacket 56 | func (pa *PubackPacket) Details() Details { 57 | return Details{Qos: pa.Qos, MessageID: pa.MessageID} 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/pubcomp.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "fmt" 21 | "io" 22 | ) 23 | 24 | // PubcompPacket is an internal representation of the fields of the 25 | // Pubcomp MQTT packet 26 | type PubcompPacket struct { 27 | FixedHeader 28 | MessageID uint16 29 | } 30 | 31 | func (pc *PubcompPacket) String() string { 32 | return fmt.Sprintf("%s MessageID: %d", pc.FixedHeader, pc.MessageID) 33 | } 34 | 35 | func (pc *PubcompPacket) Write(w io.Writer) error { 36 | var err error 37 | pc.FixedHeader.RemainingLength = 2 38 | packet := pc.FixedHeader.pack() 39 | packet.Write(encodeUint16(pc.MessageID)) 40 | _, err = packet.WriteTo(w) 41 | 42 | return err 43 | } 44 | 45 | // Unpack decodes the details of a ControlPacket after the fixed 46 | // header has been read 47 | func (pc *PubcompPacket) Unpack(b io.Reader) error { 48 | var err error 49 | pc.MessageID, err = decodeUint16(b) 50 | 51 | return err 52 | } 53 | 54 | // Details returns a Details struct containing the Qos and 55 | // MessageID of this ControlPacket 56 | func (pc *PubcompPacket) Details() Details { 57 | return Details{Qos: pc.Qos, MessageID: pc.MessageID} 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/publish.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "io" 23 | ) 24 | 25 | // PublishPacket is an internal representation of the fields of the 26 | // Publish MQTT packet 27 | type PublishPacket struct { 28 | FixedHeader 29 | TopicName string 30 | MessageID uint16 31 | Payload []byte 32 | } 33 | 34 | func (p *PublishPacket) String() string { 35 | return fmt.Sprintf("%s topicName: %s MessageID: %d payload: %s", p.FixedHeader, p.TopicName, p.MessageID, string(p.Payload)) 36 | } 37 | 38 | func (p *PublishPacket) Write(w io.Writer) error { 39 | var body bytes.Buffer 40 | var err error 41 | 42 | body.Write(encodeString(p.TopicName)) 43 | if p.Qos > 0 { 44 | body.Write(encodeUint16(p.MessageID)) 45 | } 46 | p.FixedHeader.RemainingLength = body.Len() + len(p.Payload) 47 | packet := p.FixedHeader.pack() 48 | packet.Write(body.Bytes()) 49 | packet.Write(p.Payload) 50 | _, err = w.Write(packet.Bytes()) 51 | 52 | return err 53 | } 54 | 55 | // Unpack decodes the details of a ControlPacket after the fixed 56 | // header has been read 57 | func (p *PublishPacket) Unpack(b io.Reader) error { 58 | var payloadLength = p.FixedHeader.RemainingLength 59 | var err error 60 | p.TopicName, err = decodeString(b) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | if p.Qos > 0 { 66 | p.MessageID, err = decodeUint16(b) 67 | if err != nil { 68 | return err 69 | } 70 | payloadLength -= len(p.TopicName) + 4 71 | } else { 72 | payloadLength -= len(p.TopicName) + 2 73 | } 74 | if payloadLength < 0 { 75 | return fmt.Errorf("error unpacking publish, payload length < 0") 76 | } 77 | p.Payload = make([]byte, payloadLength) 78 | _, err = b.Read(p.Payload) 79 | 80 | return err 81 | } 82 | 83 | // Copy creates a new PublishPacket with the same topic and payload 84 | // but an empty fixed header, useful for when you want to deliver 85 | // a message with different properties such as Qos but the same 86 | // content 87 | func (p *PublishPacket) Copy() *PublishPacket { 88 | newP := NewControlPacket(Publish).(*PublishPacket) 89 | newP.TopicName = p.TopicName 90 | newP.Payload = p.Payload 91 | 92 | return newP 93 | } 94 | 95 | // Details returns a Details struct containing the Qos and 96 | // MessageID of this ControlPacket 97 | func (p *PublishPacket) Details() Details { 98 | return Details{Qos: p.Qos, MessageID: p.MessageID} 99 | } 100 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/pubrec.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "fmt" 21 | "io" 22 | ) 23 | 24 | // PubrecPacket is an internal representation of the fields of the 25 | // Pubrec MQTT packet 26 | type PubrecPacket struct { 27 | FixedHeader 28 | MessageID uint16 29 | } 30 | 31 | func (pr *PubrecPacket) String() string { 32 | return fmt.Sprintf("%s MessageID: %d", pr.FixedHeader, pr.MessageID) 33 | } 34 | 35 | func (pr *PubrecPacket) Write(w io.Writer) error { 36 | var err error 37 | pr.FixedHeader.RemainingLength = 2 38 | packet := pr.FixedHeader.pack() 39 | packet.Write(encodeUint16(pr.MessageID)) 40 | _, err = packet.WriteTo(w) 41 | 42 | return err 43 | } 44 | 45 | // Unpack decodes the details of a ControlPacket after the fixed 46 | // header has been read 47 | func (pr *PubrecPacket) Unpack(b io.Reader) error { 48 | var err error 49 | pr.MessageID, err = decodeUint16(b) 50 | 51 | return err 52 | } 53 | 54 | // Details returns a Details struct containing the Qos and 55 | // MessageID of this ControlPacket 56 | func (pr *PubrecPacket) Details() Details { 57 | return Details{Qos: pr.Qos, MessageID: pr.MessageID} 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/pubrel.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "fmt" 21 | "io" 22 | ) 23 | 24 | // PubrelPacket is an internal representation of the fields of the 25 | // Pubrel MQTT packet 26 | type PubrelPacket struct { 27 | FixedHeader 28 | MessageID uint16 29 | } 30 | 31 | func (pr *PubrelPacket) String() string { 32 | return fmt.Sprintf("%s MessageID: %d", pr.FixedHeader, pr.MessageID) 33 | } 34 | 35 | func (pr *PubrelPacket) Write(w io.Writer) error { 36 | var err error 37 | pr.FixedHeader.RemainingLength = 2 38 | packet := pr.FixedHeader.pack() 39 | packet.Write(encodeUint16(pr.MessageID)) 40 | _, err = packet.WriteTo(w) 41 | 42 | return err 43 | } 44 | 45 | // Unpack decodes the details of a ControlPacket after the fixed 46 | // header has been read 47 | func (pr *PubrelPacket) Unpack(b io.Reader) error { 48 | var err error 49 | pr.MessageID, err = decodeUint16(b) 50 | 51 | return err 52 | } 53 | 54 | // Details returns a Details struct containing the Qos and 55 | // MessageID of this ControlPacket 56 | func (pr *PubrelPacket) Details() Details { 57 | return Details{Qos: pr.Qos, MessageID: pr.MessageID} 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/suback.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "io" 23 | ) 24 | 25 | // SubackPacket is an internal representation of the fields of the 26 | // Suback MQTT packet 27 | type SubackPacket struct { 28 | FixedHeader 29 | MessageID uint16 30 | ReturnCodes []byte 31 | } 32 | 33 | func (sa *SubackPacket) String() string { 34 | return fmt.Sprintf("%s MessageID: %d", sa.FixedHeader, sa.MessageID) 35 | } 36 | 37 | func (sa *SubackPacket) Write(w io.Writer) error { 38 | var body bytes.Buffer 39 | var err error 40 | body.Write(encodeUint16(sa.MessageID)) 41 | body.Write(sa.ReturnCodes) 42 | sa.FixedHeader.RemainingLength = body.Len() 43 | packet := sa.FixedHeader.pack() 44 | packet.Write(body.Bytes()) 45 | _, err = packet.WriteTo(w) 46 | 47 | return err 48 | } 49 | 50 | // Unpack decodes the details of a ControlPacket after the fixed 51 | // header has been read 52 | func (sa *SubackPacket) Unpack(b io.Reader) error { 53 | var qosBuffer bytes.Buffer 54 | var err error 55 | sa.MessageID, err = decodeUint16(b) 56 | if err != nil { 57 | return err 58 | } 59 | 60 | _, err = qosBuffer.ReadFrom(b) 61 | if err != nil { 62 | return err 63 | } 64 | sa.ReturnCodes = qosBuffer.Bytes() 65 | 66 | return nil 67 | } 68 | 69 | // Details returns a Details struct containing the Qos and 70 | // MessageID of this ControlPacket 71 | func (sa *SubackPacket) Details() Details { 72 | return Details{Qos: 0, MessageID: sa.MessageID} 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/subscribe.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "io" 23 | ) 24 | 25 | // SubscribePacket is an internal representation of the fields of the 26 | // Subscribe MQTT packet 27 | type SubscribePacket struct { 28 | FixedHeader 29 | MessageID uint16 30 | Topics []string 31 | Qoss []byte 32 | } 33 | 34 | func (s *SubscribePacket) String() string { 35 | return fmt.Sprintf("%s MessageID: %d topics: %s", s.FixedHeader, s.MessageID, s.Topics) 36 | } 37 | 38 | func (s *SubscribePacket) Write(w io.Writer) error { 39 | var body bytes.Buffer 40 | var err error 41 | 42 | body.Write(encodeUint16(s.MessageID)) 43 | for i, topic := range s.Topics { 44 | body.Write(encodeString(topic)) 45 | body.WriteByte(s.Qoss[i]) 46 | } 47 | s.FixedHeader.RemainingLength = body.Len() 48 | packet := s.FixedHeader.pack() 49 | packet.Write(body.Bytes()) 50 | _, err = packet.WriteTo(w) 51 | 52 | return err 53 | } 54 | 55 | // Unpack decodes the details of a ControlPacket after the fixed 56 | // header has been read 57 | func (s *SubscribePacket) Unpack(b io.Reader) error { 58 | var err error 59 | s.MessageID, err = decodeUint16(b) 60 | if err != nil { 61 | return err 62 | } 63 | payloadLength := s.FixedHeader.RemainingLength - 2 64 | for payloadLength > 0 { 65 | topic, err := decodeString(b) 66 | if err != nil { 67 | return err 68 | } 69 | s.Topics = append(s.Topics, topic) 70 | qos, err := decodeByte(b) 71 | if err != nil { 72 | return err 73 | } 74 | s.Qoss = append(s.Qoss, qos) 75 | payloadLength -= 2 + len(topic) + 1 // 2 bytes of string length, plus string, plus 1 byte for Qos 76 | } 77 | 78 | return nil 79 | } 80 | 81 | // Details returns a Details struct containing the Qos and 82 | // MessageID of this ControlPacket 83 | func (s *SubscribePacket) Details() Details { 84 | return Details{Qos: 1, MessageID: s.MessageID} 85 | } 86 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/unsuback.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "fmt" 21 | "io" 22 | ) 23 | 24 | // UnsubackPacket is an internal representation of the fields of the 25 | // Unsuback MQTT packet 26 | type UnsubackPacket struct { 27 | FixedHeader 28 | MessageID uint16 29 | } 30 | 31 | func (ua *UnsubackPacket) String() string { 32 | return fmt.Sprintf("%s MessageID: %d", ua.FixedHeader, ua.MessageID) 33 | } 34 | 35 | func (ua *UnsubackPacket) Write(w io.Writer) error { 36 | var err error 37 | ua.FixedHeader.RemainingLength = 2 38 | packet := ua.FixedHeader.pack() 39 | packet.Write(encodeUint16(ua.MessageID)) 40 | _, err = packet.WriteTo(w) 41 | 42 | return err 43 | } 44 | 45 | // Unpack decodes the details of a ControlPacket after the fixed 46 | // header has been read 47 | func (ua *UnsubackPacket) Unpack(b io.Reader) error { 48 | var err error 49 | ua.MessageID, err = decodeUint16(b) 50 | 51 | return err 52 | } 53 | 54 | // Details returns a Details struct containing the Qos and 55 | // MessageID of this ControlPacket 56 | func (ua *UnsubackPacket) Details() Details { 57 | return Details{Qos: 0, MessageID: ua.MessageID} 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/packets/unsubscribe.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package packets 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "io" 23 | ) 24 | 25 | // UnsubscribePacket is an internal representation of the fields of the 26 | // Unsubscribe MQTT packet 27 | type UnsubscribePacket struct { 28 | FixedHeader 29 | MessageID uint16 30 | Topics []string 31 | } 32 | 33 | func (u *UnsubscribePacket) String() string { 34 | return fmt.Sprintf("%s MessageID: %d", u.FixedHeader, u.MessageID) 35 | } 36 | 37 | func (u *UnsubscribePacket) Write(w io.Writer) error { 38 | var body bytes.Buffer 39 | var err error 40 | body.Write(encodeUint16(u.MessageID)) 41 | for _, topic := range u.Topics { 42 | body.Write(encodeString(topic)) 43 | } 44 | u.FixedHeader.RemainingLength = body.Len() 45 | packet := u.FixedHeader.pack() 46 | packet.Write(body.Bytes()) 47 | _, err = packet.WriteTo(w) 48 | 49 | return err 50 | } 51 | 52 | // Unpack decodes the details of a ControlPacket after the fixed 53 | // header has been read 54 | func (u *UnsubscribePacket) Unpack(b io.Reader) error { 55 | var err error 56 | u.MessageID, err = decodeUint16(b) 57 | if err != nil { 58 | return err 59 | } 60 | 61 | for topic, err := decodeString(b); err == nil && topic != ""; topic, err = decodeString(b) { 62 | u.Topics = append(u.Topics, topic) 63 | } 64 | 65 | return err 66 | } 67 | 68 | // Details returns a Details struct containing the Qos and 69 | // MessageID of this ControlPacket 70 | func (u *UnsubscribePacket) Details() Details { 71 | return Details{Qos: 1, MessageID: u.MessageID} 72 | } 73 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/ping.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | */ 18 | 19 | package mqtt 20 | 21 | import ( 22 | "errors" 23 | "io" 24 | "sync/atomic" 25 | "time" 26 | 27 | "github.com/eclipse/paho.mqtt.golang/packets" 28 | ) 29 | 30 | // keepalive - Send ping when connection unused for set period 31 | // connection passed in to avoid race condition on shutdown 32 | func keepalive(c *client, conn io.Writer) { 33 | defer c.workers.Done() 34 | DEBUG.Println(PNG, "keepalive starting") 35 | var checkInterval int64 36 | var pingSent time.Time 37 | 38 | if c.options.KeepAlive > 10 { 39 | checkInterval = 5 40 | } else { 41 | checkInterval = c.options.KeepAlive / 2 42 | } 43 | 44 | intervalTicker := time.NewTicker(time.Duration(checkInterval * int64(time.Second))) 45 | defer intervalTicker.Stop() 46 | 47 | for { 48 | select { 49 | case <-c.stop: 50 | DEBUG.Println(PNG, "keepalive stopped") 51 | return 52 | case <-intervalTicker.C: 53 | lastSent := c.lastSent.Load().(time.Time) 54 | lastReceived := c.lastReceived.Load().(time.Time) 55 | 56 | DEBUG.Println(PNG, "ping check", time.Since(lastSent).Seconds()) 57 | if time.Since(lastSent) >= time.Duration(c.options.KeepAlive*int64(time.Second)) || time.Since(lastReceived) >= time.Duration(c.options.KeepAlive*int64(time.Second)) { 58 | if atomic.LoadInt32(&c.pingOutstanding) == 0 { 59 | DEBUG.Println(PNG, "keepalive sending ping") 60 | ping := packets.NewControlPacket(packets.Pingreq).(*packets.PingreqPacket) 61 | // We don't want to wait behind large messages being sent, the Write call 62 | // will block until it it able to send the packet. 63 | atomic.StoreInt32(&c.pingOutstanding, 1) 64 | if err := ping.Write(conn); err != nil { 65 | ERROR.Println(PNG, err) 66 | } 67 | c.lastSent.Store(time.Now()) 68 | pingSent = time.Now() 69 | } 70 | } 71 | if atomic.LoadInt32(&c.pingOutstanding) > 0 && time.Since(pingSent) >= c.options.PingTimeout { 72 | CRITICAL.Println(PNG, "pingresp not received, disconnecting") 73 | c.internalConnLost(errors.New("pingresp not received, disconnecting")) // no harm in calling this if the connection is already down (or shutdown is in progress) 74 | return 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/store.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | */ 18 | 19 | package mqtt 20 | 21 | import ( 22 | "fmt" 23 | "strconv" 24 | 25 | "github.com/eclipse/paho.mqtt.golang/packets" 26 | ) 27 | 28 | const ( 29 | inboundPrefix = "i." 30 | outboundPrefix = "o." 31 | ) 32 | 33 | // Store is an interface which can be used to provide implementations 34 | // for message persistence. 35 | // Because we may have to store distinct messages with the same 36 | // message ID, we need a unique key for each message. This is 37 | // possible by prepending "i." or "o." to each message id 38 | type Store interface { 39 | Open() 40 | Put(key string, message packets.ControlPacket) 41 | Get(key string) packets.ControlPacket 42 | All() []string 43 | Del(key string) 44 | Close() 45 | Reset() 46 | } 47 | 48 | // A key MUST have the form "X.[messageid]" 49 | // where X is 'i' or 'o' 50 | func mIDFromKey(key string) uint16 { 51 | s := key[2:] 52 | i, err := strconv.ParseUint(s, 10, 16) 53 | chkerr(err) 54 | return uint16(i) 55 | } 56 | 57 | // Return true if key prefix is outbound 58 | func isKeyOutbound(key string) bool { 59 | return key[:2] == outboundPrefix 60 | } 61 | 62 | // Return true if key prefix is inbound 63 | func isKeyInbound(key string) bool { 64 | return key[:2] == inboundPrefix 65 | } 66 | 67 | // Return a string of the form "i.[id]" 68 | func inboundKeyFromMID(id uint16) string { 69 | return fmt.Sprintf("%s%d", inboundPrefix, id) 70 | } 71 | 72 | // Return a string of the form "o.[id]" 73 | func outboundKeyFromMID(id uint16) string { 74 | return fmt.Sprintf("%s%d", outboundPrefix, id) 75 | } 76 | 77 | // govern which outgoing messages are persisted 78 | func persistOutbound(s Store, m packets.ControlPacket) { 79 | switch m.Details().Qos { 80 | case 0: 81 | switch m.(type) { 82 | case *packets.PubackPacket, *packets.PubcompPacket: 83 | // Sending puback. delete matching publish 84 | // from ibound 85 | s.Del(inboundKeyFromMID(m.Details().MessageID)) 86 | } 87 | case 1: 88 | switch m.(type) { 89 | case *packets.PublishPacket, *packets.PubrelPacket, *packets.SubscribePacket, *packets.UnsubscribePacket: 90 | // Sending publish. store in obound 91 | // until puback received 92 | s.Put(outboundKeyFromMID(m.Details().MessageID), m) 93 | default: 94 | ERROR.Println(STR, "Asked to persist an invalid message type") 95 | } 96 | case 2: 97 | switch m.(type) { 98 | case *packets.PublishPacket: 99 | // Sending publish. store in obound 100 | // until pubrel received 101 | s.Put(outboundKeyFromMID(m.Details().MessageID), m) 102 | default: 103 | ERROR.Println(STR, "Asked to persist an invalid message type") 104 | } 105 | } 106 | } 107 | 108 | // govern which incoming messages are persisted 109 | func persistInbound(s Store, m packets.ControlPacket) { 110 | switch m.Details().Qos { 111 | case 0: 112 | switch m.(type) { 113 | case *packets.PubackPacket, *packets.SubackPacket, *packets.UnsubackPacket, *packets.PubcompPacket: 114 | // Received a puback. delete matching publish 115 | // from obound 116 | s.Del(outboundKeyFromMID(m.Details().MessageID)) 117 | case *packets.PublishPacket, *packets.PubrecPacket, *packets.PingrespPacket, *packets.ConnackPacket: 118 | default: 119 | ERROR.Println(STR, "Asked to persist an invalid messages type") 120 | } 121 | case 1: 122 | switch m.(type) { 123 | case *packets.PublishPacket, *packets.PubrelPacket: 124 | // Received a publish. store it in ibound 125 | // until puback sent 126 | s.Put(inboundKeyFromMID(m.Details().MessageID), m) 127 | default: 128 | ERROR.Println(STR, "Asked to persist an invalid messages type") 129 | } 130 | case 2: 131 | switch m.(type) { 132 | case *packets.PublishPacket: 133 | // Received a publish. store it in ibound 134 | // until pubrel received 135 | s.Put(inboundKeyFromMID(m.Details().MessageID), m) 136 | default: 137 | ERROR.Println(STR, "Asked to persist an invalid messages type") 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/token.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander 15 | */ 16 | 17 | package mqtt 18 | 19 | import ( 20 | "sync" 21 | "time" 22 | 23 | "github.com/eclipse/paho.mqtt.golang/packets" 24 | ) 25 | 26 | // PacketAndToken is a struct that contains both a ControlPacket and a 27 | // Token. This struct is passed via channels between the client interface 28 | // code and the underlying code responsible for sending and receiving 29 | // MQTT messages. 30 | type PacketAndToken struct { 31 | p packets.ControlPacket 32 | t tokenCompletor 33 | } 34 | 35 | // Token defines the interface for the tokens used to indicate when 36 | // actions have completed. 37 | type Token interface { 38 | // Wait will wait indefinitely for the Token to complete, ie the Publish 39 | // to be sent and confirmed receipt from the broker. 40 | Wait() bool 41 | 42 | // WaitTimeout takes a time.Duration to wait for the flow associated with the 43 | // Token to complete, returns true if it returned before the timeout or 44 | // returns false if the timeout occurred. In the case of a timeout the Token 45 | // does not have an error set in case the caller wishes to wait again. 46 | WaitTimeout(time.Duration) bool 47 | 48 | // Done returns a channel that is closed when the flow associated 49 | // with the Token completes. Clients should call Error after the 50 | // channel is closed to check if the flow completed successfully. 51 | // 52 | // Done is provided for use in select statements. Simple use cases may 53 | // use Wait or WaitTimeout. 54 | Done() <-chan struct{} 55 | 56 | Error() error 57 | } 58 | 59 | type TokenErrorSetter interface { 60 | setError(error) 61 | } 62 | 63 | type tokenCompletor interface { 64 | Token 65 | TokenErrorSetter 66 | flowComplete() 67 | } 68 | 69 | type baseToken struct { 70 | m sync.RWMutex 71 | complete chan struct{} 72 | err error 73 | } 74 | 75 | // Wait implements the Token Wait method. 76 | func (b *baseToken) Wait() bool { 77 | <-b.complete 78 | return true 79 | } 80 | 81 | // WaitTimeout implements the Token WaitTimeout method. 82 | func (b *baseToken) WaitTimeout(d time.Duration) bool { 83 | timer := time.NewTimer(d) 84 | select { 85 | case <-b.complete: 86 | if !timer.Stop() { 87 | <-timer.C 88 | } 89 | return true 90 | case <-timer.C: 91 | } 92 | 93 | return false 94 | } 95 | 96 | // Done implements the Token Done method. 97 | func (b *baseToken) Done() <-chan struct{} { 98 | return b.complete 99 | } 100 | 101 | func (b *baseToken) flowComplete() { 102 | select { 103 | case <-b.complete: 104 | default: 105 | close(b.complete) 106 | } 107 | } 108 | 109 | func (b *baseToken) Error() error { 110 | b.m.RLock() 111 | defer b.m.RUnlock() 112 | return b.err 113 | } 114 | 115 | func (b *baseToken) setError(e error) { 116 | b.m.Lock() 117 | b.err = e 118 | b.flowComplete() 119 | b.m.Unlock() 120 | } 121 | 122 | func newToken(tType byte) tokenCompletor { 123 | switch tType { 124 | case packets.Connect: 125 | return &ConnectToken{baseToken: baseToken{complete: make(chan struct{})}} 126 | case packets.Subscribe: 127 | return &SubscribeToken{baseToken: baseToken{complete: make(chan struct{})}, subResult: make(map[string]byte)} 128 | case packets.Publish: 129 | return &PublishToken{baseToken: baseToken{complete: make(chan struct{})}} 130 | case packets.Unsubscribe: 131 | return &UnsubscribeToken{baseToken: baseToken{complete: make(chan struct{})}} 132 | case packets.Disconnect: 133 | return &DisconnectToken{baseToken: baseToken{complete: make(chan struct{})}} 134 | } 135 | return nil 136 | } 137 | 138 | // ConnectToken is an extension of Token containing the extra fields 139 | // required to provide information about calls to Connect() 140 | type ConnectToken struct { 141 | baseToken 142 | returnCode byte 143 | sessionPresent bool 144 | } 145 | 146 | // ReturnCode returns the acknowledgement code in the connack sent 147 | // in response to a Connect() 148 | func (c *ConnectToken) ReturnCode() byte { 149 | c.m.RLock() 150 | defer c.m.RUnlock() 151 | return c.returnCode 152 | } 153 | 154 | // SessionPresent returns a bool representing the value of the 155 | // session present field in the connack sent in response to a Connect() 156 | func (c *ConnectToken) SessionPresent() bool { 157 | c.m.RLock() 158 | defer c.m.RUnlock() 159 | return c.sessionPresent 160 | } 161 | 162 | // PublishToken is an extension of Token containing the extra fields 163 | // required to provide information about calls to Publish() 164 | type PublishToken struct { 165 | baseToken 166 | messageID uint16 167 | } 168 | 169 | // MessageID returns the MQTT message ID that was assigned to the 170 | // Publish packet when it was sent to the broker 171 | func (p *PublishToken) MessageID() uint16 { 172 | return p.messageID 173 | } 174 | 175 | // SubscribeToken is an extension of Token containing the extra fields 176 | // required to provide information about calls to Subscribe() 177 | type SubscribeToken struct { 178 | baseToken 179 | subs []string 180 | subResult map[string]byte 181 | messageID uint16 182 | } 183 | 184 | // Result returns a map of topics that were subscribed to along with 185 | // the matching return code from the broker. This is either the Qos 186 | // value of the subscription or an error code. 187 | func (s *SubscribeToken) Result() map[string]byte { 188 | s.m.RLock() 189 | defer s.m.RUnlock() 190 | return s.subResult 191 | } 192 | 193 | // UnsubscribeToken is an extension of Token containing the extra fields 194 | // required to provide information about calls to Unsubscribe() 195 | type UnsubscribeToken struct { 196 | baseToken 197 | messageID uint16 198 | } 199 | 200 | // DisconnectToken is an extension of Token containing the extra fields 201 | // required to provide information about calls to Disconnect() 202 | type DisconnectToken struct { 203 | baseToken 204 | } 205 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/topic.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | */ 18 | 19 | package mqtt 20 | 21 | import ( 22 | "errors" 23 | "strings" 24 | ) 25 | 26 | // ErrInvalidQos is the error returned when an packet is to be sent 27 | // with an invalid Qos value 28 | var ErrInvalidQos = errors.New("invalid QoS") 29 | 30 | // ErrInvalidTopicEmptyString is the error returned when a topic string 31 | // is passed in that is 0 length 32 | var ErrInvalidTopicEmptyString = errors.New("invalid Topic; empty string") 33 | 34 | // ErrInvalidTopicMultilevel is the error returned when a topic string 35 | // is passed in that has the multi level wildcard in any position but 36 | // the last 37 | var ErrInvalidTopicMultilevel = errors.New("invalid Topic; multi-level wildcard must be last level") 38 | 39 | // Topic Names and Topic Filters 40 | // The MQTT v3.1.1 spec clarifies a number of ambiguities with regard 41 | // to the validity of Topic strings. 42 | // - A Topic must be between 1 and 65535 bytes. 43 | // - A Topic is case sensitive. 44 | // - A Topic may contain whitespace. 45 | // - A Topic containing a leading forward slash is different than a Topic without. 46 | // - A Topic may be "/" (two levels, both empty string). 47 | // - A Topic must be UTF-8 encoded. 48 | // - A Topic may contain any number of levels. 49 | // - A Topic may contain an empty level (two forward slashes in a row). 50 | // - A TopicName may not contain a wildcard. 51 | // - A TopicFilter may only have a # (multi-level) wildcard as the last level. 52 | // - A TopicFilter may contain any number of + (single-level) wildcards. 53 | // - A TopicFilter with a # will match the absence of a level 54 | // Example: a subscription to "foo/#" will match messages published to "foo". 55 | 56 | func validateSubscribeMap(subs map[string]byte) ([]string, []byte, error) { 57 | if len(subs) == 0 { 58 | return nil, nil, errors.New("invalid subscription; subscribe map must not be empty") 59 | } 60 | 61 | var topics []string 62 | var qoss []byte 63 | for topic, qos := range subs { 64 | if err := validateTopicAndQos(topic, qos); err != nil { 65 | return nil, nil, err 66 | } 67 | topics = append(topics, topic) 68 | qoss = append(qoss, qos) 69 | } 70 | 71 | return topics, qoss, nil 72 | } 73 | 74 | func validateTopicAndQos(topic string, qos byte) error { 75 | if len(topic) == 0 { 76 | return ErrInvalidTopicEmptyString 77 | } 78 | 79 | levels := strings.Split(topic, "/") 80 | for i, level := range levels { 81 | if level == "#" && i != len(levels)-1 { 82 | return ErrInvalidTopicMultilevel 83 | } 84 | } 85 | 86 | if qos > 2 { 87 | return ErrInvalidQos 88 | } 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/trace.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 IBM Corp and others. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v2.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * https://www.eclipse.org/legal/epl-2.0/ 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Seth Hoenig 15 | * Allan Stockdill-Mander 16 | * Mike Robertson 17 | */ 18 | 19 | package mqtt 20 | 21 | type ( 22 | // Logger interface allows implementations to provide to this package any 23 | // object that implements the methods defined in it. 24 | Logger interface { 25 | Println(v ...interface{}) 26 | Printf(format string, v ...interface{}) 27 | } 28 | 29 | // NOOPLogger implements the logger that does not perform any operation 30 | // by default. This allows us to efficiently discard the unwanted messages. 31 | NOOPLogger struct{} 32 | ) 33 | 34 | func (NOOPLogger) Println(v ...interface{}) {} 35 | func (NOOPLogger) Printf(format string, v ...interface{}) {} 36 | 37 | // Internal levels of library output that are initialised to not print 38 | // anything but can be overridden by programmer 39 | var ( 40 | ERROR Logger = NOOPLogger{} 41 | CRITICAL Logger = NOOPLogger{} 42 | WARN Logger = NOOPLogger{} 43 | DEBUG Logger = NOOPLogger{} 44 | ) 45 | -------------------------------------------------------------------------------- /vendor/github.com/eclipse/paho.mqtt.golang/websocket.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This program and the accompanying materials 3 | * are made available under the terms of the Eclipse Public License v2.0 4 | * and Eclipse Distribution License v1.0 which accompany this distribution. 5 | * 6 | * The Eclipse Public License is available at 7 | * https://www.eclipse.org/legal/epl-2.0/ 8 | * and the Eclipse Distribution License is available at 9 | * http://www.eclipse.org/org/documents/edl-v10.php. 10 | * 11 | * Contributors: 12 | */ 13 | 14 | package mqtt 15 | 16 | import ( 17 | "crypto/tls" 18 | "fmt" 19 | "io" 20 | "net" 21 | "net/http" 22 | "net/url" 23 | "sync" 24 | "time" 25 | 26 | "github.com/gorilla/websocket" 27 | ) 28 | 29 | // WebsocketOptions are config options for a websocket dialer 30 | type WebsocketOptions struct { 31 | ReadBufferSize int 32 | WriteBufferSize int 33 | Proxy ProxyFunction 34 | } 35 | 36 | type ProxyFunction func(req *http.Request) (*url.URL, error) 37 | 38 | // NewWebsocket returns a new websocket and returns a net.Conn compatible interface using the gorilla/websocket package 39 | func NewWebsocket(host string, tlsc *tls.Config, timeout time.Duration, requestHeader http.Header, options *WebsocketOptions) (net.Conn, error) { 40 | if timeout == 0 { 41 | timeout = 10 * time.Second 42 | } 43 | 44 | if options == nil { 45 | // Apply default options 46 | options = &WebsocketOptions{} 47 | } 48 | if options.Proxy == nil { 49 | options.Proxy = http.ProxyFromEnvironment 50 | } 51 | dialer := &websocket.Dialer{ 52 | Proxy: options.Proxy, 53 | HandshakeTimeout: timeout, 54 | EnableCompression: false, 55 | TLSClientConfig: tlsc, 56 | Subprotocols: []string{"mqtt"}, 57 | ReadBufferSize: options.ReadBufferSize, 58 | WriteBufferSize: options.WriteBufferSize, 59 | } 60 | 61 | ws, resp, err := dialer.Dial(host, requestHeader) 62 | 63 | if err != nil { 64 | if resp != nil { 65 | WARN.Println(CLI, fmt.Sprintf("Websocket handshake failure. StatusCode: %d. Body: %s", resp.StatusCode, resp.Body)) 66 | } 67 | return nil, err 68 | } 69 | 70 | wrapper := &websocketConnector{ 71 | Conn: ws, 72 | } 73 | return wrapper, err 74 | } 75 | 76 | // websocketConnector is a websocket wrapper so it satisfies the net.Conn interface so it is a 77 | // drop in replacement of the golang.org/x/net/websocket package. 78 | // Implementation guide taken from https://github.com/gorilla/websocket/issues/282 79 | type websocketConnector struct { 80 | *websocket.Conn 81 | r io.Reader 82 | rio sync.Mutex 83 | wio sync.Mutex 84 | } 85 | 86 | // SetDeadline sets both the read and write deadlines 87 | func (c *websocketConnector) SetDeadline(t time.Time) error { 88 | if err := c.SetReadDeadline(t); err != nil { 89 | return err 90 | } 91 | err := c.SetWriteDeadline(t) 92 | return err 93 | } 94 | 95 | // Write writes data to the websocket 96 | func (c *websocketConnector) Write(p []byte) (int, error) { 97 | c.wio.Lock() 98 | defer c.wio.Unlock() 99 | 100 | err := c.WriteMessage(websocket.BinaryMessage, p) 101 | if err != nil { 102 | return 0, err 103 | } 104 | return len(p), nil 105 | } 106 | 107 | // Read reads the current websocket frame 108 | func (c *websocketConnector) Read(p []byte) (int, error) { 109 | c.rio.Lock() 110 | defer c.rio.Unlock() 111 | for { 112 | if c.r == nil { 113 | // Advance to next message. 114 | var err error 115 | _, c.r, err = c.NextReader() 116 | if err != nil { 117 | return 0, err 118 | } 119 | } 120 | n, err := c.r.Read(p) 121 | if err == io.EOF { 122 | // At end of message. 123 | c.r = nil 124 | if n > 0 { 125 | return n, nil 126 | } 127 | // No data read, continue to next message. 128 | continue 129 | } 130 | return n, err 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | 24 | .idea/ 25 | *.iml 26 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Gorilla WebSocket authors for copyright 2 | # purposes. 3 | # 4 | # Please keep the list sorted. 5 | 6 | Gary Burd 7 | Google LLC (https://opensource.google.com/) 8 | Joachim Bauch 9 | 10 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/README.md: -------------------------------------------------------------------------------- 1 | # Gorilla WebSocket 2 | 3 | [![GoDoc](https://godoc.org/github.com/gorilla/websocket?status.svg)](https://godoc.org/github.com/gorilla/websocket) 4 | [![CircleCI](https://circleci.com/gh/gorilla/websocket.svg?style=svg)](https://circleci.com/gh/gorilla/websocket) 5 | 6 | Gorilla WebSocket is a [Go](http://golang.org/) implementation of the 7 | [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. 8 | 9 | ### Documentation 10 | 11 | * [API Reference](https://pkg.go.dev/github.com/gorilla/websocket?tab=doc) 12 | * [Chat example](https://github.com/gorilla/websocket/tree/master/examples/chat) 13 | * [Command example](https://github.com/gorilla/websocket/tree/master/examples/command) 14 | * [Client and server example](https://github.com/gorilla/websocket/tree/master/examples/echo) 15 | * [File watch example](https://github.com/gorilla/websocket/tree/master/examples/filewatch) 16 | 17 | ### Status 18 | 19 | The Gorilla WebSocket package provides a complete and tested implementation of 20 | the [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. The 21 | package API is stable. 22 | 23 | ### Installation 24 | 25 | go get github.com/gorilla/websocket 26 | 27 | ### Protocol Compliance 28 | 29 | The Gorilla WebSocket package passes the server tests in the [Autobahn Test 30 | Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn 31 | subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn). 32 | 33 | ### Gorilla WebSocket compared with other packages 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |
github.com/gorillagolang.org/x/net
RFC 6455 Features
Passes Autobahn Test SuiteYesNo
Receive fragmented messageYesNo, see note 1
Send close messageYesNo
Send pings and receive pongsYesNo
Get the type of a received data messageYesYes, see note 2
Other Features
Compression ExtensionsExperimentalNo
Read message using io.ReaderYesNo, see note 3
Write message using io.WriteCloserYesNo, see note 3
53 | 54 | Notes: 55 | 56 | 1. Large messages are fragmented in [Chrome's new WebSocket implementation](http://www.ietf.org/mail-archive/web/hybi/current/msg10503.html). 57 | 2. The application can get the type of a received data message by implementing 58 | a [Codec marshal](http://godoc.org/golang.org/x/net/websocket#Codec.Marshal) 59 | function. 60 | 3. The go.net io.Reader and io.Writer operate across WebSocket frame boundaries. 61 | Read returns when the input buffer is full or a frame boundary is 62 | encountered. Each call to Write sends a single frame message. The Gorilla 63 | io.Reader and io.WriteCloser operate on a single WebSocket message. 64 | 65 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/client_clone.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.8 6 | 7 | package websocket 8 | 9 | import "crypto/tls" 10 | 11 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 12 | if cfg == nil { 13 | return &tls.Config{} 14 | } 15 | return cfg.Clone() 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/client_clone_legacy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.8 6 | 7 | package websocket 8 | 9 | import "crypto/tls" 10 | 11 | // cloneTLSConfig clones all public fields except the fields 12 | // SessionTicketsDisabled and SessionTicketKey. This avoids copying the 13 | // sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a 14 | // config in active use. 15 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 16 | if cfg == nil { 17 | return &tls.Config{} 18 | } 19 | return &tls.Config{ 20 | Rand: cfg.Rand, 21 | Time: cfg.Time, 22 | Certificates: cfg.Certificates, 23 | NameToCertificate: cfg.NameToCertificate, 24 | GetCertificate: cfg.GetCertificate, 25 | RootCAs: cfg.RootCAs, 26 | NextProtos: cfg.NextProtos, 27 | ServerName: cfg.ServerName, 28 | ClientAuth: cfg.ClientAuth, 29 | ClientCAs: cfg.ClientCAs, 30 | InsecureSkipVerify: cfg.InsecureSkipVerify, 31 | CipherSuites: cfg.CipherSuites, 32 | PreferServerCipherSuites: cfg.PreferServerCipherSuites, 33 | ClientSessionCache: cfg.ClientSessionCache, 34 | MinVersion: cfg.MinVersion, 35 | MaxVersion: cfg.MaxVersion, 36 | CurvePreferences: cfg.CurvePreferences, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/compression.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "compress/flate" 9 | "errors" 10 | "io" 11 | "strings" 12 | "sync" 13 | ) 14 | 15 | const ( 16 | minCompressionLevel = -2 // flate.HuffmanOnly not defined in Go < 1.6 17 | maxCompressionLevel = flate.BestCompression 18 | defaultCompressionLevel = 1 19 | ) 20 | 21 | var ( 22 | flateWriterPools [maxCompressionLevel - minCompressionLevel + 1]sync.Pool 23 | flateReaderPool = sync.Pool{New: func() interface{} { 24 | return flate.NewReader(nil) 25 | }} 26 | ) 27 | 28 | func decompressNoContextTakeover(r io.Reader) io.ReadCloser { 29 | const tail = 30 | // Add four bytes as specified in RFC 31 | "\x00\x00\xff\xff" + 32 | // Add final block to squelch unexpected EOF error from flate reader. 33 | "\x01\x00\x00\xff\xff" 34 | 35 | fr, _ := flateReaderPool.Get().(io.ReadCloser) 36 | fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil) 37 | return &flateReadWrapper{fr} 38 | } 39 | 40 | func isValidCompressionLevel(level int) bool { 41 | return minCompressionLevel <= level && level <= maxCompressionLevel 42 | } 43 | 44 | func compressNoContextTakeover(w io.WriteCloser, level int) io.WriteCloser { 45 | p := &flateWriterPools[level-minCompressionLevel] 46 | tw := &truncWriter{w: w} 47 | fw, _ := p.Get().(*flate.Writer) 48 | if fw == nil { 49 | fw, _ = flate.NewWriter(tw, level) 50 | } else { 51 | fw.Reset(tw) 52 | } 53 | return &flateWriteWrapper{fw: fw, tw: tw, p: p} 54 | } 55 | 56 | // truncWriter is an io.Writer that writes all but the last four bytes of the 57 | // stream to another io.Writer. 58 | type truncWriter struct { 59 | w io.WriteCloser 60 | n int 61 | p [4]byte 62 | } 63 | 64 | func (w *truncWriter) Write(p []byte) (int, error) { 65 | n := 0 66 | 67 | // fill buffer first for simplicity. 68 | if w.n < len(w.p) { 69 | n = copy(w.p[w.n:], p) 70 | p = p[n:] 71 | w.n += n 72 | if len(p) == 0 { 73 | return n, nil 74 | } 75 | } 76 | 77 | m := len(p) 78 | if m > len(w.p) { 79 | m = len(w.p) 80 | } 81 | 82 | if nn, err := w.w.Write(w.p[:m]); err != nil { 83 | return n + nn, err 84 | } 85 | 86 | copy(w.p[:], w.p[m:]) 87 | copy(w.p[len(w.p)-m:], p[len(p)-m:]) 88 | nn, err := w.w.Write(p[:len(p)-m]) 89 | return n + nn, err 90 | } 91 | 92 | type flateWriteWrapper struct { 93 | fw *flate.Writer 94 | tw *truncWriter 95 | p *sync.Pool 96 | } 97 | 98 | func (w *flateWriteWrapper) Write(p []byte) (int, error) { 99 | if w.fw == nil { 100 | return 0, errWriteClosed 101 | } 102 | return w.fw.Write(p) 103 | } 104 | 105 | func (w *flateWriteWrapper) Close() error { 106 | if w.fw == nil { 107 | return errWriteClosed 108 | } 109 | err1 := w.fw.Flush() 110 | w.p.Put(w.fw) 111 | w.fw = nil 112 | if w.tw.p != [4]byte{0, 0, 0xff, 0xff} { 113 | return errors.New("websocket: internal error, unexpected bytes at end of flate stream") 114 | } 115 | err2 := w.tw.w.Close() 116 | if err1 != nil { 117 | return err1 118 | } 119 | return err2 120 | } 121 | 122 | type flateReadWrapper struct { 123 | fr io.ReadCloser 124 | } 125 | 126 | func (r *flateReadWrapper) Read(p []byte) (int, error) { 127 | if r.fr == nil { 128 | return 0, io.ErrClosedPipe 129 | } 130 | n, err := r.fr.Read(p) 131 | if err == io.EOF { 132 | // Preemptively place the reader back in the pool. This helps with 133 | // scenarios where the application does not call NextReader() soon after 134 | // this final read. 135 | r.Close() 136 | } 137 | return n, err 138 | } 139 | 140 | func (r *flateReadWrapper) Close() error { 141 | if r.fr == nil { 142 | return io.ErrClosedPipe 143 | } 144 | err := r.fr.Close() 145 | flateReaderPool.Put(r.fr) 146 | r.fr = nil 147 | return err 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/conn_write.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.8 6 | 7 | package websocket 8 | 9 | import "net" 10 | 11 | func (c *Conn) writeBufs(bufs ...[]byte) error { 12 | b := net.Buffers(bufs) 13 | _, err := b.WriteTo(c.conn) 14 | return err 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/conn_write_legacy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.8 6 | 7 | package websocket 8 | 9 | func (c *Conn) writeBufs(bufs ...[]byte) error { 10 | for _, buf := range bufs { 11 | if len(buf) > 0 { 12 | if _, err := c.conn.Write(buf); err != nil { 13 | return err 14 | } 15 | } 16 | } 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/join.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "io" 9 | "strings" 10 | ) 11 | 12 | // JoinMessages concatenates received messages to create a single io.Reader. 13 | // The string term is appended to each message. The returned reader does not 14 | // support concurrent calls to the Read method. 15 | func JoinMessages(c *Conn, term string) io.Reader { 16 | return &joinReader{c: c, term: term} 17 | } 18 | 19 | type joinReader struct { 20 | c *Conn 21 | term string 22 | r io.Reader 23 | } 24 | 25 | func (r *joinReader) Read(p []byte) (int, error) { 26 | if r.r == nil { 27 | var err error 28 | _, r.r, err = r.c.NextReader() 29 | if err != nil { 30 | return 0, err 31 | } 32 | if r.term != "" { 33 | r.r = io.MultiReader(r.r, strings.NewReader(r.term)) 34 | } 35 | } 36 | n, err := r.r.Read(p) 37 | if err == io.EOF { 38 | err = nil 39 | r.r = nil 40 | } 41 | return n, err 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/json.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "encoding/json" 9 | "io" 10 | ) 11 | 12 | // WriteJSON writes the JSON encoding of v as a message. 13 | // 14 | // Deprecated: Use c.WriteJSON instead. 15 | func WriteJSON(c *Conn, v interface{}) error { 16 | return c.WriteJSON(v) 17 | } 18 | 19 | // WriteJSON writes the JSON encoding of v as a message. 20 | // 21 | // See the documentation for encoding/json Marshal for details about the 22 | // conversion of Go values to JSON. 23 | func (c *Conn) WriteJSON(v interface{}) error { 24 | w, err := c.NextWriter(TextMessage) 25 | if err != nil { 26 | return err 27 | } 28 | err1 := json.NewEncoder(w).Encode(v) 29 | err2 := w.Close() 30 | if err1 != nil { 31 | return err1 32 | } 33 | return err2 34 | } 35 | 36 | // ReadJSON reads the next JSON-encoded message from the connection and stores 37 | // it in the value pointed to by v. 38 | // 39 | // Deprecated: Use c.ReadJSON instead. 40 | func ReadJSON(c *Conn, v interface{}) error { 41 | return c.ReadJSON(v) 42 | } 43 | 44 | // ReadJSON reads the next JSON-encoded message from the connection and stores 45 | // it in the value pointed to by v. 46 | // 47 | // See the documentation for the encoding/json Unmarshal function for details 48 | // about the conversion of JSON to a Go value. 49 | func (c *Conn) ReadJSON(v interface{}) error { 50 | _, r, err := c.NextReader() 51 | if err != nil { 52 | return err 53 | } 54 | err = json.NewDecoder(r).Decode(v) 55 | if err == io.EOF { 56 | // One value is expected in the message. 57 | err = io.ErrUnexpectedEOF 58 | } 59 | return err 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/mask.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // +build !appengine 6 | 7 | package websocket 8 | 9 | import "unsafe" 10 | 11 | const wordSize = int(unsafe.Sizeof(uintptr(0))) 12 | 13 | func maskBytes(key [4]byte, pos int, b []byte) int { 14 | // Mask one byte at a time for small buffers. 15 | if len(b) < 2*wordSize { 16 | for i := range b { 17 | b[i] ^= key[pos&3] 18 | pos++ 19 | } 20 | return pos & 3 21 | } 22 | 23 | // Mask one byte at a time to word boundary. 24 | if n := int(uintptr(unsafe.Pointer(&b[0]))) % wordSize; n != 0 { 25 | n = wordSize - n 26 | for i := range b[:n] { 27 | b[i] ^= key[pos&3] 28 | pos++ 29 | } 30 | b = b[n:] 31 | } 32 | 33 | // Create aligned word size key. 34 | var k [wordSize]byte 35 | for i := range k { 36 | k[i] = key[(pos+i)&3] 37 | } 38 | kw := *(*uintptr)(unsafe.Pointer(&k)) 39 | 40 | // Mask one word at a time. 41 | n := (len(b) / wordSize) * wordSize 42 | for i := 0; i < n; i += wordSize { 43 | *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(i))) ^= kw 44 | } 45 | 46 | // Mask one byte at a time for remaining bytes. 47 | b = b[n:] 48 | for i := range b { 49 | b[i] ^= key[pos&3] 50 | pos++ 51 | } 52 | 53 | return pos & 3 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/mask_safe.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // +build appengine 6 | 7 | package websocket 8 | 9 | func maskBytes(key [4]byte, pos int, b []byte) int { 10 | for i := range b { 11 | b[i] ^= key[pos&3] 12 | pos++ 13 | } 14 | return pos & 3 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/prepared.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bytes" 9 | "net" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | // PreparedMessage caches on the wire representations of a message payload. 15 | // Use PreparedMessage to efficiently send a message payload to multiple 16 | // connections. PreparedMessage is especially useful when compression is used 17 | // because the CPU and memory expensive compression operation can be executed 18 | // once for a given set of compression options. 19 | type PreparedMessage struct { 20 | messageType int 21 | data []byte 22 | mu sync.Mutex 23 | frames map[prepareKey]*preparedFrame 24 | } 25 | 26 | // prepareKey defines a unique set of options to cache prepared frames in PreparedMessage. 27 | type prepareKey struct { 28 | isServer bool 29 | compress bool 30 | compressionLevel int 31 | } 32 | 33 | // preparedFrame contains data in wire representation. 34 | type preparedFrame struct { 35 | once sync.Once 36 | data []byte 37 | } 38 | 39 | // NewPreparedMessage returns an initialized PreparedMessage. You can then send 40 | // it to connection using WritePreparedMessage method. Valid wire 41 | // representation will be calculated lazily only once for a set of current 42 | // connection options. 43 | func NewPreparedMessage(messageType int, data []byte) (*PreparedMessage, error) { 44 | pm := &PreparedMessage{ 45 | messageType: messageType, 46 | frames: make(map[prepareKey]*preparedFrame), 47 | data: data, 48 | } 49 | 50 | // Prepare a plain server frame. 51 | _, frameData, err := pm.frame(prepareKey{isServer: true, compress: false}) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | // To protect against caller modifying the data argument, remember the data 57 | // copied to the plain server frame. 58 | pm.data = frameData[len(frameData)-len(data):] 59 | return pm, nil 60 | } 61 | 62 | func (pm *PreparedMessage) frame(key prepareKey) (int, []byte, error) { 63 | pm.mu.Lock() 64 | frame, ok := pm.frames[key] 65 | if !ok { 66 | frame = &preparedFrame{} 67 | pm.frames[key] = frame 68 | } 69 | pm.mu.Unlock() 70 | 71 | var err error 72 | frame.once.Do(func() { 73 | // Prepare a frame using a 'fake' connection. 74 | // TODO: Refactor code in conn.go to allow more direct construction of 75 | // the frame. 76 | mu := make(chan struct{}, 1) 77 | mu <- struct{}{} 78 | var nc prepareConn 79 | c := &Conn{ 80 | conn: &nc, 81 | mu: mu, 82 | isServer: key.isServer, 83 | compressionLevel: key.compressionLevel, 84 | enableWriteCompression: true, 85 | writeBuf: make([]byte, defaultWriteBufferSize+maxFrameHeaderSize), 86 | } 87 | if key.compress { 88 | c.newCompressionWriter = compressNoContextTakeover 89 | } 90 | err = c.WriteMessage(pm.messageType, pm.data) 91 | frame.data = nc.buf.Bytes() 92 | }) 93 | return pm.messageType, frame.data, err 94 | } 95 | 96 | type prepareConn struct { 97 | buf bytes.Buffer 98 | net.Conn 99 | } 100 | 101 | func (pc *prepareConn) Write(p []byte) (int, error) { return pc.buf.Write(p) } 102 | func (pc *prepareConn) SetWriteDeadline(t time.Time) error { return nil } 103 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/proxy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bufio" 9 | "encoding/base64" 10 | "errors" 11 | "net" 12 | "net/http" 13 | "net/url" 14 | "strings" 15 | ) 16 | 17 | type netDialerFunc func(network, addr string) (net.Conn, error) 18 | 19 | func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) { 20 | return fn(network, addr) 21 | } 22 | 23 | func init() { 24 | proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) { 25 | return &httpProxyDialer{proxyURL: proxyURL, forwardDial: forwardDialer.Dial}, nil 26 | }) 27 | } 28 | 29 | type httpProxyDialer struct { 30 | proxyURL *url.URL 31 | forwardDial func(network, addr string) (net.Conn, error) 32 | } 33 | 34 | func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) { 35 | hostPort, _ := hostPortNoPort(hpd.proxyURL) 36 | conn, err := hpd.forwardDial(network, hostPort) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | connectHeader := make(http.Header) 42 | if user := hpd.proxyURL.User; user != nil { 43 | proxyUser := user.Username() 44 | if proxyPassword, passwordSet := user.Password(); passwordSet { 45 | credential := base64.StdEncoding.EncodeToString([]byte(proxyUser + ":" + proxyPassword)) 46 | connectHeader.Set("Proxy-Authorization", "Basic "+credential) 47 | } 48 | } 49 | 50 | connectReq := &http.Request{ 51 | Method: "CONNECT", 52 | URL: &url.URL{Opaque: addr}, 53 | Host: addr, 54 | Header: connectHeader, 55 | } 56 | 57 | if err := connectReq.Write(conn); err != nil { 58 | conn.Close() 59 | return nil, err 60 | } 61 | 62 | // Read response. It's OK to use and discard buffered reader here becaue 63 | // the remote server does not speak until spoken to. 64 | br := bufio.NewReader(conn) 65 | resp, err := http.ReadResponse(br, connectReq) 66 | if err != nil { 67 | conn.Close() 68 | return nil, err 69 | } 70 | 71 | if resp.StatusCode != 200 { 72 | conn.Close() 73 | f := strings.SplitN(resp.Status, " ", 2) 74 | return nil, errors.New(f[1]) 75 | } 76 | return conn, nil 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/trace.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | package websocket 4 | 5 | import ( 6 | "crypto/tls" 7 | "net/http/httptrace" 8 | ) 9 | 10 | func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { 11 | if trace.TLSHandshakeStart != nil { 12 | trace.TLSHandshakeStart() 13 | } 14 | err := doHandshake(tlsConn, cfg) 15 | if trace.TLSHandshakeDone != nil { 16 | trace.TLSHandshakeDone(tlsConn.ConnectionState(), err) 17 | } 18 | return err 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/trace_17.go: -------------------------------------------------------------------------------- 1 | // +build !go1.8 2 | 3 | package websocket 4 | 5 | import ( 6 | "crypto/tls" 7 | "net/http/httptrace" 8 | ) 9 | 10 | func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { 11 | return doHandshake(tlsConn, cfg) 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "crypto/rand" 9 | "crypto/sha1" 10 | "encoding/base64" 11 | "io" 12 | "net/http" 13 | "strings" 14 | "unicode/utf8" 15 | ) 16 | 17 | var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11") 18 | 19 | func computeAcceptKey(challengeKey string) string { 20 | h := sha1.New() 21 | h.Write([]byte(challengeKey)) 22 | h.Write(keyGUID) 23 | return base64.StdEncoding.EncodeToString(h.Sum(nil)) 24 | } 25 | 26 | func generateChallengeKey() (string, error) { 27 | p := make([]byte, 16) 28 | if _, err := io.ReadFull(rand.Reader, p); err != nil { 29 | return "", err 30 | } 31 | return base64.StdEncoding.EncodeToString(p), nil 32 | } 33 | 34 | // Token octets per RFC 2616. 35 | var isTokenOctet = [256]bool{ 36 | '!': true, 37 | '#': true, 38 | '$': true, 39 | '%': true, 40 | '&': true, 41 | '\'': true, 42 | '*': true, 43 | '+': true, 44 | '-': true, 45 | '.': true, 46 | '0': true, 47 | '1': true, 48 | '2': true, 49 | '3': true, 50 | '4': true, 51 | '5': true, 52 | '6': true, 53 | '7': true, 54 | '8': true, 55 | '9': true, 56 | 'A': true, 57 | 'B': true, 58 | 'C': true, 59 | 'D': true, 60 | 'E': true, 61 | 'F': true, 62 | 'G': true, 63 | 'H': true, 64 | 'I': true, 65 | 'J': true, 66 | 'K': true, 67 | 'L': true, 68 | 'M': true, 69 | 'N': true, 70 | 'O': true, 71 | 'P': true, 72 | 'Q': true, 73 | 'R': true, 74 | 'S': true, 75 | 'T': true, 76 | 'U': true, 77 | 'W': true, 78 | 'V': true, 79 | 'X': true, 80 | 'Y': true, 81 | 'Z': true, 82 | '^': true, 83 | '_': true, 84 | '`': true, 85 | 'a': true, 86 | 'b': true, 87 | 'c': true, 88 | 'd': true, 89 | 'e': true, 90 | 'f': true, 91 | 'g': true, 92 | 'h': true, 93 | 'i': true, 94 | 'j': true, 95 | 'k': true, 96 | 'l': true, 97 | 'm': true, 98 | 'n': true, 99 | 'o': true, 100 | 'p': true, 101 | 'q': true, 102 | 'r': true, 103 | 's': true, 104 | 't': true, 105 | 'u': true, 106 | 'v': true, 107 | 'w': true, 108 | 'x': true, 109 | 'y': true, 110 | 'z': true, 111 | '|': true, 112 | '~': true, 113 | } 114 | 115 | // skipSpace returns a slice of the string s with all leading RFC 2616 linear 116 | // whitespace removed. 117 | func skipSpace(s string) (rest string) { 118 | i := 0 119 | for ; i < len(s); i++ { 120 | if b := s[i]; b != ' ' && b != '\t' { 121 | break 122 | } 123 | } 124 | return s[i:] 125 | } 126 | 127 | // nextToken returns the leading RFC 2616 token of s and the string following 128 | // the token. 129 | func nextToken(s string) (token, rest string) { 130 | i := 0 131 | for ; i < len(s); i++ { 132 | if !isTokenOctet[s[i]] { 133 | break 134 | } 135 | } 136 | return s[:i], s[i:] 137 | } 138 | 139 | // nextTokenOrQuoted returns the leading token or quoted string per RFC 2616 140 | // and the string following the token or quoted string. 141 | func nextTokenOrQuoted(s string) (value string, rest string) { 142 | if !strings.HasPrefix(s, "\"") { 143 | return nextToken(s) 144 | } 145 | s = s[1:] 146 | for i := 0; i < len(s); i++ { 147 | switch s[i] { 148 | case '"': 149 | return s[:i], s[i+1:] 150 | case '\\': 151 | p := make([]byte, len(s)-1) 152 | j := copy(p, s[:i]) 153 | escape := true 154 | for i = i + 1; i < len(s); i++ { 155 | b := s[i] 156 | switch { 157 | case escape: 158 | escape = false 159 | p[j] = b 160 | j++ 161 | case b == '\\': 162 | escape = true 163 | case b == '"': 164 | return string(p[:j]), s[i+1:] 165 | default: 166 | p[j] = b 167 | j++ 168 | } 169 | } 170 | return "", "" 171 | } 172 | } 173 | return "", "" 174 | } 175 | 176 | // equalASCIIFold returns true if s is equal to t with ASCII case folding as 177 | // defined in RFC 4790. 178 | func equalASCIIFold(s, t string) bool { 179 | for s != "" && t != "" { 180 | sr, size := utf8.DecodeRuneInString(s) 181 | s = s[size:] 182 | tr, size := utf8.DecodeRuneInString(t) 183 | t = t[size:] 184 | if sr == tr { 185 | continue 186 | } 187 | if 'A' <= sr && sr <= 'Z' { 188 | sr = sr + 'a' - 'A' 189 | } 190 | if 'A' <= tr && tr <= 'Z' { 191 | tr = tr + 'a' - 'A' 192 | } 193 | if sr != tr { 194 | return false 195 | } 196 | } 197 | return s == t 198 | } 199 | 200 | // tokenListContainsValue returns true if the 1#token header with the given 201 | // name contains a token equal to value with ASCII case folding. 202 | func tokenListContainsValue(header http.Header, name string, value string) bool { 203 | headers: 204 | for _, s := range header[name] { 205 | for { 206 | var t string 207 | t, s = nextToken(skipSpace(s)) 208 | if t == "" { 209 | continue headers 210 | } 211 | s = skipSpace(s) 212 | if s != "" && s[0] != ',' { 213 | continue headers 214 | } 215 | if equalASCIIFold(t, value) { 216 | return true 217 | } 218 | if s == "" { 219 | continue headers 220 | } 221 | s = s[1:] 222 | } 223 | } 224 | return false 225 | } 226 | 227 | // parseExtensions parses WebSocket extensions from a header. 228 | func parseExtensions(header http.Header) []map[string]string { 229 | // From RFC 6455: 230 | // 231 | // Sec-WebSocket-Extensions = extension-list 232 | // extension-list = 1#extension 233 | // extension = extension-token *( ";" extension-param ) 234 | // extension-token = registered-token 235 | // registered-token = token 236 | // extension-param = token [ "=" (token | quoted-string) ] 237 | // ;When using the quoted-string syntax variant, the value 238 | // ;after quoted-string unescaping MUST conform to the 239 | // ;'token' ABNF. 240 | 241 | var result []map[string]string 242 | headers: 243 | for _, s := range header["Sec-Websocket-Extensions"] { 244 | for { 245 | var t string 246 | t, s = nextToken(skipSpace(s)) 247 | if t == "" { 248 | continue headers 249 | } 250 | ext := map[string]string{"": t} 251 | for { 252 | s = skipSpace(s) 253 | if !strings.HasPrefix(s, ";") { 254 | break 255 | } 256 | var k string 257 | k, s = nextToken(skipSpace(s[1:])) 258 | if k == "" { 259 | continue headers 260 | } 261 | s = skipSpace(s) 262 | var v string 263 | if strings.HasPrefix(s, "=") { 264 | v, s = nextTokenOrQuoted(skipSpace(s[1:])) 265 | s = skipSpace(s) 266 | } 267 | if s != "" && s[0] != ',' && s[0] != ';' { 268 | continue headers 269 | } 270 | ext[k] = v 271 | } 272 | if s != "" && s[0] != ',' { 273 | continue headers 274 | } 275 | result = append(result, ext) 276 | if s == "" { 277 | continue headers 278 | } 279 | s = s[1:] 280 | } 281 | } 282 | return result 283 | } 284 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/connector-sdk/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2020 Alex Ellis 4 | Copyright (c) 2017-2020 OpenFaaS Project 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/connector-sdk/types/controller.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s) 2019. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package types 5 | 6 | import ( 7 | "context" 8 | "fmt" 9 | "log" 10 | "net/http" 11 | "sync" 12 | "time" 13 | 14 | "github.com/openfaas/faas-provider/auth" 15 | ) 16 | 17 | // ControllerConfig configures a connector SDK controller 18 | type ControllerConfig struct { 19 | // UpstreamTimeout controls maximum timeout invoking a function via the gateway 20 | UpstreamTimeout time.Duration 21 | 22 | // GatewayURL is the remote OpenFaaS gateway 23 | GatewayURL string 24 | 25 | // PrintResponse if true prints the function responses 26 | PrintResponse bool 27 | 28 | // PrintResponseBody prints the function's response body to stdout 29 | PrintResponseBody bool 30 | 31 | // PrintRequestBody prints the request's body to stdout. 32 | PrintRequestBody bool 33 | 34 | // RebuildInterval the interval at which the topic map is rebuilt 35 | RebuildInterval time.Duration 36 | 37 | // TopicAnnotationDelimiter defines the character upon which to split the Topic annotation value 38 | TopicAnnotationDelimiter string 39 | 40 | // AsyncFunctionInvocation if true points to the asynchronous function route 41 | AsyncFunctionInvocation bool 42 | 43 | // PrintSync indicates whether the sync should be logged. 44 | PrintSync bool 45 | 46 | // ContentType defines which content type will be set in the header to inkoke the function. i.e "application/json". 47 | // Optional, if not set the Content-Type header will not be set. 48 | ContentType string 49 | 50 | // BasicAuth whether basic auth is enabled or disabled 51 | BasicAuth bool 52 | } 53 | 54 | // Controller is used to invoke functions on a per-topic basis and to subscribe to responses returned by said functions. 55 | type Controller interface { 56 | Subscribe(subscriber ResponseSubscriber) 57 | Invoke(topic string, message *[]byte, headers http.Header) 58 | InvokeWithContext(ctx context.Context, topic string, message *[]byte, headers http.Header) 59 | BeginMapBuilder() 60 | Topics() []string 61 | } 62 | 63 | // controller is the default implementation of the Controller interface. 64 | type controller struct { 65 | // Config for the controller 66 | Config *ControllerConfig 67 | 68 | // Invoker to invoke functions via HTTP(s) 69 | Invoker *Invoker 70 | 71 | // Map of which functions subscribe to which topics 72 | TopicMap *TopicMap 73 | 74 | // Credentials to access gateway 75 | Credentials *auth.BasicAuthCredentials 76 | 77 | // Subscribers which can receive messages from invocations. 78 | // See note on ResponseSubscriber interface about blocking/long-running 79 | // operations 80 | Subscribers []ResponseSubscriber 81 | 82 | // Lock used for synchronizing subscribers 83 | Lock *sync.RWMutex 84 | } 85 | 86 | // NewController create a new connector SDK controller 87 | func NewController(credentials *auth.BasicAuthCredentials, config *ControllerConfig) Controller { 88 | 89 | gatewayFunctionPath := gatewayRoute(config) 90 | 91 | invoker := NewInvoker(gatewayFunctionPath, 92 | MakeClient(config.UpstreamTimeout), 93 | config.ContentType, 94 | config.PrintResponse, 95 | config.PrintRequestBody) 96 | 97 | subs := []ResponseSubscriber{} 98 | 99 | topicMap := NewTopicMap() 100 | 101 | c := controller{ 102 | Config: config, 103 | Invoker: invoker, 104 | TopicMap: &topicMap, 105 | Credentials: credentials, 106 | Subscribers: subs, 107 | Lock: &sync.RWMutex{}, 108 | } 109 | 110 | if config.PrintResponse { 111 | c.Subscribe(&ResponsePrinter{config.PrintResponseBody}) 112 | } 113 | 114 | go func(ch *chan InvokerResponse, controller *controller) { 115 | for { 116 | res := <-*ch 117 | 118 | controller.Lock.RLock() 119 | for _, sub := range controller.Subscribers { 120 | sub.Response(res) 121 | } 122 | controller.Lock.RUnlock() 123 | } 124 | }(&invoker.Responses, &c) 125 | 126 | return &c 127 | } 128 | 129 | // Subscribe adds a ResponseSubscriber to the list of subscribers 130 | // which receive messages upon function invocation or error 131 | // Note: it is not possible to Unsubscribe at this point using 132 | // the API of the controller 133 | func (c *controller) Subscribe(subscriber ResponseSubscriber) { 134 | c.Lock.Lock() 135 | defer c.Lock.Unlock() 136 | c.Subscribers = append(c.Subscribers, subscriber) 137 | } 138 | 139 | // Invoke attempts to invoke any functions which match the 140 | // topic the incoming message was published on. 141 | func (c *controller) Invoke(topic string, message *[]byte, headers http.Header) { 142 | c.InvokeWithContext(context.Background(), topic, message, headers) 143 | } 144 | 145 | // InvokeWithContext attempts to invoke any functions which match the topic 146 | // the incoming message was published on while propagating context. 147 | func (c *controller) InvokeWithContext(ctx context.Context, topic string, message *[]byte, headers http.Header) { 148 | c.Invoker.InvokeWithContext(ctx, c.TopicMap, topic, message, headers) 149 | } 150 | 151 | // BeginMapBuilder begins to build a map of function->topic by 152 | // querying the API gateway. 153 | func (c *controller) BeginMapBuilder() { 154 | 155 | lookupBuilder := FunctionLookupBuilder{ 156 | GatewayURL: c.Config.GatewayURL, 157 | Client: MakeClient(c.Config.UpstreamTimeout), 158 | Credentials: c.Credentials, 159 | TopicDelimiter: c.Config.TopicAnnotationDelimiter, 160 | } 161 | 162 | ticker := time.NewTicker(c.Config.RebuildInterval) 163 | go c.synchronizeLookups(ticker, &lookupBuilder, c.TopicMap) 164 | } 165 | 166 | func (c *controller) synchronizeLookups(ticker *time.Ticker, 167 | lookupBuilder *FunctionLookupBuilder, 168 | topicMap *TopicMap) { 169 | 170 | fn := func() { 171 | lookups, err := lookupBuilder.Build() 172 | if err != nil { 173 | log.Fatalln(err) 174 | } 175 | 176 | if c.Config.PrintSync { 177 | log.Println("Syncing topic map") 178 | } 179 | 180 | topicMap.Sync(&lookups) 181 | } 182 | 183 | fn() 184 | for { 185 | <-ticker.C 186 | fn() 187 | } 188 | } 189 | 190 | // Topics gets the list of topics that functions have indicated should 191 | // be used as triggers. 192 | func (c *controller) Topics() []string { 193 | return c.TopicMap.Topics() 194 | } 195 | 196 | func gatewayRoute(config *ControllerConfig) string { 197 | if config.AsyncFunctionInvocation { 198 | return fmt.Sprintf("%s/%s", config.GatewayURL, "async-function") 199 | } 200 | return fmt.Sprintf("%s/%s", config.GatewayURL, "function") 201 | } 202 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/connector-sdk/types/credentials.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s) 2019. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package types 5 | 6 | import ( 7 | "os" 8 | 9 | "github.com/openfaas/faas-provider/auth" 10 | ) 11 | 12 | func GetCredentials() *auth.BasicAuthCredentials { 13 | var credentials *auth.BasicAuthCredentials 14 | 15 | if val, ok := os.LookupEnv("basic_auth"); ok && len(val) > 0 { 16 | if val == "true" || val == "1" { 17 | 18 | reader := auth.ReadBasicAuthFromDisk{} 19 | 20 | if val, ok := os.LookupEnv("secret_mount_path"); ok && len(val) > 0 { 21 | reader.SecretMountPath = os.Getenv("secret_mount_path") 22 | } 23 | 24 | res, err := reader.Read() 25 | if err != nil { 26 | panic(err) 27 | } 28 | credentials = res 29 | } 30 | } 31 | return credentials 32 | } 33 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/connector-sdk/types/function_list_builder.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s) 2019. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package types 5 | 6 | import ( 7 | "encoding/json" 8 | "fmt" 9 | "io/ioutil" 10 | "net/http" 11 | "net/url" 12 | "strings" 13 | 14 | "github.com/openfaas/faas-provider/auth" 15 | "github.com/openfaas/faas-provider/types" 16 | ) 17 | 18 | // FunctionLookupBuilder builds a list of OpenFaaS functions 19 | type FunctionLookupBuilder struct { 20 | GatewayURL string 21 | Client *http.Client 22 | Credentials *auth.BasicAuthCredentials 23 | TopicDelimiter string 24 | } 25 | 26 | // Build compiles a map of topic names and functions that have 27 | // advertised to receive messages on said topic 28 | func (s *FunctionLookupBuilder) Build() (map[string][]string, error) { 29 | var err error 30 | 31 | namespaces, err := s.getNamespaces() 32 | if err != nil { 33 | return map[string][]string{}, err 34 | } 35 | 36 | serviceMap := make(map[string][]string) 37 | 38 | if len(namespaces) == 0 { 39 | namespace := "" 40 | functions, err := s.getFunctions(namespace) 41 | if err != nil { 42 | return map[string][]string{}, fmt.Errorf("unable to get functions: %w", err) 43 | } 44 | serviceMap = buildServiceMap(&functions, s.TopicDelimiter, namespace, serviceMap) 45 | } else { 46 | for _, namespace := range namespaces { 47 | functions, err := s.getFunctions(namespace) 48 | if err != nil { 49 | return map[string][]string{}, fmt.Errorf("unable to get functions in: %s, error: %w", namespace, err) 50 | } 51 | serviceMap = buildServiceMap(&functions, s.TopicDelimiter, namespace, serviceMap) 52 | } 53 | } 54 | 55 | return serviceMap, err 56 | } 57 | 58 | // getNamespaces get openfaas namespaces 59 | func (s *FunctionLookupBuilder) getNamespaces() ([]string, error) { 60 | var ( 61 | err error 62 | namespaces []string 63 | ) 64 | uri := fmt.Sprintf("%s/system/namespaces", s.GatewayURL) 65 | req, err := http.NewRequest(http.MethodGet, uri, nil) 66 | if err != nil { 67 | return namespaces, fmt.Errorf("unable to create request: %s, error: %w", uri, err) 68 | } 69 | 70 | if s.Credentials != nil { 71 | req.SetBasicAuth(s.Credentials.User, s.Credentials.Password) 72 | } 73 | 74 | res, err := s.Client.Do(req) 75 | if err != nil { 76 | return namespaces, fmt.Errorf("unable to make request: %w", err) 77 | 78 | } 79 | 80 | if res.Body != nil { 81 | defer res.Body.Close() 82 | } 83 | 84 | bytesOut, err := ioutil.ReadAll(res.Body) 85 | if err != nil { 86 | return namespaces, err 87 | } 88 | 89 | if res.StatusCode == http.StatusUnauthorized { 90 | return namespaces, fmt.Errorf("check authorization, status code: %d", res.StatusCode) 91 | } 92 | 93 | if len(bytesOut) == 0 { 94 | return namespaces, nil 95 | } 96 | 97 | if err := json.Unmarshal(bytesOut, &namespaces); err != nil { 98 | return namespaces, fmt.Errorf("unable to marshal to JSON: %s, error: %w", string(bytesOut), err) 99 | } 100 | 101 | return namespaces, err 102 | } 103 | 104 | func (s *FunctionLookupBuilder) getFunctions(namespace string) ([]types.FunctionStatus, error) { 105 | gateway := fmt.Sprintf("%s/system/functions", s.GatewayURL) 106 | gatewayURL, err := url.Parse(gateway) 107 | if err != nil { 108 | return []types.FunctionStatus{}, fmt.Errorf("invalid gateway URL: %s", err.Error()) 109 | } 110 | if len(namespace) > 0 { 111 | query := gatewayURL.Query() 112 | query.Set("namespace", namespace) 113 | gatewayURL.RawQuery = query.Encode() 114 | } 115 | 116 | req, err := http.NewRequest(http.MethodGet, gatewayURL.String(), nil) 117 | if err != nil { 118 | return []types.FunctionStatus{}, fmt.Errorf("unable to create request: %w", err) 119 | } 120 | 121 | if s.Credentials != nil { 122 | req.SetBasicAuth(s.Credentials.User, s.Credentials.Password) 123 | } 124 | 125 | res, err := s.Client.Do(req) 126 | if err != nil { 127 | return []types.FunctionStatus{}, fmt.Errorf("unable to make HTTP request: %w", err) 128 | } 129 | 130 | if res.Body != nil { 131 | defer res.Body.Close() 132 | } 133 | 134 | bytesOut, _ := ioutil.ReadAll(res.Body) 135 | 136 | functions := []types.FunctionStatus{} 137 | if err := json.Unmarshal(bytesOut, &functions); err != nil { 138 | return []types.FunctionStatus{}, 139 | fmt.Errorf("unable to unmarshal value: %q, error: %w", string(bytesOut), err) 140 | } 141 | 142 | return functions, nil 143 | } 144 | 145 | func buildServiceMap(functions *[]types.FunctionStatus, topicDelimiter, namespace string, serviceMap map[string][]string) map[string][]string { 146 | for _, function := range *functions { 147 | 148 | if function.Annotations != nil { 149 | 150 | annotations := *function.Annotations 151 | 152 | if topicNames, exist := annotations["topic"]; exist { 153 | 154 | if len(topicDelimiter) > 0 && strings.Count(topicNames, topicDelimiter) > 0 { 155 | 156 | topicSlice := strings.Split(topicNames, topicDelimiter) 157 | 158 | for _, topic := range topicSlice { 159 | serviceMap = appendServiceMap(topic, function.Name, namespace, serviceMap) 160 | } 161 | } else { 162 | serviceMap = appendServiceMap(topicNames, function.Name, namespace, serviceMap) 163 | } 164 | } 165 | } 166 | } 167 | return serviceMap 168 | } 169 | 170 | func appendServiceMap(key, function, namespace string, sm map[string][]string) map[string][]string { 171 | 172 | key = strings.TrimSpace(key) 173 | 174 | if len(key) > 0 { 175 | 176 | if sm[key] == nil { 177 | sm[key] = []string{} 178 | } 179 | sep := "" 180 | if len(namespace) > 0 { 181 | sep = "." 182 | } 183 | 184 | functionPath := fmt.Sprintf("%s%s%s", function, sep, namespace) 185 | sm[key] = append(sm[key], functionPath) 186 | } 187 | 188 | return sm 189 | } 190 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/connector-sdk/types/invoker.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s) 2019. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package types 5 | 6 | import ( 7 | "bytes" 8 | "context" 9 | "fmt" 10 | "io" 11 | "io/ioutil" 12 | "log" 13 | "net/http" 14 | "time" 15 | ) 16 | 17 | // Invoker is used to send requests to functions. Responses are 18 | // returned via the Responses channel. 19 | type Invoker struct { 20 | PrintResponse bool 21 | PrintRequest bool 22 | Client *http.Client 23 | GatewayURL string 24 | ContentType string 25 | Responses chan InvokerResponse 26 | } 27 | 28 | // InvokerResponse is a wrapper to contain the response or error the Invoker 29 | // receives from the function. Networking errors wil be found in the Error field. 30 | type InvokerResponse struct { 31 | Context context.Context 32 | Body *[]byte 33 | Header *http.Header 34 | Status int 35 | Error error 36 | Topic string 37 | Function string 38 | Duration time.Duration 39 | } 40 | 41 | // NewInvoker constructs an Invoker instance 42 | func NewInvoker(gatewayURL string, client *http.Client, contentType string, printResponse, printRequest bool) *Invoker { 43 | return &Invoker{ 44 | PrintResponse: printResponse, 45 | PrintRequest: printRequest, 46 | Client: client, 47 | GatewayURL: gatewayURL, 48 | ContentType: contentType, 49 | Responses: make(chan InvokerResponse), 50 | } 51 | } 52 | 53 | // Invoke triggers a function by accessing the API Gateway 54 | func (i *Invoker) Invoke(topicMap *TopicMap, topic string, message *[]byte, headers http.Header) { 55 | i.InvokeWithContext(context.Background(), topicMap, topic, message, headers) 56 | } 57 | 58 | //InvokeWithContext triggers a function by accessing the API Gateway while propagating context 59 | func (i *Invoker) InvokeWithContext(ctx context.Context, topicMap *TopicMap, topic string, message *[]byte, headers http.Header) { 60 | if len(*message) == 0 { 61 | i.Responses <- InvokerResponse{ 62 | Context: ctx, 63 | Error: fmt.Errorf("no message to send"), 64 | Duration: time.Millisecond * 0, 65 | } 66 | } 67 | 68 | matchedFunctions := topicMap.Match(topic) 69 | for _, matchedFunction := range matchedFunctions { 70 | log.Printf("Invoking: %s", matchedFunction) 71 | 72 | gwURL := fmt.Sprintf("%s/%s", i.GatewayURL, matchedFunction) 73 | reader := bytes.NewReader(*message) 74 | 75 | if i.PrintRequest { 76 | fmt.Printf("[invoke] %s => %s\n\t%s\n", topic, matchedFunction, string(*message)) 77 | } 78 | 79 | start := time.Now() 80 | body, statusCode, header, err := invoke(ctx, i.Client, gwURL, i.ContentType, topic, reader, headers) 81 | if err != nil { 82 | i.Responses <- InvokerResponse{ 83 | Context: ctx, 84 | Error: fmt.Errorf("unable to invoke %s, error: %w", matchedFunction, err), 85 | Duration: time.Since(start), 86 | } 87 | continue 88 | } 89 | 90 | i.Responses <- InvokerResponse{ 91 | Context: ctx, 92 | Body: body, 93 | Status: statusCode, 94 | Header: header, 95 | Function: matchedFunction, 96 | Topic: topic, 97 | Duration: time.Since(start), 98 | } 99 | } 100 | } 101 | 102 | func invoke(ctx context.Context, c *http.Client, gwURL, contentType, topic string, reader io.Reader, headers http.Header) (*[]byte, int, *http.Header, error) { 103 | req, err := http.NewRequest(http.MethodPost, gwURL, reader) 104 | if err != nil { 105 | return nil, http.StatusServiceUnavailable, nil, err 106 | } 107 | 108 | if contentType != "" { 109 | req.Header.Set("Content-Type", contentType) 110 | } 111 | 112 | if v := req.Header.Get("X-Connector"); v == "" { 113 | req.Header.Set("X-Connector", "connector-sdk") 114 | } 115 | 116 | if v := req.Header.Get("X-Topic"); v == "" { 117 | req.Header.Set("X-Topic", topic) 118 | } 119 | 120 | for k, values := range headers { 121 | for _, value := range values { 122 | req.Header.Add(k, value) 123 | } 124 | } 125 | 126 | req = req.WithContext(ctx) 127 | if req.Body != nil { 128 | defer req.Body.Close() 129 | } 130 | 131 | var body *[]byte 132 | res, err := c.Do(req) 133 | if err != nil { 134 | return nil, http.StatusServiceUnavailable, nil, 135 | fmt.Errorf("unable to reach endpoint %s, error: %w", gwURL, err) 136 | } 137 | 138 | if res.Body != nil { 139 | defer res.Body.Close() 140 | 141 | bytesOut, err := ioutil.ReadAll(res.Body) 142 | if err != nil { 143 | return nil, http.StatusServiceUnavailable, 144 | nil, 145 | fmt.Errorf("unable to read body from response %w", err) 146 | } 147 | body = &bytesOut 148 | } 149 | 150 | return body, res.StatusCode, &res.Header, err 151 | } 152 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/connector-sdk/types/make_client.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s) 2019. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package types 5 | 6 | import ( 7 | "net" 8 | "net/http" 9 | "time" 10 | ) 11 | 12 | // MakeClient returns a http.Client with a timeout for connection establishing and request handling 13 | func MakeClient(timeout time.Duration) *http.Client { 14 | return &http.Client{ 15 | Transport: &http.Transport{ 16 | Proxy: http.ProxyFromEnvironment, 17 | DialContext: (&net.Dialer{ 18 | // Timeout is the maximum amount of time a dial will wait for 19 | // a connect to complete. If Deadline is also set, it may fail 20 | // earlier. 21 | Timeout: timeout, 22 | KeepAlive: 10 * time.Second, 23 | }).DialContext, 24 | MaxIdleConns: 100, 25 | MaxIdleConnsPerHost: 100, 26 | IdleConnTimeout: 120 * time.Millisecond, 27 | }, 28 | // Timeout specifies a time limit for requests made by this 29 | // Client. The timeout includes connection time, any 30 | // redirects, and reading the response body. The timer remains 31 | // running after Get, Head, Post, or Do return and will 32 | // interrupt reading of the Response.Body. 33 | Timeout: timeout, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/connector-sdk/types/response_printer.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s) 2019. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package types 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | ) 10 | 11 | // ResponsePrinter prints function results 12 | type ResponsePrinter struct { 13 | PrintResponseBody bool 14 | } 15 | 16 | // Response is triggered by the controller when a message is 17 | // received from the function invocation 18 | func (rp *ResponsePrinter) Response(res InvokerResponse) { 19 | if res.Error != nil { 20 | log.Printf("connector-sdk got error: %s", res.Error.Error()) 21 | } else { 22 | log.Printf("connector-sdk got result: [%d] %s => %s (%d) bytes", res.Status, res.Topic, res.Function, len(*res.Body)) 23 | if rp.PrintResponseBody { 24 | fmt.Printf("[%d] %s => %s\n%s\n", res.Status, res.Topic, res.Function, string(*res.Body)) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/connector-sdk/types/response_subscriber.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s) 2019. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package types 5 | 6 | // ResponseSubscriber enables connector or another client in connector 7 | // to receive results from the function invocation. 8 | // Note: when implementing this interface, you must not perform any 9 | // costly or high-latency operations, or should off-load them to another 10 | // go-routine to prevent blocking. 11 | type ResponseSubscriber interface { 12 | // Response is triggered by the controller when a message is 13 | // received from the function invocation 14 | Response(InvokerResponse) 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/connector-sdk/types/topic_map.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s) 2019. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package types 5 | 6 | import ( 7 | "sync" 8 | ) 9 | 10 | func NewTopicMap() TopicMap { 11 | lookup := make(map[string][]string) 12 | return TopicMap{ 13 | lookup: &lookup, 14 | lock: sync.RWMutex{}, 15 | } 16 | } 17 | 18 | type TopicMap struct { 19 | lookup *map[string][]string 20 | lock sync.RWMutex 21 | } 22 | 23 | func (t *TopicMap) Match(topicName string) []string { 24 | t.lock.RLock() 25 | defer t.lock.RUnlock() 26 | 27 | var values []string 28 | 29 | for key, val := range *t.lookup { 30 | if key == topicName { 31 | values = val 32 | break 33 | } 34 | } 35 | 36 | return values 37 | } 38 | 39 | func (t *TopicMap) Sync(updated *map[string][]string) { 40 | t.lock.Lock() 41 | defer t.lock.Unlock() 42 | 43 | t.lookup = updated 44 | } 45 | 46 | func (t *TopicMap) Topics() []string { 47 | t.lock.RLock() 48 | defer t.lock.RUnlock() 49 | 50 | topics := make([]string, 0, len(*t.lookup)) 51 | for topic := range *t.lookup { 52 | topics = append(topics, topic) 53 | } 54 | 55 | return topics 56 | } 57 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/faas-provider/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Alex Ellis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/faas-provider/auth/basic_auth.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package auth 5 | 6 | import ( 7 | "crypto/subtle" 8 | "net/http" 9 | ) 10 | 11 | // DecorateWithBasicAuth enforces basic auth as a middleware with given credentials 12 | func DecorateWithBasicAuth(next http.HandlerFunc, credentials *BasicAuthCredentials) http.HandlerFunc { 13 | return func(w http.ResponseWriter, r *http.Request) { 14 | 15 | user, password, ok := r.BasicAuth() 16 | 17 | const noMatch = 0 18 | if !ok || 19 | user != credentials.User || 20 | subtle.ConstantTimeCompare([]byte(credentials.Password), []byte(password)) == noMatch { 21 | 22 | w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) 23 | w.WriteHeader(http.StatusUnauthorized) 24 | w.Write([]byte("invalid credentials")) 25 | return 26 | } 27 | 28 | next.ServeHTTP(w, r) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/faas-provider/auth/credentials.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) OpenFaaS Author(s). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package auth 5 | 6 | import ( 7 | "fmt" 8 | "io/ioutil" 9 | "path" 10 | "strings" 11 | ) 12 | 13 | // BasicAuthCredentials for credentials 14 | type BasicAuthCredentials struct { 15 | User string 16 | Password string 17 | } 18 | 19 | type ReadBasicAuth interface { 20 | Read() (*BasicAuthCredentials, error) 21 | } 22 | 23 | type ReadBasicAuthFromDisk struct { 24 | SecretMountPath string 25 | 26 | UserFilename string 27 | 28 | PasswordFilename string 29 | } 30 | 31 | func (r *ReadBasicAuthFromDisk) Read() (*BasicAuthCredentials, error) { 32 | var credentials *BasicAuthCredentials 33 | 34 | if len(r.SecretMountPath) == 0 { 35 | return nil, fmt.Errorf("invalid SecretMountPath specified for reading secrets") 36 | } 37 | 38 | userKey := "basic-auth-user" 39 | if len(r.UserFilename) > 0 { 40 | userKey = r.UserFilename 41 | } 42 | 43 | passwordKey := "basic-auth-password" 44 | if len(r.PasswordFilename) > 0 { 45 | passwordKey = r.PasswordFilename 46 | } 47 | 48 | userPath := path.Join(r.SecretMountPath, userKey) 49 | user, userErr := ioutil.ReadFile(userPath) 50 | if userErr != nil { 51 | return nil, fmt.Errorf("unable to load %s", userPath) 52 | } 53 | 54 | userPassword := path.Join(r.SecretMountPath, passwordKey) 55 | password, passErr := ioutil.ReadFile(userPassword) 56 | if passErr != nil { 57 | return nil, fmt.Errorf("Unable to load %s", userPassword) 58 | } 59 | 60 | credentials = &BasicAuthCredentials{ 61 | User: strings.TrimSpace(string(user)), 62 | Password: strings.TrimSpace(string(password)), 63 | } 64 | 65 | return credentials, nil 66 | } 67 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/faas-provider/types/config.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | ) 7 | 8 | const ( 9 | defaultReadTimeout = 10 * time.Second 10 | defaultMaxIdleConns = 1024 11 | ) 12 | 13 | // FaaSHandlers provide handlers for OpenFaaS 14 | type FaaSHandlers struct { 15 | // FunctionProxy provides the function invocation proxy logic. Use proxy.NewHandlerFunc to 16 | // use the standard OpenFaaS proxy implementation or provide completely custom proxy logic. 17 | FunctionProxy http.HandlerFunc 18 | 19 | FunctionReader http.HandlerFunc 20 | DeployHandler http.HandlerFunc 21 | 22 | DeleteHandler http.HandlerFunc 23 | ReplicaReader http.HandlerFunc 24 | ReplicaUpdater http.HandlerFunc 25 | SecretHandler http.HandlerFunc 26 | // LogHandler provides streaming json logs of functions 27 | LogHandler http.HandlerFunc 28 | 29 | // UpdateHandler an existing function/service 30 | UpdateHandler http.HandlerFunc 31 | // HealthHandler defines the default health endpoint bound to "/healthz 32 | // If the handler is not set, then the "/healthz" path will not be configured 33 | HealthHandler http.HandlerFunc 34 | InfoHandler http.HandlerFunc 35 | ListNamespaceHandler http.HandlerFunc 36 | } 37 | 38 | // FaaSConfig set config for HTTP handlers 39 | type FaaSConfig struct { 40 | // TCPPort is the public port for the API. 41 | TCPPort *int 42 | // HTTP timeout for reading a request from clients. 43 | ReadTimeout time.Duration 44 | // HTTP timeout for writing a response from functions. 45 | WriteTimeout time.Duration 46 | // EnableHealth enables/disables the default health endpoint bound to "/healthz". 47 | // 48 | // Deprecated: basic auth is enabled automatcally by setting the HealthHandler in the FaaSHandlers 49 | // struct. This value is not longer read or used. 50 | EnableHealth bool 51 | // EnableBasicAuth enforces basic auth on the API. If set, reads secrets from file-system 52 | // location specificed in `SecretMountPath`. 53 | EnableBasicAuth bool 54 | // SecretMountPath specifies where to read secrets from for embedded basic auth. 55 | SecretMountPath string 56 | // MaxIdleConns with a default value of 1024, can be used for tuning HTTP proxy performance. 57 | MaxIdleConns int 58 | // MaxIdleConnsPerHost with a default value of 1024, can be used for tuning HTTP proxy performance. 59 | MaxIdleConnsPerHost int 60 | } 61 | 62 | // GetReadTimeout is a helper to safely return the configured ReadTimeout or the default value of 10s 63 | func (c *FaaSConfig) GetReadTimeout() time.Duration { 64 | if c.ReadTimeout <= 0*time.Second { 65 | return defaultReadTimeout 66 | } 67 | return c.ReadTimeout 68 | } 69 | 70 | // GetMaxIdleConns is a helper to safely return the configured MaxIdleConns or the default value of 1024 71 | func (c *FaaSConfig) GetMaxIdleConns() int { 72 | if c.MaxIdleConns < 1 { 73 | return defaultMaxIdleConns 74 | } 75 | 76 | return c.MaxIdleConns 77 | } 78 | 79 | // GetMaxIdleConns is a helper to safely return the configured MaxIdleConns or the default value which 80 | // should then match the MaxIdleConns 81 | func (c *FaaSConfig) GetMaxIdleConnsPerHost() int { 82 | if c.MaxIdleConnsPerHost < 1 { 83 | return c.GetMaxIdleConns() 84 | } 85 | 86 | return c.MaxIdleConnsPerHost 87 | } 88 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/faas-provider/types/function_deployment.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // FunctionDeployment represents a request to create or update a Function. 4 | type FunctionDeployment struct { 5 | 6 | // Service is the name of the function deployment 7 | Service string `json:"service"` 8 | 9 | // Image is a fully-qualified container image 10 | Image string `json:"image"` 11 | 12 | // Namespace for the function, if supported by the faas-provider 13 | Namespace string `json:"namespace,omitempty"` 14 | 15 | // EnvProcess overrides the fprocess environment variable and can be used 16 | // with the watchdog 17 | EnvProcess string `json:"envProcess,omitempty"` 18 | 19 | // EnvVars can be provided to set environment variables for the function runtime. 20 | EnvVars map[string]string `json:"envVars,omitempty"` 21 | 22 | // Constraints are specific to the faas-provider. 23 | Constraints []string `json:"constraints,omitempty"` 24 | 25 | // Secrets list of secrets to be made available to function 26 | Secrets []string `json:"secrets,omitempty"` 27 | 28 | // Labels are metadata for functions which may be used by the 29 | // faas-provider or the gateway 30 | Labels *map[string]string `json:"labels,omitempty"` 31 | 32 | // Annotations are metadata for functions which may be used by the 33 | // faas-provider or the gateway 34 | Annotations *map[string]string `json:"annotations,omitempty"` 35 | 36 | // Limits for function 37 | Limits *FunctionResources `json:"limits,omitempty"` 38 | 39 | // Requests of resources requested by function 40 | Requests *FunctionResources `json:"requests,omitempty"` 41 | 42 | // ReadOnlyRootFilesystem removes write-access from the root filesystem 43 | // mount-point. 44 | ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem,omitempty"` 45 | } 46 | 47 | // FunctionResources Memory and CPU 48 | type FunctionResources struct { 49 | Memory string `json:"memory,omitempty"` 50 | CPU string `json:"cpu,omitempty"` 51 | } 52 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/faas-provider/types/function_status.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "time" 4 | 5 | // FunctionStatus exported for system/functions endpoint 6 | type FunctionStatus struct { 7 | 8 | // Name is the name of the function deployment 9 | Name string `json:"name"` 10 | 11 | // Image is a fully-qualified container image 12 | Image string `json:"image"` 13 | 14 | // Namespace for the function, if supported by the faas-provider 15 | Namespace string `json:"namespace,omitempty"` 16 | 17 | // EnvProcess overrides the fprocess environment variable and can be used 18 | // with the watchdog 19 | EnvProcess string `json:"envProcess,omitempty"` 20 | 21 | // EnvVars set environment variables for the function runtime 22 | EnvVars map[string]string `json:"envVars,omitempty"` 23 | 24 | // Constraints are specific to the faas-provider 25 | Constraints []string `json:"constraints,omitempty"` 26 | 27 | // Secrets list of secrets to be made available to function 28 | Secrets []string `json:"secrets,omitempty"` 29 | 30 | // Labels are metadata for functions which may be used by the 31 | // faas-provider or the gateway 32 | Labels *map[string]string `json:"labels,omitempty"` 33 | 34 | // Annotations are metadata for functions which may be used by the 35 | // faas-provider or the gateway 36 | Annotations *map[string]string `json:"annotations,omitempty"` 37 | 38 | // Limits for function 39 | Limits *FunctionResources `json:"limits,omitempty"` 40 | 41 | // Requests of resources requested by function 42 | Requests *FunctionResources `json:"requests,omitempty"` 43 | 44 | // ReadOnlyRootFilesystem removes write-access from the root filesystem 45 | // mount-point. 46 | ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem,omitempty"` 47 | 48 | // ================ 49 | // Fields for status 50 | // ================ 51 | 52 | // InvocationCount count of invocations 53 | InvocationCount float64 `json:"invocationCount,omitempty"` 54 | 55 | // Replicas desired within the cluster 56 | Replicas uint64 `json:"replicas,omitempty"` 57 | 58 | // AvailableReplicas is the count of replicas ready to receive 59 | // invocations as reported by the faas-provider 60 | AvailableReplicas uint64 `json:"availableReplicas,omitempty"` 61 | 62 | // CreatedAt is the time read back from the faas backend's 63 | // data store for when the function or its container was created. 64 | CreatedAt time.Time `json:"createdAt,omitempty"` 65 | 66 | // Usage represents CPU and RAM used by all of the 67 | // functions' replicas. Divide by AvailableReplicas for an 68 | // average value per replica. 69 | Usage *FunctionUsage `json:"usage,omitempty"` 70 | } 71 | 72 | // FunctionUsage represents CPU and RAM used by all of the 73 | // functions' replicas. 74 | // 75 | // CPU is measured in seconds consumed since the last measurement 76 | // RAM is measured in total bytes consumed 77 | // 78 | type FunctionUsage struct { 79 | // CPU is the increase in CPU usage since the last measurement 80 | // equivalent to Kubernetes' concept of millicores. 81 | CPU float64 `json:"cpu,omitempty"` 82 | 83 | //TotalMemoryBytes is the total memory usage in bytes. 84 | TotalMemoryBytes float64 `json:"totalMemoryBytes,omitempty"` 85 | } 86 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/faas-provider/types/queue.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "net/http" 5 | "net/url" 6 | ) 7 | 8 | // Request for asynchronous processing 9 | type QueueRequest struct { 10 | // Header from HTTP request 11 | Header http.Header 12 | 13 | // Host from HTTP request 14 | Host string 15 | 16 | // Body from HTTP request to use for invocation 17 | Body []byte 18 | 19 | // Method from HTTP request 20 | Method string 21 | 22 | // Path from HTTP request 23 | Path string 24 | 25 | // QueryString from HTTP request 26 | QueryString string 27 | 28 | // Function name to invoke 29 | Function string 30 | 31 | // QueueName to publish the request to, leave blank 32 | // for default. 33 | QueueName string 34 | 35 | // Used by queue worker to submit a result 36 | CallbackURL *url.URL `json:"CallbackUrl"` 37 | } 38 | 39 | // RequestQueuer can public a request to be executed asynchronously 40 | type RequestQueuer interface { 41 | Queue(req *QueueRequest) error 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/faas-provider/types/read_config.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strconv" 7 | "time" 8 | ) 9 | 10 | // OsEnv implements interface to wrap os.Getenv 11 | type OsEnv struct { 12 | } 13 | 14 | // Getenv wraps os.Getenv 15 | func (OsEnv) Getenv(key string) string { 16 | return os.Getenv(key) 17 | } 18 | 19 | // HasEnv provides interface for os.Getenv 20 | type HasEnv interface { 21 | Getenv(key string) string 22 | } 23 | 24 | // ReadConfig constitutes config from env variables 25 | type ReadConfig struct { 26 | } 27 | 28 | // ParseIntValue parses the the int in val or, if there is an error, returns the 29 | // specified default value 30 | func ParseIntValue(val string, fallback int) int { 31 | if len(val) > 0 { 32 | parsedVal, parseErr := strconv.Atoi(val) 33 | if parseErr == nil && parsedVal >= 0 { 34 | return parsedVal 35 | } 36 | } 37 | return fallback 38 | } 39 | 40 | // ParseIntOrDurationValue parses the the duration in val or, if there is an error, returns the 41 | // specified default value 42 | func ParseIntOrDurationValue(val string, fallback time.Duration) time.Duration { 43 | if len(val) > 0 { 44 | parsedVal, parseErr := strconv.Atoi(val) 45 | if parseErr == nil && parsedVal >= 0 { 46 | return time.Duration(parsedVal) * time.Second 47 | } 48 | } 49 | 50 | duration, durationErr := time.ParseDuration(val) 51 | if durationErr != nil { 52 | return fallback 53 | } 54 | 55 | return duration 56 | } 57 | 58 | // ParseBoolValue parses the the boolean in val or, if there is an error, returns the 59 | // specified default value 60 | func ParseBoolValue(val string, fallback bool) bool { 61 | if len(val) > 0 { 62 | return val == "true" 63 | } 64 | return fallback 65 | } 66 | 67 | // ParseString verifies the string in val is not empty. When empty, it returns the 68 | // specified default value 69 | func ParseString(val string, fallback string) string { 70 | if len(val) > 0 { 71 | return val 72 | } 73 | return fallback 74 | } 75 | 76 | // Read fetches config from environmental variables. 77 | func (ReadConfig) Read(hasEnv HasEnv) (*FaaSConfig, error) { 78 | cfg := &FaaSConfig{ 79 | ReadTimeout: ParseIntOrDurationValue(hasEnv.Getenv("read_timeout"), time.Second*10), 80 | WriteTimeout: ParseIntOrDurationValue(hasEnv.Getenv("write_timeout"), time.Second*10), 81 | EnableBasicAuth: ParseBoolValue(hasEnv.Getenv("basic_auth"), false), 82 | // default value from Gateway 83 | SecretMountPath: ParseString(hasEnv.Getenv("secret_mount_path"), "/run/secrets/"), 84 | } 85 | 86 | port := ParseIntValue(hasEnv.Getenv("port"), 8080) 87 | cfg.TCPPort = &port 88 | 89 | cfg.MaxIdleConns = 1024 90 | maxIdleConns := hasEnv.Getenv("max_idle_conns") 91 | if len(maxIdleConns) > 0 { 92 | val, err := strconv.Atoi(maxIdleConns) 93 | if err != nil { 94 | return nil, fmt.Errorf("invalid value for max_idle_conns: %s", maxIdleConns) 95 | } 96 | cfg.MaxIdleConns = val 97 | 98 | } 99 | 100 | cfg.MaxIdleConnsPerHost = 1024 101 | maxIdleConnsPerHost := hasEnv.Getenv("max_idle_conns_per_host") 102 | if len(maxIdleConnsPerHost) > 0 { 103 | val, err := strconv.Atoi(maxIdleConnsPerHost) 104 | if err != nil { 105 | return nil, fmt.Errorf("invalid value for max_idle_conns_per_host: %s", maxIdleConnsPerHost) 106 | } 107 | cfg.MaxIdleConnsPerHost = val 108 | 109 | } 110 | 111 | return cfg, nil 112 | } 113 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/faas-provider/types/requests.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alex Ellis 2017. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | package types 5 | 6 | // ScaleServiceRequest scales the service to the requested replcia count. 7 | type ScaleServiceRequest struct { 8 | ServiceName string `json:"serviceName"` 9 | Replicas uint64 `json:"replicas"` 10 | } 11 | 12 | // DeleteFunctionRequest delete a deployed function 13 | type DeleteFunctionRequest struct { 14 | FunctionName string `json:"functionName"` 15 | } 16 | 17 | // ProviderInfo provides information about the configured provider 18 | type ProviderInfo struct { 19 | Name string `json:"provider"` 20 | Version *VersionInfo `json:"version"` 21 | Orchestration string `json:"orchestration"` 22 | } 23 | 24 | // VersionInfo provides the commit message, sha and release version number 25 | type VersionInfo struct { 26 | CommitMessage string `json:"commit_message,omitempty"` 27 | SHA string `json:"sha"` 28 | Release string `json:"release"` 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/openfaas/faas-provider/types/secret.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Secret for underlying orchestrator 4 | type Secret struct { 5 | // Name of the secret 6 | Name string `json:"name"` 7 | 8 | // Namespace if applicable for the secret 9 | Namespace string `json:"namespace,omitempty"` 10 | 11 | // Value is a string representing the string's value 12 | Value string `json:"value,omitempty"` 13 | 14 | // RawValue can be used to provide binary data when 15 | // Value is not set 16 | RawValue []byte `json:"rawValue,omitempty"` 17 | } 18 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/internal/socks/client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package socks 6 | 7 | import ( 8 | "context" 9 | "errors" 10 | "io" 11 | "net" 12 | "strconv" 13 | "time" 14 | ) 15 | 16 | var ( 17 | noDeadline = time.Time{} 18 | aLongTimeAgo = time.Unix(1, 0) 19 | ) 20 | 21 | func (d *Dialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) { 22 | host, port, err := splitHostPort(address) 23 | if err != nil { 24 | return nil, err 25 | } 26 | if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() { 27 | c.SetDeadline(deadline) 28 | defer c.SetDeadline(noDeadline) 29 | } 30 | if ctx != context.Background() { 31 | errCh := make(chan error, 1) 32 | done := make(chan struct{}) 33 | defer func() { 34 | close(done) 35 | if ctxErr == nil { 36 | ctxErr = <-errCh 37 | } 38 | }() 39 | go func() { 40 | select { 41 | case <-ctx.Done(): 42 | c.SetDeadline(aLongTimeAgo) 43 | errCh <- ctx.Err() 44 | case <-done: 45 | errCh <- nil 46 | } 47 | }() 48 | } 49 | 50 | b := make([]byte, 0, 6+len(host)) // the size here is just an estimate 51 | b = append(b, Version5) 52 | if len(d.AuthMethods) == 0 || d.Authenticate == nil { 53 | b = append(b, 1, byte(AuthMethodNotRequired)) 54 | } else { 55 | ams := d.AuthMethods 56 | if len(ams) > 255 { 57 | return nil, errors.New("too many authentication methods") 58 | } 59 | b = append(b, byte(len(ams))) 60 | for _, am := range ams { 61 | b = append(b, byte(am)) 62 | } 63 | } 64 | if _, ctxErr = c.Write(b); ctxErr != nil { 65 | return 66 | } 67 | 68 | if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil { 69 | return 70 | } 71 | if b[0] != Version5 { 72 | return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0]))) 73 | } 74 | am := AuthMethod(b[1]) 75 | if am == AuthMethodNoAcceptableMethods { 76 | return nil, errors.New("no acceptable authentication methods") 77 | } 78 | if d.Authenticate != nil { 79 | if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil { 80 | return 81 | } 82 | } 83 | 84 | b = b[:0] 85 | b = append(b, Version5, byte(d.cmd), 0) 86 | if ip := net.ParseIP(host); ip != nil { 87 | if ip4 := ip.To4(); ip4 != nil { 88 | b = append(b, AddrTypeIPv4) 89 | b = append(b, ip4...) 90 | } else if ip6 := ip.To16(); ip6 != nil { 91 | b = append(b, AddrTypeIPv6) 92 | b = append(b, ip6...) 93 | } else { 94 | return nil, errors.New("unknown address type") 95 | } 96 | } else { 97 | if len(host) > 255 { 98 | return nil, errors.New("FQDN too long") 99 | } 100 | b = append(b, AddrTypeFQDN) 101 | b = append(b, byte(len(host))) 102 | b = append(b, host...) 103 | } 104 | b = append(b, byte(port>>8), byte(port)) 105 | if _, ctxErr = c.Write(b); ctxErr != nil { 106 | return 107 | } 108 | 109 | if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil { 110 | return 111 | } 112 | if b[0] != Version5 { 113 | return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0]))) 114 | } 115 | if cmdErr := Reply(b[1]); cmdErr != StatusSucceeded { 116 | return nil, errors.New("unknown error " + cmdErr.String()) 117 | } 118 | if b[2] != 0 { 119 | return nil, errors.New("non-zero reserved field") 120 | } 121 | l := 2 122 | var a Addr 123 | switch b[3] { 124 | case AddrTypeIPv4: 125 | l += net.IPv4len 126 | a.IP = make(net.IP, net.IPv4len) 127 | case AddrTypeIPv6: 128 | l += net.IPv6len 129 | a.IP = make(net.IP, net.IPv6len) 130 | case AddrTypeFQDN: 131 | if _, err := io.ReadFull(c, b[:1]); err != nil { 132 | return nil, err 133 | } 134 | l += int(b[0]) 135 | default: 136 | return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3]))) 137 | } 138 | if cap(b) < l { 139 | b = make([]byte, l) 140 | } else { 141 | b = b[:l] 142 | } 143 | if _, ctxErr = io.ReadFull(c, b); ctxErr != nil { 144 | return 145 | } 146 | if a.IP != nil { 147 | copy(a.IP, b) 148 | } else { 149 | a.Name = string(b[:len(b)-2]) 150 | } 151 | a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1]) 152 | return &a, nil 153 | } 154 | 155 | func splitHostPort(address string) (string, int, error) { 156 | host, port, err := net.SplitHostPort(address) 157 | if err != nil { 158 | return "", 0, err 159 | } 160 | portnum, err := strconv.Atoi(port) 161 | if err != nil { 162 | return "", 0, err 163 | } 164 | if 1 > portnum || portnum > 0xffff { 165 | return "", 0, errors.New("port number out of range " + port) 166 | } 167 | return host, portnum, nil 168 | } 169 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/proxy/dial.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package proxy 6 | 7 | import ( 8 | "context" 9 | "net" 10 | ) 11 | 12 | // A ContextDialer dials using a context. 13 | type ContextDialer interface { 14 | DialContext(ctx context.Context, network, address string) (net.Conn, error) 15 | } 16 | 17 | // Dial works like DialContext on net.Dialer but using a dialer returned by FromEnvironment. 18 | // 19 | // The passed ctx is only used for returning the Conn, not the lifetime of the Conn. 20 | // 21 | // Custom dialers (registered via RegisterDialerType) that do not implement ContextDialer 22 | // can leak a goroutine for as long as it takes the underlying Dialer implementation to timeout. 23 | // 24 | // A Conn returned from a successful Dial after the context has been cancelled will be immediately closed. 25 | func Dial(ctx context.Context, network, address string) (net.Conn, error) { 26 | d := FromEnvironment() 27 | if xd, ok := d.(ContextDialer); ok { 28 | return xd.DialContext(ctx, network, address) 29 | } 30 | return dialContext(ctx, d, network, address) 31 | } 32 | 33 | // WARNING: this can leak a goroutine for as long as the underlying Dialer implementation takes to timeout 34 | // A Conn returned from a successful Dial after the context has been cancelled will be immediately closed. 35 | func dialContext(ctx context.Context, d Dialer, network, address string) (net.Conn, error) { 36 | var ( 37 | conn net.Conn 38 | done = make(chan struct{}, 1) 39 | err error 40 | ) 41 | go func() { 42 | conn, err = d.Dial(network, address) 43 | close(done) 44 | if conn != nil && ctx.Err() != nil { 45 | conn.Close() 46 | } 47 | }() 48 | select { 49 | case <-ctx.Done(): 50 | err = ctx.Err() 51 | case <-done: 52 | } 53 | return conn, err 54 | } 55 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/proxy/direct.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package proxy 6 | 7 | import ( 8 | "context" 9 | "net" 10 | ) 11 | 12 | type direct struct{} 13 | 14 | // Direct implements Dialer by making network connections directly using net.Dial or net.DialContext. 15 | var Direct = direct{} 16 | 17 | var ( 18 | _ Dialer = Direct 19 | _ ContextDialer = Direct 20 | ) 21 | 22 | // Dial directly invokes net.Dial with the supplied parameters. 23 | func (direct) Dial(network, addr string) (net.Conn, error) { 24 | return net.Dial(network, addr) 25 | } 26 | 27 | // DialContext instantiates a net.Dialer and invokes its DialContext receiver with the supplied parameters. 28 | func (direct) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { 29 | var d net.Dialer 30 | return d.DialContext(ctx, network, addr) 31 | } 32 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/proxy/per_host.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package proxy 6 | 7 | import ( 8 | "context" 9 | "net" 10 | "strings" 11 | ) 12 | 13 | // A PerHost directs connections to a default Dialer unless the host name 14 | // requested matches one of a number of exceptions. 15 | type PerHost struct { 16 | def, bypass Dialer 17 | 18 | bypassNetworks []*net.IPNet 19 | bypassIPs []net.IP 20 | bypassZones []string 21 | bypassHosts []string 22 | } 23 | 24 | // NewPerHost returns a PerHost Dialer that directs connections to either 25 | // defaultDialer or bypass, depending on whether the connection matches one of 26 | // the configured rules. 27 | func NewPerHost(defaultDialer, bypass Dialer) *PerHost { 28 | return &PerHost{ 29 | def: defaultDialer, 30 | bypass: bypass, 31 | } 32 | } 33 | 34 | // Dial connects to the address addr on the given network through either 35 | // defaultDialer or bypass. 36 | func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) { 37 | host, _, err := net.SplitHostPort(addr) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | return p.dialerForRequest(host).Dial(network, addr) 43 | } 44 | 45 | // DialContext connects to the address addr on the given network through either 46 | // defaultDialer or bypass. 47 | func (p *PerHost) DialContext(ctx context.Context, network, addr string) (c net.Conn, err error) { 48 | host, _, err := net.SplitHostPort(addr) 49 | if err != nil { 50 | return nil, err 51 | } 52 | d := p.dialerForRequest(host) 53 | if x, ok := d.(ContextDialer); ok { 54 | return x.DialContext(ctx, network, addr) 55 | } 56 | return dialContext(ctx, d, network, addr) 57 | } 58 | 59 | func (p *PerHost) dialerForRequest(host string) Dialer { 60 | if ip := net.ParseIP(host); ip != nil { 61 | for _, net := range p.bypassNetworks { 62 | if net.Contains(ip) { 63 | return p.bypass 64 | } 65 | } 66 | for _, bypassIP := range p.bypassIPs { 67 | if bypassIP.Equal(ip) { 68 | return p.bypass 69 | } 70 | } 71 | return p.def 72 | } 73 | 74 | for _, zone := range p.bypassZones { 75 | if strings.HasSuffix(host, zone) { 76 | return p.bypass 77 | } 78 | if host == zone[1:] { 79 | // For a zone ".example.com", we match "example.com" 80 | // too. 81 | return p.bypass 82 | } 83 | } 84 | for _, bypassHost := range p.bypassHosts { 85 | if bypassHost == host { 86 | return p.bypass 87 | } 88 | } 89 | return p.def 90 | } 91 | 92 | // AddFromString parses a string that contains comma-separated values 93 | // specifying hosts that should use the bypass proxy. Each value is either an 94 | // IP address, a CIDR range, a zone (*.example.com) or a host name 95 | // (localhost). A best effort is made to parse the string and errors are 96 | // ignored. 97 | func (p *PerHost) AddFromString(s string) { 98 | hosts := strings.Split(s, ",") 99 | for _, host := range hosts { 100 | host = strings.TrimSpace(host) 101 | if len(host) == 0 { 102 | continue 103 | } 104 | if strings.Contains(host, "/") { 105 | // We assume that it's a CIDR address like 127.0.0.0/8 106 | if _, net, err := net.ParseCIDR(host); err == nil { 107 | p.AddNetwork(net) 108 | } 109 | continue 110 | } 111 | if ip := net.ParseIP(host); ip != nil { 112 | p.AddIP(ip) 113 | continue 114 | } 115 | if strings.HasPrefix(host, "*.") { 116 | p.AddZone(host[1:]) 117 | continue 118 | } 119 | p.AddHost(host) 120 | } 121 | } 122 | 123 | // AddIP specifies an IP address that will use the bypass proxy. Note that 124 | // this will only take effect if a literal IP address is dialed. A connection 125 | // to a named host will never match an IP. 126 | func (p *PerHost) AddIP(ip net.IP) { 127 | p.bypassIPs = append(p.bypassIPs, ip) 128 | } 129 | 130 | // AddNetwork specifies an IP range that will use the bypass proxy. Note that 131 | // this will only take effect if a literal IP address is dialed. A connection 132 | // to a named host will never match. 133 | func (p *PerHost) AddNetwork(net *net.IPNet) { 134 | p.bypassNetworks = append(p.bypassNetworks, net) 135 | } 136 | 137 | // AddZone specifies a DNS suffix that will use the bypass proxy. A zone of 138 | // "example.com" matches "example.com" and all of its subdomains. 139 | func (p *PerHost) AddZone(zone string) { 140 | if strings.HasSuffix(zone, ".") { 141 | zone = zone[:len(zone)-1] 142 | } 143 | if !strings.HasPrefix(zone, ".") { 144 | zone = "." + zone 145 | } 146 | p.bypassZones = append(p.bypassZones, zone) 147 | } 148 | 149 | // AddHost specifies a host name that will use the bypass proxy. 150 | func (p *PerHost) AddHost(host string) { 151 | if strings.HasSuffix(host, ".") { 152 | host = host[:len(host)-1] 153 | } 154 | p.bypassHosts = append(p.bypassHosts, host) 155 | } 156 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/proxy/proxy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package proxy provides support for a variety of protocols to proxy network 6 | // data. 7 | package proxy // import "golang.org/x/net/proxy" 8 | 9 | import ( 10 | "errors" 11 | "net" 12 | "net/url" 13 | "os" 14 | "sync" 15 | ) 16 | 17 | // A Dialer is a means to establish a connection. 18 | // Custom dialers should also implement ContextDialer. 19 | type Dialer interface { 20 | // Dial connects to the given address via the proxy. 21 | Dial(network, addr string) (c net.Conn, err error) 22 | } 23 | 24 | // Auth contains authentication parameters that specific Dialers may require. 25 | type Auth struct { 26 | User, Password string 27 | } 28 | 29 | // FromEnvironment returns the dialer specified by the proxy-related 30 | // variables in the environment and makes underlying connections 31 | // directly. 32 | func FromEnvironment() Dialer { 33 | return FromEnvironmentUsing(Direct) 34 | } 35 | 36 | // FromEnvironmentUsing returns the dialer specify by the proxy-related 37 | // variables in the environment and makes underlying connections 38 | // using the provided forwarding Dialer (for instance, a *net.Dialer 39 | // with desired configuration). 40 | func FromEnvironmentUsing(forward Dialer) Dialer { 41 | allProxy := allProxyEnv.Get() 42 | if len(allProxy) == 0 { 43 | return forward 44 | } 45 | 46 | proxyURL, err := url.Parse(allProxy) 47 | if err != nil { 48 | return forward 49 | } 50 | proxy, err := FromURL(proxyURL, forward) 51 | if err != nil { 52 | return forward 53 | } 54 | 55 | noProxy := noProxyEnv.Get() 56 | if len(noProxy) == 0 { 57 | return proxy 58 | } 59 | 60 | perHost := NewPerHost(proxy, forward) 61 | perHost.AddFromString(noProxy) 62 | return perHost 63 | } 64 | 65 | // proxySchemes is a map from URL schemes to a function that creates a Dialer 66 | // from a URL with such a scheme. 67 | var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error) 68 | 69 | // RegisterDialerType takes a URL scheme and a function to generate Dialers from 70 | // a URL with that scheme and a forwarding Dialer. Registered schemes are used 71 | // by FromURL. 72 | func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) { 73 | if proxySchemes == nil { 74 | proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error)) 75 | } 76 | proxySchemes[scheme] = f 77 | } 78 | 79 | // FromURL returns a Dialer given a URL specification and an underlying 80 | // Dialer for it to make network requests. 81 | func FromURL(u *url.URL, forward Dialer) (Dialer, error) { 82 | var auth *Auth 83 | if u.User != nil { 84 | auth = new(Auth) 85 | auth.User = u.User.Username() 86 | if p, ok := u.User.Password(); ok { 87 | auth.Password = p 88 | } 89 | } 90 | 91 | switch u.Scheme { 92 | case "socks5", "socks5h": 93 | addr := u.Hostname() 94 | port := u.Port() 95 | if port == "" { 96 | port = "1080" 97 | } 98 | return SOCKS5("tcp", net.JoinHostPort(addr, port), auth, forward) 99 | } 100 | 101 | // If the scheme doesn't match any of the built-in schemes, see if it 102 | // was registered by another package. 103 | if proxySchemes != nil { 104 | if f, ok := proxySchemes[u.Scheme]; ok { 105 | return f(u, forward) 106 | } 107 | } 108 | 109 | return nil, errors.New("proxy: unknown scheme: " + u.Scheme) 110 | } 111 | 112 | var ( 113 | allProxyEnv = &envOnce{ 114 | names: []string{"ALL_PROXY", "all_proxy"}, 115 | } 116 | noProxyEnv = &envOnce{ 117 | names: []string{"NO_PROXY", "no_proxy"}, 118 | } 119 | ) 120 | 121 | // envOnce looks up an environment variable (optionally by multiple 122 | // names) once. It mitigates expensive lookups on some platforms 123 | // (e.g. Windows). 124 | // (Borrowed from net/http/transport.go) 125 | type envOnce struct { 126 | names []string 127 | once sync.Once 128 | val string 129 | } 130 | 131 | func (e *envOnce) Get() string { 132 | e.once.Do(e.init) 133 | return e.val 134 | } 135 | 136 | func (e *envOnce) init() { 137 | for _, n := range e.names { 138 | e.val = os.Getenv(n) 139 | if e.val != "" { 140 | return 141 | } 142 | } 143 | } 144 | 145 | // reset is used by tests 146 | func (e *envOnce) reset() { 147 | e.once = sync.Once{} 148 | e.val = "" 149 | } 150 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/proxy/socks5.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package proxy 6 | 7 | import ( 8 | "context" 9 | "net" 10 | 11 | "golang.org/x/net/internal/socks" 12 | ) 13 | 14 | // SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given 15 | // address with an optional username and password. 16 | // See RFC 1928 and RFC 1929. 17 | func SOCKS5(network, address string, auth *Auth, forward Dialer) (Dialer, error) { 18 | d := socks.NewDialer(network, address) 19 | if forward != nil { 20 | if f, ok := forward.(ContextDialer); ok { 21 | d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) { 22 | return f.DialContext(ctx, network, address) 23 | } 24 | } else { 25 | d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) { 26 | return dialContext(ctx, forward, network, address) 27 | } 28 | } 29 | } 30 | if auth != nil { 31 | up := socks.UsernamePassword{ 32 | Username: auth.User, 33 | Password: auth.Password, 34 | } 35 | d.AuthMethods = []socks.AuthMethod{ 36 | socks.AuthMethodNotRequired, 37 | socks.AuthMethodUsernamePassword, 38 | } 39 | d.Authenticate = up.Authenticate 40 | } 41 | return d, nil 42 | } 43 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at http://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/semaphore/semaphore.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package semaphore provides a weighted semaphore implementation. 6 | package semaphore // import "golang.org/x/sync/semaphore" 7 | 8 | import ( 9 | "container/list" 10 | "context" 11 | "sync" 12 | ) 13 | 14 | type waiter struct { 15 | n int64 16 | ready chan<- struct{} // Closed when semaphore acquired. 17 | } 18 | 19 | // NewWeighted creates a new weighted semaphore with the given 20 | // maximum combined weight for concurrent access. 21 | func NewWeighted(n int64) *Weighted { 22 | w := &Weighted{size: n} 23 | return w 24 | } 25 | 26 | // Weighted provides a way to bound concurrent access to a resource. 27 | // The callers can request access with a given weight. 28 | type Weighted struct { 29 | size int64 30 | cur int64 31 | mu sync.Mutex 32 | waiters list.List 33 | } 34 | 35 | // Acquire acquires the semaphore with a weight of n, blocking until resources 36 | // are available or ctx is done. On success, returns nil. On failure, returns 37 | // ctx.Err() and leaves the semaphore unchanged. 38 | // 39 | // If ctx is already done, Acquire may still succeed without blocking. 40 | func (s *Weighted) Acquire(ctx context.Context, n int64) error { 41 | s.mu.Lock() 42 | if s.size-s.cur >= n && s.waiters.Len() == 0 { 43 | s.cur += n 44 | s.mu.Unlock() 45 | return nil 46 | } 47 | 48 | if n > s.size { 49 | // Don't make other Acquire calls block on one that's doomed to fail. 50 | s.mu.Unlock() 51 | <-ctx.Done() 52 | return ctx.Err() 53 | } 54 | 55 | ready := make(chan struct{}) 56 | w := waiter{n: n, ready: ready} 57 | elem := s.waiters.PushBack(w) 58 | s.mu.Unlock() 59 | 60 | select { 61 | case <-ctx.Done(): 62 | err := ctx.Err() 63 | s.mu.Lock() 64 | select { 65 | case <-ready: 66 | // Acquired the semaphore after we were canceled. Rather than trying to 67 | // fix up the queue, just pretend we didn't notice the cancelation. 68 | err = nil 69 | default: 70 | isFront := s.waiters.Front() == elem 71 | s.waiters.Remove(elem) 72 | // If we're at the front and there're extra tokens left, notify other waiters. 73 | if isFront && s.size > s.cur { 74 | s.notifyWaiters() 75 | } 76 | } 77 | s.mu.Unlock() 78 | return err 79 | 80 | case <-ready: 81 | return nil 82 | } 83 | } 84 | 85 | // TryAcquire acquires the semaphore with a weight of n without blocking. 86 | // On success, returns true. On failure, returns false and leaves the semaphore unchanged. 87 | func (s *Weighted) TryAcquire(n int64) bool { 88 | s.mu.Lock() 89 | success := s.size-s.cur >= n && s.waiters.Len() == 0 90 | if success { 91 | s.cur += n 92 | } 93 | s.mu.Unlock() 94 | return success 95 | } 96 | 97 | // Release releases the semaphore with a weight of n. 98 | func (s *Weighted) Release(n int64) { 99 | s.mu.Lock() 100 | s.cur -= n 101 | if s.cur < 0 { 102 | s.mu.Unlock() 103 | panic("semaphore: released more than held") 104 | } 105 | s.notifyWaiters() 106 | s.mu.Unlock() 107 | } 108 | 109 | func (s *Weighted) notifyWaiters() { 110 | for { 111 | next := s.waiters.Front() 112 | if next == nil { 113 | break // No more waiters blocked. 114 | } 115 | 116 | w := next.Value.(waiter) 117 | if s.size-s.cur < w.n { 118 | // Not enough tokens for the next waiter. We could keep going (to try to 119 | // find a waiter with a smaller request), but under load that could cause 120 | // starvation for large requests; instead, we leave all remaining waiters 121 | // blocked. 122 | // 123 | // Consider a semaphore used as a read-write lock, with N tokens, N 124 | // readers, and one writer. Each reader can Acquire(1) to obtain a read 125 | // lock. The writer can Acquire(N) to obtain a write lock, excluding all 126 | // of the readers. If we allow the readers to jump ahead in the queue, 127 | // the writer will starve — there is always one token available for every 128 | // reader. 129 | break 130 | } 131 | 132 | s.cur += w.n 133 | s.waiters.Remove(next) 134 | close(w.ready) 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/eclipse/paho.mqtt.golang v1.4.1 2 | ## explicit; go 1.14 3 | github.com/eclipse/paho.mqtt.golang 4 | github.com/eclipse/paho.mqtt.golang/packets 5 | # github.com/gorilla/websocket v1.4.2 6 | ## explicit; go 1.12 7 | github.com/gorilla/websocket 8 | # github.com/openfaas/connector-sdk v0.6.7 9 | ## explicit; go 1.17 10 | github.com/openfaas/connector-sdk/types 11 | # github.com/openfaas/faas-provider v0.19.0 12 | ## explicit; go 1.17 13 | github.com/openfaas/faas-provider/auth 14 | github.com/openfaas/faas-provider/types 15 | # golang.org/x/net v0.7.0 16 | ## explicit; go 1.17 17 | golang.org/x/net/internal/socks 18 | golang.org/x/net/proxy 19 | # golang.org/x/sync v0.0.0-20210220032951-036812b2e83c 20 | ## explicit 21 | golang.org/x/sync/semaphore 22 | --------------------------------------------------------------------------------