2023-08-10 20:34:10 +05:00
|
|
|
package rtmp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net"
|
2023-08-10 20:58:01 +05:00
|
|
|
"encoding/binary"
|
2023-08-10 23:53:58 +05:00
|
|
|
"stream_server/rtmp/amf"
|
2023-08-11 13:09:36 +05:00
|
|
|
"errors"
|
|
|
|
"strings"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2023-08-10 20:34:10 +05:00
|
|
|
)
|
|
|
|
|
|
|
|
type ChunkWrapper struct {
|
|
|
|
conn net.Conn
|
|
|
|
params *ProtocolParams
|
|
|
|
open_chnkstrms map[uint32]*ChunkStream
|
|
|
|
open_msgs map[uint32]*Message
|
|
|
|
chunk_buffs *ChunkBuffers
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewChunkWrapper(conn net.Conn) (chnk_wrp_ptr *ChunkWrapper) {
|
|
|
|
chnk_wrp_ptr = new(ChunkWrapper)
|
|
|
|
|
|
|
|
chnk_wrp_ptr.conn = conn
|
2023-08-10 23:53:58 +05:00
|
|
|
chnk_wrp_ptr.params = &ProtocolParams{1024, 512, 0, 0, ""}
|
2023-08-10 20:34:10 +05:00
|
|
|
chnk_wrp_ptr.open_chnkstrms = make(map[uint32]*ChunkStream)
|
|
|
|
chnk_wrp_ptr.open_msgs = make(map[uint32]*Message)
|
|
|
|
buffers := ChunkBuffers{
|
|
|
|
make([]byte, 4),
|
|
|
|
make([]byte, 4),
|
|
|
|
make([]byte, 1),
|
|
|
|
make([]byte, 4),
|
|
|
|
make([]byte, 1),
|
|
|
|
make([]byte, 2),
|
|
|
|
}
|
|
|
|
chnk_wrp_ptr.chunk_buffs = &buffers
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (chnk_wrp_ptr *ChunkWrapper) ReadChunk() (*Message, error) {
|
|
|
|
full_msg_ptr, err := ReadChunk(
|
|
|
|
chnk_wrp_ptr.conn,
|
|
|
|
chnk_wrp_ptr.open_chnkstrms,
|
|
|
|
chnk_wrp_ptr.open_msgs,
|
|
|
|
chnk_wrp_ptr.params.peer_chunk_size,
|
|
|
|
chnk_wrp_ptr.chunk_buffs,
|
|
|
|
&(chnk_wrp_ptr.params.curr_read),
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return full_msg_ptr, nil
|
|
|
|
}
|
2023-08-10 20:58:01 +05:00
|
|
|
|
|
|
|
func (chnk_wrp_ptr *ChunkWrapper) ReadPeerChunkSize() (error) {
|
|
|
|
set_chunk_size_msg, err := chnk_wrp_ptr.ReadChunk()
|
|
|
|
if err != nil || set_chunk_size_msg.msg_type != 1 || set_chunk_size_msg.msg_len != 4 {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
chnk_wrp_ptr.params.peer_chunk_size = binary.BigEndian.Uint32(set_chunk_size_msg.data)
|
|
|
|
return nil
|
|
|
|
}
|
2023-08-10 23:53:58 +05:00
|
|
|
|
|
|
|
func (chnk_wrp_ptr *ChunkWrapper) ReadConnectCommand() (error) {
|
|
|
|
connect_cmd_msg, err := chnk_wrp_ptr.ReadChunk()
|
|
|
|
if err != nil || connect_cmd_msg.msg_type != 20 {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
amf_obj, err := amf.DecodeAMF(&(connect_cmd_msg.data))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-08-11 13:09:36 +05:00
|
|
|
tcUrl, err := amf_obj.ProcessConnect()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if chnk_wrp_ptr.params.stream_key, err = check_stream_key(tcUrl); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-08-10 23:53:58 +05:00
|
|
|
return nil
|
|
|
|
}
|
2023-08-11 13:09:36 +05:00
|
|
|
|
|
|
|
func check_stream_key(tcUrl string) (string, error) {
|
|
|
|
err := errors.New("bad stream key")
|
|
|
|
tcUrl_split := strings.Split(tcUrl, "/")
|
|
|
|
if len(tcUrl_split) != 5 {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
base_dir, _ := os.UserHomeDir()
|
|
|
|
stream_dir := base_dir + "/live/" + tcUrl_split[4]
|
|
|
|
fileinfo, err := os.Stat(stream_dir)
|
|
|
|
if err == nil && fileinfo.IsDir() {
|
|
|
|
return tcUrl_split[4], nil
|
|
|
|
}
|
|
|
|
return "", err
|
|
|
|
}
|