diff options
author | Brian Hinz <bphinz@users.sourceforge.net> | 2012-03-18 21:39:04 +0000 |
---|---|---|
committer | Brian Hinz <bphinz@users.sourceforge.net> | 2012-03-18 21:39:04 +0000 |
commit | 35022e07a90807f5f0686c146e49f469d4b3f2fd (patch) | |
tree | 9734715a7e8f83eb7c6d31867e5cef7e7be0f5e8 /java/com/tigervnc | |
parent | ef41e92001036029284c7bcfb6a9249cc2008a87 (diff) | |
download | tigervnc-35022e07a90807f5f0686c146e49f469d4b3f2fd.tar.gz tigervnc-35022e07a90807f5f0686c146e49f469d4b3f2fd.zip |
Changes aimed at making the behavior of the java client more consistent with the binary client.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4871 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'java/com/tigervnc')
-rw-r--r-- | java/com/tigervnc/network/FileDescriptor.java | 2 | ||||
-rw-r--r-- | java/com/tigervnc/network/SocketDescriptor.java | 31 | ||||
-rw-r--r-- | java/com/tigervnc/rdr/FdInStream.java | 73 | ||||
-rw-r--r-- | java/com/tigervnc/rdr/FdOutStream.java | 20 | ||||
-rw-r--r-- | java/com/tigervnc/rdr/InStream.java | 21 | ||||
-rw-r--r-- | java/com/tigervnc/rfb/CConnection.java | 138 | ||||
-rw-r--r-- | java/com/tigervnc/rfb/ConnParams.java | 1 | ||||
-rw-r--r-- | java/com/tigervnc/vncviewer/CConn.java | 3 |
8 files changed, 177 insertions, 112 deletions
diff --git a/java/com/tigervnc/network/FileDescriptor.java b/java/com/tigervnc/network/FileDescriptor.java index 28ea96b8..12f6d586 100644 --- a/java/com/tigervnc/network/FileDescriptor.java +++ b/java/com/tigervnc/network/FileDescriptor.java @@ -25,7 +25,7 @@ public interface FileDescriptor { public int read(byte[] buf, int bufPtr, int length) throws Exception; public int write(byte[] buf, int bufPtr, int length) throws Exception; - public int select(int interestOps, int timeout) throws Exception; + public int select(int interestOps, Integer timeout) throws Exception; public void close() throws IOException; } diff --git a/java/com/tigervnc/network/SocketDescriptor.java b/java/com/tigervnc/network/SocketDescriptor.java index 95ee84ae..f9207316 100644 --- a/java/com/tigervnc/network/SocketDescriptor.java +++ b/java/com/tigervnc/network/SocketDescriptor.java @@ -88,32 +88,37 @@ public class SocketDescriptor extends SocketChannel return n; } - synchronized public int select(int interestOps, int timeout) throws Exception { + synchronized public int select(int interestOps, Integer timeout) throws Exception { int n; + selector.selectedKeys().clear(); try { - if (timeout == 0) { - n = selector.selectNow(); + if (timeout == null) { + n = selector.select(); } else { - n = selector.select(timeout); + int tv = timeout.intValue(); + switch(tv) { + case 0: + n = selector.selectNow(); + break; + default: + n = selector.select((long)tv); + break; + } } + if (n == 0) + return -1; } catch (java.io.IOException e) { throw new Exception(e.toString()); } - if (n == 0) - return -1; 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; + if ((key.readyOps() & interestOps) != 0) { + return n; } } - keys.clear(); - return n; + return 0; } public int write(ByteBuffer buf) throws Exception { diff --git a/java/com/tigervnc/rdr/FdInStream.java b/java/com/tigervnc/rdr/FdInStream.java index ea81388f..faf98693 100644 --- a/java/com/tigervnc/rdr/FdInStream.java +++ b/java/com/tigervnc/rdr/FdInStream.java @@ -27,21 +27,36 @@ import java.util.Iterator; public class FdInStream extends InStream { - static final int defaultBufSize = 8192; + static final int DEFAULT_BUF_SIZE = 8192; static final int minBulkSize = 1024; - public FdInStream(FileDescriptor fd_, int bufSize_) { - fd = fd_; - bufSize = bufSize_; + public FdInStream(FileDescriptor fd_, int timeoutms_, int bufSize_, + boolean closeWhenDone_) + { + fd = fd_; closeWhenDone = closeWhenDone_; + timeoutms = timeoutms_; blockCallback = null; + timing = false; timeWaitedIn100us = 5; timedKbits = 0; + bufSize = ((bufSize_ > 0) ? bufSize_ : DEFAULT_BUF_SIZE); + b = new byte[bufSize]; + ptr = end = offset = 0; + } + + public FdInStream(FileDescriptor fd_) { this(fd_, -1, 0, false); } + + public FdInStream(FileDescriptor fd_, FdInStreamBlockCallback blockCallback_, + int bufSize_) + { + fd = fd_; timeoutms = 0; blockCallback = blockCallback_; + timing = false; timeWaitedIn100us = 5; timedKbits = 0; + bufSize = ((bufSize_ > 0) ? bufSize_ : DEFAULT_BUF_SIZE); b = new byte[bufSize]; ptr = end = offset = 0; - timeoutms = 0; - timing = false; - timeWaitedIn100us = 5; - timedKbits = 0; } - public FdInStream(FileDescriptor fd_) { this(fd_, defaultBufSize); } + public FdInStream(FileDescriptor fd_, + FdInStreamBlockCallback blockCallback_) { + this(fd_, blockCallback_, 0); + } public final void readBytes(byte[] data, int dataPtr, int length) { if (length < minBulkSize) { @@ -100,7 +115,8 @@ public class FdInStream extends InStream { public final long timeWaited() { return timeWaitedIn100us; } - protected int overrun(int itemSize, int nItems, boolean wait) { + protected int overrun(int itemSize, int nItems, boolean wait) + { if (itemSize > bufSize) throw new Exception("FdInStream overrun: max itemSize exceeded"); @@ -136,26 +152,28 @@ public class FdInStream extends InStream { protected int readWithTimeoutOrCallback(byte[] buf, int bufPtr, int len, boolean wait) { long before = 0; - int timeout; if (timing) before = System.nanoTime(); int n; while (true) { + do { + Integer tv; - if (!wait) { - timeout = 0; - } else if (timeoutms != -1) { - timeout = timeoutms; - } else { - timeout = 0; - } - - try { - n = fd.select(SelectionKey.OP_READ, timeout); - } catch (Exception e) { - throw new SystemException("select:"+e.toString()); - } + if (!wait) { + tv = new Integer(0); + } else if (timeoutms != -1) { + tv = new Integer(timeoutms); + } else { + tv = null; + } + + try { + n = fd.select(SelectionKey.OP_READ, tv); + } catch (Exception e) { + throw new SystemException("select:"+e.toString()); + } + } while (n < 0); if (n > 0) break; @@ -205,11 +223,12 @@ public class FdInStream extends InStream { fd = fd_; } - private int offset; - private int bufSize; private FileDescriptor fd; - private FdInStreamBlockCallback blockCallback; + boolean closeWhenDone; protected int timeoutms; + private FdInStreamBlockCallback blockCallback; + private int offset; + private int bufSize; protected boolean timing; protected long timeWaitedIn100us; diff --git a/java/com/tigervnc/rdr/FdOutStream.java b/java/com/tigervnc/rdr/FdOutStream.java index c7767245..ce89f1ec 100644 --- a/java/com/tigervnc/rdr/FdOutStream.java +++ b/java/com/tigervnc/rdr/FdOutStream.java @@ -24,22 +24,20 @@ import java.nio.channels.SelectionKey; public class FdOutStream extends OutStream { - static final int defaultBufSize = 16384; + static final int DEFAULT_BUF_SIZE = 16384; static final int minBulkSize = 1024; public FdOutStream(FileDescriptor fd_, boolean blocking_, int timeoutms_, int bufSize_) { - fd = fd_; - blocking = blocking_; - timeoutms = timeoutms_; - bufSize = bufSize_; + fd = fd_; blocking = blocking_; timeoutms = timeoutms_; + bufSize = ((bufSize_ > 0) ? bufSize_ : DEFAULT_BUF_SIZE); b = new byte[bufSize]; offset = 0; ptr = sentUpTo = start = 0; end = start + bufSize; } - public FdOutStream(FileDescriptor fd_) { this(fd_, false, 0, defaultBufSize); } + public FdOutStream(FileDescriptor fd_) { this(fd_, true, -1, 0); } public void setTimeout(int timeoutms_) { timeoutms = timeoutms_; @@ -93,19 +91,19 @@ public class FdOutStream extends OutStream { private int writeWithTimeout(byte[] data, int dataPtr, int length, int timeoutms) { - int timeout; int n; do { + Integer tv; if (timeoutms != -1) { - timeout = timeoutms; + tv = new Integer(timeoutms); } else { - timeout = 0; + tv = null; } try { - n = fd.select(SelectionKey.OP_WRITE, timeout); + n = fd.select(SelectionKey.OP_WRITE, tv); } catch (java.lang.Exception e) { System.out.println(e.toString()); throw new Exception(e.toString()); @@ -113,6 +111,8 @@ public class FdOutStream extends OutStream { } while (n < 0); + if (n == 0) return 0; + try { n = fd.write(data, dataPtr, length); } catch (java.lang.Exception e) { diff --git a/java/com/tigervnc/rdr/InStream.java b/java/com/tigervnc/rdr/InStream.java index 8e58fbda..39de6f41 100644 --- a/java/com/tigervnc/rdr/InStream.java +++ b/java/com/tigervnc/rdr/InStream.java @@ -32,12 +32,11 @@ abstract public class InStream { // maximum of nItems). public int check(int itemSize, int nItems, boolean wait) { - int available = end - ptr; - if (itemSize * nItems > available) { - if (itemSize > available) + if (ptr + itemSize * nItems > end) { + if (ptr + itemSize > end) return overrun(itemSize, nItems, wait); - nItems = available / itemSize; + nItems = (end - ptr) / itemSize; } return nItems; } @@ -53,10 +52,10 @@ abstract public class InStream { // readU/SN() methods read unsigned and signed N-bit integers. - public final int readS8() { check(1,1,true); return b[ptr++]; } - public final int readS16() { check(2,1,true); int b0 = b[ptr++]; + public final int readS8() { check(1); return b[ptr++]; } + public final int readS16() { check(2); int b0 = b[ptr++]; int b1 = b[ptr++] & 0xff; return b0 << 8 | b1; } - public final int readS32() { check(4,1,true); int b0 = b[ptr++]; + public final int readS32() { check(4); int b0 = b[ptr++]; int b1 = b[ptr++] & 0xff; int b2 = b[ptr++] & 0xff; int b3 = b[ptr++] & 0xff; @@ -91,7 +90,7 @@ abstract public class InStream { public final void skip(int bytes) { while (bytes > 0) { - int n = check(1, bytes, true); + int n = check(1, bytes); ptr += n; bytes -= n; } @@ -102,7 +101,7 @@ abstract public class InStream { public void readBytes(byte[] data, int dataPtr, int length) { int dataEnd = dataPtr + length; while (dataPtr < dataEnd) { - int n = check(1, dataEnd - dataPtr, true); + int n = check(1, dataEnd - dataPtr); System.arraycopy(b, ptr, data, dataPtr, n); ptr += n; dataPtr += n; @@ -115,10 +114,10 @@ abstract public class InStream { public final int readOpaque8() { return readU8(); } public final int readOpaque16() { return readU16(); } public final int readOpaque32() { return readU32(); } - public final int readOpaque24A() { check(3, 1, true); int b0 = b[ptr++]; + public final int readOpaque24A() { check(3); int b0 = b[ptr++]; int b1 = b[ptr++]; int b2 = b[ptr++]; return b0 << 24 | b1 << 16 | b2 << 8; } - public final int readOpaque24B() { check(3, 1, true); int b0 = b[ptr++]; + public final int readOpaque24B() { check(3); int b0 = b[ptr++]; int b1 = b[ptr++]; int b2 = b[ptr++]; return b0 << 16 | b1 << 8 | b2; } diff --git a/java/com/tigervnc/rfb/CConnection.java b/java/com/tigervnc/rfb/CConnection.java index 0ec44044..1e55f043 100644 --- a/java/com/tigervnc/rfb/CConnection.java +++ b/java/com/tigervnc/rfb/CConnection.java @@ -25,31 +25,37 @@ import com.tigervnc.rdr.*; abstract public class CConnection extends CMsgHandler { - public CConnection() { + public CConnection() + { + csecurity = null; is = null; os = null; reader_ = null; + writer_ = null; shared = false; + state_ = RFBSTATE_UNINITIALISED; useProtocol3_3 = false; security = new SecurityClient(); } - // setStreams() sets the streams to be used for the connection. These must - // be set before initialiseProtocol() and processMsg() are called. The - // CSecurity object may call setStreams() again to provide alternative - // streams over which the RFB protocol is sent (i.e. encrypting/decrypting - // streams). Ownership of the streams remains with the caller - // (i.e. SConnection will not delete them). - public void setStreams(InStream is_, OutStream os_) { - is = is_; - os = os_; + // deleteReaderAndWriter() deletes the reader and writer associated with + // this connection. This may be useful if you want to delete the streams + // before deleting the SConnection to make sure that no attempt by the + // SConnection is made to read or write. + // XXX Do we really need this at all??? + public void deleteReaderAndWriter() + { + reader_ = null; + writer_ = null; } // initialiseProtocol() should be called once the streams and security // types are set. Subsequently, processMsg() should be called whenever // there is data to read on the InStream. - public void initialiseProtocol() { + public final void initialiseProtocol() + { state_ = RFBSTATE_PROTOCOL_VERSION; } // processMsg() should be called whenever there is data to read on the // InStream. You must have called initialiseProtocol() first. - public void processMsg() { + public void processMsg() + { switch (state_) { case RFBSTATE_PROTOCOL_VERSION: processVersionMsg(); break; @@ -65,7 +71,8 @@ abstract public class CConnection extends CMsgHandler { } } - private void processVersionMsg() { + private void processVersionMsg() + { vlog.debug("reading protocol version"); Boolean done = new Boolean(true); if (!cp.readVersion(is, done)) { @@ -74,8 +81,8 @@ abstract public class CConnection extends CMsgHandler { } if (!done.booleanValue()) return; - vlog.info("Server supports RFB protocol version "+cp.majorVersion+"."+ - cp.minorVersion); + vlog.info("Server supports RFB protocol version " + +cp.majorVersion+"."+ cp.minorVersion); // The only official RFB protocol versions are currently 3.3, 3.7 and 3.8 if (cp.beforeVersion(3,3)) { @@ -97,15 +104,14 @@ abstract public class CConnection extends CMsgHandler { cp.majorVersion+"."+cp.minorVersion); } - private void processSecurityTypesMsg() { - vlog.info("processing security types message"); + private void processSecurityTypesMsg() + { + vlog.debug("processing security types message"); int secType = Security.secTypeInvalid; List<Integer> secTypes = new ArrayList<Integer>(); secTypes = Security.GetEnabledSecTypes(); - //for (Iterator i = secTypes.iterator(); i.hasNext(); ) - // vlog.info(((Integer)i.next()).toString()); if (cp.isVersion(3,3)) { @@ -123,10 +129,10 @@ abstract public class CConnection extends CMsgHandler { secType = refType; break; } - if (!i.hasNext()) - secType = Security.secTypeInvalid; } + if (!secTypes.contains(secType)) + secType = Security.secTypeInvalid; } else { vlog.error("Unknown 3.3 security type "+secType); throw new Exception("Unknown 3.3 security type"); @@ -140,9 +146,11 @@ abstract public class CConnection extends CMsgHandler { if (nServerSecTypes == 0) throwConnFailedException(); + Iterator j; + for (int i = 0; i < nServerSecTypes; i++) { int serverSecType = is.readU8(); - vlog.info("Server offers security type "+ + vlog.debug("Server offers security type "+ Security.secTypeName(serverSecType)+"("+serverSecType+")"); /* @@ -150,7 +158,7 @@ abstract public class CConnection extends CMsgHandler { * It means server's order specifies priority. */ if (secType == Security.secTypeInvalid) { - for (Iterator j = secTypes.iterator(); j.hasNext(); ) { + for (j = secTypes.iterator(); j.hasNext(); ) { int refType = (Integer)j.next(); if (refType == serverSecType) { secType = refType; @@ -164,7 +172,7 @@ abstract public class CConnection extends CMsgHandler { if (secType != Security.secTypeInvalid) { os.writeU8(secType); os.flush(); - vlog.info("Choosing security type "+Security.secTypeName(secType)+ + vlog.debug("Choosing security type "+Security.secTypeName(secType)+ "("+secType+")"); } } @@ -246,10 +254,30 @@ abstract public class CConnection extends CMsgHandler { // which we are connected. This might be the result of getPeerEndpoint on // a TcpSocket, for example, or a host specified by DNS name & port. // The serverName is used when verifying the Identity of a host (see RA2). - public void setServerName(String name) { + public final void setServerName(String name) { serverName = name; } + // setStreams() sets the streams to be used for the connection. These must + // be set before initialiseProtocol() and processMsg() are called. The + // CSecurity object may call setStreams() again to provide alternative + // streams over which the RFB protocol is sent (i.e. encrypting/decrypting + // streams). Ownership of the streams remains with the caller + // (i.e. SConnection will not delete them). + public final void setStreams(InStream is_, OutStream os_) + { + is = is_; + os = os_; + } + + // setShared sets the value of the shared flag which will be sent to the + // server upon initialisation. + public final void setShared(boolean s) { shared = s; } + + // setProtocol3_3 configures whether or not the CConnection should + // only ever support protocol version 3.3 + public final void setProtocol3_3(boolean s) { useProtocol3_3 = s; } + public void setServerPort(int port) { serverPort = port; } @@ -258,15 +286,22 @@ abstract public class CConnection extends CMsgHandler { nSecTypes = 0; } - // setShared sets the value of the shared flag which will be sent to the - // server upon initialisation. - public void setShared(boolean s) { shared = s; } + // Methods to be overridden in a derived class - // setProtocol3_3 configures whether or not the CConnection should - // only ever support protocol version 3.3 - public void setProtocol3_3(boolean s) { useProtocol3_3 = s; } + // getIdVerifier() returns the identity verifier associated with the connection. + // Ownership of the IdentityVerifier is retained by the CConnection instance. + //public IdentityVerifier getIdentityVerifier() { return 0; } - // Methods to be overridden in a derived class + // authSuccess() is called when authentication has succeeded. + public void authSuccess() {} + + // serverInit() is called when the ServerInit message is received. The + // derived class must call on to CConnection::serverInit(). + public void serverInit() + { + state_ = RFBSTATE_NORMAL; + vlog.debug("initialisation done"); + } // getCSecurity() gets the CSecurity object for the given type. The type // is guaranteed to be one of the secTypes passed in to addSecType(). The @@ -286,16 +321,6 @@ abstract public class CConnection extends CMsgHandler { clientSecTypeOrder = csto; } - // authSuccess() is called when authentication has succeeded. - public void authSuccess() {} - - // serverInit() is called when the ServerInit message is received. The - // derived class must call on to CConnection::serverInit(). - public void serverInit() { - state_ = RFBSTATE_NORMAL; - vlog.debug("initialisation done"); - } - // Other methods public CMsgReaderV3 reader() { return reader_; } @@ -318,7 +343,22 @@ abstract public class CConnection extends CMsgHandler { public int state() { return state_; } - protected void setState(int s) { state_ = s; } + protected final void setState(int s) { state_ = s; } + + public void fence(int flags, int len, byte[] data) + { + super.fence(flags, len, data); + + if ((flags & fenceTypes.fenceFlagRequest) != 0) + return; + + // We cannot guarantee any synchronisation at this level + flags = 0; + + synchronized(this) { + writer().writeFence(flags, len, data); + } + } private void throwAuthFailureException() { String reason; @@ -333,11 +373,11 @@ abstract public class CConnection extends CMsgHandler { throw new AuthFailureException(reason); } - InStream is = null; - OutStream os = null; - CMsgReaderV3 reader_ = null; - CMsgWriterV3 writer_ = null; - boolean shared = false; + InStream is; + OutStream os; + CMsgReaderV3 reader_; + CMsgWriterV3 writer_; + boolean shared; public CSecurity csecurity; public SecurityClient security; public static final int maxSecTypes = 8; @@ -346,7 +386,7 @@ abstract public class CConnection extends CMsgHandler { int state_ = RFBSTATE_UNINITIALISED; String serverName; int serverPort; - boolean useProtocol3_3 = false; + boolean useProtocol3_3; boolean clientSecTypeOrder; static LogWriter vlog = new LogWriter("CConnection"); diff --git a/java/com/tigervnc/rfb/ConnParams.java b/java/com/tigervnc/rfb/ConnParams.java index e3c3a824..08037231 100644 --- a/java/com/tigervnc/rfb/ConnParams.java +++ b/java/com/tigervnc/rfb/ConnParams.java @@ -47,6 +47,7 @@ public class ConnParams { { if (verStrPos >= 12) return false; verStr = new StringBuilder(13); + is.check(12); while (verStrPos < 12) { verStr.insert(verStrPos++,(char)is.readU8()); } diff --git a/java/com/tigervnc/vncviewer/CConn.java b/java/com/tigervnc/vncviewer/CConn.java index d4ef5e90..061e6fbe 100644 --- a/java/com/tigervnc/vncviewer/CConn.java +++ b/java/com/tigervnc/vncviewer/CConn.java @@ -530,7 +530,8 @@ public class CConn extends CConnection public void fence(int flags, int len, byte[] data) { - super.fence(flags, len, data); + // can't call super.super.fence(flags, len, data); + cp.supportsFence = true; if ((flags & fenceTypes.fenceFlagRequest) != 0) { // We handle everything synchronously so we trivially honor these modes |