PageRenderTime 526ms CodeModel.GetById 181ms app.highlight 144ms RepoModel.GetById 198ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocket.as

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
ActionScript | 370 lines | 279 code | 59 blank | 32 comment | 14 complexity | 0355b553f39c273b2967cf166e7c3966 MD5 | raw file
  1/**
  2 * TLSSocket
  3 * 
  4 * This is the "end-user" TLS class.
  5 * It works just like a Socket, by encapsulating a Socket and
  6 * wrapping the TLS protocol around the data that passes over it.
  7 * This class can either create a socket connection, or reuse an
  8 * existing connected socket. The later is useful for STARTTLS flows.
  9 * 
 10 * Copyright (c) 2007 Henri Torgemane
 11 * 
 12 * See LICENSE.txt for full license information.
 13 */
 14package com.hurlant.crypto.tls {
 15	import flash.events.Event;
 16	import flash.events.EventDispatcher;
 17	import flash.events.IOErrorEvent;
 18	import flash.events.ProgressEvent;
 19	import flash.events.SecurityErrorEvent;
 20	import flash.net.ObjectEncoding;
 21	import flash.net.Socket;
 22	import flash.utils.ByteArray;
 23	import flash.utils.Endian;
 24	import flash.utils.IDataInput;
 25	import flash.utils.IDataOutput;
 26	import flash.utils.clearTimeout;
 27	import flash.utils.setTimeout;
 28	import com.hurlant.crypto.cert.X509Certificate;
 29	
 30	
 31	[Event(name="close", type="flash.events.Event")]
 32	[Event(name="connect", type="flash.events.Event")]
 33	[Event(name="ioError", type="flash.events.IOErrorEvent")]
 34	[Event(name="securityError", type="flash.events.SecurityErrorEvent")]
 35	[Event(name="socketData", type="flash.events.ProgressEvent")]
 36	[Event(name="acceptPeerCertificatePrompt", type="flash.events.Event")]
 37	
 38	/**
 39	 * It feels like a socket, but it wraps the stream
 40	 * over TLS 1.0
 41	 * 
 42	 * That's all.
 43	 * 
 44	 */
 45	public class TLSSocket extends Socket implements IDataInput, IDataOutput {
 46		
 47		private var _endian:String;
 48		private var _objectEncoding:uint;
 49		
 50		private var _iStream:ByteArray;
 51		private var _oStream:ByteArray;
 52		private var _iStream_cursor:uint;
 53		
 54		private var _socket:Socket;
 55		private var _config:TLSConfig;
 56		private var _engine:TLSEngine;
 57		public static const ACCEPT_PEER_CERT_PROMPT:String = "acceptPeerCertificatePrompt"
 58		
 59		public function TLSSocket(host:String = null, port:int = 0, config:TLSConfig = null) {
 60			_config = config;
 61			if (host!=null && port!=0) {
 62				connect(host, port);
 63			}
 64		}
 65		
 66		override public function get bytesAvailable():uint {
 67			return _iStream.bytesAvailable;
 68		}
 69		override public function get connected():Boolean {
 70			return _socket.connected;
 71		}
 72		override public function get endian():String {
 73			return _endian;
 74		}
 75		override public function set endian(value:String):void {
 76			_endian = value;
 77			_iStream.endian = value;
 78			_oStream.endian = value;
 79		}
 80		override public function get objectEncoding():uint {
 81			return _objectEncoding;
 82		}
 83		override public function set objectEncoding(value:uint):void {
 84			_objectEncoding = value;
 85			_iStream.objectEncoding = value;
 86			_oStream.objectEncoding = value;
 87		}
 88		
 89		
 90		private function onTLSData(event:TLSEvent):void {
 91			if (_iStream.position == _iStream.length) {
 92				_iStream.position = 0;
 93				_iStream.length = 0;
 94				_iStream_cursor = 0;
 95			}
 96			var cursor:uint = _iStream.position;
 97			_iStream.position = _iStream_cursor;
 98			_iStream.writeBytes(event.data);
 99			_iStream_cursor = _iStream.position;
100			_iStream.position = cursor;
101			dispatchEvent(new ProgressEvent(ProgressEvent.SOCKET_DATA, false, false, event.data.length));
102		}
103		
104		private function onTLSReady(event:TLSEvent):void {
105			_ready = true;
106			scheduleWrite();
107		}
108		
109		private function onTLSClose(event:Event):void {
110			dispatchEvent(event);
111			// trace("Received TLS close");
112			close();
113		}
114		
115		private var _ready:Boolean;
116		private var _writeScheduler:uint;
117		private function scheduleWrite():void {
118			if (_writeScheduler!=0) return;
119			_writeScheduler = setTimeout(commitWrite, 0);
120		}
121		private function commitWrite():void {
122			clearTimeout(_writeScheduler);
123			_writeScheduler = 0;
124			if (_ready) {
125				_engine.sendApplicationData(_oStream);
126				_oStream.length = 0;
127			}
128		}
129		
130		
131		override public function close():void {
132			_ready = false;
133			_engine.close();
134			if (_socket.connected) {
135				_socket.flush();
136				_socket.close();
137			}
138		}
139		public function setTLSConfig( config:TLSConfig) : void {
140			_config = config;
141		}		
142
143		override public function connect(host:String, port:int):void {
144			init(new Socket, _config, host);
145			_socket.connect(host, port);
146			_engine.start();
147		}
148		
149		public function releaseSocket() : void {
150			_socket.removeEventListener(Event.CONNECT, dispatchEvent);
151			_socket.removeEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
152			_socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, dispatchEvent);
153			_socket.removeEventListener(Event.CLOSE, dispatchEvent);
154			_socket.removeEventListener(ProgressEvent.SOCKET_DATA, _engine.dataAvailable);
155			_socket = null; 
156		}
157		
158		public function reinitialize(host:String, config:TLSConfig) : void {
159			// Reinitialize the connection using new values
160			// but re-use the existing socket
161			// Doubt this is useful in any valid context other than my specific case (VMWare)
162			var ba:ByteArray = new ByteArray;
163			
164			if (_socket.bytesAvailable > 0) {
165				_socket.readBytes(ba, 0, _socket.bytesAvailable);	
166			}
167			// Do nothing with it.
168			_iStream = new ByteArray;
169			_oStream = new ByteArray;
170			_iStream_cursor = 0;
171			objectEncoding = ObjectEncoding.DEFAULT;
172			endian = Endian.BIG_ENDIAN;
173			/* 
174			_socket.addEventListener(Event.CONNECT, dispatchEvent);
175			_socket.addEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
176			_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, dispatchEvent);
177			_socket.addEventListener(Event.CLOSE, dispatchEvent);
178			*/
179			
180			if (config == null) {
181				config = new TLSConfig(TLSEngine.CLIENT);
182			}
183			
184			_engine = new TLSEngine(config, _socket, _socket, host);
185			_engine.addEventListener(TLSEvent.DATA, onTLSData);
186			_engine.addEventListener(TLSEvent.READY, onTLSReady);
187			_engine.addEventListener(Event.CLOSE, onTLSClose);
188			_engine.addEventListener(ProgressEvent.SOCKET_DATA, function(e:*):void { _socket.flush(); });
189			_socket.addEventListener(ProgressEvent.SOCKET_DATA, _engine.dataAvailable);
190			_engine.addEventListener( TLSEvent.PROMPT_ACCEPT_CERT, onAcceptCert );
191
192			_ready = false;
193			_engine.start();
194		}
195		
196		public function startTLS(socket:Socket, host:String, config:TLSConfig = null):void {
197			if (!socket.connected) {
198				throw new Error("Cannot STARTTLS on a socket that isn't connected.");
199			}
200			init(socket, config, host);
201			_engine.start();
202		}
203		
204		private function init(socket:Socket, config:TLSConfig, host:String):void {
205			_iStream = new ByteArray;
206			_oStream = new ByteArray;
207			_iStream_cursor = 0;
208			objectEncoding = ObjectEncoding.DEFAULT;
209			endian = Endian.BIG_ENDIAN;
210			_socket = socket;
211			_socket.addEventListener(Event.CONNECT, dispatchEvent);
212			_socket.addEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
213			_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, dispatchEvent);
214			_socket.addEventListener(Event.CLOSE, dispatchEvent);
215			
216			if (config == null) {
217				config = new TLSConfig(TLSEngine.CLIENT);
218			}
219			_engine = new TLSEngine(config, _socket, _socket, host);
220			_engine.addEventListener(TLSEvent.DATA, onTLSData);
221			_engine.addEventListener( TLSEvent.PROMPT_ACCEPT_CERT, onAcceptCert );
222			_engine.addEventListener(TLSEvent.READY, onTLSReady);
223			_engine.addEventListener(Event.CLOSE, onTLSClose);
224			_engine.addEventListener(ProgressEvent.SOCKET_DATA, function(e:*):void { if(connected) _socket.flush(); });
225			_socket.addEventListener(ProgressEvent.SOCKET_DATA, _engine.dataAvailable);
226
227			_ready = false;
228		}
229		
230		override public function flush():void {
231			commitWrite();
232			_socket.flush();
233		}
234		
235		override public function readBoolean():Boolean {
236			return _iStream.readBoolean();
237		}
238		
239		override public function readByte():int {
240			return _iStream.readByte();
241		}
242		
243		override public function readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void {
244			return _iStream.readBytes(bytes, offset, length);
245		}
246		
247		override public function readDouble():Number {
248			return _iStream.readDouble();
249		}
250		
251		override public function readFloat():Number {
252			return _iStream.readFloat();
253		}
254		
255		override public function readInt():int {
256			return _iStream.readInt();
257		}
258		
259		override public function readMultiByte(length:uint, charSet:String):String {
260			return _iStream.readMultiByte(length, charSet);
261		}
262		
263		override public function readObject():* {
264			return _iStream.readObject();
265		}
266		
267		override public function readShort():int {
268			return _iStream.readShort();
269		}
270		
271		override public function readUnsignedByte():uint {
272			return _iStream.readUnsignedByte();
273		}
274		
275		override public function readUnsignedInt():uint {
276			return _iStream.readUnsignedInt();
277		}
278		
279		override public function readUnsignedShort():uint {
280			return _iStream.readUnsignedShort();
281		}
282		
283		override public function readUTF():String {
284			return _iStream.readUTF();
285		}
286		
287		override public function readUTFBytes(length:uint):String {
288			return _iStream.readUTFBytes(length);
289		}
290		
291		override public function writeBoolean(value:Boolean):void {
292			_oStream.writeBoolean(value);
293			scheduleWrite();
294		}
295		
296		override public function writeByte(value:int):void {
297			_oStream.writeByte(value);
298			scheduleWrite();
299		}
300		
301		override public function writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void {
302			_oStream.writeBytes(bytes, offset, length);
303			scheduleWrite();
304		}
305		
306		override public function writeDouble(value:Number):void {
307			_oStream.writeDouble(value);
308			scheduleWrite();
309		}
310		
311		override public function writeFloat(value:Number):void {
312			_oStream.writeFloat(value);
313			scheduleWrite();
314		}
315		
316		override public function writeInt(value:int):void {
317			_oStream.writeInt(value);
318			scheduleWrite();
319		}
320		
321		override public function writeMultiByte(value:String, charSet:String):void {
322			_oStream.writeMultiByte(value, charSet);
323			scheduleWrite();
324		}
325		
326		override public function writeObject(object:*):void {
327			_oStream.writeObject(object);
328			scheduleWrite();
329		}
330		
331		override public function writeShort(value:int):void {
332			_oStream.writeShort(value);
333			scheduleWrite();
334		}
335		
336		override public function writeUnsignedInt(value:uint):void {
337			_oStream.writeUnsignedInt(value);
338			scheduleWrite();
339		}
340		
341		override public function writeUTF(value:String):void {
342			_oStream.writeUTF(value);
343			scheduleWrite();
344		}
345		
346		override public function writeUTFBytes(value:String):void {
347			_oStream.writeUTFBytes(value);
348			scheduleWrite();
349		}
350		
351		public function getPeerCertificate() : X509Certificate {
352			return _engine.peerCertificate;
353		}
354		
355		public function onAcceptCert( event:TLSEvent ) : void {
356			dispatchEvent( new TLSSocketEvent( _engine.peerCertificate ) );
357		}
358		
359		// These are just a passthroughs to the engine. Encapsulation, et al
360		public function acceptPeerCertificate( event:Event ) : void {
361			_engine.acceptPeerCertificate();
362		}
363	
364		public function rejectPeerCertificate( event:Event ) : void {
365			_engine.rejectPeerCertificate();
366		}
367		
368	}
369}
370