mirror of https://github.com/jetkvm/kvm.git
release 0.3.9 (#349)
This commit is contained in:
commit
5452d7c721
43
cloud.go
43
cloud.go
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -59,6 +60,13 @@ var (
|
|||
},
|
||||
[]string{"type", "source"},
|
||||
)
|
||||
metricConnectionLastPingReceivedTimestamp = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "jetkvm_connection_last_ping_received_timestamp",
|
||||
Help: "The timestamp when the last ping request was received",
|
||||
},
|
||||
[]string{"type", "source"},
|
||||
)
|
||||
metricConnectionLastPingDuration = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "jetkvm_connection_last_ping_duration",
|
||||
|
@ -76,16 +84,23 @@ var (
|
|||
},
|
||||
[]string{"type", "source"},
|
||||
)
|
||||
metricConnectionTotalPingCount = promauto.NewCounterVec(
|
||||
metricConnectionTotalPingSentCount = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_connection_total_ping_count",
|
||||
Name: "jetkvm_connection_total_ping_sent",
|
||||
Help: "The total number of pings sent to the connection",
|
||||
},
|
||||
[]string{"type", "source"},
|
||||
)
|
||||
metricConnectionTotalPingReceivedCount = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_connection_total_ping_received",
|
||||
Help: "The total number of pings received from the connection",
|
||||
},
|
||||
[]string{"type", "source"},
|
||||
)
|
||||
metricConnectionSessionRequestCount = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_connection_session_total_request_count",
|
||||
Name: "jetkvm_connection_session_total_requests",
|
||||
Help: "The total number of session requests received",
|
||||
},
|
||||
[]string{"type", "source"},
|
||||
|
@ -131,6 +146,8 @@ func wsResetMetrics(established bool, sourceType string, source string) {
|
|||
metricConnectionLastPingTimestamp.WithLabelValues(sourceType, source).Set(-1)
|
||||
metricConnectionLastPingDuration.WithLabelValues(sourceType, source).Set(-1)
|
||||
|
||||
metricConnectionLastPingReceivedTimestamp.WithLabelValues(sourceType, source).Set(-1)
|
||||
|
||||
metricConnectionLastSessionRequestTimestamp.WithLabelValues(sourceType, source).Set(-1)
|
||||
metricConnectionLastSessionRequestDuration.WithLabelValues(sourceType, source).Set(-1)
|
||||
|
||||
|
@ -275,18 +292,31 @@ func runWebsocketClient() error {
|
|||
defer cancelDial()
|
||||
c, _, err := websocket.Dial(dialCtx, wsURL.String(), &websocket.DialOptions{
|
||||
HTTPHeader: header,
|
||||
OnPingReceived: func(ctx context.Context, payload []byte) bool {
|
||||
websocketLogger.Infof("ping frame received: %v, source: %s, sourceType: cloud", payload, wsURL.Host)
|
||||
|
||||
metricConnectionTotalPingReceivedCount.WithLabelValues("cloud", wsURL.Host).Inc()
|
||||
metricConnectionLastPingReceivedTimestamp.WithLabelValues("cloud", wsURL.Host).SetToCurrentTime()
|
||||
|
||||
return true
|
||||
},
|
||||
})
|
||||
// if the context is canceled, we don't want to return an error
|
||||
if err != nil {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
cloudLogger.Infof("websocket connection canceled")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
defer c.CloseNow() //nolint:errcheck
|
||||
cloudLogger.Infof("websocket connected to %s", wsURL)
|
||||
|
||||
// set the metrics when we successfully connect to the cloud.
|
||||
wsResetMetrics(true, "cloud", "")
|
||||
wsResetMetrics(true, "cloud", wsURL.Host)
|
||||
|
||||
// we don't have a source for the cloud connection
|
||||
return handleWebRTCSignalWsMessages(c, true, "")
|
||||
return handleWebRTCSignalWsMessages(c, true, wsURL.Host)
|
||||
}
|
||||
|
||||
func authenticateSession(ctx context.Context, c *websocket.Conn, req WebRTCSessionRequest) error {
|
||||
|
@ -375,9 +405,6 @@ func handleSessionRequest(ctx context.Context, c *websocket.Conn, req WebRTCSess
|
|||
|
||||
func RunWebsocketClient() {
|
||||
for {
|
||||
// reset the metrics when we start the websocket client.
|
||||
wsResetMetrics(false, "cloud", "")
|
||||
|
||||
// If the cloud token is not set, we don't need to run the websocket client.
|
||||
if config.CloudToken == "" {
|
||||
time.Sleep(5 * time.Second)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Exit immediately if a command exits with a non-zero status
|
||||
set -e
|
||||
|
||||
|
@ -16,7 +18,6 @@ show_help() {
|
|||
echo "Example:"
|
||||
echo " $0 -r 192.168.0.17"
|
||||
echo " $0 -r 192.168.0.17 -u admin"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Default values
|
||||
|
@ -70,10 +71,10 @@ cd bin
|
|||
ssh "${REMOTE_USER}@${REMOTE_HOST}" "killall jetkvm_app_debug || true"
|
||||
|
||||
# Copy the binary to the remote host
|
||||
cat jetkvm_app | ssh "${REMOTE_USER}@${REMOTE_HOST}" "cat > $REMOTE_PATH/jetkvm_app_debug"
|
||||
ssh "${REMOTE_USER}@${REMOTE_HOST}" "cat > ${REMOTE_PATH}/jetkvm_app_debug" < jetkvm_app
|
||||
|
||||
# Deploy and run the application on the remote host
|
||||
ssh "${REMOTE_USER}@${REMOTE_HOST}" ash <<EOF
|
||||
ssh "${REMOTE_USER}@${REMOTE_HOST}" ash << EOF
|
||||
set -e
|
||||
|
||||
# Set the library path to include the directory where librockit.so is located
|
||||
|
@ -84,13 +85,13 @@ killall jetkvm_app || true
|
|||
killall jetkvm_app_debug || true
|
||||
|
||||
# Navigate to the directory where the binary will be stored
|
||||
cd "$REMOTE_PATH"
|
||||
cd "${REMOTE_PATH}"
|
||||
|
||||
# Make the new binary executable
|
||||
chmod +x jetkvm_app_debug
|
||||
|
||||
# Run the application in the background
|
||||
PION_LOG_TRACE=jetkvm,cloud ./jetkvm_app_debug
|
||||
PION_LOG_TRACE=jetkvm,cloud,websocket ./jetkvm_app_debug
|
||||
EOF
|
||||
|
||||
echo "Deployment complete."
|
||||
|
|
2
go.mod
2
go.mod
|
@ -7,7 +7,7 @@ toolchain go1.21.1
|
|||
require (
|
||||
github.com/Masterminds/semver/v3 v3.3.0
|
||||
github.com/beevik/ntp v1.3.1
|
||||
github.com/coder/websocket v1.8.12
|
||||
github.com/coder/websocket v1.8.13
|
||||
github.com/coreos/go-oidc/v3 v3.11.0
|
||||
github.com/creack/pty v1.1.23
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
|
|
2
go.sum
2
go.sum
|
@ -18,6 +18,8 @@ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
|||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
||||
github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
||||
github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE=
|
||||
github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
||||
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
|
||||
github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
|
||||
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
||||
|
|
6
ota.go
6
ota.go
|
@ -126,12 +126,10 @@ func downloadFile(ctx context.Context, path string, url string, downloadProgress
|
|||
return fmt.Errorf("error creating request: %w", err)
|
||||
}
|
||||
|
||||
// TODO: set a separate timeout for the download but keep the TLS handshake short
|
||||
// use Transport here will cause CA certificate validation failure so we temporarily removed it
|
||||
client := http.Client{
|
||||
// allow a longer timeout for the download but keep the TLS handshake short
|
||||
Timeout: 10 * time.Minute,
|
||||
Transport: &http.Transport{
|
||||
TLSHandshakeTimeout: 1 * time.Minute,
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Check if a commit message was provided
|
||||
if [ -z "$1" ]; then
|
||||
|
@ -26,7 +26,7 @@ git checkout -b release-temp
|
|||
if git ls-remote --heads public main | grep -q 'refs/heads/main'; then
|
||||
git reset --soft public/main
|
||||
else
|
||||
git reset --soft $(git rev-list --max-parents=0 HEAD)
|
||||
git reset --soft "$(git rev-list --max-parents=0 HEAD)"
|
||||
fi
|
||||
|
||||
# Merge changes from main
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Check if an IP address was provided as an argument
|
||||
if [ -z "$1" ]; then
|
||||
|
@ -16,4 +16,4 @@ echo "└───────────────────────
|
|||
# Set the environment variable and run Vite
|
||||
echo "Starting development server with JetKVM device at: $ip_address"
|
||||
sleep 1
|
||||
JETKVM_PROXY_URL="http://$ip_address" npx vite dev --mode=device
|
||||
JETKVM_PROXY_URL="ws://$ip_address" npx vite dev --mode=device
|
||||
|
|
|
@ -15,12 +15,12 @@ const Modal = React.memo(function Modal({
|
|||
onClose: () => void;
|
||||
}) {
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose} className="relative z-10">
|
||||
<Dialog open={open} onClose={onClose} className="relative z-20">
|
||||
<DialogBackdrop
|
||||
transition
|
||||
className="fixed inset-0 bg-gray-500/75 transition-opacity data-[closed]:opacity-0 data-[enter]:duration-500 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in dark:bg-slate-900/90"
|
||||
/>
|
||||
<div className="fixed inset-0 z-10 w-screen overflow-y-auto">
|
||||
<div className="fixed inset-0 z-20 w-screen overflow-y-auto">
|
||||
{/* TODO: This doesn't work well with other-sessions */}
|
||||
<div className="flex min-h-full items-end justify-center p-4 text-center md:items-baseline md:p-4">
|
||||
<DialogPanel
|
||||
|
|
|
@ -28,6 +28,7 @@ export default function WebRTCVideo() {
|
|||
const videoElm = useRef<HTMLVideoElement>(null);
|
||||
const mediaStream = useRTCStore(state => state.mediaStream);
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
const peerConnectionState = useRTCStore(state => state.peerConnectionState);
|
||||
|
||||
// Store hooks
|
||||
const settings = useSettingsStore();
|
||||
|
@ -601,7 +602,10 @@ export default function WebRTCVideo() {
|
|||
"cursor-none":
|
||||
settings.mouseMode === "absolute" &&
|
||||
settings.isCursorHidden,
|
||||
"opacity-0": isVideoLoading || hdmiError,
|
||||
"opacity-0":
|
||||
isVideoLoading ||
|
||||
hdmiError ||
|
||||
peerConnectionState !== "connected",
|
||||
"animate-slideUpFade border border-slate-800/30 opacity-0 shadow dark:border-slate-300/20":
|
||||
isPlaying,
|
||||
},
|
||||
|
|
|
@ -243,7 +243,7 @@ export default function KvmIdRoute() {
|
|||
{
|
||||
heartbeat: true,
|
||||
retryOnError: true,
|
||||
reconnectAttempts: 5,
|
||||
reconnectAttempts: 15,
|
||||
reconnectInterval: 1000,
|
||||
onReconnectStop: () => {
|
||||
console.log("Reconnect stopped");
|
||||
|
@ -398,11 +398,6 @@ export default function KvmIdRoute() {
|
|||
setConnectionFailed(false);
|
||||
setLoadingMessage("Connecting to device...");
|
||||
|
||||
if (peerConnection?.signalingState === "stable") {
|
||||
console.log("[setupPeerConnection] Peer connection already established");
|
||||
return;
|
||||
}
|
||||
|
||||
let pc: RTCPeerConnection;
|
||||
try {
|
||||
console.log("[setupPeerConnection] Creating peer connection");
|
||||
|
@ -499,7 +494,6 @@ export default function KvmIdRoute() {
|
|||
cleanupAndStopReconnecting,
|
||||
iceConfig?.iceServers,
|
||||
legacyHTTPSignaling,
|
||||
peerConnection?.signalingState,
|
||||
sendWebRTCSignal,
|
||||
setDiskChannel,
|
||||
setMediaMediaStream,
|
||||
|
@ -791,6 +785,7 @@ export default function KvmIdRoute() {
|
|||
<button className="absolute top-0" tabIndex={-1} id="videoFocusTrap" />
|
||||
</div>
|
||||
</FocusTrap>
|
||||
|
||||
<div className="grid h-full select-none grid-rows-headerBody">
|
||||
<DashboardNavbar
|
||||
primaryLinks={isOnDevice ? [] : [{ title: "Cloud Devices", to: "/devices" }]}
|
||||
|
@ -801,21 +796,23 @@ export default function KvmIdRoute() {
|
|||
kvmName={deviceName || "JetKVM Device"}
|
||||
/>
|
||||
|
||||
<div className="flex h-full w-full overflow-hidden">
|
||||
<div className="pointer-events-none fixed inset-0 isolate z-20 flex h-full w-full items-center justify-center">
|
||||
<div className="my-2 h-full max-h-[720px] w-full max-w-[1280px] rounded-md">
|
||||
<div className="relative flex h-full w-full overflow-hidden">
|
||||
<WebRTCVideo />
|
||||
<div
|
||||
style={{ animationDuration: "500ms" }}
|
||||
className="pointer-events-none absolute inset-0 flex animate-slideUpFade items-center justify-center p-4 opacity-0"
|
||||
>
|
||||
<div className="relative h-full max-h-[720px] w-full max-w-[1280px] rounded-md">
|
||||
{!!ConnectionStatusElement && ConnectionStatusElement}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{peerConnectionState === "connected" && <WebRTCVideo />}
|
||||
<SidebarContainer sidebarView={sidebarView} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="isolate"
|
||||
className="z-50"
|
||||
onKeyUp={e => e.stopPropagation()}
|
||||
onKeyDown={e => {
|
||||
e.stopPropagation();
|
||||
|
|
120
web.go
120
web.go
|
@ -1,9 +1,11 @@
|
|||
package kvm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
|
@ -99,6 +101,22 @@ func setupRouter() *gin.Engine {
|
|||
protected := r.Group("/")
|
||||
protected.Use(protectedMiddleware())
|
||||
{
|
||||
/*
|
||||
* Legacy WebRTC session endpoint
|
||||
*
|
||||
* This endpoint is maintained for backward compatibility when users upgrade from a version
|
||||
* using the legacy HTTP-based signaling method to the new WebSocket-based signaling method.
|
||||
*
|
||||
* During the upgrade process, when the "Rebooting device after update..." message appears,
|
||||
* the browser still runs the previous JavaScript code which polls this endpoint to establish
|
||||
* a new WebRTC session. Once the session is established, the page will automatically reload
|
||||
* with the updated code.
|
||||
*
|
||||
* Without this endpoint, the stale JavaScript would fail to establish a connection,
|
||||
* causing users to see the "Rebooting device after update..." message indefinitely
|
||||
* until they manually refresh the page, leading to a confusing user experience.
|
||||
*/
|
||||
protected.POST("/webrtc/session", handleWebRTCSession)
|
||||
protected.GET("/webrtc/signaling/client", handleLocalWebRTCSignal)
|
||||
protected.POST("/cloud/register", handleCloudRegister)
|
||||
protected.GET("/cloud/state", handleCloudState)
|
||||
|
@ -126,11 +144,59 @@ func setupRouter() *gin.Engine {
|
|||
// TODO: support multiple sessions?
|
||||
var currentSession *Session
|
||||
|
||||
func handleWebRTCSession(c *gin.Context) {
|
||||
var req WebRTCSessionRequest
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
session, err := newSession(SessionConfig{})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
sd, err := session.ExchangeOffer(req.Sd)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
if currentSession != nil {
|
||||
writeJSONRPCEvent("otherSessionConnected", nil, currentSession)
|
||||
peerConn := currentSession.peerConnection
|
||||
go func() {
|
||||
time.Sleep(1 * time.Second)
|
||||
_ = peerConn.Close()
|
||||
}()
|
||||
}
|
||||
currentSession = session
|
||||
c.JSON(http.StatusOK, gin.H{"sd": sd})
|
||||
}
|
||||
|
||||
var (
|
||||
pingMessage = []byte("ping")
|
||||
pongMessage = []byte("pong")
|
||||
)
|
||||
|
||||
func handleLocalWebRTCSignal(c *gin.Context) {
|
||||
cloudLogger.Infof("new websocket connection established")
|
||||
|
||||
// get the source from the request
|
||||
source := c.ClientIP()
|
||||
|
||||
// Create WebSocket options with InsecureSkipVerify to bypass origin check
|
||||
wsOptions := &websocket.AcceptOptions{
|
||||
InsecureSkipVerify: true, // Allow connections from any origin
|
||||
OnPingReceived: func(ctx context.Context, payload []byte) bool {
|
||||
websocketLogger.Infof("ping frame received: %v, source: %s, sourceType: local", payload, source)
|
||||
|
||||
metricConnectionTotalPingReceivedCount.WithLabelValues("local", source).Inc()
|
||||
metricConnectionLastPingReceivedTimestamp.WithLabelValues("local", source).SetToCurrentTime()
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
wsCon, err := websocket.Accept(c.Writer, c.Request, wsOptions)
|
||||
|
@ -139,9 +205,6 @@ func handleLocalWebRTCSignal(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
// get the source from the request
|
||||
source := c.ClientIP()
|
||||
|
||||
// Now use conn for websocket operations
|
||||
defer wsCon.Close(websocket.StatusNormalClosure, "")
|
||||
|
||||
|
@ -164,7 +227,6 @@ func handleWebRTCSignalWsMessages(wsCon *websocket.Conn, isCloudConnection bool,
|
|||
|
||||
// Add connection tracking to detect reconnections
|
||||
connectionID := uuid.New().String()
|
||||
cloudLogger.Infof("new websocket connection established with ID: %s", connectionID)
|
||||
|
||||
// connection type
|
||||
var sourceType string
|
||||
|
@ -176,29 +238,40 @@ func handleWebRTCSignalWsMessages(wsCon *websocket.Conn, isCloudConnection bool,
|
|||
|
||||
// probably we can use a better logging framework here
|
||||
logInfof := func(format string, args ...interface{}) {
|
||||
args = append(args, source, sourceType)
|
||||
websocketLogger.Infof(format+", source: %s, sourceType: %s", args...)
|
||||
args = append(args, source, sourceType, connectionID)
|
||||
websocketLogger.Infof(format+", source: %s, sourceType: %s, id: %s", args...)
|
||||
}
|
||||
logWarnf := func(format string, args ...interface{}) {
|
||||
args = append(args, source, sourceType)
|
||||
websocketLogger.Warnf(format+", source: %s, sourceType: %s", args...)
|
||||
args = append(args, source, sourceType, connectionID)
|
||||
websocketLogger.Warnf(format+", source: %s, sourceType: %s, id: %s", args...)
|
||||
}
|
||||
logTracef := func(format string, args ...interface{}) {
|
||||
args = append(args, source, sourceType)
|
||||
websocketLogger.Tracef(format+", source: %s, sourceType: %s", args...)
|
||||
args = append(args, source, sourceType, connectionID)
|
||||
websocketLogger.Tracef(format+", source: %s, sourceType: %s, id: %s", args...)
|
||||
}
|
||||
|
||||
logInfof("new websocket connection established")
|
||||
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(WebsocketPingInterval)
|
||||
|
||||
if ctxErr := runCtx.Err(); ctxErr != nil {
|
||||
if !errors.Is(ctxErr, context.Canceled) {
|
||||
logWarnf("websocket connection closed: %v", ctxErr)
|
||||
} else {
|
||||
logTracef("websocket connection closed as the context was canceled: %v")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// set the timer for the ping duration
|
||||
timer := prometheus.NewTimer(prometheus.ObserverFunc(func(v float64) {
|
||||
metricConnectionLastPingDuration.WithLabelValues(sourceType, source).Set(v)
|
||||
metricConnectionPingDuration.WithLabelValues(sourceType, source).Observe(v)
|
||||
}))
|
||||
|
||||
logInfof("pinging websocket")
|
||||
logTracef("sending ping frame")
|
||||
err := wsCon.Ping(runCtx)
|
||||
|
||||
if err != nil {
|
||||
|
@ -208,10 +281,12 @@ func handleWebRTCSignalWsMessages(wsCon *websocket.Conn, isCloudConnection bool,
|
|||
}
|
||||
|
||||
// dont use `defer` here because we want to observe the duration of the ping
|
||||
timer.ObserveDuration()
|
||||
duration := timer.ObserveDuration()
|
||||
|
||||
metricConnectionTotalPingCount.WithLabelValues(sourceType, source).Inc()
|
||||
metricConnectionTotalPingSentCount.WithLabelValues(sourceType, source).Inc()
|
||||
metricConnectionLastPingTimestamp.WithLabelValues(sourceType, source).SetToCurrentTime()
|
||||
|
||||
logTracef("received pong frame, duration: %v", duration)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -249,6 +324,20 @@ func handleWebRTCSignalWsMessages(wsCon *websocket.Conn, isCloudConnection bool,
|
|||
Data json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
if bytes.Equal(msg, pingMessage) {
|
||||
logInfof("ping message received: %s", string(msg))
|
||||
err = wsCon.Write(context.Background(), websocket.MessageText, pongMessage)
|
||||
if err != nil {
|
||||
logWarnf("unable to write pong message: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
metricConnectionTotalPingReceivedCount.WithLabelValues(sourceType, source).Inc()
|
||||
metricConnectionLastPingReceivedTimestamp.WithLabelValues(sourceType, source).SetToCurrentTime()
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
err = json.Unmarshal(msg, &message)
|
||||
if err != nil {
|
||||
logWarnf("unable to parse ws message: %v", err)
|
||||
|
@ -264,8 +353,9 @@ func handleWebRTCSignalWsMessages(wsCon *websocket.Conn, isCloudConnection bool,
|
|||
continue
|
||||
}
|
||||
|
||||
logInfof("new session request: %v", req.OidcGoogle)
|
||||
logTracef("session request info: %v", req)
|
||||
if req.OidcGoogle != "" {
|
||||
logInfof("new session request with OIDC Google: %v", req.OidcGoogle)
|
||||
}
|
||||
|
||||
metricConnectionSessionRequestCount.WithLabelValues(sourceType, source).Inc()
|
||||
metricConnectionLastSessionRequestTimestamp.WithLabelValues(sourceType, source).SetToCurrentTime()
|
||||
|
|
Loading…
Reference in New Issue