mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-17 06:23:00 +00:00
feat: update WebRTC handlers to support dynamic SFU host configuration and add monitoring script
This commit is contained in:
parent
3597c61cfc
commit
bcfdabb32d
158
example.http
158
example.http
@ -1,158 +0,0 @@
|
|||||||
### Orama Network Gateway API Examples
|
|
||||||
# This file is designed for the VS Code "REST Client" extension.
|
|
||||||
# It demonstrates the core capabilities of the DeBros Network Gateway.
|
|
||||||
|
|
||||||
@baseUrl = http://localhost:6001
|
|
||||||
@apiKey = ak_X32jj2fiin8zzv0hmBKTC5b5:default
|
|
||||||
@contentType = application/json
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
### 1. SYSTEM & HEALTH
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# @name HealthCheck
|
|
||||||
GET {{baseUrl}}/v1/health
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# @name SystemStatus
|
|
||||||
# Returns the full status of the gateway and connected services
|
|
||||||
GET {{baseUrl}}/v1/status
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# @name NetworkStatus
|
|
||||||
# Returns the P2P network status and PeerID
|
|
||||||
GET {{baseUrl}}/v1/network/status
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
### 2. DISTRIBUTED CACHE (OLRIC)
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# @name CachePut
|
|
||||||
# Stores a value in the distributed cache (DMap)
|
|
||||||
POST {{baseUrl}}/v1/cache/put
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
Content-Type: {{contentType}}
|
|
||||||
|
|
||||||
{
|
|
||||||
"dmap": "demo-cache",
|
|
||||||
"key": "video-demo",
|
|
||||||
"value": "Hello from REST Client!"
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# @name CacheGet
|
|
||||||
# Retrieves a value from the distributed cache
|
|
||||||
POST {{baseUrl}}/v1/cache/get
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
Content-Type: {{contentType}}
|
|
||||||
|
|
||||||
{
|
|
||||||
"dmap": "demo-cache",
|
|
||||||
"key": "video-demo"
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# @name CacheScan
|
|
||||||
# Scans for keys in a specific DMap
|
|
||||||
POST {{baseUrl}}/v1/cache/scan
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
Content-Type: {{contentType}}
|
|
||||||
|
|
||||||
{
|
|
||||||
"dmap": "demo-cache"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
### 3. DECENTRALIZED STORAGE (IPFS)
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# @name StorageUpload
|
|
||||||
# Uploads a file to IPFS (Multipart)
|
|
||||||
POST {{baseUrl}}/v1/storage/upload
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
Content-Type: multipart/form-data; boundary=boundary
|
|
||||||
|
|
||||||
--boundary
|
|
||||||
Content-Disposition: form-data; name="file"; filename="demo.txt"
|
|
||||||
Content-Type: text/plain
|
|
||||||
|
|
||||||
This is a demonstration of decentralized storage on the Sonr Network.
|
|
||||||
--boundary--
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# @name StorageStatus
|
|
||||||
# Check the pinning status and replication of a CID
|
|
||||||
# Replace {cid} with the CID returned from the upload above
|
|
||||||
@demoCid = bafkreid76y6x6v2n5o4n6n5o4n6n5o4n6n5o4n6n5o4
|
|
||||||
GET {{baseUrl}}/v1/storage/status/{{demoCid}}
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# @name StorageDownload
|
|
||||||
# Retrieve content directly from IPFS via the gateway
|
|
||||||
GET {{baseUrl}}/v1/storage/get/{{demoCid}}
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
### 4. REAL-TIME PUB/SUB
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# @name ListTopics
|
|
||||||
# Lists all active topics in the current namespace
|
|
||||||
GET {{baseUrl}}/v1/pubsub/topics
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# @name PublishMessage
|
|
||||||
# Publishes a base64 encoded message to a topic
|
|
||||||
POST {{baseUrl}}/v1/pubsub/publish
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
Content-Type: {{contentType}}
|
|
||||||
|
|
||||||
{
|
|
||||||
"topic": "network-updates",
|
|
||||||
"data_base64": "U29uciBOZXR3b3JrIGlzIGF3ZXNvbWUh"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
### 5. SERVERLESS FUNCTIONS
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# @name ListFunctions
|
|
||||||
# Lists all deployed serverless functions
|
|
||||||
GET {{baseUrl}}/v1/functions
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# @name InvokeFunction
|
|
||||||
# Invokes a deployed function by name
|
|
||||||
# Path: /v1/invoke/{namespace}/{functionName}
|
|
||||||
POST {{baseUrl}}/v1/invoke/default/hello
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
Content-Type: {{contentType}}
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "Developer"
|
|
||||||
}
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# @name WhoAmI
|
|
||||||
# Validates the API Key and returns caller identity
|
|
||||||
GET {{baseUrl}}/v1/auth/whoami
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
@ -340,6 +340,7 @@ func New(logger *logging.ColoredLogger, cfg *Config) (*Gateway, error) {
|
|||||||
if cfg.WebRTCEnabled && cfg.SFUPort > 0 {
|
if cfg.WebRTCEnabled && cfg.SFUPort > 0 {
|
||||||
gw.webrtcHandlers = webrtchandlers.NewWebRTCHandlers(
|
gw.webrtcHandlers = webrtchandlers.NewWebRTCHandlers(
|
||||||
logger,
|
logger,
|
||||||
|
gw.localWireGuardIP,
|
||||||
cfg.SFUPort,
|
cfg.SFUPort,
|
||||||
cfg.TURNDomain,
|
cfg.TURNDomain,
|
||||||
cfg.TURNSecret,
|
cfg.TURNSecret,
|
||||||
|
|||||||
@ -15,6 +15,7 @@ func testHandlers() *WebRTCHandlers {
|
|||||||
logger, _ := logging.NewColoredLogger(logging.ComponentGeneral, false)
|
logger, _ := logging.NewColoredLogger(logging.ComponentGeneral, false)
|
||||||
return NewWebRTCHandlers(
|
return NewWebRTCHandlers(
|
||||||
logger,
|
logger,
|
||||||
|
"", // defaults to 127.0.0.1 in tests
|
||||||
8443,
|
8443,
|
||||||
"turn.ns-test.dbrs.space",
|
"turn.ns-test.dbrs.space",
|
||||||
"test-secret-key-32bytes-long!!!!",
|
"test-secret-key-32bytes-long!!!!",
|
||||||
@ -91,7 +92,7 @@ func TestCredentialsHandler_NoNamespace(t *testing.T) {
|
|||||||
|
|
||||||
func TestCredentialsHandler_NoTURNSecret(t *testing.T) {
|
func TestCredentialsHandler_NoTURNSecret(t *testing.T) {
|
||||||
logger, _ := logging.NewColoredLogger(logging.ComponentGeneral, false)
|
logger, _ := logging.NewColoredLogger(logging.ComponentGeneral, false)
|
||||||
h := NewWebRTCHandlers(logger, 8443, "turn.test.dbrs.space", "", nil)
|
h := NewWebRTCHandlers(logger, "", 8443, "turn.test.dbrs.space", "", nil)
|
||||||
|
|
||||||
req := requestWithNamespace("POST", "/v1/webrtc/turn/credentials", "test-ns")
|
req := requestWithNamespace("POST", "/v1/webrtc/turn/credentials", "test-ns")
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
@ -119,7 +120,7 @@ func TestSignalHandler_NoNamespace(t *testing.T) {
|
|||||||
|
|
||||||
func TestSignalHandler_NoSFUPort(t *testing.T) {
|
func TestSignalHandler_NoSFUPort(t *testing.T) {
|
||||||
logger, _ := logging.NewColoredLogger(logging.ComponentGeneral, false)
|
logger, _ := logging.NewColoredLogger(logging.ComponentGeneral, false)
|
||||||
h := NewWebRTCHandlers(logger, 0, "", "secret", nil)
|
h := NewWebRTCHandlers(logger, "", 0, "", "secret", nil)
|
||||||
|
|
||||||
req := requestWithNamespace("GET", "/v1/webrtc/signal", "test-ns")
|
req := requestWithNamespace("GET", "/v1/webrtc/signal", "test-ns")
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
@ -171,7 +172,7 @@ func TestRoomsHandler_NoNamespace(t *testing.T) {
|
|||||||
|
|
||||||
func TestRoomsHandler_NoSFUPort(t *testing.T) {
|
func TestRoomsHandler_NoSFUPort(t *testing.T) {
|
||||||
logger, _ := logging.NewColoredLogger(logging.ComponentGeneral, false)
|
logger, _ := logging.NewColoredLogger(logging.ComponentGeneral, false)
|
||||||
h := NewWebRTCHandlers(logger, 0, "", "secret", nil)
|
h := NewWebRTCHandlers(logger, "", 0, "", "secret", nil)
|
||||||
|
|
||||||
req := requestWithNamespace("GET", "/v1/webrtc/rooms", "test-ns")
|
req := requestWithNamespace("GET", "/v1/webrtc/rooms", "test-ns")
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
@ -206,7 +207,7 @@ func TestRoomsHandler_SFUProxySuccess(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h := NewWebRTCHandlers(logger, port, "", "secret", nil)
|
h := NewWebRTCHandlers(logger, "", port, "", "secret", nil)
|
||||||
req := requestWithNamespace("GET", "/v1/webrtc/rooms", "test-ns")
|
req := requestWithNamespace("GET", "/v1/webrtc/rooms", "test-ns")
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ func (h *WebRTCHandlers) RoomsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Proxy to SFU health endpoint which returns room count
|
// Proxy to SFU health endpoint which returns room count
|
||||||
targetURL := fmt.Sprintf("http://127.0.0.1:%d/health", h.sfuPort)
|
targetURL := fmt.Sprintf("http://%s:%d/health", h.sfuHost, h.sfuPort)
|
||||||
|
|
||||||
client := &http.Client{Timeout: 5 * time.Second}
|
client := &http.Client{Timeout: 5 * time.Second}
|
||||||
resp, err := client.Get(targetURL)
|
resp, err := client.Get(targetURL)
|
||||||
|
|||||||
@ -23,8 +23,7 @@ func (h *WebRTCHandlers) SignalHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Proxy WebSocket to local SFU on WireGuard IP
|
// Proxy WebSocket to local SFU on WireGuard IP
|
||||||
// SFU binds to WireGuard IP, so we use 127.0.0.1 since we're on the same node
|
targetHost := fmt.Sprintf("%s:%d", h.sfuHost, h.sfuPort)
|
||||||
targetHost := fmt.Sprintf("127.0.0.1:%d", h.sfuPort)
|
|
||||||
|
|
||||||
h.logger.ComponentDebug(logging.ComponentGeneral, "Proxying WebRTC signal to SFU",
|
h.logger.ComponentDebug(logging.ComponentGeneral, "Proxying WebRTC signal to SFU",
|
||||||
zap.String("namespace", ns),
|
zap.String("namespace", ns),
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import (
|
|||||||
// These run on the namespace gateway and proxy signaling to the local SFU.
|
// These run on the namespace gateway and proxy signaling to the local SFU.
|
||||||
type WebRTCHandlers struct {
|
type WebRTCHandlers struct {
|
||||||
logger *logging.ColoredLogger
|
logger *logging.ColoredLogger
|
||||||
|
sfuHost string // SFU host IP (WireGuard IP) to proxy connections to
|
||||||
sfuPort int // Local SFU signaling port to proxy WebSocket connections to
|
sfuPort int // Local SFU signaling port to proxy WebSocket connections to
|
||||||
turnDomain string // TURN server domain for building URIs
|
turnDomain string // TURN server domain for building URIs
|
||||||
turnSecret string // HMAC-SHA1 shared secret for TURN credential generation
|
turnSecret string // HMAC-SHA1 shared secret for TURN credential generation
|
||||||
@ -23,13 +24,18 @@ type WebRTCHandlers struct {
|
|||||||
// NewWebRTCHandlers creates a new WebRTCHandlers instance.
|
// NewWebRTCHandlers creates a new WebRTCHandlers instance.
|
||||||
func NewWebRTCHandlers(
|
func NewWebRTCHandlers(
|
||||||
logger *logging.ColoredLogger,
|
logger *logging.ColoredLogger,
|
||||||
|
sfuHost string,
|
||||||
sfuPort int,
|
sfuPort int,
|
||||||
turnDomain string,
|
turnDomain string,
|
||||||
turnSecret string,
|
turnSecret string,
|
||||||
proxyWS func(w http.ResponseWriter, r *http.Request, targetHost string) bool,
|
proxyWS func(w http.ResponseWriter, r *http.Request, targetHost string) bool,
|
||||||
) *WebRTCHandlers {
|
) *WebRTCHandlers {
|
||||||
|
if sfuHost == "" {
|
||||||
|
sfuHost = "127.0.0.1"
|
||||||
|
}
|
||||||
return &WebRTCHandlers{
|
return &WebRTCHandlers{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
sfuHost: sfuHost,
|
||||||
sfuPort: sfuPort,
|
sfuPort: sfuPort,
|
||||||
turnDomain: turnDomain,
|
turnDomain: turnDomain,
|
||||||
turnSecret: turnSecret,
|
turnSecret: turnSecret,
|
||||||
|
|||||||
36
scripts/monitor-webrtc.sh
Executable file
36
scripts/monitor-webrtc.sh
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Monitor WebRTC endpoints every 10 seconds
|
||||||
|
# Usage: ./scripts/monitor-webrtc.sh
|
||||||
|
|
||||||
|
API_KEY="ak_SiODBDJFHrfE3HxjOtSe4CYm:anchat-test"
|
||||||
|
BASE="https://ns-anchat-test.orama-devnet.network"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
TS=$(date '+%H:%M:%S')
|
||||||
|
|
||||||
|
# 1. Health check
|
||||||
|
HEALTH=$(curl -sk -o /dev/null -w "%{http_code}" "${BASE}/v1/health")
|
||||||
|
|
||||||
|
# 2. TURN credentials
|
||||||
|
CREDS=$(curl -sk -o /dev/null -w "%{http_code}" -X POST -H "X-API-Key: ${API_KEY}" "${BASE}/v1/webrtc/turn/credentials")
|
||||||
|
|
||||||
|
# 3. WebSocket signal (connect, send join, read response, disconnect)
|
||||||
|
WS_OUT=$(echo '{"type":"join","data":{"roomId":"monitor-room","userId":"monitor"}}' \
|
||||||
|
| timeout 5 websocat -k --no-close -t "wss://ns-anchat-test.orama-devnet.network/v1/webrtc/signal?token=${API_KEY}" 2>&1 \
|
||||||
|
| head -1)
|
||||||
|
|
||||||
|
if echo "$WS_OUT" | grep -q '"welcome"'; then
|
||||||
|
SIGNAL="OK"
|
||||||
|
else
|
||||||
|
SIGNAL="FAIL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Print status
|
||||||
|
if [ "$HEALTH" = "200" ] && [ "$CREDS" = "200" ] && [ "$SIGNAL" = "OK" ]; then
|
||||||
|
echo "$TS health=$HEALTH creds=$CREDS signal=$SIGNAL ✓"
|
||||||
|
else
|
||||||
|
echo "$TS health=$HEALTH creds=$CREDS signal=$SIGNAL ✗ PROBLEM"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
Loading…
x
Reference in New Issue
Block a user