package de.dtele.net {
import de.dtele.net.events.ConnectionErrorEvent;
import de.dtele.net.events.ConnectionEvent;
import de.dtele.net.events.ProtocolHandlerErrorEvent;
import de.dtele.net.events.ProtocolHandlerEvent;
import de.dtele.net.protocol.IProtocolHandler;
import de.dtele.providers.ProviderManager;
import flash.events.EventDispatcher;
import mx.utils.URLUtil;
/**
* Dispatched when the connection has been opened
*
* @eventType de.dtele.net.events.ConnectionEvent.OPENED
*/
[Event("opened", type="de.dtele.net.events.ConnectionEvent")]
/**
* Dispatched when the connection has been closed
*
* @eventType de.dtele.net.events.ConnectionEvent.CLOSED
*/
[Event("closed", type="de.dtele.net.events.ConnectionEvent")]
/**
* Dispatched when a response has been received
*
* @eventType de.dtele.net.events.ConnectionEvent.RESPONSE
*/
[Event("response", type="de.dtele.net.events.ConnectionEvent")]
/**
* Dispatched when an error has occurred
*
* @eventType de.dtele.net.events.ConnectionEvent.ERROR
*/
[Event("error", type="de.dtele.net.events.ConnectionEvent")]
/**
* Represents a connection to an URL, no matter the underlying implementation.
* Handles MediaRequest requests to and responses from URLs.
*
* @author Mathias Brodala
*/
public class Connection extends EventDispatcher {
public static const IDLE:String = "idle";
public static const OPENING:String = "opening";
public static const OPEN:String = "open";
public static const CLOSING:String = "closing";
public static const CLOSED:String = "CLOSED";
private var _url:String;
/**
* The URL this connection points to
*/
public function get url():String {
return _url;
}
/**
* The specific handler for this URL's protocol
*/
private var handler:IProtocolHandler;
private var _state:String = Connection.IDLE;
/**
* The state this connection is in
*/
public function get state():String {
return _state;
}
/**
* Sets up the connection
*
* @param url The url the connection shall point to
*/
public function Connection(url:String) {
this._url = url;
}
/**
* Opens the connection to the URL
*/
public function open():void {
var protocol:String = URLUtil.getProtocol(this.url);
var protocolHandler:Class = ProviderManager.instance.getProvider("protocolHandlers", protocol) as Class
||
ProviderManager.instance.getProvider("protocolHandlers", "__unknown__") as Class;
this.handler = new protocolHandler();
this.handler.addEventListener(ProtocolHandlerEvent.CONNECTED, this.onHandlerConnected);
this.handler.addEventListener(ProtocolHandlerEvent.DISCONNECTED, this.onHandlerDisconnected);
this.handler.addEventListener(ProtocolHandlerEvent.RESPONSE, this.onHandlerResponse);
this.handler.addEventListener(ProtocolHandlerErrorEvent.ERROR, this.onHandlerError);
trace("[Connection] Connecting to " + this.url + " via " + handler);
this.handler.connect(this.url);
}
/**
* Sends requests to the URL
*
* @param request The MediaRequest
*/
public function send(request:MediaRequest):void {
if (this.state == Connection.CLOSED) {
this.dispatchEvent(new ConnectionEvent(ConnectionEvent.CLOSED));
return;
}
if (this.state == Connection.CLOSING) {
return;
}
if (this.handler != null) {
this.handler.send(request);
} else {
this.dispatchEvent(new ConnectionEvent(ConnectionEvent.CLOSED));
}
}
/**
* Closes the connection to the URL,
* no further requests will be possible
*/
public function close():void {
if (this.state == Connection.CLOSING) {
return;
}
if (this.state == Connection.CLOSED) {
this.dispatchEvent(new ConnectionEvent(ConnectionEvent.CLOSED));
return;
}
this._state = Connection.CLOSING;
handler.disconnect();
}
/**
* Notifies about successfully opened connections
*/
private function onHandlerConnected(e:ProtocolHandlerEvent):void {
this._state = Connection.OPEN;
this.dispatchEvent(new ConnectionEvent(ConnectionEvent.OPENED));
}
/**
* Notifies about closed connections
*/
private function onHandlerDisconnected(e:ProtocolHandlerEvent):void {
this._state = Connection.CLOSED;
this.dispatchEvent(new ConnectionEvent(ConnectionEvent.CLOSED));
}
/**
* Notifies about the response from the source
*/
private function onHandlerResponse(e:ProtocolHandlerEvent):void {
if (e.request) {
e.request.bytesLoaded = e.request.bytesTotal = 1;
}
if (e.response.version != MediaRequest.VERSION) {
this.dispatchEvent(new ConnectionErrorEvent(
ConnectionErrorEvent.ERROR,
new MediaRequestError(MediaRequestError.UNKNOWN_PROTOCOL_VERSION),
e.request
));
}
if (e.response.result == MediaResponse.ERROR) {
this.dispatchEvent(new ConnectionErrorEvent(ConnectionErrorEvent.ERROR, e.response.error, e.request));
return;
}
this.dispatchEvent(new ConnectionEvent(ConnectionEvent.RESPONSE, e.request, e.response));
}
/**
* Notifies about errors of a request
*/
private function onHandlerError(e:ProtocolHandlerErrorEvent):void {
this.dispatchEvent(new ConnectionErrorEvent(ConnectionErrorEvent.ERROR, e.error, e.request));
}
}
}