mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-06 03:20:13 +08:00
feat: put terminal service into container refactor: separate main into terminal and websocket feat: create zsh using commander in home feat: pass backendUrl to container feat: pass token to ws server to cmd-hook feat: gen terminal access token for frontend feat: success to connect through traefik fix: handle invalid jwt feat: connect to session container via traefik
96 lines
2.1 KiB
Go
96 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gorilla/websocket"
|
|
)
|
|
|
|
const (
|
|
// Time allowed to write a message to the peer.
|
|
writeWait = 10 * time.Second
|
|
|
|
// Maximum message size allowed from peer.
|
|
maxMessageSize = 8192
|
|
|
|
// Time allowed to read the next pong message from the peer.
|
|
pongWait = 60 * time.Second
|
|
|
|
// Send pings to peer with this period. Must be less than pongWait.
|
|
pingPeriod = (pongWait * 9) / 10
|
|
|
|
// Time to wait before force close on connection.
|
|
closeGracePeriod = 10 * time.Second
|
|
)
|
|
|
|
var upgrader = websocket.Upgrader{
|
|
ReadBufferSize: 1024,
|
|
WriteBufferSize: 1024,
|
|
// Allow all origins for now - we'll restrict this in production
|
|
CheckOrigin: func(r *http.Request) bool {
|
|
return true
|
|
},
|
|
}
|
|
|
|
func pumpStdin(ws *websocket.Conn, w io.Writer) {
|
|
defer ws.Close()
|
|
ws.SetReadLimit(maxMessageSize)
|
|
ws.SetReadDeadline(time.Now().Add(pongWait))
|
|
ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
|
for {
|
|
_, message, err := ws.ReadMessage()
|
|
if err != nil {
|
|
break
|
|
}
|
|
if _, err := w.Write(message); err != nil {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func pumpStdout(ws *websocket.Conn, r io.Reader, done chan struct{}) {
|
|
defer func() {
|
|
}()
|
|
buf := make([]byte, 1024)
|
|
for {
|
|
n, err := r.Read(buf)
|
|
if err != nil {
|
|
break
|
|
}
|
|
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
|
if err := ws.WriteMessage(websocket.TextMessage, buf[:n]); err != nil {
|
|
ws.Close()
|
|
break
|
|
}
|
|
}
|
|
close(done)
|
|
|
|
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
|
ws.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
|
time.Sleep(closeGracePeriod)
|
|
ws.Close()
|
|
}
|
|
|
|
func ping(ws *websocket.Conn, done chan struct{}) {
|
|
ticker := time.NewTicker(pingPeriod)
|
|
defer ticker.Stop()
|
|
for {
|
|
select {
|
|
case <-ticker.C:
|
|
if err := ws.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(writeWait)); err != nil {
|
|
log.Println("ping:", err)
|
|
}
|
|
case <-done:
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func internalError(ws *websocket.Conn, msg string, err error) {
|
|
log.Println(msg, err)
|
|
ws.WriteMessage(websocket.TextMessage, []byte("Internal server error."))
|
|
}
|