Files
yovision/Sense/server/app/sense/adapters/rtsp/verifier.go
T

75 lines
2.1 KiB
Go

package rtsp
import (
"bufio"
"context"
"encoding/base64"
"fmt"
"net"
"net/url"
"strings"
"time"
)
type Credential struct {
Username string
Password string
}
type Result struct {
Status string `json:"status"`
LatencyMS int64 `json:"latency_ms"`
Detail string `json:"detail,omitempty"`
}
type Verifier interface {
Verify(context.Context, string, Credential) (Result, error)
}
type NetVerifier struct{ Timeout time.Duration }
func (v NetVerifier) Verify(ctx context.Context, raw string, credential Credential) (Result, error) {
parsed, err := url.Parse(raw)
if err != nil || parsed.Scheme != "rtsp" || parsed.Host == "" {
return Result{}, fmt.Errorf("invalid_rtsp_uri")
}
if parsed.User != nil {
return Result{}, fmt.Errorf("rtsp_uri_contains_credentials")
}
address := parsed.Host
if !strings.Contains(address, ":") {
address += ":554"
}
timeout := v.Timeout
if timeout <= 0 {
timeout = 5 * time.Second
}
dialer := net.Dialer{Timeout: timeout}
started := time.Now()
connection, err := dialer.DialContext(ctx, "tcp", address)
if err != nil {
return Result{Status: "unreachable", Detail: "无法连接视频端口"}, nil
}
defer connection.Close()
_ = connection.SetDeadline(time.Now().Add(timeout))
authorization := ""
if credential.Username != "" {
authorization = "Authorization: Basic " + base64.StdEncoding.EncodeToString([]byte(credential.Username+":"+credential.Password)) + "\r\n"
}
request := fmt.Sprintf("OPTIONS %s RTSP/1.0\r\nCSeq: 1\r\nUser-Agent: YoVision-Sense\r\n%s\r\n", parsed.String(), authorization)
if _, err := connection.Write([]byte(request)); err != nil {
return Result{}, err
}
line, err := bufio.NewReader(connection).ReadString('\n')
if err != nil {
return Result{Status: "timeout", Detail: "等待视频响应超时"}, nil
}
status := "ready"
detail := "码流可访问"
if strings.Contains(line, " 401 ") {
status = "authentication_failed"
detail = "设备拒绝了当前凭据"
} else if !strings.Contains(line, " 200 ") {
status = "failed"
detail = "设备返回非成功状态"
}
return Result{Status: status, LatencyMS: time.Since(started).Milliseconds(), Detail: detail}, nil
}