diff --git a/.gitignore b/.gitignore index 4e89af21..9836eec0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ # Created by .ignore support plugin (hsz.mobi) .idea dist +room_keys.json +.vscode +.tmp +vendor \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..b89bd581 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,44 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added +- JSON Web Token support. +``` json + // .livego.json + { + "jwt": { + "secret": "testing", + "algorithm": "HS256s" + }, + "server": [ + { + "appname": "live", + "liveon": "on", + "hlson": "on" + } + ] + } +``` +- Use redis for store room keys +``` json + // .livego.json + { + "redis_addr": "localhost:6379", + "server": [ + { + "appname": "live", + "liveon": "on", + "hlson": "on" + } + ] + } +``` + +### Changed +- Show `players`. +- Show `stream_id`. \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 2bf89c10..37aa7d11 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,17 +3,20 @@ WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . -RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o livego ./ +RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o livego . FROM alpine:latest -LABEL maintainer="gwuhaolin " +LABEL maintainer="Ruben Cid Lara " +RUN mkdir -p /app/config +WORKDIR /app ENV RTMP_PORT 1935 ENV HTTP_FLV_PORT 7001 ENV HLS_PORT 7002 ENV HTTP_OPERATION_PORT 8090 +COPY --from=builder /app/config ./config COPY --from=builder /app/livego . EXPOSE ${RTMP_PORT} EXPOSE ${HTTP_FLV_PORT} EXPOSE ${HLS_PORT} EXPOSE ${HTTP_OPERATION_PORT} -CMD ./livego \ No newline at end of file +ENTRYPOINT ["./livego"] diff --git a/README.md b/README.md index c07f4967..c8e772ea 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,42 @@ # livego -简单高效的直播服务器: -- 安装和使用非常简单; -- 纯 Golang 编写,性能高,跨平台; -- 支持常用的传输协议、文件格式、编码格式; +Simple and efficient live broadcast server: +- Very simple to install and use; +- Pure Golang, high performance, cross-platform; +- Support commonly used transmission protocols, file formats, encoding formats; -#### 支持的传输协议 +#### Supported transport protocols - RTMP - AMF - HLS - HTTP-FLV -#### 支持的容器格式 +#### Supported container formats - FLV - TS -#### 支持的编码格式 +#### Supported encoding formats - H264 - AAC -- MP3 +- sMP3 -## 安装 -直接下载编译好的[二进制文件](https://github.com/gwuhaolin/livego/releases)后,在命令行中执行。 +## Installation +After directly downloading the compiled [binary file](https://github.com/gwuhaolin/livego/releases), execute it on the command line. -#### 从 Docker 启动 -执行`docker run -p 1935:1935 -p 7001:7001 -p 7002:7002 -d --name livego gwuhaolin/livego`启动 +#### Boot from Docker +Run `docker run -p 1935:1935 -p 7001:7001 -p 7002:7002 -d --name livego gnurub/livego` to start -#### 从源码编译 -1. 下载源码 `git clone https://github.com/gwuhaolin/livego.git` -2. 去 livego 目录中 执行 `go build` +#### Compile from source +1. Download the source code `git clone https://github.com/gwuhaolin/livego.git` +2. Go to the livego directory and execute `go build` -## 使用 -2. 启动服务:执行 `livego` 二进制文件启动 livego 服务; -3. 上行推流:通过 `RTMP` 协议把视频流推送到 `rtmp://localhost:1935/live/movie`,例如使用 `ffmpeg -re -i demo.flv -c copy -f flv rtmp://localhost:1935/live/movie` 推送; -4. 下行播放:支持以下三种播放协议,播放地址如下: - - `RTMP`:`rtmp://localhost:1935/live/movie` - - `FLV`:`http://127.0.0.1:7001/live/movie.flv` - - `HLS`:`http://127.0.0.1:7002/live/movie.m3u8` +## Use +2. Start the service: execute the livego binary file to start the livego service; +3. Upstream push: Push the video stream to `rtmp://localhost:1935/live/movie` through the` RTMP` protocol, for example, use `ffmpeg -re -i demo.flv -c copy -f flv rtmp://localhost:1935/live/movie` push; +4. Downstream playback: The following three playback protocols are supported, and the playback address is as follows: + -`RTMP`:`rtmp://localhost:1935/live/movie` + -`FLV`:`http://127.0.0.1:7001/live/movie.flv` + -`HLS`:`http://127.0.0.1:7002/live/movie.m3u8` +### [Use with flv.js](https://github.com/gwuhaolin/blog/issues/3) -### [和 flv.js 搭配使用](https://github.com/gwuhaolin/blog/issues/3) - -对Golang感兴趣?请看[Golang 中文学习资料汇总](http://go.wuhaolin.cn/) +Interested in Golang? Please see [Golang Chinese Learning Materials Summary](http://go.wuhaolin.cn/) diff --git a/.livego.json b/config/livego.json similarity index 100% rename from .livego.json rename to config/livego.json diff --git a/configure/channel.go b/configure/channel.go new file mode 100755 index 00000000..38eb30a5 --- /dev/null +++ b/configure/channel.go @@ -0,0 +1,200 @@ +package configure + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "math/rand" + "sync" + "time" + + "github.com/go-redis/redis/v7" +) + +var RoomKeys = LoadRoomKey(*GetKeyFile()) + +var roomUpdated = false + +var saveInFile = true +var redisCli *redis.Client + +func Init() { + saveInFile = GetRedisAddr() == nil + + rand.Seed(time.Now().UnixNano()) + if saveInFile { + go func() { + for { + time.Sleep(15 * time.Second) + if roomUpdated { + RoomKeys.Save(*roomKeySaveFile) + roomUpdated = false + } + } + }() + + return + } + + redisCli = redis.NewClient(&redis.Options{ + Addr: *GetRedisAddr(), + Password: *GetRedisPwd(), + DB: 0, + }) + + _, err := redisCli.Ping().Result() + if err != nil { + panic(err) + } + + log.Printf("Redis connected") +} + +type RoomKeysType struct { + mapChanKey sync.Map + mapKeyChan sync.Map +} + +func LoadRoomKey(f string) *RoomKeysType { + result := &RoomKeysType{ + mapChanKey: sync.Map{}, + mapKeyChan: sync.Map{}, + } + raw := map[string]string{} + content, err := ioutil.ReadFile(f) + if err != nil { + log.Printf("Failed to read file %s for room keys", f) + return result + } + if json.Unmarshal(content, &raw) != nil { + log.Printf("Failed to unmarshal file %s for room keys", f) + return result + } + for room, key := range raw { + result.mapChanKey.Store(room, key) + result.mapKeyChan.Store(key, room) + } + return result +} + +func (r *RoomKeysType) Save(f string) { + raw := map[string]string{} + r.mapChanKey.Range(func(channel, key interface{}) bool { + raw[channel.(string)] = key.(string) + return true + }) + content, err := json.Marshal(raw) + if err != nil { + log.Println("Failed to marshal room keys") + return + } + if ioutil.WriteFile(f, content, 0644) != nil { + log.Println("Failed to save room keys") + return + } +} + +// set/reset a random key for channel +func (r *RoomKeysType) SetKey(channel string) (key string, err error) { + if !saveInFile { + for { + key = randStringRunes(48) + if _, err = redisCli.Get(key).Result(); err == redis.Nil { + err = redisCli.Set(channel, key, 0).Err() + if err != nil { + return + } + + err = redisCli.Set(key, channel, 0).Err() + return + } else if err != nil { + return + } + } + } + + for { + key = randStringRunes(48) + if _, found := r.mapKeyChan.Load(key); !found { + r.mapChanKey.Store(channel, key) + r.mapKeyChan.Store(key, channel) + break + } + } + roomUpdated = true + return +} + +func (r *RoomKeysType) GetKey(channel string) (newKey string, err error) { + if !saveInFile { + if newKey, err = redisCli.Get(channel).Result(); err == redis.Nil { + newKey, err = r.SetKey(channel) + log.Printf("[KEY] new channel [%s]: %s", channel, newKey) + return + } + + return + } + + var key interface{} + var found bool + if key, found = r.mapChanKey.Load(channel); found { + return key.(string), nil + } + newKey, err = r.SetKey(channel) + log.Printf("[KEY] new channel [%s]: %s", channel, newKey) + return +} + +func (r *RoomKeysType) GetChannel(key string) (channel string, err error) { + if !saveInFile { + return redisCli.Get(key).Result() + } + + chann, found := r.mapKeyChan.Load(key) + if found { + return chann.(string), nil + } else { + return "", fmt.Errorf("%s does not exists", key) + } +} + +func (r *RoomKeysType) DeleteChannel(channel string) bool { + if !saveInFile { + return redisCli.Del(channel).Err() != nil + } + + key, ok := r.mapChanKey.Load(channel) + if ok { + r.mapChanKey.Delete(channel) + r.mapKeyChan.Delete(key) + return true + } + return false +} + +func (r *RoomKeysType) DeleteKey(key string) bool { + if !saveInFile { + return redisCli.Del(key).Err() != nil + } + + channel, ok := r.mapKeyChan.Load(key) + if ok { + r.mapChanKey.Delete(channel) + r.mapKeyChan.Delete(key) + return true + } + return false +} + +// helpers +var letterRunes = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func randStringRunes(n int) string { + b := make([]rune, n) + for i := range b { + b[i] = letterRunes[rand.Intn(len(letterRunes))] + } + return string(b) +} diff --git a/configure/liveconfig.go b/configure/liveconfig.go index 68305735..af5350cb 100644 --- a/configure/liveconfig.go +++ b/configure/liveconfig.go @@ -2,44 +2,60 @@ package configure import ( "encoding/json" + "flag" "io/ioutil" "log" ) /* { - [ - { - "application":"live", - "live":"on", - "hls":"on", - "static_push":["rtmp://xx/live"] - } - ] + "server": [ + { + "appname": "live", + "liveon": "on", + "hlson": "on", + "static_push": [] + } + ] } */ +var ( + roomKeySaveFile = flag.String("KeyFile", "room_keys.json", "path to save room keys") + RedisAddr = flag.String("redis_addr", "", "redis addr to save room keys ex. localhost:6379") + RedisPwd = flag.String("redis_pwd", "", "redis password") +) + type Application struct { - Appname string - Liveon string - Hlson string - Static_push []string + Appname string `json:"appname"` + Liveon string `json:"liveon"` + Hlson string `json:"hlson"` + StaticPush []string `json:"static_push"` +} + +type JWTCfg struct { + Secret string `json:"secret"` + Algorithm string `json:"algorithm"` } type ServerCfg struct { - Server []Application + KeyFile string `json:"key_file"` + RedisAddr string `json:"redis_addr"` + RedisPwd string `json:"redis_pwd"` + JWTCfg `json:"jwt"` + Server []Application `json:"server"` } var RtmpServercfg ServerCfg func LoadConfig(configfilename string) error { - log.Printf("starting load configure file(%s)......", configfilename) + log.Printf("starting load configure file %s", configfilename) data, err := ioutil.ReadFile(configfilename) if err != nil { log.Printf("ReadFile %s error:%v", configfilename, err) return err } - log.Printf("loadconfig: \r\n%s", string(data)) + // log.Printf("loadconfig: \r\n%s", string(data)) err = json.Unmarshal(data, &RtmpServercfg) if err != nil { @@ -47,9 +63,40 @@ func LoadConfig(configfilename string) error { return err } log.Printf("get config json data:%v", RtmpServercfg) + + Init() + return nil } +func GetKeyFile() *string { + if len(RtmpServercfg.KeyFile) > 0 { + *roomKeySaveFile = RtmpServercfg.KeyFile + } + + return roomKeySaveFile +} + +func GetRedisAddr() *string { + if len(RtmpServercfg.RedisAddr) > 0 { + *RedisAddr = RtmpServercfg.RedisAddr + } + + if len(*RedisAddr) == 0 { + return nil + } + + return RedisAddr +} + +func GetRedisPwd() *string { + if len(RtmpServercfg.RedisPwd) > 0 { + *RedisPwd = RtmpServercfg.RedisPwd + } + + return RedisPwd +} + func CheckAppName(appname string) bool { for _, app := range RtmpServercfg.Server { if (app.Appname == appname) && (app.Liveon == "on") { @@ -62,8 +109,8 @@ func CheckAppName(appname string) bool { func GetStaticPushUrlList(appname string) ([]string, bool) { for _, app := range RtmpServercfg.Server { if (app.Appname == appname) && (app.Liveon == "on") { - if len(app.Static_push) > 0 { - return app.Static_push, true + if len(app.StaticPush) > 0 { + return app.StaticPush, true } else { return nil, false } diff --git a/container/flv/demuxer.go b/container/flv/demuxer.go index 2c205ba3..bfcc7842 100755 --- a/container/flv/demuxer.go +++ b/container/flv/demuxer.go @@ -3,7 +3,7 @@ package flv import ( "errors" - "github.com/gwuhaolin/livego/av" + "livego/av" ) var ( diff --git a/container/flv/muxer.go b/container/flv/muxer.go index 465ba3d3..a7eaa884 100755 --- a/container/flv/muxer.go +++ b/container/flv/muxer.go @@ -5,20 +5,22 @@ import ( "fmt" "log" "os" + "path" "strings" "time" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/protocol/amf" - "github.com/gwuhaolin/livego/utils/pio" - "github.com/gwuhaolin/livego/utils/uid" + "livego/av" + "livego/protocol/amf" + "livego/utils/pio" + "livego/utils/uid" ) var ( flvHeader = []byte{0x46, 0x4c, 0x56, 0x01, 0x05, 0x00, 0x00, 0x00, 0x09} - flvFile = flag.String("filFile", "./out.flv", "output flv file name") + flvDir = flag.String("flvDir", "tmp", "output flv file at flvDir/APP/KEY_TIME.flv") ) +/* func NewFlv(handler av.Handler, info av.Info) { patths := strings.SplitN(info.Key, "/", 2) @@ -41,6 +43,7 @@ func NewFlv(handler av.Handler, info av.Info) { log.Println("close flv file") writer.ctx.Close() } +*/ const ( headerLen = 11 @@ -144,18 +147,17 @@ type FlvDvr struct{} func (f *FlvDvr) GetWriter(info av.Info) av.WriteCloser { paths := strings.SplitN(info.Key, "/", 2) if len(paths) != 2 { - log.Println("invalid info") return nil } - err := os.MkdirAll(paths[0], 0755) + err := os.MkdirAll(path.Join(*flvDir, paths[0]), 0755) if err != nil { log.Println("mkdir error:", err) return nil } - fileName := fmt.Sprintf("%s_%d.%s", info.Key, time.Now().Unix(), "flv") + fileName := fmt.Sprintf("%s_%d.%s", path.Join(*flvDir, info.Key), time.Now().Unix(), "flv") log.Println("flv dvr save stream to: ", fileName) w, err := os.OpenFile(fileName, os.O_CREATE|os.O_RDWR, 0755) if err != nil { diff --git a/container/flv/tag.go b/container/flv/tag.go index 5c85466e..d2aec4f5 100755 --- a/container/flv/tag.go +++ b/container/flv/tag.go @@ -3,7 +3,7 @@ package flv import ( "fmt" - "github.com/gwuhaolin/livego/av" + "livego/av" ) type flvTag struct { diff --git a/container/ts/muxer.go b/container/ts/muxer.go index cbb9981d..8f7ad3d2 100755 --- a/container/ts/muxer.go +++ b/container/ts/muxer.go @@ -3,7 +3,7 @@ package ts import ( "io" - "github.com/gwuhaolin/livego/av" + "livego/av" ) const ( diff --git a/container/ts/muxer_test.go b/container/ts/muxer_test.go index 52b36685..5ee3cf38 100755 --- a/container/ts/muxer_test.go +++ b/container/ts/muxer_test.go @@ -3,7 +3,8 @@ package ts import ( "testing" - "github.com/gwuhaolin/livego/av" + "livego/av" + "github.com/stretchr/testify/assert" ) diff --git a/go.mod b/go.mod index eb767277..5294b52a 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,15 @@ -module github.com/gwuhaolin/livego +module livego go 1.13 require ( - github.com/kr/pretty v0.1.0 // indirect + github.com/auth0/go-jwt-middleware v0.0.0-20190805220309-36081240882b + github.com/dgrijalva/jwt-go v3.2.0+incompatible + github.com/go-redis/redis/v7 v7.2.0 + github.com/gorilla/mux v1.7.4 // indirect github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6 github.com/satori/go.uuid v1.2.0 + github.com/smartystreets/goconvey v1.6.4 // indirect github.com/stretchr/testify v1.4.0 - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + github.com/urfave/negroni v1.0.0 // indirect ) diff --git a/go.sum b/go.sum index a066b49a..000ad9eb 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,72 @@ +github.com/auth0/go-jwt-middleware v0.0.0-20190805220309-36081240882b h1:CvoEHGmxWl5kONC5icxwqV899dkf4VjOScbxLpllEnw= +github.com/auth0/go-jwt-middleware v0.0.0-20190805220309-36081240882b/go.mod h1:LWMyo4iOLWXHGdBki7NIht1kHru/0wM179h+d3g8ATM= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-redis/redis/v7 v7.2.0 h1:CrCexy/jYWZjW0AyVoHlcJUeZN19VWlbepTh1Vq6dJs= +github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= +github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6 h1:lNCW6THrCKBiJBpz8kbVGjC7MgdCGKwuvBgc7LoD6sw= github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index bdd45ffc..09575bc8 100755 --- a/main.go +++ b/main.go @@ -6,11 +6,11 @@ import ( "net" "time" - "github.com/gwuhaolin/livego/configure" - "github.com/gwuhaolin/livego/protocol/hls" - "github.com/gwuhaolin/livego/protocol/httpflv" - "github.com/gwuhaolin/livego/protocol/httpopera" - "github.com/gwuhaolin/livego/protocol/rtmp" + "livego/configure" + "livego/protocol/hls" + "livego/protocol/httpflv" + "livego/protocol/httpopera" + "livego/protocol/rtmp" ) var ( @@ -19,7 +19,7 @@ var ( httpFlvAddr = flag.String("httpflv-addr", ":7001", "HTTP-FLV server listen address") hlsAddr = flag.String("hls-addr", ":7002", "HLS server listen address") operaAddr = flag.String("manage-addr", ":8090", "HTTP manage interface server listen address") - configfilename = flag.String("cfgfile", ".livego.json", "configure filename") + configfilename = flag.String("config-file", "config/livego.json", "configure filename") ) func init() { diff --git a/parser/aac/parser.go b/parser/aac/parser.go index e9caf57a..7ad9f05f 100755 --- a/parser/aac/parser.go +++ b/parser/aac/parser.go @@ -4,7 +4,7 @@ import ( "errors" "io" - "github.com/gwuhaolin/livego/av" + "livego/av" ) type mpegExtension struct { diff --git a/parser/parser.go b/parser/parser.go index 05b4d730..31bdd4fa 100755 --- a/parser/parser.go +++ b/parser/parser.go @@ -4,10 +4,10 @@ import ( "errors" "io" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/parser/aac" - "github.com/gwuhaolin/livego/parser/h264" - "github.com/gwuhaolin/livego/parser/mp3" + "livego/av" + "livego/parser/aac" + "livego/parser/h264" + "livego/parser/mp3" ) var ( diff --git a/protocol/hls/hls.go b/protocol/hls/hls.go index 749b81ae..0648f033 100755 --- a/protocol/hls/hls.go +++ b/protocol/hls/hls.go @@ -11,8 +11,9 @@ import ( "strings" "time" - "github.com/gwuhaolin/livego/av" - "github.com/orcaman/concurrent-map" + "livego/av" + + cmap "github.com/orcaman/concurrent-map" ) const ( diff --git a/protocol/hls/source.go b/protocol/hls/source.go index c2fc7a0f..60f4f832 100644 --- a/protocol/hls/source.go +++ b/protocol/hls/source.go @@ -7,10 +7,10 @@ import ( "log" "time" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/container/flv" - "github.com/gwuhaolin/livego/container/ts" - "github.com/gwuhaolin/livego/parser" + "livego/av" + "livego/container/flv" + "livego/container/ts" + "livego/parser" ) const ( diff --git a/protocol/httpflv/server.go b/protocol/httpflv/server.go index 8c46c238..1974dbbf 100644 --- a/protocol/httpflv/server.go +++ b/protocol/httpflv/server.go @@ -7,8 +7,8 @@ import ( "net/http" "strings" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/protocol/rtmp" + "livego/av" + "livego/protocol/rtmp" ) type Server struct { diff --git a/protocol/httpflv/writer.go b/protocol/httpflv/writer.go index 70ed67b1..e97e6006 100755 --- a/protocol/httpflv/writer.go +++ b/protocol/httpflv/writer.go @@ -7,10 +7,10 @@ import ( "net/http" "time" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/protocol/amf" - "github.com/gwuhaolin/livego/utils/pio" - "github.com/gwuhaolin/livego/utils/uid" + "livego/av" + "livego/protocol/amf" + "livego/utils/pio" + "livego/utils/uid" ) const ( diff --git a/protocol/httpopera/http_opera.go b/protocol/httpopera/http_opera.go index 22071b44..584f0e14 100755 --- a/protocol/httpopera/http_opera.go +++ b/protocol/httpopera/http_opera.go @@ -3,25 +3,29 @@ package httpopera import ( "encoding/json" "fmt" - "io" "log" "net" "net/http" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/protocol/rtmp" - "github.com/gwuhaolin/livego/protocol/rtmp/rtmprelay" + "livego/av" + "livego/configure" + "livego/protocol/rtmp" + "livego/protocol/rtmp/rtmprelay" + + jwtmiddleware "github.com/auth0/go-jwt-middleware" + "github.com/dgrijalva/jwt-go" ) type Response struct { - w http.ResponseWriter - Status int `json:"status"` - Message string `json:"message"` + w http.ResponseWriter + Status int `json:"status"` + Data interface{} `json:"data"` } func (r *Response) SendJson() (int, error) { resp, _ := json.Marshal(r) r.w.Header().Set("Content-Type", "application/json") + r.w.WriteHeader(r.Status) return r.w.Write(resp) } @@ -58,10 +62,38 @@ func NewServer(h av.Handler, rtmpAddr string) *Server { } } +func JWTMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if len(configure.RtmpServercfg.JWTCfg.Secret) > 0 { + var algorithm jwt.SigningMethod + if len(configure.RtmpServercfg.JWTCfg.Algorithm) > 0 { + algorithm = jwt.GetSigningMethod(configure.RtmpServercfg.JWTCfg.Algorithm) + } + + if algorithm == nil { + algorithm = jwt.SigningMethodHS256 + } + + jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{ + Extractor: jwtmiddleware.FromFirst(jwtmiddleware.FromAuthHeader, jwtmiddleware.FromParameter("jwt")), + ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { + return []byte(configure.RtmpServercfg.Secret), nil + }, + SigningMethod: algorithm, + }) + + jwtMiddleware.HandlerWithNext(w, r, next.ServeHTTP) + return + } + next.ServeHTTP(w, r) + + }) +} + func (s *Server) Serve(l net.Listener) error { mux := http.NewServeMux() - mux.Handle("/statics", http.FileServer(http.Dir("statics"))) + mux.Handle("/statics/", http.StripPrefix("/statics/", http.FileServer(http.Dir("statics")))) mux.HandleFunc("/control/push", func(w http.ResponseWriter, r *http.Request) { s.handlePush(w, r) @@ -69,21 +101,30 @@ func (s *Server) Serve(l net.Listener) error { mux.HandleFunc("/control/pull", func(w http.ResponseWriter, r *http.Request) { s.handlePull(w, r) }) + mux.HandleFunc("/control/get", func(w http.ResponseWriter, r *http.Request) { + s.handleGet(w, r) + }) + mux.HandleFunc("/control/reset", func(w http.ResponseWriter, r *http.Request) { + s.handleReset(w, r) + }) + mux.HandleFunc("/control/delete", func(w http.ResponseWriter, r *http.Request) { + s.handleDelete(w, r) + }) mux.HandleFunc("/stat/livestat", func(w http.ResponseWriter, r *http.Request) { s.GetLiveStatics(w, r) }) - http.Serve(l, mux) + http.Serve(l, JWTMiddleware(mux)) return nil } type stream struct { Key string `json:"key"` - Url string `json:"Url"` - StreamId uint32 `json:"StreamId"` - VideoTotalBytes uint64 `json:123456` - VideoSpeed uint64 `json:123456` - AudioTotalBytes uint64 `json:123456` - AudioSpeed uint64 `json:123456` + Url string `json:"url"` + StreamId uint32 `json:"stream_id"` + VideoTotalBytes uint64 `json:"video_total_bytes"` + VideoSpeed uint64 `json:"video_speed"` + AudioTotalBytes uint64 `json:"audio_total_bytes"` + AudioSpeed uint64 `json:"audio_speed"` } type streams struct { @@ -93,9 +134,18 @@ type streams struct { //http://127.0.0.1:8090/stat/livestat func (server *Server) GetLiveStatics(w http.ResponseWriter, req *http.Request) { + res := &Response{ + w: w, + Data: nil, + Status: 200, + } + + defer res.SendJson() + rtmpStream := server.handler.(*rtmp.RtmpStream) if rtmpStream == nil { - io.WriteString(w, "

Get rtmp stream information error

") + res.Status = 500 + res.Data = "Get rtmp stream information error" return } @@ -130,17 +180,29 @@ func (server *Server) GetLiveStatics(w http.ResponseWriter, req *http.Request) { } } } + resp, _ := json.Marshal(msgs) - w.Header().Set("Content-Type", "application/json") - w.Write(resp) + res.Data = resp } -//http://127.0.0.1:8090/control/push?&oper=start&app=live&name=123456&url=rtmp://192.168.16.136/live/123456 +//http://127.0.0.1:8090/control/pull?&oper=start&app=live&name=123456&url=rtmp://192.168.16.136/live/123456 func (s *Server) handlePull(w http.ResponseWriter, req *http.Request) { var retString string var err error - req.ParseForm() + res := &Response{ + w: w, + Data: nil, + Status: 200, + } + + defer res.SendJson() + + if req.ParseForm() != nil { + res.Status = 400 + res.Data = "url: /control/pull?&oper=start&app=live&name=123456&url=rtmp://192.168.16.136/live/123456" + return + } oper := req.Form["oper"] app := req.Form["app"] @@ -149,7 +211,8 @@ func (s *Server) handlePull(w http.ResponseWriter, req *http.Request) { log.Printf("control pull: oper=%v, app=%v, name=%v, url=%v", oper, app, name, url) if (len(app) <= 0) || (len(name) <= 0) || (len(url) <= 0) { - io.WriteString(w, "control push parameter error, please check them.
") + res.Status = 400 + res.Data = "control push parameter error, please check them." return } @@ -162,7 +225,8 @@ func (s *Server) handlePull(w http.ResponseWriter, req *http.Request) { if !found { retString = fmt.Sprintf("session key[%s] not exist, please check it again.", keyString) - io.WriteString(w, retString) + res.Status = 400 + res.Data = retString return } log.Printf("rtmprelay stop push %s from %s", remoteurl, localurl) @@ -170,7 +234,8 @@ func (s *Server) handlePull(w http.ResponseWriter, req *http.Request) { delete(s.session, keyString) retString = fmt.Sprintf("

push url stop %s ok


", url[0]) - io.WriteString(w, retString) + res.Status = 400 + res.Data = retString log.Printf("pull stop return %s", retString) } else { pullRtmprelay := rtmprelay.NewRtmpRelay(&localurl, &remoteurl) @@ -182,7 +247,8 @@ func (s *Server) handlePull(w http.ResponseWriter, req *http.Request) { s.session[keyString] = pullRtmprelay retString = fmt.Sprintf("

push url start %s ok


", url[0]) } - io.WriteString(w, retString) + res.Status = 400 + res.Data = retString log.Printf("pull start return %s", retString) } } @@ -192,7 +258,18 @@ func (s *Server) handlePush(w http.ResponseWriter, req *http.Request) { var retString string var err error - req.ParseForm() + res := &Response{ + w: w, + Data: nil, + Status: 200, + } + + defer res.SendJson() + + if req.ParseForm() != nil { + res.Data = "url: /control/push?&oper=start&app=live&name=123456&url=rtmp://192.168.16.136/live/123456" + return + } oper := req.Form["oper"] app := req.Form["app"] @@ -201,7 +278,7 @@ func (s *Server) handlePush(w http.ResponseWriter, req *http.Request) { log.Printf("control push: oper=%v, app=%v, name=%v, url=%v", oper, app, name, url) if (len(app) <= 0) || (len(name) <= 0) || (len(url) <= 0) { - io.WriteString(w, "control push parameter error, please check them.
") + res.Data = "control push parameter error, please check them." return } @@ -213,7 +290,7 @@ func (s *Server) handlePush(w http.ResponseWriter, req *http.Request) { pushRtmprelay, found := s.session[keyString] if !found { retString = fmt.Sprintf("

session key[%s] not exist, please check it again.

", keyString) - io.WriteString(w, retString) + res.Data = retString return } log.Printf("rtmprelay stop push %s from %s", remoteurl, localurl) @@ -221,7 +298,7 @@ func (s *Server) handlePush(w http.ResponseWriter, req *http.Request) { delete(s.session, keyString) retString = fmt.Sprintf("

push url stop %s ok


", url[0]) - io.WriteString(w, retString) + res.Data = retString log.Printf("push stop return %s", retString) } else { pushRtmprelay := rtmprelay.NewRtmpRelay(&localurl, &remoteurl) @@ -234,7 +311,101 @@ func (s *Server) handlePush(w http.ResponseWriter, req *http.Request) { s.session[keyString] = pushRtmprelay } - io.WriteString(w, retString) + res.Data = retString log.Printf("push start return %s", retString) } } + +//http://127.0.0.1:8090/control/reset?room=ROOM_NAME +func (s *Server) handleReset(w http.ResponseWriter, r *http.Request) { + res := &Response{ + w: w, + Data: nil, + Status: 200, + } + defer res.SendJson() + + if err := r.ParseForm(); err != nil { + res.Status = 400 + res.Data = "url: /control/reset?room=ROOM_NAME" + return + } + room := r.Form.Get("room") + + if len(room) == 0 { + res.Status = 400 + res.Data = "url: /control/get?room=ROOM_NAME" + return + } + + msg, err := configure.RoomKeys.SetKey(room) + + if err != nil { + msg = err.Error() + res.Status = 400 + } + + res.Data = msg +} + +//http://127.0.0.1:8090/control/get?room=ROOM_NAME +func (s *Server) handleGet(w http.ResponseWriter, r *http.Request) { + res := &Response{ + w: w, + Data: nil, + Status: 200, + } + defer res.SendJson() + + if err := r.ParseForm(); err != nil { + res.Status = 400 + res.Data = "url: /control/get?room=ROOM_NAME" + return + } + + room := r.Form.Get("room") + + if len(room) == 0 { + res.Status = 400 + res.Data = "url: /control/get?room=ROOM_NAME" + return + } + + msg, err := configure.RoomKeys.GetKey(room) + if err != nil { + msg = err.Error() + res.Status = 400 + } + res.Data = msg +} + +//http://127.0.0.1:8090/control/delete?room=ROOM_NAME +func (s *Server) handleDelete(w http.ResponseWriter, r *http.Request) { + res := &Response{ + w: w, + Data: nil, + Status: 200, + } + defer res.SendJson() + + if err := r.ParseForm(); err != nil { + res.Status = 400 + res.Data = "url: /control/delete?room=ROOM_NAME" + return + } + + room := r.Form.Get("room") + + if len(room) == 0 { + res.Status = 400 + res.Data = "url: /control/get?room=ROOM_NAME" + return + } + + if configure.RoomKeys.DeleteChannel(room) { + res.Data = "Ok" + return + } + res.Status = 404 + res.Data = "Room not found" +} diff --git a/protocol/rtmp/cache/cache.go b/protocol/rtmp/cache/cache.go index a5c604b7..b644e94d 100755 --- a/protocol/rtmp/cache/cache.go +++ b/protocol/rtmp/cache/cache.go @@ -3,7 +3,7 @@ package cache import ( "flag" - "github.com/gwuhaolin/livego/av" + "livego/av" ) var ( diff --git a/protocol/rtmp/cache/gop.go b/protocol/rtmp/cache/gop.go index ececab4b..401bab08 100755 --- a/protocol/rtmp/cache/gop.go +++ b/protocol/rtmp/cache/gop.go @@ -3,7 +3,7 @@ package cache import ( "errors" - "github.com/gwuhaolin/livego/av" + "livego/av" ) var ( diff --git a/protocol/rtmp/cache/special.go b/protocol/rtmp/cache/special.go index 89c9693b..dce82a3f 100755 --- a/protocol/rtmp/cache/special.go +++ b/protocol/rtmp/cache/special.go @@ -4,8 +4,8 @@ import ( "bytes" "log" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/protocol/amf" + "livego/av" + "livego/protocol/amf" ) const ( diff --git a/protocol/rtmp/core/chunk_stream.go b/protocol/rtmp/core/chunk_stream.go index 33970c48..379646b2 100755 --- a/protocol/rtmp/core/chunk_stream.go +++ b/protocol/rtmp/core/chunk_stream.go @@ -4,8 +4,8 @@ import ( "encoding/binary" "fmt" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/utils/pool" + "livego/av" + "livego/utils/pool" ) type ChunkStream struct { diff --git a/protocol/rtmp/core/chunk_stream_test.go b/protocol/rtmp/core/chunk_stream_test.go index 749c7abb..94cd05a6 100755 --- a/protocol/rtmp/core/chunk_stream_test.go +++ b/protocol/rtmp/core/chunk_stream_test.go @@ -4,7 +4,8 @@ import ( "bytes" "testing" - "github.com/gwuhaolin/livego/utils/pool" + "livego/utils/pool" + "github.com/stretchr/testify/assert" ) diff --git a/protocol/rtmp/core/conn.go b/protocol/rtmp/core/conn.go index 610a58c8..2e563a9f 100755 --- a/protocol/rtmp/core/conn.go +++ b/protocol/rtmp/core/conn.go @@ -5,8 +5,8 @@ import ( "net" "time" - "github.com/gwuhaolin/livego/utils/pio" - "github.com/gwuhaolin/livego/utils/pool" + "livego/utils/pio" + "livego/utils/pool" ) const ( diff --git a/protocol/rtmp/core/conn_client.go b/protocol/rtmp/core/conn_client.go index 566e67fc..42db529d 100755 --- a/protocol/rtmp/core/conn_client.go +++ b/protocol/rtmp/core/conn_client.go @@ -12,8 +12,8 @@ import ( "log" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/protocol/amf" + "livego/av" + "livego/protocol/amf" ) var ( diff --git a/protocol/rtmp/core/conn_server.go b/protocol/rtmp/core/conn_server.go index 006b5204..f1bb88d9 100755 --- a/protocol/rtmp/core/conn_server.go +++ b/protocol/rtmp/core/conn_server.go @@ -7,8 +7,8 @@ import ( "log" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/protocol/amf" + "livego/av" + "livego/protocol/amf" ) var ( diff --git a/protocol/rtmp/core/conn_test.go b/protocol/rtmp/core/conn_test.go index 170543de..1f4cb9b4 100755 --- a/protocol/rtmp/core/conn_test.go +++ b/protocol/rtmp/core/conn_test.go @@ -5,7 +5,8 @@ import ( "io" "testing" - "github.com/gwuhaolin/livego/utils/pool" + "livego/utils/pool" + "github.com/stretchr/testify/assert" ) diff --git a/protocol/rtmp/core/handshake.go b/protocol/rtmp/core/handshake.go index e5583768..61a79b20 100755 --- a/protocol/rtmp/core/handshake.go +++ b/protocol/rtmp/core/handshake.go @@ -10,7 +10,7 @@ import ( "time" - "github.com/gwuhaolin/livego/utils/pio" + "livego/utils/pio" ) var ( diff --git a/protocol/rtmp/rtmp.go b/protocol/rtmp/rtmp.go index b8b475a4..d999c9bb 100755 --- a/protocol/rtmp/rtmp.go +++ b/protocol/rtmp/rtmp.go @@ -11,11 +11,12 @@ import ( "strings" "time" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/configure" - "github.com/gwuhaolin/livego/container/flv" - "github.com/gwuhaolin/livego/protocol/rtmp/core" - "github.com/gwuhaolin/livego/utils/uid" + "livego/utils/uid" + + "livego/av" + "livego/configure" + "livego/container/flv" + "livego/protocol/rtmp/core" ) const ( @@ -111,7 +112,7 @@ func (s *Server) handleConn(conn *core.Conn) error { return err } - appname, _, _ := connServer.GetInfo() + appname, name, _ := connServer.GetInfo() if ret := configure.CheckAppName(appname); !ret { err := errors.New(fmt.Sprintf("application name=%s is not configured", appname)) @@ -122,6 +123,14 @@ func (s *Server) handleConn(conn *core.Conn) error { log.Printf("handleConn: IsPublisher=%v", connServer.IsPublisher()) if connServer.IsPublisher() { + channel, err := configure.RoomKeys.GetChannel(name) + if err != nil { + err := errors.New(fmt.Sprintf("invalid key")) + conn.Close() + log.Println("CheckKey err:", err) + return err + } + connServer.PublishInfo.Name = channel if pushlist, ret := configure.GetStaticPushUrlList(appname); ret && (pushlist != nil) { log.Printf("GetStaticPushUrlList: %v", pushlist) } diff --git a/protocol/rtmp/rtmprelay/rtmprelay.go b/protocol/rtmp/rtmprelay/rtmprelay.go index 1980b9b5..5434b0e9 100644 --- a/protocol/rtmp/rtmprelay/rtmprelay.go +++ b/protocol/rtmp/rtmprelay/rtmprelay.go @@ -7,8 +7,8 @@ import ( "io" "log" - "github.com/gwuhaolin/livego/protocol/amf" - "github.com/gwuhaolin/livego/protocol/rtmp/core" + "livego/protocol/amf" + "livego/protocol/rtmp/core" ) var ( diff --git a/protocol/rtmp/rtmprelay/staticrelay.go b/protocol/rtmp/rtmprelay/staticrelay.go index 6a376b89..00e6cf9f 100644 --- a/protocol/rtmp/rtmprelay/staticrelay.go +++ b/protocol/rtmp/rtmprelay/staticrelay.go @@ -6,9 +6,9 @@ import ( "log" "sync" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/configure" - "github.com/gwuhaolin/livego/protocol/rtmp/core" + "livego/av" + "livego/configure" + "livego/protocol/rtmp/core" ) type StaticPush struct { @@ -63,7 +63,7 @@ func GetStaticPushObject(rtmpurl string) (*StaticPush, error) { } g_MapLock.RUnlock() - return nil, errors.New(fmt.Sprintf("G_StaticPushMap[%s] not exist....")) + return nil, errors.New(fmt.Sprintf("G_StaticPushMap[%s] not exist....", rtmpurl)) } func ReleaseStaticPushObject(rtmpurl string) { diff --git a/protocol/rtmp/stream.go b/protocol/rtmp/stream.go index a5dbaed6..381cef0b 100755 --- a/protocol/rtmp/stream.go +++ b/protocol/rtmp/stream.go @@ -6,10 +6,11 @@ import ( "strings" "time" - "github.com/gwuhaolin/livego/av" - "github.com/gwuhaolin/livego/protocol/rtmp/cache" - "github.com/gwuhaolin/livego/protocol/rtmp/rtmprelay" - "github.com/orcaman/concurrent-map" + "livego/av" + "livego/protocol/rtmp/cache" + "livego/protocol/rtmp/rtmprelay" + + cmap "github.com/orcaman/concurrent-map" ) var ( diff --git a/utils/queue/queue.go b/utils/queue/queue.go index fc82ff9b..03e4b6f7 100755 --- a/utils/queue/queue.go +++ b/utils/queue/queue.go @@ -3,7 +3,7 @@ package queue import ( "sync" - "github.com/gwuhaolin/livego/av" + "livego/av" ) // Queue is a basic FIFO queue for Messages.