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

Last change on this file since 1470 was 1438, checked in by broder, 16 years ago

Isolate our patches to the VNC client from the upstream TightVNC
source

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