source: trunk/packages/invirt-vnc-client/debian/patches/invirt-ssl-proxy.patch @ 1663

Last change on this file since 1663 was 1472, checked in by quentin, 16 years ago

Document source for included code in VNC server

File size: 24.6 KB
RevLine 
[1438]1Index: invirt-vnc-client/InvirtTrustManager.java
2===================================================================
3--- /dev/null   1970-01-01 00:00:00.000000000 +0000
4+++ invirt-vnc-client/InvirtTrustManager.java   2008-10-31 06:09:10.000000000 -0400
[1472]5@@ -0,0 +1,123 @@
6+// This code is based on http://svntrac.hanhuy.com/repo/browser/hanhuy/trunk/cms/src/com/hanhuy/ria/client/RIATrustManager.java
[1438]7+/*
8+ * Copyright 2006 Perry Nguyen <pfnguyen@hanhuy.com>
9+ * Licensed under the Apache License, Version 2.0 (the "License");
10+ * you may not use this file except in compliance with the License.
11+ * You may obtain a copy of the License at
12+ *
13+ *     http://www.apache.org/licenses/LICENSE-2.0
14+ *
15+ * Unless required by applicable law or agreed to in writing, software
16+ * distributed under the License is distributed on an "AS IS" BASIS,
17+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+ * See the License for the specific language governing permissions and
19+ * limitations under the License.
20+ */
21+import java.io.IOException;
22+import java.io.InputStream;
23+import java.security.KeyStore;
24+import java.security.KeyStoreException;
25+import java.security.NoSuchAlgorithmException;
26+import java.security.cert.CertificateException;
27+import java.security.cert.X509Certificate;
28+import java.util.Enumeration;
29+import java.util.logging.Level;
30+import java.util.logging.Logger;
31+
32+import javax.net.ssl.TrustManager;
33+import javax.net.ssl.TrustManagerFactory;
34+import javax.net.ssl.X509TrustManager;
35+
36+public class InvirtTrustManager implements X509TrustManager {
37+    private X509TrustManager trustManager;
38+    private final static char[] KEY_STORE_PASSWORD =
39+        { 'f', 'o', 'o', 'b', 'a', 'r' };
40+    private final static String KEY_STORE_RESOURCE =
41+        "trust.store";
42+
43+    private KeyStore loadKeyStore() throws Exception {
44+        InputStream in = getClass().getClassLoader().getResourceAsStream(
45+                KEY_STORE_RESOURCE);
46+        KeyStore ks = null;
47+        try {
48+            if (in == null) {
49+                //log.severe("Unable to open KeyStore");
50+                throw new NullPointerException();
51+            }
52+            ks = KeyStore.getInstance(KeyStore.getDefaultType());
53+            ks.load(in, KEY_STORE_PASSWORD);
54+           /*if (log.isLoggable(Level.FINEST)) {
55+                for (Enumeration<String> aliases = ks.aliases();
56+                aliases.hasMoreElements();) {
57+                    String alias = aliases.nextElement();
58+                    log.finest("ALIAS: " + alias);
59+                }
60+               }*/
61+        } catch (NoSuchAlgorithmException e) {
62+            throwError(e);
63+        } catch (CertificateException e) {
64+            throwError(e);
65+        } catch (IOException e) {
66+            throwError(e);
67+        } catch (KeyStoreException e) {
68+            throwError(e);
69+        } finally {
70+            try {
71+                if (in != null)
72+                    in.close();
73+            }
74+            catch (IOException e) { } // ignore
75+        }
76+        return ks;
77+    }
78+    private void createTrustManager() {
79+       try {
80+           try {
81+               KeyStore keystore = loadKeyStore();
82+               TrustManagerFactory factory = TrustManagerFactory.getInstance(
83+                                                                             TrustManagerFactory.getDefaultAlgorithm());
84+               factory.init(keystore);
85+               TrustManager[] trustManagers = factory.getTrustManagers();
86+               if (trustManagers.length == 0)
87+                   throw new IllegalStateException("No trust manager found");
88+               setTrustManager((X509TrustManager) trustManagers[0]);
89+           } catch (NoSuchAlgorithmException e) {
90+               throwError(e);
91+           } catch (KeyStoreException e) {
92+               throwError(e);
93+           }
94+       } catch (Exception e) {
95+           e.printStackTrace();
96+       }
97+    }
98+    private void throwError(Exception e) throws Exception {
99+        //HttpClientError error = new HttpClientError(e.getMessage());
100+        //error.initCause(e);
101+        throw e;
102+    }
103+    public X509TrustManager getTrustManager() {
104+        if (trustManager == null)
105+            createTrustManager();
106+        return trustManager;
107+    }
108+
109+    public void setTrustManager(X509TrustManager trustManager) {
110+        this.trustManager = trustManager;
111+    }
112+
113+    public void checkClientTrusted(X509Certificate[] chain, String authType)
114+            throws CertificateException {
115+        getTrustManager().checkClientTrusted(chain, authType);
116+    }
117+
118+    public void checkServerTrusted(X509Certificate[] chain, String authType)
119+            throws CertificateException {
120+        getTrustManager().checkServerTrusted(chain, authType);
121+
122+    }
123+
124+    public X509Certificate[] getAcceptedIssuers() {
125+        return getTrustManager().getAcceptedIssuers();
126+    }
127+
128+}
129\ No newline at end of file
130Index: invirt-vnc-client/Makefile
131===================================================================
132--- invirt-vnc-client.orig/Makefile     2008-10-31 06:09:10.000000000 -0400
133+++ invirt-vnc-client/Makefile  2008-10-31 06:09:10.000000000 -0400
134@@ -17,8 +17,10 @@
135          DesCipher.class CapabilityInfo.class CapsContainer.class \
136          RecordingFrame.class SessionRecorder.class \
137          SocketFactory.class HTTPConnectSocketFactory.class \
138+         VNCProxyConnectSocketFactory.class VNCProxyConnectSocket.class \
139          HTTPConnectSocket.class ReloginPanel.class \
140-         InStream.class MemInStream.class ZlibInStream.class
141+         InStream.class MemInStream.class ZlibInStream.class \
142+         VNCProxyConnectSocketWrapper.class SocketWrapper.class SocketWrapper\$$WrappingSocketImpl.class InvirtTrustManager.class
143 
144 SOURCES = VncViewer.java RfbProto.java AuthPanel.java VncCanvas.java \
145          VncCanvas2.java \
146@@ -26,8 +28,10 @@
147          DesCipher.java CapabilityInfo.java CapsContainer.java \
148          RecordingFrame.java SessionRecorder.java \
149          SocketFactory.java HTTPConnectSocketFactory.java \
150+         VNCProxyConnectSocketFactory.java VNCProxyConnectSocket.java \
151          HTTPConnectSocket.java ReloginPanel.java \
152-         InStream.java MemInStream.java ZlibInStream.java
153+         InStream.java MemInStream.java ZlibInStream.java \
154+         VNCProxyConnectSocketWrapper.java SocketWrapper.java InvirtTrustManager.java
155 
156 all: $(CLASSES) $(ARCHIVE)
157 
158Index: invirt-vnc-client/RfbProto.java
159===================================================================
160--- invirt-vnc-client.orig/RfbProto.java        2007-04-26 22:36:00.000000000 -0400
161+++ invirt-vnc-client/RfbProto.java     2008-10-31 06:09:10.000000000 -0400
162@@ -208,11 +208,13 @@
163     port = p;
164 
165     if (viewer.socketFactory == null) {
166+       System.out.println("Null socketFactory");
167       sock = new Socket(host, port);
168     } else {
169       try {
170        Class factoryClass = Class.forName(viewer.socketFactory);
171        SocketFactory factory = (SocketFactory)factoryClass.newInstance();
172+       System.out.println("Using socketFactory " + factory);
173        if (viewer.inAnApplet)
174          sock = factory.createSocket(host, port, viewer);
175        else
176@@ -236,7 +238,7 @@
177     try {
178       sock.close();
179       closed = true;
180-      System.out.println("RFB socket closed");
181+      System.out.println("RFB socket closed " + sock);
182       if (rec != null) {
183        rec.close();
184        rec = null;
185Index: invirt-vnc-client/SocketWrapper.java
186===================================================================
187--- /dev/null   1970-01-01 00:00:00.000000000 +0000
188+++ invirt-vnc-client/SocketWrapper.java        2008-10-31 06:09:10.000000000 -0400
[1472]189@@ -0,0 +1,263 @@
[1438]190+/*
191+ * Written by Dawid Kurzyniec and released to the public domain, as explained
192+ * at http://creativecommons.org/licenses/publicdomain
193+ */
[1472]194+// Upstream is at http://www.dcl.mathcs.emory.edu/downloads/h2o/doc/api/edu/emory/mathcs/util/net/SocketWrapper.html
[1438]195+
196+//package edu.emory.mathcs.util.net;
197+
198+import java.io.*;
199+import java.net.*;
200+import java.nio.channels.*;
201+
202+/**
203+ * Wrapper for sockets which enables to add functionality in subclasses
204+ * on top of existing, connected sockets. It is useful when direct subclassing
205+ * of delegate socket class is not possible, e.g. if the delegate socket is
206+ * created by a library. Possible usage example is socket factory chaining.
207+ * This class delegates all socket-related requests to the wrapped delegate,
208+ * as of JDK 1.4.
209+ *
210+ * @author Dawid Kurzyniec
211+ * @version 1.4
212+ */
213+public abstract class SocketWrapper extends Socket {
214+
215+    /**
216+     * the wrapped delegate socket.
217+     */
218+    protected final Socket delegate;
219+
220+    /**
221+     * Creates new socket wrapper for a given socket. The delegate
222+     * must be connected and bound and it must not be closed.
223+     * @param delegate the delegate socket to wrap
224+     * @throws SocketException if the delegate socket is closed, not bound,
225+     *                         or not connected
226+     */
227+    protected SocketWrapper(Socket delegate) throws SocketException {
228+        super(new WrappingSocketImpl(delegate));
229+        this.delegate = delegate;
230+       System.out.println("Creating SocketWrapper $Rev$");
231+    }
232+
233+    public SocketChannel getChannel() {
234+        return delegate.getChannel();
235+    }
236+
237+    /**
238+     * Returns true, indicating that the socket is bound.
239+     *
240+     * @return true
241+     */
242+    public boolean isBound() {
243+        return true;
244+    }
245+
246+    public boolean isClosed() {
247+        return super.isClosed() || delegate.isClosed();
248+    }
249+
250+    /**
251+     * Returns true, indicating that the socket is connected.
252+     *
253+     * @return true
254+     */
255+    public boolean isConnected() {
256+        return true;
257+    }
258+
259+    public boolean isInputShutdown() {
260+        return super.isInputShutdown() || delegate.isInputShutdown();
261+    }
262+
263+    public boolean isOutputShutdown() {
264+        return super.isInputShutdown() || delegate.isOutputShutdown();
265+    }
266+
267+    private static class WrappingSocketImpl extends SocketImpl {
268+        private final Socket delegate;
269+        WrappingSocketImpl(Socket delegate) throws SocketException {
270+            if (delegate == null) {
271+                throw new NullPointerException();
272+            }
273+            if (delegate.isClosed()) {
274+                throw new SocketException("Delegate server socket is closed");
275+            }
276+            if (!(delegate.isBound())) {
277+                throw new SocketException("Delegate server socket is not bound");
278+            }
279+            if (!(delegate.isConnected())) {
280+                throw new SocketException("Delegate server socket is not connected");
281+            }
282+            this.delegate = delegate;
283+        }
284+
285+        protected void create(boolean stream) {}
286+
287+        protected void connect(String host, int port) {
288+            // delegate is always connected, thus this method is never called
289+            throw new UnsupportedOperationException();
290+        }
291+
292+        protected void connect(InetAddress address, int port) {
293+            // delegate is always connected, thus this method is never called
294+            throw new UnsupportedOperationException();
295+        }
296+
297+        protected void connect(SocketAddress address, int timeout) {
298+            // delegate is always connected, thus this method is never called
299+            throw new UnsupportedOperationException();
300+        }
301+
302+        protected void bind(InetAddress host, int port) {
303+            // delegate is always bound, thus this method is never called
304+            throw new UnsupportedOperationException();
305+        }
306+
307+        protected void listen(int backlog) {
308+            // this wrapper is never used by a ServerSocket
309+            throw new UnsupportedOperationException();
310+        }
311+
312+        protected void accept(SocketImpl s) {
313+            // this wrapper is never used by a ServerSocket
314+            throw new UnsupportedOperationException();
315+        }
316+
317+        protected InputStream getInputStream() throws IOException {
318+            return delegate.getInputStream();
319+        }
320+
321+        protected OutputStream getOutputStream() throws IOException {
322+            return delegate.getOutputStream();
323+        }
324+
325+        protected int available() throws IOException {
326+            return getInputStream().available();
327+        }
328+
329+        protected void close() throws IOException {
330+           System.out.println("Calling delegate.close");
331+            delegate.close();
332+        }
333+
334+        protected void shutdownInput() throws IOException {
335+            delegate.shutdownInput();
336+        }
337+
338+        protected void shutdownOutput() throws IOException {
339+            delegate.shutdownOutput();
340+        }
341+
342+        protected FileDescriptor getFileDescriptor() {
343+            // this wrapper is never used by a ServerSocket
344+            throw new UnsupportedOperationException();
345+        }
346+
347+        protected InetAddress getInetAddress() {
348+            return delegate.getInetAddress();
349+        }
350+
351+        protected int getPort() {
352+            return delegate.getPort();
353+        }
354+
355+        protected boolean supportsUrgentData() {
356+            return false; // must be overridden in sub-class
357+        }
358+
359+        protected void sendUrgentData (int data) throws IOException {
360+            delegate.sendUrgentData(data);
361+        }
362+
363+        protected int getLocalPort() {
364+            return delegate.getLocalPort();
365+        }
366+
367+        public Object getOption(int optID) throws SocketException {
368+            switch (optID) {
369+                case SocketOptions.IP_TOS:
370+                    return new Integer(delegate.getTrafficClass());
371+                case SocketOptions.SO_BINDADDR:
372+                    return delegate.getLocalAddress();
373+                case SocketOptions.SO_KEEPALIVE:
374+                    return Boolean.valueOf(delegate.getKeepAlive());
375+                case SocketOptions.SO_LINGER:
376+                    return new Integer(delegate.getSoLinger());
377+                case SocketOptions.SO_OOBINLINE:
378+                    return Boolean.valueOf(delegate.getOOBInline());
379+                case SocketOptions.SO_RCVBUF:
380+                    return new Integer(delegate.getReceiveBufferSize());
381+                case SocketOptions.SO_REUSEADDR:
382+                    return Boolean.valueOf(delegate.getReuseAddress());
383+                case SocketOptions.SO_SNDBUF:
384+                    return new Integer(delegate.getSendBufferSize());
385+                case SocketOptions.SO_TIMEOUT:
386+                    return new Integer(delegate.getSoTimeout());
387+                case SocketOptions.TCP_NODELAY:
388+                    return Boolean.valueOf(delegate.getTcpNoDelay());
389+                case SocketOptions.SO_BROADCAST:
390+                default:
391+                    throw new IllegalArgumentException("Unsupported option type");
392+            }
393+        }
394+
395+        public void setOption(int optID, Object value) throws SocketException {
396+            switch (optID) {
397+                case SocketOptions.SO_BINDADDR:
398+                    throw new IllegalArgumentException("Socket is bound");
399+                case SocketOptions.SO_KEEPALIVE:
400+                    delegate.setKeepAlive(((Boolean)value).booleanValue());
401+                    break;
402+                case SocketOptions.SO_LINGER:
403+                    if (value instanceof Boolean) {
404+                        delegate.setSoLinger(((Boolean)value).booleanValue(), 0);
405+                    }
406+                    else {
407+                        delegate.setSoLinger(true, ((Integer)value).intValue());
408+                    }
409+                    break;
410+                case SocketOptions.SO_OOBINLINE:
411+                    delegate.setOOBInline(((Boolean)value).booleanValue());
412+                    break;
413+                case SocketOptions.SO_RCVBUF:
414+                    delegate.setReceiveBufferSize(((Integer)value).intValue());
415+                    break;
416+                case SocketOptions.SO_REUSEADDR:
417+                    delegate.setReuseAddress(((Boolean)value).booleanValue());
418+                    break;
419+                case SocketOptions.SO_SNDBUF:
420+                    delegate.setSendBufferSize(((Integer)value).intValue());
421+                    break;
422+                case SocketOptions.SO_TIMEOUT:
423+                    delegate.setSoTimeout(((Integer)value).intValue());
424+                    break;
425+                case SocketOptions.TCP_NODELAY:
426+                    delegate.setTcpNoDelay(((Boolean)value).booleanValue());
427+                    break;
428+                case SocketOptions.SO_BROADCAST:
429+                default:
430+                    throw new IllegalArgumentException("Unsupported option type");
431+            }
432+        }
433+    }
434+
435+    public void close() throws IOException {
436+       System.out.println("Calling SocketWrapper.delegate.close");
437+       delegate.close();
438+    }
439+
440+    public boolean equals(Object obj) {
441+        if (!(obj instanceof SocketWrapper)) return false;
442+        SocketWrapper that = (SocketWrapper)obj;
443+        return this.delegate.equals(that.delegate);
444+    }
445+
446+    public int hashCode() {
447+        return delegate.hashCode() ^ 0x01010101;
448+    }
449+    public String toString() {
450+       return "<SocketWrapper " + super.toString() + "(delegating to " + delegate.toString() +  ")" + ">";
451+    }
452+}
453\ No newline at end of file
454Index: invirt-vnc-client/VNCProxyConnectSocket.java
455===================================================================
456--- /dev/null   1970-01-01 00:00:00.000000000 +0000
457+++ invirt-vnc-client/VNCProxyConnectSocket.java        2008-10-31 06:09:10.000000000 -0400
458@@ -0,0 +1,61 @@
459+//
460+//  Copyright (C) 2002 Constantin Kaplinsky, Inc.  All Rights Reserved.
461+//  Copyright 2007 MIT Student Information Processing Board
462+//
463+//  This is free software; you can redistribute it and/or modify
464+//  it under the terms of the GNU General Public License as published by
465+//  the Free Software Foundation; either version 2 of the License, or
466+//  (at your option) any later version.
467+//
468+//  This software is distributed in the hope that it will be useful,
469+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
470+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
471+//  GNU General Public License for more details.
472+//
473+//  You should have received a copy of the GNU General Public License
474+//  along with this software; if not, write to the Free Software
475+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
476+//  USA.
477+//
478+
479+//
480+// VNCProxySocket.java together with VNCProxySocketFactory.java
481+// implement an alternate way to connect to VNC servers via one or two
482+// VNCProxy proxies supporting the VNCProxy VNCCONNECT method.
483+//
484+
485+import java.net.*;
486+import java.io.*;
487+
488+class VNCProxyConnectSocket extends Socket {
489+
490+  public VNCProxyConnectSocket(String host, int port,
491+                               String vmname, String authtoken)
492+    throws IOException {
493+
494+    // Connect to the specified HTTP proxy
495+    super(host, port);
496+
497+    // Send the CONNECT request
498+    getOutputStream().write(("CONNECTVNC " + vmname +
499+                             " VNCProxy/1.0\r\nAuth-token: " + authtoken +
500+                             "\r\n\r\n").getBytes());
501+
502+    // Read the first line of the response
503+    DataInputStream is = new DataInputStream(getInputStream());
504+    String str = is.readLine();
505+
506+    // Check the HTTP error code -- it should be "200" on success
507+    if (!str.startsWith("VNCProxy/1.0 200 ")) {
508+      if (str.startsWith("VNCProxy/1.0 "))
509+        str = str.substring(13);
510+      throw new IOException("Proxy reports \"" + str + "\"");
511+    }
512+
513+    // Success -- skip remaining HTTP headers
514+    do {
515+      str = is.readLine();
516+    } while (str.length() != 0);
517+  }
518+}
519+
520Index: invirt-vnc-client/VNCProxyConnectSocketFactory.java
521===================================================================
522--- /dev/null   1970-01-01 00:00:00.000000000 +0000
523+++ invirt-vnc-client/VNCProxyConnectSocketFactory.java 2008-10-31 06:09:10.000000000 -0400
524@@ -0,0 +1,98 @@
525+//
526+//  Copyright (C) 2002 Constantin Kaplinsky, Inc.  All Rights Reserved.
527+//  Copyright 2007 MIT Student Information Processing Board
528+//
529+//  This is free software; you can redistribute it and/or modify
530+//  it under the terms of the GNU General Public License as published by
531+//  the Free Software Foundation; either version 2 of the License, or
532+//  (at your option) any later version.
533+//
534+//  This software is distributed in the hope that it will be useful,
535+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
536+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
537+//  GNU General Public License for more details.
538+//
539+//  You should have received a copy of the GNU General Public License
540+//  along with this software; if not, write to the Free Software
541+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
542+//  USA.
543+//
544+
545+//
546+// VNCProxyConnectSocketFactory.java together with VNCProxyConnectSocket.java
547+// implement an alternate way to connect to VNC servers via one or two
548+// VNCProxy proxies supporting the VNCProxy CONNECT method.
549+//
550+
551+import java.applet.*;
552+import java.net.*;
553+import javax.net.ssl.*;
554+import java.io.*;
555+
556+class VNCProxyConnectSocketFactory implements SocketFactory {
557+
558+    SSLSocketFactory factory;
559+   
560+    public VNCProxyConnectSocketFactory() {
561+       try {
562+           SSLContext c = SSLContext.getInstance("SSL");
563+           c.init(null,
564+                  new TrustManager[] { new InvirtTrustManager() },
565+                  null);
566+           factory =
567+               (SSLSocketFactory)c.getSocketFactory();
568+       } catch (Exception e) {
569+           e.printStackTrace();
570+       }
571+    }
572+
573+  public Socket createSocket(String host, int port, Applet applet)
574+    throws IOException {
575+
576+    return createSocket(host, port,
577+                       applet.getParameter("VMNAME"),
578+                       applet.getParameter("AUTHTOKEN"));
579+  }
580+
581+  public Socket createSocket(String host, int port, String[] args)
582+    throws IOException {
583+
584+    return createSocket(host, port,
585+                       readArg(args, "VMNAME"),
586+                       readArg(args, "AUTHTOKEN"));
587+  }
588+
589+  public Socket createSocket(String host, int port,
590+                            String vmname, String authtoken)
591+    throws IOException {
592+
593+    if (vmname == null || authtoken == null) {
594+      System.out.println("Incomplete parameter list for VNCProxyConnectSocket");
595+      return new Socket(host, port);
596+    }
597+
598+    System.out.println("VNCProxy CONNECT via proxy " + host +
599+                      " port " + port + " to vm " + vmname);
600+    SSLSocket ssls = (SSLSocket)factory.createSocket(host, port);
601+    ssls.startHandshake();
602+    VNCProxyConnectSocketWrapper s =
603+      new VNCProxyConnectSocketWrapper(ssls, vmname, authtoken);
604+
605+    return (Socket)s;
606+  }
607+
608+  private String readArg(String[] args, String name) {
609+
610+    for (int i = 0; i < args.length; i += 2) {
611+      if (args[i].equalsIgnoreCase(name)) {
612+       try {
613+         return args[i+1];
614+       } catch (Exception e) {
615+         return null;
616+       }
617+      }
618+    }
619+    return null;
620+  }
621+}
622+
623Index: invirt-vnc-client/VNCProxyConnectSocketWrapper.java
624===================================================================
625--- /dev/null   1970-01-01 00:00:00.000000000 +0000
626+++ invirt-vnc-client/VNCProxyConnectSocketWrapper.java 2008-10-31 06:09:10.000000000 -0400
627@@ -0,0 +1,60 @@
628+//
629+//  Copyright (C) 2002 Constantin Kaplinsky, Inc.  All Rights Reserved.
630+//  Copyright 2007 MIT Student Information Processing Board
631+//
632+//  This is free software; you can redistribute it and/or modify
633+//  it under the terms of the GNU General Public License as published by
634+//  the Free Software Foundation; either version 2 of the License, or
635+//  (at your option) any later version.
636+//
637+//  This software is distributed in the hope that it will be useful,
638+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
639+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
640+//  GNU General Public License for more details.
641+//
642+//  You should have received a copy of the GNU General Public License
643+//  along with this software; if not, write to the Free Software
644+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
645+//  USA.
646+//
647+
648+//
649+// VNCProxySocket.java together with VNCProxySocketFactory.java
650+// implement an alternate way to connect to VNC servers via one or two
651+// VNCProxy proxies supporting the VNCProxy VNCCONNECT method.
652+//
653+
654+import java.net.*;
655+import java.io.*;
656+
657+class VNCProxyConnectSocketWrapper extends SocketWrapper {
658+
659+  public VNCProxyConnectSocketWrapper(Socket sock,
660+                               String vmname, String authtoken)
661+    throws IOException {
662+
663+    super(sock);
664+
665+    // Send the CONNECT request
666+    getOutputStream().write(("CONNECTVNC " + vmname +
667+                             " VNCProxy/1.0\r\nAuth-token: " + authtoken +
668+                             "\r\n\r\n").getBytes());
669+
670+    // Read the first line of the response
671+    DataInputStream is = new DataInputStream(getInputStream());
672+    String str = is.readLine();
673+
674+    // Check the HTTP error code -- it should be "200" on success
675+    if (!str.startsWith("VNCProxy/1.0 200 ")) {
676+      if (str.startsWith("VNCProxy/1.0 "))
677+        str = str.substring(13);
678+      throw new IOException("Proxy reports \"" + str + "\"");
679+    }
680+
681+    // Success -- skip remaining HTTP headers
682+    do {
683+      str = is.readLine();
684+    } while (str.length() != 0);
685+  }
686+}
687+
Note: See TracBrowser for help on using the repository browser.