diff --git a/rtmp/rtmp.go b/rtmp/rtmp.go index 95ca0b8f..aaac0d87 100644 --- a/rtmp/rtmp.go +++ b/rtmp/rtmp.go @@ -190,12 +190,72 @@ func startSession(rtmp *C_RTMP, u string, timeout uint32) (*C_RTMP, error) { return rtmp, nil } +func endSession(rtmp *C_RTMP) uint32 { + if rtmp == nil { + return 3 + } + + //C.RTMP_Close(rtmp) + //C.RTMP_Free(rtmp) + return 0 +} + +// #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 + } +} + +// #define 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 +} + // uint32_t RTMP_GetTime(); // rtmp.c +156 func C_RTMP_GetTime() int32 { return int32(time.Now().UnixNano() / 1000000) } +// int RTMPPacket_Alloc(RTMPPacket* p, uint32_t nSize); +// rtmp.c +189 +func C_RTMPPacket_Alloc(p *C_RTMPPacket, nSize uint32) int { + var ptr *byte + // TODO: port C.SIZE_MAX + // also work out how to deal with the overfloat + /* + if int64(nSize) > (C.SIZE_MAX - RTMP_MAX_HEADER_SIZE) { + return 0 + } + */ + ptr = (*byte)(calloc(1, uintptr(nSize+RTMP_MAX_HEADER_SIZE))) + + if ptr == nil { + return 0 + } + p.m_body = (*byte)(incBytePtr(unsafe.Pointer(ptr), RTMP_MAX_HEADER_SIZE)) + p.m_nBytesRead = 0 + return 1 +} + +// 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 + } +} + // RTMP* RTMP_IsConnected(); // rtmp.c +317 func C_RTMP_Alloc() *C_RTMP { @@ -575,6 +635,181 @@ func C_SocksNegotiate(r *C_RTMP) int { } } +// int RTMP_ConnectStream(RTMP* r, int seekTime); +// rtmp.c +1099 +func C_RTMP_ConnectStream(r *C_RTMP, seekTime int32) int { + var packet C_RTMPPacket + memset((*byte)(unsafe.Pointer(&packet)), 0, int(unsafe.Sizeof(packet))) + + if seekTime > 0 { + r.Link.seekTime = int32(seekTime) + } + + 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 { + + // TODO: port is ready + if C_RTMPPacket_IsReady(&packet) != 0 { + if packet.m_nBodySize == 0 { + continue + } + + if packet.m_packetType == RTMP_PACKET_TYPE_AUDIO || + packet.m_packetType == RTMP_PACKET_TYPE_VIDEO || + packet.m_packetType == RTMP_PACKET_TYPE_INFO { + log.Println("C_RTMP_ConnectStream: got packet before play()! Ignoring.") + C_RTMPPacket_Free(&packet) + continue + } + + //C.RTMP_ClientPacket(r, &packet) + C_RTMP_ClientPacket(r, &packet) + C_RTMPPacket_Free(&packet) + } + } + return int(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 + switch packet.m_packetType { + + case RTMP_PACKET_TYPE_CHUNK_SIZE: + log.Println("RTMP_PACKET_TYPE_CHUNK_SIZE") + // TODO: port this + //C.HandleChangeChunkSize(r, packet) + C_HandleChangeChunkSize(r, packet) + /* + case RTMP_PACKET_TYPE_BYTES_READ_REPORT: + log.Println("RTMP_PACKET_TYPE_BYTES_READ_REPORT") + // TODO: usue new logger here + //RTMP_Log(RTMP_LOGDEBUG, "%s, received: bytes read report", __FUNCTION__); + + case RTMP_PACKET_TYPE_CONTROL: + log.Println("RTMP_PACKET_TYPE_CONTROL") + // TODO: port this + C.HandleCtrl(r, packet) + */ + case RTMP_PACKET_TYPE_SERVER_BW: + log.Println("RTMP_PACKET_TYPE_SERVER_BW") + // TODO: port this + //C.HandleServerBW(r, packet) + C_HandlServerBW(r, packet) + + case RTMP_PACKET_TYPE_CLIENT_BW: + log.Println("RTMP_PACKET_TYPE_CLIENT_BW") + // TODO: port this + //C.HandleClientBW(r, packet) + C_HandleClientBW(r, packet) + /* + case RTMP_PACKET_TYPE_AUDIO: + log.Println("RTMP_PACKET_TYPE_AUDIO") + // TODO port this + //C.HandleAudio(r, packet) NOTE this does nothing + bHasMediaPacket = 1 + if r.m_mediaChannel == 0 { + r.m_mediaChannel = packet.m_nChannel + } + + if r.m_pausing == 0 { + r.m_mediaStamp = packet.m_nTimeStamp + } + + case RTMP_PACKET_TYPE_VIDEO: + log.Println("RTMP_PACKET_TYPE_VIDEO:") + // TODO port this + // C.HandleVideo(r, packet) NOTE this does nothing + bHasMediaPacket = 1 + if r.m_mediaChannel == 0 { + r.m_mediaChannel = packet.m_nChannel + } + if r.m_pausing == 0 { + r.m_mediaStamp = packet.m_nTimeStamp + } + + case RTMP_PACKET_TYPE_FLEX_MESSAGE: + log.Println("RTMP_PACKET_TYPE_FLEX_MESSAGE:") + { + // TODO use new logger here + // RTMP_Log(RTMP_LOGDEBUG,"%s, flex message, size %u bytes, not fully supported", __FUNCTION__, packet.m_nBodySize); + + if C.HandleInvoke(r, (*byte)(incBytePtr(unsafe.Pointer(packet.m_body), 1)), + C.uint(packet.m_nBodySize-1)) == 1 { + bHasMediaPacket = 2 + } + } + case RTMP_PACKET_TYPE_INFO: + log.Println(" RTMP_PACKET_TYPE_INFO:") + // TODO use new logger here + //RTMP_Log(RTMP_LOGDEBUG, "%s, received: notify %u bytes", __FUNCTION__,packet.m_nBodySize); + if C.HandleMetadata(r, packet.m_body, C.uint(packet.m_nBodySize)) != 0 { + bHasMediaPacket = 1 + } + */ + + case RTMP_PACKET_TYPE_INVOKE: + log.Println("RTMP_PACKET_TYPE_INVOKE:") + // 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 { + log.Println("HasMediaPacket") + bHasMediaPacket = 2 + } + /* + case RTMP_PACKET_TYPE_FLASH_VIDEO: + log.Println("RTMP_PACKET_TYPE_FLASH_VIDEO:") + { + var pos uint32 = 0 + var nTimeStamp uint32 = uint32(packet.m_nTimeStamp) + + for pos+11 < uint32(packet.m_nBodySize) { + var dataSize uint32 = C_AMF_DecodeInt24((*byte)(incBytePtr(unsafe.Pointer( + packet.m_body), int(pos+1)))) + + if pos+11+dataSize+4 > uint32(packet.m_nBodySize) { + // TODO use new logger here + // RTMP_Log(RTMP_LOGWARNING, "Stream corrupt?!"); + break + } + + switch { + case *indxBytePtr(unsafe.Pointer(packet.m_body), int(pos)) == 0x12: + C.HandleMetadata(r, (*byte)(incBytePtr(unsafe.Pointer(packet.m_body), + int(pos+11))), C.uint(dataSize)) + case *indxBytePtr(unsafe.Pointer(packet.m_body), int(pos)) == 8 || + *indxBytePtr(unsafe.Pointer(packet.m_body), int(pos)) == 9: + nTimeStamp = C_AMF_DecodeInt24((*byte)(incBytePtr(unsafe.Pointer( + packet.m_body), int(pos+4)))) + nTimeStamp |= uint32(*indxBytePtr(unsafe.Pointer(packet.m_body), + int(pos+7)) << 24) + } + pos += (11 + dataSize + 4) + } + if r.m_pausing == 0 { + r.m_mediaStamp = uint32(nTimeStamp) + } + + bHasMediaPacket = 1 + + } + default: + log.Println("DEFAULT") + // TODO use new logger here + // RTMP_Log(RTMP_LOGDEBUG, "%s, unknown packet type received: 0x%02x", __FUNCTION__,packet.m_packetType); + */ + } + return bHasMediaPacket +} + // int ReadN(RTMP* r, char* buffer, int n); // rtmp.c +1390 func C_ReadN(r *C_RTMP, buffer *byte, n int) int { @@ -636,6 +871,40 @@ func C_ReadN(r *C_RTMP, buffer *byte, n int) int { return nOriginalSize - n } +// int WriteN(RTMP* r, const char* buffer, int n); +// rtmp.c +1502 +func C_WriteN(r *C_RTMP, buffer unsafe.Pointer, n int) int { + ptr := buffer + for n > 0 { + var nBytes int + + nBytes = int(C_RTMPSockBuf_Send(&r.m_sb, (*byte)(ptr), int32(n))) + + if nBytes < 0 { + if debugMode { + log.Println("C_WriteN, RTMP send error") + } + + // TODO: port this + //C.RTMP_Close(r) + n = 1 + break + } + + if nBytes == 0 { + break + } + + n -= nBytes + ptr = incBytePtr(ptr, nBytes) + } + + if n == 0 { + return 1 + } + return 0 +} + // int SendConnectPacket(RTMP* r, RTMPPacket* cp); // rtmp.c +1579 func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) int { @@ -816,6 +1085,146 @@ func C_SendConnectPacket(r *C_RTMP, cp *C_RTMPPacket) int { return C_RTMP_SendPacket(r, &packet, 1) } +// int RTMP_SendCreateStream(RTMP* r); +// rtmp.c +1725 +func C_RTMP_SendCreateStream(r *C_RTMP) int32 { + var packet C_RTMPPacket + var pbuf [256]byte + var pend *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&pbuf[0])) + + unsafe.Sizeof(pbuf))) + 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 = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), + int(RTMP_MAX_HEADER_SIZE))) + + enc = (*byte)(unsafe.Pointer(packet.m_body)) + enc = C_AMF_EncodeString(enc, pend, &av_createStream) + r.m_numInvokes++ + enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) + *enc = AMF_NULL + enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) + + packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( + unsafe.Pointer(packet.m_body))) + + return int32(C_RTMP_SendPacket(r, &packet, 1)) +} + +// int SendReleaseStream(RTMP* r); +// rtmp.c +1816 +func C_SendReleaseStream(r *C_RTMP) int32 { + 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 /* 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 = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), + int(RTMP_MAX_HEADER_SIZE))) + + enc = (*byte)(unsafe.Pointer(packet.m_body)) + 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) + if enc == nil { + return 0 + } + packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( + unsafe.Pointer(packet.m_body))) + + return int32(C_RTMP_SendPacket(r, &packet, 0)) +} + +// int SendFCPublish(RTMP* r); +// rtmp.c +1846 +func C_SendFCPublish(r *C_RTMP) int32 { + 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 /* 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 = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), + int(RTMP_MAX_HEADER_SIZE))) + + enc = (*byte)(unsafe.Pointer(packet.m_body)) + 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) + if enc == nil { + return 0 + } + packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( + unsafe.Pointer(packet.m_body))) + + return int32(C_RTMP_SendPacket(r, &packet, 0)) +} + +// int SendPublish(RTMP* r); +// rtmp.c +1908 +func C_SendPublish(r *C_RTMP) int32 { + 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 = 0x04 /* source channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE + 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))) + + enc = (*byte)(unsafe.Pointer(packet.m_body)) + 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) + + if enc == nil { + return 0 + } + + enc = C_AMF_EncodeString(enc, pend, &av_live) + if enc == nil { + return 0 + } + + packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( + unsafe.Pointer(packet.m_body))) + + return int32(C_RTMP_SendPacket(r, &packet, 1)) +} + // int SendBytesReceived(RTMP* r); // rtmp.c +2080 func C_SendBytesReceived(r *C_RTMP) int { @@ -843,320 +1252,56 @@ func C_SendBytesReceived(r *C_RTMP) int { return C_RTMP_SendPacket(r, &packet, 0) } -// 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) - var uptime, suptime uint32 - var typ byte - //clientbuf := make([]byte, RTMP_SIG_SIZE+1) - var clientbuf [RTMP_SIG_SIZE + 1]byte - clientsig := (*byte)(incBytePtr(unsafe.Pointer(&clientbuf[0]), 1)) - //serversig := make([]byte, RTMP_SIG_SIZE) - var serversig [RTMP_SIG_SIZE]byte - - 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) - - memset(indxBytePtr(unsafe.Pointer(clientsig), 4), 0, 4) - - for i := 8; i < RTMP_SIG_SIZE; i++ { - *indxBytePtr(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.ReadN(r, (*byte)(unsafe.Pointer(&typ)), 1) != 1 { - if C_ReadN(r, (*byte)(unsafe.Pointer(&typ)), 1) != 1 { - return 0 - } - - if debugMode { - log.Println("C_HandShake: Type answer: %v", typ) - } - if typ != clientbuf[0] { - log.Println("C_HandShake: type mismatch: client sent %v, server sent: %v", - 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 - } - - // decode server response - memmove(unsafe.Pointer(&suptime), unsafe.Pointer(&serversig[0]), 4) - suptime = inet.Ntohl(suptime) - - // 2nd part of handshake - if C_WriteN(r, unsafe.Pointer(&serversig[0]), RTMP_SIG_SIZE) == 0 { - return 0 - } - - 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 - } - - // TODO: find golang memcmp - bMatch = 0 - if memcmp(unsafe.Pointer(&serversig[0]), unsafe.Pointer(clientsig), - RTMP_SIG_SIZE) == 0 { - bMatch = 1 - } - - if bMatch == 0 { - log.Println("Client signature does not match!") - } - return 1 -} - -// int RTMPSockBuf_Fill(RTMPSockBuf* sb); -// rtmp.c +4253 -func C_RTMPSockBuf_Fill(sb *C_RTMPSockBuf) int { - var nBytes int - - if sb.sb_size == 0 { - sb.sb_start = &sb.sb_buf[0] - } - - for { - nBytes = int(unsafe.Sizeof(sb.sb_buf)) - 1 - int(sb.sb_size) - - int(uintptr(unsafe.Pointer(sb.sb_start))-uintptr(unsafe.Pointer( - &sb.sb_buf[0]))) - - // TODO: figure out what to do with recv - nBytes = int(C.recv(C.int(sb.sb_socket), unsafe.Pointer(uintptr(unsafe.Pointer( - sb.sb_start))+uintptr(int(sb.sb_size))), C.size_t(nBytes), 0)) - - if nBytes != -1 { - sb.sb_size += int32(nBytes) - } else { - log.Println("C_RTMPSockBuf_Fill: recv error!") - } - break - } - return nBytes -} - -// int RTMP_ConnectStream(RTMP* r, int seekTime); -// rtmp.c +1099 -func C_RTMP_ConnectStream(r *C_RTMP, seekTime int32) int { +// int SendCheckBW(RTMP* r); +// rtmp.c +2105 +func C_SendCheckBW(r *C_RTMP) int32 { var packet C_RTMPPacket - memset((*byte)(unsafe.Pointer(&packet)), 0, int(unsafe.Sizeof(packet))) + var pbuf [256]byte + var pend *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&pbuf[0])) + + unsafe.Sizeof(pbuf))) + var enc *byte - if seekTime > 0 { - r.Link.seekTime = int32(seekTime) - } + packet.m_nChannel = 0x03 /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE + 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))) - r.m_mediaChannel = 0 + enc = (*byte)(unsafe.Pointer(packet.m_body)) + enc = C_AMF_EncodeString(enc, pend, &av__checkbw) + r.m_numInvokes++ + enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) + *enc = AMF_NULL + enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) - // 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 { + packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( + unsafe.Pointer(packet.m_body))) - // TODO: port is ready - if C_RTMPPacket_IsReady(&packet) != 0 { - if packet.m_nBodySize == 0 { - continue - } - - if packet.m_packetType == RTMP_PACKET_TYPE_AUDIO || - packet.m_packetType == RTMP_PACKET_TYPE_VIDEO || - packet.m_packetType == RTMP_PACKET_TYPE_INFO { - log.Println("C_RTMP_ConnectStream: got packet before play()! Ignoring.") - C_RTMPPacket_Free(&packet) - continue - } - - //C.RTMP_ClientPacket(r, &packet) - C_RTMP_ClientPacket(r, &packet) - C_RTMPPacket_Free(&packet) - } - } - return int(r.m_bPlaying) + return int32(C_RTMP_SendPacket(r, &packet, 0)) } -// 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 - switch packet.m_packetType { - - case RTMP_PACKET_TYPE_CHUNK_SIZE: - log.Println("RTMP_PACKET_TYPE_CHUNK_SIZE") - // TODO: port this - //C.HandleChangeChunkSize(r, packet) - C_HandleChangeChunkSize(r, packet) - /* - case RTMP_PACKET_TYPE_BYTES_READ_REPORT: - log.Println("RTMP_PACKET_TYPE_BYTES_READ_REPORT") - // TODO: usue new logger here - //RTMP_Log(RTMP_LOGDEBUG, "%s, received: bytes read report", __FUNCTION__); - - case RTMP_PACKET_TYPE_CONTROL: - log.Println("RTMP_PACKET_TYPE_CONTROL") - // TODO: port this - C.HandleCtrl(r, packet) - */ - case RTMP_PACKET_TYPE_SERVER_BW: - log.Println("RTMP_PACKET_TYPE_SERVER_BW") - // TODO: port this - //C.HandleServerBW(r, packet) - C_HandlServerBW(r, packet) - - case RTMP_PACKET_TYPE_CLIENT_BW: - log.Println("RTMP_PACKET_TYPE_CLIENT_BW") - // TODO: port this - //C.HandleClientBW(r, packet) - C_HandleClientBW(r, packet) - /* - case RTMP_PACKET_TYPE_AUDIO: - log.Println("RTMP_PACKET_TYPE_AUDIO") - // TODO port this - //C.HandleAudio(r, packet) NOTE this does nothing - bHasMediaPacket = 1 - if r.m_mediaChannel == 0 { - r.m_mediaChannel = packet.m_nChannel - } - - if r.m_pausing == 0 { - r.m_mediaStamp = packet.m_nTimeStamp - } - - case RTMP_PACKET_TYPE_VIDEO: - log.Println("RTMP_PACKET_TYPE_VIDEO:") - // TODO port this - // C.HandleVideo(r, packet) NOTE this does nothing - bHasMediaPacket = 1 - if r.m_mediaChannel == 0 { - r.m_mediaChannel = packet.m_nChannel - } - if r.m_pausing == 0 { - r.m_mediaStamp = packet.m_nTimeStamp - } - - case RTMP_PACKET_TYPE_FLEX_MESSAGE: - log.Println("RTMP_PACKET_TYPE_FLEX_MESSAGE:") - { - // TODO use new logger here - // RTMP_Log(RTMP_LOGDEBUG,"%s, flex message, size %u bytes, not fully supported", __FUNCTION__, packet.m_nBodySize); - - if C.HandleInvoke(r, (*byte)(incBytePtr(unsafe.Pointer(packet.m_body), 1)), - C.uint(packet.m_nBodySize-1)) == 1 { - bHasMediaPacket = 2 - } - } - case RTMP_PACKET_TYPE_INFO: - log.Println(" RTMP_PACKET_TYPE_INFO:") - // TODO use new logger here - //RTMP_Log(RTMP_LOGDEBUG, "%s, received: notify %u bytes", __FUNCTION__,packet.m_nBodySize); - if C.HandleMetadata(r, packet.m_body, C.uint(packet.m_nBodySize)) != 0 { - bHasMediaPacket = 1 - } - */ - - case RTMP_PACKET_TYPE_INVOKE: - log.Println("RTMP_PACKET_TYPE_INVOKE:") - // 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 { - log.Println("HasMediaPacket") - bHasMediaPacket = 2 - } - /* - case RTMP_PACKET_TYPE_FLASH_VIDEO: - log.Println("RTMP_PACKET_TYPE_FLASH_VIDEO:") - { - var pos uint32 = 0 - var nTimeStamp uint32 = uint32(packet.m_nTimeStamp) - - for pos+11 < uint32(packet.m_nBodySize) { - var dataSize uint32 = C_AMF_DecodeInt24((*byte)(incBytePtr(unsafe.Pointer( - packet.m_body), int(pos+1)))) - - if pos+11+dataSize+4 > uint32(packet.m_nBodySize) { - // TODO use new logger here - // RTMP_Log(RTMP_LOGWARNING, "Stream corrupt?!"); - break - } - - switch { - case *indxBytePtr(unsafe.Pointer(packet.m_body), int(pos)) == 0x12: - C.HandleMetadata(r, (*byte)(incBytePtr(unsafe.Pointer(packet.m_body), - int(pos+11))), C.uint(dataSize)) - case *indxBytePtr(unsafe.Pointer(packet.m_body), int(pos)) == 8 || - *indxBytePtr(unsafe.Pointer(packet.m_body), int(pos)) == 9: - nTimeStamp = C_AMF_DecodeInt24((*byte)(incBytePtr(unsafe.Pointer( - packet.m_body), int(pos+4)))) - nTimeStamp |= uint32(*indxBytePtr(unsafe.Pointer(packet.m_body), - int(pos+7)) << 24) - } - pos += (11 + dataSize + 4) - } - if r.m_pausing == 0 { - r.m_mediaStamp = uint32(nTimeStamp) - } - - bHasMediaPacket = 1 - - } - default: - log.Println("DEFAULT") - // TODO use new logger here - // RTMP_Log(RTMP_LOGDEBUG, "%s, unknown packet type received: 0x%02x", __FUNCTION__,packet.m_packetType); - */ +// void AV_erase(C_RTMP_METHOD* vals, int* num, int i, int freeit); +// rtmp.c +2393 +func C_AV_erase(vals *C_RTMP_METHOD, num *int32, i, freeit int32) { + if freeit != 0 { + //C.free(unsafe.Pointer((*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(vals), int(i), + //int(unsafe.Sizeof(*vals))))).name.av_val)) } - return bHasMediaPacket -} - -// void HandleChangeChunkSize(RTMP* r, const RTMPPacket* packet); -// rtmp.c +3345 -func C_HandleChangeChunkSize(r *C_RTMP, packet *C_RTMPPacket) { - if packet.m_nBodySize >= 4 { - //r.m_inChunkSize = int32(C.AMF_DecodeInt32((*byte)(unsafe.Pointer(packet.m_body)))) - r.m_inChunkSize = int32(C_AMF_DecodeInt32((*byte)(unsafe.Pointer(packet.m_body)))) - // TODO use new logger here - // RTMP_Log(RTMP_LOGDEBUG, "%s, received: chunk size change to %d", __FUNCTION__, r.m_inChunkSize); + (*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)))) } -} - -// void HandleServerBW(RTMP* r, const RTMPPacket* packet); -// 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); -} - -// void HandleClientBW(RTMP* r, const RTMPPacket* packet); -// rtmp.c +3515 -func C_HandleClientBW(r *C_RTMP, packet *C_RTMPPacket) { - r.m_nClientBW = int32(C_AMF_DecodeInt32((*byte)(unsafe.Pointer(packet.m_body)))) - //r.m_nClientBW = int32(C.AMF_DecodeInt32((*byte)(unsafe.Pointer(packet.m_body)))) - - if packet.m_nBodySize > 4 { - r.m_nClientBW2 = (uint8)(*indxBytePtr(unsafe.Pointer(packet.m_body), 4)) - } else { - //r.m_nClientBW2 = -1 - r.m_nClientBW2 = 0 - } - // TODO use new logger here - // RTMP_Log(RTMP_LOGDEBUG, "%s: client BW = %d %d", __FUNCTION__, r.m_nClientBW, - //r.m_nClientBW2); + (*(*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 } // int HandleInvoke(RTMP* r, const char* body, unsigned int nBodySize); @@ -1437,216 +1582,64 @@ leave: return ret } -// int SendReleaseStream(RTMP* r); -// rtmp.c +1816 -func C_SendReleaseStream(r *C_RTMP) int32 { - 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 /* 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 = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), - int(RTMP_MAX_HEADER_SIZE))) - - enc = (*byte)(unsafe.Pointer(packet.m_body)) - 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) - if enc == nil { - return 0 +// void HandleChangeChunkSize(RTMP* r, const RTMPPacket* packet); +// rtmp.c +3345 +func C_HandleChangeChunkSize(r *C_RTMP, packet *C_RTMPPacket) { + if packet.m_nBodySize >= 4 { + //r.m_inChunkSize = int32(C.AMF_DecodeInt32((*byte)(unsafe.Pointer(packet.m_body)))) + r.m_inChunkSize = int32(C_AMF_DecodeInt32((*byte)(unsafe.Pointer(packet.m_body)))) + // TODO use new logger here + // RTMP_Log(RTMP_LOGDEBUG, "%s, received: chunk size change to %d", __FUNCTION__, r.m_inChunkSize); } - packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( - unsafe.Pointer(packet.m_body))) - - return int32(C_RTMP_SendPacket(r, &packet, 0)) } -// int SendFCPublish(RTMP* r); -// rtmp.c +1846 -func C_SendFCPublish(r *C_RTMP) int32 { - 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 /* 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 = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), - int(RTMP_MAX_HEADER_SIZE))) - - enc = (*byte)(unsafe.Pointer(packet.m_body)) - 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) - if enc == nil { - return 0 - } - packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( - unsafe.Pointer(packet.m_body))) - - return int32(C_RTMP_SendPacket(r, &packet, 0)) +// void HandleServerBW(RTMP* r, const RTMPPacket* packet); +// 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); } -// int RTMP_SendCreateStream(RTMP* r); -// rtmp.c +1725 -func C_RTMP_SendCreateStream(r *C_RTMP) int32 { - var packet C_RTMPPacket - var pbuf [256]byte - var pend *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&pbuf[0])) + - unsafe.Sizeof(pbuf))) - var enc *byte +// void HandleClientBW(RTMP* r, const RTMPPacket* packet); +// rtmp.c +3515 +func C_HandleClientBW(r *C_RTMP, packet *C_RTMPPacket) { + r.m_nClientBW = int32(C_AMF_DecodeInt32((*byte)(unsafe.Pointer(packet.m_body)))) + //r.m_nClientBW = int32(C.AMF_DecodeInt32((*byte)(unsafe.Pointer(packet.m_body)))) - 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 = (*byte)(incBytePtr(unsafe.Pointer(&pbuf[0]), - int(RTMP_MAX_HEADER_SIZE))) - - enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = C_AMF_EncodeString(enc, pend, &av_createStream) - r.m_numInvokes++ - enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) - *enc = AMF_NULL - enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) - - packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( - unsafe.Pointer(packet.m_body))) - - return int32(C_RTMP_SendPacket(r, &packet, 1)) -} - -// int SendPublish(RTMP* r); -// rtmp.c +1908 -func C_SendPublish(r *C_RTMP) int32 { - 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 = 0x04 /* source channel (invoke) */ - packet.m_headerType = RTMP_PACKET_SIZE_LARGE - packet.m_packetType = RTMP_PACKET_TYPE_INVOKE - 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))) - - enc = (*byte)(unsafe.Pointer(packet.m_body)) - 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) - - if enc == nil { - return 0 - } - - enc = C_AMF_EncodeString(enc, pend, &av_live) - if enc == nil { - return 0 - } - - packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( - unsafe.Pointer(packet.m_body))) - - return int32(C_RTMP_SendPacket(r, &packet, 1)) -} - -// int SendCheckBW(RTMP* r); -// rtmp.c +2105 -func C_SendCheckBW(r *C_RTMP) int32 { - var packet C_RTMPPacket - var pbuf [256]byte - var pend *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&pbuf[0])) + - unsafe.Sizeof(pbuf))) - var enc *byte - - packet.m_nChannel = 0x03 /* control channel (invoke) */ - packet.m_headerType = RTMP_PACKET_SIZE_LARGE - packet.m_packetType = RTMP_PACKET_TYPE_INVOKE - 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))) - - enc = (*byte)(unsafe.Pointer(packet.m_body)) - enc = C_AMF_EncodeString(enc, pend, &av__checkbw) - r.m_numInvokes++ - enc = C_AMF_EncodeNumber(enc, pend, float64(r.m_numInvokes)) - *enc = AMF_NULL - enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) - - packet.m_nBodySize = uint32(uintptr(unsafe.Pointer(enc)) - uintptr( - unsafe.Pointer(packet.m_body))) - - return int32(C_RTMP_SendPacket(r, &packet, 0)) -} - -// #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 + if packet.m_nBodySize > 4 { + r.m_nClientBW2 = (uint8)(*indxBytePtr(unsafe.Pointer(packet.m_body), 4)) } else { - return 0 + //r.m_nClientBW2 = -1 + r.m_nClientBW2 = 0 } + // TODO use new logger here + // RTMP_Log(RTMP_LOGDEBUG, "%s: client BW = %d %d", __FUNCTION__, r.m_nClientBW, + //r.m_nClientBW2); } -// void AV_erase(C_RTMP_METHOD* vals, int* num, int i, int freeit); -// rtmp.c +2393 -func C_AV_erase(vals *C_RTMP_METHOD, num *int32, i, freeit int32) { - if freeit != 0 { - //C.free(unsafe.Pointer((*(*C_RTMP_METHOD)(incPtr(unsafe.Pointer(vals), int(i), - //int(unsafe.Sizeof(*vals))))).name.av_val)) - } - (*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 +// static int DecodeInt32LE(const char* data); +// rtmp.c +3527 +func C_DecodeInt32LE(data *byte) int32 { + var c *uint8 = (*uint8)(data) + return int32((*indxBytePtr(unsafe.Pointer(c), 3) << 24) | + (*indxBytePtr(unsafe.Pointer(c), 2) << 16) | + (*indxBytePtr(unsafe.Pointer(c), 1) << 8) | + *c) } -// 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 - } +// int EncodeInt32LE(char* output, int nVal); +// rtmp.c +3537 +func C_EncodeInt32LE(output *byte, nVal int32) int32 { + *output = byte(nVal) + nVal >>= 8 + *indxBytePtr(unsafe.Pointer(output), 1) = byte(nVal) + nVal >>= 8 + *indxBytePtr(unsafe.Pointer(output), 2) = byte(nVal) + nVal >>= 8 + *indxBytePtr(unsafe.Pointer(output), 3) = byte(nVal) + return 4 } // int RTMP_ReadPacket(RTMP* r, RTMPPacket* packet); @@ -1869,161 +1862,79 @@ func C_RTMP_ReadPacket(r *C_RTMP, packet *C_RTMPPacket) int32 { return 1 } -// static int DecodeInt32LE(const char* data); -// rtmp.c +3527 -func C_DecodeInt32LE(data *byte) int32 { - var c *uint8 = (*uint8)(data) - return int32((*indxBytePtr(unsafe.Pointer(c), 3) << 24) | - (*indxBytePtr(unsafe.Pointer(c), 2) << 16) | - (*indxBytePtr(unsafe.Pointer(c), 1) << 8) | - *c) -} +// 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) + var uptime, suptime uint32 + var typ byte + //clientbuf := make([]byte, RTMP_SIG_SIZE+1) + var clientbuf [RTMP_SIG_SIZE + 1]byte + clientsig := (*byte)(incBytePtr(unsafe.Pointer(&clientbuf[0]), 1)) + //serversig := make([]byte, RTMP_SIG_SIZE) + var serversig [RTMP_SIG_SIZE]byte -// int EncodeInt32LE(char* output, int nVal); -// rtmp.c +3537 -func C_EncodeInt32LE(output *byte, nVal int32) int32 { - *output = byte(nVal) - nVal >>= 8 - *indxBytePtr(unsafe.Pointer(output), 1) = byte(nVal) - nVal >>= 8 - *indxBytePtr(unsafe.Pointer(output), 2) = byte(nVal) - nVal >>= 8 - *indxBytePtr(unsafe.Pointer(output), 3) = byte(nVal) - return 4 -} + clientbuf[0] = 0x03 // not encrypted -// #define 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 -} + // 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) -func endSession(rtmp *C_RTMP) uint32 { - if rtmp == nil { - return 3 + memset(indxBytePtr(unsafe.Pointer(clientsig), 4), 0, 4) + + for i := 8; i < RTMP_SIG_SIZE; i++ { + *indxBytePtr(unsafe.Pointer(clientsig), i) = byte(rand.Intn(256)) } - //C.RTMP_Close(rtmp) - //C.RTMP_Free(rtmp) - return 0 -} - -// int RTMP_Write(RTMP* r, const char* buf, int size); -// rtmp.c +5095 -func C_RTMP_Write(r *C_RTMP, data []byte) int { - buf := sliceToPtr(data) - // TODO: port RTMPPacket - var pkt = &r.m_write - var pend, enc unsafe.Pointer - size := len(data) - s2 := size - var ret, num int - - pkt.m_nChannel = 0x04 - pkt.m_nInfoField2 = int32(r.m_stream_id) - for s2 != 0 { - if pkt.m_nBytesRead == 0 { - if size < minDataSize { - log.Printf("size: %d\n", size) - log.Printf("too small \n") - return 0 - } - - if *indxBytePtr(buf, 0) == 'F' && *indxBytePtr(buf, 1) == 'L' && *indxBytePtr(buf, 2) == 'V' { - buf = unsafe.Pointer(uintptr(buf) + uintptr(13)) - s2 -= 13 - } - - pkt.m_packetType = uint8(*indxBytePtr(buf, 0)) - buf = incBytePtr(buf, 1) - pkt.m_nBodySize = uint32(C_AMF_DecodeInt24((*byte)(buf))) - buf = incBytePtr(buf, 3) - pkt.m_nTimeStamp = uint32(C_AMF_DecodeInt24((*byte)(buf))) - buf = incBytePtr(buf, 3) - pkt.m_nTimeStamp |= uint32(*indxBytePtr(buf, 0)) << 24 - buf = incBytePtr(buf, 4) - s2 -= 11 - - if ((pkt.m_packetType == RTMP_PACKET_TYPE_AUDIO || - pkt.m_packetType == RTMP_PACKET_TYPE_VIDEO) && - pkt.m_nTimeStamp == 0) || pkt.m_packetType == RTMP_PACKET_TYPE_INFO { - - pkt.m_headerType = RTMP_PACKET_SIZE_LARGE - - if pkt.m_packetType == RTMP_PACKET_TYPE_INFO { - pkt.m_nBodySize += 16 - } - } else { - pkt.m_headerType = RTMP_PACKET_SIZE_MEDIUM - } - // TODO: Port this - if int(C_RTMPPacket_Alloc(pkt, uint32(pkt.m_nBodySize))) == 0 { - log.Println("Failed to allocate packet") - return 0 - } - - enc = unsafe.Pointer(pkt.m_body) - pend = incBytePtr(enc, int(pkt.m_nBodySize)) - - if pkt.m_packetType == RTMP_PACKET_TYPE_INFO { - enc = unsafe.Pointer(C_AMF_EncodeString((*byte)(enc), (*byte)(pend), &setDataFrame)) - pkt.m_nBytesRead = uint32(math.Abs(float64(uintptr(enc) - - uintptr(unsafe.Pointer(pkt.m_body))))) - } - - } else { - enc = incBytePtr(unsafe.Pointer(pkt.m_body), int(pkt.m_nBytesRead)) - } - num = int(pkt.m_nBodySize - pkt.m_nBytesRead) - if num > s2 { - num = s2 - } - - memmove(enc, buf, uintptr(num)) - pkt.m_nBytesRead += uint32(num) - s2 -= num - buf = incBytePtr(buf, num) - if pkt.m_nBytesRead == pkt.m_nBodySize { - // TODO: Port this - ret = C_RTMP_SendPacket(r, pkt, 0) - // TODO: Port this - //C.RTMPPacket_Free(pkt) - C_RTMPPacket_Free(pkt) - pkt.m_nBytesRead = 0 - if ret == 0 { - return -1 - } - buf = incBytePtr(buf, 4) - s2 -= 4 - if s2 < 0 { - break - } - } - } - return size + s2 -} - -// int RTMPPacket_Alloc(RTMPPacket* p, uint32_t nSize); -// rtmp.c +189 -func C_RTMPPacket_Alloc(p *C_RTMPPacket, nSize uint32) int { - var ptr *byte - // TODO: port C.SIZE_MAX - // also work out how to deal with the overfloat - /* - if int64(nSize) > (C.SIZE_MAX - RTMP_MAX_HEADER_SIZE) { - return 0 - } - */ - ptr = (*byte)(calloc(1, uintptr(nSize+RTMP_MAX_HEADER_SIZE))) - - if ptr == nil { + if C_WriteN(r, unsafe.Pointer(&clientbuf[0]), RTMP_SIG_SIZE+1) == 0 { return 0 } - p.m_body = (*byte)(incBytePtr(unsafe.Pointer(ptr), RTMP_MAX_HEADER_SIZE)) - p.m_nBytesRead = 0 + + //if C.ReadN(r, (*byte)(unsafe.Pointer(&typ)), 1) != 1 { + if C_ReadN(r, (*byte)(unsafe.Pointer(&typ)), 1) != 1 { + return 0 + } + + if debugMode { + log.Println("C_HandShake: Type answer: %v", typ) + } + if typ != clientbuf[0] { + log.Println("C_HandShake: type mismatch: client sent %v, server sent: %v", + 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 + } + + // decode server response + memmove(unsafe.Pointer(&suptime), unsafe.Pointer(&serversig[0]), 4) + suptime = inet.Ntohl(suptime) + + // 2nd part of handshake + if C_WriteN(r, unsafe.Pointer(&serversig[0]), RTMP_SIG_SIZE) == 0 { + return 0 + } + + 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 + } + + // TODO: find golang memcmp + bMatch = 0 + if memcmp(unsafe.Pointer(&serversig[0]), unsafe.Pointer(clientsig), + RTMP_SIG_SIZE) == 0 { + bMatch = 1 + } + + if bMatch == 0 { + log.Println("Client signature does not match!") + } return 1 } @@ -2289,38 +2200,32 @@ func C_RTMP_SendPacket(r *C_RTMP, packet *C_RTMPPacket, queue int) int { return 1 } -// int WriteN(RTMP* r, const char* buffer, int n); -// rtmp.c +1502 -func C_WriteN(r *C_RTMP, buffer unsafe.Pointer, n int) int { - ptr := buffer - for n > 0 { - var nBytes int +// int RTMPSockBuf_Fill(RTMPSockBuf* sb); +// rtmp.c +4253 +func C_RTMPSockBuf_Fill(sb *C_RTMPSockBuf) int { + var nBytes int - nBytes = int(C_RTMPSockBuf_Send(&r.m_sb, (*byte)(ptr), int32(n))) - - if nBytes < 0 { - if debugMode { - log.Println("C_WriteN, RTMP send error") - } - - // TODO: port this - //C.RTMP_Close(r) - n = 1 - break - } - - if nBytes == 0 { - break - } - - n -= nBytes - ptr = incBytePtr(ptr, nBytes) + if sb.sb_size == 0 { + sb.sb_start = &sb.sb_buf[0] } - if n == 0 { - return 1 + for { + nBytes = int(unsafe.Sizeof(sb.sb_buf)) - 1 - int(sb.sb_size) - + int(uintptr(unsafe.Pointer(sb.sb_start))-uintptr(unsafe.Pointer( + &sb.sb_buf[0]))) + + // TODO: figure out what to do with recv + nBytes = int(C.recv(C.int(sb.sb_socket), unsafe.Pointer(uintptr(unsafe.Pointer( + sb.sb_start))+uintptr(int(sb.sb_size))), C.size_t(nBytes), 0)) + + if nBytes != -1 { + sb.sb_size += int32(nBytes) + } else { + log.Println("C_RTMPSockBuf_Fill: recv error!") + } + break } - return 0 + return nBytes } // int RTMPSockBuf_Send(RTMPSockBuf* sb, const char* buf, int len); @@ -2330,27 +2235,99 @@ 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)) } -// 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) { - 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)))))) - } - 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)) - *indxBytePtr(tmp, int(av.av_len)) = '\000' +// int RTMP_Write(RTMP* r, const char* buf, int size); +// rtmp.c +5095 +func C_RTMP_Write(r *C_RTMP, data []byte) int { + buf := sliceToPtr(data) + // TODO: port RTMPPacket + var pkt = &r.m_write + var pend, enc unsafe.Pointer + size := len(data) + s2 := size + var ret, num int - (*(*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)++ + pkt.m_nChannel = 0x04 + pkt.m_nInfoField2 = int32(r.m_stream_id) + for s2 != 0 { + if pkt.m_nBytesRead == 0 { + if size < minDataSize { + log.Printf("size: %d\n", size) + log.Printf("too small \n") + return 0 + } + + if *indxBytePtr(buf, 0) == 'F' && *indxBytePtr(buf, 1) == 'L' && *indxBytePtr(buf, 2) == 'V' { + buf = unsafe.Pointer(uintptr(buf) + uintptr(13)) + s2 -= 13 + } + + pkt.m_packetType = uint8(*indxBytePtr(buf, 0)) + buf = incBytePtr(buf, 1) + pkt.m_nBodySize = uint32(C_AMF_DecodeInt24((*byte)(buf))) + buf = incBytePtr(buf, 3) + pkt.m_nTimeStamp = uint32(C_AMF_DecodeInt24((*byte)(buf))) + buf = incBytePtr(buf, 3) + pkt.m_nTimeStamp |= uint32(*indxBytePtr(buf, 0)) << 24 + buf = incBytePtr(buf, 4) + s2 -= 11 + + if ((pkt.m_packetType == RTMP_PACKET_TYPE_AUDIO || + pkt.m_packetType == RTMP_PACKET_TYPE_VIDEO) && + pkt.m_nTimeStamp == 0) || pkt.m_packetType == RTMP_PACKET_TYPE_INFO { + + pkt.m_headerType = RTMP_PACKET_SIZE_LARGE + + if pkt.m_packetType == RTMP_PACKET_TYPE_INFO { + pkt.m_nBodySize += 16 + } + } else { + pkt.m_headerType = RTMP_PACKET_SIZE_MEDIUM + } + // TODO: Port this + if int(C_RTMPPacket_Alloc(pkt, uint32(pkt.m_nBodySize))) == 0 { + log.Println("Failed to allocate packet") + return 0 + } + + enc = unsafe.Pointer(pkt.m_body) + pend = incBytePtr(enc, int(pkt.m_nBodySize)) + + if pkt.m_packetType == RTMP_PACKET_TYPE_INFO { + enc = unsafe.Pointer(C_AMF_EncodeString((*byte)(enc), (*byte)(pend), &setDataFrame)) + pkt.m_nBytesRead = uint32(math.Abs(float64(uintptr(enc) - + uintptr(unsafe.Pointer(pkt.m_body))))) + } + + } else { + enc = incBytePtr(unsafe.Pointer(pkt.m_body), int(pkt.m_nBytesRead)) + } + num = int(pkt.m_nBodySize - pkt.m_nBytesRead) + if num > s2 { + num = s2 + } + + memmove(enc, buf, uintptr(num)) + pkt.m_nBytesRead += uint32(num) + s2 -= num + buf = incBytePtr(buf, num) + if pkt.m_nBytesRead == pkt.m_nBodySize { + // TODO: Port this + ret = C_RTMP_SendPacket(r, pkt, 0) + // TODO: Port this + //C.RTMPPacket_Free(pkt) + C_RTMPPacket_Free(pkt) + pkt.m_nBytesRead = 0 + if ret == 0 { + return -1 + } + buf = incBytePtr(buf, 4) + s2 -= 4 + if s2 < 0 { + break + } + } + } + return size + s2 } /*