X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;ds=inline;f=src%2Fbe%2Fnikiroo%2Futils%2Fserial%2Fserver%2FConnectAction.java;h=6a19368bbf97824deb624ffaf9eac238b44dfad7;hb=3bfc1d20054f0a97f268f1fffea29df10ae14b42;hp=d359e08b217f623ddde1749090aeefc2391deffd;hpb=d2219aa05bbcc5603e90aa69220fecb4a6a41f55;p=nikiroo-utils.git diff --git a/src/be/nikiroo/utils/serial/server/ConnectAction.java b/src/be/nikiroo/utils/serial/server/ConnectAction.java index d359e08..6a19368 100644 --- a/src/be/nikiroo/utils/serial/server/ConnectAction.java +++ b/src/be/nikiroo/utils/serial/server/ConnectAction.java @@ -10,6 +10,7 @@ import javax.net.ssl.SSLException; import be.nikiroo.utils.CryptUtils; import be.nikiroo.utils.IOUtils; import be.nikiroo.utils.StringUtils; +import be.nikiroo.utils.Version; import be.nikiroo.utils.serial.Exporter; import be.nikiroo.utils.serial.Importer; import be.nikiroo.utils.streams.BufferedOutputStream; @@ -28,9 +29,18 @@ import be.nikiroo.utils.streams.ReplaceOutputStream; * @author niki */ abstract class ConnectAction { + // We separate each "packet" we send with this character and make sure it + // does not occurs in the message itself. + static private char STREAM_SEP = '\b'; + static private String[] STREAM_RAW = new String[] { "\\", "\b" }; + static private String[] STREAM_CODED = new String[] { "\\\\", "\\b" }; + private Socket s; private boolean server; + private Version clientVersion; + private Version serverVersion; + private CryptUtils crypt; private Object lock = new Object(); @@ -42,10 +52,28 @@ abstract class ConnectAction { * Method that will be called when an action is performed on either the * client or server this {@link ConnectAction} represent. * + * @param version + * the version on the other side of the communication (client or + * server) + * * @throws Exception * in case of I/O error */ - abstract protected void action() throws Exception; + abstract protected void action(Version version) throws Exception; + + /** + * Method called when we negotiate the version with the client. + *
+ * Thus, it is only called on the server. + *
+ * Will return the actual server version by default. + * + * @param clientVersion + * the client version + * + * @return the version to send to the client + */ + abstract protected Version negotiateVersion(Version clientVersion); /** * Handler called when an unexpected error occurs in the code. @@ -67,13 +95,40 @@ abstract class ConnectAction { * @param key * an optional key to encrypt all the communications (if NULL, * everything will be sent in clear text) + * @param version + * the client-or-server version (depending upon the boolean + * parameter server) */ - protected ConnectAction(Socket s, boolean server, String key) { + protected ConnectAction(Socket s, boolean server, String key, + Version version) { this.s = s; this.server = server; if (key != null) { crypt = new CryptUtils(key); } + + if (version == null) { + version = new Version(); + } + + if (server) { + serverVersion = version; + } else { + clientVersion = version; + } + } + + /** + * The version of this client-or-server. + * + * @return the version + */ + public Version getVersion() { + if (server) { + return serverVersion; + } + + return clientVersion; } /** @@ -99,15 +154,34 @@ abstract class ConnectAction { */ public void connect() { try { - // TODO: assure that \b is never used, make sure \n usage is OK in = new NextableInputStream(s.getInputStream(), - new NextableInputStreamStep('\b')); - + new NextableInputStreamStep(STREAM_SEP)); try { out = new BufferedOutputStream(s.getOutputStream()); - try { - action(); + // Negotiate version + Version version; + if (server) { + String HELLO = recString(); + if (HELLO == null || !HELLO.startsWith("VERSION ")) { + throw new SSLException( + "Client used bad encryption key"); + } + version = negotiateVersion(new Version( + HELLO.substring("VERSION ".length()))); + sendString("VERSION " + version); + } else { + String HELLO = sendString("VERSION " + clientVersion); + if (HELLO == null || !HELLO.startsWith("VERSION ")) { + throw new SSLException( + "Server did not accept the encryption key"); + } + version = new Version(HELLO.substring("VERSION " + .length())); + } + + // Actual code + action(version); } finally { out.close(); } @@ -294,12 +368,7 @@ abstract class ConnectAction { sub = out.open(); } - // TODO: could be possible to check for non-crypt and only - // do it for crypt - sub = new ReplaceOutputStream(sub, // - new String[] { "\\", "\b" }, // - new String[] { "\\\\", "\\b" }); - + sub = new ReplaceOutputStream(sub, STREAM_RAW, STREAM_CODED); try { if (asString) { sub.write(StringUtils.getBytes(data.toString())); @@ -310,7 +379,7 @@ abstract class ConnectAction { sub.close(); } - out.write('\b'); + out.write(STREAM_SEP); if (server) { out.flush(); @@ -377,12 +446,8 @@ abstract class ConnectAction { } if (in.next() && !in.eof()) { - // TODO: could be possible to check for non-crypt and only - // do it for crypt - InputStream read = new ReplaceInputStream(in.open(), // - new String[] { "\\\\", "\\b" }, // - new String[] { "\\", "\b" }); - + InputStream read = new ReplaceInputStream(in.open(), + STREAM_CODED, STREAM_RAW); try { if (crypt != null) { read = crypt.decrypt64(read);