/***************************************************** * * Copyright 2009 Adobe Systems Incorporated. All Rights Reserved. * ***************************************************** * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * * The Initial Developer of the Original Code is Adobe Systems Incorporated. * Portions created by Adobe Systems Incorporated are Copyright (C) 2009 Adobe Systems * Incorporated. All Rights Reserved. * * Contributor(s): Akamai Technologies * *****************************************************/ package org.osmf.net { import __AS3__.vec.Vector; import org.osmf.utils.URL; [ExcludeClass] /** * @private * * Parses a URL into properties specific to Flash Media Server. * * @see URL * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public class FMSURL extends URL { /** * Set the URL this class will work with. * * @param url The URL this class will use to provide FMS-specific information such as app name and instance name. * @param useInstance If true, then the second part of the URL path is considered the instance name, * such as rtmp://host/app/foo/bar/stream. In this case the instance name would be 'foo' and the stream would * be 'bar/stream'. * If false, then the second part of the URL path is considered to be the stream name, * such as rtmp://host/app/foo/bar/stream. In this case there is no instance name and the stream would * be 'foo/bar/stream'. * * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public function FMSURL(url:String, useInstance:Boolean=false) { super(url); _useInstance = useInstance; _appName = ""; _instanceName = ""; _streamName = ""; _fileFormat = ""; parsePath(); parseQuery(); } /** * Whether a named instance is being used within the URI * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public function get useInstance():Boolean { return _useInstance; } /** * The FMS application name. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public function get appName():String { return _appName; } /** * The FMS instance name. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public function get instanceName():String { return _instanceName; } /** * The FMS stream name. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public function get streamName():String { return _streamName; } /** * The file format of the streaming media. Corresponds to one of the * public constants defined in this class, such as MP4_STREAM, * or the blank stream for flv media streams. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public function get fileFormat():String { return _fileFormat; } /** * The vector of edges. * * @see FMSHost * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public function get edges():Vector. { return _edges; } /** * The vector of origins. * * @see FMSHost * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public function get origins():Vector. { return _origins; } /** * Parse the path in the URL object into FMS specific properties. * The path is everything after the host but before any query string parameters, with no leading or trailing slashes. *

* For example, in this URL: "http://host.com:80/foo/bar/index.html?a=1&b=2" * path would be "foo/bar/index.html"

* * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ private function parsePath():void { if ((path == null) || (path.length == 0)) { // Check the query string for a stream name since the path is empty _streamName = getParamValue(QUERY_STRING_STREAM); // Check the query string for stream type since the path is empty _fileFormat = getParamValue(QUERY_STRING_STREAMTYPE); return; } var pattern:RegExp = /(\/)/; var result:Array = path.split(pattern); if (result != null) { _appName = result[APPNAME_START_INDEX]; _instanceName = ""; _streamName = ""; // If "_definst_" is in the path and in the right place, we'll assume everything after that is the stream var definstPattern:RegExp = new RegExp("^.*\/" + DEFAULT_INSTANCE_NAME, "i"); if (path.search(definstPattern) > -1) { _useInstance = true; } var streamStartNdx:uint = STREAMNAME_START_INDEX; if (_useInstance) { _instanceName = result[INSTANCENAME_START_INDEX]; } else { streamStartNdx = INSTANCENAME_START_INDEX; } for (var i:int = streamStartNdx; i < result.length; i++) { _streamName += result[i]; } // If no streamName found in the path, check the query string if (_streamName == null || _streamName == "") { _streamName = getParamValue(QUERY_STRING_STREAM); } if (_streamName.search(/^mp4:/i) > -1) { _fileFormat = MP4_STREAM; } else if (_streamName.search(/^mp3:/i) > -1) { _fileFormat = MP3_STREAM; } else if (_streamName.search(/^id3:/i) > -1) { _fileFormat = ID3_STREAM; } // If no stream type found check the query string if (_fileFormat == null || _fileFormat == "") { _fileFormat = getParamValue(QUERY_STRING_STREAMTYPE); } } } /** * Parse the query string for origin/edge info. * A sample FMS URI with origin/edge info in the query string might look like this: * "rtmp://edge1/?rtmp://edge2/?rtmp://origin/app/inst/mp4:foldera/folder/b/myfile.mp4" * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ private function parseQuery():void { // If there is no query string or there are no protocols in the query string, there is nothing to do if (query == null || query.length == 0 || (query.search(/:\//) == -1)) { return; } var edgeOriginURIs:Array = query.split("?"); // Remove the items that don't have a protocol for (var ndx:int = 0; ndx < edgeOriginURIs.length; ndx++) { var tempIndex:int = edgeOriginURIs[ndx].toString().search(/:\//); if (tempIndex == -1) { edgeOriginURIs.splice(ndx, 1); } } var hasEdge:Boolean = false; var originIndex:int = 0; // if it splits into more than one item, we assume it has an edge and the last one is the origin if (edgeOriginURIs.length >= 2) { hasEdge = true; originIndex = edgeOriginURIs.length -1; } var tempSN:String = ""; // temporary server name var tempPN:String = ""; // temporary port number var colonIndex:int = 0; var slashIndex:int = 0; var startIndex:int = 0; var endIndex:int = 0; for (var i:int = 0; i < edgeOriginURIs.length; i++) { var tempNdex:int = edgeOriginURIs[i].toString().search(/:\//); startIndex = tempNdex + 2; if (edgeOriginURIs[i].charAt(startIndex) == '/') { // if not local URI (i.e. rtmp:/app/) then move index up startIndex++; } // get server (and maybe port) colonIndex = edgeOriginURIs[i].indexOf(":", startIndex); slashIndex = edgeOriginURIs[i].indexOf("/", startIndex); if (slashIndex < 0 && colonIndex < 0) { tempSN = edgeOriginURIs[i].slice(startIndex); } else if (colonIndex >= 0 && colonIndex < slashIndex) { endIndex = colonIndex; tempSN = edgeOriginURIs[i].slice(startIndex, endIndex); startIndex = endIndex + 1; endIndex = slashIndex; tempPN = edgeOriginURIs[i].slice(startIndex, endIndex); } else if (edgeOriginURIs[i].indexOf("://") != -1) { endIndex = slashIndex; tempSN = edgeOriginURIs[i].slice(startIndex, endIndex); } else { endIndex = edgeOriginURIs[i].indexOf("/"); tempSN = "localhost"; } // if it's the origin, we need to push the origin and get the app and stream name if (i == originIndex) { if (_origins == null) { _origins = new Vector.; } _origins.push(new FMSHost(tempSN, tempPN)); var tempFMSURL:FMSURL = new FMSURL(edgeOriginURIs[i], _useInstance); if (_appName == "") { _appName = tempFMSURL.appName; } if (_useInstance && _instanceName == "") { _instanceName = tempFMSURL.instanceName; } if (_streamName == "") { _streamName = tempFMSURL.streamName; } } else if((edgeOriginURIs[i] != query) && hasEdge) { if (_edges == null) { _edges = new Vector.; } _edges.push(new FMSHost(tempSN, tempPN)); } } } private var _useInstance:Boolean; private var _appName:String; private var _instanceName:String; private var _streamName:String; private var _fileFormat:String; private var _origins:Vector.; private var _edges:Vector.; private static const APPNAME_START_INDEX:uint = 0; private static const INSTANCENAME_START_INDEX:uint = 2; private static const STREAMNAME_START_INDEX:uint = 4; private static const DEFAULT_INSTANCE_NAME:String = "_definst_"; public static const MP4_STREAM:String = "mp4"; public static const MP3_STREAM:String = "mp3"; public static const ID3_STREAM:String = "id3"; public static const QUERY_STRING_STREAM:String = "streamName"; public static const QUERY_STRING_STREAMTYPE:String = "streamType"; } }