diff --git a/rtmp/rtmp.go b/rtmp/rtmp.go index 8fb9a819..57192e63 100644 --- a/rtmp/rtmp.go +++ b/rtmp/rtmp.go @@ -188,6 +188,12 @@ const ( debugMode = false ) +// TODO(kortschak): Remove these. +const ( + TRUE = 1 + FALSE = 0 +) + // av_setDataFrame is a static const global in rtmp.c var ( AV_empty = AVC("") @@ -1567,7 +1573,7 @@ func C_SendConnectPacket(r *C.RTMP, cp *C.RTMPPacket) int { //incPtr(unsafe.Pointer(&r.Link.extras.o_props), int(unsafe.Sizeof( //r.Link.extras.o_props)), i)), (*C.char)(unsafe.Pointer(enc)), (*C.char)( //unsafe.Pointer(pend))))) - enc = C_AMFPropEncode((*C.AMFObjectProperty)(incPtr(unsafe.Pointer( + 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) @@ -1586,7 +1592,7 @@ func C_SendConnectPacket(r *C.RTMP, cp *C.RTMPPacket) int { // char* AMFPropEncode(AMFOBjectProperty* prop, char* pBufer, char* pBufEnd); // amf.c +366 -func C_AMFPropEncode(p *C.AMFObjectProperty, pBuffer *byte, pBufEnd *byte) *byte { +func C_AMF_PropEncode(p *C.AMFObjectProperty, pBuffer *byte, pBufEnd *byte) *byte { if p.p_type == AMF_INVALID { return nil } @@ -1626,25 +1632,25 @@ func C_AMFPropEncode(p *C.AMFObjectProperty, pBuffer *byte, pBufEnd *byte) *byte *(*byte)(unsafe.Pointer(pBuffer)) = AMF_NULL pBuffer = (*byte)(incBytePtr(unsafe.Pointer(pBuffer), 1)) case AMF_OBJECT: - pBuffer = C_AMFEncode(&p.p_vu.p_object, pBuffer, pBufEnd) + pBuffer = C_AMF_Encode(&p.p_vu.p_object, pBuffer, pBufEnd) //pBuffer = (*byte)(unsafe.Pointer(C.AMF_Encode(&p.p_vu.p_object, (*C.char)( //unsafe.Pointer(pBuffer)), (*C.char)(unsafe.Pointer(pBufEnd))))) case AMF_ECMA_ARRAY: - pBuffer = C_AMFEncodeEcmaArray(&p.p_vu.p_object, pBuffer, pBufEnd) + pBuffer = C_AMF_EncodeEcmaArray(&p.p_vu.p_object, pBuffer, pBufEnd) //pBuffer = (*byte)(unsafe.Pointer(C.AMF_EncodeEcmaArray(&p.p_vu.p_object, (*C.char)(unsafe.Pointer(pBuffer)), (*C.char)(unsafe.Pointer(pBufEnd))))) case AMF_STRICT_ARRAY: //pBuffer = (*byte)(unsafe.Pointer(C.AMF_EncodeArray(&p.p_vu.p_object, (*C.char)(unsafe.Pointer(pBuffer)), (*C.char)(unsafe.Pointer(pBufEnd))))) - pBuffer = C_AMFEncodeArray(&p.p_vu.p_object, pBuffer, pBufEnd) + pBuffer = C_AMF_EncodeArray(&p.p_vu.p_object, pBuffer, pBufEnd) default: - log.Println("C_AMFPropEncode: invalid type!") + log.Println("C_AMF_PropEncode: invalid type!") pBuffer = nil } return pBuffer } -// char* AMF_ENCODE(AMFObject* obj, char* pBuffer, char* pBufEnd); +// char* AMF_Encode(AMFObject* obj, char* pBuffer, char* pBufEnd); // amf.c +891 -func C_AMFEncode(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte { +func C_AMF_Encode(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte { if uintptr(unsafe.Pointer(pBuffer))+uintptr(4) >= uintptr(unsafe.Pointer(pBufEnd)) { return nil } @@ -1653,10 +1659,10 @@ func C_AMFEncode(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte { pBuffer = (*byte)(incBytePtr(unsafe.Pointer(pBuffer), 1)) for i := 0; i < int(obj.o_num); i++ { - res := C_AMFPropEncode((*C.AMFObjectProperty)(incPtr(unsafe.Pointer( + res := C_AMF_PropEncode((*C.AMFObjectProperty)(incPtr(unsafe.Pointer( obj.o_props), i, int(unsafe.Sizeof(*obj.o_props)))), pBuffer, pBufEnd) if res == nil { - log.Println("C_AMFEncode: failed to encode property in index") + log.Println("C_AMF_Encode: failed to encode property in index") break } else { pBuffer = res @@ -1667,14 +1673,14 @@ func C_AMFEncode(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte { return nil } - pBuffer = C_AMFEncodeInt24(pBuffer, pBufEnd, int32(AMF_OBJECT_END)) + pBuffer = C_AMF_EncodeInt24(pBuffer, pBufEnd, int32(AMF_OBJECT_END)) return pBuffer } // char* AMF_EncodeEcmaArray(AMFObject* obj, char* pBuffer, char* pBufEnd); // amf.c +924 -func C_AMFEncodeEcmaArray(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte { +func C_AMF_EncodeEcmaArray(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte { if int(uintptr(unsafe.Pointer(pBuffer)))+4 >= int(uintptr(unsafe.Pointer(pBufEnd))) { return nil } @@ -1685,10 +1691,10 @@ func C_AMFEncodeEcmaArray(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte pBuffer = C_AMF_EncodeInt32(pBuffer, pBufEnd, int32(obj.o_num)) for i := 0; i < int(obj.o_num); i++ { - res := C_AMFPropEncode((*C.AMFObjectProperty)(incPtr(unsafe.Pointer( + res := C_AMF_PropEncode((*C.AMFObjectProperty)(incPtr(unsafe.Pointer( obj.o_props), i, int(unsafe.Sizeof(*obj.o_props)))), pBuffer, pBufEnd) if res == nil { - log.Println("C_AMFEncodeEcmaArray: failed to encode property!") + log.Println("C_AMF_EncodeEcmaArray: failed to encode property!") break } else { pBuffer = res @@ -1699,14 +1705,14 @@ func C_AMFEncodeEcmaArray(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte return nil } - pBuffer = C_AMFEncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END) + pBuffer = C_AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END) return pBuffer } // char* AMF_EncodeArray(AMFObject* obj, char* pBuffer, char* pBufEnd); // amf.c +959 -func C_AMFEncodeArray(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte { +func C_AMF_EncodeArray(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte { if int(uintptr(unsafe.Pointer(pBuffer)))+4 >= int(uintptr(unsafe.Pointer(pBufEnd))) { return nil } @@ -1717,10 +1723,10 @@ func C_AMFEncodeArray(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte { pBuffer = C_AMF_EncodeInt32(pBuffer, pBufEnd, int32(obj.o_num)) for i := 0; i < int(obj.o_num); i++ { - res := C_AMFPropEncode((*C.AMFObjectProperty)(incPtr(unsafe.Pointer( + res := C_AMF_PropEncode((*C.AMFObjectProperty)(incPtr(unsafe.Pointer( obj.o_props), i, int(unsafe.Sizeof(*obj.o_props)))), pBuffer, pBufEnd) if res == nil { - log.Println("C_AMFEncodeEcmaArray: failed to encode property!") + log.Println("C_AMF_EncodeEcmaArray: failed to encode property!") break } else { pBuffer = res @@ -1730,6 +1736,39 @@ func C_AMFEncodeArray(obj *C.AMFObject, pBuffer *byte, pBufEnd *byte) *byte { return pBuffer } +// int AMF_DecodeArray(AMFObject *obj, const char *pBuffer, int nSize, int nArrayLen, int bDecodeName); +func C_AMF_DecodeArray(obj *C.AMFObject, pBuffer *byte, nSize, nArrayLen, bDecodeName int32) int32 { + nOriginalSize := nSize + var bError int32 = FALSE + + obj.o_num = 0 + obj.o_props = nil + for nArrayLen > 0 { + var prop C.AMFObjectProperty + var nRes int32 + nArrayLen-- + + if nSize <= 0 { + bError = TRUE + break + } + nRes = C_AMFProp_Decode(&prop, pBuffer, nSize, bDecodeName) + if nRes == -1 { + bError = TRUE + break + } else { + nSize -= nRes + pBuffer = (*byte)(incBytePtr(unsafe.Pointer(pBuffer), int(nRes))) + C_AMF_AddProp(obj, &prop) + } + } + if bError != 0 { + return -1 + } + + return nOriginalSize - nSize +} + // int RTMP_ConnectStream(RTMP* r, int seekTime); // rtmp.c +1099 func C_RTMP_ConnectStream(r *C.RTMP, seekTime int32) int { @@ -2786,8 +2825,7 @@ func C_AMF_Decode(obj *C.AMFObject, pBuffer *byte, nSize int32, bDecodeName int3 // int AMFProp_Decode(C.AMFOBjectProperty* prop, const char* pBuffer, int nSize, int bDecodeName); // amf.c +619 -func C_AMFProp_Decode(prop *C.AMFObjectProperty, pBuffer *byte, - nSize, bDecodeName int32) int32 { +func C_AMFProp_Decode(prop *C.AMFObjectProperty, pBuffer *byte, nSize, bDecodeName int32) int32 { var nOriginalSize int32 = nSize var nRes int32 @@ -2809,7 +2847,7 @@ func C_AMFProp_Decode(prop *C.AMFObjectProperty, pBuffer *byte, } if bDecodeName != 0 { - var nNameSize uint8 = uint8(C_AMF_DecodeInt16(pBuffer)) + nNameSize := C_AMF_DecodeInt16(pBuffer) if int32(nNameSize) > nSize-2 { // TODO use new logger here //RTMP_Log(RTMP_LOGDEBUG, "%s: Name size out of range: namesize (%d) > len (%d) - 2",__FUNCTION__, nNameSize, nSize); @@ -2842,19 +2880,18 @@ func C_AMFProp_Decode(prop *C.AMFObjectProperty, pBuffer *byte, if nSize < 1 { return -1 } - // TODO port AMF_DecodeBoolean - prop.p_vu.p_number = C.double(C.AMF_DecodeBoolean((*C.char)(unsafe.Pointer(pBuffer)))) + prop.p_vu.p_number = C.double(C_AMF_DecodeBoolean((*byte)(unsafe.Pointer(pBuffer)))) nSize-- case AMF_STRING: { - var nStringSize uint8 = uint8(C_AMF_DecodeInt16(pBuffer)) + var nStringSize = C_AMF_DecodeInt16(pBuffer) if int64(nSize) < int64(nStringSize)+2 { return -1 } C_AMF_DecodeString(pBuffer, &prop.p_vu.p_aval) - nSize -= uint8(2 + nStringSize) + nSize -= int32(2 + nStringSize) } case AMF_OBJECT: @@ -2907,11 +2944,10 @@ func C_AMFProp_Decode(prop *C.AMFObjectProperty, pBuffer *byte, } case AMF_STRICT_ARRAY: { - var nArrayLen uint32 = C_AMF_DecodeInt32(pBuffer) + nArrayLen := int32(C_AMF_DecodeInt32(pBuffer)) nSize -= 4 - nRes = C_AMF_DecodeArray(&prop.p_vu.p_object, pBuffer+4, nSize, - nArrayLen, FALSE) + nRes = C_AMF_DecodeArray(&prop.p_vu.p_object, (*byte)(incBytePtr(unsafe.Pointer(pBuffer), 4)), nSize, int32(nArrayLen), FALSE) if nRes == -1 { return -1 } @@ -2927,8 +2963,8 @@ func C_AMFProp_Decode(prop *C.AMFObjectProperty, pBuffer *byte, return -1 } - prop.p_vu.p_number = C_AMF_DecodeNumber(pBuffer) - prop.p_UTCoffset = C_AMF_DecodeInt16(pBuffer + 8) + prop.p_vu.p_number = C.double(C_AMF_DecodeNumber(pBuffer)) + prop.p_UTCoffset = C.short(C_AMF_DecodeInt16((*byte)(incBytePtr(unsafe.Pointer(pBuffer), 8)))) nSize -= 10 @@ -2937,11 +2973,11 @@ func C_AMFProp_Decode(prop *C.AMFObjectProperty, pBuffer *byte, case AMF_XML_DOC: { var nStringSize uint32 = C_AMF_DecodeInt32(pBuffer) - if nSize < int64(nStringSize)+4 { + if int64(nSize) < int64(nStringSize)+4 { return -1 } - AMF_DecodeLongString(pBuffer, &prop.p_vu.p_aval) - nSize -= (4 + nStringSize) + C_AMF_DecodeLongString(pBuffer, &prop.p_vu.p_aval) + nSize -= int32(4 + nStringSize) if prop.p_type == AMF_LONG_STRING { prop.p_type = AMF_STRING } @@ -2958,13 +2994,13 @@ func C_AMFProp_Decode(prop *C.AMFObjectProperty, pBuffer *byte, case AMF_TYPED_OBJECT: { // TODO use new logger here - RTMP_Log(RTMP_LOGERROR, "AMF_TYPED_OBJECT not supported!") + // RTMP_Log(RTMP_LOGERROR, "AMF_TYPED_OBJECT not supported!") return -1 } case AMF_AVMPLUS: { - var nRes int32 = int32(C.AMF3_Decode(&prop.p_vu.p_object, pBuffer, nSize, 1)) + nRes := int32(C.AMF3_Decode(&prop.p_vu.p_object, (*C.char)(unsafe.Pointer(pBuffer)), C.int(nSize), 1)) if nRes == -1 { return -1 } @@ -3288,11 +3324,11 @@ func C_RTMP_SendPacket(r *C.RTMP, packet *C.RTMPPacket, queue int) int { if t > 0xffffff { res = 0xffffff } - hptr = unsafe.Pointer(C_AMFEncodeInt24((*byte)(hptr), (*byte)(hend), res)) + hptr = unsafe.Pointer(C_AMF_EncodeInt24((*byte)(hptr), (*byte)(hend), res)) } if nSize > 4 { - hptr = unsafe.Pointer(C_AMFEncodeInt24((*byte)(hptr), (*byte)(hend), (int32(packet.m_nBodySize)))) + hptr = unsafe.Pointer(C_AMF_EncodeInt24((*byte)(hptr), (*byte)(hend), (int32(packet.m_nBodySize)))) *(*byte)(hptr) = byte(packet.m_packetType) hptr = incBytePtr(hptr, 1) } @@ -3559,6 +3595,17 @@ func C_AMF_EncodeNumber(output *byte, outend *byte, dVal float64) *byte { return (*byte)(incBytePtr(unsafe.Pointer(output), 8)) } +// void AMF_DecodeLongString(const char *data, AVal *bv); +// amf.c +75 +func C_AMF_DecodeLongString(data *byte, bv *C.AVal) { + bv.av_len = C.int(C_AMF_DecodeInt32(data)) + if bv.av_len > 0 { + bv.av_val = (*C.char)(incBytePtr(unsafe.Pointer(data), 4)) + } else { + bv.av_val = nil + } +} + // double AMF_DecodeNumber(const char* data); // amf.c +82 func C_AMF_DecodeNumber(data *byte) float64 { @@ -3572,6 +3619,15 @@ func C_AMF_DecodeNumber(data *byte) float64 { return dVal } +// int AMF_DecodeBoolean(const char *data); +// amf.c +132 +func C_AMF_DecodeBoolean(data *byte) int32 { + if *data != 0 { + return 1 + } + return 0 +} + // 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 { @@ -3606,7 +3662,7 @@ func C_AMF_DecodeInt16(data *byte) uint16 { // char* AMF_EncodeInt24(char* output, char* outend, int nVal); // amf.c +149 -func C_AMFEncodeInt24(output *byte, outend *byte, nVal int32) *byte { +func C_AMF_EncodeInt24(output *byte, outend *byte, nVal int32) *byte { outputPtr := unsafe.Pointer(output) outendPtr := unsafe.Pointer(outend) if uintptr(outputPtr)+3 > uintptr(outendPtr) {