Wrote rtmpSetupUrl, but need to test

This commit is contained in:
saxon 2018-07-20 01:05:21 +09:30
parent e04ae76dcf
commit e5696f389d
1 changed files with 143 additions and 26 deletions

View File

@ -146,6 +146,18 @@ var setDataFrame = AVC("@setDataFrame")
var packetSize = [...]int{12, 8, 4, 1} var packetSize = [...]int{12, 8, 4, 1}
var RTMPProtocolStringsLower = [...]string{
"rtmp",
"rtmpt",
"rtmpe",
"rtmpte",
"rtmps",
"rtmpts",
"",
"",
"rtmfp",
}
// Session provides an interface for sending flv tags over rtmp. // Session provides an interface for sending flv tags over rtmp.
type Session interface { type Session interface {
Open() error Open() error
@ -318,13 +330,40 @@ func (s *session) Open() error {
return nil return nil
} }
// Close terminates the rtmp connection
func (s *session) Close() error {
if s.rtmp == nil {
return Err(3)
}
ret := endSession(s.rtmp)
s.rtmp = nil
if ret != 0 {
return Err(ret)
}
return nil
}
// Write writes a frame (flv tag) to the rtmp connection
func (s *session) Write(data []byte) (int, error) {
if s.rtmp == nil {
return 0, Err(3)
}
if C.RTMP_IsConnected(s.rtmp) == 0 {
return 0, Err(1)
}
//if C.RTMP_Write(s.rtmp,(*C.char)(unsafe.Pointer(&data[0])),C.int(len(data))) == 0 {
if rtmpWrite(s.rtmp, data) == 0 {
return 0, Err(2)
}
return len(data), nil
}
func startSession(rtmp *C.RTMP, u string, timeout uint32) (*C.RTMP, error) { func startSession(rtmp *C.RTMP, u string, timeout uint32) (*C.RTMP, error) {
url := C.CString(u)
connect_timeout := C.int(timeout) connect_timeout := C.int(timeout)
rtmp = rtmpAlloc() rtmp = rtmpAlloc()
rtmpInit(rtmp) rtmpInit(rtmp)
rtmp.Link.timeout = connect_timeout rtmp.Link.timeout = connect_timeout
if C.RTMP_SetupURL(rtmp, url) == 0 { if rtmpSetupUrl(rtmp, u) == 0 {
C.RTMP_Close(rtmp) C.RTMP_Close(rtmp)
C.RTMP_Free(rtmp) C.RTMP_Free(rtmp)
return nil, errors.New("rtmp startSession: Failed to setup URL!") return nil, errors.New("rtmp startSession: Failed to setup URL!")
@ -366,17 +405,75 @@ func rtmpInit(r *C.RTMP) {
r.Link.swfAge = 30 r.Link.swfAge = 30
} }
// Close terminates the rtmp connection func rtmpSetupUrl(r *C.RTMP, u string) int32 {
func (s *session) Close() error { length := len(u)
if s.rtmp == nil { url := goStrToCStr(u)
return Err(3)
var opt, arg AVal
var p1, p2 *byte
ptr := strchr(url, byte(' '))
var ret, len int32
var port uint32
port = 0
len = strlen(url)
ret = int32(C.RTMP_ParseURL((*C.char)(unsafe.Pointer(url)), &r.Link.protocol, &r.Link.hostname,
(*C.uint)(&port), &r.Link.playpath0, &r.Link.app))
if ret == 0 {
return ret
} }
ret := endSession(s.rtmp)
s.rtmp = nil r.Link.port = C.ushort(port)
if ret != 0 { r.Link.playpath = r.Link.playpath0
return Err(ret)
if r.Link.tcUrl.av_len == 0 {
r.Link.tcUrl.av_val = url
if r.Link.app.av_len != 0 {
if int(uintptr(unsafe.Pointer(r.Link.app.av_val))) <
int(uintptr(incBytePtr(url, len))) {
r.Link.tcUrl.av_len = r.Link.app.av_len +
int(uintptr(decBytePtr(r.Link.app.av_val, int(uintptr(unsafe.Pointer(url))))))
} else {
len = r.Link.hostname.av_len + r.Link.app.av_len +
int(unsafe.Sizeof("rtmpte://:65535/"))
r.Link.tcUrl.av_val = (*C.char)(allocate(uintptr(len)))
hostname := string(ptrToSlice(unsafe.Pointer(r.Link.hostname.av_val),
int(r.Link.hostname.av_len)))
app := string(ptrToSlice(unsafe.Pointer(r.Link.app.av_val),
int(r.Link.app.av_len)))
fString := fmt.Sprintf("%v://%v:%v/%v",
RTMPProtocolStringsLower[r.Link.protocol], hostname, r.Link.port, app)
r.Link.tcUrl.av_val = (*C.char)(goStrToCStr(fString))
r.Link.tcUrl.av_len = len(RTMPProtocolStringsLower[r.Link.protocol]) +
len(string("://")) + len(hostname) + len(string(":")) +
len(strconv.Itoa(int(r.Link.port))) + len(string("/")) + len(app)
r.Link.lFlags |= RTMP_LF_FTCU
} }
return nil } else {
r.Link.tcUrl.av_len = strlen(url)
}
}
C.SocksSetup(r, &r.Link.sockshost)
if r.Link.port == 0 {
switch {
case r.Link.Protocol & RRTMP_FEATURE_SSL:
r.Link.port = 433
case r.Link.protocol & RTMP_FEATURE_HTTP:
r.Link.port = 80
default:
r.Link.port = 1935
}
}
return 1
} }
func endSession(rtmp *C.RTMP) uint32 { func endSession(rtmp *C.RTMP) uint32 {
@ -389,21 +486,6 @@ func endSession(rtmp *C.RTMP) uint32 {
return 0 return 0
} }
// Write writes a frame (flv tag) to the rtmp connection
func (s *session) Write(data []byte) (int, error) {
if s.rtmp == nil {
return 0, Err(3)
}
if C.RTMP_IsConnected(s.rtmp) == 0 {
return 0, Err(1)
}
//if C.RTMP_Write(s.rtmp,(*C.char)(unsafe.Pointer(&data[0])),C.int(len(data))) == 0 {
if rtmpWrite(s.rtmp, data) == 0 {
return 0, Err(2)
}
return len(data), nil
}
// rtmpWrite writes data to the current rtmp connection encapsulated by r // rtmpWrite writes data to the current rtmp connection encapsulated by r
func rtmpWrite(r *C.RTMP, data []byte) int { func rtmpWrite(r *C.RTMP, data []byte) int {
buf := sliceToPtr(data) buf := sliceToPtr(data)
@ -968,6 +1050,41 @@ func avQueue(vals **C.RTMP_METHOD, num *int, av *C.AVal, txn int) {
int(unsafe.Sizeof(rtmpMethodPtr))))).name.av_val = (*C.char)(tmp) int(unsafe.Sizeof(rtmpMethodPtr))))).name.av_val = (*C.char)(tmp)
} }
func goStrToCStr(str string) *byte {
l := len(str)
slice := make([]byte, l+1)
ptr := unsafe.Pointer(&[]byte(str)[0])
for i := 0; i < l; i++ {
slice[i] = *indxBytePtr(ptr, i)
}
slice[l] = '\000'
return slice
}
func strlen(str *byte) int32 {
for i := 0; true; i++ {
ptr = indxBytePtr(unsafe.Pointer(str), i)
if *ptr == '\000' {
return i
}
}
return 0
}
func strchr(str *byte, val byte) *byte {
var ptr *byte
for i := 0; true; i++ {
ptr = indxBytePtr(unsafe.Pointer(str), i)
if *ptr == val {
return ptr
}
if *ptr == '\000' {
break
}
}
return nil
}
func allocate(nOfBytes uintptr) unsafe.Pointer { func allocate(nOfBytes uintptr) unsafe.Pointer {
mem := make([]byte, int(nOfBytes)) mem := make([]byte, int(nOfBytes))
return unsafe.Pointer(&mem[0]) return unsafe.Pointer(&mem[0])