VideoStream/main.go

170 lines
3.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"VideoStream/dao"
"VideoStream/handler"
"VideoStream/proto"
"VideoStream/service"
"VideoStream/worker"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt"
"github.com/robfig/cron/v3"
"gocv.io/x/gocv"
"log"
"strconv"
"strings"
"sync"
)
func main() {
gin.SetMode(gin.ReleaseMode)
r := gin.Default()
//数据库初始
err0 := dao.Init()
defer dao.Close()
if err0 != nil {
panic("failed to connect database:" + err0.Error())
}
err0 = worker.InitRedis()
defer worker.CloseRedis()
if err0 != nil {
panic("failed to connect redis:" + err0.Error())
}
r.Use(handler.CrosHandler())
r.Use(JWTAuthMiddleware()) // 使用 JWT 认证中间件
handler.SetUpToolGroup(r) // Tool
err := worker.InitRedis()
if err != nil {
panic("failed to connect redis:" + err.Error())
}
//定时任务
c := cron.New(cron.WithSeconds())
// 添加每 10 秒执行一次的任务
_, err2 := c.AddFunc("@every 10s", myTask)
if err2 != nil {
log.Fatal("添加定时任务失败: ", err2)
}
c.Start()
err3 := r.Run(":" + proto.Config.SERVER_PORT)
if err3 != nil {
panic("failed to run server:" + err3.Error())
}
}
func init() {
//读取配置文件
//文件地址/home/videoplayer/vp.conf
configPath := "/home/videoplayer/vp_stream.conf"
//读取配置文件
err := proto.ReadConfig(configPath)
if err != nil {
panic("failed to read config file:" + err.Error())
}
for _, device := range proto.Config.DeviceInfo {
service.DeviceRWMap[device.ID] = sync.RWMutex{}
service.DeviceCurrentFrameMap[device.ID] = gocv.NewMat()
service.DeviceIsStop[device.ID] = true
}
}
func myTask() {
log.Println("每10秒执行一次")
ReadConfigAndSetSystem()
}
func ReadConfigAndSetSystem() {
configPath := "/home/videoplayer/vp_stream.conf"
//读取配置文件
err := proto.ReadConfig(configPath)
if err != nil {
panic("failed to read config file:" + err.Error())
}
//检测是否需要获取设备流,如果需要则开启
for _, device := range proto.Config.DeviceInfo {
if service.DeviceIsStop[device.ID] == false {
go service.GetVideoStream(device.ID)
}
}
}
func JWTAuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 从请求头中获取 JWT 令牌
tokenString := c.Request.Header.Get("token")
//请求方式为get时从url中获取token
if tokenString == "" {
tokenString = c.Query("token")
}
//如果请求为login或register则不需要验证token
for k, _ := range proto.Url_map {
if strings.Contains(c.Request.URL.Path, k) {
c.Next()
return
}
}
if tokenString == "" {
//c.AbortWithStatus(200)
c.JSON(200, gin.H{
"message": "Unauthorized",
"error": "token is empty",
"code": 3,
})
return
}
if proto.Config.TOKEN_USE_REDIS {
redisToken := worker.GetRedis(tokenString)
if redisToken == "" {
c.AbortWithStatus(200)
c.JSON(200, gin.H{
"message": "NOT_LOGIN",
"error": "server token is empty",
"code": 3,
})
return
}
}
//查看token是否在超级token中
if worker.IsContainSet("super_permission_tokens", tokenString) {
s_id := c.Request.Header.Get("super_id")
if s_id == "" {
c.AbortWithStatus(200)
c.JSON(200, gin.H{
"message": "NOT_LOGIN",
"error": "super_id is empty",
"code": 3,
})
return
}
id, _ := strconv.Atoi(s_id)
//查看s_id类型
c.Set("id", id)
c.Next()
return
}
// 使用加密secret 解析 JWT 令牌
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return proto.SigningKey, nil
})
// 验证令牌
if err != nil || !token.Valid {
c.AbortWithStatus(200)
c.JSON(200, gin.H{
"message": "NOT_LOGIN",
"error": "Invalid token",
"code": 4,
})
return
}
userId := int(token.Claims.(jwt.MapClaims)["id"].(float64))
// 将用户信息添加到上下文中
c.Set("id", userId)
// 继续处理请求
c.Next()
}
}