Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["server.go"],
importpath = "go-common/app/service/video/stream-mng/server/grpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/video/stream-mng/api/v1:go_default_library",
"//app/service/video/stream-mng/common:go_default_library",
"//app/service/video/stream-mng/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/net/rpc/warden:go_default_library",
"@org_golang_google_grpc//:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,667 @@
// Package server generate by warden_gen
package grpc
import (
"context"
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"go-common/app/service/video/stream-mng/api/v1"
"go-common/app/service/video/stream-mng/common"
"go-common/app/service/video/stream-mng/service"
"go-common/library/ecode"
"go-common/library/log"
nmd "go-common/library/net/metadata"
"go-common/library/net/rpc/warden"
"google.golang.org/grpc"
"math/rand"
"strconv"
"strings"
"time"
)
// New Stream warden rpc server
func New(c *warden.ServerConfig, svr *service.Service) *warden.Server {
//ws := warden.NewServer(c, grpc.MaxRecvMsgSize(32*1024*1024), grpc.MaxSendMsgSize(32*1024*1024)) 这里需要考虑配置问题
ws := warden.NewServer(c)
ws.Use(middleware())
v1.RegisterStreamServer(ws.Server(), &server{svr})
ws, err := ws.Start()
if err != nil {
panic(err)
}
return ws
}
type server struct {
svr *service.Service
}
var _ v1.StreamServer = &server{}
// GetSingleScreeShotByRoomID
func (s *server) GetSingleScreeShot(ctx context.Context, req *v1.GetSingleScreeShotReq) (*v1.GetSingleScreeShotReply, error) {
roomID := req.RoomId
start := req.StartTime
end := req.EndTime
channel := req.Channel
resp := &v1.GetSingleScreeShotReply{}
if roomID <= 0 || start == "" || end == "" {
st, _ := ecode.Error(ecode.RequestErr, "some fields are empty").WithDetails(resp)
return nil, st
}
startTime, err := time.ParseInLocation("2006-01-02 15:04:05", start, time.Local)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, "Start time format is incorrect").WithDetails(resp)
return nil, st
}
endTime, err := time.ParseInLocation("2006-01-02 15:04:05", end, time.Local)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, "End time format is incorrect").WithDetails(resp)
return nil, st
}
info, err := s.svr.GetSingleScreeShot(ctx, roomID, startTime.Unix(), endTime.Unix(), channel)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
return &v1.GetSingleScreeShotReply{
List: info,
}, nil
}
// GetMultiScreenShotByRommID
func (s *server) GetMultiScreenShot(ctx context.Context, req *v1.GetMultiScreenShotReq) (*v1.GetMultiScreenShotReply, error) {
rooms := req.RoomIds
ts := req.Ts
channel := req.Channel
resp := &v1.GetMultiScreenShotReply{}
if rooms == "" || ts == 0 {
st, _ := ecode.Error(ecode.RequestErr, "some fields are empty").WithDetails(resp)
return nil, st
}
// 切割room_id
roomIDs := strings.Split(rooms, ",")
if len(roomIDs) <= 0 {
st, _ := ecode.Error(ecode.RequestErr, "room_ids is not right").WithDetails(resp)
return nil, st
}
res := v1.GetMultiScreenShotReply{
List: map[int64]string{},
}
rids := []int64{}
for _, v := range roomIDs {
roomID, err := strconv.ParseInt(v, 10, 64)
if err != nil {
continue
}
rids = append(rids, roomID)
}
urls, err := s.svr.GetMultiScreenShot(ctx, rids, ts, channel)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
res.List = urls
return &res, nil
}
// GetOriginScreenShotPic
func (s *server) GetOriginScreenShotPic(ctx context.Context, req *v1.GetOriginScreenShotPicReq) (*v1.GetOriginScreenShotPicReply, error) {
rooms := req.RoomIds
ts := req.Ts
resp := &v1.GetOriginScreenShotPicReply{}
if rooms == "" || ts == 0 {
st, _ := ecode.Error(ecode.RequestErr, "some fields are empty").WithDetails(resp)
return nil, st
}
// 切割room_id
roomIDs := strings.Split(rooms, ",")
if len(roomIDs) <= 0 {
st, _ := ecode.Error(ecode.RequestErr, "room_ids is not right").WithDetails(resp)
return nil, st
}
res := v1.GetOriginScreenShotPicReply{
List: map[int64]string{},
}
rids := []int64{}
for _, v := range roomIDs {
roomID, err := strconv.ParseInt(v, 10, 64)
if err != nil {
continue
}
rids = append(rids, roomID)
}
urls, err := s.svr.GetOriginScreenShotPic(ctx, rids, ts)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
res.List = urls
return &res, nil
}
// CreateOfficeStream 创建正式流
func (s *server) CreateOfficalStream(ctx context.Context, req *v1.CreateOfficalStreamReq) (*v1.CreateOfficalStreamReply, error) {
key := req.Key
streamName := req.StreamName
if req.Uid != 0 {
key = mockStreamKey(fmt.Sprintf("%d", req.Uid))
streamName = mockStreamName(fmt.Sprintf("%d", req.Uid))
}
resp := &v1.CreateOfficalStreamReply{}
// 检查参数
if streamName == "" || key == "" || req.RoomId <= 0 {
st, _ := ecode.Error(ecode.RequestErr, "some fields are empty").WithDetails(resp)
return nil, st
}
flag := s.svr.CreateOfficalStream(ctx, streamName, key, req.RoomId)
return &v1.CreateOfficalStreamReply{
Success: flag,
}, nil
}
// GetStreamInfo 获取单个流信息
func (s *server) GetStreamInfo(ctx context.Context, req *v1.GetStreamInfoReq) (*v1.GetStreamInfoReply, error) {
rid := req.RoomId
sname := req.StreamName
resp := &v1.GetStreamInfoReply{}
if rid == 0 && sname == "" {
resp.Code = -400
resp.Message = "some fields are empty"
return resp, nil
}
info, err := s.svr.GetStreamInfo(ctx, int64(rid), sname)
if err != nil {
resp.Code = -400
resp.Message = err.Error()
return resp, nil
}
baseList := []*v1.StreamBase{}
for _, v := range info.List {
forward := []uint32{}
for _, f := range v.Forward {
forward = append(forward, uint32(f))
}
baseList = append(baseList, &v1.StreamBase{
StreamName: v.StreamName,
DefaultUpstream: uint32(v.DefaultUpStream),
Origin: uint32(v.Origin),
Forward: forward,
Type: uint32(v.Type),
Options: uint32(v.Options),
//Key: v.Key,
})
}
resp.Code = 0
resp.Data = &v1.StreamFullInfo{
RoomId: uint32(info.RoomID),
Hot: uint32(info.Hot),
List: baseList,
}
return resp, nil
}
// GetMultiStreamInfo 批量获取流信息
func (s *server) GetMultiStreamInfo(ctx context.Context, req *v1.GetMultiStreamInfoReq) (*v1.GetMultiStreamInfoReply, error) {
rids := req.RoomIds
resp := &v1.GetMultiStreamInfoReply{}
// 切割room_id
if len(rids) <= 0 {
resp.Code = 0
resp.Message = "success"
return resp, nil
}
if len(rids) > 30 {
resp.Code = -400
resp.Message = "The number of rooms must be less than 30"
return resp, nil
}
roomIDs := []int64{}
for _, v := range rids {
roomID := int64(v)
if roomID <= 0 {
continue
}
roomIDs = append(roomIDs, roomID)
}
info, err := s.svr.GetMultiStreamInfo(ctx, roomIDs)
if err != nil {
log.Infov(ctx, log.KV("log", err.Error()))
resp.Code = 0
resp.Message = "success"
return resp, nil
}
if info == nil || len(info) == 0 {
log.Infov(ctx, log.KV("log", "can find any things"))
resp.Code = 0
resp.Message = "success"
return resp, nil
}
res := map[uint32]*v1.StreamFullInfo{}
for id, v := range info {
item := &v1.StreamFullInfo{}
item.Hot = uint32(v.Hot)
item.RoomId = uint32(v.RoomID)
baseList := []*v1.StreamBase{}
for _, i := range v.List {
forward := []uint32{}
for _, f := range i.Forward {
forward = append(forward, uint32(f))
}
baseList = append(baseList, &v1.StreamBase{
StreamName: i.StreamName,
DefaultUpstream: uint32(i.DefaultUpStream),
Origin: uint32(i.Origin),
Forward: forward,
Type: uint32(i.Type),
Options: uint32(i.Options),
//Key: i.Key,
})
}
item.List = baseList
res[uint32(id)] = item
}
resp.Code = 0
resp.Data = res
return resp, nil
}
// ChangeSrc 切换cdn
func (s *server) ChangeSrc(ctx context.Context, req *v1.ChangeSrcReq) (*v1.EmptyStruct, error) {
resp := &v1.EmptyStruct{}
if req.RoomId <= 0 || req.Src == 0 || req.Source == "" || req.OperateName == "" {
st, _ := ecode.Error(ecode.RequestErr, "some fields are empty").WithDetails(resp)
return nil, st
}
// todo 后续改为新的src
src := int8(req.Src)
if _, ok := common.SrcMapBitwise[src]; !ok {
st, _ := ecode.Error(ecode.RequestErr, "src is not right").WithDetails(resp)
return nil, st
}
err := s.svr.ChangeSrc(ctx, req.RoomId, common.SrcMapBitwise[src], req.Source, req.OperateName, req.Reason)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
return resp, nil
}
// GetStreamLastTime 得到流到最后推流时间;主流的推流时间up_rank = 1
func (s *server) GetStreamLastTime(ctx context.Context, req *v1.GetStreamLastTimeReq) (*v1.GetStreamLastTimeReply, error) {
rid := req.RoomId
resp := &v1.GetStreamLastTimeReply{}
if rid <= 0 {
st, _ := ecode.Error(ecode.RequestErr, "room_id is not right").WithDetails(resp)
return nil, st
}
t, err := s.svr.GetStreamLastTime(ctx, rid)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
return &v1.GetStreamLastTimeReply{
LastTime: t,
}, nil
}
// GetStreamNameByRoomID 需要考虑备用流 + 考虑短号
func (s *server) GetStreamNameByRoomID(ctx context.Context, req *v1.GetStreamNameByRoomIDReq) (*v1.GetStreamNameByRoomIDReply, error) {
rid := req.RoomId
resp := &v1.GetStreamNameByRoomIDReply{}
if rid <= 0 {
st, _ := ecode.Error(ecode.RequestErr, "room_id is not right").WithDetails(resp)
return nil, st
}
res, err := s.svr.GetStreamNameByRoomID(ctx, rid, false)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
if len(res) == 0 {
st, _ := ecode.Error(ecode.RequestErr, fmt.Sprintf("can not find info by room_id=%d", rid)).WithDetails(resp)
return nil, st
}
return &v1.GetStreamNameByRoomIDReply{
StreamName: res[0],
}, nil
}
// GetRoomIDByStreamName 查询房间号
func (s *server) GetRoomIDByStreamName(ctx context.Context, req *v1.GetRoomIDByStreamNameReq) (*v1.GetRoomIDByStreamNameReply, error) {
resp := &v1.GetRoomIDByStreamNameReply{}
if req.StreamName == "" {
st, _ := ecode.Error(ecode.RequestErr, "stream name is empty").WithDetails(resp)
return nil, st
}
res, err := s.svr.GetRoomIDByStreamName(ctx, req.StreamName)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
if res <= 0 {
st, _ := ecode.Error(ecode.RequestErr, fmt.Sprintf("can not find any info by name = %s", req.StreamName)).WithDetails(resp)
return nil, st
}
return &v1.GetRoomIDByStreamNameReply{
RoomId: res,
}, nil
}
// GetAdapterStreamByStreamName 适配结果输出, 此处也可以输入备用流, 该结果只输出直推上行
func (s *server) GetAdapterStreamByStreamName(ctx context.Context, req *v1.GetAdapterStreamByStreamNameReq) (*v1.GetAdapterStreamByStreamNameReply, error) {
res := v1.GetAdapterStreamByStreamNameReply{
List: map[string]*v1.AdapterStream{},
}
snames := req.StreamNames
if snames == "" {
st, _ := ecode.Error(ecode.RequestErr, "stream_names is empty").WithDetails(&res)
return nil, st
}
nameSlice := strings.Split(snames, ",")
if len(nameSlice) == 0 {
st, _ := ecode.Error(ecode.RequestErr, "stream_names is empty").WithDetails(&res)
return nil, st
}
if len(nameSlice) > 500 {
st, _ := ecode.Error(ecode.RequestErr, "too many names").WithDetails(&res)
return nil, st
}
info := s.svr.GetAdapterStreamByStreamName(ctx, nameSlice)
if info != nil {
for name, v := range info {
res.List[name] = &v1.AdapterStream{
Src: v.Src,
RoomId: v.RoomID,
UpRank: v.UpRank,
SrcName: v.SrcName,
}
}
}
return &res, nil
}
// GetSrcByRoomID
func (s *server) GetSrcByRoomID(ctx context.Context, req *v1.GetSrcByRoomIDReq) (*v1.GetSrcByRoomIDReply, error) {
rid := req.RoomId
resp := &v1.GetSrcByRoomIDReply{}
if rid <= 0 {
st, _ := ecode.Error(ecode.RequestErr, "room_id is not right").WithDetails(resp)
return nil, st
}
info, err := s.svr.GetSrcByRoomID(ctx, rid)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
if info == nil || len(info) == 0 {
st, _ := ecode.Error(ecode.RequestErr, "获取线路失败").WithDetails(resp)
return nil, st
}
res := &v1.GetSrcByRoomIDReply{
List: []*v1.RoomSrcCheck{},
}
for _, v := range info {
res.List = append(res.List, &v1.RoomSrcCheck{
Src: v.Src,
Checked: int32(v.Checked),
Desc: v.Desc,
})
}
return res, nil
}
// GetLineListByRoomID
func (s *server) GetLineListByRoomID(ctx context.Context, req *v1.GetLineListByRoomIDReq) (*v1.GetLineListByRoomIDReply, error) {
resp := &v1.GetLineListByRoomIDReply{}
if req.RoomId <= 0 {
st, _ := ecode.Error(ecode.RequestErr, "room_id is not right").WithDetails(resp)
return nil, st
}
info, err := s.svr.GetLineListByRoomID(ctx, req.RoomId)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
if info == nil || len(info) == 0 {
st, _ := ecode.Error(ecode.RequestErr, "获取线路失败").WithDetails(resp)
return nil, st
}
res := &v1.GetLineListByRoomIDReply{
List: []*v1.LineList{},
}
for _, v := range info {
res.List = append(res.List, &v1.LineList{
Src: v.Src,
Use: v.Use,
Desc: v.Desc,
})
}
return res, nil
}
// GetUpStreamRtmp UpStream
func (s *server) GetUpStreamRtmp(ctx context.Context, req *v1.GetUpStreamRtmpReq) (*v1.GetUpStreamRtmpReply, error) {
resp := &v1.GetUpStreamRtmpReply{}
if req.RoomId == 0 || req.Platform == "" {
st, _ := ecode.Error(ecode.RequestErr, "some fields are empty").WithDetails(resp)
return nil, st
}
if req.Ip == "" {
if cmd, ok := nmd.FromContext(ctx); ok {
if ip, ok := cmd[nmd.RemoteIP].(string); ok {
req.Ip = ip
}
}
}
info, err := s.svr.GetUpStreamRtmp(ctx, req.RoomId, req.FreeFlow, req.Ip, req.AreaId, int(req.Attentions), 0, req.Platform)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
if info != nil {
resp.Up = &v1.UpStreamRtmp{
Addr: info.Addr,
Code: info.Code,
NewLink: info.NewLink,
}
}
return resp, nil
}
// StreamCut 切流的房间和时间, 内部调用
func (s *server) StreamCut(ctx context.Context, req *v1.StreamCutReq) (*v1.EmptyStruct, error) {
roomID := req.RoomId
cutTime := req.CutTime
resp := &v1.EmptyStruct{}
if roomID <= 0 {
st, _ := ecode.Error(ecode.RequestErr, "room_ids is not right").WithDetails(resp)
return nil, st
}
if cutTime == 0 {
cutTime = 1
}
s.svr.StreamCut(ctx, roomID, cutTime, 0)
return &v1.EmptyStruct{}, nil
}
// Ping Service
func (s *server) Ping(ctx context.Context, req *v1.PingReq) (*v1.PingReply, error) {
return &v1.PingReply{}, nil
}
// Close Service
func (s *server) Close(ctx context.Context, req *v1.CloseReq) (*v1.CloseReply, error) {
return &v1.CloseReply{}, nil
}
// ClearStreamStatus
func (s *server) ClearStreamStatus(ctx context.Context, req *v1.ClearStreamStatusReq) (*v1.EmptyStruct, error) {
rid := req.RoomId
resp := &v1.EmptyStruct{}
if rid <= 0 {
st, _ := ecode.Error(ecode.RequestErr, "room_ids is not right").WithDetails(resp)
return nil, st
}
err := s.svr.ClearStreamStatus(ctx, rid)
if err != nil {
st, _ := ecode.Error(ecode.RequestErr, err.Error()).WithDetails(resp)
return nil, st
}
return &v1.EmptyStruct{}, nil
}
// CheckLiveStreamList
func (s *server) CheckLiveStreamList(ctx context.Context, req *v1.CheckLiveStreamReq) (*v1.CheckLiveStreamReply, error) {
resp := &v1.CheckLiveStreamReply{}
rids := req.RoomId
if len(rids) == 0 {
st, _ := ecode.Error(ecode.RequestErr, "room_ids is empty").WithDetails(resp)
return nil, st
}
res := s.svr.CheckLiveStreamList(ctx, rids)
resp.List = res
return resp, nil
}
// mockStream 模拟生成的流名
func mockStreamName(uid string) string {
num := rand.Int63n(88888888)
return fmt.Sprintf("live_%s_%d", uid, num+1111111)
}
// mockStreamKey 模拟生成的key
func mockStreamKey(uid string) string {
str := fmt.Sprintf("nvijqwopW1%s%d", uid, time.Now().Unix())
h := md5.New()
h.Write([]byte(str))
cipherStr := h.Sum(nil)
md5Str := hex.EncodeToString(cipherStr)
return md5Str
}
func middleware() grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
resp, err = handler(ctx, req)
out := ""
if err != nil {
out = err.Error()
} else {
jo, _ := json.Marshal(resp)
out = string(jo)
}
// 记录调用方法
log.Infov(ctx,
log.KV("path", info.FullMethod),
log.KV("caller", nmd.String(ctx, nmd.Caller)),
log.KV("input_params", fmt.Sprintf("%s", req)),
log.KV("output_data", out),
)
return
}
}

View File

@@ -0,0 +1,59 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"backup.go",
"change-log.go",
"change-src.go",
"check-live.go",
"clear-cache.go",
"clear-retweet.go",
"http.go",
"notify.go",
"official.go",
"screen-shot.go",
"stream.go",
"stream-cut.go",
"stream-info.go",
"stream-mask.go",
"stream-validate.go",
"upstream-rtmp.go",
"upstream-summary.go",
],
importpath = "go-common/app/service/video/stream-mng/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/video/stream-mng/common:go_default_library",
"//app/service/video/stream-mng/conf:go_default_library",
"//app/service/video/stream-mng/middleware:go_default_library",
"//app/service/video/stream-mng/model:go_default_library",
"//app/service/video/stream-mng/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/auth:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
"//library/net/metadata:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,74 @@
package http
import (
"encoding/json"
"go-common/app/service/video/stream-mng/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"io/ioutil"
"strconv"
)
// createBackupStream 创建备用流
func createBackupStream(c *bm.Context) {
var bs model.BackupStream
switch c.Request.Header.Get("Content-Type") {
case "application/x-www-form-urlencoded":
if len(c.Request.PostForm) == 0 {
c.Set("output_data", "empty params")
c.JSONMap(map[string]interface{}{"message": "empty params"}, ecode.RequestErr)
c.Abort()
return
}
bs.StreamName = c.Request.PostFormValue("stream_name")
bs.Key = c.Request.PostFormValue("key")
default_vendor := c.Request.PostFormValue("default_vendor")
vendor, _ := strconv.ParseInt(default_vendor, 10, 64)
bs.DefaultVendor = vendor
id := c.Request.PostFormValue("room_id")
rid, _ := strconv.ParseInt(id, 10, 64)
bs.RoomID = rid
//bs.ExpiresAt = c.Request.PostFormValue("expires_at")
default:
defer c.Request.Body.Close()
b, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err}, ecode.RequestErr)
c.Abort()
return
}
if len(b) == 0 {
c.Set("output_data", "参数不能为空")
c.JSONMap(map[string]interface{}{"message": "参数不能为空"}, ecode.RequestErr)
c.Abort()
return
}
err = json.Unmarshal(b, &bs)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": "请确认格式是否正常"}, ecode.RequestErr)
c.Abort()
return
}
if bs.RoomID <= 0 {
c.Set("output_data", "房间号不正确")
c.JSONMap(map[string]interface{}{"message": "房间号不正确"}, ecode.RequestErr)
c.Abort()
return
}
}
c.Set("input_params", bs)
_, err := srv.CreateBackupStream(c, &bs)
c.JSON(bs, err)
}

View File

@@ -0,0 +1,41 @@
package http
import (
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"strconv"
)
// getChangeLogByRoomID 查询cdn切换记录
func getChangeLogByRoomID(c *bm.Context) {
params := c.Request.URL.Query()
room := params.Get("room_id")
limit := params.Get("limit")
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "room_id is not right"}, ecode.RequestErr)
c.Abort()
return
}
// 默认查询1最近一条记录
limitInt, _ := strconv.ParseInt(limit, 10, 64)
if limitInt <= 0 {
limitInt = 1
}
infos, err := srv.GetChangeLogByRoomID(c, roomID, limitInt)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.JSONMap(map[string]interface{}{"data": infos}, nil)
}

View File

@@ -0,0 +1,100 @@
package http
import (
"encoding/json"
"fmt"
"go-common/app/service/video/stream-mng/common"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"io/ioutil"
"strconv"
)
// 单独文件切换cdn
// changeSrc 切换cdn
func changeSrc(c *bm.Context) {
// 这里传递的src是新的src
type changStruct struct {
RoomID int64 `json:"room_id,omitempty"`
ToOrigin int8 `json:"src,omitempty"`
Source string `json:"source,omitempty"`
OperateName string `json:"operate_name,omitempty"`
Reason string `json:"reason,omitempty"`
}
var cs changStruct
switch c.Request.Header.Get("Content-Type") {
case "application/x-www-form-urlencoded":
if len(c.Request.PostForm) == 0 {
c.Set("output_data", "参数为空")
c.JSONMap(map[string]interface{}{"message": "参数为空"}, ecode.RequestErr)
c.Abort()
return
}
toOrigin := c.Request.PostFormValue("src")
or, _ := strconv.ParseInt(toOrigin, 10, 64)
cs.ToOrigin = int8(or)
rid, _ := strconv.ParseInt(c.Request.PostFormValue("room_id"), 10, 64)
cs.RoomID = rid
cs.Source = c.Request.PostFormValue("source")
cs.OperateName = c.Request.PostFormValue("operate_name")
default:
// 验证传参数
defer c.Request.Body.Close()
b, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
c.JSONMap(map[string]interface{}{"message": err}, ecode.RequestErr)
c.Abort()
return
}
if len(b) == 0 {
c.JSONMap(map[string]interface{}{"message": "参数为空"}, ecode.RequestErr)
c.Abort()
return
}
err = json.Unmarshal(b, &cs)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
}
c.Set("input_params", cs)
// 校验:房间号+src+平台来源+操作人 都是必须的, 操作理由可以不填
if cs.RoomID <= 0 || cs.ToOrigin == 0 || cs.Source == "" || cs.OperateName == "" {
c.Set("output_data", "some fields are not right")
c.JSONMap(map[string]interface{}{"message": "部分参数为空"}, ecode.RequestErr)
c.Abort()
return
}
// todo 先使用老的src, 后续改为新的src
src := int8(cs.ToOrigin)
if _, ok := common.SrcMapBitwise[src]; !ok {
c.Set("output_data", "src is not right")
c.JSONMap(map[string]interface{}{"message": "src is not right"}, ecode.RequestErr)
c.Abort()
return
}
err := srv.ChangeSrc(c, cs.RoomID, common.SrcMapBitwise[src], cs.Source, cs.OperateName, cs.Reason)
if err == nil {
c.Set("output_data", fmt.Sprintf("room_id = %d, change src success", cs.RoomID))
c.JSONMap(map[string]interface{}{"message": "ok"}, nil)
c.Abort()
return
}
c.Set("output_data", fmt.Sprintf("room_id = %d, change src faild = %v", cs.RoomID, err))
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
}

View File

@@ -0,0 +1,44 @@
package http
import (
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"strconv"
"strings"
)
func checkLiveStreamList(c *bm.Context) {
params := c.Request.URL.Query()
rooms := params.Get("room_ids")
c.Set("input_params", params)
if rooms == "" {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
// 切割room_id
roomIDs := strings.Split(rooms, ",")
if len(roomIDs) <= 0 {
c.Set("output_data", "room_ids is not right")
c.JSONMap(map[string]interface{}{"message": "room_ids is not right"}, ecode.RequestErr)
c.Abort()
return
}
rids := []int64{}
for _, v := range roomIDs {
roomID, err := strconv.ParseInt(v, 10, 64)
if err != nil {
continue
}
rids = append(rids, roomID)
}
c.JSONMap(map[string]interface{}{"data": srv.CheckLiveStreamList(c, rids)}, nil)
}

View File

@@ -0,0 +1,32 @@
package http
import (
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"strconv"
)
// clearRoomCacheByRID删除room_id缓存的接口防止缓存问题出现的bug
func clearRoomCacheByRID(c *bm.Context) {
params := c.Request.URL.Query()
room := params.Get("room_id")
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "room_id is empty")
c.JSONMap(map[string]interface{}{"message": "room_id is empty"}, ecode.RequestErr)
c.Abort()
return
}
err = srv.ClearRoomCacheByRID(c, roomID)
if err != nil {
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.JSONMap(map[string]interface{}{"message": "ok"}, nil)
}

View File

@@ -0,0 +1,75 @@
package http
import (
"encoding/json"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"io/ioutil"
)
// clearStreamStatus 清理互推标志
func clearStreamStatus(c *bm.Context) {
type room struct {
RoomID json.Number `json:"room_id"`
}
vp := &room{}
switch c.Request.Header.Get("Content-Type") {
case "application/x-www-form-urlencoded":
if len(c.Request.PostForm) == 0 {
c.Set("output_data", "clearStreamStatus = empty post body")
c.JSONMap(map[string]interface{}{"message": "empty post body"}, ecode.RequestErr)
c.Abort()
return
}
vp.RoomID = json.Number(c.Request.PostFormValue("room_id"))
default:
defer c.Request.Body.Close()
b, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
if len(b) == 0 {
c.Set("output_data", "clearStreamStatus empty params")
c.JSONMap(map[string]interface{}{"message": "empty params"}, ecode.RequestErr)
c.Abort()
return
}
err = json.Unmarshal(b, &vp)
if err != nil {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "room_id is not right"}, ecode.RequestErr)
c.Abort()
return
}
}
roomID, err := vp.RoomID.Int64()
if roomID <= 0 || err != nil {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "room_id is not right"}, ecode.RequestErr)
c.Abort()
return
}
c.Set("input_params", map[string]int64{"room_id": roomID})
err = srv.ClearStreamStatus(c, roomID)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", "clear status success")
c.JSONMap(map[string]interface{}{"message": "ok"}, nil)
}

View File

@@ -0,0 +1,121 @@
package http
import (
"net/http"
"go-common/app/service/video/stream-mng/conf"
"go-common/app/service/video/stream-mng/middleware"
"go-common/app/service/video/stream-mng/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/auth"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
srv *service.Service
vfy *verify.Verify
authSvr *auth.Auth
)
// Init init
func Init(c *conf.Config, svc *service.Service) {
srv = svc
vfy = verify.New(c.Verify)
authSvr = auth.New(c.Auth)
engine := bm.DefaultServer(c.BM)
engine.Use(middleware.Logger())
route(engine)
if err := engine.Start(); err != nil {
log.Error("bm Start error(%v)", err)
panic(err)
}
}
func route(e *bm.Engine) {
e.Ping(ping)
e.Register(register)
g := e.Group("/video/stream-mng")
{
g.GET("/", alive)
g.POST("/stream/backup", createBackupStream)
g.POST("/stream/offical", createOfficalStream)
g.POST("/stream/validate", streamValidate)
g.GET("/stream/old/getbyroomid", getOldStreamInfoByRoomID)
g.GET("/stream/old/getbyname", getOldStreamInfoByStreamName)
g.GET("/notifymaskbyroomid", saveMaskByRoomID) //控制一个主流是否需要转蒙版直播流
g.GET("/notifymaskbystreamname", saveMaskByStreamName) //控制一个主流是否可提供蒙版给PLAYURL
g.POST("/addhotstream", addHotStream) //增加热流到redis
g.GET("/getstream", getStream)
g.GET("/getmultistreams", getMultiStreams)
g.GET("/stream/getRoomIdByStreamName", getRoomIDByStreamName)
g.GET("/stream/getStreamNameByRoomId", getStreamNameByRoomID)
g.POST("/stream/changeSrc", changeSrc)
g.GET("/stream/cut", cutStream)
g.GET("/stream/cutmobilestream", authSvr.User, cutStreamByMobile)
g.GET("/stream/getLastTime", getStreamLastTime)
g.GET("/stream/getAdapterStream", getAdapterStreamByStreamName)
g.GET("/stream/getSrcByRoomID", getSrcByRoomID)
g.GET("/stream/getLineListByRoomID", getLineListByRoomID)
g.GET("/shot/getSinglePic", getSingleScreenShot)
g.GET("/shot/getMultiPic", getMultiScreenShot)
g.GET("/shot/getOriginPic", getOriginScreenShotPic)
g.GET("/shot/getperiodpic", getTimePeriodScreenShot)
g.POST("/stream/clearstreamstatus", clearStreamStatus)
g.GET("/stream/getRoomRtmp", getRoomRtmp) // 拜年祭推流码
g.GET("/stream/getUpStreamRtmp", getUpStreamRtmp) // 后台调用,无需鉴权
g.GET("/stream/getmobilertmp", authSvr.User, getMobileRtmp) // 移动端调用
g.GET("/stream/getwebrtmp", authSvr.User, getWebRtmp) // 被web端和pc_link调用
g.GET("/stream/live", checkLiveStreamList)
// 删除room_id缓存的接口防止缓存问题出现的bug
g.GET("/stream/clearcache", clearRoomCacheByRID)
// 查询更改记录
g.GET("/change/getchangeLog", getChangeLogByRoomID)
// 查询统计上行调度信息
g.GET("/summary/upstream", getSummaryUpStreamRtmp)
g.GET("/summary/isp", getSummaryUpStreamISP)
g.GET("/summary/country", getSummaryUpStreamCountry)
g.GET("/summary/platform", getSummaryUpStreamPlatform)
g.GET("/summary/city", getSummaryUpStreamCity)
}
g2 := e.Group("/live_stream/v1/StreamThird")
{
g2.POST("/stream_validate", streamValidate)
g2.POST("/open_notify", openNotify)
g2.POST("/close_notify", closeNotify)
}
g7 := e.Group("/live_stream/v1/StreamList")
{
g7.GET("/get_stream_by_roomId", authSvr.User, getWebRtmp)
}
g8 := e.Group("/live_stream/v1/UpStreamExt")
{
g8.GET("/get_by_room", authSvr.User, getMobileRtmp)
g8.GET("/pause_by_room", authSvr.User, cutStreamByMobile)
}
}
func ping(c *bm.Context) {
if err := srv.Ping(c); err != nil {
log.Error("ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}
func register(c *bm.Context) {
c.JSON(map[string]interface{}{}, nil)
}
func alive(c *bm.Context) {
c.String(0, "Golang 大法好 !!!")
}

View File

@@ -0,0 +1,96 @@
package http
import (
"encoding/json"
"errors"
"fmt"
"go-common/app/service/video/stream-mng/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"io/ioutil"
)
func openNotify(c *bm.Context) {
p, err := parseNotifyBody(c)
if err != nil {
// log.Errorv(c, log.KV("log", fmt.Sprintf("open_notify_err = %v", err)))
c.JSONMap(map[string]interface{}{"msg": err.Error()}, ecode.RequestErr)
c.Set("output_data", err.Error())
return
}
err = srv.StreamingNotify(c, p, true)
if err != nil {
// log.Errorv(c, log.KV("log", fmt.Sprintf("open_notify_err = %v", err)))
c.JSONMap(map[string]interface{}{"msg": err.Error()}, ecode.RequestErr)
c.Set("output_data", err.Error())
// c.Abort()
return
}
c.Set("output_data", "success")
c.JSONMap(map[string]interface{}{"msg": "success"}, ecode.OK)
}
func closeNotify(c *bm.Context) {
p, err := parseNotifyBody(c)
if err != nil {
c.JSONMap(map[string]interface{}{"msg": err.Error()}, ecode.RequestErr)
c.Set("output_data", err.Error())
return
}
err = srv.StreamingNotify(c, p, false)
if err != nil {
c.JSONMap(map[string]interface{}{"msg": err.Error()}, ecode.RequestErr)
c.Set("output_data", err.Error())
return
}
c.Set("output_data", "success")
c.JSONMap(map[string]interface{}{"msg": "success"}, ecode.OK)
}
func parseNotifyBody(c *bm.Context) (*model.StreamingNotifyParam, error) {
// log.Info("%v %v", c.Request.Header.Get("Content-Type"), c.Request.Form)
switch c.Request.Header.Get("Content-Type") {
case "application/x-www-form-urlencoded":
// log.Info("%+v", c.Request.PostForm)
if len(c.Request.PostForm) == 0 {
return nil, errors.New("empty post body")
}
p := &model.StreamingNotifyParam{}
p.Key = c.Request.PostFormValue("key")
p.Sign = c.Request.PostFormValue("sign")
p.SRC = c.Request.PostFormValue("src")
p.StreamName = c.Request.PostFormValue("stream_name")
p.SUID = c.Request.PostFormValue("suid")
p.TS = json.Number(c.Request.PostFormValue("ts"))
p.Type = json.Number(c.Request.PostFormValue("type"))
// log.Info("%+v", p)
// log.Infov(c, log.KV("log", fmt.Sprintf("notify_input = %+v", p)))
c.Set("input_params", *p)
return p, nil
default:
defer c.Request.Body.Close()
b, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
return nil, err
}
if len(b) == 0 {
return nil, errors.New("empty body")
}
var snp model.StreamingNotifyParam
err = json.Unmarshal(b, &snp)
if err != nil {
log.Errorv(c, log.KV("log", fmt.Sprintf("notify_parse_body_error = %v", err)))
return &snp, errors.New("invalid json body")
}
// log.Infov(c, log.KV("log", fmt.Sprintf("notify_input = %+v", snp)))
c.Set("input_params", snp)
return &snp, nil
}
}

View File

@@ -0,0 +1,90 @@
package http
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"io/ioutil"
"math/rand"
"time"
)
// createOfficalStream 创建正式流
// optional string debug; 1表示线下测试
// required int uid; uid线下测试必传
func createOfficalStream(c *bm.Context) {
defer c.Request.Body.Close()
b, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
c.JSONMap(map[string]interface{}{"message": err}, ecode.RequestErr)
c.Abort()
return
}
if len(b) == 0 {
c.JSONMap(map[string]interface{}{"message": "empty params"}, ecode.RequestErr)
c.Abort()
return
}
type officialParams struct {
RoomID int64 `json:"room_id,omitempty"`
StreamName string `json:"stream_name,omitempty"`
Key string `json:"key,omitempty"`
Debug string `json:"debug,omitempty"`
Uid int `json:"uid,omitempty"`
}
var off officialParams
err = json.Unmarshal(b, &off)
if err != nil {
c.JSONMap(map[string]interface{}{"message": err}, ecode.RequestErr)
c.Abort()
return
}
streamName := off.StreamName
key := off.Key
uid := off.Uid
roomID := off.RoomID
// 线下测试, 1表示线下测试,uid线下测试必传
if uid != 0 {
id := fmt.Sprintf("%d", uid)
key = mockStreamKey(id)
streamName = mockStreamName(id)
}
// 检查参数
if streamName == "" || key == "" || roomID <= 0 {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
flag := srv.CreateOfficalStream(c, streamName, key, roomID)
c.Set("output_data", fmt.Sprintf("create stream success = %v, room_id = %d", flag, roomID))
c.JSONMap(map[string]interface{}{"data": map[string]bool{"succ": flag}}, nil)
}
// mockStream 模拟生成的流名
func mockStreamName(uid string) string {
num := rand.Int63n(88888888)
return fmt.Sprintf("live_%s_%d", uid, num+1111111)
}
// mockStreamKey 模拟生成的key
func mockStreamKey(uid string) string {
str := fmt.Sprintf("nvijqwopW1%s%d", uid, time.Now().Unix())
h := md5.New()
h.Write([]byte(str))
cipherStr := h.Sum(nil)
md5Str := hex.EncodeToString(cipherStr)
return md5Str
}

View File

@@ -0,0 +1,235 @@
package http
import (
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"strconv"
"strings"
"time"
)
// 截图相关业务
// getScreeShotByRoomID 得到一个房间某个时间段的截图
func getSingleScreenShot(c *bm.Context) {
params := c.Request.URL.Query()
room := params.Get("room_id")
// 2018-10-24 14:27:07
start := params.Get("start_time")
end := params.Get("end_time")
channel := params.Get("channel")
c.Set("input_params", params)
if room == "" || start == "" || end == "" {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "room_id is not right"}, ecode.RequestErr)
c.Abort()
return
}
startTime, err := time.ParseInLocation("2006-01-02 15:04:05", start, time.Local)
if err != nil {
c.Set("output_data", "Start time format is incorrect")
c.JSONMap(map[string]interface{}{"message": "Start time format is incorrect"}, ecode.RequestErr)
c.Abort()
return
}
endTime, err := time.ParseInLocation("2006-01-02 15:04:05", end, time.Local)
if err != nil {
c.Set("output_data", "End time format is incorrect")
c.JSONMap(map[string]interface{}{"message": "End time format is incorrect"}, ecode.RequestErr)
c.Abort()
return
}
info, err := srv.GetSingleScreeShot(c, roomID, startTime.Unix(), endTime.Unix(), channel)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": map[string][]string{"list": info}}, nil)
}
// getMultiScreenShot 得到多个房间一个时间点截图
func getMultiScreenShot(c *bm.Context) {
params := c.Request.URL.Query()
rooms := params.Get("room_ids")
ts := params.Get("ts")
channel := params.Get("channel")
c.Set("input_params", params)
if rooms == "" || ts == "" {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
// 切割room_id
roomIDs := strings.Split(rooms, ",")
if len(roomIDs) <= 0 {
c.Set("output_data", "room_ids is not right")
c.JSONMap(map[string]interface{}{"message": "room_ids is not right"}, ecode.RequestErr)
c.Abort()
return
}
tsInt, _ := strconv.ParseInt(ts, 10, 64)
rids := []int64{}
for _, v := range roomIDs {
roomID, err := strconv.ParseInt(v, 10, 64)
if err != nil {
log.Warn("room id is not right")
continue
}
rids = append(rids, roomID)
}
resp, err := srv.GetMultiScreenShot(c, rids, tsInt, channel)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", resp)
c.JSONMap(map[string]interface{}{"data": map[string]interface{}{"list": resp}}, nil)
}
// getOriginScreenShotPic 获取原始图片地址
func getOriginScreenShotPic(c *bm.Context) {
params := c.Request.URL.Query()
rooms := params.Get("room_ids")
ts := params.Get("ts")
//tp := params.Get("type")
c.Set("input_params", params)
if rooms == "" {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
// 切割room_id
roomIDs := strings.Split(rooms, ",")
if len(roomIDs) <= 0 {
c.Set("output_data", "room_ids is not right")
c.JSONMap(map[string]interface{}{"message": "room_ids is not right"}, ecode.RequestErr)
c.Abort()
return
}
tsInt, _ := strconv.ParseInt(ts, 10, 64)
rids := []int64{}
for _, v := range roomIDs {
roomID, err := strconv.ParseInt(v, 10, 64)
if err != nil {
log.Warn("room id is not right")
continue
}
rids = append(rids, roomID)
}
resp, err := srv.GetOriginScreenShotPic(c, rids, tsInt)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", resp)
c.JSONMap(map[string]interface{}{"data": map[string]interface{}{"list": resp}}, nil)
}
// getTimePeriodScreenShot 获取多个房间一个时间段内的截图
func getTimePeriodScreenShot(c *bm.Context) {
params := c.Request.URL.Query()
room := params.Get("room_ids")
// 2018-10-24 14:27:07
start := params.Get("start_time")
end := params.Get("end_time")
channel := params.Get("channel")
c.Set("input_params", params)
if room == "" || start == "" || end == "" {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
startTime, err := time.ParseInLocation("2006-01-02 15:04:05", start, time.Local)
if err != nil {
c.Set("output_data", "Start time format is incorrect")
c.JSONMap(map[string]interface{}{"message": "Start time format is incorrect"}, ecode.RequestErr)
c.Abort()
return
}
endTime, err := time.ParseInLocation("2006-01-02 15:04:05", end, time.Local)
if err != nil {
c.Set("output_data", "End time format is incorrect")
c.JSONMap(map[string]interface{}{"message": "End time format is incorrect"}, ecode.RequestErr)
c.Abort()
return
}
// 切割room_id
roomIDs := strings.Split(room, ",")
if len(roomIDs) <= 0 {
c.Set("output_data", "room_ids is not right")
c.JSONMap(map[string]interface{}{"message": "room_ids is not right"}, ecode.RequestErr)
c.Abort()
return
}
resp := map[int64][]string{}
for _, v := range roomIDs {
roomID, err := strconv.ParseInt(v, 10, 64)
if err != nil {
log.Warn("room id is not right")
continue
}
urls, err := srv.GetSingleScreeShot(c, roomID, startTime.Unix(), endTime.Unix(), channel)
if err != nil {
log.Warn("%v", err)
continue
}
resp[roomID] = urls
}
c.Set("output_data", resp)
c.JSONMap(map[string]interface{}{"data": resp}, nil)
}

View File

@@ -0,0 +1,86 @@
package http
import (
"fmt"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/metadata"
"strconv"
)
// cutStream 切流, 内部调用
func cutStream(c *bm.Context) {
// roomid 必须
params := c.Request.URL.Query()
room := params.Get("room_id")
cutTime := params.Get("cut_time")
c.Set("input_params", params)
// 验证传参数
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "roomid is not right")
c.JSONMap(map[string]interface{}{"message": "roomid is not right"}, ecode.RequestErr)
c.Abort()
return
}
// 默认切流时间为1s,可以传入-1
ct, err := strconv.ParseInt(cutTime, 10, 64)
if err != nil || ct == 0 {
ct = 1
}
srv.StreamCut(c, roomID, ct, 0)
c.Set("output_data", "ok")
c.JSONMap(map[string]interface{}{"data": map[string]int{}}, nil)
}
// cutStreamByExt 外部调用
func cutStreamByMobile(c *bm.Context) {
// roomid 必须
params := c.Request.URL.Query()
room := params.Get("room_id")
cutTime := params.Get("cut_time")
c.Set("input_params", params)
// 验证传参数
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "roomid is not right")
c.JSONMap(map[string]interface{}{"message": "roomid is not right"}, ecode.RequestErr)
c.Abort()
return
}
// 默认切流时间为1s,可以传入-1
ct, err := strconv.ParseInt(cutTime, 10, 64)
if err != nil || ct == 0 {
ct = 1
}
uid, ok := metadata.Value(c, metadata.Mid).(int64)
//uid = 19148701
//ok = true
if !ok {
c.Set("output_data", "未登陆")
c.JSONMap(map[string]interface{}{"message": fmt.Sprintf("未登陆")}, ecode.RequestErr)
c.Abort()
return
}
err = srv.StreamCut(c, roomID, ct, uid)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", "ok")
c.JSONMap(map[string]interface{}{"data": map[string]int{}}, nil)
}

View File

@@ -0,0 +1,196 @@
package http
import (
"encoding/json"
"fmt"
"go-common/app/service/video/stream-mng/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"io/ioutil"
"strconv"
"strings"
)
// addHotStream 增加房间热流标记
func addHotStream(c *bm.Context) {
req := c.Request
bs, err := ioutil.ReadAll(req.Body)
if err != nil {
c.Set("output_data", "ioutil.ReadAll() error")
c.JSONMap(map[string]interface{}{"message": "outil.ReadAll() error"}, err)
c.Abort()
return
}
req.Body.Close()
var hrbody []string
if err := json.Unmarshal(bs, &hrbody); err != nil {
c.Set("output_data", "json.Unmarshal() error")
c.JSONMap(map[string]interface{}{"message": "json.Unmarshal() error"}, err)
c.Abort()
return
}
if len(hrbody) <= 0 {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
for _, streamName := range hrbody {
srv.AddHotStreamInfo(c, streamName)
}
c.Set("output_data", "success")
c.JSONMap(map[string]interface{}{"data": "success"}, nil)
}
// getStream 获取单个流信息
func getStream(c *bm.Context) {
params := c.Request.URL.Query()
rid := params.Get("room_id")
sname := params.Get("stream_name")
if rid == "" && sname == "" {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
var roomID int64
var err error
var info *model.StreamFullInfo
if sname == "" {
roomID, err = strconv.ParseInt(rid, 10, 64)
// 验证传参数
if err != nil || roomID <= 0 {
c.Set("output_data", "roomid is not right")
c.JSONMap(map[string]interface{}{"message": "roomid is not right"}, ecode.RequestErr)
c.Abort()
return
}
info, err = srv.GetStreamInfo(c, roomID, "")
} else {
info, err = srv.GetStreamInfo(c, 0, sname)
}
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": info}, nil)
}
// getMulitiStreams 批量查询流接口
func getMultiStreams(c *bm.Context) {
params := c.Request.URL.Query()
roomID := params.Get("room_ids")
if roomID == "" {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
roomIDs := []int64{}
rids := strings.Split(roomID, ",")
for _, v := range rids {
rid, err := strconv.ParseInt(v, 10, 64)
// 验证传参数
if err == nil && rid > 0 {
roomIDs = append(roomIDs, rid)
}
}
if len(roomIDs) > 30 {
c.Set("output_data", "The number of rooms must be less than 30")
c.JSONMap(map[string]interface{}{"message": "The number of rooms must be less than 30"}, ecode.RequestErr)
c.Abort()
return
}
info, err := srv.GetMultiStreamInfo(c, roomIDs)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
if info == nil || len(info) == 0 {
c.Set("output_data", fmt.Sprintf("can not find any info by room_ids=%s", roomID))
c.JSONMap(map[string]interface{}{"message": fmt.Sprintf("can not find any info by room_ids=%s", roomID)}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": info}, nil)
}
// getOldStreamInfoByRoomID map 到原始src数据
func getOldStreamInfoByRoomID(c *bm.Context) {
params := c.Request.URL.Query()
room := params.Get("roomid")
room2 := params.Get("room_id")
rid := ""
if room == "" {
rid = room2
} else {
rid = room
}
roomID, err := strconv.ParseInt(rid, 10, 64)
// 验证传参数
if err != nil || roomID <= 0 {
c.Set("output_data", "roomid is not right")
c.JSONMap(map[string]interface{}{"message": "roomid is not right"}, ecode.RequestErr)
c.Abort()
return
}
info, err := srv.GetStreamInfoByRIDMapSrcFromDB(c, roomID)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": info}, nil)
}
// getOldStreamInfoByStreamName map到原始src数据
func getOldStreamInfoByStreamName(c *bm.Context) {
params := c.Request.URL.Query()
sname := params.Get("stream_name")
sname = strings.TrimSpace(sname)
if sname == "" {
c.JSONMap(map[string]interface{}{"message": "stream name is empty"}, ecode.RequestErr)
c.Abort()
return
}
info, err := srv.GetStreamInfoBySNameMapSrcFromDB(c, sname)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": info}, nil)
}

View File

@@ -0,0 +1,103 @@
package http
import (
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"strconv"
"strings"
)
// getStreamLastTime 得到流到最后推流时间
func saveMaskByRoomID(c *bm.Context) {
params := c.Request.URL.Query()
roomid := params.Get("room_id")
mask := params.Get("mask")
c.Set("input_data", params)
roomID, err := strconv.ParseInt(roomid, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "room_id is not right"}, ecode.RequestErr)
c.Abort()
return
}
int64mask, err := strconv.ParseInt(mask, 10, 64)
// 验证传参数
if err != nil || int64mask < 0 || int64mask > 1 {
c.Set("output_data", "mask is not right")
c.JSONMap(map[string]interface{}{"message": "mask is not right"}, ecode.RequestErr)
c.Abort()
return
}
//直接修改数据库,更新缓存
result, err := srv.ChangeMaskStreamByRoomID(c, roomID, "", int64mask)
if err != nil {
c.Set("output_data", err)
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", result)
c.JSONMap(map[string]interface{}{"data": result}, nil)
}
// getStreamLastTime 得到流到最后推流时间
func saveMaskByStreamName(c *bm.Context) {
params := c.Request.URL.Query()
sname := params.Get("stream_name")
mask := params.Get("mask")
c.Set("input_data", params)
if sname == "" {
c.Set("output_data", "stream_name is not right")
c.JSONMap(map[string]interface{}{"message": "stream_name is not right"}, ecode.RequestErr)
c.Abort()
return
}
int64mask, err := strconv.ParseInt(mask, 10, 64)
// 验证传参数
if err != nil || int64mask < 0 || int64mask > 1 {
c.Set("output_data", "mask is not right")
c.JSONMap(map[string]interface{}{"message": "mask is not right"}, ecode.RequestErr)
c.Abort()
return
}
var newmask int64
var newsname string
if len(sname) > 6 && strings.Contains(sname, "_wmask") {
//设置第三位为1
if int64mask == 0 {
newmask = 3
} else {
newmask = 2
}
newsname = sname[0 : len(sname)-6]
} else if len(sname) > 6 && strings.Contains(sname, "_mmask") {
//设置第四位为1
if int64mask == 0 {
newmask = 5
} else {
newmask = 4
}
newsname = sname[0 : len(sname)-6]
} else {
c.Set("output_data", "stream_name is not right")
c.JSONMap(map[string]interface{}{"message": "stream_name is not right"}, ecode.RequestErr)
c.Abort()
return
}
//直接修改数据库,更新缓存
result, err := srv.ChangeMaskStreamByRoomID(c, 0, newsname, newmask)
if err != nil {
c.Set("output_data", err)
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", result)
c.JSONMap(map[string]interface{}{"data": result}, nil)
}

View File

@@ -0,0 +1,69 @@
package http
import (
"encoding/json"
"go-common/app/service/video/stream-mng/service"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"io/ioutil"
)
// streamValidate 流鉴权接口
func streamValidate(c *bm.Context) {
var vp service.ValidateParams
switch c.Request.Header.Get("Content-Type") {
case "application/x-www-form-urlencoded":
if len(c.Request.PostForm) == 0 {
c.Set("output_data", "stream_valid_err = empty post body")
c.JSONMap(map[string]interface{}{"message": "empty post body"}, ecode.RequestErr)
c.Abort()
return
}
vp.Key = c.Request.PostFormValue("key")
vp.StreamName = c.Request.PostFormValue("stream_name")
vp.Src = c.Request.PostFormValue("src")
vp.Type = json.Number(c.Request.PostFormValue("type"))
default:
defer c.Request.Body.Close()
b, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
if len(b) == 0 {
c.Set("output_data", "stream_valid_err = empty params")
c.JSONMap(map[string]interface{}{"message": "empty params"}, ecode.RequestErr)
c.Abort()
return
}
err = json.Unmarshal(b, &vp)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
}
c.Set("input_params", vp)
permission, err := srv.CheckStreamValidate(c, &vp, false)
if err != nil {
c.Set("output_data", err.Error())
if err.Error() == "room is closed" {
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.LimitExceed)
} else {
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
}
c.Abort()
return
}
c.Set("output_data", permission)
c.JSONMap(map[string]interface{}{"data": map[string]int{"permission": permission}}, nil)
}

View File

@@ -0,0 +1,181 @@
package http
import (
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"strconv"
"strings"
)
// 简单的流信息的处理和返回
// getStreamLastTime 得到流到最后推流时间
func getStreamLastTime(c *bm.Context) {
// 获取url中的room_id
params := c.Request.URL.Query()
room := params.Get("room_id")
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "room_id is not right"}, ecode.RequestErr)
c.Abort()
return
}
t, err := srv.GetStreamLastTime(c, roomID)
if err != nil {
log.Warn("%v", err)
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.JSONMap(map[string]interface{}{"data": map[string]int64{"last_time": t}}, nil)
}
// getStreamNameByRoomID 根据房间号获取流名
func getStreamNameByRoomID(c *bm.Context) {
params := c.Request.URL.Query()
room := params.Get("room_id")
back := params.Get("back")
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "room_id is not right"}, ecode.RequestErr)
c.Abort()
return
}
flag := false
if back == "1" {
flag = true
}
info, err := srv.GetStreamNameByRoomID(c, roomID, flag)
if err != nil {
c.Set("output_data", err)
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
if !flag && len(info) > 0 {
c.JSONMap(map[string]interface{}{"data": info[0]}, nil)
return
}
c.JSONMap(map[string]interface{}{"data": info}, nil)
}
// getRoomIdByStreamName 得到房间号,传递流名,可传入备用流名
func getRoomIDByStreamName(c *bm.Context) {
params := c.Request.URL.Query()
sname := params.Get("stream_name")
sname = strings.TrimSpace(sname)
if len(sname) == 0 {
c.Set("output_data", "stream name is empty")
c.JSONMap(map[string]interface{}{"message": "stream name is empty"}, ecode.RequestErr)
c.Abort()
return
}
rid, err := srv.GetRoomIDByStreamName(c, sname)
if err != nil {
c.Set("output_data", err)
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.JSONMap(map[string]interface{}{"data": map[string]int64{"room_id": rid}}, nil)
}
// getAdapterStreamByStreamName 得到适配的流信息迁移PHP接口
func getAdapterStreamByStreamName(c *bm.Context) {
params := c.Request.URL.Query()
snames := params.Get("stream_names")
snames = strings.TrimSpace(snames)
if len(snames) == 0 {
c.Set("output_data", "stream names is empty")
c.JSONMap(map[string]interface{}{"message": "stream names is empty"}, ecode.RequestErr)
c.Abort()
return
}
// 最多查询500个数据
nameSlice := strings.Split(snames, ",")
if len(nameSlice) > 500 {
c.Set("output_data", "too many names")
c.JSONMap(map[string]interface{}{"message": "too many names"}, ecode.RequestErr)
c.Abort()
return
}
info := srv.GetAdapterStreamByStreamName(c, nameSlice)
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": info}, nil)
}
// getSrcByRoom 获取线路接口, 适配原PHP代码 线路名称+线路编码src+是否当前选择的线路
func getSrcByRoomID(c *bm.Context) {
params := c.Request.URL.Query()
room := params.Get("room_id")
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "room_id is not right"}, ecode.RequestErr)
c.Abort()
return
}
info, err := srv.GetSrcByRoomID(c, roomID)
if err != nil {
c.Set("output_data", err)
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": info}, nil)
}
// getLineListByRoomID 得下线路信息, 和getSrcByRoomID 只有返回的格式不一样
func getLineListByRoomID(c *bm.Context) {
params := c.Request.URL.Query()
room := params.Get("room_id")
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "room_id is not right"}, ecode.RequestErr)
c.Abort()
return
}
info, err := srv.GetLineListByRoomID(c, roomID)
if err != nil {
c.Set("output_data", err)
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": info}, nil)
}

View File

@@ -0,0 +1,279 @@
package http
import (
"fmt"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/metadata"
"net"
"strconv"
)
// 获取上行推流地址, 一共三个方法调用
// UpStream
func getUpStreamRtmp(c *bm.Context) {
params := c.Request.URL.Query()
room := params.Get("room_id")
// 来源pc表示PC端ios表示ios端android安卓端ios_link表示ios端android_link 安卓端live_mng表示live后台;vc_mng表示vc后台;
platform := params.Get("platform")
// client_ip
ip := params.Get("ip")
// 分区id
area := params.Get("area_id")
// 免流标志
freeFlow := params.Get("free_flow")
attentions := params.Get("attentions")
c.Set("input_params", params)
if room == "" || platform == "" || area == "" {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "房间号错误"}, ecode.RequestErr)
c.Abort()
return
}
var attentionsInt int
if attentions == "" {
attentionsInt = 0
} else {
att, _ := strconv.ParseInt(attentions, 10, 64)
attentionsInt = int(att)
}
// ip映射
realIP := ip
if ip == "" {
remoteAddr := c.Request.RemoteAddr
// 使用header: X-REAL-IP + X_FORWARED_FOR + reamoteadd
if add := c.Request.Header.Get("X-REAL-IP"); add != "" {
remoteAddr = add
} else if add = c.Request.Header.Get("X_FORWARED_FOR"); add != "" {
remoteAddr = add
} else {
remoteAddr, _, _ = net.SplitHostPort(remoteAddr)
}
if remoteAddr == "::1" {
remoteAddr = "127.0.0.1"
}
realIP = remoteAddr
}
areaID, _ := strconv.ParseInt(area, 10, 64)
info, err := srv.GetUpStreamRtmp(c, roomID, freeFlow, realIP, areaID, attentionsInt, 0, platform)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": "获取线路信息失败,刷新页面或稍后重试"}, ecode.RequestErr)
c.Abort()
return
}
if info == nil {
c.Set("output_data", fmt.Sprintf("can find any info by room_id=%d", roomID))
c.JSONMap(map[string]interface{}{"message": "获取线路信息失败,刷新页面或稍后重试"}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": map[string]interface{}{"up_stream": info}}, nil)
}
// getWebRtmp web端调用
func getWebRtmp(c *bm.Context) {
// 获取room_id
params := c.Request.URL.Query()
room := params.Get("room_id")
c.Set("input_params", params)
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "room_id is not right")
c.JSONMap(map[string]interface{}{"message": "房间号不正确"}, ecode.RequestErr)
c.Abort()
return
}
// 获取uid
uid, ok := metadata.Value(c, metadata.Mid).(int64)
//uid = 19148701
//ok = true
//log.Infov(c, log.KV("log", fmt.Sprintf("uid=%v", uid)))
if !ok {
log.Warn("%v=%v", uid, ok)
c.Set("output_data", "未登陆")
c.JSONMap(map[string]interface{}{"message": fmt.Sprintf("未登陆")}, ecode.RequestErr)
c.Abort()
return
}
remoteAddr := c.Request.RemoteAddr
// 使用header: X-REAL-IP + X_FORWARED_FOR + reamoteadd
if add := c.Request.Header.Get("X-REAL-IP"); add != "" {
remoteAddr = add
} else if add = c.Request.Header.Get("X_FORWARED_FOR"); add != "" {
remoteAddr = add
} else {
remoteAddr, _, _ = net.SplitHostPort(remoteAddr)
}
if remoteAddr == "::1" {
remoteAddr = "127.0.0.1"
}
realIP := remoteAddr
info, err := srv.GetWebRtmp(c, roomID, uid, realIP, "web")
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": "获取线路信息失败,刷新页面或稍后重试"}, ecode.RequestErr)
c.Abort()
return
}
if info == nil {
c.Set("output_data", fmt.Sprintf("can find any info by room_id=%d", roomID))
c.JSONMap(map[string]interface{}{"message": "获取线路信息失败,刷新页面或稍后重试"}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": info}, nil)
}
// getMobileRtmp 移动端调用
func getMobileRtmp(c *bm.Context) {
params := c.Request.URL.Query()
room := params.Get("room_id")
// 来源pc表示PC端ios表示ios端android安卓端ios_link表示ios端android_link 安卓端live_mng表示live后台;vc_mng表示vc后台;
platform := params.Get("platform")
// client_ip
ip := params.Get("ip")
// 分区id
area := params.Get("area_id")
// 免流标志
freeFlow := params.Get("free_flow")
c.Set("input_params", params)
if room == "" || platform == "" || area == "" {
c.Set("output_data", "some fields are empty")
c.JSONMap(map[string]interface{}{"message": "some fields are empty"}, ecode.RequestErr)
c.Abort()
return
}
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "房间号错误")
c.JSONMap(map[string]interface{}{"message": "房间号错误"}, ecode.RequestErr)
c.Abort()
return
}
// ip映射
realIP := ip
if ip == "" {
remoteAddr := c.Request.RemoteAddr
// 使用header: X-REAL-IP + X_FORWARED_FOR + reamoteadd
if add := c.Request.Header.Get("X-REAL-IP"); add != "" {
remoteAddr = add
} else if add = c.Request.Header.Get("X_FORWARED_FOR"); add != "" {
remoteAddr = add
} else {
remoteAddr, _, _ = net.SplitHostPort(remoteAddr)
}
if remoteAddr == "::1" {
remoteAddr = "127.0.0.1"
}
realIP = remoteAddr
}
areaID, _ := strconv.ParseInt(area, 10, 64)
// 获取uid
uid, ok := metadata.Value(c, metadata.Mid).(int64)
//uid = 19148701
//ok = true
if !ok {
c.Set("output_data", "未登陆")
c.JSONMap(map[string]interface{}{"message": fmt.Sprintf("未登陆")}, ecode.RequestErr)
c.Abort()
return
}
info, err := srv.GetUpStreamRtmp(c, roomID, freeFlow, realIP, areaID, 0, uid, platform)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": "获取线路信息失败,刷新页面或稍后重试"}, ecode.RequestErr)
c.Abort()
return
}
if info == nil {
c.Set("output_data", fmt.Sprintf("can find any info by room_id=%d", roomID))
c.JSONMap(map[string]interface{}{"message": "获取线路信息失败,刷新页面或稍后重试"}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": map[string]interface{}{"up_stream": info}}, nil)
}
// getRoomRtmp 拜年祭房间推流码接口
func getRoomRtmp(c *bm.Context) {
params := c.Request.URL.Query()
c.Set("input_params", params)
room := params.Get("room_id")
roomID, err := strconv.ParseInt(room, 10, 64)
if err != nil || roomID <= 0 {
c.Set("output_data", "房间号不正确")
c.JSONMap(map[string]interface{}{"message": "房间号不正确"}, ecode.RequestErr)
c.Abort()
return
}
info, err := srv.GetRoomRtmp(c, roomID)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": "获取房间信息失败"}, ecode.RequestErr)
c.Abort()
return
}
if info == nil {
c.Set("output_data", fmt.Sprintf("can find any info by room_id=%d", roomID))
c.JSONMap(map[string]interface{}{"message": "获取房间信息失败,请确认是否房间存在"}, ecode.RequestErr)
c.Abort()
return
}
c.Set("output_data", info)
c.JSONMap(map[string]interface{}{"data": info}, nil)
}

View File

@@ -0,0 +1,147 @@
package http
import (
"fmt"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"strconv"
"time"
)
// getSummaryUpStreamRtmp 查询统计信息
func getSummaryUpStreamRtmp(c *bm.Context) {
st, ed, err := analysisTimeParams(c)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
res, err := srv.GetSummaryUpStreamRtmp(c, st, ed)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.JSONMap(map[string]interface{}{"data": res}, nil)
}
// getSummaryUpStreamISP 获取运营商信息统计
func getSummaryUpStreamISP(c *bm.Context) {
st, ed, err := analysisTimeParams(c)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
res, err := srv.GetSummaryUpStreamISP(c, st, ed)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.JSONMap(map[string]interface{}{"data": res}, nil)
}
// getSummaryUpStreamISP 获取运营商信息统计
func getSummaryUpStreamCountry(c *bm.Context) {
st, ed, err := analysisTimeParams(c)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
res, err := srv.GetSummaryUpStreamCountry(c, st, ed)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.JSONMap(map[string]interface{}{"data": res}, nil)
}
// getSummaryUpStreamPlatform 获取Platform信息统计
func getSummaryUpStreamPlatform(c *bm.Context) {
st, ed, err := analysisTimeParams(c)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
res, err := srv.GetSummaryUpStreamPlatform(c, st, ed)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.JSONMap(map[string]interface{}{"data": res}, nil)
}
// getSummaryUpStreamCity 获取City信息统计
func getSummaryUpStreamCity(c *bm.Context) {
st, ed, err := analysisTimeParams(c)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
res, err := srv.GetSummaryUpStreamCity(c, st, ed)
if err != nil {
c.Set("output_data", err.Error())
c.JSONMap(map[string]interface{}{"message": err.Error()}, ecode.RequestErr)
c.Abort()
return
}
c.JSONMap(map[string]interface{}{"data": res}, nil)
}
// analysisTimeParams 分析传入参数
func analysisTimeParams(c *bm.Context) (int64, int64, error) {
params := c.Request.URL.Query()
start := params.Get("start")
end := params.Get("end")
var st int64
var ed int64
var err error
if start == "" {
t := time.Now()
year, month, day := t.Date()
st = time.Date(year, month, day, 0, 0, 0, 0, t.Location()).Unix()
} else {
st, err = strconv.ParseInt(start, 10, 64)
if err != nil {
return 0, 0, fmt.Errorf("start is not right")
}
}
if end == "" {
ed = time.Now().Unix()
} else {
ed, err = strconv.ParseInt(end, 10, 64)
if err != nil {
return 0, 0, fmt.Errorf("end is not right")
}
}
return st, ed, nil
}