Working on fix for issue #16

This commit is contained in:
Gideon le Grange 2015-03-29 12:56:23 +02:00
parent 8bde47a9ad
commit 60b1bd16f2
5 changed files with 66 additions and 29 deletions

3
.gitignore vendored
View File

@ -19,3 +19,6 @@ nbactions.xml
.classpath .classpath
.project .project
# Maven
pom.xml.versionsBackup

View File

@ -7,7 +7,7 @@ package examples;
public class Config { 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 USERNAME = "admin";
public static final String PASSWORD = ""; public static final String PASSWORD = "";

View File

@ -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<Map<String, String>> res = con.execute("/user/add name=çãáõ");
for (Map<String, String> r : res) {
System.out.println(r);
}
// con.execute("/ip/firewall/filter/add chain=forward hotspot=!auth protocol=tcp src-port=8000-8084");
}
}

View File

@ -20,7 +20,7 @@ public abstract class ApiConnection {
* @throws me.legrange.mikrotik.MikrotikApiException Thrown if there is a problem connecting * @throws me.legrange.mikrotik.MikrotikApiException Thrown if there is a problem connecting
*/ */
public static ApiConnection connectTLS(String host, int port) throws MikrotikApiException { 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 * @throws me.legrange.mikrotik.MikrotikApiException Thrown if there is a problem connecting
*/ */
public static ApiConnection connectTLS(String host) throws MikrotikApiException { 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 * @throws me.legrange.mikrotik.MikrotikApiException Thrown if there is a problem connecting
*/ */
public static ApiConnection connect(String host, int port) throws MikrotikApiException { 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; private static final int DEFAULT_PORT = 8728;
/** default TCP TLS port used by Mikrotik API */ /** default TCP TLS port used by Mikrotik API */
private static final int DEFAULT_TLS_PORT = 8729; 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;
} }

View File

@ -5,7 +5,9 @@ import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedList; import java.util.LinkedList;
@ -38,9 +40,9 @@ public final class ApiConnectionImpl extends ApiConnection {
* @throws me.legrange.mikrotik.ApiConnectionException Thrown if there is a * @throws me.legrange.mikrotik.ApiConnectionException Thrown if there is a
* problem connecting * 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(); ApiConnectionImpl con = new ApiConnectionImpl();
con.open(host, port, secure); con.open(host, port, secure, timeOut);
return con; return con;
} }
@ -123,8 +125,10 @@ public final class ApiConnectionImpl extends ApiConnection {
/** /**
* cancel a command * cancel a command
*
* @param tag * @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 @Override
public void cancel(String tag) throws MikrotikApiException { public void cancel(String tag) throws MikrotikApiException {
@ -155,23 +159,16 @@ public final class ApiConnectionImpl extends ApiConnection {
this.listeners = new ConcurrentHashMap<>(); 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 * 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 { try {
InetAddress ia = InetAddress.getByName(host.trim()); InetAddress ia = InetAddress.getByName(host.trim());
if (secure) { if (secure) {
sock = openSSLSocket(ia, port); sock = openSSLSocket(ia, port, conTimeout);
} else { } else {
sock = new Socket(ia, port); sock = openClearSocket(ia, port, conTimeout);
} }
in = new DataInputStream(sock.getInputStream()); in = new DataInputStream(sock.getInputStream());
out = new DataOutputStream(sock.getOutputStream()); 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. * open and configure a SSL socket.
*/ */
private Socket openSSLSocket(InetAddress ia, int port) throws IOException { private Socket openSSLSocket(InetAddress ia, int port, int timeOut) throws IOException {
SSLSocket ssl = (SSLSocket) SSLSocketFactory.getDefault().createSocket(ia, port); SSLSocket ssl = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
ssl.connect(new InetSocketAddress(ia, port), timeOut);
List<String> cs = new LinkedList<>(); List<String> cs = new LinkedList<>();
// not happy with this code. Without it, SSL throws a "Remote host closed connection during handshake" error // 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 // caused by a "SSL peer shut down incorrectly" error
@ -212,7 +217,7 @@ public final class ApiConnectionImpl extends ApiConnection {
_tag++; _tag++;
return Integer.toHexString(_tag); return Integer.toHexString(_tag);
} }
private static final int DEFAULT_PORT = 8728;
private Socket sock = null; private Socket sock = null;
private DataOutputStream out = null; private DataOutputStream out = null;
private DataInputStream in = null; private DataInputStream in = null;
@ -318,8 +323,8 @@ public final class ApiConnectionImpl extends ApiConnection {
return !lines.isEmpty() || !reader.isEmpty(); return !lines.isEmpty() || !reader.isEmpty();
} }
private String peekLine() throws ApiConnectionException, ApiDataException { private String peekLine() throws ApiConnectionException, ApiDataException {
if (lines.isEmpty()) { if (lines.isEmpty()) {
String block = reader.take(); String block = reader.take();
String parts[] = block.split("\n"); String parts[] = block.split("\n");
lines.addAll(Arrays.asList(parts)); lines.addAll(Arrays.asList(parts));
@ -340,7 +345,7 @@ public final class ApiConnectionImpl extends ApiConnection {
return unpackError(); return unpackError();
case "!halt": case "!halt":
return unpackError(); return unpackError();
case "" : case "":
System.out.printf("sock.isClosed() = %s, sock.isInputShutdown() = %s\n", sock.isClosed(), sock.isInputShutdown()); System.out.printf("sock.isClosed() = %s, sock.isInputShutdown() = %s\n", sock.isClosed(), sock.isInputShutdown());
default: default:
throw new ApiDataException(String.format("Unexpected line '%s'", line)); throw new ApiDataException(String.format("Unexpected line '%s'", line));
@ -380,7 +385,7 @@ public final class ApiConnectionImpl extends ApiConnection {
return res; return res;
} }
private String unpackResult(String first )throws ApiConnectionException, ApiDataException { private String unpackResult(String first) throws ApiConnectionException, ApiDataException {
StringBuilder buf = new StringBuilder(first); StringBuilder buf = new StringBuilder(first);
line = null; line = null;
@ -390,8 +395,7 @@ public final class ApiConnectionImpl extends ApiConnection {
nextLine(); nextLine();
buf.append("\n"); buf.append("\n");
buf.append(line); buf.append(line);
} } else {
else {
break; break;
} }
} }