summaryrefslogtreecommitdiff
path: root/vendor/github.com/eclipse/paho.mqtt.golang/websocket.go
diff options
context:
space:
mode:
authorxengineering <me@xengineering.eu>2025-12-20 12:09:44 +0100
committerxengineering <me@xengineering.eu>2025-12-20 12:09:44 +0100
commitb0fcc3e7590b9f3486f1edf8c2b004d035e38652 (patch)
tree81c123444d97f311e3b45a1881c9d2ff4ad2581b /vendor/github.com/eclipse/paho.mqtt.golang/websocket.go
parentf9fac85222892e45554a2cc49dd93455a374ef68 (diff)
downloadsia-server-b0fcc3e7590b9f3486f1edf8c2b004d035e38652.tar
sia-server-b0fcc3e7590b9f3486f1edf8c2b004d035e38652.tar.zst
sia-server-b0fcc3e7590b9f3486f1edf8c2b004d035e38652.zip
Add github.com/eclipse/paho.mqtt.golang
This dependency is required to use MQTT with Go.
Diffstat (limited to 'vendor/github.com/eclipse/paho.mqtt.golang/websocket.go')
-rw-r--r--vendor/github.com/eclipse/paho.mqtt.golang/websocket.go132
1 files changed, 132 insertions, 0 deletions
diff --git a/vendor/github.com/eclipse/paho.mqtt.golang/websocket.go b/vendor/github.com/eclipse/paho.mqtt.golang/websocket.go
new file mode 100644
index 0000000..e0f2583
--- /dev/null
+++ b/vendor/github.com/eclipse/paho.mqtt.golang/websocket.go
@@ -0,0 +1,132 @@
+/*
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ */
+
+package mqtt
+
+import (
+ "crypto/tls"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+ "sync"
+ "time"
+
+ "github.com/gorilla/websocket"
+)
+
+// WebsocketOptions are config options for a websocket dialer
+type WebsocketOptions struct {
+ ReadBufferSize int
+ WriteBufferSize int
+ Proxy ProxyFunction
+}
+
+type ProxyFunction func(req *http.Request) (*url.URL, error)
+
+// NewWebsocket returns a new websocket and returns a net.Conn compatible interface using the gorilla/websocket package
+func NewWebsocket(host string, tlsc *tls.Config, timeout time.Duration, requestHeader http.Header, options *WebsocketOptions) (net.Conn, error) {
+ if timeout == 0 {
+ timeout = 10 * time.Second
+ }
+
+ if options == nil {
+ // Apply default options
+ options = &WebsocketOptions{}
+ }
+ if options.Proxy == nil {
+ options.Proxy = http.ProxyFromEnvironment
+ }
+ dialer := &websocket.Dialer{
+ Proxy: options.Proxy,
+ HandshakeTimeout: timeout,
+ EnableCompression: false,
+ TLSClientConfig: tlsc,
+ Subprotocols: []string{"mqtt"},
+ ReadBufferSize: options.ReadBufferSize,
+ WriteBufferSize: options.WriteBufferSize,
+ }
+
+ ws, resp, err := dialer.Dial(host, requestHeader)
+
+ if err != nil {
+ if resp != nil {
+ WARN.Println(CLI, fmt.Sprintf("Websocket handshake failure. StatusCode: %d. Body: %s", resp.StatusCode, resp.Body))
+ }
+ return nil, err
+ }
+
+ wrapper := &websocketConnector{
+ Conn: ws,
+ }
+ return wrapper, err
+}
+
+// websocketConnector is a websocket wrapper so it satisfies the net.Conn interface so it is a
+// drop in replacement of the golang.org/x/net/websocket package.
+// Implementation guide taken from https://github.com/gorilla/websocket/issues/282
+type websocketConnector struct {
+ *websocket.Conn
+ r io.Reader
+ rio sync.Mutex
+ wio sync.Mutex
+}
+
+// SetDeadline sets both the read and write deadlines
+func (c *websocketConnector) SetDeadline(t time.Time) error {
+ if err := c.SetReadDeadline(t); err != nil {
+ return err
+ }
+ err := c.SetWriteDeadline(t)
+ return err
+}
+
+// Write writes data to the websocket
+func (c *websocketConnector) Write(p []byte) (int, error) {
+ c.wio.Lock()
+ defer c.wio.Unlock()
+
+ err := c.WriteMessage(websocket.BinaryMessage, p)
+ if err != nil {
+ return 0, err
+ }
+ return len(p), nil
+}
+
+// Read reads the current websocket frame
+func (c *websocketConnector) Read(p []byte) (int, error) {
+ c.rio.Lock()
+ defer c.rio.Unlock()
+ for {
+ if c.r == nil {
+ // Advance to next message.
+ var err error
+ _, c.r, err = c.NextReader()
+ if err != nil {
+ return 0, err
+ }
+ }
+ n, err := c.r.Read(p)
+ if err == io.EOF {
+ // At end of message.
+ c.r = nil
+ if n > 0 {
+ return n, nil
+ }
+ // No data read, continue to next message.
+ continue
+ }
+ return n, err
+ }
+}