From 60b1bd16f28584ff8333fab3870504915ec53cd7 Mon Sep 17 00:00:00 2001 From: Gideon le Grange Date: Sun, 29 Mar 2015 12:56:23 +0200 Subject: [PATCH] Working on fix for issue #16 --- .gitignore | 3 ++ src/main/java/examples/Config.java | 2 +- src/main/java/examples/Example9.java | 28 ++++++++++ .../me/legrange/mikrotik/ApiConnection.java | 8 +-- .../mikrotik/impl/ApiConnectionImpl.java | 54 ++++++++++--------- 5 files changed, 66 insertions(+), 29 deletions(-) create mode 100644 src/main/java/examples/Example9.java diff --git a/.gitignore b/.gitignore index ae4703f..dee2255 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ nbactions.xml .classpath .project + +# Maven +pom.xml.versionsBackup diff --git a/src/main/java/examples/Config.java b/src/main/java/examples/Config.java index 67dcab9..020c596 100644 --- a/src/main/java/examples/Config.java +++ b/src/main/java/examples/Config.java @@ -7,7 +7,7 @@ package examples; public class Config { - public static final String HOST = "10.0.1.134"; + public static final String HOST = "192.168.1.1"; public static final String USERNAME = "admin"; public static final String PASSWORD = ""; diff --git a/src/main/java/examples/Example9.java b/src/main/java/examples/Example9.java new file mode 100644 index 0000000..5870a9c --- /dev/null +++ b/src/main/java/examples/Example9.java @@ -0,0 +1,28 @@ +package examples; + +import java.util.List; +import java.util.Map; +import me.legrange.mikrotik.MikrotikApiException; + +/** + * Example 9: Test special characters in usernames + * + * @author gideon + */ +public class Example9 extends Example { + + public static void main(String... args) throws Exception { + Example9 ex = new Example9(); + ex.connect(); + ex.test(); + ex.disconnect(); + } + + private void test() throws MikrotikApiException, InterruptedException { + List> res = con.execute("/user/add name=çãáõ"); + for (Map r : res) { + System.out.println(r); + } +// con.execute("/ip/firewall/filter/add chain=forward hotspot=!auth protocol=tcp src-port=8000-8084"); + } +} diff --git a/src/main/java/me/legrange/mikrotik/ApiConnection.java b/src/main/java/me/legrange/mikrotik/ApiConnection.java index 29fa64c..9bef672 100644 --- a/src/main/java/me/legrange/mikrotik/ApiConnection.java +++ b/src/main/java/me/legrange/mikrotik/ApiConnection.java @@ -20,7 +20,7 @@ public abstract class ApiConnection { * @throws me.legrange.mikrotik.MikrotikApiException Thrown if there is a problem connecting */ public static ApiConnection connectTLS(String host, int port) throws MikrotikApiException { - return ApiConnectionImpl.connect(host, port, true); + return ApiConnectionImpl.connect(host, port, true, DEFAULT_CONNECTION_TIMEOUT); } @@ -31,7 +31,7 @@ public abstract class ApiConnection { * @throws me.legrange.mikrotik.MikrotikApiException Thrown if there is a problem connecting */ public static ApiConnection connectTLS(String host) throws MikrotikApiException { - return ApiConnectionImpl.connect(host, DEFAULT_TLS_PORT, true); + return ApiConnectionImpl.connect(host, DEFAULT_TLS_PORT, true, DEFAULT_CONNECTION_TIMEOUT); } @@ -43,7 +43,7 @@ public abstract class ApiConnection { * @throws me.legrange.mikrotik.MikrotikApiException Thrown if there is a problem connecting */ public static ApiConnection connect(String host, int port) throws MikrotikApiException { - return ApiConnectionImpl.connect(host, port, false); + return ApiConnectionImpl.connect(host, port, false, DEFAULT_CONNECTION_TIMEOUT); } /** @@ -104,5 +104,7 @@ public abstract class ApiConnection { private static final int DEFAULT_PORT = 8728; /** default TCP TLS port used by Mikrotik API */ private static final int DEFAULT_TLS_PORT = 8729; + /** default connection timeout to use when opening the connection */ + private static final int DEFAULT_CONNECTION_TIMEOUT = 60000; } \ No newline at end of file diff --git a/src/main/java/me/legrange/mikrotik/impl/ApiConnectionImpl.java b/src/main/java/me/legrange/mikrotik/impl/ApiConnectionImpl.java index bee6bcb..b6dff4f 100644 --- a/src/main/java/me/legrange/mikrotik/impl/ApiConnectionImpl.java +++ b/src/main/java/me/legrange/mikrotik/impl/ApiConnectionImpl.java @@ -5,7 +5,9 @@ import java.io.DataOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.Socket; +import java.net.SocketAddress; import java.net.UnknownHostException; import java.util.Arrays; import java.util.LinkedList; @@ -38,9 +40,9 @@ public final class ApiConnectionImpl extends ApiConnection { * @throws me.legrange.mikrotik.ApiConnectionException Thrown if there is a * problem connecting */ - public static ApiConnection connect(String host, int port, boolean secure) throws ApiConnectionException { + public static ApiConnection connect(String host, int port, boolean secure, int timeOut) throws ApiConnectionException { ApiConnectionImpl con = new ApiConnectionImpl(); - con.open(host, port, secure); + con.open(host, port, secure, timeOut); return con; } @@ -123,8 +125,10 @@ public final class ApiConnectionImpl extends ApiConnection { /** * cancel a command + * * @param tag - * @throws me.legrange.mikrotik.MikrotikApiException Thrown if an error is experienced while canceling the + * @throws me.legrange.mikrotik.MikrotikApiException Thrown if an error is + * experienced while canceling the */ @Override public void cancel(String tag) throws MikrotikApiException { @@ -155,23 +159,16 @@ public final class ApiConnectionImpl extends ApiConnection { this.listeners = new ConcurrentHashMap<>(); } - /** - * Start the API. Connects to the Mikrotik without using encryption - */ - private void open(String host, int port) throws ApiConnectionException { - open(host, port, false); - } - /** * Start the API. Connects to the Mikrotik */ - private void open(String host, int port, boolean secure) throws ApiConnectionException { + private void open(String host, int port, boolean secure, int conTimeout) throws ApiConnectionException { try { InetAddress ia = InetAddress.getByName(host.trim()); if (secure) { - sock = openSSLSocket(ia, port); + sock = openSSLSocket(ia, port, conTimeout); } else { - sock = new Socket(ia, port); + sock = openClearSocket(ia, port, conTimeout); } in = new DataInputStream(sock.getInputStream()); out = new DataOutputStream(sock.getOutputStream()); @@ -191,11 +188,19 @@ public final class ApiConnectionImpl extends ApiConnection { } } + private Socket openClearSocket(InetAddress ia, int port, int timeOut) throws IOException { + Socket clear = new Socket(); + SocketAddress addr = new InetSocketAddress(ia, port); + clear.connect(new InetSocketAddress(ia, port), timeOut); + return clear; + } + /** * open and configure a SSL socket. */ - private Socket openSSLSocket(InetAddress ia, int port) throws IOException { - SSLSocket ssl = (SSLSocket) SSLSocketFactory.getDefault().createSocket(ia, port); + private Socket openSSLSocket(InetAddress ia, int port, int timeOut) throws IOException { + SSLSocket ssl = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); + ssl.connect(new InetSocketAddress(ia, port), timeOut); List cs = new LinkedList<>(); // not happy with this code. Without it, SSL throws a "Remote host closed connection during handshake" error // caused by a "SSL peer shut down incorrectly" error @@ -212,7 +217,7 @@ public final class ApiConnectionImpl extends ApiConnection { _tag++; return Integer.toHexString(_tag); } - private static final int DEFAULT_PORT = 8728; + private Socket sock = null; private DataOutputStream out = null; private DataInputStream in = null; @@ -318,15 +323,15 @@ public final class ApiConnectionImpl extends ApiConnection { return !lines.isEmpty() || !reader.isEmpty(); } - private String peekLine() throws ApiConnectionException, ApiDataException { - if (lines.isEmpty()) { + private String peekLine() throws ApiConnectionException, ApiDataException { + if (lines.isEmpty()) { String block = reader.take(); String parts[] = block.split("\n"); lines.addAll(Arrays.asList(parts)); } return lines.get(0); } - + private Response unpack() throws MikrotikApiException { if (line == null) { nextLine(); @@ -340,7 +345,7 @@ public final class ApiConnectionImpl extends ApiConnection { return unpackError(); case "!halt": return unpackError(); - case "" : + case "": System.out.printf("sock.isClosed() = %s, sock.isInputShutdown() = %s\n", sock.isClosed(), sock.isInputShutdown()); default: throw new ApiDataException(String.format("Unexpected line '%s'", line)); @@ -379,8 +384,8 @@ public final class ApiConnectionImpl extends ApiConnection { } return res; } - - private String unpackResult(String first )throws ApiConnectionException, ApiDataException { + + private String unpackResult(String first) throws ApiConnectionException, ApiDataException { StringBuilder buf = new StringBuilder(first); line = null; @@ -390,8 +395,7 @@ public final class ApiConnectionImpl extends ApiConnection { nextLine(); buf.append("\n"); buf.append(line); - } - else { + } else { break; } } @@ -498,7 +502,7 @@ public final class ApiConnectionImpl extends ApiConnection { private List> getResults() throws MikrotikApiException { try { - synchronized (this) { // don't wait if we already have a result. + synchronized (this) { // don't wait if we already have a result. if ((err == null) && results.isEmpty()) { wait(); }