Some small cleanups and refactoring. Fixed minor potential concurrency issue
This commit is contained in:
parent
a111646c1f
commit
2e431894bf
|
|
@ -17,6 +17,7 @@ public abstract class ApiConnection {
|
||||||
* @param host The host to which to connect.
|
* @param host The host to which to connect.
|
||||||
* @param port The TCP port to use.
|
* @param port The TCP port to use.
|
||||||
* @return The ApiConnection
|
* @return The ApiConnection
|
||||||
|
* @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);
|
||||||
|
|
@ -27,6 +28,7 @@ public abstract class ApiConnection {
|
||||||
* Create a new API connection to the give device on the default API port, using anonymous TLS for encryption.
|
* Create a new API connection to the give device on the default API port, using anonymous TLS for encryption.
|
||||||
* @param host The host to which to connect.
|
* @param host The host to which to connect.
|
||||||
* @return The ApiConnection
|
* @return The ApiConnection
|
||||||
|
* @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);
|
||||||
|
|
@ -38,6 +40,7 @@ public abstract class ApiConnection {
|
||||||
* @param host The host to which to connect.
|
* @param host The host to which to connect.
|
||||||
* @param port The TCP port to use.
|
* @param port The TCP port to use.
|
||||||
* @return The ApiConnection
|
* @return The ApiConnection
|
||||||
|
* @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);
|
||||||
|
|
@ -47,6 +50,7 @@ public abstract class ApiConnection {
|
||||||
* Create a new API connection to the give device on the default API port.
|
* Create a new API connection to the give device on the default API port.
|
||||||
* @param host The host to which to connect.
|
* @param host The host to which to connect.
|
||||||
* @return The ApiConnection
|
* @return The ApiConnection
|
||||||
|
* @throws me.legrange.mikrotik.MikrotikApiException Thrown if there is a problem connecting
|
||||||
*/
|
*/
|
||||||
public static ApiConnection connect(String host) throws MikrotikApiException {
|
public static ApiConnection connect(String host) throws MikrotikApiException {
|
||||||
return connect(host, DEFAULT_PORT);
|
return connect(host, DEFAULT_PORT);
|
||||||
|
|
@ -61,6 +65,7 @@ public abstract class ApiConnection {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnect from the remote API
|
* Disconnect from the remote API
|
||||||
|
* @throws me.legrange.mikrotik.MikrotikApiException Thrown if there is a problem disconnecting
|
||||||
*/
|
*/
|
||||||
public abstract void disconnect() throws MikrotikApiException;
|
public abstract void disconnect() throws MikrotikApiException;
|
||||||
|
|
||||||
|
|
@ -69,12 +74,15 @@ public abstract class ApiConnection {
|
||||||
*
|
*
|
||||||
* @param username - username of the user on the router
|
* @param username - username of the user on the router
|
||||||
* @param password - password for the user
|
* @param password - password for the user
|
||||||
|
* @throws me.legrange.mikrotik.MikrotikApiException
|
||||||
|
* @throws java.lang.InterruptedException
|
||||||
*/
|
*/
|
||||||
public abstract void login(String username, String password) throws MikrotikApiException, InterruptedException;
|
public abstract void login(String username, String password) throws MikrotikApiException, InterruptedException;
|
||||||
|
|
||||||
/** execute a command and return a list of results.
|
/** execute a command and return a list of results.
|
||||||
* @param cmd Command to execute
|
* @param cmd Command to execute
|
||||||
* @return The list of results
|
* @return The list of results
|
||||||
|
* @throws me.legrange.mikrotik.MikrotikApiException
|
||||||
*/
|
*/
|
||||||
public abstract List<Map<String, String>> execute(String cmd) throws MikrotikApiException;
|
public abstract List<Map<String, String>> execute(String cmd) throws MikrotikApiException;
|
||||||
|
|
||||||
|
|
@ -87,7 +95,9 @@ public abstract class ApiConnection {
|
||||||
*/
|
*/
|
||||||
public abstract String execute(String cmd, ResultListener lis) throws MikrotikApiException;
|
public abstract String execute(String cmd, ResultListener lis) throws MikrotikApiException;
|
||||||
|
|
||||||
/** cancel a command */
|
/** cancel a command
|
||||||
|
* @param tag The tag of the command to cancel
|
||||||
|
* @throws me.legrange.mikrotik.MikrotikApiException Thrown if there is a problem canceling the command */
|
||||||
public abstract void cancel(String tag) throws MikrotikApiException;
|
public abstract void cancel(String tag) throws MikrotikApiException;
|
||||||
|
|
||||||
/** default TCP port used by Mikrotik API */
|
/** default TCP port used by Mikrotik API */
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ import me.legrange.mikrotik.MikrotikApiException;
|
||||||
public class ApiCommandException extends MikrotikApiException {
|
public class ApiCommandException extends MikrotikApiException {
|
||||||
|
|
||||||
|
|
||||||
/** return the tag associated with this exception, if there is one */
|
/** return the tag associated with this exception, if there is one
|
||||||
|
* @return the tag associated with this exception. Null if there is no tag*/
|
||||||
public String getTag() {
|
public String getTag() {
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package me.legrange.mikrotik.impl;
|
package me.legrange.mikrotik.impl;
|
||||||
|
|
||||||
import me.legrange.mikrotik.*;
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -9,14 +8,17 @@ import java.net.InetAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import javax.net.ssl.SSLSocket;
|
import javax.net.ssl.SSLSocket;
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
//import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import me.legrange.mikrotik.ApiConnection;
|
||||||
|
import me.legrange.mikrotik.ApiConnectionException;
|
||||||
|
import me.legrange.mikrotik.MikrotikApiException;
|
||||||
|
import me.legrange.mikrotik.ResultListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Mikrotik API connection implementation. This is the class used to connect
|
* The Mikrotik API connection implementation. This is the class used to connect
|
||||||
|
|
@ -77,12 +79,15 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
*
|
*
|
||||||
* @param username - username of the user on the router
|
* @param username - username of the user on the router
|
||||||
* @param password - password for the user
|
* @param password - password for the user
|
||||||
|
* @throws me.legrange.mikrotik.MikrotikApiException
|
||||||
|
* @throws java.lang.InterruptedException
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void login(String username, String password) throws MikrotikApiException, InterruptedException {
|
public void login(String username, String password) throws MikrotikApiException, InterruptedException {
|
||||||
List<Map<String, String>> list = execute("/login");
|
List<Map<String, String>> list = execute("/login");
|
||||||
Map<String, String> res = list.get(0);
|
Map<String, String> res = list.get(0);
|
||||||
String hash = res.get("ret");
|
String hash = res.get("ret");
|
||||||
String chal = Util.hexStrToStr("00") + new String(makePass(password)) + Util.hexStrToStr(hash);
|
String chal = Util.hexStrToStr("00") + new String(password.toCharArray()) + Util.hexStrToStr(hash);
|
||||||
chal = Util.hashMD5(chal);
|
chal = Util.hashMD5(chal);
|
||||||
execute("/login name=" + username + " response=00" + chal);
|
execute("/login name=" + username + " response=00" + chal);
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +97,9 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
*
|
*
|
||||||
* @param cmd Command to execute
|
* @param cmd Command to execute
|
||||||
* @return The list of results
|
* @return The list of results
|
||||||
|
* @throws me.legrange.mikrotik.MikrotikApiException
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public List<Map<String, String>> execute(String cmd) throws MikrotikApiException {
|
public List<Map<String, String>> execute(String cmd) throws MikrotikApiException {
|
||||||
return execute(Parser.parse(cmd));
|
return execute(Parser.parse(cmd));
|
||||||
}
|
}
|
||||||
|
|
@ -105,13 +112,17 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
* @return A command object that can be used to cancel the command.
|
* @return A command object that can be used to cancel the command.
|
||||||
* @throws MikrotikApiException
|
* @throws MikrotikApiException
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String execute(String cmd, ResultListener lis) throws MikrotikApiException {
|
public String execute(String cmd, ResultListener lis) throws MikrotikApiException {
|
||||||
return execute(Parser.parse(cmd), lis);
|
return execute(Parser.parse(cmd), lis);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cancel a command
|
* cancel a command
|
||||||
|
* @param tag
|
||||||
|
* @throws me.legrange.mikrotik.MikrotikApiException Thrown if an error is experienced while canceling the
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void cancel(String tag) throws MikrotikApiException {
|
public void cancel(String tag) throws MikrotikApiException {
|
||||||
execute(String.format("/cancel tag=%s", tag));
|
execute(String.format("/cancel tag=%s", tag));
|
||||||
}
|
}
|
||||||
|
|
@ -137,6 +148,7 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiConnectionImpl() {
|
private ApiConnectionImpl() {
|
||||||
|
this.listeners = new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -180,7 +192,7 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
*/
|
*/
|
||||||
private Socket openSSLSocket(InetAddress ia, int port) throws IOException {
|
private Socket openSSLSocket(InetAddress ia, int port) throws IOException {
|
||||||
SSLSocket ssl = (SSLSocket) SSLSocketFactory.getDefault().createSocket(ia, port);
|
SSLSocket ssl = (SSLSocket) SSLSocketFactory.getDefault().createSocket(ia, port);
|
||||||
List<String> cs = new LinkedList<String>();
|
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
|
||||||
for (String s : ssl.getSupportedCipherSuites()) {
|
for (String s : ssl.getSupportedCipherSuites()) {
|
||||||
|
|
@ -192,16 +204,6 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
return ssl;
|
return ssl;
|
||||||
}
|
}
|
||||||
|
|
||||||
private char[] makePass(String pass) {
|
|
||||||
if (true) {
|
|
||||||
return pass.toCharArray();
|
|
||||||
}
|
|
||||||
char[] res = new char[pass.length() + 1];
|
|
||||||
System.arraycopy(pass.toCharArray(), 0, res, 0, pass.length());
|
|
||||||
res[pass.length()] = 0x0;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized String nextTag() {
|
private synchronized String nextTag() {
|
||||||
_tag++;
|
_tag++;
|
||||||
return Integer.toHexString(_tag);
|
return Integer.toHexString(_tag);
|
||||||
|
|
@ -213,7 +215,7 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
private boolean connected = false;
|
private boolean connected = false;
|
||||||
private Reader reader;
|
private Reader reader;
|
||||||
private Processor processor;
|
private Processor processor;
|
||||||
private final Map<String, ResultListener> listeners = new HashMap<String, ResultListener>();
|
private final Map<String, ResultListener> listeners;
|
||||||
private Integer _tag = 0;
|
private Integer _tag = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -253,12 +255,11 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
queue.put(ex);
|
queue.put(ex);
|
||||||
} catch (InterruptedException ex2) {
|
} catch (InterruptedException ex2) {
|
||||||
}
|
}
|
||||||
} catch (ApiConnectionException ex) {
|
} catch (ApiConnectionException | InterruptedException ex) {
|
||||||
} catch (InterruptedException ex1) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private LinkedBlockingQueue queue = new LinkedBlockingQueue(40);
|
private final LinkedBlockingQueue queue = new LinkedBlockingQueue(40);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -280,7 +281,6 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} catch (MikrotikApiException ex) {
|
} catch (MikrotikApiException ex) {
|
||||||
ex.printStackTrace();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ResultListener l = listeners.get(res.getTag());
|
ResultListener l = listeners.get(res.getTag());
|
||||||
|
|
@ -443,17 +443,19 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private List<String> lines = new LinkedList<String>();
|
private final List<String> lines = new LinkedList<>();
|
||||||
private String line;
|
private String line;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SyncListener implements ResultListener {
|
private class SyncListener implements ResultListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
public synchronized void error(MikrotikApiException ex) {
|
public synchronized void error(MikrotikApiException ex) {
|
||||||
this.err = ex;
|
this.err = ex;
|
||||||
notify();
|
notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public synchronized void completed() {
|
public synchronized void completed() {
|
||||||
notify();
|
notify();
|
||||||
}
|
}
|
||||||
|
|
@ -467,6 +469,7 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
notify();
|
notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void receive(Map<String, String> result) {
|
public void receive(Map<String, String> result) {
|
||||||
results.add(result);
|
results.add(result);
|
||||||
}
|
}
|
||||||
|
|
@ -486,7 +489,7 @@ public final class ApiConnectionImpl extends ApiConnection {
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
private List<Map<String, String>> results = new LinkedList<Map<String, String>>();
|
private final List<Map<String, String>> results = new LinkedList<>();
|
||||||
private MikrotikApiException err;
|
private MikrotikApiException err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,9 @@ class Command {
|
||||||
List<Parameter> getParameters() {
|
List<Parameter> getParameters() {
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
private String cmd;
|
private final String cmd;
|
||||||
private List<Parameter> params = new LinkedList<Parameter>();
|
private final List<Parameter> params = new LinkedList<>();
|
||||||
private List<String> queries = new LinkedList<String>();
|
private final List<String> queries = new LinkedList<>();
|
||||||
private List<String> properties = new LinkedList<String>();
|
private final List<String> properties = new LinkedList<>();
|
||||||
private String tag;
|
private String tag;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ class Result extends Response implements Map<String, String> {
|
||||||
return map.get(key);
|
return map.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return map.isEmpty();
|
return map.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
@ -24,53 +25,64 @@ class Result extends Response implements Map<String, String> {
|
||||||
return String.format("tag=%s, data=%s", getTag(), map);
|
return String.format("tag=%s, data=%s", getTag(), map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return map.size();
|
return map.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean containsKey(Object o) {
|
public boolean containsKey(Object o) {
|
||||||
return map.containsKey(o);
|
return map.containsKey(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean containsValue(Object o) {
|
public boolean containsValue(Object o) {
|
||||||
return map.containsValue(o);
|
return map.containsValue(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String get(Object o) {
|
public String get(Object o) {
|
||||||
return map.get(o);
|
return map.get(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String put(String k, String v) {
|
public String put(String k, String v) {
|
||||||
return map.put(k, v);
|
return map.put(k, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String remove(Object o) {
|
public String remove(Object o) {
|
||||||
return map.remove(o);
|
return map.remove(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void putAll(Map<? extends String, ? extends String> map) {
|
public void putAll(Map<? extends String, ? extends String> map) {
|
||||||
this.map.putAll(map);
|
this.map.putAll(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
map.clear();
|
map.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Set<String> keySet() {
|
public Set<String> keySet() {
|
||||||
return map.keySet();
|
return map.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Collection<String> values() {
|
public Collection<String> values() {
|
||||||
return map.values();
|
return map.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Set<Entry<String, String>> entrySet() {
|
public Set<Entry<String, String>> entrySet() {
|
||||||
return map.entrySet();
|
return map.entrySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result() {
|
Result() {
|
||||||
super(null);
|
super(null);
|
||||||
this.map = new HashMap<String, String>();
|
this.map = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String, String> map;
|
private final Map<String, String> map;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package me.legrange.mikrotik.impl;
|
package me.legrange.mikrotik.impl;
|
||||||
|
|
||||||
import me.legrange.mikrotik.MikrotikApiException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown if the scanner encounters an error while scanning a command line.
|
* Exception thrown if the scanner encounters an error while scanning a command line.
|
||||||
* @author GideonLeGrange
|
* @author GideonLeGrange
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue