diff --git a/rtmp/parseurl.go b/rtmp/parseurl.go new file mode 100644 index 00000000..d1106ec4 --- /dev/null +++ b/rtmp/parseurl.go @@ -0,0 +1,296 @@ +package rtmp + +// 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 + } + + 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 = int32(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))) + } + + // 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 + } + } + + 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 = int32(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 := int32(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 = int32(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)(indxBytePtr(unsafe.Pointer(ppstart), int(uintptr(pplen)- + uintptr(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 = (*byte)(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) + *indxBytePtr(unsafe.Pointer(destptr), 0) = byte(c) + destptr = (*byte)(incBytePtr(unsafe.Pointer(destptr), 1)) + pplen -= 3 + p = (*byte)(incBytePtr(unsafe.Pointer(p), 3)) + } else { + *indxBytePtr(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))) +} diff --git a/rtmp/rtmp.go b/rtmp/rtmp.go index 3d1defd1..e329d941 100644 --- a/rtmp/rtmp.go +++ b/rtmp/rtmp.go @@ -576,301 +576,6 @@ func C_RTMP_SetupURL(r *C_RTMP, u string) int32 { return 1 } -// 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 - } - - 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 = int32(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))) - } - - // 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 - } - } - - 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 = int32(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 := int32(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 = int32(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)(indxBytePtr(unsafe.Pointer(ppstart), int(uintptr(pplen)- - uintptr(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 = (*byte)(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) - *indxBytePtr(unsafe.Pointer(destptr), 0) = byte(c) - destptr = (*byte)(incBytePtr(unsafe.Pointer(destptr), 1)) - pplen -= 3 - p = (*byte)(incBytePtr(unsafe.Pointer(p), 3)) - } else { - *indxBytePtr(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))) -} - // void SocksSetup(RTMP *r, C_AVal* sockshost); // rtmp.c +410 func C_SocksSetup(r *C_RTMP, sockshost *C_AVal) {