001: package com.sun.portal.netlet.eproxy;
002:
003: /**
004: * ProxyletSession
005: *
006: * @desc Opens a connection to end-host ( through proxy/direct ).
007: * Tunnels data between proxylet and end-host.
008: *
009: * @author Sudha.S
010: */
011:
012: import java.io.ByteArrayOutputStream;
013: import java.io.IOException;
014: import java.io.InputStream;
015: import java.io.OutputStream;
016: import java.io.UnsupportedEncodingException;
017: import java.net.Socket;
018: import java.util.logging.Level;
019: import java.util.logging.Logger;
020:
021: import com.sun.portal.log.common.PortalLogger;
022: import com.sun.portal.rproxy.configservlet.client.GatewayProfile;
023: import com.sun.portal.rproxy.connectionhandler.HTTPRequest;
024: import com.sun.portal.util.GWDebug;
025: import com.sun.portal.util.ServiceIdentifier;
026:
027: public class ProxyletSession implements Runnable {
028: protected InputStream nonsslin;
029:
030: protected OutputStream nonsslout;
031:
032: protected Socket nonsslsocket;
033:
034: protected Integer logId;
035:
036: protected String endhost;
037:
038: protected int endport;
039:
040: protected Socket connection;
041:
042: protected static boolean _useProxy;
043:
044: protected HTTPRequest req = null;
045:
046: // private static Logger logger =
047: // Logger.getLogger("com.sun.portal.sra.netlet");
048: private static Logger logger = PortalLogger
049: .getLogger(ProxyletSession.class);
050:
051: public ProxyletSession() {
052: }
053:
054: public ProxyletSession(Socket nonsslsocket, Integer logId,
055: String host, int port, Socket sslsocket) {
056: try {
057: logId = logId;
058: this .nonsslsocket = nonsslsocket;
059: // System.out.println("nonssl socket info in ProxyletSession " +
060: // nonsslsocket );
061: nonsslin = nonsslsocket.getInputStream();
062: nonsslout = nonsslsocket.getOutputStream();
063:
064: this .endhost = host;
065: this .endport = port;
066:
067: this .connection = sslsocket;
068:
069: } catch (Exception e) {
070: e.printStackTrace();
071: }
072: }
073:
074: static {
075: //
076: // Indicates if proxy option is enabled in the gateway.
077: //
078: _useProxy = GatewayProfile.getBoolean("UseProxy", false)
079: && ServiceIdentifier.isGateway();
080: }
081:
082: public void run() {
083:
084: Socket tunnel = null;
085: InputStream in = null;
086: OutputStream out = null;
087: byte conn[] = null;
088:
089: String proxyhost = null;
090: int proxyport = -1;
091:
092: // OutputStream nonsslout = null;
093: // InputStream nonsslin = null;
094:
095: try {
096:
097: //
098: // Check from the gateway config if we need to connect
099: // through a proxy
100: //
101: if (_useProxy == true) {
102: //
103: // Determine if proxy is configured for endhost domain
104: //
105: HTTPRequest proxyDomain = new HTTPRequest("https://"
106: + endhost + ":" + endport);
107: proxyDomain.populateWebProxyInfo();
108: proxyport = proxyDomain.getProxyPort();
109: proxyhost = proxyDomain.getProxyHost();
110:
111: }
112:
113: //
114: // Connect through proxy
115: //
116: try {
117: OutputStream sslGOut = connection.getOutputStream();
118: if (proxyhost != null) {
119: tunnel = createTunnelSocket(proxyhost, proxyport,
120: endhost, endport);
121:
122: //
123: // Send a connection established message to client
124: //
125:
126: String _temp = "HTTP/1.0 200 Connection established \r\n\r\n";
127: byte[] _temp1 = _temp.getBytes();
128:
129: // System.out.println("response to be sent " + _temp);
130:
131: // now send the response to connect message
132: // nonsslout.write(_temp1);
133: // nonsslout.flush();
134: sslGOut.write(_temp1);
135: sslGOut.flush();
136: } else {
137: tunnel = new Socket(endhost, endport);
138:
139: String _temp = "HTTP/1.0 200 Connection established \r\n\r\n";
140: byte[] _temp1 = _temp.getBytes();
141:
142: // System.out.println("response to be sent " + _temp);
143:
144: // nonsslout.write(_temp1);
145: // nonsslout.flush();
146: sslGOut.write(_temp1);
147: sslGOut.flush();
148:
149: }
150: } catch (Exception e) {
151: if (GWDebug.debug.errorEnabled())
152: GWDebug.debug
153: .error("PROXYLET could not create tunnel "
154: + e.getMessage());
155:
156: e.printStackTrace();
157: nonsslout
158: .write(("HTTP/1.0 400 Failed to establish "
159: + "connection with endhost through proxy\r\n\r\n")
160: .getBytes());
161: nonsslout.flush();
162: return;
163: }
164:
165: // System.out.println("Message sent");
166:
167: try {
168: tunnel.setTcpNoDelay(true);
169: tunnel.setKeepAlive(true);
170: } catch (Exception e) {
171: }
172:
173: //
174: // Start tunneling data
175: //
176: in = tunnel.getInputStream();
177: out = tunnel.getOutputStream();
178:
179: StreamCopier copyOut = new StreamCopier(nonsslin, out,
180: "proxylet -> real server");
181: StreamCopier copyIn = new StreamCopier(in, nonsslout,
182: "proxylet<- real server");
183:
184: // tunnel.setSoTimeout(30*1000);
185: // nonsslsocket.setSoTimeout(30*1000);
186:
187: tunnel.setSoLinger(true, 240);
188:
189: synchronized (copyIn) {
190: synchronized (copyOut) {
191: while (copyIn.isCopying() && copyOut.isCopying()) {
192: try {
193: copyIn.wait(1000L);
194: } catch (InterruptedException e) {
195: }
196: try {
197: copyOut.wait(1000L);
198: } catch (InterruptedException e) {
199: }
200: }
201: }
202: }
203:
204: } catch (Exception e) {
205: // logger.severe("Error in processing proxylet connection " +
206: // e.getMessage());
207: Object[] params0 = { e.getMessage() };
208: logger.log(Level.SEVERE, "PSSRNTLT_CSPNEPROX057", params0);
209: if (GWDebug.debug.errorEnabled())
210: GWDebug.debug
211: .error("Error in processing proxylet connection "
212: + e.getMessage());
213: } finally {
214: synchronized (this ) {
215: try {
216: in.close();
217: out.close();
218: tunnel.close();
219: nonsslin.close();
220: nonsslout.close();
221: nonsslsocket.close();
222: if (connection != null)
223: connection.close();
224: // System.out.println("in the finally block of
225: // proxyletsession");
226: } catch (Exception e) {
227: }
228:
229: }
230:
231: }
232:
233: }
234:
235: public Socket createTunnelSocket(String proxyhost, int proxyport,
236: String endhost, int endport) throws IOException {
237: int replyLen = 0;
238: Socket tunnel = new Socket(proxyhost, proxyport);
239:
240: if (endport == -1)
241: endport = 443;
242:
243: OutputStream out = tunnel.getOutputStream();
244: String msg = null;
245: msg = "CONNECT " + endhost + ":" + endport + " HTTP/1.0\n"
246: + "User-Agent: "
247: + sun.net.www.protocol.http.HttpURLConnection.userAgent
248: + "\r\n\r\n";
249:
250: byte b[];
251: try {
252: // We really do want ASCII7 -- the http protocol doesn't change
253: // with locale.
254: b = msg.getBytes("ASCII7");
255: } catch (UnsupportedEncodingException ignored) {
256: // If ASCII7 isn't there, something serious is wrong, but
257: // Paranoia Is Good (tm)
258: b = msg.getBytes();
259: }
260: out.write(b);
261: out.flush();
262:
263: // We need to store the reply so we can create a detailed
264: // error message to the user.
265: InputStream in = tunnel.getInputStream();
266: boolean error = false;
267:
268: byte[] reply = readInputStream(in);
269:
270: // Converting the byte array to a string is slightly wasteful
271: // in the case where the connection was successful, but it's
272: // insignificant compared to the network overhead.
273: String replyStr;
274: // try {
275: replyStr = new String(reply);
276: // } catch (UnsupportedEncodingException ignored) {
277: // System.out.println("Read response from webcache error " + ignored);
278: // replyStr = new String(reply, 0, replyLen);
279: // }
280:
281: // We asked for HTTP/1.0, so we should get that back
282: if (!replyStr.startsWith("HTTP/1.0 200")) {
283: throw new IOException("Unable to tunnel through "
284: + req.getProxyHost() + ":" + req.getProxyPort()
285: + ". Proxy returns \"" + replyStr + "\"");
286: }
287:
288: // tunneling Handshake was successful!
289: return tunnel;
290: }
291:
292: private byte[] readInputStream(InputStream in) throws IOException {
293: byte reply[] = new byte[200];
294: int replyLen = 0;
295: int newlinesSeen = 0;
296: boolean headerDone = false; // Done on first newline
297: while (newlinesSeen < 2) {
298: int i = in.read();
299: if (i < 0) {
300: throw new IOException("Unexpected EOF from proxy");
301: }
302: if (i == '\n') {
303: headerDone = true;
304: ++newlinesSeen;
305: } else if (i != '\r') {
306: newlinesSeen = 0;
307: if (!headerDone && replyLen < reply.length) {
308: reply[replyLen++] = (byte) i;
309: }
310: }
311: }
312:
313: return reply;
314: }
315:
316: public static void main(String[] args) {
317: ProxyletSession p = new ProxyletSession();
318: // System.out.println ("useproxy = " + p._useProxy );
319: }
320: }
321:
322: class StreamCopier extends Thread {
323:
324: private InputStream from;
325:
326: private OutputStream to;
327:
328: private ByteArrayOutputStream record;
329:
330: private boolean copying;
331:
332: private IOException exception;
333:
334: private String who;
335:
336: public StreamCopier(InputStream from, OutputStream to, String who) {
337: this .from = from;
338: this .to = to;
339: record = new ByteArrayOutputStream();
340: copying = true;
341: this .who = who;
342: start();
343: }
344:
345: public void run() {
346: byte buf[] = new byte[8192];
347: try {
348: for (int read = from.read(buf, 0, buf.length); read != -1; read = from
349: .read(buf, 0, buf.length)) {
350:
351: // System.out.println("Writing from " + who );
352: to.write(buf, 0, read);
353: to.flush();
354: }
355:
356: } catch (IOException e) {
357: e.printStackTrace();
358:
359: exception = e;
360: }
361:
362: synchronized (this ) {
363: copying = false;
364: notifyAll();
365: }
366:
367: }
368:
369: public byte[] getRecord() {
370: return record.toByteArray();
371: }
372:
373: public boolean isCopying() {
374: return copying;
375: }
376:
377: public IOException getException() {
378: return exception;
379: }
380:
381: }
|