file(GLOB DEPEND_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/com/tigervnc/rfb/*.java
${CMAKE_CURRENT_SOURCE_DIR}/com/tigervnc/rdr/*.java
+ ${CMAKE_CURRENT_SOURCE_DIR}/com/tigervnc/network/*.java
${CMAKE_CURRENT_SOURCE_DIR}/com/jcraft/jzlib/*.java)
string(REGEX REPLACE " " ";" JAVACFLAGS "${JAVACFLAGS}")
com/tigervnc/vncviewer/*.class
com/tigervnc/rfb/*.class
com/tigervnc/rdr/*.class
+ com/tigervnc/network/*.class
com/jcraft/jzlib/*.class
com/tigervnc/vncviewer/tigervnc.png
com/tigervnc/vncviewer/tigervnc.ico
--- /dev/null
+/*
+ * Copyright (C) 2012 TigerVNC Team.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+package com.tigervnc.network;
+
+import java.lang.Exception;
+import java.io.IOException;
+
+public interface FileDescriptor {
+
+ public int read(byte[] buf, int bufPtr, int length) throws java.lang.Exception;
+ public int write(byte[] buf, int bufPtr, int length) throws java.lang.Exception;
+ public int select(int interestOps, int timeout) throws java.lang.Exception;
+ public void close() throws IOException;
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (C) 2008 Trustin Heuiseung Lee
+ * Copyright (C) 2012 TigerVNC Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
+ */
+ package com.tigervnc.network;
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.*;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import com.tigervnc.rdr.FdInStream;
+import com.tigervnc.rdr.FdOutStream;
+
+public class SSLEngineManager {
+
+ private SSLEngine engine = null;
+
+ private int applicationBufferSize;
+ private int packetBufferSize;
+
+ private ByteBuffer myAppData;
+ private ByteBuffer myNetData;
+ private ByteBuffer peerAppData;
+ private ByteBuffer peerNetData;
+
+
+ private Executor executor;
+ private FdInStream inStream;
+ private FdOutStream outStream;
+
+ public SSLEngineManager(SSLEngine sslEngine, FdInStream is,
+ FdOutStream os) throws IOException {
+
+ inStream = is;
+ outStream = os;
+ engine = sslEngine;
+
+ executor = Executors.newSingleThreadExecutor();
+
+ packetBufferSize = engine.getSession().getPacketBufferSize();
+ applicationBufferSize = engine.getSession().getApplicationBufferSize();
+
+ myAppData = ByteBuffer.allocate(applicationBufferSize);
+ myNetData = ByteBuffer.allocate(packetBufferSize);
+ peerAppData = ByteBuffer.allocate(applicationBufferSize);
+ peerNetData = ByteBuffer.allocate(packetBufferSize);
+ }
+
+ public void doHandshake() throws Exception {
+
+ // Begin handshake
+ engine.beginHandshake();
+ SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
+
+ // Process handshaking message
+ while (hs != SSLEngineResult.HandshakeStatus.FINISHED &&
+ hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
+
+ switch (hs) {
+
+ case NEED_UNWRAP:
+ // Receive handshaking data from peer
+ pull(peerNetData);
+ //if (pull(peerNetData) < 0) {
+ // Handle closed channel
+ //}
+
+ // Process incoming handshaking data
+ peerNetData.flip();
+ SSLEngineResult res = engine.unwrap(peerNetData, peerAppData);
+ peerNetData.compact();
+ hs = res.getHandshakeStatus();
+
+ // Check status
+ switch (res.getStatus()) {
+ case OK :
+ // Handle OK status
+ break;
+
+ // Handle other status: BUFFER_UNDERFLOW, BUFFER_OVERFLOW, CLOSED
+ //...
+ }
+ break;
+
+ case NEED_WRAP :
+ // Empty the local network packet buffer.
+ myNetData.clear();
+
+ // Generate handshaking data
+ res = engine.wrap(myAppData, myNetData);
+ hs = res.getHandshakeStatus();
+
+ // Check status
+ switch (res.getStatus()) {
+ case OK :
+ //myNetData.flip();
+
+ push(myNetData);
+ // Send the handshaking data to peer
+ //while (myNetData.hasRemaining()) {
+ // if (push(myNetData) < 0) {
+ // // Handle closed channel
+ // }
+ //}
+ break;
+
+ // Handle other status: BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED
+ //...
+ }
+ break;
+
+ case NEED_TASK :
+ // Handle blocking tasks
+ executeTasks();
+ break;
+
+ // Handle other status: // FINISHED or NOT_HANDSHAKING
+ //...
+ }
+ hs = engine.getHandshakeStatus();
+ }
+
+ // Processes after handshaking
+ //...
+}
+
+ private void executeTasks() {
+ Runnable task;
+ while ((task = engine.getDelegatedTask()) != null) {
+ executor.execute(task);
+ }
+ }
+
+ public int read(byte[] data, int dataPtr, int length) throws IOException {
+ // Read SSL/TLS encoded data from peer
+ int bytesRead = 0;
+ SSLEngineResult res;
+ do {
+ // Process incoming data
+ int packetLength = pull(peerNetData);
+ peerNetData.flip();
+ res = engine.unwrap(peerNetData, peerAppData);
+ peerNetData.compact();
+ bytesRead += packetLength;
+ } while (res.getStatus() != SSLEngineResult.Status.OK);
+ peerAppData.flip();
+ int n = Math.min(peerAppData.remaining(), length);
+ peerAppData.get(data, dataPtr, n);
+ peerAppData.compact();
+ return n;
+ }
+
+ public int write(byte[] data, int dataPtr, int length) throws IOException {
+ int n = 0;
+//while (myAppData.hasRemaining()) {
+ // Generate SSL/TLS encoded data (handshake or application data)
+ // FIXME:
+ // Need to make sure myAppData has space for data!
+ myAppData.put(data, dataPtr, length);
+ myAppData.flip();
+ SSLEngineResult res = engine.wrap(myAppData, myNetData);
+ myAppData.compact();
+
+ // Process status of call
+ //if (res.getStatus() == SSLEngineResult.Status.OK) {
+ //myAppData.compact();
+
+ // Send SSL/TLS encoded data to peer
+ //while(myNetData.hasRemaining()) {
+ int num = push(myNetData);
+ if (num == -1) {
+ // handle closed channel
+ } else if (num == 0) {
+ // no bytes written; try again later
+ }
+ //n += num;
+ //}
+ //}
+
+ // Handle other status: BUFFER_OVERFLOW, CLOSED
+ //...
+ //}
+ return num;
+ }
+
+ private int push(ByteBuffer src) throws IOException {
+ src.flip();
+ int n = src.remaining();
+ byte[] b = new byte[n];
+ src.get(b);
+ src.clear();
+ outStream.writeBytes(b, 0, n);
+ outStream.flush();
+ return n;
+ }
+
+ private int pull(ByteBuffer dst) throws IOException {
+ int packetLength = 0;
+ inStream.checkNoWait(5);
+ //if (!inStream.checkNoWait(5)) {
+ // return 0;
+ //}
+
+ byte[] header = new byte[5];
+ inStream.readBytes(header, 0, 5);
+
+ boolean tls;
+ int h = header[0] & 0xFF;
+ switch (header[0] & 0xFF) {
+ case 20: // change_cipher_spec
+ case 21: // alert
+ case 22: // handshake
+ case 23: // application_data
+ tls = true;
+ break;
+ default:
+ // SSLv2 bad data
+ tls = false;
+ }
+
+ if (tls) {
+ int majorVersion = (int)(header[1] & 0xFF);
+ if (majorVersion >= 3 && majorVersion < 10) {
+ // SSLv3 or TLS
+ packetLength = (int)(((header[3] << 8) | (header[4] & 0xFF)) & 0xFFFF) + 5;
+ if (packetLength <= 5) {
+ // Neither SSLv2 or TLSv1
+ tls = false;
+ }
+ } else {
+ // Neither SSLv2 or TLSv1
+ tls = false;
+ }
+ }
+
+ if (!tls) {
+ boolean sslv2 = true;
+ int headerLength = (int)((header[0] & 0xFF) & 0x80) != 0 ? 2 : 3;
+ int majorVersion = (int)(header[headerLength + 1] & 0xFF);
+ if (majorVersion >= 2 && majorVersion < 10) {
+ // SSLv2
+ if (headerLength == 2) {
+ packetLength = (int)(((header[0] << 8) | (header[1] & 0xFF)) & 0x7FFF) + 2;
+ } else {
+ packetLength = (int)(((header[0] << 8) | (header[1] & 0xFF)) & 0x3FFF) + 3;
+ }
+ if (packetLength <= headerLength) {
+ sslv2 = false;
+ }
+ } else {
+ sslv2 = false;
+ }
+
+ if (!sslv2) {
+ throw new IOException("not an SSL/TLS record");
+ }
+ }
+
+ assert packetLength > 0;
+
+ byte[] buf = new byte[packetLength - 5];
+ inStream.readBytes(buf, 0, packetLength - 5);
+ dst.put(header);
+ dst.put(buf);
+ return packetLength;
+ }
+
+ public SSLSession getSession() {
+ return engine.getSession();
+ }
+
+}
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2012 TigerVNC Team
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+// -=- Socket - abstract base-class for any kind of network stream/socket
+
+package com.tigervnc.network;
+
+import com.tigervnc.rdr.*;
+import java.nio.channels.*;
+import java.nio.channels.spi.SelectorProvider;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+abstract public class Socket {
+
+ public Socket(FileDescriptor fd) {
+ instream = new FdInStream(fd);
+ outstream = new FdOutStream(fd);
+ ownStreams = true; isShutdown_ = false;
+ queryConnection = false;
+ }
+
+ public FdInStream inStream() {return instream;}
+ public FdOutStream outStream() {return outstream;}
+ public FileDescriptor getFd() {return outstream.getFd();}
+
+ // if shutdown() is overridden then the override MUST call on to here
+ public void shutdown() {isShutdown_ = true;}
+ public void close() throws IOException {getFd().close();}
+ public final boolean isShutdown() {return isShutdown_;}
+
+ // information about this end of the socket
+ abstract public int getMyPort();
+
+ // information about the remote end of the socket
+ abstract public String getPeerAddress(); // a string e.g. "192.168.0.1"
+ abstract public int getPeerPort();
+ abstract public String getPeerEndpoint(); // <address>::<port>
+
+ // Is the remote end on the same machine?
+ abstract public boolean sameMachine();
+
+ // Was there a "?" in the ConnectionFilter used to accept this Socket?
+ public void setRequiresQuery() {queryConnection = true;}
+ public final boolean requiresQuery() {return queryConnection;}
+
+ protected Socket() {
+ instream = null; outstream = null; ownStreams = false;
+ isShutdown_ = false; queryConnection = false;
+ }
+
+ protected Socket(FdInStream i, FdOutStream o, boolean own) {
+ instream = i; outstream = o; ownStreams = own;
+ isShutdown_ = false; queryConnection = false;
+ }
+
+ protected FdInStream instream;
+ protected FdOutStream outstream;
+ boolean ownStreams;
+ boolean isShutdown_;
+ boolean queryConnection;
+}
+
+/*
+abstract class ConnectionFilter {
+ public abstract boolean verifyConnection(Socket s);
+};
+
+abstract class SocketListener {
+ public SocketListener() {
+ fd = null; filter = null;
+ }
+
+ // shutdown() stops the socket from accepting further connections
+ public abstract void shutdown();
+
+ // accept() returns a new Socket object if there is a connection
+ // attempt in progress AND if the connection passes the filter
+ // if one is installed. Otherwise, returns 0.
+ public abstract Socket accept();
+
+ // setFilter() applies the specified filter to all new connections
+ public void setFilter(ConnectionFilter f) {filter = f;}
+ //public SocketDescriptor getFd() {return fd;}
+ protected FileDescriptor fd;
+ protected ConnectionFilter filter;
+};
+*/
+
+//struct SocketException : public rdr::SystemException {
+// SocketException(const char* text, int err_) : rdr::SystemException(text, err_) {}
+//};
--- /dev/null
+/*
+ * Copyright (C) 2012 TigerVNC Team
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+package com.tigervnc.network;
+
+import java.io.IOException;
+import java.lang.Exception;
+
+import java.net.SocketAddress;
+import java.nio.*;
+import java.nio.channels.*;
+import java.nio.channels.spi.SelectorProvider;
+
+import java.util.Set;
+import java.util.Iterator;
+
+public class SocketDescriptor extends SocketChannel
+ implements FileDescriptor {
+
+ public SocketDescriptor() throws Exception {
+ super(SelectorProvider.provider());
+ try {
+ channel = SocketChannel.open();
+ channel.configureBlocking(false);
+ selector = Selector.open();
+ } catch (java.io.IOException e) {
+ throw new Exception(e.toString());
+ }
+ try {
+ channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE );
+ } catch (java.nio.channels.ClosedChannelException e) {
+ throw new Exception(e.toString());
+ }
+ }
+
+ public int read(byte[] buf, int bufPtr, int length) throws Exception {
+ int n;
+ ByteBuffer b = ByteBuffer.allocate(length);
+ try {
+ n = channel.read(b);
+ } catch (java.io.IOException e) {
+ System.out.println(e.toString());
+ throw new Exception(e.toString());
+ }
+ //if (n == 0)
+ // throw new Exception;
+ b.flip();
+ b.get(buf, bufPtr, n);
+ b.clear();
+ return n;
+
+ }
+
+ public int write(byte[] buf, int bufPtr, int length) throws Exception {
+ int n;
+ ByteBuffer b = ByteBuffer.allocate(length);
+ b.put(buf, bufPtr, length);
+ b.flip();
+ try {
+ n = channel.write(b);
+ } catch (java.io.IOException e) {
+ System.out.println(e.toString());
+ throw new Exception(e.toString());
+ }
+ b.clear();
+ return n;
+ }
+
+ public int select(int interestOps, int timeout) throws Exception {
+ int n;
+ try {
+ n = selector.select(timeout);
+ } catch (Exception e) {
+ System.out.println(e.toString());
+ throw new Exception(e.toString());
+ }
+ Set keys = selector.selectedKeys();
+ Iterator iter = keys.iterator();
+ while (iter.hasNext()) {
+ SelectionKey key = (SelectionKey)iter.next();
+ if ((key.readyOps() & interestOps) != 0) {
+ n = 1;
+ break;
+ } else {
+ n = -1;
+ }
+ }
+ keys.clear();
+ return n;
+ }
+
+ public int write(ByteBuffer buf) throws IOException {
+ int n = 0;
+ try {
+ n = channel.write(buf);
+ } catch (java.io.IOException e) {
+ System.out.println(e.toString());
+ throw e;
+ }
+ return n;
+ }
+
+ public long write(ByteBuffer[] buf, int offset, int length)
+ throws IOException
+ {
+ long n = 0;
+ try {
+ n = channel.write(buf, offset, length);
+ } catch (java.io.IOException e) {
+ System.out.println(e.toString());
+ }
+ return n;
+ }
+
+ public int read(ByteBuffer buf) throws IOException {
+ int n = 0;
+ try {
+ n = channel.read(buf);
+ } catch (java.io.IOException e) {
+ System.out.println(e.toString());
+ throw e;
+ }
+ return n;
+ }
+
+ public long read(ByteBuffer[] buf, int offset, int length)
+ throws IOException
+ {
+ long n = 0;
+ try {
+ n = channel.read(buf, offset, length);
+ } catch (java.io.IOException e) {
+ System.out.println(e.toString());
+ }
+ return n;
+ }
+
+ public java.net.Socket socket() {
+ return channel.socket();
+ }
+
+ public boolean isConnectionPending() {
+ return channel.isConnectionPending();
+ }
+
+ public boolean connect(SocketAddress remote) throws IOException {
+ return channel.connect(remote);
+ }
+
+ public boolean finishConnect() throws IOException {
+ return channel.finishConnect();
+ }
+
+ public boolean isConnected() {
+ return channel.isConnected();
+ }
+
+ protected void implConfigureBlocking(boolean block) throws IOException {
+ channel.configureBlocking(block);
+ }
+
+ protected synchronized void implCloseSelectableChannel() throws IOException {
+ channel.close();
+ notifyAll();
+ }
+
+ protected void setChannel(SocketChannel channel_) {
+ try {
+ if (channel != null)
+ channel.close();
+ if (selector != null)
+ selector.close();
+ channel = channel_;
+ channel.configureBlocking(false);
+ selector = Selector.open();
+ } catch (java.io.IOException e) {
+ System.out.println(e.toString());
+ }
+ try {
+ channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE );
+ } catch (java.nio.channels.ClosedChannelException e) {
+ System.out.println(e.toString());
+ }
+ }
+
+ protected SocketChannel channel;
+ protected Selector selector;
+
+}
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2012 Brian P Hinz. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+// -=- SocketListener - abstract base-class for any kind of network stream/socket
+
+package com.tigervnc.network;
+
+import java.nio.channels.*;
+import java.nio.channels.spi.SelectorProvider;
+
+abstract public class SocketListener {
+
+ public SocketListener() {}
+
+ // shutdown() stops the socket from accepting further connections
+ abstract public void shutdown();
+
+ // accept() returns a new Socket object if there is a connection
+ // attempt in progress AND if the connection passes the filter
+ // if one is installed. Otherwise, returns 0.
+ abstract public Socket accept();
+
+ // setFilter() applies the specified filter to all new connections
+ //public void setFilter(ConnectionFilter* f) {filter = f;}
+ public FileDescriptor getFd() {return fd;}
+
+ protected FileDescriptor fd;
+ //protected ConnectionFilter* filter;
+
+}
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2012 TigerVNC Team
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.network;
+
+import java.io.IOException;
+import java.lang.Exception;
+import java.nio.*;
+import java.nio.channels.*;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import java.util.Set;
+import java.util.Iterator;
+
+public class TcpListener extends SocketListener {
+
+ public static boolean socketsInitialised = false;
+
+ public TcpListener(String listenaddr, int port, boolean localhostOnly,
+ SocketDescriptor sock, boolean close_) throws Exception {
+ closeFd = close_;
+ if (sock != null) {
+ fd = sock;
+ return;
+ }
+
+ TcpSocket.initSockets();
+ try {
+ channel = ServerSocketChannel.open();
+ channel.configureBlocking(false);
+ } catch(IOException e) {
+ throw new Exception("unable to create listening socket: "+e.toString());
+ }
+
+ // - Bind it to the desired port
+ InetAddress addr = null;
+
+ try {
+ if (localhostOnly) {
+ addr = InetAddress.getByName(null);
+ } else if (listenaddr != null) {
+ addr = java.net.InetAddress.getByName(listenaddr);
+ } else {
+ // FIXME: need to be sure we get the wildcard address?
+ addr = InetAddress.getByName(null);
+ //addr = InetAddress.getLocalHost();
+ }
+ } catch (UnknownHostException e) {
+ System.out.println(e.toString());
+ System.exit(-1);
+ }
+
+ try {
+ channel.socket().bind(new InetSocketAddress(addr, port));
+ } catch (IOException e) {
+ throw new Exception("unable to bind listening socket: "+e.toString());
+ }
+
+ // - Set it to be a listening socket
+ try {
+ selector = Selector.open();
+ channel.register(selector, SelectionKey.OP_ACCEPT);
+ } catch (IOException e) {
+ throw new Exception("unable to set socket to listening mode: "+e.toString());
+ }
+ }
+
+ public TcpListener(String listenaddr, int port) throws Exception {
+ this(listenaddr, port, false, null, true);
+ }
+
+// TcpListener::~TcpListener() {
+// if (closeFd) closesocket(fd);
+// }
+
+ public void shutdown() {
+ //shutdown(getFd(), 2);
+ }
+
+ public TcpSocket accept() {
+ SocketChannel new_sock = null;
+
+ // Accept an incoming connection
+ try {
+ if (selector.select() > 0) {
+ Set keys = selector.selectedKeys();
+ Iterator iter = keys.iterator();
+ while (iter.hasNext()) {
+ SelectionKey key = (SelectionKey)iter.next();
+ iter.remove();
+ if (key.isAcceptable()) {
+ new_sock = channel.accept();
+ break;
+ }
+ }
+ keys.clear();
+ if (new_sock == null)
+ return null;
+ }
+ } catch (IOException e) {
+ //throw SocketException("unable to accept new connection", errorNumber);
+ System.out.println(e.toString());
+ }
+
+ // Disable Nagle's algorithm, to reduce latency
+ TcpSocket.enableNagles(new_sock, false);
+
+ // Create the socket object & check connection is allowed
+ SocketDescriptor fd = null;
+ try {
+ fd = new SocketDescriptor();
+ } catch (java.lang.Exception e) {
+ System.out.println(e.toString());
+ System.exit(-1);
+ }
+ fd.setChannel(new_sock);
+ TcpSocket s = new TcpSocket(fd);
+ //if (filter && !filter->verifyConnection(s)) {
+ // delete s;
+ // return 0;
+ //}
+ return s;
+ }
+
+/*
+void TcpListener::getMyAddresses(std::list<char*>* result) {
+ const hostent* addrs = gethostbyname(0);
+ if (addrs == 0)
+ throw rdr::SystemException("gethostbyname", errorNumber);
+ if (addrs->h_addrtype != AF_INET)
+ throw rdr::Exception("getMyAddresses: bad family");
+ for (int i=0; addrs->h_addr_list[i] != 0; i++) {
+ const char* addrC = inet_ntoa(*((struct in_addr*)addrs->h_addr_list[i]));
+ char* addr = new char[strlen(addrC)+1];
+ strcpy(addr, addrC);
+ result->push_back(addr);
+ }
+}
+ */
+
+ //public int getMyPort() {
+ // return TcpSocket.getSockPort();
+ //}
+
+ private boolean closeFd;
+ private ServerSocketChannel channel;
+ private Selector selector;
+
+}
+
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2012 TigerVNC Team
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.network;
+
+import com.tigervnc.rdr.FdInStream;
+import com.tigervnc.rdr.FdOutStream;
+import com.tigervnc.rfb.LogWriter;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.nio.*;
+import java.nio.channels.*;
+
+public class TcpSocket extends Socket {
+
+ // -=- Socket initialisation
+ public static boolean socketsInitialised = false;
+ public static void initSockets() {
+ if (socketsInitialised)
+ return;
+ socketsInitialised = true;
+ }
+
+ // -=- TcpSocket
+
+ public TcpSocket(SocketDescriptor sock, boolean close) {
+ super(new FdInStream(sock), new FdOutStream(sock), true);
+ //this.sock = sock;
+ closeFd = close;
+ }
+
+ public TcpSocket(SocketDescriptor sock) {
+ this(sock, true);
+ }
+
+ public TcpSocket(String host, int port) throws Exception {
+ closeFd = true;
+ SocketDescriptor sock = null;
+ InetAddress addr = null;
+ boolean result = false;
+
+ // - Create a socket
+ initSockets();
+
+ try {
+ addr = java.net.InetAddress.getByName(host);
+ } catch(UnknownHostException e) {
+ throw new Exception("unable to resolve host by name: "+e.toString());
+ }
+
+ try {
+ sock = new SocketDescriptor();
+ } catch(UnknownHostException e) {
+ throw new Exception("unable to create socket: "+e.toString());
+ }
+
+ /* Attempt to connect to the remote host */
+ try {
+ result = sock.connect(new InetSocketAddress(addr, port));
+ } catch(java.io.IOException e) {
+ //throw new java.lang.Exception(e.getMessage());
+ System.out.println("connect failed: "+e.getMessage());
+ }
+
+ if (!result && sock.isConnectionPending()) {
+ while (!result) {
+ try {
+ result = sock.finishConnect();
+ } catch(java.nio.channels.ClosedChannelException e) {
+ throw new Exception(e.getMessage());
+ }
+ }
+ }
+
+ if (!result)
+ throw new Exception("unable connect to socket");
+
+ // Disable Nagle's algorithm, to reduce latency
+ enableNagles(sock, false);
+
+ // Create the input and output streams
+ instream = new FdInStream(sock);
+ outstream = new FdOutStream(sock);
+ ownStreams = true;
+ }
+
+ protected void finalize() throws Exception {
+ if (closeFd)
+ try {
+ ((SocketDescriptor)getFd()).close();
+ } catch (IOException e) {
+ throw new Exception(e.toString());
+ }
+ }
+
+ public int getMyPort() {
+ SocketAddress address = ((SocketDescriptor)getFd()).socket().getLocalSocketAddress();
+ return ((InetSocketAddress)address).getPort();
+ }
+
+ public String getPeerAddress() {
+ SocketAddress peer = ((SocketDescriptor)getFd()).socket().getRemoteSocketAddress();
+ if (peer != null)
+ return peer.toString();
+ return "";
+ }
+
+ public int getPeerPort() {
+ SocketAddress address = ((SocketDescriptor)getFd()).socket().getRemoteSocketAddress();
+ return ((InetSocketAddress)address).getPort();
+ }
+
+ public String getPeerEndpoint() {
+ String address = getPeerAddress();
+ int port = getPeerPort();
+ return address+"::"+port;
+ }
+
+ public boolean sameMachine() {
+ SocketAddress peeraddr = ((SocketDescriptor)getFd()).socket().getRemoteSocketAddress();
+ SocketAddress myaddr = ((SocketDescriptor)getFd()).socket().getLocalSocketAddress();
+ return myaddr.equals(peeraddr);
+ }
+
+ public void shutdown() {
+ super.shutdown();
+ }
+
+ public void close() throws IOException {
+ ((SocketDescriptor)getFd()).close();
+ }
+
+ public static boolean enableNagles(SocketChannel sock, boolean enable) {
+ try {
+ sock.socket().setTcpNoDelay(!enable);
+ } catch(SocketException e) {
+ vlog.error(e.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean isSocket(java.net.Socket sock) {
+ return sock.getClass().toString().equals("com.tigervnc.net.Socket");
+ }
+
+ public boolean isConnected() {
+ return ((SocketDescriptor)getFd()).isConnected();
+ }
+
+ public int getSockPort() {
+ return ((InetSocketAddress)((SocketDescriptor)getFd()).socket().getRemoteSocketAddress()).getPort();
+ }
+
+ private boolean closeFd;
+ static LogWriter vlog = new LogWriter("TcpSocket");
+
+}
+
+/* Tunnelling support. */
+/*
+public int findFreeTcpPort() {
+ int sock;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ throw SocketException("unable to create socket", errorNumber);
+
+ int port = 0;
+ if (bind (sock, (struct sockaddr *)&addr, sizeof (addr)) < 0)
+ throw SocketException("unable to find free port", errorNumber);
+
+ socklen_t n = sizeof(addr);
+ if (getsockname (sock, (struct sockaddr *)&addr, &n) < 0)
+ throw SocketException("unable to get port number", errorNumber);
+
+ closesocket(sock);
+ return ntohs(addr.sin_port);
+}
+*/
+
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2012 TigerVNC Team
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.rdr;
+
+import com.tigervnc.network.*;
+import java.nio.channels.Selector;
+import java.nio.channels.SelectionKey;
+import java.util.Set;
+import java.util.Iterator;
+
+public class FdInStream extends InStream {
+
+ static final int defaultBufSize = 8192;
+ static final int minBulkSize = 1024;
+
+ public FdInStream(FileDescriptor fd_, int bufSize_) {
+ fd = fd_;
+ bufSize = bufSize_;
+ b = new byte[bufSize];
+ ptr = end = offset = 0;
+ timeoutms = 0;
+ timing = false;
+ timeWaitedIn100us = 5;
+ timedKbits = 0;
+ }
+
+ public FdInStream(FileDescriptor fd_) { this(fd_, defaultBufSize); }
+
+ public final void readBytes(byte[] data, int dataPtr, int length) {
+ if (length < minBulkSize) {
+ super.readBytes(data, dataPtr, length);
+ return;
+ }
+
+ int n = end - ptr;
+ if (n > length) n = length;
+
+ System.arraycopy(b, ptr, data, dataPtr, n);
+ dataPtr += n;
+ length -= n;
+ ptr += n;
+
+ while (length > 0) {
+ n = readWithTimeoutOrCallback(data, dataPtr, length);
+ dataPtr += n;
+ length -= n;
+ offset += n;
+ }
+ }
+
+ public void setTimeout(int timeoutms_) {
+ timeoutms = timeoutms_;
+ }
+
+ public void setBlockCallback(FdInStreamBlockCallback blockCallback_)
+ {
+ blockCallback = blockCallback_;
+ timeoutms = 0;
+ }
+
+ public final int pos() { return offset + ptr; }
+
+ public final void startTiming() {
+ timing = true;
+
+ // Carry over up to 1s worth of previous rate for smoothing.
+
+ if (timeWaitedIn100us > 10000) {
+ timedKbits = timedKbits * 10000 / timeWaitedIn100us;
+ timeWaitedIn100us = 10000;
+ }
+ }
+
+ public final void stopTiming() {
+ timing = false;
+ if (timeWaitedIn100us < timedKbits/2)
+ timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
+ }
+
+ public final long kbitsPerSecond() {
+ return timedKbits * 10000 / timeWaitedIn100us;
+ }
+
+ public final long timeWaited() { return timeWaitedIn100us; }
+
+ protected int overrun(int itemSize, int nItems, boolean wait) {
+ if (itemSize > bufSize)
+ throw new Exception("FdInStream overrun: max itemSize exceeded");
+
+ if (end - ptr != 0)
+ System.arraycopy(b, ptr, b, 0, end - ptr);
+
+ offset += ptr;
+ end -= ptr;
+ ptr = 0;
+
+ int bytes_to_read;
+ while (end < itemSize) {
+ bytes_to_read = bufSize - end;
+ if (!timing) {
+ // When not timing, we must be careful not to read too much
+ // extra data into the buffer. Otherwise, the line speed
+ // estimation might stay at zero for a long time: All reads
+ // during timing=1 can be satisfied without calling
+ // readWithTimeoutOrCallback. However, reading only 1 or 2 bytes
+ // bytes is ineffecient.
+ bytes_to_read = Math.min(bytes_to_read, Math.max(itemSize*nItems, 8));
+ }
+ int n = readWithTimeoutOrCallback(b, end, bytes_to_read, wait);
+ if (n == 0) return 0;
+ end += n;
+ }
+
+ if (itemSize * nItems > end - ptr)
+ nItems = (end - ptr) / itemSize;
+
+ return nItems;
+ }
+
+ protected int readWithTimeoutOrCallback(byte[] buf, int bufPtr, int len, boolean wait) {
+ long before = 0;
+ long timeout;
+ if (timing)
+ before = System.nanoTime();
+
+ int n;
+ while (true) {
+
+ if (!wait) {
+ timeout = 0;
+ } else if (timeoutms != -1) {
+ timeout = (long)timeoutms;
+ } else {
+ timeout = 0;
+ }
+
+ try {
+ n = fd.select(SelectionKey.OP_READ, timeoutms);
+ } catch (java.lang.Exception e) {
+ System.out.println(e.toString());
+ throw new Exception(e.toString());
+ }
+
+
+ if (n > 0) break;
+ if (!wait) return 0;
+ //if (blockCallback == null) throw TimedOut();
+
+ blockCallback.blockCallback();
+ }
+
+ try {
+ n = fd.read(buf, bufPtr, len);
+ } catch (java.lang.Exception e) {
+ System.out.println("read:"+e.toString());
+ throw new Exception(e.toString());
+ }
+
+ if (n == 0) throw new EndOfStream();
+
+ if (timing) {
+ long after = System.nanoTime();
+ long newTimeWaited = (after - before) / 100000;
+ int newKbits = n * 8 / 1000;
+
+ // limit rate to between 10kbit/s and 40Mbit/s
+
+ if (newTimeWaited > newKbits*1000) {
+ newTimeWaited = newKbits*1000;
+ } else if (newTimeWaited < newKbits/4) {
+ newTimeWaited = newKbits/4;
+ }
+
+ timeWaitedIn100us += newTimeWaited;
+ timedKbits += newKbits;
+ }
+
+ return n;
+ }
+
+ private int readWithTimeoutOrCallback(byte[] buf, int bufPtr, int len) {
+ return readWithTimeoutOrCallback(buf, bufPtr, len, true);
+ }
+
+ public FileDescriptor getFd() {
+ return fd;
+ }
+
+ public void setFd(FileDescriptor fd_) {
+ fd = fd_;
+ }
+
+ private int offset;
+ private int bufSize;
+ private FileDescriptor fd;
+ private FdInStreamBlockCallback blockCallback;
+ protected int timeoutms;
+
+ protected boolean timing;
+ protected long timeWaitedIn100us;
+ protected long timedKbits;
+}
--- /dev/null
+/* Copyright (C) 2010-2012 TigerVNC Team
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.rdr;
+
+public interface FdInStreamBlockCallback {
+ abstract public void blockCallback();
+}
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2012 TigerVnc Team
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.rdr;
+
+import com.tigervnc.network.*;
+import java.nio.channels.SelectionKey;
+
+public class FdOutStream extends OutStream {
+
+ static final int defaultBufSize = 8192;
+ static final int minBulkSize = 1024;
+
+ public FdOutStream(FileDescriptor fd_, boolean blocking_, int timeoutms_, int bufSize_)
+ {
+ fd = fd_;
+ blocking = blocking_;
+ timeoutms = timeoutms_;
+ bufSize = bufSize_;
+ b = new byte[bufSize];
+ offset = 0;
+ ptr = sentUpTo = start = 0;
+ end = start + bufSize;
+ }
+
+ public FdOutStream(FileDescriptor fd_) { this(fd_, false, 0, defaultBufSize); }
+
+ public void setTimeout(int timeoutms_) {
+ timeoutms = timeoutms_;
+ }
+
+ public void setBlocking(boolean blocking_) {
+ blocking = blocking_;
+ }
+
+ public int length()
+ {
+ return offset + ptr - sentUpTo;
+ }
+
+ public void flush()
+ {
+ int timeoutms_;
+
+ if (blocking)
+ timeoutms_ = timeoutms;
+ else
+ timeoutms_ = 0;
+
+ while (sentUpTo < ptr) {
+ int n = writeWithTimeout(b, sentUpTo, ptr - sentUpTo, timeoutms_);
+
+ // Timeout?
+ if (n == 0) {
+ // If non-blocking then we're done here
+ if (!blocking)
+ break;
+
+ // Otherwise try blocking (with possible timeout)
+ if ((timeoutms_ == 0) && (timeoutms != 0)) {
+ timeoutms_ = timeoutms;
+ break;
+ }
+
+ // Proper timeout
+ //throw TimedOut();
+ }
+
+ sentUpTo += n;
+ offset += n;
+ }
+
+ // Managed to flush everything?
+ if (sentUpTo == ptr)
+ ptr = sentUpTo = start;
+ }
+
+ private int writeWithTimeout(byte[] data, int dataPtr, int length, int timeoutms)
+ {
+ long timeout;
+ int n;
+
+ do {
+
+ if (timeoutms != -1) {
+ timeout = (long)timeoutms;
+ } else {
+ timeout = 0;
+ }
+
+ try {
+ n = fd.select(SelectionKey.OP_WRITE, timeoutms);
+ } catch (java.lang.Exception e) {
+ System.out.println(e.toString());
+ throw new Exception(e.toString());
+ }
+
+ } while (n < 0);
+
+ try {
+ n = fd.write(data, dataPtr, length);
+ } catch (java.lang.Exception e) {
+ System.out.println("read:"+e.toString());
+ throw new Exception(e.toString());
+ }
+
+ return n;
+ }
+
+ protected int overrun(int itemSize, int nItems)
+ {
+ if (itemSize > bufSize)
+ throw new Exception("FdOutStream overrun: max itemSize exceeded");
+
+ // First try to get rid of the data we have
+ flush();
+
+ // Still not enough space?
+ if (itemSize > end - ptr) {
+ // Can we shuffle things around?
+ // (don't do this if it gains us less than 25%)
+ if ((sentUpTo - start > bufSize / 4) &&
+ (itemSize < bufSize - (ptr - sentUpTo))) {
+ System.arraycopy(b, ptr, b, start, ptr - sentUpTo);
+ ptr = start + (ptr - sentUpTo);
+ sentUpTo = start;
+ } else {
+ // Have to get rid of more data, so turn off non-blocking
+ // for a bit...
+ boolean realBlocking;
+
+ realBlocking = blocking;
+ blocking = true;
+ flush();
+ blocking = realBlocking;
+ }
+ }
+
+ // Can we fit all the items asked for?
+ if (itemSize * nItems > end - ptr)
+ nItems = (end - ptr) / itemSize;
+
+ return nItems;
+ }
+
+ public FileDescriptor getFd() {
+ return fd;
+ }
+
+ public void setFd(FileDescriptor fd_) {
+ fd = fd_;
+ }
+
+ protected FileDescriptor fd;
+ protected boolean blocking;
+ protected int timeoutms;
+ protected int start;
+ protected int sentUpTo;
+ protected int offset;
+ protected int bufSize;
+}
package com.tigervnc.rdr;
+import com.tigervnc.network.*;
+
abstract public class InStream {
// check() ensures there is buffer data for at least one item of size
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-//
-// A JavaInStream reads from a java.io.InputStream
-//
-
-package com.tigervnc.rdr;
-
-public class JavaInStream extends InStream {
-
- static final int defaultBufSize = 8192;
- static final int minBulkSize = 1024;
-
- public JavaInStream(java.io.InputStream jis_, int bufSize_) {
- jis = jis_;
- bufSize = bufSize_;
- b = new byte[bufSize];
- ptr = end = offset = 0;
- timing = false;
- timeWaitedIn100us = 5;
- timedKbits = 0;
- }
-
- public JavaInStream(java.io.InputStream jis_) { this(jis_, defaultBufSize); }
-
- public void readBytes(byte[] data, int dataPtr, int length) {
- if (length < minBulkSize) {
- super.readBytes(data, dataPtr, length);
- return;
- }
-
- int n = end - ptr;
- if (n > length) n = length;
-
- System.arraycopy(b, ptr, data, dataPtr, n);
- dataPtr += n;
- length -= n;
- ptr += n;
-
- while (length > 0) {
- n = read(data, dataPtr, length);
- dataPtr += n;
- length -= n;
- offset += n;
- }
- }
-
- public int pos() { return offset + ptr; }
-
- public void startTiming() {
- timing = true;
-
- // Carry over up to 1s worth of previous rate for smoothing.
-
- if (timeWaitedIn100us > 10000) {
- timedKbits = timedKbits * 10000 / timeWaitedIn100us;
- timeWaitedIn100us = 10000;
- }
- }
-
- public void stopTiming() {
- timing = false;
- if (timeWaitedIn100us < timedKbits/2)
- timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
- }
-
- public long kbitsPerSecond() {
- return timedKbits * 10000 / timeWaitedIn100us;
- }
-
- public long timeWaited() { return timeWaitedIn100us; }
-
- protected int overrun(int itemSize, int nItems, boolean wait) {
- if (itemSize > bufSize)
- throw new Exception("JavaInStream overrun: max itemSize exceeded");
-
- if (end - ptr != 0)
- System.arraycopy(b, ptr, b, 0, end - ptr);
-
- offset += ptr;
- end -= ptr;
- ptr = 0;
-
- while (end < itemSize) {
- int bytes_to_read = bufSize - end;
-
- if (!timing) {
- bytes_to_read = Math.min(bytes_to_read, Math.max(itemSize*nItems, 8));
- }
-
- int n = read(b, end, bytes_to_read, wait);
-
- end += n;
- }
-
- if (itemSize * nItems > end)
- nItems = end / itemSize;
-
- return nItems;
- }
-
- private int read(byte[] buf, int bufPtr, int len, boolean wait) {
- long before = 0;
- if (timing)
- before = System.nanoTime();
-
- int n = -1;
- try {
- n = jis.read(buf, bufPtr, len);
- } catch (java.io.IOException e) {
- throw new IOException(e);
- }
-
- if (n < 0) throw new EndOfStream();
- if (n == 0) return 0;
-
- if (timing) {
- long after = System.nanoTime();
- long newTimeWaited = (after - before) / 100000;
- int newKbits = n * 8 / 1000;
-
- // limit rate to between 10kbit/s and 40Mbit/s
-
- if (newTimeWaited > newKbits*1000) {
- newTimeWaited = newKbits*1000;
- } else if (newTimeWaited < newKbits/4) {
- newTimeWaited = newKbits/4;
- }
-
- timeWaitedIn100us += newTimeWaited;
- timedKbits += newKbits;
- }
-
- return n;
-
- }
- private int read(byte[] buf, int bufPtr, int len) { return read(buf, bufPtr, len, true); }
-
- private java.io.InputStream jis;
- private int offset;
- private int bufSize;
-
- boolean timing;
- long timeWaitedIn100us;
- long timedKbits;
-}
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-//
-// A JavaOutStream writes to a java.io.OutputStream
-//
-
-package com.tigervnc.rdr;
-
-public class JavaOutStream extends OutStream {
-
- static final int defaultBufSize = 16384;
- static final int minBulkSize = 1024;
-
- public JavaOutStream(java.io.OutputStream jos_, int bufSize_) {
- jos = jos_;
- bufSize = bufSize_;
- b = new byte[bufSize];
- ptr = offset = start = 0;
- end = start + bufSize;
- }
-
- public JavaOutStream(java.io.OutputStream jos) { this(jos, defaultBufSize); }
-
- public int length()
- {
- return offset + ptr - start;
- }
-
- public void flush()
- {
- int sentUpTo = start;
- while (sentUpTo < ptr) {
- try {
- jos.write(b, sentUpTo, ptr - sentUpTo);
- sentUpTo += ptr - sentUpTo;
- offset += ptr - sentUpTo;
- } catch (java.io.IOException e) {
- throw new IOException(e);
- }
- }
- ptr = start;
- }
-
- protected int overrun(int itemSize, int nItems)
- {
- if (itemSize > bufSize)
- throw new Exception("JavaOutStream overrun: max itemSize exceeded");
-
- flush();
-
- if (itemSize * nItems > end - ptr)
- nItems = (end - ptr) / itemSize;
-
- return nItems;
- }
-
- private java.io.OutputStream jos;
- private int start;
- private int offset;
- private int bufSize;
-}
package com.tigervnc.rdr;
+import com.tigervnc.network.*;
+
abstract public class OutStream {
// check() ensures there is buffer space for at least one item of size
--- /dev/null
+/*
+ * Copyright (C) 2004 Red Hat Inc.
+ * Copyright (C) 2010-2012 TigerVNC Team
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.rdr;
+
+class TLSException extends Exception {
+ public TLSException(String s, int n) {
+ // FIXME: append enumerated n
+ super(s);
+ }
+}
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2005 Martin Koegler
+ * Copyright (C) 2010-2012 TigerVNC Team
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.rdr;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import javax.net.ssl.*;
+
+import com.tigervnc.network.*;
+
+public class TLSInStream extends InStream {
+
+ static final int defaultBufSize = 16384;
+
+ public TLSInStream(InStream _in, SSLEngineManager _manager) {
+ in = (FdInStream)_in;
+ manager = _manager;
+ offset = 0;
+ SSLSession session = manager.getSession();
+ bufSize = session.getApplicationBufferSize();
+ b = new byte[bufSize];
+ ptr = end = start = 0;
+ }
+
+ public final int pos() {
+ return offset + ptr - start;
+ }
+
+ public final void startTiming() {
+ in.startTiming();
+ }
+
+ public final void stopTiming() {
+ in.stopTiming();
+ }
+
+ public final long kbitsPerSecond() {
+ return in.kbitsPerSecond();
+ }
+
+ public final long timeWaited() {
+ return in.timeWaited();
+ }
+
+ protected final int overrun(int itemSize, int nItems, boolean wait) {
+ if (itemSize > bufSize)
+ throw new Exception("TLSInStream overrun: max itemSize exceeded");
+
+ if (end - ptr != 0)
+ System.arraycopy(b, ptr, b, 0, end - ptr);
+
+ offset += ptr - start;
+ end -= ptr - start;
+ ptr = start;
+
+ while (end < start + itemSize) {
+ int n = readTLS(b, end, start + bufSize - end, wait);
+ if (!wait && n == 0)
+ return 0;
+ end += n;
+ }
+
+ if (itemSize * nItems > end - ptr)
+ nItems = (end - ptr) / itemSize;
+
+ return nItems;
+ }
+
+ protected int readTLS(byte[] buf, int bufPtr, int len, boolean wait)
+ {
+ int n = -1;
+
+ //n = in.check(1, 1, wait);
+ //if (n == 0)
+ // return 0;
+
+ try {
+ n = manager.read(buf, bufPtr, len);
+ } catch (java.io.IOException e) {
+ e.printStackTrace();
+ }
+
+ if (n < 0) throw new TLSException("readTLS", n);
+
+ return n;
+ }
+
+ private SSLEngineManager manager;
+ private int offset;
+ private int start;
+ private int bufSize;
+ private FdInStream in;
+}
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2005 Martin Koegler
+ * Copyright (C) 2010-2012 TigerVNC Team
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.rdr;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import javax.net.ssl.*;
+
+import com.tigervnc.network.*;
+
+public class TLSOutStream extends OutStream {
+
+ static final int defaultBufSize = 16384;
+
+ public TLSOutStream(OutStream _out, SSLEngineManager _manager) {
+ manager = _manager;
+ out = (FdOutStream)_out;
+ SSLSession session = manager.getSession();
+ bufSize = session.getApplicationBufferSize();
+ b = new byte[bufSize];
+ ptr = offset = start = 0;
+ end = start + bufSize;
+ }
+
+ public int length()
+ {
+ return offset + ptr - start;
+ }
+
+ public void flush()
+ {
+ int sentUpTo = start;
+ while (sentUpTo < ptr) {
+ int n = writeTLS(b, sentUpTo, ptr - sentUpTo);
+ sentUpTo += n;
+ offset += n;
+ }
+
+ ptr = start;
+ //out.flush();
+ }
+
+ protected int overrun(int itemSize, int nItems)
+ {
+ if (itemSize > bufSize)
+ throw new Exception("TLSOutStream overrun: max itemSize exceeded");
+
+ flush();
+
+ if (itemSize * nItems > end - ptr)
+ nItems = (end - ptr) / itemSize;
+
+ return nItems;
+ }
+
+ protected int writeTLS(byte[] data, int dataPtr, int length)
+ {
+ int n = 0;
+
+ try {
+ n = manager.write(data, dataPtr, length);
+ } catch (java.io.IOException e) {
+ throw new Exception(e.toString());
+ }
+ //if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN)
+ // return 0;
+
+ //if (n < 0)
+ // throw new TLSException("writeTLS", n);
+
+ return n;
+ }
+
+ private SSLEngineManager manager;
+ private FdOutStream out;
+ private int start;
+ private int offset;
+ private int bufSize;
+}
import java.util.*;
+import com.tigervnc.network.*;
import com.tigervnc.rdr.*;
abstract public class CConnection extends CMsgHandler {
int serverPort;
boolean useProtocol3_3 = false;
boolean clientSecTypeOrder;
- public static java.net.Socket sock;
-
- public static java.net.Socket getSocket() { return sock; }
- public static void setSocket(java.net.Socket sock_) { sock = sock_; }
static LogWriter vlog = new LogWriter("CConnection");
}
/*
- * Copyright (C) 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2004 Red Hat Inc.
+ * Copyright (C) 2005 Martin Koegler
+ * Copyright (C) 2010 m-privacy GmbH
+ * Copyright (C) 2010-2012 TigerVNC Team
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
package com.tigervnc.rfb;
import javax.net.ssl.*;
+import java.security.*;
import java.security.cert.*;
import java.security.KeyStore;
import java.io.File;
import com.tigervnc.vncviewer.UserPrefs;
import com.tigervnc.rdr.*;
+import com.tigervnc.network.*;
+import java.util.concurrent.Executors;
+import java.nio.channels.SelectionKey;
public class CSecurityTLS extends CSecurity {
private void initGlobal()
{
- try {
- SSLSocketFactory sslfactory;
- SSLContext ctx = SSLContext.getInstance("TLS");
- if (anon) {
- ctx.init(null, null, null);
- } else {
- TrustManager[] myTM = new TrustManager[] {
- new MyX509TrustManager()
- };
- ctx.init (null, myTM, null);
- }
- sslfactory = ctx.getSocketFactory();
+ boolean globalInitDone = false;
+
+ if (!globalInitDone) {
try {
- ssl = (SSLSocket)sslfactory.createSocket(CConnection.sock,
- CConnection.sock.getInetAddress().getHostName(),
- CConnection.sock.getPort(), true);
- } catch (java.io.IOException e) {
+ ctx = SSLContext.getInstance("TLS");
+ } catch(NoSuchAlgorithmException e) {
throw new Exception(e.toString());
}
- if (anon) {
- String[] supported;
- ArrayList<String> enabled = new ArrayList<String>();
-
- supported = ssl.getSupportedCipherSuites();
-
- for (int i = 0; i < supported.length; i++)
- if (supported[i].matches("TLS_DH_anon.*"))
- enabled.add(supported[i]);
-
- ssl.setEnabledCipherSuites(enabled.toArray(new String[0]));
- } else {
- ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites());
- }
-
- ssl.setEnabledProtocols(new String[]{"SSLv3","TLSv1"});
- ssl.addHandshakeCompletedListener(new MyHandshakeListener());
- }
- catch (java.security.GeneralSecurityException e)
- {
- vlog.error ("TLS handshake failed " + e.toString ());
- return;
+ globalInitDone = true;
}
}
public CSecurityTLS(boolean _anon)
{
anon = _anon;
+ session = null;
+
setDefaults();
cafile = x509ca.getData();
crlfile = x509crl.getData();
x509crl.setDefaultStr(crlDefault);
}
+// FIXME:
+// Need to shutdown the connection cleanly
+
+// FIXME?
+// add a finalizer method that calls shutdown
+
public boolean processMsg(CConnection cc) {
- is = cc.getInStream();
+ is = (FdInStream)cc.getInStream();
+ os = (FdOutStream)cc.getOutStream();
+ client = cc;
initGlobal();
- if (!is.checkNoWait(1))
- return false;
-
- if (is.readU8() == 0) {
- int result = is.readU32();
- String reason;
- if (result == Security.secResultFailed ||
- result == Security.secResultTooMany)
- reason = is.readString();
- else
- reason = new String("Authentication failure (protocol error)");
- throw new AuthFailureException(reason);
+ if (session == null) {
+ if (!is.checkNoWait(1))
+ return false;
+
+ if (is.readU8() == 0) {
+ int result = is.readU32();
+ String reason;
+ if (result == Security.secResultFailed ||
+ result == Security.secResultTooMany)
+ reason = is.readString();
+ else
+ reason = new String("Authentication failure (protocol error)");
+ throw new AuthFailureException(reason);
+ }
+
+ setParam();
+
}
- // SSLSocket.getSession blocks until the handshake is complete
- session = ssl.getSession();
- if (!session.isValid())
- throw new Exception("TLS Handshake failed!");
+ try {
+ manager = new SSLEngineManager(engine, is, os);
+ } catch(java.lang.Exception e) {
+ System.out.println(e.toString());
+ }
try {
- cc.setStreams(new JavaInStream(ssl.getInputStream()),
- new JavaOutStream(ssl.getOutputStream()));
- } catch (java.io.IOException e) {
- throw new Exception("Failed to set streams");
+ manager.doHandshake();
+ } catch (java.lang.Exception e) {
+ throw new Exception(e.toString());
}
+ //checkSession();
+
+ cc.setStreams(new TLSInStream(is, manager),
+ new TLSOutStream(os, manager));
return true;
}
+ private void setParam() {
+
+ if (anon) {
+ try {
+ ctx.init(null, null, null);
+ } catch(KeyManagementException e) {
+ throw new AuthFailureException(e.toString());
+ }
+ } else {
+ try {
+ TrustManager[] myTM = new TrustManager[] {
+ new MyX509TrustManager()
+ };
+ ctx.init (null, myTM, null);
+ } catch (java.security.GeneralSecurityException e) {
+ throw new AuthFailureException(e.toString());
+ }
+ }
+ SSLSocketFactory sslfactory = ctx.getSocketFactory();
+ engine = ctx.createSSLEngine(client.getServerName(),
+ client.getServerPort());
+ engine.setUseClientMode(true);
+
+ if (anon) {
+ String[] supported;
+ ArrayList<String> enabled = new ArrayList<String>();
+
+ supported = engine.getSupportedCipherSuites();
+
+ for (int i = 0; i < supported.length; i++)
+ if (supported[i].matches("TLS_DH_anon.*"))
+ enabled.add(supported[i]);
+
+ engine.setEnabledCipherSuites(enabled.toArray(new String[0]));
+ } else {
+ engine.setEnabledCipherSuites(engine.getSupportedCipherSuites());
+ }
+
+ engine.setEnabledProtocols(new String[]{"SSLv3","TLSv1"});
+ }
+
class MyHandshakeListener implements HandshakeCompletedListener {
public void handshakeCompleted(HandshakeCompletedEvent e) {
vlog.info("Handshake succesful!");
public final String description()
{ return anon ? "TLS Encryption without VncAuth" : "X509 Encryption without VncAuth"; }
-
- //protected void setParam();
//protected void checkSession();
- protected CConnection cc;
+ protected CConnection client;
- private boolean anon;
+
+
+ private SSLContext ctx;
private SSLSession session;
+ private SSLEngine engine;
+ private SSLEngineManager manager;
+ private boolean anon;
+
private String cafile, crlfile;
- private InStream is;
- private SSLSocket ssl;
+ private FdInStream is;
+ private FdOutStream os;
static LogWriter vlog = new LogWriter("CSecurityTLS");
}
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2012 TigerVNC Team
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
import java.util.jar.Manifest;
import javax.swing.*;
import javax.swing.ImageIcon;
+import java.net.InetSocketAddress;
import java.net.URL;
+import java.net.SocketException;
import java.util.*;
import com.tigervnc.rdr.*;
import com.tigervnc.rfb.Exception;
import com.tigervnc.rfb.Point;
import com.tigervnc.rfb.Rect;
+import com.tigervnc.network.Socket;
+import com.tigervnc.network.TcpSocket;
class ViewportFrame extends JFrame
{
});
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
- cc.close();
+ cc.deleteWindow();
}
});
addComponentListener(new ComponentAdapter() {
}
public class CConn extends CConnection
- implements UserPasswdGetter, UserMsgBox, OptionsDialogCallback
+ implements UserPasswdGetter, UserMsgBox, OptionsDialogCallback, FdInStreamBlockCallback
{
////////////////////////////////////////////////////////////////////
// The following methods are all called from the RFB thread
- public CConn(VncViewer viewer_, java.net.Socket sock_,
+ public CConn(VncViewer viewer_, Socket sock_,
String vncServerName, boolean reverse)
{
serverHost = null; serverPort = 0; sock = sock_; viewer = viewer_;
initMenu();
if (sock != null) {
- String name = sock.getRemoteSocketAddress()+"::"+sock.getPort();
+ String name = sock.getPeerEndpoint();
vlog.info("Accepted connection from "+name);
} else {
if (vncServerName != null) {
}
try {
- sock = new java.net.Socket(serverHost, serverPort);
- } catch (java.io.IOException e) {
+ sock = new TcpSocket(serverHost, serverPort);
+ } catch (java.lang.Exception e) {
throw new Exception(e.toString());
}
vlog.info("connected to host "+serverHost+" port "+serverPort);
}
- sameMachine = (sock.getLocalSocketAddress() == sock.getRemoteSocketAddress());
- try {
- sock.setTcpNoDelay(true);
- sock.setTrafficClass(0x10);
- setServerName(serverHost);
- jis = new JavaInStream(sock.getInputStream());
- jos = new JavaOutStream(sock.getOutputStream());
- } catch (java.net.SocketException e) {
- throw new Exception(e.toString());
- } catch (java.io.IOException e) {
- throw new Exception(e.toString());
- }
- setStreams(jis, jos);
+ sameMachine = sock.sameMachine();
+ sock.inStream().setBlockCallback(this);
+ setServerName(serverHost);
+ setStreams(sock.inStream(), sock.outStream());
initialiseProtocol();
}
if (viewport != null)
viewport.dispose();
viewport = null;
+ System.exit(1);
}
+ // blockCallback() is called when reading from the socket would block.
+ public void blockCallback() {
+ try {
+ synchronized(this) {
+ wait(1);
+ }
+ } catch (java.lang.InterruptedException e) {
+ throw new Exception(e.toString());
+ }
+ }
+
// getUserPasswd() is called by the CSecurity object when it needs us to read
// a password from the user.
public void clientRedirect(int port, String host,
String x509subject) {
try {
- getSocket().close();
+ sock.close();
setServerPort(port);
- sock = new java.net.Socket(host, port);
- sock.setTcpNoDelay(true);
- sock.setTrafficClass(0x10);
- setSocket(sock);
+ sock = new TcpSocket(host, port);
vlog.info("Redirected to "+host+":"+port);
- setStreams(new JavaInStream(sock.getInputStream()),
- new JavaOutStream(sock.getOutputStream()));
+ setStreams(sock.inStream(), sock.outStream());
initialiseProtocol();
- } catch (java.io.IOException e) {
- e.printStackTrace();
+ } catch (java.lang.Exception e) {
+ throw new Exception(e.toString());
}
}
// avoid skewing the bandwidth estimation as a result of the server
// being slow or the network having high latency
public void beginRect(Rect r, int encoding) {
- ((JavaInStream)getInStream()).startTiming();
+ sock.inStream().startTiming();
if (encoding != Encodings.encodingCopyRect) {
lastServerEncoding = encoding;
}
}
public void endRect(Rect r, int encoding) {
- ((JavaInStream)getInStream()).stopTiming();
+ sock.inStream().stopTiming();
}
public void fillRect(Rect r, int p) {
// with something more intelligent at the server end.
//
private void autoSelectFormatAndEncoding() {
- long kbitsPerSecond = ((JavaInStream)getInStream()).kbitsPerSecond();
- long timeWaited = ((JavaInStream)getInStream()).timeWaited();
+ long kbitsPerSecond = sock.inStream().kbitsPerSecond();
+ long timeWaited = sock.inStream().timeWaited();
boolean newFullColour = fullColour;
int newQualityLevel = cp.qualityLevel;
// close() closes the socket, thus waking up the RFB thread.
public void close() {
- try {
- shuttingDown = true;
- sock.close();
- } catch (java.io.IOException e) {
- e.printStackTrace();
- }
+ shuttingDown = true;
+ sock.shutdown();
}
// Menu callbacks. These are guaranteed only to be called after serverInit()
void showInfo() {
JOptionPane.showMessageDialog(viewport,
"Desktop name: "+cp.name()+"\n"
- +"Host: "+serverHost+":"+sock.getPort()+"\n"
+ +"Host: "+serverHost+":"+serverPort+"\n"
+"Size: "+cp.width+"x"+cp.height+"\n"
+"Pixel format: "+desktop.getPF().print()+"\n"
+"(server default "+serverPF.print()+")\n"
+"Requested encoding: "+Encodings.encodingName(currentEncoding)+"\n"
+"Last used encoding: "+Encodings.encodingName(lastServerEncoding)+"\n"
- +"Line speed estimate: "+((JavaInStream)getInStream()).kbitsPerSecond()+" kbit/s"+"\n"
+ +"Line speed estimate: "+sock.inStream().kbitsPerSecond()+" kbit/s"+"\n"
+"Protocol version: "+cp.majorVersion+"."+cp.minorVersion+"\n"
+"Security method: "+Security.secTypeName(csecurity.getType())
+" ["+csecurity.description()+"]",
}
// the following never change so need no synchronization:
- JavaInStream jis;
- JavaOutStream jos;
// viewer object is only ever accessed by the GUI thread so needs no
public String serverHost;
public int serverPort;
+ public Socket sock;
public int menuKey;
PixelFormat serverPF;
ViewportFrame viewport;
import java.io.InputStream;
import java.io.IOException;
import java.lang.Character;
-import java.net.ServerSocket;
-import java.net.Socket;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import javax.swing.*;
import com.tigervnc.rdr.*;
import com.tigervnc.rfb.*;
+import com.tigervnc.network.*;
public class VncViewer extends java.applet.Applet implements Runnable
{
public void run() {
CConn cc = null;
Socket sock = null;
+
if (listenMode.getValue()) {
int port = 5500;
- ServerSocket listener = null;
+
if (vncServerName.getValue() != null &&
Character.isDigit(vncServerName.getValue().charAt(0)))
port = Integer.parseInt(vncServerName.getValue());
+ TcpListener listener = null;
try {
- listener = new ServerSocket(port);
- } catch (IOException e) {
- System.out.println("Could not listen on port: "+port);
- System.exit(-1);
+ listener = new TcpListener(null, port);
+ } catch (java.lang.Exception e) {
+ System.out.println(e.toString());
+ System.exit(1);
}
vlog.info("Listening on port "+port);
- try {
+ while (true) {
sock = listener.accept();
- listener.close();
- } catch (IOException e) {
- System.out.println("Accept failed: "+port);
- System.exit(-1);
+ if (sock != null)
+ break;
+ //listener.close();
}
-
}
+
try {
cc = new CConn(this, sock, vncServerName.getValue(), false);
while (true)