Skip to content

Commit 20a5bb7

Browse files
committed
Simple HUB
1 parent 1ff38df commit 20a5bb7

File tree

2 files changed

+93
-14
lines changed

2 files changed

+93
-14
lines changed

home.html

+10-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
const socket = setupWebsocket();
2727

28+
const ws = newWebsocket();
29+
2830
// Handle the form submission and send the message to the websocket.
2931
document
3032
.getElementById("form")
@@ -39,28 +41,33 @@
3941
return false;
4042
}
4143
socket.emit("command", input.value);
44+
// emit to ws
45+
ws.send(input.value);
4246
input.value = "";
47+
48+
4349
});
4450
});
4551

46-
window.onload = function () {
52+
function newWebsocket() {
4753
var conn;
4854
if (window["WebSocket"]) {
4955
console.log("Connecting to websocket", "ws://" + document.location.host + "/ws");
5056
conn = new WebSocket("ws://127.0.0.1:9001/ws");
5157
conn.onclose = function (evt) {
52-
console.log("Closing: " + evt);
58+
console.log("Closing: " + evt.data);
5359
};
5460
conn.onmessage = function (evt) {
5561
console.log("Received: " + evt.data);
5662
const wsLog = document.getElementById("ws-log");
5763
wsLog.textContent = evt.data;
5864
};
5965
} else {
60-
var item = document.createElement("div");
66+
var item = document.createElement("ws-log");
6167
item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
6268
appendLog(item);
6369
}
70+
return conn;
6471
};
6572

6673
function getListMsgVisibility() {

main.go

+83-11
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"runtime/debug"
3333
"strconv"
3434
"strings"
35+
"sync"
3536
"time"
3637

3738
cert "github.com/arduino/arduino-create-agent/certificates"
@@ -467,9 +468,10 @@ func loop() {
467468
r.POST("/update", updateHandler)
468469

469470
// TODO: temporary using a different port for the websocket server
471+
hub := newHub()
470472
go func() {
471473
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
472-
ServeWS(w, r)
474+
ServeWS(hub, w, r)
473475
})
474476
fmt.Println("Starting server and websocket on " + *address + ":9001")
475477
log.Fatal(http.ListenAndServe(*address+":9001", nil))
@@ -570,21 +572,91 @@ func promptInstallCertsSafari() bool {
570572
return utilities.UserPrompt("The Arduino Agent needs a local HTTPS certificate to work correctly with Safari.\nIf you use Safari, you need to install it.", "{\"Do not install\", \"Install the certificate for Safari\"}", "Install the certificate for Safari", "Install the certificate for Safari", "Arduino Agent: Install certificate")
571573
}
572574

573-
var upgrader = websocket.Upgrader{}
574-
575-
func ServeWS(w http.ResponseWriter, r *http.Request) {
576-
upgrader.CheckOrigin = func(r *http.Request) bool {
575+
var upgrader = websocket.Upgrader{
576+
CheckOrigin: func(r *http.Request) bool {
577577
// TODO: check origin with the list of allowed origins
578578
return true
579-
}
579+
},
580+
}
581+
582+
const (
583+
// Time allowed to write a message to the peer.
584+
writeWait = 10 * time.Second
585+
586+
// Time allowed to read the next pong message from the peer.
587+
pongWait = 60 * time.Second
588+
589+
// Send pings to peer with this period. Must be less than pongWait.
590+
pingPeriod = (pongWait * 9) / 10
591+
592+
// Maximum message size allowed from peer.
593+
maxMessageSize = 512
594+
)
580595

581-
ws, err := upgrader.Upgrade(w, r, nil)
596+
func ServeWS(hub *Hub, w http.ResponseWriter, r *http.Request) {
597+
conn, err := upgrader.Upgrade(w, r, nil)
582598
if err != nil {
583-
log.Println("upgrade:", err)
599+
log.Error("upgrade:", err)
584600
return
585601
}
602+
defer hub.unregister(conn)
603+
604+
hub.register(conn)
605+
606+
read(hub, conn)
607+
}
608+
609+
func read(hub *Hub, conn *websocket.Conn) {
610+
611+
conn.SetReadLimit(maxMessageSize)
612+
conn.SetReadDeadline(time.Now().Add(pongWait))
613+
conn.SetPongHandler(func(string) error { conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
614+
for {
615+
_, message, err := conn.ReadMessage()
616+
if err != nil {
617+
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
618+
log.Printf("error: %v", err)
619+
}
620+
break
621+
}
622+
log.Info("Received message from client: " + string(message))
623+
hub.broadcast(message)
624+
}
625+
}
626+
627+
type Hub struct {
628+
// Registered clients.
629+
clients map[*websocket.Conn]bool
630+
mu sync.Mutex
631+
}
632+
633+
func newHub() *Hub {
634+
return &Hub{
635+
clients: make(map[*websocket.Conn]bool),
636+
}
637+
}
586638

587-
defer ws.Close()
588-
fmt.Println("[WS] Client connected")
589-
ws.WriteMessage(websocket.TextMessage, []byte("Hello, client!"))
639+
func (h *Hub) register(conn *websocket.Conn) {
640+
defer h.mu.Unlock()
641+
h.mu.Lock()
642+
h.clients[conn] = true
643+
conn.WriteMessage(websocket.TextMessage, []byte("Hello, client!"))
644+
}
645+
646+
func (h *Hub) unregister(conn *websocket.Conn) {
647+
defer h.mu.Unlock()
648+
h.mu.Lock()
649+
delete(h.clients, conn)
650+
conn.Close()
651+
}
652+
653+
func (h *Hub) broadcast(message []byte) {
654+
for conn := range h.clients {
655+
log.Info("Broadcasting message to client" + conn.RemoteAddr().String())
656+
err := conn.WriteMessage(websocket.TextMessage, message)
657+
if err != nil {
658+
// TODO: handle error
659+
log.Println("write:", err)
660+
}
661+
}
590662
}

0 commit comments

Comments
 (0)