Project

General

Profile

Statistics
| Branch: | Revision:

colonymech / docs / www / colonyscout / internal / includes / uploadify / com / adobe / net / proxies / RFC2817Socket.as @ f59acf11

History | View | Annotate | Download (6.89 KB)

1
/*
2
  Copyright (c) 2008, Adobe Systems Incorporated
3
  All rights reserved.
4

    
5
  Redistribution and use in source and binary forms, with or without 
6
  modification, are permitted provided that the following conditions are
7
  met:
8

    
9
  * Redistributions of source code must retain the above copyright notice, 
10
    this list of conditions and the following disclaimer.
11
  
12
  * Redistributions in binary form must reproduce the above copyright
13
    notice, this list of conditions and the following disclaimer in the 
14
    documentation and/or other materials provided with the distribution.
15
  
16
  * Neither the name of Adobe Systems Incorporated nor the names of its 
17
    contributors may be used to endorse or promote products derived from 
18
    this software without specific prior written permission.
19

    
20
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21
  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22
  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
24
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
*/
32
package com.adobe.net.proxies
33
{
34
	import flash.events.Event;
35
	import flash.events.IOErrorEvent;
36
	import flash.events.ProgressEvent;
37
	import flash.net.Socket;
38

    
39
	/**
40
	 * This class allows TCP socket connections through HTTP proxies in accordance with
41
	 * RFC 2817:
42
	 * 
43
	 * ftp://ftp.rfc-editor.org/in-notes/rfc2817.txt
44
	 * 
45
	 * It can also be used to make direct connections to a destination, as well. If you
46
	 * pass the host and port into the constructor, no proxy will be used. You can also
47
	 * call connect, passing in the host and the port, and if you didn't set the proxy
48
	 * info, a direct connection will be made. A proxy is only used after you have called
49
	 * the setProxyInfo function.
50
	 * 
51
	 * The connection to and negotiation with the proxy is completely hidden. All the
52
	 * same events are thrown whether you are using a proxy or not, and the data you
53
	 * receive from the target server will look exact as it would if you were connected
54
	 * to it directly rather than through a proxy.
55
	 * 
56
	 * @author Christian Cantrell
57
	 * 
58
	 **/
59
	public class RFC2817Socket
60
		extends Socket
61
	{
62
		private var proxyHost:String = null;
63
		private var host:String = null;
64
		private var proxyPort:int = 0;
65
		private var port:int = 0;
66
		private var deferredEventHandlers:Object = new Object();
67
		private var buffer:String = new String();
68

    
69
		/**
70
		 * Construct a new RFC2817Socket object. If you pass in the host and the port,
71
		 * no proxy will be used. If you want to use a proxy, instantiate with no
72
		 * arguments, call setProxyInfo, then call connect.
73
		 **/
74
		public function RFC2817Socket(host:String = null, port:int = 0)
75
		{
76
			super(host, port);
77
		}
78
		
79
		/**
80
		 * Set the proxy host and port number. Your connection will only proxied if
81
		 * this function has been called.
82
		 **/
83
		public function setProxyInfo(host:String, port:int):void
84
		{
85
			this.proxyHost = host;
86
			this.proxyPort = port;
87

    
88
			var deferredSocketDataHandler:Object = this.deferredEventHandlers[ProgressEvent.SOCKET_DATA];
89
			var deferredConnectHandler:Object = this.deferredEventHandlers[Event.CONNECT];
90

    
91
			if (deferredSocketDataHandler != null)
92
			{
93
				super.removeEventListener(ProgressEvent.SOCKET_DATA, deferredSocketDataHandler.listener, deferredSocketDataHandler.useCapture);
94
			}
95

    
96
			if (deferredConnectHandler != null)
97
			{
98
				super.removeEventListener(Event.CONNECT, deferredConnectHandler.listener, deferredConnectHandler.useCapture);
99
			}
100
		}
101
		
102
		/**
103
		 * Connect to the specified host over the specified port. If you want your
104
		 * connection proxied, call the setProxyInfo function first.
105
		 **/
106
		public override function connect(host:String, port:int):void
107
		{
108
			if (this.proxyHost == null)
109
			{
110
				this.redirectConnectEvent();
111
				this.redirectSocketDataEvent();
112
				super.connect(host, port);
113
			}
114
			else
115
			{
116
				this.host = host;
117
				this.port = port;
118
				super.addEventListener(Event.CONNECT, this.onConnect);
119
				super.addEventListener(ProgressEvent.SOCKET_DATA, this.onSocketData);
120
				super.connect(this.proxyHost, this.proxyPort);
121
			}
122
		}
123

    
124
		private function onConnect(event:Event):void
125
		{
126
			this.writeUTFBytes("CONNECT "+this.host+":"+this.port+" HTTP/1.1\n\n");
127
			this.flush();
128
			this.redirectConnectEvent();
129
		}
130
		
131
		private function onSocketData(event:ProgressEvent):void
132
		{
133
			while (this.bytesAvailable != 0)
134
			{
135
				this.buffer += this.readUTFBytes(1);
136
				if (this.buffer.search(/\r?\n\r?\n$/) != -1)
137
				{
138
					this.checkResponse(event);
139
					break;
140
				}
141
			}
142
		}
143
		
144
		private function checkResponse(event:ProgressEvent):void
145
		{
146
			var responseCode:String = this.buffer.substr(this.buffer.indexOf(" ")+1, 3);
147

    
148
			if (responseCode.search(/^2/) == -1)
149
			{
150
				var ioError:IOErrorEvent = new IOErrorEvent(IOErrorEvent.IO_ERROR);
151
				ioError.text = "Error connecting to the proxy ["+this.proxyHost+"] on port ["+this.proxyPort+"]: " + this.buffer;
152
				this.dispatchEvent(ioError);
153
			}
154
			else
155
			{
156
				this.redirectSocketDataEvent();
157
				this.dispatchEvent(new Event(Event.CONNECT));
158
				if (this.bytesAvailable > 0)
159
				{
160
					this.dispatchEvent(event);
161
				}
162
			}
163
			this.buffer = null;
164
		}
165
		
166
		private function redirectConnectEvent():void
167
		{
168
			super.removeEventListener(Event.CONNECT, onConnect);
169
			var deferredEventHandler:Object = this.deferredEventHandlers[Event.CONNECT];
170
			if (deferredEventHandler != null)
171
			{
172
				super.addEventListener(Event.CONNECT, deferredEventHandler.listener, deferredEventHandler.useCapture, deferredEventHandler.priority, deferredEventHandler.useWeakReference);			
173
			}
174
		}
175
		
176
		private function redirectSocketDataEvent():void
177
		{
178
			super.removeEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
179
			var deferredEventHandler:Object = this.deferredEventHandlers[ProgressEvent.SOCKET_DATA];
180
			if (deferredEventHandler != null)
181
			{
182
				super.addEventListener(ProgressEvent.SOCKET_DATA, deferredEventHandler.listener, deferredEventHandler.useCapture, deferredEventHandler.priority, deferredEventHandler.useWeakReference);			
183
			}
184
		}
185
		
186
		public override function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int=0.0, useWeakReference:Boolean=false):void
187
		{
188
			if (type == Event.CONNECT || type == ProgressEvent.SOCKET_DATA)
189
			{
190
				this.deferredEventHandlers[type] = {listener:listener,useCapture:useCapture, priority:priority, useWeakReference:useWeakReference};
191
			}
192
			else
193
			{
194
				super.addEventListener(type, listener, useCapture, priority, useWeakReference);
195
			}
196
		}
197
	}
198
}