diff --git a/rtmp/amf.go b/rtmp/amf.go index 46b3fdb7..339d6f72 100644 --- a/rtmp/amf.go +++ b/rtmp/amf.go @@ -39,6 +39,7 @@ package rtmp import "C" import ( + "encoding/binary" "log" "unsafe" ) @@ -91,26 +92,22 @@ func C_AMF_DecodeInt32(data *byte) uint32 { // void AMF_DecodeString(const char* data, C_AVal* bv); // amf.c +68 -func C_AMF_DecodeString(data *byte, bv *C_AVal) { - dataPtr := unsafe.Pointer(data) - //bv.av_len = int32(C.AMF_DecodeInt16((*byte)(dataPtr))) - bv.av_len = int32(C_AMF_DecodeInt16((*byte)(dataPtr))) - if bv.av_len > 0 { - bv.av_val = (*byte)(incBytePtr(dataPtr, 2)) - } else { - bv.av_val = nil +func C_AMF_DecodeString(data *byte) string { + n := C_AMF_DecodeInt16(data) + if n == 0 { + return "" } + return string((*[_Gi]byte)(incBytePtr(unsafe.Pointer(data), 2))[:n]) } // void AMF_DecodeLongString(const char *data, AVal *bv); // amf.c +75 -func C_AMF_DecodeLongString(data *byte, bv *C_AVal) { - bv.av_len = int32(C_AMF_DecodeInt32(data)) - if bv.av_len > 0 { - bv.av_val = (*byte)(incBytePtr(unsafe.Pointer(data), 4)) - } else { - bv.av_val = nil +func C_AMF_DecodeLongString(data *byte) string { + n := C_AMF_DecodeInt32(data) + if n == 0 { + return "" } + return string((*[_Gi]byte)(incBytePtr(unsafe.Pointer(data), 4))[:n]) } // double AMF_DecodeNumber(const char* data); @@ -128,11 +125,8 @@ func C_AMF_DecodeNumber(data *byte) float64 { // int AMF_DecodeBoolean(const char *data); // amf.c +132 -func C_AMF_DecodeBoolean(data *byte) int32 { - if *data != 0 { - return 1 - } - return 0 +func C_AMF_DecodeBoolean(data *byte) bool { + return *data != 0 } // char* AMF_EncodeInt16(char* output, char* outend, short nVal); @@ -197,33 +191,27 @@ func C_AMF_EncodeInt32(output *byte, outend *byte, nVal int32) *byte { // char* AMF_EncodeString(char* output, char* outend, const C_AVal* bv); // amf.c +174 -func C_AMF_EncodeString(output *byte, outend *byte, bv *C_AVal) *byte { - outputPtr := unsafe.Pointer(output) - outendPtr := unsafe.Pointer(outend) - if (bv.av_len < 65536 && uintptr(incBytePtr(outputPtr, 1+2+int(bv.av_len))) > - uintptr(outendPtr)) || uintptr(incBytePtr(outputPtr, 1+4+int(bv.av_len))) > - uintptr(outendPtr) { +func C_AMF_EncodeString(output *byte, outend *byte, s string) *byte { + buflen := int(uintptr(unsafe.Pointer(outend)) - uintptr(unsafe.Pointer(output))) + if len(s) < 65536 && 1+2+len(s) > buflen { return nil } - if bv.av_len < 65536 { - *(*byte)(outputPtr) = AMF_STRING - outputPtr = incBytePtr(outputPtr, 1) - // TODO: port AMF_EncodeInt16 - outputPtr = unsafe.Pointer(C_AMF_EncodeInt16((*byte)(outputPtr), (*byte)( - outendPtr), int16(bv.av_len))) - //outputPtr = unsafe.Pointer(C_AMF_EncodeInt16((*byte)(outputPtr), - //(*byte)(outendPtr), (int16)(bv.av_len))) - } else { - *(*byte)(outputPtr) = AMF_LONG_STRING - outputPtr = incBytePtr(outputPtr, 1) - outputPtr = unsafe.Pointer(C_AMF_EncodeInt32((*byte)(outputPtr), (*byte)( - outendPtr), int32(bv.av_len))) - //outputPtr = unsafe.Pointer(C_AMF_EncodeInt32((*byte)(outputPtr), - //(*byte)(outendPtr), (int32)(bv.av_len))) + if 1+4+len(s) > buflen { + return nil + } + outputPtr := unsafe.Pointer(output) + dst := (*[_Gi]byte)(unsafe.Pointer(output))[:buflen] + if len(s) < 65536 { + dst[0] = AMF_STRING + binary.BigEndian.PutUint16(dst[1:3], uint16(len(s))) + copy(dst[3:], s) + outputPtr = incBytePtr(outputPtr, 3+len(s)) + } else { + dst[0] = AMF_LONG_STRING + binary.BigEndian.PutUint32(dst[1:5], uint32(len(s))) + copy(dst[5:], s) + outputPtr = incBytePtr(outputPtr, 5+len(s)) } - memmove(unsafe.Pointer(outputPtr), unsafe.Pointer(bv.av_val), uintptr(bv.av_len)) - //C.memcpy(unsafe.Pointer(outputPtr), unsafe.Pointer(bv.av_val), (C.size_t)(bv.av_len)) - outputPtr = incBytePtr(outputPtr, int(bv.av_len)) return (*byte)(outputPtr) } @@ -249,15 +237,15 @@ func C_AMF_EncodeNumber(output *byte, outend *byte, dVal float64) *byte { // char* AMF_EncodeBoolean(char* output, char* outend, int bVal); // amf.c +260 -func C_AMF_EncodeBoolean(output *byte, outend *byte, bVal int) *byte { +func C_AMF_EncodeBoolean(output *byte, outend *byte, bVal bool) *byte { if int(uintptr(unsafe.Pointer(output)))+2 > int(uintptr(unsafe.Pointer(outend))) { return nil } *(*byte)(unsafe.Pointer(output)) = AMF_BOOLEAN output = (*byte)(incBytePtr(unsafe.Pointer(output), 1)) - val := byte(0x01) - if bVal == 0 { - val = byte(0x00) + var val byte + if bVal { + val = 1 } *(*byte)(unsafe.Pointer(output)) = val output = (*byte)(incBytePtr(unsafe.Pointer(output), 1)) @@ -266,44 +254,50 @@ func C_AMF_EncodeBoolean(output *byte, outend *byte, bVal int) *byte { // char* AMF_EncodeNamedString(char* output, char* outend, const C_AVal* strName, const C_AVal* strValue); // amf.c +273 -func C_AMF_EncodeNamedString(output *byte, outend *byte, strName *C_AVal, strValue *C_AVal) *byte { - if int(uintptr(unsafe.Pointer(output)))+2+int(strName.av_len) > int(uintptr(unsafe.Pointer(outend))) { +func C_AMF_EncodeNamedString(output *byte, outend *byte, key, val string) *byte { + buflen := int(uintptr(unsafe.Pointer(outend)) - uintptr(unsafe.Pointer(output))) + if 2+len(key) > buflen { return nil } - output = C_AMF_EncodeInt16(output, outend, int16(strName.av_len)) - memmove(unsafe.Pointer(output), unsafe.Pointer(strName.av_val), uintptr(strName.av_len)) - output = (*byte)(incBytePtr(unsafe.Pointer(output), int(strName.av_len))) - return C_AMF_EncodeString(output, outend, strValue) + dst := (*[_Gi]byte)(unsafe.Pointer(output))[:buflen] + binary.BigEndian.PutUint16(dst[:2], uint16(len(key))) + copy(dst[2:], key) + output = (*byte)(incBytePtr(unsafe.Pointer(output), 2+len(key))) + return C_AMF_EncodeString(output, outend, val) } // char* AMF_EncodeNamedNumber(char* output, char* outend, const C_AVal* strName, double dVal); // amf.c +286 -func C_AMF_EncodeNamedNumber(output *byte, outend *byte, strName *C_AVal, dVal float64) *byte { - if int(uintptr(unsafe.Pointer(output)))+2+int(strName.av_len) > int(uintptr(unsafe.Pointer(outend))) { +func C_AMF_EncodeNamedNumber(output *byte, outend *byte, key string, val float64) *byte { + buflen := int(uintptr(unsafe.Pointer(outend)) - uintptr(unsafe.Pointer(output))) + if 2+len(key) > buflen { return nil } - output = C_AMF_EncodeInt16(output, outend, int16(strName.av_len)) - memmove(unsafe.Pointer(output), unsafe.Pointer(strName.av_val), uintptr(strName.av_len)) - output = (*byte)(incBytePtr(unsafe.Pointer(output), int(strName.av_len))) - return C_AMF_EncodeNumber(output, outend, dVal) + dst := (*[_Gi]byte)(unsafe.Pointer(output))[:buflen] + binary.BigEndian.PutUint16(dst[:2], uint16(len(key))) + copy(dst[2:], key) + output = (*byte)(incBytePtr(unsafe.Pointer(output), 2+len(key))) + return C_AMF_EncodeNumber(output, outend, val) } // char* AMF_EncodeNamedBoolean(char* output, char* outend, const C_AVal* strname, int bVal); // amf.c +299 -func C_AMF_EncodeNamedBoolean(output *byte, outend *byte, strName *C_AVal, bVal int) *byte { - if int(uintptr(unsafe.Pointer(output)))+2+int(strName.av_len) > int(uintptr(unsafe.Pointer(outend))) { +func C_AMF_EncodeNamedBoolean(output *byte, outend *byte, key string, val bool) *byte { + buflen := int(uintptr(unsafe.Pointer(outend)) - uintptr(unsafe.Pointer(output))) + if 2+len(key) > buflen { return nil } - output = C_AMF_EncodeInt16(output, outend, int16(strName.av_len)) - memmove(unsafe.Pointer(output), unsafe.Pointer(strName.av_val), uintptr(strName.av_len)) - output = (*byte)(incBytePtr(unsafe.Pointer(output), int(strName.av_len))) - return C_AMF_EncodeBoolean(output, outend, bVal) + dst := (*[_Gi]byte)(unsafe.Pointer(output))[:buflen] + binary.BigEndian.PutUint16(dst[:2], uint16(len(key))) + copy(dst[2:], key) + output = (*byte)(incBytePtr(unsafe.Pointer(output), 2+len(key))) + return C_AMF_EncodeBoolean(output, outend, val) } // void AMFProp_SetName(AMFObjectProperty *prop, AVal *name); // amf.c +318 -func C_AMFProp_SetName(prop *C_AMFObjectProperty, name *C_AVal) { - prop.p_name = *name +func C_AMFProp_SetName(prop *C_AMFObjectProperty, name string) { + prop.p_name = name } // double AMFProp_GetNumber(AMFObjectProperty* prop); @@ -314,12 +308,11 @@ func C_AMFProp_GetNumber(prop *C_AMFObjectProperty) float64 { // void AMFProp_GetString(AMFObjectProperty* prop, AVal* str); // amf.c +341 -func C_AMFProp_GetString(prop *C_AMFObjectProperty, str *C_AVal) { +func C_AMFProp_GetString(prop *C_AMFObjectProperty) string { if prop.p_type == AMF_STRING { - *str = prop.p_vu.p_aval - } else { - *str = AV_empty + return prop.p_vu.p_aval } + return "" } // void AMFProp_GetObject(AMFObjectProperty *prop, AMFObject *obj); @@ -339,36 +332,30 @@ func C_AMF_PropEncode(p *C_AMFObjectProperty, pBuffer *byte, pBufEnd *byte) *byt return nil } - if p.p_type != AMF_NULL && int(uintptr(unsafe.Pointer(pBuffer)))+ - int(p.p_name.av_len)+2+1 >= int( - uintptr(unsafe.Pointer(pBufEnd))) { + buflen := int(uintptr(unsafe.Pointer(pBufEnd)) - uintptr(unsafe.Pointer(pBuffer))) + if p.p_type != AMF_NULL && len(p.p_name)+2+1 >= buflen { return nil } - if p.p_type != AMF_NULL && p.p_name.av_len != 0 { - (*[_Gi]byte)(unsafe.Pointer(pBuffer))[0] = byte(p.p_name.av_len >> 8) + if p.p_type != AMF_NULL && len(p.p_name) != 0 { + (*[_Gi]byte)(unsafe.Pointer(pBuffer))[0] = byte(len(p.p_name) >> 8) pBuffer = (*byte)(incBytePtr(unsafe.Pointer(pBuffer), 1)) - (*[_Gi]byte)(unsafe.Pointer(pBuffer))[0] = byte(p.p_name.av_len & 0xff) + (*[_Gi]byte)(unsafe.Pointer(pBuffer))[0] = byte(len(p.p_name) & 0xff) pBuffer = (*byte)(incBytePtr(unsafe.Pointer(pBuffer), 1)) - memmove(unsafe.Pointer(pBuffer), unsafe.Pointer(p.p_name.av_val), - uintptr(p.p_name.av_len)) - pBuffer = (*byte)(incBytePtr(unsafe.Pointer(pBuffer), int(p.p_name.av_len))) + copy((*[_Gi]byte)(unsafe.Pointer(pBuffer))[:], p.p_name) + pBuffer = (*byte)(incBytePtr(unsafe.Pointer(pBuffer), len(p.p_name))) } switch p.p_type { case AMF_NUMBER: pBuffer = C_AMF_EncodeNumber(pBuffer, pBufEnd, float64(p.p_vu.p_number)) case AMF_BOOLEAN: - val := 0 - if p.p_vu.p_number != 0 { - val = 1 - } - pBuffer = C_AMF_EncodeBoolean(pBuffer, pBufEnd, val) + pBuffer = C_AMF_EncodeBoolean(pBuffer, pBufEnd, p.p_vu.p_number != 0) case AMF_STRING: - pBuffer = C_AMF_EncodeString(pBuffer, pBufEnd, &p.p_vu.p_aval) + pBuffer = C_AMF_EncodeString(pBuffer, pBufEnd, p.p_vu.p_aval) case AMF_NULL: - if uintptr(incBytePtr(unsafe.Pointer(pBuffer), 1)) >= uintptr(unsafe.Pointer( - pBufEnd)) { + buflen = int(uintptr(unsafe.Pointer(pBufEnd)) - uintptr(unsafe.Pointer(pBuffer))) + if 1 >= buflen { return nil } *(*byte)(unsafe.Pointer(pBuffer)) = AMF_NULL @@ -434,7 +421,7 @@ func C_AMF3ReadInteger(data *byte, valp *int32) int32 { // int AMF3ReadString(const char *data, AVal *str); // amf.c +466 -func C_AMF3ReadString(data *byte, str *C_AVal) int32 { +func C_AMF3ReadString(data *byte, str *string) int32 { var ref int32 // assert elided - we will get a panic if it's nil. @@ -448,13 +435,11 @@ func C_AMF3ReadString(data *byte, str *C_AVal) int32 { // RTMP_Log(RTMP_LOGDEBUG, // "%s, string reference, index: %d, not supported, ignoring!", // __FUNCTION__, refIndex); - str.av_val = nil - str.av_len = 0 + *str = "" return len } else { nSize := (ref >> 1) - str.av_val = data - str.av_len = int32(nSize) + *str = string((*[_Gi]byte)(unsafe.Pointer(data))[:nSize]) return len + nSize } return len @@ -467,8 +452,7 @@ func C_AMFProp_Decode(prop *C_AMFObjectProperty, pBuffer *byte, nSize, bDecodeNa var nOriginalSize int32 = nSize var nRes int32 - prop.p_name.av_len = 0 - prop.p_name.av_val = nil + prop.p_name = "" if nSize == 0 || pBuffer == nil { // TODO use new logger here @@ -491,7 +475,7 @@ func C_AMFProp_Decode(prop *C_AMFObjectProperty, pBuffer *byte, nSize, bDecodeNa return -1 } - C_AMF_DecodeString(pBuffer, &prop.p_name) + prop.p_name = C_AMF_DecodeString(pBuffer) nSize -= int32(2 + nNameSize) pBuffer = (*byte)(incBytePtr(unsafe.Pointer(pBuffer), int(2+nNameSize))) } @@ -522,7 +506,7 @@ func C_AMFProp_Decode(prop *C_AMFObjectProperty, pBuffer *byte, nSize, bDecodeNa if int64(nSize) < int64(nStringSize)+2 { return -1 } - C_AMF_DecodeString(pBuffer, &prop.p_vu.p_aval) + prop.p_vu.p_aval = C_AMF_DecodeString(pBuffer) nSize -= int32(2 + nStringSize) case AMF_OBJECT: @@ -605,8 +589,7 @@ func C_AMFProp_Reset(prop *C_AMFObjectProperty) { prop.p_type == AMF_STRICT_ARRAY { C_AMF_Reset(&prop.p_vu.p_object) } else { - prop.p_vu.p_aval.av_len = 0 - prop.p_vu.p_aval.av_val = nil + prop.p_vu.p_aval = "" } prop.p_type = AMF_INVALID } @@ -802,18 +785,17 @@ func C_AMF_AddProp(obj *C_AMFObject, prop *C_AMFObjectProperty) { // AMFObjectProperty* AMF_GetProp(AMFObject *obj, const AVal* name, int nIndex); // amf.c + 1249 -func C_AMF_GetProp(obj *C_AMFObject, name *C_AVal, nIndex int32) *C_AMFObjectProperty { +func C_AMF_GetProp(obj *C_AMFObject, name string, nIndex int32) *C_AMFObjectProperty { if nIndex >= 0 { if nIndex < int32(obj.o_num) { return &(*(*C_AMFObjectProperty)(incPtr(unsafe.Pointer(obj.o_props), int(nIndex), int(unsafe.Sizeof(*obj.o_props))))) - //return &obj.o_props[nIndex] } } else { - var n int32 - for n = 0; n < int32(obj.o_num); n++ { - if C_AVMATCH(&(*(*C_AMFObjectProperty)(incPtr(unsafe.Pointer(obj.o_props), - int(n), int(unsafe.Sizeof(*obj.o_props))))).p_name, name) != 0 { + for n := int32(0); n < obj.o_num; n++ { + p_name := (*(*C_AMFObjectProperty)(incPtr(unsafe.Pointer(obj.o_props), + int(n), int(unsafe.Sizeof(*obj.o_props))))).p_name + if p_name == name { return &(*(*C_AMFObjectProperty)(incPtr(unsafe.Pointer(obj.o_props), int(n), int(unsafe.Sizeof(*obj.o_props))))) } diff --git a/rtmp/amf_headers.go b/rtmp/amf_headers.go index 02e5343b..8ca2d429 100644 --- a/rtmp/amf_headers.go +++ b/rtmp/amf_headers.go @@ -31,10 +31,6 @@ LICENSE */ package rtmp -import ( - "unsafe" -) - const ( AMF_NUMBER = iota AMF_BOOLEAN @@ -61,37 +57,6 @@ const ( // amf.h +40 type C_AMFDataType int32 -// typedef struct C_AVal -// amf.h +57 -type C_AVal struct { - av_val *byte - av_len int32 -} - -// C_AVal is in amf.h -// amf.h +62 -func AVC(str string) C_AVal { - var aval C_AVal - if len(str) != 0 { - aval.av_val = &([]byte(str)[0]) - } else { - aval.av_val = nil - } - aval.av_len = int32(len(str)) - return aval -} - -// #define AVMATCH(a1,a2) -// amf.h +63 -func C_AVMATCH(a1, a2 *C_AVal) int32 { - if a1.av_len == a2.av_len && memcmp(unsafe.Pointer(a1.av_val), - unsafe.Pointer(a2.av_val), int(a1.av_len)) == 0 { - return 1 - } else { - return 0 - } -} - // typedef struct AMF_Object // amf.h +67 type C_AMFObject struct { @@ -103,14 +68,14 @@ type C_AMFObject struct { // amf.h +73 type P_vu struct { p_number float64 - p_aval C_AVal + p_aval string p_object C_AMFObject } // typedef struct AMFObjectProperty // amf.h +79 type C_AMFObjectProperty struct { - p_name C_AVal + p_name string p_type C_AMFDataType p_vu P_vu p_UTCoffset int16 diff --git a/rtmp/parseurl.go b/rtmp/parseurl.go index 7af55ebb..5c8872a5 100644 --- a/rtmp/parseurl.go +++ b/rtmp/parseurl.go @@ -6,6 +6,7 @@ DESCRIPTION See Readme.md AUTHOR + Dan Kortschak Saxon Nelson-Milton LICENSE @@ -32,303 +33,71 @@ LICENSE package rtmp import ( - "fmt" "log" + "net/url" + "path" "strconv" "strings" - "unsafe" ) -// int RTMP_ParseURL(const char *url, int *protocol, AVal *host, unsigned int *port, -// AVal *playpath, AVal *app); +// int RTMP_ParseURL(const char *url, int *protocol, AVal *host, unsigned int *port, AVal *playpath, AVal *app); // parseurl.c +33 -func C_RTMP_ParseURL(url *byte, protocol *int32, host *C_AVal, port *uint32, - playpath *C_AVal, app *C_AVal) int { - - var p, end, col, ques, slash *byte - // TODO: use our logger here - // RTMP_Log(RTMP_LOGDEBUG, "Parsing..."); - - *protocol = RTMP_PROTOCOL_RTMP - *port = 0 - playpath.av_len = 0 - playpath.av_val = nil - app.av_len = 0 - app.av_val = nil - - p = strstr(url, goStrToCStr("://")) - - if p == nil { - // TODO: use our logger here - log.Println("RTMP URL: No :// in url!") - return 0 - } - /* - NOTE: the following code nees to be ported if we're using anything other than - rtmp! - { - int len = (int)(p-url); - - if(len == 4 && strncasecmp(url, "rtmp", 4)==0) - *protocol = RTMP_PROTOCOL_RTMP; - else if(len == 5 && strncasecmp(url, "rtmpt", 5)==0) - *protocol = RTMP_PROTOCOL_RTMPT; - else if(len == 5 && strncasecmp(url, "rtmps", 5)==0) - *protocol = RTMP_PROTOCOL_RTMPS; - else if(len == 5 && strncasecmp(url, "rtmpe", 5)==0) - *protocol = RTMP_PROTOCOL_RTMPE; - else if(len == 5 && strncasecmp(url, "rtmfp", 5)==0) - *protocol = RTMP_PROTOCOL_RTMFP; - else if(len == 6 && strncasecmp(url, "rtmpte", 6)==0) - *protocol = RTMP_PROTOCOL_RTMPTE; - else if(len == 6 && strncasecmp(url, "rtmpts", 6)==0) - *protocol = RTMP_PROTOCOL_RTMPTS; - else { - RTMP_Log(RTMP_LOGWARNING, "Unknown protocol!\n"); - goto parsehost; - } - } - */ - // TODO: implement new logger here - // RTMP_Log(RTMP_LOGDEBUG, "Parsed protocol: %d", *protocol); - - // Get the hostname - p = (*byte)(incBytePtr(unsafe.Pointer(p), 3)) - - // check for sudden death - if *p == 0 { - // TODO: use new logger here - // RTMP_Log(RTMP_LOGWARNING, "No hostname in URL!"); - return 0 +func C_RTMP_ParseURL(addr string) (protocol int32, host string, port uint16, app, playpath string, ok bool) { + u, err := url.Parse(addr) + if err != nil { + log.Printf("failed to parse addr: %v", err) + return protocol, host, port, app, playpath, false } - end = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + uintptr(strlen(p)))) - col = strchr(p, ':') - ques = strchr(p, '?') - slash = strchr(p, '/') - - { - var hostlen int32 - if slash != nil { - hostlen = int32(uintptr(unsafe.Pointer(slash)) - uintptr(unsafe.Pointer(p))) - } else { - hostlen = int32(uintptr(unsafe.Pointer(end)) - uintptr(unsafe.Pointer(p))) - } - if col != nil && int32(uintptr(unsafe.Pointer(col))-uintptr(unsafe.Pointer(p))) < hostlen { - hostlen = int32(uintptr(unsafe.Pointer(col)) - uintptr(unsafe.Pointer(p))) - } - - if hostlen < 256 { - host.av_val = (*byte)(unsafe.Pointer(p)) - host.av_len = hostlen - // TODO: use new logger with this - //RTMP_Log(RTMP_LOGDEBUG, "Parsed host : %.*s", hostlen, host.av_val); - } else { - // TODO: use new logger with this - // RTMP_Log(RTMP_LOGWARNING, "Hostname exceeds 255 characters!"); - } - - p = (*byte)(incBytePtr(unsafe.Pointer(p), int(hostlen))) + switch u.Scheme { + case "rtmp": + protocol = RTMP_PROTOCOL_RTMP + case "rtmpt": + protocol = RTMP_PROTOCOL_RTMPT + case "rtmps": + protocol = RTMP_PROTOCOL_RTMPS + case "rtmpe": + protocol = RTMP_PROTOCOL_RTMPE + case "rtmfp": + protocol = RTMP_PROTOCOL_RTMFP + case "rtmpte": + protocol = RTMP_PROTOCOL_RTMPTE + case "rtmpts": + protocol = RTMP_PROTOCOL_RTMPTS + default: + log.Printf("unknown scheme: %q", u.Scheme) + return protocol, host, port, app, playpath, false } - // get port number if available - if *p == ':' { - var p2 uint32 - p = (*byte)(incBytePtr(unsafe.Pointer(p), 1)) - tmp, _ := strconv.Atoi(cStrToGoStr(p)) - p2 = uint32(tmp) - if p2 > 65535 { - // TODO: use new logger with this - // RTMP_Log(RTMP_LOGWARNING, "Invalid port number!"); - } else { - *port = p2 + host = u.Host + if p := u.Port(); p != "" { + pi, err := strconv.Atoi(p) + if err != nil { + return protocol, host, port, app, playpath, false + } + port = uint16(pi) + } + + if !path.IsAbs(u.Path) { + return protocol, host, port, app, playpath, true + } + elems := strings.SplitN(u.Path[1:], "/", 3) + app = elems[0] + playpath = elems[1] + if len(elems) == 3 && len(elems[2]) != 0 { + playpath = path.Join(elems[1:]...) + switch ext := path.Ext(playpath); ext { + case ".f4v", ".mp4": + playpath = "mp4:" + playpath[:len(playpath)-len(ext)] + case ".mp3": + playpath = "mp3:" + playpath[:len(playpath)-len(ext)] + case ".flv": + playpath = playpath[:len(playpath)-len(ext)] + } + if u.RawQuery != "" { + playpath += "?" + u.RawQuery } } - if slash == nil { - // TODO: use new logger - // RTMP_Log(RTMP_LOGWARNING, "No application or playpath in URL!"); - return 1 - } - - p = (*byte)(incBytePtr(unsafe.Pointer(slash), 1)) - - { - /* parse application - * - * rtmp://host[:port]/app[/appinstance][/...] - * application = app[/appinstance] - */ - - var slash2 *byte - var slash3 *byte = nil - var slash4 *byte = nil - var applen, appnamelen int32 - - slash2 = strchr(p, '/') - - if slash2 != nil { - slash3 = strchr((*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(slash2))+ - uintptr(1))), '/') - } - if slash3 != nil { - slash4 = strchr((*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(slash3))+ - uintptr(1))), '/') - } - - // ondemand, pass all parameters as app - applen = int32(uintptr(unsafe.Pointer(end)) - uintptr(unsafe.Pointer(p))) - appnamelen = applen - - switch { - case ques != nil && strstr(p, goStrToCStr("slist=")) != nil: - appnamelen = int32(uintptr(unsafe.Pointer(ques)) - uintptr(unsafe.Pointer(p))) - case strings.Compare(cStrToGoStr(p)[:9], "ondemand/") == 0: - /* app = ondemand/foobar, only pass app=ondemand */ - applen = 8 - appnamelen = 8 - default: - switch { - case slash4 != nil: - appnamelen = int32(uintptr(unsafe.Pointer(slash4)) - uintptr( - unsafe.Pointer(p))) - case slash3 != nil: - appnamelen = int32(uintptr(unsafe.Pointer(slash3)) - uintptr( - unsafe.Pointer(p))) - case slash2 != nil: - appnamelen = int32(uintptr(unsafe.Pointer(slash2)) - uintptr( - unsafe.Pointer(p))) - } - - applen = appnamelen - } - - app.av_val = (*byte)(unsafe.Pointer(p)) - app.av_len = applen - // TODO: use new logging here - // RTMP_Log(RTMP_LOGDEBUG, "Parsed app : %.*s", applen, p); - - p = (*byte)(incBytePtr(unsafe.Pointer(p), int(appnamelen))) - } - - if *p == '/' { - p = (*byte)(incBytePtr(unsafe.Pointer(p), 1)) - } - // NOTE: don't think we currently need this section - see 787 for this func - - if int(uintptr(unsafe.Pointer(end))-uintptr(unsafe.Pointer(p))) != 0 { - var av C_AVal - av.av_val = (*byte)(unsafe.Pointer(p)) - av.av_len = int32(uintptr(unsafe.Pointer(end)) - uintptr(unsafe.Pointer(p))) - // TODO: port THis - //C.RTMP_ParsePlaypath(&av, playpath) - C_RTMP_ParsePlaypath(&av, playpath) - } - - return 1 -} - -// void RTMP_ParsePlaypath(AVal *in, AVal *out); -// parseurl.c +201 -func C_RTMP_ParsePlaypath(in, out *C_AVal) { - var addMP4 int32 = 0 - var addMP3 int32 = 0 - var subExt int32 = 0 - playpath := in.av_val - var temp, q *byte - var ext *byte = nil - ppstart := (*byte)(unsafe.Pointer(playpath)) - var streamname, destptr, p *byte - - pplen := in.av_len - - out.av_val = nil - out.av_len = 0 - - temp = strstr((*byte)(unsafe.Pointer(ppstart)), goStrToCStr("slist=")) - if *ppstart == '?' && temp != nil { - ppstart = (*byte)(incBytePtr(unsafe.Pointer(temp), 6)) - pplen = strlen(ppstart) - - temp = strchr(ppstart, '&') - - if temp != nil { - pplen = int32(uintptr(unsafe.Pointer(temp)) - uintptr(unsafe.Pointer(ppstart))) - } - } - - q = strchr(ppstart, '?') - - if pplen >= 4 { - if q != nil { - ext = (*byte)(decBytePtr(unsafe.Pointer(q), 4)) - } else { - ext = (*byte)(sliceToPtr((*[_Gi]byte)(unsafe.Pointer(ppstart))[uintptr(pplen)-4:])) - } - switch { - case strings.Compare(cStrToGoStr(ext)[:4], ".f4v") == 0 || - strings.Compare(cStrToGoStr(ext)[:4], ".mp4") == 0: - addMP4 = 1 - subExt = 1 - case ppstart == (*byte)(unsafe.Pointer(playpath)) && strings.Compare( - cStrToGoStr(ext)[:4], ".flv") == 0: - subExt = 1 - case strings.Compare(cStrToGoStr(ext)[:4], ".mp3") == 0: - addMP3 = 1 - subExt = 1 - } - } - - streamname = (*byte)(malloc(uintptr(pplen + 4 + 1))) - - if streamname == nil { - return - } - - destptr = streamname - switch { - case addMP4 != 0: - if strings.Compare(cStrToGoStr(ppstart)[:4], "mp4") != 0 { - memmove(unsafe.Pointer(destptr), unsafe.Pointer(goStrToCStr("mp4:")), - uintptr(len("mp4:"))) - destptr = (*byte)(incBytePtr(unsafe.Pointer(destptr), 4)) - } else { - subExt = 0 - } - case addMP3 != 0: - if strings.Compare(cStrToGoStr(ppstart)[:4], "mp3") != 0 { - memmove(unsafe.Pointer(destptr), unsafe.Pointer(goStrToCStr("mp3:")), - uintptr(len("mp4:"))) - destptr = (*byte)(incBytePtr(unsafe.Pointer(destptr), 4)) - } else { - subExt = 0 - } - } - - p = ppstart - for pplen > 0 { - if subExt != 0 && p == ext { - p = (*byte)(incBytePtr(unsafe.Pointer(p), 4)) - pplen -= 4 - continue - } - if *p == '%' { - var c uint32 - fmt.Sscanf(cStrToGoStr((*byte)(incBytePtr(unsafe.Pointer(p), 1))), "%02x", &c) - (*[_Gi]byte)(unsafe.Pointer(destptr))[0] = byte(c) - destptr = (*byte)(incBytePtr(unsafe.Pointer(destptr), 1)) - pplen -= 3 - p = (*byte)(incBytePtr(unsafe.Pointer(p), 3)) - } else { - (*[_Gi]byte)(unsafe.Pointer(destptr))[0] = *p - destptr = (*byte)(incBytePtr(unsafe.Pointer(destptr), 1)) - p = (*byte)(incBytePtr(unsafe.Pointer(p), 1)) - pplen-- - } - } - *destptr = '\x00' - - out.av_val = (*byte)(unsafe.Pointer(streamname)) - out.av_len = int32(uintptr(unsafe.Pointer(destptr)) - uintptr(unsafe.Pointer( - streamname))) + return protocol, host, port, app, playpath, true } diff --git a/rtmp/rtmp.go b/rtmp/rtmp.go index 8f05d953..00528432 100644 --- a/rtmp/rtmp.go +++ b/rtmp/rtmp.go @@ -35,6 +35,7 @@ package rtmp /* #include +#include #include #include #include @@ -45,11 +46,13 @@ typedef struct sockaddr sockaddr; import "C" import ( + "bytes" "errors" "fmt" "log" "math/rand" "strconv" + "strings" "time" "unsafe" @@ -64,57 +67,59 @@ const ( length = 512 ) -// av_setDataFrame is a static const global in rtmp.c -var ( - AV_empty = AVC("") - setDataFrame = AVC("@setDataFrame") - av_connect = AVC("connect") - av_app = AVC("app") - av_type = AVC("type") - av_nonprivate = AVC("nonprivate") - av_flashVer = AVC("flashVer") - av_swfUrl = AVC("swfUrl") - av_tcUrl = AVC("tcUrl") - av_fpad = AVC("fpad") - av_capabilities = AVC("capabilities") - av_audioCodecs = AVC("audioCodecs") - av_videoCodecs = AVC("videoCodecs") - av_videoFunction = AVC("videoFunction") - av_pageUrl = AVC("pageUrl") - av_objectEncoding = AVC("objectEncoding") - av__result = AVC("_result") - av_secureToken = AVC("secureToken") - av_createStream = AVC("createStream") - av_releaseStream = AVC("releaseStream") - av_play = AVC("play") - av_publish = AVC("publish") - av_onBWDone = AVC("onBWDone") - av_onFCSubscribe = AVC("onFCSubscribe") - av_onFCUnsubscribe = AVC("onFCUnsubscribe") - av__onbwcheck = AVC("_onbwcheck") - av__onbwdone = AVC("_onbwdone") - av_ping = AVC("ping") - av__checkbw = AVC("_checkbw") - av_close = AVC("close") - av_onStatus = AVC("onStatus") - av_code = AVC("code") - av_level = AVC("level") - av_NetStream_Failed = AVC("NetStream.Failed") - av_NetStream_Play_Failed = AVC("NetStream.Play.Failed") - av_NetConnection_Connect_InvalidApp = AVC("NetConnection.Connect.InvalidApp") - av_NetStream_Play_StreamNotFound = AVC("NetStream.Play.StreamNotFound") - av_NetStream_Play_Start = AVC("NetStream.Play.Start") - av_NetStream_Play_PublishNotify = AVC("NetStream.Play.PublishNotify") - av_NetStream_Publish_Start = AVC("NetStream.Publish.Start") - av_NetStream_Play_Complete = AVC("NetStream.Play.Complete") - av_NetStream_Play_Stop = AVC("NetStream.Play.Stop") - av_NetStream_Play_UnpublishNotify = AVC("NetStream.Play.UnpublishNotify") - av_NetStream_Seek_Notify = AVC("NetStream.Seek.Notify") - av_NetStream_Pause_Notify = AVC("NetStream.Pause.Notify") - av_playlist_ready = AVC("playlist_ready") - av_set_playlist = AVC("set_playlist") - av_FCPublish = AVC("FCPublish") - av_live = AVC("live") +const ( + // av_setDataFrame is a static const global in rtmp.c + setDataFrame = "@setDataFrame" + + av__checkbw = "_checkbw" + av__onbwcheck = "_onbwcheck" + av__onbwdone = "_onbwdone" + av__result = "_result" + av_app = "app" + av_audioCodecs = "audioCodecs" + av_capabilities = "capabilities" + av_close = "close" + av_code = "code" + av_connect = "connect" + av_createStream = "createStream" + av_deleteStream = "deleteStream" + av_FCPublish = "FCPublish" + av_FCUnpublish = "FCUnpublish" + av_flashVer = "flashVer" + av_fpad = "fpad" + av_level = "level" + av_live = "live" + av_NetConnection_Connect_InvalidApp = "NetConnection.Connect.InvalidApp" + av_NetStream_Failed = "NetStream.Failed" + av_NetStream_Pause_Notify = "NetStream.Pause.Notify" + av_NetStream_Play_Complete = "NetStream.Play.Complete" + av_NetStream_Play_Failed = "NetStream.Play.Failed" + av_NetStream_Play_PublishNotify = "NetStream.Play.PublishNotify" + av_NetStream_Play_Start = "NetStream.Play.Start" + av_NetStream_Play_Stop = "NetStream.Play.Stop" + av_NetStream_Play_StreamNotFound = "NetStream.Play.StreamNotFound" + av_NetStream_Play_UnpublishNotify = "NetStream.Play.UnpublishNotify" + av_NetStream_Publish_Start = "NetStream.Publish.Start" + av_NetStream_Seek_Notify = "NetStream.Seek.Notify" + av_nonprivate = "nonprivate" + av_objectEncoding = "objectEncoding" + av_onBWDone = "onBWDone" + av_onFCSubscribe = "onFCSubscribe" + av_onFCUnsubscribe = "onFCUnsubscribe" + av_onStatus = "onStatus" + av_pageUrl = "pageUrl" + av_ping = "ping" + av_play = "play" + av_playlist_ready = "playlist_ready" + av_publish = "publish" + av_releaseStream = "releaseStream" + av_secureToken = "secureToken" + av_set_playlist = "set_playlist" + av_swfUrl = "swfUrl" + av_tcUrl = "tcUrl" + av_type = "type" + av_videoCodecs = "videoCodecs" + av_videoFunction = "videoFunction" ) var RTMPT_cmds = []string{ @@ -142,31 +147,24 @@ var ( func startSession(rtmp *C_RTMP, u string, timeout uint32) (*C_RTMP, error) { connect_timeout := int32(timeout) rtmp = C_RTMP_Alloc() - //rtmp = C.RTMP_Alloc() C_RTMP_Init(rtmp) - //C.RTMP_Init(rtmp) rtmp.Link.timeout = connect_timeout - if C_RTMP_SetupURL(rtmp, u) == 0 { - // if C.RTMP_SetupURL(rtmp, C.CString(u)) == 0 { + if !C_RTMP_SetupURL(rtmp, u) { C_RTMP_Close(rtmp) //C.RTMP_Free(rtmp) return nil, errors.New("rtmp startSession: Failed to setup URL!") } C_RTMP_EnableWrite(rtmp) - //C.RTMP_EnableWrite(rtmp) C_RTMP_SetBufferMS(rtmp, 3600*1000) - //C.RTMP_SetBufferMS(rtmp, 3600*1000) - if C_RTMP_Connect(rtmp, nil) == 0 { - //if C.RTMP_Connect(rtmp, nil) == 0 { + if !C_RTMP_Connect(rtmp, nil) { C_RTMP_Close(rtmp) //C.RTMP_Free(rtmp) return nil, errors.New("rtmp startSession: Failed to connect!") } // TODO: port this - if C_RTMP_ConnectStream(rtmp, 0) == 0 { - //if C.RTMP_ConnectStream(rtmp, 0) == 0 { + if !C_RTMP_ConnectStream(rtmp, 0) { C_RTMP_Close(rtmp) //C.RTMP_Free(rtmp) return nil, errors.New("rtmp startSession: Failed to connect stream!") @@ -193,7 +191,7 @@ func C_RTMP_GetTime() int32 { // int RTMPPacket_Alloc(RTMPPacket* p, uint32_t nSize); // rtmp.c +189 -func C_RTMPPacket_Alloc(p *C_RTMPPacket, nSize uint32) int { +func C_RTMPPacket_Alloc(p *C_RTMPPacket, nSize uint32) (ok bool) { var ptr *byte // TODO: port C.SIZE_MAX // also work out how to deal with the overfloat @@ -205,18 +203,17 @@ func C_RTMPPacket_Alloc(p *C_RTMPPacket, nSize uint32) int { ptr = (*byte)(calloc(1, uintptr(nSize+RTMP_MAX_HEADER_SIZE))) if ptr == nil { - return 0 + return false } p.m_body = (*byte)(incBytePtr(unsafe.Pointer(ptr), RTMP_MAX_HEADER_SIZE)) p.m_nBytesRead = 0 - return 1 + return true } // void RTMPPacket_Free(RTMPPacket* p); // rtmp.c +203 func C_RTMPPacket_Free(p *C_RTMPPacket) { if p.m_body != nil { - //C.free(decBytePtr(unsafe.Pointer(p.m_body), RTMP_MAX_HEADER_SIZE)) p.m_body = nil } } @@ -225,7 +222,6 @@ func C_RTMPPacket_Free(p *C_RTMPPacket) { // rtmp.c +317 func C_RTMP_Alloc() *C_RTMP { return &C_RTMP{} - //return (*C_RTMP)(allocate(unsafe.Sizeof(r))) } // void RTMP_Init(RTMP *r); @@ -268,31 +264,21 @@ func C_RTMP_SetBufferMS(r *C_RTMP, size int32) { // void SocksSetup(RTMP *r, C_AVal* sockshost); // rtmp.c +410 -func C_SocksSetup(r *C_RTMP, sockshost *C_AVal) { - if sockshost.av_len != 0 { - socksport := strchr((*byte)(unsafe.Pointer(sockshost.av_val)), ':') - hostname := strdup((*byte)(unsafe.Pointer(sockshost.av_val))) - - if unsafe.Pointer(socksport) != nil { - (*[_Gi]byte)(unsafe.Pointer(hostname))[uintptr(decBytePtr(unsafe.Pointer(socksport), - int(uintptr(unsafe.Pointer(sockshost.av_val)))))] = '\000' - r.Link.sockshost.av_val = (*byte)(unsafe.Pointer(hostname)) - r.Link.sockshost.av_len = int32(strlen(hostname)) - - value, err := strconv.Atoi(string((*[_Gi]byte)(unsafe.Pointer(uintptr( - unsafe.Pointer(socksport)) + uintptr(1)))[:strlen((*byte)(unsafe.Pointer( - uintptr(unsafe.Pointer(socksport))+uintptr(1))))+1])) +func C_SocksSetup(r *C_RTMP, sockshost string) { + if sockshost != "" { + p := strings.SplitN(sockshost, ":", 2) + r.Link.sockshost = p[0] + r.Link.socksport = 1080 + if len(p) != 1 { + port, err := strconv.Atoi(p[1]) if err != nil { + port = 1080 log.Println("C_SocksSetup: bad string conversion!") } - if uintptr(unsafe.Pointer(socksport)) == 0 { - value = 1080 - } - r.Link.socksport = uint16(value) + r.Link.socksport = uint16(port) } } else { - r.Link.sockshost.av_val = nil - r.Link.sockshost.av_len = 0 + r.Link.sockshost = "" r.Link.socksport = 0 } } @@ -300,61 +286,24 @@ func C_SocksSetup(r *C_RTMP, sockshost *C_AVal) { // int RTMP_SetupURL(RTMP *r, char* url); // rtmp.c +757 // NOTE: code dealing with rtmp over http has been disregarded -func C_RTMP_SetupURL(r *C_RTMP, u string) int32 { - url := goStrToCStr(u) - - var ret, length int32 - var port uint32 - port = 0 - - length = strlen(url) - // TODO: port this - //ret = int32(C.RTMP_ParseURL((*byte)(unsafe.Pointer(url)), &r.Link.protocol, - // &r.Link.hostname, (*C.uint)(&port), &r.Link.playpath0, &r.Link.app)) - ret = int32(C_RTMP_ParseURL((*byte)(unsafe.Pointer(url)), (*int32)( - unsafe.Pointer(&r.Link.protocol)), &r.Link.hostname, (*uint32)( - unsafe.Pointer(&port)), &r.Link.playpath0, &r.Link.app)) - if ret == 0 { - return ret +func C_RTMP_SetupURL(r *C_RTMP, addr string) (ok bool) { + r.Link.protocol, r.Link.hostname, r.Link.port, r.Link.app, r.Link.playpath0, ok = C_RTMP_ParseURL(addr) + if !ok { + return false } - - r.Link.port = uint16(port) r.Link.playpath = r.Link.playpath0 - if r.Link.tcUrl.av_len == 0 { - r.Link.tcUrl.av_val = (*byte)(unsafe.Pointer(url)) - if r.Link.app.av_len != 0 { - if int(uintptr(unsafe.Pointer(r.Link.app.av_val))) < - int(uintptr(incBytePtr(unsafe.Pointer(url), int(length)))) { - - r.Link.tcUrl.av_len = int32(int(r.Link.app.av_len) + - int(uintptr(decBytePtr(unsafe.Pointer(r.Link.app.av_val), - int(uintptr(unsafe.Pointer(url))))))) - } else { - length = int32(r.Link.hostname.av_len) + int32(r.Link.app.av_len) + - int32(len("rtmpte://:65535/\x00")) - - r.Link.tcUrl.av_val = (*byte)(malloc(uintptr(uintptr(length)))) - hostname := string((*[_Gi]byte)(unsafe.Pointer(r.Link.hostname.av_val))[:r.Link.hostname.av_len]) - - app := string((*[_Gi]byte)(unsafe.Pointer(r.Link.app.av_val))[: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 = (*byte)(bToUP(goStrToCStr(fString))) - r.Link.tcUrl.av_len = int32(strLen(RTMPProtocolStringsLower[r.Link.protocol]) + - strLen(string("://")) + strLen(hostname) + strLen(string(":")) + - strLen(strconv.Itoa(int(r.Link.port))) + strLen(string("/")) + strLen(app)) - - r.Link.lFlags |= RTMP_LF_FTCU - } + if r.Link.tcUrl == "" { + if r.Link.app != "" { + r.Link.tcUrl = fmt.Sprintf("%v://%v:%v/%v", + RTMPProtocolStringsLower[r.Link.protocol], r.Link.hostname, r.Link.port, r.Link.app) + r.Link.lFlags |= RTMP_LF_FTCU } else { - r.Link.tcUrl.av_len = int32(strlen(url)) + r.Link.tcUrl = addr } } - C_SocksSetup(r, &r.Link.sockshost) + C_SocksSetup(r, r.Link.sockshost) if r.Link.port == 0 { switch { @@ -366,39 +315,30 @@ func C_RTMP_SetupURL(r *C_RTMP, u string) int32 { r.Link.port = 1935 } } - return 1 + return true } // int add_addr_info(struct sockaddr_in *service, AVal *host, int port) // rtmp.c +869 -func C_add_addr_info(service *C.sockaddr_in, host *C_AVal, port C.int) int32 { - var hostname *byte - if (*[1 << 20]byte)(unsafe.Pointer(host.av_val))[host.av_len] != 0 { - name := make([]byte, host.av_len+1) - copy(name, (*[1 << 20]byte)(unsafe.Pointer(host.av_val))[:host.av_len]) - name[len(name)-1] = 0 - hostname = (*byte)(unsafe.Pointer(&name[0])) - } else { - hostname = host.av_val - } - - service.sin_addr.s_addr = C.inet_addr((*C.char)(unsafe.Pointer(hostname))) +func C_add_addr_info(service *C.sockaddr_in, hostname string, port uint16) (ok bool) { + h := (*C.char)(unsafe.Pointer(goStrToCStr(hostname))) + service.sin_addr.s_addr = C.inet_addr(h) if service.sin_addr.s_addr == C.INADDR_NONE { - host := C.gethostbyname((*C.char)(unsafe.Pointer(hostname))) + host := C.gethostbyname(h) if host == nil || *host.h_addr_list == nil { //RTMP_Log(RTMP_LOGERROR, "Problem accessing the DNS. (addr: %s)", hostname) - return 0 + return false } service.sin_addr = *(*C.struct_in_addr)(unsafe.Pointer(*host.h_addr_list)) } - service.sin_port = C.ushort(inet.Htons(uint16(port))) - return 1 + service.sin_port = C.ushort(inet.Htons(port)) + return true } // int RTMP_Connect0(RTMP *r, struct sockaddr* service); // rtmp.c +906 -func C_RTMP_Connect0(r *C_RTMP, service *C.sockaddr) int { +func C_RTMP_Connect0(r *C_RTMP, service *C.sockaddr) (ok bool) { on := 1 r.m_sb.sb_timedout = 0 r.m_pausing = 0 @@ -416,21 +356,19 @@ func C_RTMP_Connect0(r *C_RTMP, service *C.sockaddr) int { log.Println("C_RTMP_Connect0: socks negotiation.") } - //if C.SocksNegotiate(r) == 0 { - if C_SocksNegotiate(r) == 0 { + if !C_SocksNegotiate(r) { log.Println("C_RTMP_Connect0: SOCKS negotiation failed.") - return 0 + return false } } } else { log.Println("C_RTMP_Connect0: failed to create socket.") - return 0 + return false } { var tv int32 SET_RCVTIMEO(&tv, int32(r.Link.timeout)) - // tv := int32(r.Link.timeout * 1000) if C.setsockopt(C.int(r.m_sb.sb_socket), C.SOL_SOCKET, C.SO_RCVTIMEO, unsafe.Pointer(&tv), C.socklen_t(unsafe.Sizeof(tv))) != 0 { @@ -441,39 +379,37 @@ func C_RTMP_Connect0(r *C_RTMP, service *C.sockaddr) int { C.setsockopt(C.int(r.m_sb.sb_socket), C.IPPROTO_TCP, C.TCP_NODELAY, unsafe.Pointer(&on), C.socklen_t(unsafe.Sizeof(on))) - return 1 + return true } // int RTMP_Connect1(RTMP* r, RTMPPacket* cp); // rtmp.c +978 -func C_RTMP_Connect1(r *C_RTMP, cp *C_RTMPPacket) int { +func C_RTMP_Connect1(r *C_RTMP, cp *C_RTMPPacket) (ok bool) { if debugMode { log.Println("... connected, handshaking...") } - //if C.HandShake(r, 1) == 0 { - if C_HandShake(r, 1) == 0 { + if !C_HandShake(r, 1) { log.Println("C_RTMP_Connect1: handshake failed!") - return 0 + return false } if debugMode { log.Println("... handshaked...") } - //if C.SendConnectPacket(r, cp) == 0 { - if C_SendConnectPacket(r, cp) == 0 { + if !C_SendConnectPacket(r, cp) { log.Println("RTMP connect failed!") - return 0 + return false } - return 1 + return true } // int RTMP_Connect(RTMP *r, RTMPPacket* cp); // rtmp.c +1032 -func C_RTMP_Connect(r *C_RTMP, cp *C_RTMPPacket) int { +func C_RTMP_Connect(r *C_RTMP, cp *C_RTMPPacket) (ok bool) { // TODO: port this var service C.sockaddr_in - if r.Link.hostname.av_len == 0 { - return 0 + if r.Link.hostname == "" { + return false } memset((*byte)(unsafe.Pointer(&service)), 0, int(unsafe.Sizeof(service))) @@ -481,36 +417,33 @@ func C_RTMP_Connect(r *C_RTMP, cp *C_RTMPPacket) int { service.sin_family = C.AF_INET if r.Link.socksport != 0 { - if C_add_addr_info(&service, (*C_AVal)(unsafe.Pointer(&r.Link.sockshost)), C.int(r.Link.socksport)) == 0 { - return 0 + if !C_add_addr_info(&service, r.Link.sockshost, r.Link.socksport) { + return false } } else { // connect directly - if C_add_addr_info(&service, (*C_AVal)(unsafe.Pointer(&r.Link.hostname)), - C.int(r.Link.port)) == 0 { - return 0 + if !C_add_addr_info(&service, r.Link.hostname, r.Link.port) { + return false } } - //if C.RTMP_Connect0(r, (*C.sockaddr)(unsafe.Pointer(&service))) == 0 { - if C_RTMP_Connect0(r, (*C.sockaddr)(unsafe.Pointer(&service))) == 0 { - return 0 + if !C_RTMP_Connect0(r, (*C.sockaddr)(unsafe.Pointer(&service))) { + return false } r.m_bSendCounter = 1 - return int(C_RTMP_Connect1(r, cp)) - //return int(C.RTMP_Connect1(r, cp)) + return C_RTMP_Connect1(r, cp) } // int SocksNegotiate(RTMP* r); // rtmp.c +1062 -func C_SocksNegotiate(r *C_RTMP) int { +func C_SocksNegotiate(r *C_RTMP) (ok bool) { var addr int32 var service C.sockaddr_in memset((*byte)(unsafe.Pointer(&service)), 0, int(unsafe.Sizeof(service))) - C_add_addr_info(&service, (*C_AVal)(unsafe.Pointer(&r.Link.hostname)), C.int(r.Link.port)) + C_add_addr_info(&service, r.Link.hostname, r.Link.port) addr = int32(inet.Htonl(uint32(service.sin_addr.s_addr))) { @@ -526,22 +459,22 @@ func C_SocksNegotiate(r *C_RTMP) int { C_WriteN(r, unsafe.Pointer(&packet[0]), int(unsafe.Sizeof(packet))) if C_ReadN(r, &packet[0], 8) != 8 { - return 0 + return false } if packet[0] == 0 && packet[1] == 90 { - return 1 + return true } else { // TODO: use new logger here log.Println("C_SocksNegotitate: SOCKS returned error code!") - return 0 + return false } } } // int RTMP_ConnectStream(RTMP* r, int seekTime); // rtmp.c +1099 -func C_RTMP_ConnectStream(r *C_RTMP, seekTime int32) int { +func C_RTMP_ConnectStream(r *C_RTMP, seekTime int32) (playing bool) { var packet C_RTMPPacket memset((*byte)(unsafe.Pointer(&packet)), 0, int(unsafe.Sizeof(packet))) @@ -552,12 +485,9 @@ func C_RTMP_ConnectStream(r *C_RTMP, seekTime int32) int { r.m_mediaChannel = 0 // TODO: read packet - for r.m_bPlaying == 0 && C_RTMP_IsConnected(r) != 0 && - //C.RTMP_ReadPacket(r, &packet) != 0 { - C_RTMP_ReadPacket(r, &packet) != 0 { - + for !r.m_bPlaying && C_RTMP_IsConnected(r) != 0 && C_RTMP_ReadPacket(r, &packet) { // TODO: port is ready - if C_RTMPPacket_IsReady(&packet) != 0 { + if C_RTMPPacket_IsReady(&packet) { if packet.m_nBodySize == 0 { continue } @@ -570,24 +500,22 @@ func C_RTMP_ConnectStream(r *C_RTMP, seekTime int32) int { continue } - //C.RTMP_ClientPacket(r, &packet) C_RTMP_ClientPacket(r, &packet) C_RTMPPacket_Free(&packet) } } - return int(r.m_bPlaying) + return r.m_bPlaying } // int RTMP_ClientPacket() // rtmp.c +1226 // NOTE cases have been commented out that are not currently used by AusOcean func C_RTMP_ClientPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { - var bHasMediaPacket int32 = 0 + var bHasMediaPacket int32 switch packet.m_packetType { case RTMP_PACKET_TYPE_CHUNK_SIZE: // TODO: port this - //C.HandleChangeChunkSize(r, packet) C_HandleChangeChunkSize(r, packet) case RTMP_PACKET_TYPE_BYTES_READ_REPORT: @@ -603,12 +531,10 @@ func C_RTMP_ClientPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { */ case RTMP_PACKET_TYPE_SERVER_BW: // TODO: port this - //C.HandleServerBW(r, packet) C_HandlServerBW(r, packet) case RTMP_PACKET_TYPE_CLIENT_BW: // TODO: port this - //C.HandleClientBW(r, packet) C_HandleClientBW(r, packet) case RTMP_PACKET_TYPE_AUDIO: @@ -628,8 +554,8 @@ func C_RTMP_ClientPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { // TODO use new logger here //RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %u bytes", __FUNCTION__,packet.m_nBodySize); - //if C.HandleInvoke(r, packet.m_body, C.uint(packet.m_nBodySize)) == 1 { - if C_HandleInvoke(r, (*byte)(unsafe.Pointer(packet.m_body)), uint32(packet.m_nBodySize)) == 1 { + if C_HandleInvoke(r, (*byte)(unsafe.Pointer(packet.m_body)), uint32(packet.m_nBodySize)) { + // This will never happen with the methods we implement. log.Println("HasMediaPacket") bHasMediaPacket = 2 } @@ -662,7 +588,6 @@ func C_ReadN(r *C_RTMP, buffer *byte, n int) int { avail = int(r.m_sb.sb_size) if avail == 0 { if C_RTMPSockBuf_Fill(&r.m_sb) < 1 { - // if C.RTMPSockBuf_Fill(&r.m_sb) < 1 { if r.m_sb.sb_timedout == 0 { return 0 } @@ -685,8 +610,7 @@ func C_ReadN(r *C_RTMP, buffer *byte, n int) int { r.m_nBytesIn += int32(nRead) if r.m_bSendCounter != 0 && r.m_nBytesIn > (r.m_nBytesInSent+ r.m_nClientBW/10) { - //if C.SendBytesReceived(r) == 0 { - if C_SendBytesReceived(r) == 0 { + if !C_SendBytesReceived(r) { return 0 } } @@ -707,7 +631,7 @@ func C_ReadN(r *C_RTMP, buffer *byte, n int) int { // int WriteN(RTMP* r, const char* buffer, int n); // rtmp.c +1502 -func C_WriteN(r *C_RTMP, buffer unsafe.Pointer, n int) int { +func C_WriteN(r *C_RTMP, buffer unsafe.Pointer, n int) (ok bool) { ptr := buffer for n > 0 { var nBytes int @@ -733,15 +657,13 @@ func C_WriteN(r *C_RTMP, buffer unsafe.Pointer, n int) int { ptr = incBytePtr(ptr, nBytes) } - if n == 0 { - return 1 - } - return 0 + // !ok here is equivalent to io.ErrShortWrite. + return n == 0 } // int SendConnectPacket(RTMP* r, RTMPPacket* cp); // rtmp.c +1579 -func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) int { +func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) (ok bool) { var packet C_RTMPPacket var pbuf [4096]byte pend := (*byte)(unsafe.Pointer(incBytePtr(unsafe.Pointer(&pbuf[0]), @@ -750,7 +672,6 @@ func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) int { if cp != nil { return C_RTMP_SendPacket(r, cp, 1) - //return int(C.RTMP_SendPacket(r, cp, 1)) } packet.m_nChannel = 0x03 @@ -759,118 +680,89 @@ func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) int { packet.m_nTimeStamp = 0 packet.m_nInfoField2 = 0 packet.m_hasAbsTimestamp = 0 - packet.m_body = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), - RTMP_MAX_HEADER_SIZE)) + packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] enc = (*byte)(unsafe.Pointer(packet.m_body)) - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeString((*byte)(unsafe.Pointer(enc)), - //(*byte)(unsafe.Pointer(pend)), &av_connect))) - enc = C_AMF_EncodeString(enc, pend, &av_connect) + enc = C_AMF_EncodeString(enc, pend, av_connect) + r.m_numInvokes += 1 - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNumber((*byte)(unsafe.Pointer(enc)), - //(*byte)(unsafe.Pointer(pend)), float64(r.m_numInvokes)))) enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) (*[_Gi]byte)(unsafe.Pointer(enc))[0] = AMF_OBJECT enc = (*byte)(unsafe.Pointer(incBytePtr(unsafe.Pointer(enc), 1))) - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*byte)( - //unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_app, &r.Link.app))) - enc = C_AMF_EncodeNamedString(enc, pend, &av_app, &r.Link.app) + enc = C_AMF_EncodeNamedString(enc, pend, av_app, r.Link.app) if enc == nil { - return 0 + return false } if r.Link.protocol&RTMP_FEATURE_WRITE != 0 { - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*byte)( - //unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_type, &av_nonprivate))) - enc = C_AMF_EncodeNamedString(enc, pend, &av_type, &av_nonprivate) - + enc = C_AMF_EncodeNamedString(enc, pend, av_type, av_nonprivate) if enc == nil { - return 0 + return false } } - if r.Link.flashVer.av_len != 0 { - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*byte)( - //unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_flashVer, &r.Link.flashVer))) - enc = C_AMF_EncodeNamedString(enc, pend, &av_flashVer, &r.Link.flashVer) + if r.Link.flashVer != "" { + enc = C_AMF_EncodeNamedString(enc, pend, av_flashVer, r.Link.flashVer) if enc == nil { - return 0 + return false } } - if r.Link.swfUrl.av_len != 0 { - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*byte)( - // unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_swfUrl, &r.Link.swfUrl))) - enc = C_AMF_EncodeNamedString(enc, pend, &av_swfUrl, &r.Link.swfUrl) + if r.Link.swfUrl != "" { + enc = C_AMF_EncodeNamedString(enc, pend, av_swfUrl, r.Link.swfUrl) if enc == nil { - return 0 + return false } } - if r.Link.tcUrl.av_len != 0 { - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*byte)( - //unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_tcUrl, &r.Link.tcUrl))) - enc = C_AMF_EncodeNamedString(enc, pend, &av_tcUrl, &r.Link.tcUrl) + if r.Link.tcUrl != "" { + enc = C_AMF_EncodeNamedString(enc, pend, av_tcUrl, r.Link.tcUrl) if enc == nil { - return 0 + return false } } if r.Link.protocol&RTMP_FEATURE_WRITE == 0 { - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedBoolean((*byte)( - //unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_fpad, 0))) - enc = C_AMF_EncodeNamedBoolean(enc, pend, &av_fpad, 0) + enc = C_AMF_EncodeNamedBoolean(enc, pend, av_fpad, false) if enc == nil { - return 0 + return false } - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*byte)( - //unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_capabilities, 15.0))) - enc = C_AMF_EncodeNamedNumber(enc, pend, &av_capabilities, 15.0) + enc = C_AMF_EncodeNamedNumber(enc, pend, av_capabilities, 15) if enc == nil { - return 0 + return false } - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*byte)( - // unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_audioCodecs, r.m_fAudioCodecs))) - enc = C_AMF_EncodeNamedNumber(enc, pend, &av_audioCodecs, float64(r.m_fAudioCodecs)) + enc = C_AMF_EncodeNamedNumber(enc, pend, av_audioCodecs, float64(r.m_fAudioCodecs)) if enc == nil { - return 0 + return false } - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*byte)( - //unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_videoCodecs, r.m_fVideoCodecs))) - enc = C_AMF_EncodeNamedNumber(enc, pend, &av_videoCodecs, float64(r.m_fVideoCodecs)) + enc = C_AMF_EncodeNamedNumber(enc, pend, av_videoCodecs, float64(r.m_fVideoCodecs)) if enc == nil { - return 0 + return false } - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*byte)( - // unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_videoFunction, 1.0))) - enc = C_AMF_EncodeNamedNumber(enc, pend, &av_videoFunction, 1.0) + enc = C_AMF_EncodeNamedNumber(enc, pend, av_videoFunction, 1) if enc == nil { - return 0 + return false } - if r.Link.pageUrl.av_len != 0 { - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*byte)( - //unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_pageUrl, &r.Link.pageUrl))) - enc = C_AMF_EncodeNamedString(enc, pend, &av_pageUrl, &r.Link.pageUrl) + if r.Link.pageUrl != "" { + enc = C_AMF_EncodeNamedString(enc, pend, av_pageUrl, r.Link.pageUrl) if enc == nil { - return 0 + return false } } } if r.m_fEncoding != 0.0 || r.m_bSendEncoding != 0 { - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*byte)( - //unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), &av_objectEncoding, r.m_fEncoding))) - enc = C_AMF_EncodeNamedNumber(enc, pend, &av_objectEncoding, float64(r.m_fEncoding)) + enc = C_AMF_EncodeNamedNumber(enc, pend, av_objectEncoding, float64(r.m_fEncoding)) if enc == nil { - return 0 + return false } } if int(uintptr(incBytePtr(unsafe.Pointer(enc), 3))) >= int(uintptr( unsafe.Pointer(pend))) { - return 0 + return false } (*[_Gi]byte)(unsafe.Pointer(enc))[0] = 0 @@ -881,33 +773,25 @@ func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) int { enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) /* add auth string */ - if r.Link.auth.av_len != 0 { - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeBoolean((*byte)( - // unsafe.Pointer(enc)), (*byte)(unsafe.Pointer(pend)), r.Link.lFlags&RTMP_LF_AUTH))) - enc = C_AMF_EncodeBoolean(enc, pend, int(r.Link.lFlags&RTMP_LF_AUTH)) + if r.Link.auth != "" { + enc = C_AMF_EncodeBoolean(enc, pend, r.Link.lFlags&RTMP_LF_AUTH != 0) if enc == nil { - return 0 + return false } - //enc = (*byte)(unsafe.Pointer(C.AMF_EncodeString((*byte)(unsafe.Pointer(enc)), - //(*byte)(unsafe.Pointer(pend)), &r.Link.auth))) - enc = C_AMF_EncodeString(enc, (*byte)(pend), &r.Link.auth) + enc = C_AMF_EncodeString(enc, (*byte)(pend), r.Link.auth) if enc == nil { - return 0 + return false } } if r.Link.extras.o_num != 0 { for i := 0; i < int(r.Link.extras.o_num); i++ { - //enc = (*byte)(unsafe.Pointer(C.AMFProp_Encode((*C_AMFObjectProperty)( - //incPtr(unsafe.Pointer(&r.Link.extras.o_props), int(unsafe.Sizeof( - //r.Link.extras.o_props)), i)), (*byte)(unsafe.Pointer(enc)), (*byte)( - //unsafe.Pointer(pend))))) enc = C_AMF_PropEncode((*C_AMFObjectProperty)(incPtr(unsafe.Pointer( &r.Link.extras.o_props), int(unsafe.Sizeof(r.Link.extras.o_props)), i)), enc, pend) if enc == nil { - return 0 + return false } } } @@ -915,13 +799,12 @@ func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) int { packet.m_nBodySize = uint32(uintptr(decBytePtr(unsafe.Pointer(enc), int(uintptr(unsafe.Pointer(packet.m_body)))))) - //return int(C.RTMP_SendPacket(r, &packet, 1)) return C_RTMP_SendPacket(r, &packet, 1) } // int RTMP_SendCreateStream(RTMP* r); // rtmp.c +1725 -func C_RTMP_SendCreateStream(r *C_RTMP) int32 { +func C_RTMP_SendCreateStream(r *C_RTMP) (ok bool) { var packet C_RTMPPacket var pbuf [256]byte var pend *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&pbuf[0])) + @@ -934,11 +817,10 @@ func C_RTMP_SendCreateStream(r *C_RTMP) int32 { packet.m_nTimeStamp = 0 packet.m_nInfoField2 = 0 packet.m_hasAbsTimestamp = 0 - packet.m_body = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), - int(RTMP_MAX_HEADER_SIZE))) + packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = C_AMF_EncodeString(enc, pend, &av_createStream) + enc = C_AMF_EncodeString(enc, pend, av_createStream) r.m_numInvokes++ enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) *enc = AMF_NULL @@ -947,12 +829,12 @@ func C_RTMP_SendCreateStream(r *C_RTMP) int32 { packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( unsafe.Pointer(packet.m_body))) - return int32(C_RTMP_SendPacket(r, &packet, 1)) + return C_RTMP_SendPacket(r, &packet, 1) } // int SendReleaseStream(RTMP* r); // rtmp.c +1816 -func C_SendReleaseStream(r *C_RTMP) int32 { +func C_SendReleaseStream(r *C_RTMP) (ok bool) { var packet C_RTMPPacket var pbuf [1024]byte var pend *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&pbuf[0])) + @@ -965,28 +847,27 @@ func C_SendReleaseStream(r *C_RTMP) int32 { packet.m_nTimeStamp = 0 packet.m_nInfoField2 = 0 packet.m_hasAbsTimestamp = 0 - packet.m_body = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), - int(RTMP_MAX_HEADER_SIZE))) + packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = C_AMF_EncodeString(enc, pend, &av_releaseStream) + enc = C_AMF_EncodeString(enc, pend, av_releaseStream) r.m_numInvokes++ enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) *enc = AMF_NULL enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) - enc = C_AMF_EncodeString(enc, pend, &r.Link.playpath) + enc = C_AMF_EncodeString(enc, pend, r.Link.playpath) if enc == nil { - return 0 + return false } packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( unsafe.Pointer(packet.m_body))) - return int32(C_RTMP_SendPacket(r, &packet, 0)) + return C_RTMP_SendPacket(r, &packet, 0) } // int SendFCPublish(RTMP* r); // rtmp.c +1846 -func C_SendFCPublish(r *C_RTMP) int32 { +func C_SendFCPublish(r *C_RTMP) (ok bool) { var packet C_RTMPPacket var pbuf [1024]byte var pend *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&pbuf[0])) + @@ -999,64 +880,62 @@ func C_SendFCPublish(r *C_RTMP) int32 { packet.m_nTimeStamp = 0 packet.m_nInfoField2 = 0 packet.m_hasAbsTimestamp = 0 - packet.m_body = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), - int(RTMP_MAX_HEADER_SIZE))) + packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = C_AMF_EncodeString(enc, pend, &av_FCPublish) + enc = C_AMF_EncodeString(enc, pend, av_FCPublish) r.m_numInvokes++ enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) *enc = AMF_NULL enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) - enc = C_AMF_EncodeString(enc, pend, &r.Link.playpath) + enc = C_AMF_EncodeString(enc, pend, r.Link.playpath) if enc == nil { - return 0 + return false } packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( unsafe.Pointer(packet.m_body))) - return int32(C_RTMP_SendPacket(r, &packet, 0)) + return C_RTMP_SendPacket(r, &packet, 0) } // int SendFCUnpublish(RTMP *r); // rtmp.c +1875 -func C_SendFCUnpublish(r *C_RTMP) int32 { - // TODO finish porting - /* - var packet C_RTMPPacket - var pbuf [1024]byte - var pend []byte = pbuf[1024:] - var enc []byte +func C_SendFCUnpublish(r *C_RTMP) (ok bool) { + var packet C_RTMPPacket + var pbuf [1024]byte + var pend *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&pbuf[0])) + + unsafe.Sizeof(pbuf))) + var enc *byte - packet.m_nChannel = 0x03 - packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM - packet.m_packetType = RTMP_PACKET_TYPE_INVOKE - packet.m_nTimeStamp = 0 - packet.m_nInfoField2 = 0 - packet.m_hasAbsTimestamp = 0 - packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE + packet.m_nChannel = 0x03 /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE + packet.m_nTimeStamp = 0 + packet.m_nInfoField2 = 0 + packet.m_hasAbsTimestamp = 0 + packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] - // NOTE use of unsafe pointer will be remove here when packet.m_nBody becomes []byte - enc = []byte(unsafe.Pointer(packet.m_nBody)) - enc = C_AMF_EncodeString((*byte)(unsafe.Pointer(&enc[0])), - (*byte)(unsafe.Pointer(&pend[0])), &av_FCUnpublish) - r.m_numInvokes++ - enc = C_AMF_EncodeNumber(enc, pend, r->m_numInvokes); - *enc++ = AMF_NULL; - enc = AMF_EncodeString(enc, pend, &r->Link.playpath); - if (!enc) - return FALSE; + enc = (*byte)(unsafe.Pointer(packet.m_body)) + enc = C_AMF_EncodeString(enc, pend, av_FCUnpublish) + r.m_numInvokes++ + enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) + *enc = AMF_NULL + enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) + enc = C_AMF_EncodeString(enc, pend, r.Link.playpath) - packet.m_nBodySize = enc - packet.m_body; + if enc == nil { + return false + } - return RTMP_SendPacket(r, &packet, FALSE); - */ - return 0 + packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( + unsafe.Pointer(packet.m_body))) + + return C_RTMP_SendPacket(r, &packet, 0) } // int SendPublish(RTMP* r); // rtmp.c +1908 -func C_SendPublish(r *C_RTMP) int32 { +func C_SendPublish(r *C_RTMP) (ok bool) { var packet C_RTMPPacket var pbuf [1024]byte var pend *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&pbuf[0])) + @@ -1069,35 +948,66 @@ func C_SendPublish(r *C_RTMP) int32 { packet.m_nTimeStamp = 0 packet.m_nInfoField2 = int32(r.m_stream_id) packet.m_hasAbsTimestamp = 0 - packet.m_body = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), - int(RTMP_MAX_HEADER_SIZE))) + packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = C_AMF_EncodeString(enc, pend, &av_publish) + enc = C_AMF_EncodeString(enc, pend, av_publish) r.m_numInvokes++ enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) *enc = AMF_NULL enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) - enc = C_AMF_EncodeString(enc, pend, &r.Link.playpath) + enc = C_AMF_EncodeString(enc, pend, r.Link.playpath) if enc == nil { - return 0 + return false } - enc = C_AMF_EncodeString(enc, pend, &av_live) + enc = C_AMF_EncodeString(enc, pend, av_live) if enc == nil { - return 0 + return false } packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( unsafe.Pointer(packet.m_body))) - return int32(C_RTMP_SendPacket(r, &packet, 1)) + return C_RTMP_SendPacket(r, &packet, 1) +} + +// int +// SendDeleteStream(RTMP *r, double dStreamId) +// rtmp.c +1942 +func C_SendDeleteStream(r *C_RTMP, dStreamId float64) (ok bool) { + var packet C_RTMPPacket + var pbuf [256]byte + pend := (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), 256)) + var enc *byte + + packet.m_nChannel = 0x03 /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE + packet.m_nTimeStamp = 0 + packet.m_nInfoField2 = 0 + packet.m_hasAbsTimestamp = 0 + packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] + + enc = (*byte)(unsafe.Pointer(packet.m_body)) + enc = C_AMF_EncodeString(enc, pend, av_deleteStream) + r.m_numInvokes++ + enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) + *enc = AMF_NULL + enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) + enc = C_AMF_EncodeNumber(enc, pend, dStreamId) + + packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( + unsafe.Pointer(packet.m_body))) + + /* no response expected */ + return C_RTMP_SendPacket(r, &packet, 0) } // int SendBytesReceived(RTMP* r); // rtmp.c +2080 -func C_SendBytesReceived(r *C_RTMP) int { +func C_SendBytesReceived(r *C_RTMP) (ok bool) { var packet C_RTMPPacket var pbuf [256]byte pend := (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), 256)) @@ -1108,23 +1018,20 @@ func C_SendBytesReceived(r *C_RTMP) int { packet.m_nTimeStamp = 0 packet.m_nInfoField2 = 0 packet.m_hasAbsTimestamp = 0 - packet.m_body = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), - RTMP_MAX_HEADER_SIZE)) + packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] packet.m_nBodySize = 4 C_AMF_EncodeInt32((*byte)(unsafe.Pointer(packet.m_body)), pend, int32(r.m_nBytesIn)) - // C.AMF_EncodeInt32(packet.m_body, (*byte)(unsafe.Pointer(pend)), r.m_nBytesIn) r.m_nBytesInSent = r.m_nBytesIn - //return int(C.RTMP_SendPacket(r, &packet, 0)) return C_RTMP_SendPacket(r, &packet, 0) } // int SendCheckBW(RTMP* r); // rtmp.c +2105 -func C_SendCheckBW(r *C_RTMP) int32 { +func C_SendCheckBW(r *C_RTMP) (ok bool) { var packet C_RTMPPacket var pbuf [256]byte var pend *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&pbuf[0])) + @@ -1137,11 +1044,10 @@ func C_SendCheckBW(r *C_RTMP) int32 { packet.m_nTimeStamp = 0 packet.m_nInfoField2 = 0 packet.m_hasAbsTimestamp = 0 - packet.m_body = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), - int(RTMP_MAX_HEADER_SIZE))) + packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = C_AMF_EncodeString(enc, pend, &av__checkbw) + enc = C_AMF_EncodeString(enc, pend, av__checkbw) r.m_numInvokes++ enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) *enc = AMF_NULL @@ -1150,7 +1056,7 @@ func C_SendCheckBW(r *C_RTMP) int32 { packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( unsafe.Pointer(packet.m_body))) - return int32(C_RTMP_SendPacket(r, &packet, 0)) + return C_RTMP_SendPacket(r, &packet, 0) } // void AV_erase(C_RTMP_METHOD* vals, int* num, int i, int freeit); @@ -1160,204 +1066,178 @@ func C_AV_erase(vals *C_RTMP_METHOD, num *int32, i, freeit int32) { //C.free(unsafe.Pointer((*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(vals), int(i), //int(unsafe.Sizeof(*vals))))).name.av_val)) } - (*num)-- + *num-- for ; i < *num; i++ { *(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(vals), int(i), int(unsafe.Sizeof(*vals)))) = *(*C_RTMP_METHOD)(incPtr( unsafe.Pointer(vals), int(i+1), int(unsafe.Sizeof(*vals)))) } - (*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(vals), int(i), - int(unsafe.Sizeof(*vals))))).name.av_val = nil - (*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(vals), int(i), - int(unsafe.Sizeof(*vals))))).name.av_len = 0 - (*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(vals), int(i), - int(unsafe.Sizeof(*vals))))).num = 0 + *(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(vals), int(i), int(unsafe.Sizeof(*vals)))) = C_RTMP_METHOD{} } // void AV_queue(RTMP_METHOD** vals, int* num, C_AVal* av, int txn); // rtmp.c +2414 -func C_AV_queue(vals **C_RTMP_METHOD, num *int32, av *C_AVal, txn int32) { +func C_AV_queue(vals **C_RTMP_METHOD, num *int32, av string, txn int32) { if (*num & 0x0f) == 0 { - //*vals = (*C_RTMP_METHOD)(realloc(unsafe.Pointer(*vals), uint32((*num+16)* - //int32(unsafe.Sizeof(*(*vals)))))) - *vals = (*C_RTMP_METHOD)(C.realloc(unsafe.Pointer(*vals), C.size_t((*num+16)* - int32(unsafe.Sizeof(*(*vals)))))) + *vals = (*C_RTMP_METHOD)(C.realloc(unsafe.Pointer(*vals), C.size_t((*num+16)*int32(unsafe.Sizeof(**vals))))) } - tmp := malloc(uintptr(av.av_len + 1)) - //tmp := allocate(uintptr(av.av_len + 1)) - memmove(tmp, unsafe.Pointer(av.av_val), uintptr(av.av_len)) - (*[_Gi]byte)(tmp)[av.av_len] = '\000' - (*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(*vals), int(*num), - int(unsafe.Sizeof(*(*vals)))))).num = int32(txn) - (*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(*vals), int(*num), - int(unsafe.Sizeof(*(*vals)))))).name.av_len = av.av_len - (*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(*vals), int(*num), - int(unsafe.Sizeof(*(*vals)))))).name.av_val = (*byte)(tmp) - (*num)++ + meth := (*C_RTMP_METHOD)(incPtr(unsafe.Pointer(*vals), int(*num), int(unsafe.Sizeof(**vals)))) + *meth = C_RTMP_METHOD{ + name: av, + num: int32(txn), + } + *num++ } // int HandleInvoke(RTMP* r, const char* body, unsigned int nBodySize); // rtmp.c +2912 -func C_HandleInvoke(r *C_RTMP, body *byte, nBodySize uint32) int32 { +func C_HandleInvoke(r *C_RTMP, body *byte, nBodySize uint32) (ok bool) { var obj C_AMFObject - var method C_AVal var txn float64 - var ret int32 = 0 var nRes int32 if *body != 0x02 { // TODO use new logger here //RTMP_Log(RTMP_LOGWARNING, "%s, Sanity failed. no string method in invoke packet", //__FUNCTION__); - return 0 + return false } nRes = C_AMF_Decode(&obj, body, int32(nBodySize), 0) - //nRes = int32(C.AMF_Decode(&obj, (*byte)(unsafe.Pointer(body)), int32(nBodySize), 0)) if nRes < 0 { // TODO use new logger here //RTMP_Log(RTMP_LOGERROR, "%s, error decoding invoke packet", __FUNCTION__); - return 0 + return false } // NOTE we don't really need this ?? still functions without it //C.AMF_Dump(&obj) //C.AMFProp_GetString(C_AMF_GetProp(&obj, nil, 0), &method) - C_AMFProp_GetString(C_AMF_GetProp(&obj, nil, 0), &method) - txn = float64(C_AMFProp_GetNumber(C_AMF_GetProp(&obj, nil, 1))) + method := C_AMFProp_GetString(C_AMF_GetProp(&obj, "", 0)) + txn = float64(C_AMFProp_GetNumber(C_AMF_GetProp(&obj, "", 1))) // TODO use new logger here // RTMP_Log(RTMP_LOGDEBUG, "%s, server invoking <%s>", __FUNCTION__, method.av_val); - switch { - case C_AVMATCH(&method, &av__result) != 0: - { - var methodInvoked C_AVal - var i int32 - for i = 0; i < int32(r.m_numCalls); i++ { - if float64((*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(r.m_methodCalls), int(i), - int(unsafe.Sizeof(*r.m_methodCalls))))).num) == txn { - methodInvoked = (*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(r.m_methodCalls), - int(i), int(unsafe.Sizeof(*r.m_methodCalls))))).name - //C.AV_erase(r.m_methodCalls, &r.m_numCalls, int32(i), 0) - C_AV_erase(r.m_methodCalls, (*int32)(&r.m_numCalls), int32(i), 0) - break - } + switch method { + case av__result: + var methodInvoked string + for i := int32(0); i < r.m_numCalls; i++ { + if float64((*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(r.m_methodCalls), int(i), int(unsafe.Sizeof(*r.m_methodCalls))))).num) == txn { + methodInvoked = (*C_RTMP_METHOD)(incPtr(unsafe.Pointer(r.m_methodCalls), int(i), int(unsafe.Sizeof(*r.m_methodCalls)))).name + C_AV_erase(r.m_methodCalls, (*int32)(&r.m_numCalls), int32(i), 0) + break } - if methodInvoked.av_val == nil { - // TODO use new logger here - //RTMP_Log(RTMP_LOGDEBUG, "%s, received result id %f without matching request", - //__FUNCTION__, txn); - goto leave - } - // TODO use new logger here - //RTMP_Log(RTMP_LOGDEBUG, "%s, received result for method call <%s>", __FUNCTION__, - //methodInvoked.av_val); - switch { - case C_AVMATCH(&methodInvoked, &av_connect) != 0: - if r.Link.token.av_len != 0 { - panic("No support for link token") - - } - if (r.Link.protocol & RTMP_FEATURE_WRITE) != 0 { - C_SendReleaseStream(r) - C_SendFCPublish(r) - } else { - panic("Link protocol has no RTMP_FEATURE_WRITE") - } - - C_RTMP_SendCreateStream(r) - if (r.Link.protocol & RTMP_FEATURE_WRITE) == 0 { - panic("Link protocol has no RTMP_FEATURE_WRITE") - } - - case C_AVMATCH(&methodInvoked, &av_createStream) != 0: - r.m_stream_id = int32(C_AMFProp_GetNumber(C_AMF_GetProp(&obj, nil, 3))) - - if (r.Link.protocol & RTMP_FEATURE_WRITE) != 0 { - C_SendPublish(r) - } else { - panic("Link protocol has no RTMP_FEATURE_WRITE") - } - - case C_AVMATCH(&methodInvoked, &av_play) != 0 || - C_AVMATCH(&methodInvoked, &av_publish) != 0: - panic("Unsupported method av_play/av_publish") - } - //C.free(unsafe.Pointer(methodInvoked.av_val)) } - case C_AVMATCH(&method, &av_onBWDone) != 0: + if methodInvoked == "" { + // TODO use new logger here + //RTMP_Log(RTMP_LOGDEBUG, "%s, received result id %f without matching request", + //__FUNCTION__, txn); + goto leave + } + // TODO use new logger here + //RTMP_Log(RTMP_LOGDEBUG, "%s, received result for method call <%s>", __FUNCTION__, + //methodInvoked.av_val); + switch methodInvoked { + case av_connect: + if r.Link.token != "" { + panic("No support for link token") + + } + if (r.Link.protocol & RTMP_FEATURE_WRITE) != 0 { + C_SendReleaseStream(r) + C_SendFCPublish(r) + } else { + panic("Link protocol has no RTMP_FEATURE_WRITE") + } + + C_RTMP_SendCreateStream(r) + if (r.Link.protocol & RTMP_FEATURE_WRITE) == 0 { + panic("Link protocol has no RTMP_FEATURE_WRITE") + } + + case av_createStream: + r.m_stream_id = int32(C_AMFProp_GetNumber(C_AMF_GetProp(&obj, "", 3))) + + if r.Link.protocol&RTMP_FEATURE_WRITE != 0 { + C_SendPublish(r) + } else { + panic("Link protocol has no RTMP_FEATURE_WRITE") + } + + case av_play, av_publish: + panic("Unsupported method av_play/av_publish") + } + //C.free(unsafe.Pointer(methodInvoked.av_val)) + + case av_onBWDone: if r.m_nBWCheckCounter == 0 { C_SendCheckBW(r) } - case C_AVMATCH(&method, &av_onFCUnsubscribe) != 0 || C_AVMATCH(&method, &av_onFCSubscribe) != 0: + case av_onFCUnsubscribe, av_onFCSubscribe: panic("Unsupported method av_onFCUnsubscribe/av_onFCSubscribe") - case C_AVMATCH(&method, &av_ping) != 0: + case av_ping: panic("Unsupported method av_ping") - case C_AVMATCH(&method, &av__onbwcheck) != 0: + case av__onbwcheck: panic("Unsupported method av_onbwcheck") - case C_AVMATCH(&method, &av__onbwdone) != 0: + case av__onbwdone: panic("Unsupported method av_onbwdone") - case C_AVMATCH(&method, &av_close) != 0: + case av_close: panic("Unsupported method av_close") - case C_AVMATCH(&method, &av_onStatus) != 0: + case av_onStatus: var obj2 C_AMFObject - var code, level C_AVal - C_AMFProp_GetObject(C_AMF_GetProp(&obj, nil, 3), &obj2) - C_AMFProp_GetString(C_AMF_GetProp(&obj2, &av_code, -1), &code) - C_AMFProp_GetString(C_AMF_GetProp(&obj2, &av_level, -1), &level) + C_AMFProp_GetObject(C_AMF_GetProp(&obj, "", 3), &obj2) + code := C_AMFProp_GetString(C_AMF_GetProp(&obj2, av_code, -1)) + + level := C_AMFProp_GetString(C_AMF_GetProp(&obj2, av_level, -1)) // Not used. + _ = level // TODO use new logger // RTMP_Log(RTMP_LOGDEBUG, "%s, onStatus: %s", __FUNCTION__, code.av_val); - switch { - case C_AVMATCH(&code, &av_NetStream_Failed) != 0 || - C_AVMATCH(&code, &av_NetStream_Play_Failed) != 0 || - C_AVMATCH(&code, &av_NetStream_Play_StreamNotFound) != 0 || - C_AVMATCH(&code, &av_NetConnection_Connect_InvalidApp) != 0: + + switch code { + case av_NetStream_Failed, av_NetStream_Play_Failed, + av_NetStream_Play_StreamNotFound, av_NetConnection_Connect_InvalidApp: panic("Unsupported method av_NetStream/av_NetStream_Play_Failed/av_netSTream_Play_StreamNotFound/av_netConnection_Connect_invalidApp") - case C_AVMATCH(&code, &av_NetStream_Play_Start) != 0 || - C_AVMATCH(&code, &av_NetStream_Play_PublishNotify) != 0: + case av_NetStream_Play_Start, av_NetStream_Play_PublishNotify: panic("Unsupported method av_NetStream_Play_Start/av_NetStream_Play_PublishNotify") - case C_AVMATCH(&code, &av_NetStream_Publish_Start) != 0: - - var i int32 - r.m_bPlaying = 1 - for i = 0; i < int32(r.m_numCalls); i++ { - if C_AVMATCH(&(*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(r.m_methodCalls), int(i), - int(unsafe.Sizeof(*r.m_methodCalls))))).name, &av_publish) != 0 { - //C.AV_erase(r.m_methodCalls, &r.m_numCalls, int32(i), 1) + case av_NetStream_Publish_Start: + r.m_bPlaying = true + for i := int32(0); i < r.m_numCalls; i++ { + method_name := (*C_RTMP_METHOD)(incPtr(unsafe.Pointer(r.m_methodCalls), int(i), int(unsafe.Sizeof(*r.m_methodCalls)))).name + if method_name == av_publish { C_AV_erase(r.m_methodCalls, (*int32)(&r.m_numCalls), int32(i), 1) break } } - case C_AVMATCH(&code, &av_NetStream_Play_Complete) != 0 || - C_AVMATCH(&code, &av_NetStream_Play_Stop) != 0 || - C_AVMATCH(&code, &av_NetStream_Play_UnpublishNotify) != 0: + case av_NetStream_Play_Complete, av_NetStream_Play_Stop, av_NetStream_Play_UnpublishNotify: panic("Unsupported method av_NetStream_Play_Complete/av_NetStream_Play_Stop/av_NetStream_Play_UnpublishNotify") - case C_AVMATCH(&code, &av_NetStream_Seek_Notify) != 0: + case av_NetStream_Seek_Notify: panic("Unsupported method av_netStream_Seek_Notify") - case C_AVMATCH(&code, &av_NetStream_Pause_Notify) != 0: + case av_NetStream_Pause_Notify: panic("Unsupported method av_NetStream_Pause_Notify") } - case C_AVMATCH(&method, &av_playlist_ready) != 0: + case av_playlist_ready: panic("Unsupported method av_playlist_ready") default: + panic(fmt.Sprintf("unknown method: %q", method)) } leave: C_AMF_Reset(&obj) - return ret + // None of the methods we implement will result in a true return. + return ok } // void HandleChangeChunkSize(RTMP* r, const RTMPPacket* packet); @@ -1375,7 +1255,6 @@ func C_HandleChangeChunkSize(r *C_RTMP, packet *C_RTMPPacket) { // rtmp.c +3508 func C_HandlServerBW(r *C_RTMP, packet *C_RTMPPacket) { r.m_nServerBW = int32(C_AMF_DecodeInt32((*byte)(unsafe.Pointer(packet.m_body)))) - //r.m_nServerBW = int32(C.AMF_DecodeInt32((*byte)(unsafe.Pointer(packet.m_body)))) // TODO use new logger here // RTMP_Log(RTMP_LOGDEBUG, "%s: server BW = %d", __FUNCTION__, r.m_nServerBW); } @@ -1421,7 +1300,7 @@ func C_EncodeInt32LE(output *byte, nVal int32) int32 { // int RTMP_ReadPacket(RTMP* r, RTMPPacket* packet); // rtmp.c +3550 -func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { +func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) (ok bool) { var hbuf [RTMP_MAX_HEADER_SIZE]uint8 memset((*byte)(&hbuf[0]), 0, RTMP_MAX_HEADER_SIZE) var header *byte @@ -1431,7 +1310,7 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { if C_ReadN(r, (*byte)(&hbuf[0]), 1) == 0 { log.Println("C_RTMP_ReadPacket: failed to read RTMP packet header!") - return 0 + return false } packet.m_headerType = uint8((hbuf[0] & 0xc0) >> 6) @@ -1442,7 +1321,7 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { case packet.m_nChannel == 0: if C_ReadN(r, (*byte)(&hbuf[1]), 1) != 1 { log.Println("C_RTMP_ReadPacket: failed to read rtmp packet header 2nd byte.") - return 0 + return false } packet.m_nChannel = int32(hbuf[1]) @@ -1453,7 +1332,7 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { if C_ReadN(r, (*byte)(&hbuf[1]), 2) != 2 { log.Println("C_RTMP_ReadPacket: failed to read RTMP packet 3rd byte") - return 0 + return false } tmp = int32((hbuf[2] << 8) + hbuf[1]) @@ -1465,14 +1344,10 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { if packet.m_nChannel >= r.m_channelsAllocatedIn { var n int32 = int32(packet.m_nChannel + 10) - //timestamp := (*int32)(realloc(unsafe.Pointer(r.m_channelTimestamp), - //uint32(int32(unsafe.Sizeof(n))*n))) timestamp := (*int32)(C.realloc(unsafe.Pointer(r.m_channelTimestamp), C.size_t(int32(unsafe.Sizeof(n))*n))) var packetPtr *C_RTMPPacket - //packets := (**C_RTMPPacket)(realloc(unsafe.Pointer(r.m_vecChannelsIn), - //uint32(int32(unsafe.Sizeof(packetPtr))*n))) packets := (**C_RTMPPacket)(C.realloc(unsafe.Pointer(r.m_vecChannelsIn), C.size_t(int32(unsafe.Sizeof(packetPtr))*n))) if timestamp == nil { @@ -1488,7 +1363,7 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { if timestamp == nil || packets == nil { r.m_channelsAllocatedIn = 0 - return 0 + return false } memset((*byte)(incPtr(unsafe.Pointer(r.m_channelTimestamp), @@ -1519,7 +1394,7 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { if nSize > 0 && C_ReadN(r, header, int(nSize)) != int(nSize) { log.Println("C_RTMP_ReadPacket: failed to read rtmp packet header.") - return 0 + return false } hSize = int32(uintptr(incBytePtr(decBytePtr(unsafe.Pointer(header), int(uintptr( @@ -1540,8 +1415,6 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { // TODO: port this packet.m_nInfoField2 = int32(C_DecodeInt32LE((*byte)(incBytePtr( unsafe.Pointer(header), 7)))) - //packet.m_nInfoField2 = int32(C.DecodeInt32LE((*byte)(incBytePtr( - //unsafe.Pointer(header), 7)))) } } } @@ -1554,21 +1427,19 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { if extendedTimestamp != 0 { if C_ReadN(r, (*byte)(incBytePtr(unsafe.Pointer(header), int(nSize))), 4) != 4 { log.Println("RTMPRead_Packet: Failed to read extended timestamp") - return 0 + return false } // TODO: port this packet.m_nTimeStamp = uint32(C_AMF_DecodeInt32((*byte)(incBytePtr( unsafe.Pointer(header), int(nSize))))) - //packet.m_nTimeStamp = uint32(C.AMF_DecodeInt32((*byte)(incBytePtr( - //unsafe.Pointer(header), int(nSize))))) hSize += 4 } if packet.m_nBodySize > 0 && packet.m_body == nil { // TODO: port this - if C_RTMPPacket_Alloc(packet, uint32(packet.m_nBodySize)) == 0 { + if !C_RTMPPacket_Alloc(packet, uint32(packet.m_nBodySize)) { log.Println("RTMPRead_Packet: failed to allocate packet") - return 0 + return false } packet.m_headerType = uint8((hbuf[0] & 0xc0) >> 6) } @@ -1592,7 +1463,7 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { if C_ReadN(r, (*byte)(incBytePtr(unsafe.Pointer(packet.m_body), int(packet.m_nBytesRead))), int(nChunk)) != int(nChunk) { log.Println("C_RTMP_ReadPacket: failed to read RTMP packet body") - return 0 + return false } packet.m_nBytesRead += uint32(nChunk) @@ -1618,7 +1489,7 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { } // TODO: port this - if C_RTMPPacket_IsReady(packet) != 0 { + if C_RTMPPacket_IsReady(packet) { if packet.m_hasAbsTimestamp == 0 { // timestamps seem to always be relative packet.m_nTimeStamp += *(*uint32)(incPtr(unsafe.Pointer(r.m_channelTimestamp), @@ -1636,16 +1507,12 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { } else { packet.m_body = nil /* so it won't be erased on free */ } - return 1 + return true } // int HandShake(RTMP* r, int FP9HandShake); // rtmp.c +3744 -func C_HandShake(r *C_RTMP, FP9HandShake int32) int { - var bMatch int - //uptime := uint32(0) - //suptime := uint32(0) - //typ := byte(0) +func C_HandShake(r *C_RTMP, FP9HandShake int32) (ok bool) { var uptime, suptime uint32 var typ byte //clientbuf := make([]byte, RTMP_SIG_SIZE+1) @@ -1657,7 +1524,6 @@ func C_HandShake(r *C_RTMP, FP9HandShake int32) int { clientbuf[0] = 0x03 // not encrypted // TODO: port rtmp_getTime - //uptime = inet.Htonl(uint32(C.RTMP_GetTime())) uptime = inet.Htonl(uint32(C_RTMP_GetTime())) memmove(unsafe.Pointer(clientsig), unsafe.Pointer(&uptime), 4) @@ -1667,13 +1533,12 @@ func C_HandShake(r *C_RTMP, FP9HandShake int32) int { (*[_Gi]byte)(unsafe.Pointer(clientsig))[i] = byte(rand.Intn(256)) } - if C_WriteN(r, unsafe.Pointer(&clientbuf[0]), RTMP_SIG_SIZE+1) == 0 { - return 0 + if !C_WriteN(r, unsafe.Pointer(&clientbuf[0]), RTMP_SIG_SIZE+1) { + return false } - //if C.ReadN(r, (*byte)(unsafe.Pointer(&typ)), 1) != 1 { if C_ReadN(r, (*byte)(unsafe.Pointer(&typ)), 1) != 1 { - return 0 + return false } if debugMode { @@ -1684,8 +1549,7 @@ func C_HandShake(r *C_RTMP, FP9HandShake int32) int { clientbuf[0], typ) } if C_ReadN(r, (*byte)(unsafe.Pointer(&serversig[0])), RTMP_SIG_SIZE) != RTMP_SIG_SIZE { - //if C.ReadN(r, (*byte)(unsafe.Pointer(&serversig[0])), RTMP_SIG_SIZE) != RTMP_SIG_SIZE { - return 0 + return false } // decode server response @@ -1693,31 +1557,24 @@ func C_HandShake(r *C_RTMP, FP9HandShake int32) int { suptime = inet.Ntohl(suptime) // 2nd part of handshake - if C_WriteN(r, unsafe.Pointer(&serversig[0]), RTMP_SIG_SIZE) == 0 { - return 0 + if !C_WriteN(r, unsafe.Pointer(&serversig[0]), RTMP_SIG_SIZE) { + return false } if C_ReadN(r, (*byte)(unsafe.Pointer(&serversig[0])), RTMP_SIG_SIZE) != RTMP_SIG_SIZE { - //if C.ReadN(r, (*byte)(unsafe.Pointer(&serversig[0])), RTMP_SIG_SIZE) != RTMP_SIG_SIZE { - return 0 + return false } - // TODO: find golang memcmp - bMatch = 0 - if memcmp(unsafe.Pointer(&serversig[0]), unsafe.Pointer(clientsig), - RTMP_SIG_SIZE) == 0 { - bMatch = 1 + if !bytes.Equal(serversig[:RTMP_SIG_SIZE], clientbuf[1:RTMP_SIG_SIZE+1]) { + log.Printf("Client signature does not match: %q != %q", + serversig[:RTMP_SIG_SIZE], clientbuf[1:RTMP_SIG_SIZE+1]) } - - if bMatch == 0 { - log.Println("Client signature does not match!") - } - return 1 + return true } // int RTMP_SendPacket(RTMP* r, RTMPPacket* packet, int queue); // rtmp.c +3896 -func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) int { +func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) (ok bool) { var prevPacket *C_RTMPPacket last := 0 var nSize, hSize, cSize, nChunkSize int @@ -1732,14 +1589,12 @@ func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) int { n := int(packet.m_nChannel + 10) packets = C.realloc(unsafe.Pointer(r.m_vecChannelsOut), C.size_t( unsafe.Sizeof(packet)*uintptr(n))) - //packets = realloc(unsafe.Pointer(r.m_vecChannelsOut), - //uint32(unsafe.Sizeof(packet)*uintptr(n))) if uintptr(packets) == uintptr(0) { //C.free(unsafe.Pointer(r.m_vecChannelsOut)) r.m_vecChannelsOut = nil r.m_channelsAllocatedOut = 0 - return 0 + return false } r.m_vecChannelsOut = (**C_RTMPPacket)(packets) @@ -1747,9 +1602,6 @@ func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) int { int(unsafe.Sizeof(packet)))), 0, int(unsafe.Sizeof(packet)* uintptr(n-int(r.m_channelsAllocatedOut)))) - //memset((*byte)(incPtr(unsafe.Pointer(r.m_vecChannelsOut), int( - // r.m_channelsAllocatedOut), int(unsafe.Sizeof(packet)))), 0, int( - // unsafe.Sizeof(packet)*uintptr(n-int(r.m_channelsAllocatedOut)))) r.m_channelsAllocatedOut = int32(n) } prevPacket = *(**C_RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsOut), @@ -1775,7 +1627,7 @@ func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) int { if packet.m_headerType > 3 { log.Printf("Sanity failed! trying to send header of type: 0x%02x.", packet.m_headerType) - return 0 + return false } nSize = packetSize[int(packet.m_headerType)] @@ -1853,8 +1705,6 @@ func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) int { // TODO: port this hptr = incBytePtr(hptr, int(C_EncodeInt32LE((*byte)(hptr), int32(packet.m_nInfoField2)))) - //hptr = incBytePtr(hptr, int(C.EncodeInt32LE((*byte)(hptr), - //int32(packet.m_nInfoField2)))) } if t >= 0xffffff { @@ -1870,22 +1720,17 @@ func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) int { } for (nSize + hSize) != 0 { - var wrote int - if nSize < nChunkSize { nChunkSize = nSize } if tbuf != nil { - //memmove(toff, header, uintptr(nChunkSize + hSize)) copy((*[_Gi]byte)(toff)[:nChunkSize+hSize], (*[_Gi]byte)(header)[:nChunkSize+hSize]) toff = incBytePtr(toff, nChunkSize+hSize) } else { // TODO: port this - wrote = int(C_WriteN(r, header, nChunkSize+hSize)) - - if wrote == 0 { - return 0 + if !C_WriteN(r, header, nChunkSize+hSize) { + return false } } @@ -1926,13 +1771,12 @@ func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) int { } if tbuf != nil { - wrote := int(C_WriteN(r, tbuf, int(uintptr(decBytePtr(toff, - int(uintptr(unsafe.Pointer(tbuf)))))))) + ok := C_WriteN(r, tbuf, int(uintptr(decBytePtr(toff, int(uintptr(unsafe.Pointer(tbuf))))))) ////C.free(tbuf) tbuf = nil - if wrote == 0 { - return 0 + if !ok { + return false } } @@ -1940,25 +1784,18 @@ func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) int { // TODO: port the const if packet.m_packetType == RTMP_PACKET_TYPE_INVOKE { // TODO: port C_AVal - var method C_AVal var ptr unsafe.Pointer ptr = incBytePtr(unsafe.Pointer(packet.m_body), 1) - //C.AMF_DecodeString((*byte)(ptr), &method) - C_AMF_DecodeString((*byte)(ptr), &method) + method := C_AMF_DecodeString((*byte)(ptr)) if debugMode { - log.Printf("Invoking %v", method.av_val) + log.Printf("invoking %v", method) } // keep it in call queue till result arrives if queue != 0 { - var txn int - ptr = incBytePtr(ptr, 3+int(method.av_len)) - //txn = int(C.AMF_DecodeNumber((*byte)(ptr))) - txn = int(C_AMF_DecodeNumber((*byte)(ptr))) - C_AV_queue(&r.m_methodCalls, (*int32)(unsafe.Pointer(&r.m_numCalls)), - &method, int32(txn)) - //C.AV_queue(&r.m_methodCalls, (*int32)(unsafe.Pointer(&r.m_numCalls)), &method, - //int32(txn)) + ptr = incBytePtr(ptr, 3+len(method)) + txn := int32(C_AMF_DecodeNumber((*byte)(ptr))) + C_AV_queue(&r.m_methodCalls, (*int32)(unsafe.Pointer(&r.m_numCalls)), method, txn) } } @@ -1973,7 +1810,7 @@ func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) int { memmove(unsafe.Pointer(*(**C_RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsOut), int(packet.m_nChannel), int(unsafe.Sizeof(packet))))), unsafe.Pointer(packet), uintptr(unsafe.Sizeof(*packet))) - return 1 + return true } // void RTMP_Close(RTMP *r); @@ -1985,89 +1822,80 @@ func C_RTMP_Close(r *C_RTMP) { // static void CloseInternal(RTMP *r, int reconnect); // rtmp.c +4175 func C_CloseInternal(r *C_RTMP, reconnect int32) { - // TODO: port SendFCUnpublish - // TODO: port SendDeleteStream - // TODO: port RTMPSockBuf_Close - // TODO: port AV_Clear - /* - var i int32 + var i int32 - if C_RTMP_IsConnected(r) != 0 { - if r.m_stream_id > 0 { - i = int32(r.m_stream_id) - if r.Link.protocol&RTMP_FEATURE_WRITE != 0 { - C.SendFCUnpublish(r) - } - C.SendDeleteStream(r, float64(i)) + if C_RTMP_IsConnected(r) != 0 { + if r.m_stream_id > 0 { + i = int32(r.m_stream_id) + if r.Link.protocol&RTMP_FEATURE_WRITE != 0 { + C_SendFCUnpublish(r) } - C.RTMPSockBuf_Close(&r.m_sb) + C_SendDeleteStream(r, float64(i)) } + C_RTMPSockBuf_Close(&r.m_sb) + } - r.m_stream_id = -1 - r.m_sb.sb_socket = -1 - r.m_nBWCheckCounter = 0 - r.m_nBytesIn = 0 - r.m_nBytesInSent = 0 + r.m_stream_id = -1 + r.m_sb.sb_socket = -1 + r.m_nBWCheckCounter = 0 + r.m_nBytesIn = 0 + r.m_nBytesInSent = 0 - if r.m_read.flags&RTMP_READ_HEADER != 0 { - //C.free(unsafe.Pointer(r.m_read.buf)) - r.m_read.buf = nil + if r.m_read.flags&RTMP_READ_HEADER != 0 { + //C.free(unsafe.Pointer(r.m_read.buf)) + r.m_read.buf = nil + } + + r.m_read.dataType = 0 + r.m_read.flags = 0 + r.m_read.status = 0 + r.m_read.nResumeTS = 0 + r.m_read.nIgnoredFrameCounter = 0 + r.m_read.nIgnoredFlvFrameCounter = 0 + + r.m_write.m_nBytesRead = 0 + C_RTMPPacket_Free(&r.m_write) + + // NOTE: C frees - not using in our case + for i := 0; i < int(r.m_channelsAllocatedIn); i++ { + if *(**C_RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), i, + int(unsafe.Sizeof(&r.m_write)))) != nil { + + //C.RTMPPacket_Free(*(**C_RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), i, + //int(unsafe.Sizeof(&r.m_write))))) + + //C.free(unsafe.Pointer(*(**C_RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), + //i, int(unsafe.Sizeof(&r.m_write)))))) + + *(**C_RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), + i, int(unsafe.Sizeof(&r.m_write)))) = nil } + } - r.m_read.dataType = 0 - r.m_read.flags = 0 - r.m_read.status = 0 - r.m_read.nResumeTS = 0 - r.m_read.nIgnoredFrameCounter = 0 - r.m_read.nIgnoredFlvFrameCounter = 0 + //C.free(unsafe.Pointer(r.m_vecChannelsOut)) + r.m_vecChannelsOut = nil + r.m_channelsAllocatedOut = 0 + r.m_methodCalls = nil //C_AV_clear(r.m_methodCalls, r.m_numCalls) - r.m_write.m_nBytesRead = 0 - C.RTMPPacket_Free(&r.m_write) + r.m_methodCalls = nil + r.m_numCalls = 0 + r.m_numInvokes = 0 - // NOTE: C frees - not using in our case - for i := 0; i < int(r.m_channelsAllocatedIn); i++ { - if *(**C_RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), i, - int(unsafe.Sizeof(&r.m_write)))) != nil { + r.m_bPlaying = false + r.m_sb.sb_size = 0 - //C.RTMPPacket_Free(*(**C_RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), i, - //int(unsafe.Sizeof(&r.m_write))))) + r.m_msgCounter = 0 + r.m_resplen = 0 + r.m_unackd = 0 - //C.free(unsafe.Pointer(*(**C_RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), - //i, int(unsafe.Sizeof(&r.m_write)))))) + if ((r.Link.lFlags & RTMP_LF_FTCU) != 0) && (reconnect == 0) { + r.Link.app = "" + r.Link.lFlags ^= RTMP_LF_FAPU + } - *(**C_RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), - i, int(unsafe.Sizeof(&r.m_write)))) = nil - } - } - - - //C.free(unsafe.Pointer(r.m_vecChannelsOut)) - r.m_vecChannelsOut = nil - r.m_channelsAllocatedOut = 0 - C.AV_clear(r.m_methodCalls, r.m_numCalls) - - r.m_methodCalls = nil - r.m_numCalls = 0 - r.m_numInvokes = 0 - - r.m_bPlaying = C.uchar(0) - r.m_sb.sb_size = 0 - - r.m_msgCounter = 0 - r.m_resplen = 0 - r.m_unackd = 0 - - if ((r.Link.lFlags & RTMP_LF_FTCU) != 0) && (reconnect == 0) { - //C.free(unsafe.Pointer(r.Link.app.av_val)) - r.Link.app.av_val = nil - r.Link.lFlags ^= RTMP_LF_FAPU - } - - if reconnect == 0 { - //C.free(unsafe.Pointer(r.Link.playpath0.av_val)) - r.Link.playpath0.av_val = nil - } - */ + if reconnect == 0 { + r.Link.playpath0 = "" + } } // int RTMPSockBuf_Fill(RTMPSockBuf* sb); @@ -2105,6 +1933,16 @@ func C_RTMPSockBuf_Send(sb *C_RTMPSockBuf, buf *byte, l int32) int32 { return int32(C.send(C.int(sb.sb_socket), unsafe.Pointer(buf), C.size_t(l), 0)) } +// int +// RTMPSockBuf_Close(RTMPSockBuf *sb) +// rtmp.c +4369 +func C_RTMPSockBuf_Close(sb *C_RTMPSockBuf) int32 { + if sb.sb_socket != -1 { + return int32(C.close(C.int(sb.sb_socket))) + } + return 0 +} + // int RTMP_Write(RTMP* r, const char* buf, int size); // rtmp.c +5136 func C_RTMP_Write(r *C_RTMP, buf []byte) int { @@ -2112,7 +1950,7 @@ func C_RTMP_Write(r *C_RTMP, buf []byte) int { var pkt = &r.m_write var pend, enc []byte size := len(buf) - var ret, num int + var num int pkt.m_nChannel = 0x04 pkt.m_nInfoField2 = int32(r.m_stream_id) @@ -2150,7 +1988,7 @@ func C_RTMP_Write(r *C_RTMP, buf []byte) int { pkt.m_headerType = RTMP_PACKET_SIZE_MEDIUM } // TODO: Port this - if int(C_RTMPPacket_Alloc(pkt, uint32(pkt.m_nBodySize))) == 0 { + if !C_RTMPPacket_Alloc(pkt, uint32(pkt.m_nBodySize)) { log.Println("Failed to allocate packet") return 0 } @@ -2160,7 +1998,7 @@ func C_RTMP_Write(r *C_RTMP, buf []byte) int { if pkt.m_packetType == RTMP_PACKET_TYPE_INFO { enc = (*[_Gi]byte)(unsafe.Pointer(C_AMF_EncodeString((*byte)(unsafe.Pointer(&enc[0])), - (*byte)(unsafe.Pointer(&pend[0])), &setDataFrame)))[:pkt.m_nBodySize] + (*byte)(unsafe.Pointer(&pend[0])), setDataFrame)))[:pkt.m_nBodySize] // TODO: work out what to do with this pkt.m_nBytesRead = uint32(float64(uintptr(unsafe.Pointer(&enc[0])) - @@ -2180,12 +2018,11 @@ func C_RTMP_Write(r *C_RTMP, buf []byte) int { buf = buf[num:] if pkt.m_nBytesRead == pkt.m_nBodySize { // TODO: Port this - ret = C_RTMP_SendPacket(r, pkt, 0) + ok := C_RTMP_SendPacket(r, pkt, 0) // TODO: Port this - //C.RTMPPacket_Free(pkt) C_RTMPPacket_Free(pkt) pkt.m_nBytesRead = 0 - if ret == 0 { + if !ok { return -1 } if len(buf) < 4 { @@ -2197,13 +2034,6 @@ func C_RTMP_Write(r *C_RTMP, buf []byte) int { return size } -/* -func realloc(ptr unsafe.Pointer, newSize uint32) unsafe.Pointer { - return unsafe.Pointer(crt.Xrealloc(crt.TLS(uintptr(unsafe.Pointer(nil))), - uintptr(ptr), uint32(newSize))) -} -*/ - func memmove(to, from unsafe.Pointer, n uintptr) { if to != nil && from != nil && n != 0 { copy((*[_Gi]byte)(to)[:n], (*[_Gi]byte)(from)[:n]) diff --git a/rtmp/rtmp_headers.go b/rtmp/rtmp_headers.go index a45afd69..e836a49d 100644 --- a/rtmp/rtmp_headers.go +++ b/rtmp/rtmp_headers.go @@ -142,65 +142,46 @@ type C_RTMPSockBuf struct { sb_start *byte sb_buf [RTMP_BUFFER_CACHE_SIZE]byte // port const sb_timedout int32 - sb_ssl uintptr } // RTMPPacket_IsReady(a) // rtmp.h +142 -func C_RTMPPacket_IsReady(p *C_RTMPPacket) int { - if p.m_nBytesRead == p.m_nBodySize { - return 1 - } - return 0 +func C_RTMPPacket_IsReady(p *C_RTMPPacket) bool { + return p.m_nBytesRead == p.m_nBodySize } // typedef struct RTMP_LNK // rtmp.h +144 type C_RTMP_LNK struct { - hostname C_AVal - sockshost C_AVal - playpath0 C_AVal - playpath C_AVal - tcUrl C_AVal - swfUrl C_AVal - pageUrl C_AVal - app C_AVal - auth C_AVal - flashVer C_AVal - subscribepath C_AVal - usherToken C_AVal - token C_AVal - pubUser C_AVal - pubPasswd C_AVal - extras C_AMFObject - edepth int32 - seekTime int32 - stopTime int32 - lFlags int32 - swfAge int32 - protocol int32 - timeout int32 - pFlags int32 - socksport uint16 - port uint16 + hostname string + sockshost string + playpath0 string + playpath string + tcUrl string + swfUrl string + pageUrl string + app string + auth string + flashVer string + token string + extras C_AMFObject + seekTime int32 + lFlags int32 + swfAge int32 + protocol int32 + timeout int32 + socksport uint16 + port uint16 } // typedef struct RTMP_READ // rtmp.h +200 type C_RTMP_READ struct { buf *byte - bufpos *byte - buflen uint - timestamp uint32 dataType uint8 flags uint8 status int8 - initialFrameType uint8 nResumeTS uint32 - metaHeader *byte - initialFrame *byte - nMetaHeaderSize uint32 - nInitialFrameSize uint32 nIgnoredFrameCounter uint32 nIgnoredFlvFrameCounter uint32 } @@ -208,7 +189,7 @@ type C_RTMP_READ struct { // typedef struct RTMPMethod // rtmp.h +231 type C_RTMP_METHOD struct { - name C_AVal + name string num int32 } @@ -223,13 +204,11 @@ type C_RTMP struct { m_nBufferMS int32 m_stream_id int32 m_mediaChannel int32 - m_mediaStamp uint32 - m_pauseStamp uint32 m_pausing int32 m_nServerBW int32 m_nClientBW int32 m_nClientBW2 uint8 - m_bPlaying uint8 + m_bPlaying bool m_bSendEncoding uint8 m_bSendCounter uint8 m_numInvokes int32 @@ -245,10 +224,8 @@ type C_RTMP struct { m_fEncoding float64 m_fDuration float64 m_msgCounter int32 - m_polling int32 m_resplen int32 m_unackd int32 - m_clientID C_AVal m_read C_RTMP_READ m_write C_RTMPPacket m_sb C_RTMPSockBuf diff --git a/rtmp/rtmp_test.go b/rtmp/rtmp_test.go index b33417cc..4e3cce70 100644 --- a/rtmp/rtmp_test.go +++ b/rtmp/rtmp_test.go @@ -76,7 +76,7 @@ func TestMemset(t *testing.T) { setNum := 5 testVal := byte('A') mem := malloc(uintptr(size)) - memset((*byte)(mem), int(testVal), setNum) + memset((*byte)(mem), testVal, setNum) for i := 0; i < size; i++ { if i > setNum-1 { testVal = byte(0)