001: package com.sun.portal.netlet.client.jnlp.connect;
002:
003: import java.io.OutputStream;
004: import com.sun.portal.log.common.PortalLogger;
005: import java.io.IOException;
006: import java.io.UnsupportedEncodingException;
007: import java.io.InputStream;
008: import java.net.Socket;
009:
010: public class HTTPS_Handler implements ProtocolHandlerI {
011:
012: /**
013: * handleRequest
014: *
015: * $desc Following describes the sequence of events that takes places between
016: * the browser and end host
017: *
018: * a. Connection receives CONNECT request from browser.
019: * b. Connection opens a tunnel to enterprise proxy, if one exists.
020: * c. Enterprise proxy establishes a connection with EProxy and sends the response to proxylet.
021: * d. At this point, a tunnel is established between proxylet and EProxy.
022: * e. Connection sends a special CONNECT command comprising the end host and port value to EProxy.
023: * f. Eproxy inteprets this message and establishes a connection with end host.
024: * g. If an external proxy is configured at the EProxy end, EProxy sends a CONNECT command to the
025: * external proxy requesting connection to end host. It then sends a response back to enterprise
026: * proxy or to proxylet.
027: * h. At this point, a virtual connection is established between proxylet and end host.
028: * i. Connection would then start tunneling data back and forth between the browser and end host.
029: * @param requestFields
030: * @param in
031: * @param out
032: * @throws IOException
033: */
034: public void handleRequest(HTTPFields requestFields,
035: HTTPRequestStream in, OutputStream out) throws IOException {
036: OutputStream remoteOut = null;
037: java.io.InputStream remoteIn = null;
038: Socket remoteConnect = null;
039: PSessionMsg pMsg = new PSessionMsg(Constants.PMSG_ID.getBytes());
040:
041: try {
042: if (requestFields.getPort() == -1)
043: throw new IOException(
044: "No port specified in CONNECT to \""
045: + requestFields + "\"");
046:
047: try {
048: /*
049: if( GlobalConfigMgr.getUseClientProxy() )
050: {
051: remoteConnect = this.createTunnelSocket();
052: }
053: else{
054: Log.message("" + GlobalConfigMgr.getGatewayHost() + " " + GlobalConfigMgr.getGatewayPort());
055: remoteConnect = new Socket(GlobalConfigMgr.getGatewayHost(), GlobalConfigMgr.getGatewayPort());
056: }
057: */
058: } catch (Exception e) {
059: //Log.error("Exception " + e.getMessage());
060: throw new IOException(e.getMessage());
061: }
062:
063: remoteOut = remoteConnect.getOutputStream();
064: remoteIn = remoteConnect.getInputStream();
065: //
066: // check if end-to-end tunnel is required
067: // end-2-end tunnel is required when user has requested connection to some internal
068: // site that runs https
069: //
070:
071: //Log.message("Req host " + requestFields.getHost() );
072: /*
073: if( !requestFields.getHost().equalsIgnoreCase(GlobalConfigMgr.getGatewayHost()))
074: {
075: //Log.message( "Send End to End Protocol");
076: //
077: // Send a special message to gateway indicating that a tunnel is to be
078: // established with the end host
079: //
080: int rc = pMsg.writeMsg(remoteOut,requestFields.getHost(), requestFields.getPort());
081: if ( rc == -1 )
082: {
083: //Log.message( "Could not send proxylet special message ");
084: throw new IOException("Could not send proxylet special message");
085: }
086: //
087: // Wait for a response from Gateway
088: //
089: String resp = readResponse(remoteIn);
090: //Log.message( "Response from gateway " + resp);
091: if( resp.indexOf("200") >= 0)
092: {
093: // send a response for CONNECT command to user agent.
094: //Log.message( "Send response for CONNECT message");
095: out.write("HTTP/1.0 200 Connection established\r\n\r\n".getBytes());
096: out.flush();
097: }
098:
099: }
100: else{
101: //Log.message( "Send Connect response");
102: //
103: //Write the response of tunneling to browser
104: //
105: out.write("HTTP/1.0 200 Connection established\r\n\r\n".getBytes());
106: out.flush();
107:
108: }
109:
110:
111: StreamCopier copyOut = new StreamCopier(in, remoteOut, "Browser-> Gateway");
112: StreamCopier copyIn = new StreamCopier(remoteIn, out, "Browser <- Gateway ");
113: synchronized(copyIn)
114: {
115: synchronized(copyOut)
116: {
117: while(copyIn.isCopying() && copyOut.isCopying())
118: {
119: try
120: {
121: copyIn.wait(1000L);
122: }
123: catch(InterruptedException e) { }
124: try
125: {
126: copyOut.wait(1000L);
127: }
128: catch(InterruptedException e) { }
129: }
130: }
131: }
132: if(copyIn.getException() != null)
133: {
134: if(copyIn.getRecord().length == 0)
135: throw copyIn.getException();
136: System.err.println(requestFields + ": " + copyIn.getException());
137: }
138: requestFields.setRequestBody(copyOut.getRecord());
139: remoteOut.flush();
140: requestFields.setResponseHeader(new HTTPFields());
141: requestFields.setResponseBody(copyIn.getRecord());
142:
143: out.flush();
144: out.close();
145: in.close();
146: */
147: } catch (IOException e) {
148: throw new IOException(requestFields + ": " + e);
149: } finally {
150: try {
151: if (remoteConnect != null) {
152: remoteOut.close();
153: remoteIn.close();
154: remoteConnect.close();
155: remoteConnect = null;
156: }
157: } catch (IOException e) {
158: }
159:
160: }
161:
162: }
163:
164: private String readResponse(InputStream in) throws IOException {
165: byte reply[] = new byte[100];
166: int replyLen = 0;
167: int newlinesSeen = 0;
168: boolean headerDone = false; /* Done on first newline */
169: boolean error = false;
170:
171: while (newlinesSeen < 2) {
172: int i = in.read();
173: if (i < 0) {
174: throw new IOException("Unexpected EOF from proxy");
175: }
176: if (i == '\n') {
177: headerDone = true;
178: ++newlinesSeen;
179: } else if (i != '\r') {
180: newlinesSeen = 0;
181: if (!headerDone && replyLen < reply.length) {
182: reply[replyLen++] = (byte) i;
183: }
184: }
185: }
186:
187: reply[replyLen++] = (byte) '\0';
188:
189: return new String(reply);
190: }
191:
192: //
193: //This function is replicated in HTTP_1_Handler also.. Please do some
194: //refactoring and try to reuse code here...
195: //
196: /*
197: private Socket createTunnelSocket()
198: throws IOException
199: {
200: Socket tunnel = null ;
201:
202: try{
203: tunnel = new Socket(GlobalConfigMgr.getClientProxyHost(), GlobalConfigMgr.getClientProxyPort());
204: }catch(Exception e){
205: throw new IOException("Could not establish a connection with proxy");
206: }
207:
208: OutputStream out = tunnel.getOutputStream();
209: String msg = "CONNECT " + GlobalConfigMgr.getGatewayHost() + ":" + GlobalConfigMgr.getGatewayPort() + " HTTP/1.0\n"
210: + "User-Agent: "
211: + sun.net.www.protocol.http.HttpURLConnection.userAgent
212: + "\r\n\r\n";
213:
214: byte b[];
215: try {
216: /*
217: * We really do want ASCII7 -- the http protocol doesn't change
218: * with locale.
219: */
220: /* b = msg.getBytes("ASCII7");
221: } catch (UnsupportedEncodingException ignored) {
222: /*
223: * If ASCII7 isn't there, something serious is wrong, but
224: * Paranoia Is Good (tm)
225: */
226: /* b = msg.getBytes();
227: }
228: out.write(b);
229: out.flush();
230:
231: byte reply[] = new byte[200];
232: int replyLen = 0;
233: int newlinesSeen = 0;
234: boolean headerDone = false; /* Done on first newline */
235: /* boolean error = false;
236: InputStream in = tunnel.getInputStream();
237: while (newlinesSeen < 2) {
238: int i = in.read();
239: if (i < 0) {
240: throw new IOException("Unexpected EOF from proxy");
241: }
242: if (i == '\n') {
243: headerDone = true;
244: ++newlinesSeen;
245: } else if (i != '\r') {
246: newlinesSeen = 0;
247: if (!headerDone && replyLen < reply.length) {
248: reply[replyLen++] = (byte) i;
249: }
250: }
251: }
252:
253: /*
254: * Converting the byte array to a string is slightly wasteful
255: * in the case where the connection was successful, but it's
256: * insignificant compared to the network overhead.
257: */
258: /* String replyStr;
259: try {
260: replyStr = new String(reply, 0, replyLen, "ASCII7");
261: } catch (UnsupportedEncodingException ignored) {
262: replyStr = new String(reply, 0, replyLen);
263: }
264:
265: /* Look for 200 connection established */
266: /* if(replyStr.toLowerCase().indexOf("200 connection established") == -1){
267: throw new IOException("Unable to tunnel through "
268: + GlobalConfigMgr.getClientProxyHost()+ ":" + GlobalConfigMgr.getClientProxyPort()
269: + ". Proxy returns \"" + replyStr + "\"");
270: }
271:
272: return tunnel;
273:
274: }
275: */
276:
277: }
|