diff --git a/rtmp/amf.go b/rtmp/amf.go index 2c96068d..6a190521 100644 --- a/rtmp/amf.go +++ b/rtmp/amf.go @@ -39,6 +39,7 @@ package rtmp import "C" import ( + "encoding/binary" "log" "unsafe" ) @@ -91,24 +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) C_AVal { - var bv C_AVal - bv.av_len = int32(C_AMF_DecodeInt16(data)) - if bv.av_len != 0 { - bv.av_val = (*byte)(incBytePtr(unsafe.Pointer(data), 2)) +func C_AMF_DecodeString(data *byte) string { + n := C_AMF_DecodeInt16(data) + if n == 0 { + return "" } - return bv + 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) C_AVal { - var 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)) +func C_AMF_DecodeLongString(data *byte) string { + n := C_AMF_DecodeInt32(data) + if n == 0 { + return "" } - return bv + return string((*[_Gi]byte)(incBytePtr(unsafe.Pointer(data), 4))[:n]) } // double AMF_DecodeNumber(const char* data); @@ -195,33 +194,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) } @@ -264,38 +257,44 @@ 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 int) *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); @@ -363,7 +362,7 @@ func C_AMF_PropEncode(p *C_AMFObjectProperty, pBuffer *byte, pBufEnd *byte) *byt } pBuffer = C_AMF_EncodeBoolean(pBuffer, pBufEnd, val) case AMF_STRING: - pBuffer = C_AMF_EncodeString(pBuffer, pBufEnd, &p.p_vu.p_aval) + pBuffer = C_AMF_EncodeString(pBuffer, pBufEnd, CAV(&p.p_vu.p_aval)) case AMF_NULL: if uintptr(incBytePtr(unsafe.Pointer(pBuffer), 1)) >= uintptr(unsafe.Pointer( pBufEnd)) { @@ -489,7 +488,7 @@ func C_AMFProp_Decode(prop *C_AMFObjectProperty, pBuffer *byte, nSize, bDecodeNa return -1 } - prop.p_name = C_AMF_DecodeString(pBuffer) + prop.p_name = AVC(C_AMF_DecodeString(pBuffer)) nSize -= int32(2 + nNameSize) pBuffer = (*byte)(incBytePtr(unsafe.Pointer(pBuffer), int(2+nNameSize))) } @@ -520,7 +519,7 @@ func C_AMFProp_Decode(prop *C_AMFObjectProperty, pBuffer *byte, nSize, bDecodeNa if int64(nSize) < int64(nStringSize)+2 { return -1 } - prop.p_vu.p_aval = C_AMF_DecodeString(pBuffer) + prop.p_vu.p_aval = AVC(C_AMF_DecodeString(pBuffer)) nSize -= int32(2 + nStringSize) case AMF_OBJECT: diff --git a/rtmp/amf_headers.go b/rtmp/amf_headers.go index 02e5343b..27eb90f1 100644 --- a/rtmp/amf_headers.go +++ b/rtmp/amf_headers.go @@ -81,6 +81,10 @@ func AVC(str string) C_AVal { return aval } +func CAV(av *C_AVal) string { + return string((*[_Gi]byte)(unsafe.Pointer(av.av_val))[:av.av_len]) +} + // #define AVMATCH(a1,a2) // amf.h +63 func C_AVMATCH(a1, a2 *C_AVal) int32 { diff --git a/rtmp/rtmp.go b/rtmp/rtmp.go index 8d74db94..8b77090d 100644 --- a/rtmp/rtmp.go +++ b/rtmp/rtmp.go @@ -737,7 +737,7 @@ func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) (ok bool) { enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = C_AMF_EncodeString(enc, pend, &av_connect) + enc = C_AMF_EncodeString(enc, pend, CAV(&av_connect)) r.m_numInvokes += 1 enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) @@ -746,60 +746,60 @@ func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) (ok bool) { enc = (*byte)(unsafe.Pointer(incBytePtr(unsafe.Pointer(enc), 1))) - enc = C_AMF_EncodeNamedString(enc, pend, &av_app, &r.Link.app) + enc = C_AMF_EncodeNamedString(enc, pend, CAV(&av_app), CAV(&r.Link.app)) if enc == nil { return false } if r.Link.protocol&RTMP_FEATURE_WRITE != 0 { - enc = C_AMF_EncodeNamedString(enc, pend, &av_type, &av_nonprivate) + enc = C_AMF_EncodeNamedString(enc, pend, CAV(&av_type), CAV(&av_nonprivate)) if enc == nil { return false } } if r.Link.flashVer.av_len != 0 { - enc = C_AMF_EncodeNamedString(enc, pend, &av_flashVer, &r.Link.flashVer) + enc = C_AMF_EncodeNamedString(enc, pend, CAV(&av_flashVer), CAV(&r.Link.flashVer)) if enc == nil { return false } } if r.Link.swfUrl.av_len != 0 { - enc = C_AMF_EncodeNamedString(enc, pend, &av_swfUrl, &r.Link.swfUrl) + enc = C_AMF_EncodeNamedString(enc, pend, CAV(&av_swfUrl), CAV(&r.Link.swfUrl)) if enc == nil { return false } } if r.Link.tcUrl.av_len != 0 { - enc = C_AMF_EncodeNamedString(enc, pend, &av_tcUrl, &r.Link.tcUrl) + enc = C_AMF_EncodeNamedString(enc, pend, CAV(&av_tcUrl), CAV(&r.Link.tcUrl)) if enc == nil { return false } } if r.Link.protocol&RTMP_FEATURE_WRITE == 0 { - enc = C_AMF_EncodeNamedBoolean(enc, pend, &av_fpad, 0) + enc = C_AMF_EncodeNamedBoolean(enc, pend, CAV(&av_fpad), 0) if enc == nil { return false } - enc = C_AMF_EncodeNamedNumber(enc, pend, &av_capabilities, 15.0) + enc = C_AMF_EncodeNamedNumber(enc, pend, CAV(&av_capabilities), 15) if enc == nil { return false } - enc = C_AMF_EncodeNamedNumber(enc, pend, &av_audioCodecs, float64(r.m_fAudioCodecs)) + enc = C_AMF_EncodeNamedNumber(enc, pend, CAV(&av_audioCodecs), float64(r.m_fAudioCodecs)) if enc == nil { return false } - enc = C_AMF_EncodeNamedNumber(enc, pend, &av_videoCodecs, float64(r.m_fVideoCodecs)) + enc = C_AMF_EncodeNamedNumber(enc, pend, CAV(&av_videoCodecs), float64(r.m_fVideoCodecs)) if enc == nil { return false } - enc = C_AMF_EncodeNamedNumber(enc, pend, &av_videoFunction, 1.0) + enc = C_AMF_EncodeNamedNumber(enc, pend, CAV(&av_videoFunction), 1) if enc == nil { return false } if r.Link.pageUrl.av_len != 0 { - enc = C_AMF_EncodeNamedString(enc, pend, &av_pageUrl, &r.Link.pageUrl) + enc = C_AMF_EncodeNamedString(enc, pend, CAV(&av_pageUrl), CAV(&r.Link.pageUrl)) if enc == nil { return false } @@ -807,7 +807,7 @@ func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) (ok bool) { } if r.m_fEncoding != 0.0 || r.m_bSendEncoding != 0 { - enc = C_AMF_EncodeNamedNumber(enc, pend, &av_objectEncoding, float64(r.m_fEncoding)) + enc = C_AMF_EncodeNamedNumber(enc, pend, CAV(&av_objectEncoding), float64(r.m_fEncoding)) if enc == nil { return false } @@ -831,7 +831,7 @@ func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) (ok bool) { if enc == nil { return false } - enc = C_AMF_EncodeString(enc, (*byte)(pend), &r.Link.auth) + enc = C_AMF_EncodeString(enc, (*byte)(pend), CAV(&r.Link.auth)) if enc == nil { return false } @@ -873,7 +873,7 @@ func C_RTMP_SendCreateStream(r *C_RTMP) (ok bool) { 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, CAV(&av_createStream)) r.m_numInvokes++ enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) *enc = AMF_NULL @@ -903,12 +903,12 @@ func C_SendReleaseStream(r *C_RTMP) (ok bool) { 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, CAV(&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, CAV(&r.Link.playpath)) if enc == nil { return false } @@ -936,12 +936,12 @@ func C_SendFCPublish(r *C_RTMP) (ok bool) { 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, CAV(&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, CAV(&r.Link.playpath)) if enc == nil { return false } @@ -969,12 +969,12 @@ func C_SendFCUnpublish(r *C_RTMP) (ok bool) { packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = C_AMF_EncodeString(enc, pend, &av_FCUnpublish) + enc = C_AMF_EncodeString(enc, pend, CAV(&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) + enc = C_AMF_EncodeString(enc, pend, CAV(&r.Link.playpath)) if enc == nil { return false @@ -1004,18 +1004,18 @@ func C_SendPublish(r *C_RTMP) (ok bool) { 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, CAV(&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, CAV(&r.Link.playpath)) if enc == nil { return false } - enc = C_AMF_EncodeString(enc, pend, &av_live) + enc = C_AMF_EncodeString(enc, pend, CAV(&av_live)) if enc == nil { return false } @@ -1044,7 +1044,7 @@ func C_SendDeleteStream(r *C_RTMP, dStreamId float64) (ok bool) { packet.m_body = &pbuf[RTMP_MAX_HEADER_SIZE] enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = C_AMF_EncodeString(enc, pend, &av_deleteStream) + enc = C_AMF_EncodeString(enc, pend, CAV(&av_deleteStream)) r.m_numInvokes++ enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) *enc = AMF_NULL @@ -1100,7 +1100,7 @@ func C_SendCheckBW(r *C_RTMP) (ok bool) { 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, CAV(&av__checkbw)) r.m_numInvokes++ enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) *enc = AMF_NULL @@ -1135,23 +1135,20 @@ func C_AV_erase(vals *C_RTMP_METHOD, num *int32, i, freeit int32) { // 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)(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' + tmp := make([]byte, len(av)+1) + copy(tmp, av) (*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(*vals), int(*num), - int(unsafe.Sizeof(*(*vals)))))).num = int32(txn) + 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 + int(unsafe.Sizeof(**vals))))).name.av_len = int32(len(av)) (*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(*vals), int(*num), - int(unsafe.Sizeof(*(*vals)))))).name.av_val = (*byte)(tmp) - (*num)++ + int(unsafe.Sizeof(**vals))))).name.av_val = &tmp[0] + *num++ } // int HandleInvoke(RTMP* r, const char* body, unsigned int nBodySize); @@ -1863,15 +1860,13 @@ func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) (ok bool) { 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))) - 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) } } @@ -2076,7 +2071,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])), CAV(&setDataFrame))))[:pkt.m_nBodySize] // TODO: work out what to do with this pkt.m_nBytesRead = uint32(float64(uintptr(unsafe.Pointer(&enc[0])) -