Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to support websocket? #7

Open
Leadrive opened this issue Sep 5, 2022 · 0 comments
Open

How to support websocket? #7

Leadrive opened this issue Sep 5, 2022 · 0 comments

Comments

@Leadrive
Copy link

Leadrive commented Sep 5, 2022

Hi, I test this project. And I want to support the ws.

package main

import (
	"flag"
	"io"
	"log"
	"net"
	"net/http"
	"time"

	websocket "github.com/gorilla/websocket"
	gows "golang.org/x/net/websocket"
)

var (
	flagBind    = flag.String("bind", ":8883", "bind to")
	flagBackend = flag.String("be", "127.0.0.1:1883", "nats server")
	flagToken   = flag.String("token", "test", "secret token for http connection")
	flagPath    = flag.String("http-path", "mq", "http path to websockets")
)
var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

func copyWorker(dst io.Writer, src io.Reader, doneCh chan bool) {
	io.Copy(dst, src)
	doneCh <- true
}

func relayHandler(ws *gows.Conn) {
	log.Println("relayHandler")
	conn, err := net.Dial("tcp", *flagBackend)
	if err != nil {
		log.Printf("[ERROR] %v \n", err)
		return
	}

	//if binaryMode {
	//	// ws.PayloadType = websocket.BinaryFrame
	//}

	doneCh := make(chan bool)

	go copyWorker(conn, ws, doneCh)
	go copyWorker(ws, conn, doneCh)

	<-doneCh
	conn.Close()
	ws.Close()
	<-doneCh
}

func main() {
	flag.Parse()
	log.Printf("bind:%s, backend:%s\n", *flagBind, *flagBackend)
	upgrader.CheckOrigin = func(r *http.Request) bool { return true }
	// nginx config
	/*
		location /  {
			proxy_redirect off;
			proxy_pass http://127.0.0.1:8883/;
			proxy_http_version 1.1;
			proxy_set_header Host $host;
			proxy_set_header Upgrade $http_upgrade;
			proxy_set_header Connection Upgrade;
			proxy_set_header X-real-ip $remote_addr;
			proxy_set_header X-Forwarded-For $remote_addr;
		}
	*/
	http.Handle("/js", gows.Handler(relayHandler))
	http.HandleFunc("/js/health", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("OK"))
	})
	http.HandleFunc("/mqtt/health", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("OK"))
	})
	http.HandleFunc("/mqtt", func(w http.ResponseWriter, r *http.Request) { // go
		log.Printf("request mqtt\n")
		//if r.URL.Query().Get("token") != *flagToken {
		//	http.NotFound(w, r)
		//	return
		//}
		conn, err := upgrader.Upgrade(w, r, nil)
		if err != nil {
			log.Printf("%v\n", err)
			return
		}

		ncon, err := net.Dial("tcp", *flagBackend)
		if err != nil {
			log.Printf("%v", err)
			conn.Close()
			return
		}
		doneCh := make(chan bool)

		conn.UnderlyingConn().(*net.TCPConn).SetKeepAlivePeriod(1 * time.Second)

		go copyWorker(ncon, conn.UnderlyingConn(), doneCh)
		go copyWorker(conn.UnderlyingConn(), ncon, doneCh)

		<-doneCh

		ncon.Close()
		conn.Close()

		<-doneCh
	})

	http.ListenAndServe(*flagBind, nil)
}

After I test it on MQTTX with ws://xxx.xxx.xxx.xxx:8883/mqtt
It take a panic
ERROR 2022/09/06 01:06:39 %!v(PANIC=String method: runtime error: invalid memory address or nil pointer dereference) unexpected EOF
DEBUG 2022/09/06 01:06:39 %!v(PANIC=String method: runtime error: invalid memory address or nil pointer dereference) client connection could not be established

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant