diff --git a/rtmp/rtmp.go b/rtmp/rtmp.go index 0f0ed99e..334f2bcf 100644 --- a/rtmp/rtmp.go +++ b/rtmp/rtmp.go @@ -803,7 +803,8 @@ func handShake(r *C.RTMP, FP9HandShake int32) int { func sendConnectPacket(r *C.RTMP, cp *C.RTMPPacket) int { var packet C.RTMPPacket var pbuf [4096]byte - pend := incBytePtr(unsafe.Pointer(&pbuf[0]), int(unsafe.Sizeof(pbuf))) + pend := (*byte)(unsafe.Pointer(incBytePtr(unsafe.Pointer(&pbuf[0]), + int(unsafe.Sizeof(pbuf))))) var enc *byte if cp != nil { @@ -820,25 +821,20 @@ func sendConnectPacket(r *C.RTMP, cp *C.RTMPPacket) int { RTMP_MAX_HEADER_SIZE)) enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = afmEncodeString(enc, (*byte)(pend), &av_connect) + enc = amfEncodeString(enc, (*byte)(pend), &av_connect) r.m_numInvokes += 1 // TODO: port this - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNumber((*C.char)(unsafe.Pointer(enc)), - (*C.char)(unsafe.Pointer(pend)), - C.double(r.m_numInvokes)))) + enc = amfEncodeNumber(enc, pend, float64(r.m_numInvokes)) // TODO: port this const *indxBytePtr(unsafe.Pointer(enc), 0) = C.AMF_OBJECT // TODO: port this - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer( - enc)), (*C.char)(unsafe.Pointer(pend)), &av_app, &r.Link.app))) - + enc = amfEncodeNamedString(enc, pend, &av_app, &r.Link.app) if enc == nil { return 0 } if r.Link.protocol&RTMP_FEATURE_WRITE != 0 { - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer(enc)), - (*C.char)(unsafe.Pointer(pend)), &av_type, &av_nonprivate))) + enc = amfEncodeNamedString(enc, pend, &av_type, &av_nonprivate) if enc == nil { return 0 @@ -846,23 +842,20 @@ func sendConnectPacket(r *C.RTMP, cp *C.RTMPPacket) int { } if r.Link.flashVer.av_len != 0 { - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer(enc)), - (*C.char)(unsafe.Pointer(pend)), &av_flashVer, &r.Link.flashVer))) + enc = amfEncodeNamedString(enc, pend, &av_flashVer, &r.Link.flashVer) if enc == nil { return 0 } } if r.Link.swfUrl.av_len != 0 { - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer(enc)), - (*C.char)(unsafe.Pointer(pend)), &av_swfUrl, &r.Link.swfUrl))) + enc = amfEncodeNamedString(enc, pend, &av_swfUrl, &r.Link.swfUrl) if enc == nil { return 0 } } if r.Link.tcUrl.av_len != 0 { - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer(enc)), - (*C.char)(unsafe.Pointer(pend)), &av_tcUrl, &r.Link.tcUrl))) + enc = amfEncodeNamedString(enc, pend, &av_tcUrl, &r.Link.tcUrl) if enc == nil { return 0 } @@ -870,35 +863,28 @@ func sendConnectPacket(r *C.RTMP, cp *C.RTMPPacket) int { if r.Link.protocol&RTMP_FEATURE_WRITE == 0 { // TODO: port this - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedBoolean((*C.char)( - unsafe.Pointer(enc)), (*C.char)(unsafe.Pointer(pend)), &av_fpad, 0))) + enc = C.AMF_EncodeNamedBoolean(enc, pend, &av_fpad, 0) if enc == nil { return 0 } - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*C.char)( - unsafe.Pointer(enc)), (*C.char)(unsafe.Pointer(pend)), &av_capabilities, - 15.0))) + enc = C.AMF_EncodeNamedNumber(enc, pend, &av_capabilities, 15.0) if enc == nil { return 0 } - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*C.char)(unsafe.Pointer(enc)), (*C.char)( - unsafe.Pointer(pend)), &av_audioCodecs, r.m_fAudioCodecs))) + enc = C.AMF_EncodeNamedNumber(enc, pend, &av_audioCodecs, r.m_fAudioCodecs) if enc == nil { return 0 } - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*C.char)(unsafe.Pointer(enc)), (*C.char)( - unsafe.Pointer(pend)), &av_videoCodecs, r.m_fVideoCodecs))) + enc = C.AMF_EncodeNamedNumber(enc, pend, &av_videoCodecs, r.m_fVideoCodecs) if enc == nil { return 0 } - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*C.char)(unsafe.Pointer(enc)), (*C.char)( - unsafe.Pointer(pend)), &av_videoFunction, 1.0))) + enc = C.AMF_EncodeNamedNumber(enc, pend, &av_videoFunction, 1.0) if enc == nil { return 0 } if r.Link.pageUrl.av_len != 0 { - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer(enc)), (*C.char)( - unsafe.Pointer(pend)), &av_pageUrl, &r.Link.pageUrl))) + enc = amfEncodeNamedString(enc, pend, &av_pageUrl, &r.Link.pageUrl) if enc == nil { return 0 } @@ -906,8 +892,7 @@ func sendConnectPacket(r *C.RTMP, cp *C.RTMPPacket) int { } if r.m_fEncoding != 0.0 || r.m_bSendEncoding != 0 { - enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*C.char)(unsafe.Pointer(enc)), (*C.char)( - unsafe.Pointer(pend)), &av_objectEncoding, r.m_fEncoding))) + enc = C.AMF_EncodeNamedNumber(enc, pend, &av_objectEncoding, r.m_fEncoding) if enc == nil { return 0 } @@ -933,7 +918,7 @@ func sendConnectPacket(r *C.RTMP, cp *C.RTMPPacket) int { if enc == nil { return 0 } - enc = afmEncodeString(enc, (*byte)(pend), &r.Link.auth) + enc = amfEncodeString(enc, (*byte)(pend), &r.Link.auth) if enc == nil { return 0 } @@ -952,8 +937,8 @@ func sendConnectPacket(r *C.RTMP, cp *C.RTMPPacket) int { } } - packet.m_nBodySize = C.uint32_t(int(uintptr(decBytePtr(unsafe.Pointer(enc), int(uintptr( - unsafe.Pointer(packet.m_body))))))) + packet.m_nBodySize = C.uint32_t(int(uintptr(decBytePtr(unsafe.Pointer(enc), + int(uintptr(unsafe.Pointer(packet.m_body))))))) return sendPacket(r, &packet, 1) } @@ -1037,9 +1022,9 @@ func rtmpWrite(r *C.RTMP, data []byte) int { pkt.m_packetType = C.uint8_t(*indxBytePtr(buf, 0)) buf = incBytePtr(buf, 1) - pkt.m_nBodySize = C.uint32_t(afmDecodeInt24((*byte)(buf))) + pkt.m_nBodySize = C.uint32_t(amfDecodeInt24((*byte)(buf))) buf = incBytePtr(buf, 3) - pkt.m_nTimeStamp = C.uint32_t(afmDecodeInt24((*byte)(buf))) + pkt.m_nTimeStamp = C.uint32_t(amfDecodeInt24((*byte)(buf))) buf = incBytePtr(buf, 3) pkt.m_nTimeStamp |= C.uint32_t(*indxBytePtr(buf, 0)) << 24 buf = incBytePtr(buf, 4) @@ -1067,7 +1052,7 @@ func rtmpWrite(r *C.RTMP, data []byte) int { pend = incBytePtr(enc, int(pkt.m_nBodySize)) if pkt.m_packetType == RTMP_PACKET_TYPE_INFO { - enc = unsafe.Pointer(afmEncodeString((*byte)(enc), (*byte)(pend), &setDataFrame)) + enc = unsafe.Pointer(amfEncodeString((*byte)(enc), (*byte)(pend), &setDataFrame)) pkt.m_nBytesRead = C.uint32_t(math.Abs(float64(uintptr(enc) - uintptr(unsafe.Pointer(pkt.m_body))))) } @@ -1103,93 +1088,6 @@ func rtmpWrite(r *C.RTMP, data []byte) int { return size + s2 } -// afmDecodeInt24 decodes data into an unsigned int -func afmDecodeInt24(data *byte) uint32 { - // TODO Understand logic and simplify - c := (*uint8)(unsafe.Pointer(data)) - dst := uint32(int32(*c) << 16) - dst |= uint32(int32(*((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(c)) + - (uintptr)(int32(1))*unsafe.Sizeof(*c))))) << 8) - dst |= uint32(int32(*((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(c)) + - (uintptr)(int32(2))*unsafe.Sizeof(*c)))))) - return dst -} - -func afmEncodeString(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) { - return nil - } - - if bv.av_len < 65536 { - *(*C.char)(outputPtr) = C.AMF_STRING - incBytePtr(outputPtr, 1) - - outputPtr = unsafe.Pointer(afmEncodeInt16((*byte)(outputPtr), - (*byte)(outendPtr), (int16)(bv.av_len))) - } else { - *(*C.char)(outputPtr) = C.AMF_LONG_STRING - incBytePtr(outputPtr, 1) - - outputPtr = unsafe.Pointer(afmEncodeInt32((*byte)(outputPtr), - (*byte)(outendPtr), (int32)(bv.av_len))) - } - 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)) - incBytePtr(outputPtr, int(bv.av_len)) - - return (*byte)(outputPtr) -} - -// afmEncodeInt16 encodes a int16 into data -func afmEncodeInt16(output *byte, outend *byte, nVal int16) *byte { - outputPtr := unsafe.Pointer(output) - outendPtr := unsafe.Pointer(outend) - if uintptr(outputPtr)+2 > uintptr(outendPtr) { - // length < 2 - return nil - } - - // Assign output[1] - second := (*byte)(incBytePtr(outputPtr, 1)) - *second = (byte)(nVal & 0xff) - - // Assign output[0] - *output = (byte)(nVal >> 8) - - return (*byte)(incBytePtr(outputPtr, 2)) -} - -// afmEncodeInt32 encodes a int32 into data -func afmEncodeInt32(output *byte, outend *byte, nVal int32) *byte { - outputPtr := unsafe.Pointer(output) - outendPtr := unsafe.Pointer(outend) - if uintptr(outputPtr)+4 > uintptr(outendPtr) { - // length < 4 - return nil - } - - // Assign output[3] - forth := (*byte)(incBytePtr(outputPtr, 3)) - *forth = (byte)(nVal & 0xff) - - // Assign output[2] - third := (*byte)(incBytePtr(outputPtr, 2)) - *third = (byte)(nVal >> 8) - - // Assign output[1] - second := (*byte)(incBytePtr(outputPtr, 1)) - *second = (byte)(nVal >> 16) - - // Assign output[0] - *output = (byte)(nVal >> 24) - - return (*byte)(incBytePtr(outputPtr, 4)) -} - // send packet version 1 - less C stuff func sendPacket(r *C.RTMP, packet *C.RTMPPacket, queue int) int { var prevPacket *C.RTMPPacket @@ -1310,11 +1208,11 @@ func sendPacket(r *C.RTMP, packet *C.RTMPPacket, queue int) int { if t > 0xffffff { res = 0xffffff } - hptr = unsafe.Pointer(afmEncodeInt24((*byte)(hptr), (*byte)(hend), res)) + hptr = unsafe.Pointer(amfEncodeInt24((*byte)(hptr), (*byte)(hend), res)) } if nSize > 4 { - hptr = unsafe.Pointer(afmEncodeInt24((*byte)(hptr), (*byte)(hend), (int32(packet.m_nBodySize)))) + hptr = unsafe.Pointer(amfEncodeInt24((*byte)(hptr), (*byte)(hend), (int32(packet.m_nBodySize)))) *(*byte)(hptr) = byte(packet.m_packetType) hptr = incBytePtr(hptr, 1) } @@ -1325,7 +1223,7 @@ func sendPacket(r *C.RTMP, packet *C.RTMPPacket, queue int) int { } if t >= 0xffffff { - hptr = unsafe.Pointer(afmEncodeInt32((*byte)(hptr), (*byte)(hend), (int32)(t))) + hptr = unsafe.Pointer(amfEncodeInt32((*byte)(hptr), (*byte)(hend), (int32)(t))) } nSize = int(packet.m_nBodySize) @@ -1402,7 +1300,7 @@ func sendPacket(r *C.RTMP, packet *C.RTMPPacket, queue int) int { } if t >= 0xffffff { extendedTimestamp := incBytePtr(header, 1+cSize) - afmEncodeInt32((*byte)(extendedTimestamp), + amfEncodeInt32((*byte)(extendedTimestamp), (*byte)(incBytePtr(extendedTimestamp, 4)), (int32)(t)) } } @@ -1427,7 +1325,7 @@ func sendPacket(r *C.RTMP, packet *C.RTMPPacket, queue int) int { var method C.AVal var ptr unsafe.Pointer ptr = incBytePtr(unsafe.Pointer(packet.m_body), 1) - afmDecodeString((*byte)(ptr), &method) + amfDecodeString((*byte)(ptr), &method) if debugMode { log.Printf("Invoking %v", method.av_val) @@ -1454,53 +1352,9 @@ func 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))) - //C.memcpy(unsafe.Pointer(*(**C.RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsOut), - //int(packet.m_nChannel), int(unsafe.Sizeof(packet))))), unsafe.Pointer(packet), - //C.size_t(uintptr(unsafe.Sizeof(*packet)))) return 1 } -// afmDecodeString decodes data into a string inside a AVal -func afmDecodeString(data *byte, bv *C.AVal) { - dataPtr := unsafe.Pointer(data) - bv.av_len = C.int(afmDecodeInt16((*byte)(dataPtr))) - - if bv.av_len > 0 { - bv.av_val = (*C.char)(incBytePtr(dataPtr, 2)) - } else { - bv.av_val = nil - } -} - -// afmDecodeInt16 decodes data into a 16 bit number -func afmDecodeInt16(data *byte) uint16 { - c := unsafe.Pointer(data) - return (uint16(*(*uint8)(c)) << 8) | *(*uint16)(incBytePtr(c, 1)) -} - -// afmEncodeInt24 encodes a int24 into data -func afmEncodeInt24(output *byte, outend *byte, nVal int32) *byte { - outputPtr := unsafe.Pointer(output) - outendPtr := unsafe.Pointer(outend) - if uintptr(outputPtr)+3 > uintptr(outendPtr) { - // length < 3 - return nil - } - - // Assign output[2] - third := (*byte)(incBytePtr(outputPtr, 2)) - *third = (byte)(nVal & 0xff) - - // Assign output[1] - second := (*byte)(incBytePtr(outputPtr, 1)) - *second = (byte)(nVal >> 8) - - // Assign output[0] - *output = (byte)(nVal >> 16) - - return (*byte)(incBytePtr(outputPtr, 3)) -} - func writeN(r *C.RTMP, buffer unsafe.Pointer, n int) int { ptr := buffer for n > 0 { @@ -1566,6 +1420,170 @@ func avQueue(vals **C.RTMP_METHOD, num *int, av *C.AVal, txn int) { int(unsafe.Sizeof(rtmpMethodPtr))))).name.av_val = (*C.char)(tmp) } +func amfEncodeNamedNumber(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))) { + return nil + } + output = amfEncodeInt16(output, outend, int16(strName.av_len)) + memmove(unsafe.Pointer(output), unsafe.Pointer(outend), uintptr(strName.av_len)) + output = (*byte)(incBytePtr(unsafe.Pointer(output), int(strName.av_len))) + return amfEncodeNumber(output, outend, dVal) +} + +func amfEncodeNamedBoolean(output *byte, outend *byte, strName *AVal, bVal int) *byte { + if int(uintptr(unsafe.Pointer(output)))+2+int(strName.av_len) > int(uintptr(unsafe.Pointer(outend))) { + return nil + } + output = amfEncodeInt16(output, outend, int16(strName.av_len)) + memmove(unsafe.Pointer(output), unsafe.Pointer(outend), uintptr(strName.av_len)) + output = (*byte)(incBytePtr(unsafe.Pointer(output), int(strName.av_len))) + + return amfEncodeBoolean(output, outend, dVal) +} + +func amfEncodeNumber(output *byte, outend *byte, dVal float64) *byte { + if int(uintptr(unsafe.Pointer(output)))+1+8 > int(uintptr(unsafe.Pointer(outend))) { + return nil + } + + // TODO: port this + *(*byte)(unsafe.Pointer(enc)) = C.AMF_NUMBER + output = (*byte)(incBytePtr(unsafe.Pointer(output), 1)) + + // NOTE: here we are assuming little endian for both byte order and float + // word order + var ci, co *uint8 + ci = (*uint8)(unsafe.Pointer(&dVal)) + co = (*uint8)(unsafe.Pointer(output)) + + for i := 0; i < 8; i++ { + *indxBytePtr(unsafe.Pointer(co), i) = *indxBytePtr(unsafe.Pointer(ci), 7-i) + } + + return (*Byte)(incBytePtr(unsafe.Pointer(output), 8)) +} + +func amfEncodeNamedString(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))) { + return nil + } + output = amfEncodeInt16(output, outend, int16(strName.av_len)) + memmove(unsafe.Pointer(output), unsafe.Pointer(outend), uintptr(strName.av_len)) + output = (*byte)(incBytePtr(unsafe.Pointer(output), int(strName.av_len))) + return amfEncodeString(output, outend, strValue) +} + +// amfDecodeString decodes data into a string inside a AVal +func amfDecodeString(data *byte, bv *C.AVal) { + dataPtr := unsafe.Pointer(data) + bv.av_len = C.int(amfDecodeInt16((*byte)(dataPtr))) + if bv.av_len > 0 { + bv.av_val = (*C.char)(incBytePtr(dataPtr, 2)) + } else { + bv.av_val = nil + } +} + +// amfDecodeInt16 decodes data into a 16 bit number +func amfDecodeInt16(data *byte) uint16 { + c := unsafe.Pointer(data) + return (uint16(*(*uint8)(c)) << 8) | *(*uint16)(incBytePtr(c, 1)) +} + +// amfEncodeInt24 encodes a int24 into data +func amfEncodeInt24(output *byte, outend *byte, nVal int32) *byte { + outputPtr := unsafe.Pointer(output) + outendPtr := unsafe.Pointer(outend) + if uintptr(outputPtr)+3 > uintptr(outendPtr) { + // length < 3 + return nil + } + // Assign output[2] + third := (*byte)(incBytePtr(outputPtr, 2)) + *third = (byte)(nVal & 0xff) + // Assign output[1] + second := (*byte)(incBytePtr(outputPtr, 1)) + *second = (byte)(nVal >> 8) + // Assign output[0] + *output = (byte)(nVal >> 16) + return (*byte)(incBytePtr(outputPtr, 3)) +} + +// amfDecodeInt24 decodes data into an unsigned int +func amfDecodeInt24(data *byte) uint32 { + // TODO Understand logic and simplify + c := (*uint8)(unsafe.Pointer(data)) + dst := uint32(int32(*c) << 16) + dst |= uint32(int32(*((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(c)) + + (uintptr)(int32(1))*unsafe.Sizeof(*c))))) << 8) + dst |= uint32(int32(*((*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(c)) + + (uintptr)(int32(2))*unsafe.Sizeof(*c)))))) + return dst +} + +func amfEncodeString(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) { + return nil + } + if bv.av_len < 65536 { + *(*C.char)(outputPtr) = C.AMF_STRING + incBytePtr(outputPtr, 1) + outputPtr = unsafe.Pointer(amfEncodeInt16((*byte)(outputPtr), + (*byte)(outendPtr), (int16)(bv.av_len))) + } else { + *(*C.char)(outputPtr) = C.AMF_LONG_STRING + incBytePtr(outputPtr, 1) + outputPtr = unsafe.Pointer(amfEncodeInt32((*byte)(outputPtr), + (*byte)(outendPtr), (int32)(bv.av_len))) + } + 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)) + incBytePtr(outputPtr, int(bv.av_len)) + return (*byte)(outputPtr) +} + +// amfEncodeInt16 encodes a int16 into data +func amfEncodeInt16(output *byte, outend *byte, nVal int16) *byte { + outputPtr := unsafe.Pointer(output) + outendPtr := unsafe.Pointer(outend) + if uintptr(outputPtr)+2 > uintptr(outendPtr) { + // length < 2 + return nil + } + // Assign output[1] + second := (*byte)(incBytePtr(outputPtr, 1)) + *second = (byte)(nVal & 0xff) + // Assign output[0] + *output = (byte)(nVal >> 8) + return (*byte)(incBytePtr(outputPtr, 2)) +} + +// amfEncodeInt32 encodes a int32 into data +func amfEncodeInt32(output *byte, outend *byte, nVal int32) *byte { + outputPtr := unsafe.Pointer(output) + outendPtr := unsafe.Pointer(outend) + if uintptr(outputPtr)+4 > uintptr(outendPtr) { + // length < 4 + return nil + } + // Assign output[3] + forth := (*byte)(incBytePtr(outputPtr, 3)) + *forth = (byte)(nVal & 0xff) + // Assign output[2] + third := (*byte)(incBytePtr(outputPtr, 2)) + *third = (byte)(nVal >> 8) + // Assign output[1] + second := (*byte)(incBytePtr(outputPtr, 1)) + *second = (byte)(nVal >> 16) + // Assign output[0] + *output = (byte)(nVal >> 24) + return (*byte)(incBytePtr(outputPtr, 4)) +} + // TODO: write test for this func func memcmp(a, b unsafe.Pointer, size int) int { for i := 0; i < size; i++ {