/* NAME parseurl.go DESCRIPTION See Readme.md AUTHOR Dan Kortschak <dan@ausocean.org> Saxon Nelson-Milton <saxon@ausocean.org> Alan Noble <alan@ausocean.org> LICENSE parseurl.go is Copyright (C) 2017-2019 the Australian Ocean Lab (AusOcean) It is free software: you can redistribute it and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with revid in gpl.txt. If not, see http://www.gnu.org/licenses. Derived from librtmp under the GNU Lesser General Public License 2.1 Copyright (C) 2005-2008 Team XBMC http://www.xbmc.org Copyright (C) 2008-2009 Andrej Stepanchuk Copyright (C) 2009-2010 Howard Chu */ package rtmp import ( "net/url" "path" "strconv" "strings" ) // parseURL parses an RTMP URL (ok, technically it is lexing). func parseURL(addr string) (protocol int32, host string, port uint16, app, playpath string, err error) { u, err := url.Parse(addr) if err != nil { return protocol, host, port, app, playpath, err } switch u.Scheme { case "rtmp": protocol = protoRTMP case "rtmpt": protocol = protoRTMPT case "rtmps": protocol = protoRTMPS case "rtmpe": protocol = protoRTMPE case "rtmfp": protocol = protoRTMFP case "rtmpte": protocol = protoRTMPTE case "rtmpts": protocol = protoRTMPTS default: return protocol, host, port, app, playpath, errUnknownScheme } host = u.Host if p := u.Port(); p != "" { pi, err := strconv.Atoi(p) if err != nil { return protocol, host, port, app, playpath, err } port = uint16(pi) } if len(u.Path) < 1 || !path.IsAbs(u.Path) { return protocol, host, port, app, playpath, errInvalidURL } elems := strings.SplitN(u.Path[1:], "/", 3) if len(elems) < 2 || elems[0] == "" || elems[1] == "" { return protocol, host, port, app, playpath, errInvalidURL } app = elems[0] playpath = path.Join(elems[1:]...) switch ext := path.Ext(playpath); ext { case ".f4v", ".mp4": playpath = playpath[:len(playpath)-len(ext)] if !strings.HasPrefix(playpath, "mp4:") { playpath = "mp4:" + playpath } case ".mp3": playpath = playpath[:len(playpath)-len(ext)] if !strings.HasPrefix(playpath, "mp3:") { playpath = "mp3:" + playpath } case ".flv": playpath = playpath[:len(playpath)-len(ext)] } if u.RawQuery != "" { playpath += "?" + u.RawQuery } switch { case port != 0: case (protocol & featureSSL) != 0: return protocol, host, port, app, playpath, errUnimplemented // port = 433 case (protocol & featureHTTP) != 0: port = 80 default: port = 1935 } return protocol, host, port, app, playpath, nil }