1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
|
/*
* jPlayer Plugin for jQuery JavaScript Library
* http://www.jplayer.org
*
* Copyright (c) 2009 - 2014 Happyworm Ltd
* Licensed under the MIT license.
* http://opensource.org/licenses/MIT
*
* Author: Robert M. Hall
* Date: 7th August 2012
* Custom NetConnection Manager for more robust RTMP support
* Based in part on work by Will Law for the old Akamai NCManager.as
* and some of Will's new work in the OVP base classes (Open Video Player)
* as well as similar approaches by many other NetConnection managers
*
*/
/*
TODO LIST 08/18/2011:
1. Wired up errors to dispatch events to Jplayer events to allow them to bubble up to JS
2. Rework event dispatch to handoff netconnection instead of a passed in reference
3. Allow a customizeable list of protocols and ports to be used instead of entire list
4. Allow a specific port/protocol (1 connect type) to be used first, and then optionally fallback on a custom list or the default list
5. Remove some traces and check a few other items below where I've made notes
*/
package happyworm.jPlayer {
import flash.events.*;
import flash.net.*;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.utils.clearInterval;
import flash.utils.setInterval;
public class ConnectManager extends Object {
private var protocols_arr:Array = new Array("rtmp","rtmpt","rtmpe","rtmpte","rtmps");
private var ports_arr:Array = new Array("",":1935",":80",":443");
private const protCount:Number = 5;
private const portCount:Number = 4;
private var _ncRef:Object;
private var _aNC:Array;
private var k_TIMEOUT:Number = 30000;
private var k_startConns:Number;
private var m_connList:Array = [];
private var m_serverName:String;
private var m_appName:String;
private var m_streamName:String;
private var m_connListCounter:Number;
private var m_flashComConnectTimeOut:Number;
private var m_validNetConnection:NetConnection;
private var connectSuccess:Boolean=false;
private var negotiating:Boolean=false;
private var idleTimeOut:Boolean=false;
public function ConnectManager() {
trace ("ConnectManager Initialized Version: 1.00 DT");
createPortsProtocolsArray();
}
private function createPortsProtocolsArray():void {
var outerLoop:Number=0;
var innerLoop:Number=0;
for (outerLoop=0; outerLoop<protocols_arr.length; outerLoop++) {
for (innerLoop=0; innerLoop<ports_arr.length; innerLoop++) {
m_connList.push( { protocol: protocols_arr[outerLoop], port: ports_arr[innerLoop] } );
}
}
}
public function negotiateConnect(ncRef:Object,p_serverName:String,p_appName:String):void
{
negotiating=true;
_ncRef=ncRef;
trace("*** SERVER NAME: "+p_serverName);
trace("*** APP NAME: "+p_serverName);
k_startConns = getTimer();
m_serverName = p_serverName;
m_appName = p_appName;
// Set a timeout function, just in case we never connect successfully
clearInterval(m_flashComConnectTimeOut);
m_flashComConnectTimeOut = setInterval(onFlashComConnectTimeOut,k_TIMEOUT,k_TIMEOUT);
// Createe a NetConnection for each of the protocols/ports listed in the m_connList list.
// Connection attempts occur at intervals of 1.5 seconds.
// The first connection to succeed will be used, all the others will be closed.
_aNC = new Array();
for (var i:uint = 0; i < m_connList.length; i++)
{
_aNC[i] = new NetConnection();
_aNC[i].addEventListener(NetStatusEvent.NET_STATUS,netStatus);
_aNC[i].addEventListener(SecurityErrorEvent.SECURITY_ERROR,netSecurityError);
_aNC[i].addEventListener(AsyncErrorEvent.ASYNC_ERROR,asyncError);
_aNC[i].client = new Object;
_aNC[i].client.owner = this;
_aNC[i].client.connIndex = i;
_aNC[i].client.id = i;
_aNC[i].client.pending = true;
/* Revisit this chunk - not needed at the moment as NC is handed off and this
// is handled elsewhere
// Need to put in some event dispatching as a more elegant solution and leave it here
_aNC[i].client.onBWDone = function (p_bw, deltaDown, deltaTime, latency) {
//this.owner.dispatchEvent ({type:"ncBandWidth", kbps:p_bw, latency:latency});
};
_aNC[i].client.onBWCheck = function (counter) {
return ++counter;
};
_aNC[i].client.onStatus = function (info) {
//
};
*/
}
m_connListCounter = 0;
nextConnect ();
}
private function nextConnect():void
{
trace("*** Connection: "+ m_connListCounter + ": "+m_connList[m_connListCounter].protocol + "://" + m_serverName + m_connList[m_connListCounter].port + "/" + m_appName);
try {
_aNC[m_connListCounter].connect(m_connList[m_connListCounter].protocol + "://" + m_serverName + m_connList[m_connListCounter].port + "/" + m_appName);
} catch (error:Error) {
// statements
trace("*** Caught an error condition: "+error);
m_connListCounter = m_connList.length+1;
}
// statements
clearInterval(_aNC["ncInt" + m_connListCounter]);
if ((m_connListCounter < m_connList.length - 1))
{
m_connListCounter++;
_aNC["ncInt" + m_connListCounter] = setInterval(nextConnect,1500);
}
}
// Cleans up all connections if none have succeeded by the timeout interval
private function onFlashComConnectTimeOut(timeout:Number):void
{
stopAll();
}
private function handleGoodConnect(_nc:NetConnection):void {
negotiating=false;
trace("Handing OFF NetConnection");
clearInterval(m_flashComConnectTimeOut);
_ncRef.connectStream();
_ncRef.onBWDone(null,_nc);
//dispatchEvent(event);
// Need to enable and pass to Jplayer event system- revisit
// right now handing back a hardcoded reference that is passed in
// Should come up with a more loosely coupled way via event dispatch
}
public function getNegotiating():Boolean {
return negotiating;
}
public function setNegotiating(bool:Boolean):void {
negotiating=bool;
}
public function stopAll(bool:Boolean=false):void {
//this.dispatchEvent ({type:"ncFailedToConnect", timeout:timeout});
// Need to enable and pass to Jplayer event system- revisit
// trace(_aNC+":"+m_flashComConnectTimeOut+":"+m_connList.length)
if(_aNC!=null && !isNaN(m_flashComConnectTimeOut) ) {
clearInterval(m_flashComConnectTimeOut);
for (var i:uint = 0; i < m_connList.length; i++)
{
if (_aNC[i]!=null)
{
clearInterval(_aNC["ncInt" + i]);
_aNC[i].close();
if(bool==false) {
_aNC[i].client = null;
}
_aNC[i] = null;
delete _aNC[i];
}
}
}
}
private function netStatus(event:NetStatusEvent):void {
trace(event.info.code);
if(event.info.description != undefined) {
trace(event.info.description);
}
_aNC[event.target.client.id].client.pending = true;
// this.owner.m_validNetConnection = this.client.owner[this.client.connIndex];
// if (info.description == "[ License.Limit.Exceeded ]") {
switch (event.info.code) {
case "NetConnection.Connect.IdleTimeOut":
trace("IDLE TIMEOUT OCCURRED!")
negotiating=true;
idleTimeOut=true;
_ncRef.shutDownNcNs();
break;
case "NetConnection.Connect.Closed":
if(!negotiating && !idleTimeOut) {
idleTimeOut = false;
_ncRef.doneYet();
}
break;
case "NetConnection.Connect.InvalidApp":
case "NetConnection.Connect.Rejected":
//handleRejectedOrInvalid(event)
break;
case "NetConnection.Call.Failed":
/*
if (event.info.description.indexOf("_checkbw") != -1) {
event.target.expectBWDone = true;
event.target.call("checkBandwidth",null);
}
*/
break;
case "NetConnection.Connect.Success":
var i:uint=0;
for ( i = 0; i<_aNC.length; i++) {
if (_aNC[i] && (i != event.target.client.id)) {
_aNC[i].close();
_aNC[i] = null;
}
}
var _nc:NetConnection = NetConnection(event.target);
var connID:Number = event.target.client.id;
var _actualPort:String = m_connList[m_connListCounter].port;
var _actualProtocol:String = m_connList[m_connListCounter].protocol;
// See if we have version info
var _serverVersion:String = "UNKNOWN";
if (event.info.data && event.info.data.version) {
_serverVersion = event.info.data.version;
}
trace("Connect ID: "+connID+" - PORT: "+_actualPort+" - PROTOCOL: "+_actualProtocol+" - FMS Version: "+_serverVersion);
clearInterval(_aNC["ncInt" + connID]);
clearInterval(_aNC["ncInt" + m_connListCounter]);
handleGoodConnect(_nc);
break;
}
}
/** Catches any netconnection net security errors
* @private
*/
private function netSecurityError(event:SecurityErrorEvent):void {
trace("SECURITY ERROR:"+event);
//dispatchEvent(event);
// Need to enable and pass to Jplayer event system- revisit
}
/** Catches any async errors
* @private
*/
private function asyncError(event:AsyncErrorEvent):void {
trace("ASYNC ERROR:"+event.error);
//dispatchEvent(event);
// Need to enable and pass to Jplayer event system- revisit
}
}// class
} //package
|