mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-21 14:07:53 +00:00
Refactor Java API
Add stateful class to represent the state of the serval daemon, shifting some functions from BatPhone Add convenience functions to get pre-configured MDP and HTTP Restful client classes
This commit is contained in:
parent
47f051917d
commit
68dbaef38d
@ -12,8 +12,8 @@ public abstract class AbstractMdpProtocol<T> extends ChannelSelector.Handler {
|
||||
protected final MdpSocket socket;
|
||||
protected final AsyncResult<T> results;
|
||||
|
||||
public AbstractMdpProtocol(ChannelSelector selector, AsyncResult<T> results) throws IOException {
|
||||
socket = new MdpSocket();
|
||||
public AbstractMdpProtocol(ChannelSelector selector, int loopbackMdpPort, AsyncResult<T> results) throws IOException {
|
||||
this.socket = new MdpSocket(loopbackMdpPort);
|
||||
socket.bind();
|
||||
this.selector = selector;
|
||||
this.results = results;
|
||||
|
@ -7,8 +7,8 @@ import java.io.IOException;
|
||||
*/
|
||||
public class MdpDnaLookup extends AbstractMdpProtocol<ServalDCommand.LookupResult> {
|
||||
|
||||
public MdpDnaLookup(ChannelSelector selector, AsyncResult<ServalDCommand.LookupResult> results) throws IOException {
|
||||
super(selector, results);
|
||||
public MdpDnaLookup(ChannelSelector selector, int loopbackMdpPort, AsyncResult<ServalDCommand.LookupResult> results) throws IOException {
|
||||
super(selector, loopbackMdpPort, results);
|
||||
}
|
||||
|
||||
public void sendRequest(SubscriberId destination, String did) throws IOException {
|
||||
|
@ -21,8 +21,8 @@ public class MdpServiceLookup extends AbstractMdpProtocol<MdpServiceLookup.Servi
|
||||
}
|
||||
}
|
||||
|
||||
public MdpServiceLookup(ChannelSelector selector, AsyncResult<ServiceResult> results) throws IOException {
|
||||
super(selector, results);
|
||||
public MdpServiceLookup(ChannelSelector selector, int loopbackMdpPort, AsyncResult<ServiceResult> results) throws IOException {
|
||||
super(selector, loopbackMdpPort, results);
|
||||
}
|
||||
|
||||
public void sendRequest(SubscriberId destination, String pattern) throws IOException {
|
||||
|
@ -17,10 +17,11 @@ public class MdpSocket{
|
||||
private int port;
|
||||
|
||||
private static final InetAddress loopback;
|
||||
public static int loopbackMdpPort =0;
|
||||
private final int loopbackMdpPort;
|
||||
static {
|
||||
InetAddress local=null;
|
||||
try {
|
||||
// can't trust Inet4Address.getLocalHost() as some implementations can fail to resolve the name "loopback"
|
||||
local = Inet4Address.getByAddress(new byte[]{127, 0, 0, 1});
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
@ -29,12 +30,15 @@ public class MdpSocket{
|
||||
}
|
||||
|
||||
/* Create an unbound socket, may be used for other information requests before binding */
|
||||
public MdpSocket() throws IOException {
|
||||
public MdpSocket(int loopbackMdpPort) throws IOException {
|
||||
this.loopbackMdpPort = loopbackMdpPort;
|
||||
}
|
||||
public MdpSocket(int port) throws IOException {
|
||||
public MdpSocket(int loopbackMdpPort, int port) throws IOException {
|
||||
this(loopbackMdpPort);
|
||||
bind(SubscriberId.ANY, port);
|
||||
}
|
||||
public MdpSocket(SubscriberId sid, int port) throws IOException {
|
||||
public MdpSocket(int loopbackMdpPort, SubscriberId sid, int port) throws IOException {
|
||||
this(loopbackMdpPort);
|
||||
bind(sid, port);
|
||||
}
|
||||
|
||||
|
@ -20,72 +20,33 @@
|
||||
|
||||
package org.servalproject.servaldna;
|
||||
|
||||
import org.servalproject.codec.Base64;
|
||||
import org.servalproject.servaldna.meshms.MeshMSConversationList;
|
||||
import org.servalproject.servaldna.meshms.MeshMSException;
|
||||
import org.servalproject.servaldna.meshms.MeshMSMessageList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.HttpURLConnection;
|
||||
import org.servalproject.codec.Base64;
|
||||
import org.servalproject.servaldna.SubscriberId;
|
||||
import org.servalproject.servaldna.ServalDCommand;
|
||||
import org.servalproject.servaldna.ServalDInterfaceException;
|
||||
import org.servalproject.servaldna.meshms.MeshMSConversationList;
|
||||
import org.servalproject.servaldna.meshms.MeshMSMessageList;
|
||||
import org.servalproject.servaldna.meshms.MeshMSException;
|
||||
|
||||
public class ServalDClient implements ServalDHttpConnectionFactory
|
||||
{
|
||||
private final int httpPort;
|
||||
private final String restfulUsername;
|
||||
private final String restfulPassword;
|
||||
|
||||
private static final String restfulUsername = "ServalDClient";
|
||||
private static final String restfulPasswordDefault = "u6ng^ues%@@SabLEEEE8";
|
||||
private static String restfulPassword;
|
||||
protected boolean connected;
|
||||
int httpPort;
|
||||
|
||||
public static ServalDClient newServalDClient()
|
||||
{
|
||||
return new ServalDClient();
|
||||
}
|
||||
|
||||
protected ServalDClient()
|
||||
{
|
||||
restfulPassword = null;
|
||||
connected = false;
|
||||
httpPort = 0;
|
||||
}
|
||||
|
||||
private void connect() throws ServalDInterfaceException
|
||||
{
|
||||
ensureServerRunning();
|
||||
if (!connected) {
|
||||
if (!fetchRestfulAuthorization())
|
||||
createRestfulAuthorization();
|
||||
connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureServerRunning() throws ServalDInterfaceException
|
||||
{
|
||||
ServalDCommand.Status s = ServalDCommand.serverStatus();
|
||||
if (!s.status.equals("running"))
|
||||
throw new ServalDInterfaceException("server is not running");
|
||||
if (s.httpPort < 1 || s.httpPort > 65535)
|
||||
throw new ServalDInterfaceException("invalid HTTP port number: " + s.httpPort);
|
||||
httpPort = s.httpPort;
|
||||
}
|
||||
|
||||
private boolean fetchRestfulAuthorization() throws ServalDInterfaceException
|
||||
{
|
||||
restfulPassword = ServalDCommand.getConfigItem("rhizome.api.restful.users." + restfulUsername + ".password");
|
||||
return restfulPassword != null;
|
||||
}
|
||||
|
||||
private void createRestfulAuthorization() throws ServalDInterfaceException
|
||||
{
|
||||
ServalDCommand.setConfigItem("rhizome.api.restful.users." + restfulUsername + ".password", restfulPasswordDefault);
|
||||
ServalDCommand.configSync();
|
||||
if (!fetchRestfulAuthorization())
|
||||
throw new ServalDInterfaceException("restful password not set");
|
||||
public ServalDClient(int httpPort, String restfulUsername, String restfulPassword) throws ServalDInterfaceException {
|
||||
if (httpPort < 1 || httpPort > 65535)
|
||||
throw new ServalDInterfaceException("invalid HTTP port number: " + httpPort);
|
||||
if (restfulUsername == null)
|
||||
throw new ServalDInterfaceException("invalid HTTP username");
|
||||
if (restfulPassword == null)
|
||||
throw new ServalDInterfaceException("invalid HTTP password");
|
||||
this.httpPort = httpPort;
|
||||
this.restfulUsername = restfulUsername;
|
||||
this.restfulPassword = restfulPassword;
|
||||
}
|
||||
|
||||
public MeshMSConversationList meshmsListConversations(SubscriberId sid) throws ServalDInterfaceException, IOException, MeshMSException
|
||||
@ -105,9 +66,6 @@ public class ServalDClient implements ServalDHttpConnectionFactory
|
||||
// interface ServalDHttpConnectionFactory
|
||||
public HttpURLConnection newServalDHttpConnection(String path) throws ServalDInterfaceException, IOException
|
||||
{
|
||||
connect();
|
||||
assert restfulPassword != null;
|
||||
assert httpPort != 0;
|
||||
URL url = new URL("http", "localhost", httpPort, path);
|
||||
URLConnection uconn = url.openConnection();
|
||||
HttpURLConnection conn;
|
||||
@ -117,7 +75,6 @@ public class ServalDClient implements ServalDHttpConnectionFactory
|
||||
catch (ClassCastException e) {
|
||||
throw new ServalDInterfaceException("URL.openConnection() returned a " + uconn.getClass().getName() + ", expecting a HttpURLConnection", e);
|
||||
}
|
||||
int status = 0;
|
||||
conn.setAllowUserInteraction(false);
|
||||
try {
|
||||
conn.addRequestProperty("Authorization", "Basic " + Base64.encode((restfulUsername + ":" + restfulPassword).getBytes("US-ASCII")));
|
||||
|
109
java/org/servalproject/servaldna/ServerControl.java
Normal file
109
java/org/servalproject/servaldna/ServerControl.java
Normal file
@ -0,0 +1,109 @@
|
||||
package org.servalproject.servaldna;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* Created by jeremy on 20/06/14.
|
||||
*/
|
||||
public class ServerControl {
|
||||
private String instancePath;
|
||||
private final String execPath;
|
||||
private int loopbackMdpPort;
|
||||
private int httpPort=0;
|
||||
private int pid;
|
||||
private static final String restfulUsername="ServalDClient";
|
||||
private ServalDClient client;
|
||||
|
||||
public ServerControl(){
|
||||
this(null);
|
||||
}
|
||||
public ServerControl(String execPath){
|
||||
this.execPath = execPath;
|
||||
}
|
||||
|
||||
public String getInstancePath(){
|
||||
return instancePath;
|
||||
}
|
||||
|
||||
private void setStatus(ServalDCommand.Status result){
|
||||
loopbackMdpPort = result.mdpInetPort;
|
||||
pid = result.pid;
|
||||
httpPort = result.httpPort;
|
||||
instancePath = result.instancePath;
|
||||
}
|
||||
|
||||
private void clearStatus(){
|
||||
loopbackMdpPort = 0;
|
||||
pid = 0;
|
||||
httpPort = 0;
|
||||
client = null;
|
||||
}
|
||||
|
||||
public void start() throws ServalDFailureException {
|
||||
if (execPath==null)
|
||||
setStatus(ServalDCommand.serverStart());
|
||||
else
|
||||
setStatus(ServalDCommand.serverStart(execPath));
|
||||
}
|
||||
|
||||
public void stop() throws ServalDFailureException {
|
||||
try{
|
||||
ServalDCommand.serverStop();
|
||||
}finally{
|
||||
clearStatus();
|
||||
}
|
||||
}
|
||||
|
||||
public void restart() throws ServalDFailureException {
|
||||
try {
|
||||
stop();
|
||||
} catch (ServalDFailureException e) {
|
||||
// ignore failures, at least we tried...
|
||||
e.printStackTrace();
|
||||
}
|
||||
start();
|
||||
}
|
||||
|
||||
public boolean isRunning() throws ServalDFailureException {
|
||||
ServalDCommand.Status s = ServalDCommand.serverStatus();
|
||||
|
||||
if (s.status.equals("running")) {
|
||||
setStatus(s);
|
||||
}else{
|
||||
clearStatus();
|
||||
}
|
||||
return pid!=0;
|
||||
}
|
||||
|
||||
public MdpServiceLookup getMdpService(ChannelSelector selector, AsyncResult<MdpServiceLookup.ServiceResult> results) throws ServalDInterfaceException, IOException {
|
||||
if (!isRunning())
|
||||
throw new ServalDInterfaceException("server is not running");
|
||||
return new MdpServiceLookup(selector, this.loopbackMdpPort, results);
|
||||
}
|
||||
|
||||
public MdpDnaLookup getMdpDnaLookup(ChannelSelector selector, AsyncResult<ServalDCommand.LookupResult> results) throws ServalDInterfaceException, IOException {
|
||||
if (!isRunning())
|
||||
throw new ServalDInterfaceException("server is not running");
|
||||
return new MdpDnaLookup(selector, this.loopbackMdpPort, results);
|
||||
}
|
||||
|
||||
public ServalDClient getRestfulClient() throws ServalDInterfaceException {
|
||||
if (!isRunning())
|
||||
throw new ServalDInterfaceException("server is not running");
|
||||
if (client==null) {
|
||||
String restfulPassword = ServalDCommand.getConfigItem("rhizome.api.restful.users." + restfulUsername + ".password");
|
||||
if (restfulPassword == null) {
|
||||
String pwd = new BigInteger(130, new SecureRandom()).toString(32);
|
||||
ServalDCommand.setConfigItem("rhizome.api.restful.users." + restfulUsername + ".password", pwd);
|
||||
ServalDCommand.configSync();
|
||||
restfulPassword = ServalDCommand.getConfigItem("rhizome.api.restful.users." + restfulUsername + ".password");
|
||||
if (restfulPassword == null)
|
||||
throw new ServalDInterfaceException("Failed to set restful password");
|
||||
}
|
||||
client = new ServalDClient(this.httpPort, restfulUsername, restfulPassword);
|
||||
}
|
||||
return client;
|
||||
}
|
||||
}
|
@ -4,10 +4,11 @@ import org.servalproject.servaldna.AsyncResult;
|
||||
import org.servalproject.servaldna.ChannelSelector;
|
||||
import org.servalproject.servaldna.MdpDnaLookup;
|
||||
import org.servalproject.servaldna.MdpServiceLookup;
|
||||
import org.servalproject.servaldna.MdpSocket;
|
||||
import org.servalproject.servaldna.ResultList;
|
||||
import org.servalproject.servaldna.ServalDCommand;
|
||||
import org.servalproject.servaldna.ServalDFailureException;
|
||||
import org.servalproject.servaldna.ServalDInterfaceException;
|
||||
import org.servalproject.servaldna.ServerControl;
|
||||
import org.servalproject.servaldna.SubscriberId;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -34,14 +35,8 @@ public class CommandLine {
|
||||
}
|
||||
}
|
||||
|
||||
static void lookup(String did) throws IOException, InterruptedException, ServalDFailureException {
|
||||
ServalDCommand.Status s = ServalDCommand.serverStatus();
|
||||
System.out.println(s);
|
||||
if (s.getResult()!=0)
|
||||
throw new ServalDFailureException("Serval daemon isn't running");
|
||||
MdpSocket.loopbackMdpPort = s.mdpInetPort;
|
||||
ChannelSelector selector = new ChannelSelector();
|
||||
MdpDnaLookup lookup = new MdpDnaLookup(selector, new AsyncResult<ServalDCommand.LookupResult>() {
|
||||
static void lookup(String did) throws IOException, InterruptedException, ServalDInterfaceException {
|
||||
MdpDnaLookup lookup = new ServerControl().getMdpDnaLookup(new ChannelSelector(), new AsyncResult<ServalDCommand.LookupResult>() {
|
||||
@Override
|
||||
public void result(ServalDCommand.LookupResult nextResult) {
|
||||
System.out.println(nextResult.toString());
|
||||
@ -52,14 +47,8 @@ public class CommandLine {
|
||||
lookup.close();
|
||||
}
|
||||
|
||||
static void service(String pattern) throws IOException, InterruptedException, ServalDFailureException {
|
||||
ServalDCommand.Status s = ServalDCommand.serverStatus();
|
||||
System.out.println(s);
|
||||
if (s.getResult()!=0)
|
||||
throw new ServalDFailureException("Serval daemon isn't running");
|
||||
MdpSocket.loopbackMdpPort = s.mdpInetPort;
|
||||
ChannelSelector selector = new ChannelSelector();
|
||||
MdpServiceLookup lookup = new MdpServiceLookup(selector, new AsyncResult<MdpServiceLookup.ServiceResult>() {
|
||||
static void service(String pattern) throws IOException, InterruptedException, ServalDInterfaceException {
|
||||
MdpServiceLookup lookup = new ServerControl().getMdpService(new ChannelSelector(), new AsyncResult<MdpServiceLookup.ServiceResult>() {
|
||||
@Override
|
||||
public void result(MdpServiceLookup.ServiceResult nextResult) {
|
||||
System.out.println(nextResult.toString());
|
||||
|
@ -20,23 +20,23 @@
|
||||
|
||||
package org.servalproject.test;
|
||||
|
||||
import java.lang.System;
|
||||
import java.io.IOException;
|
||||
import org.servalproject.servaldna.SubscriberId;
|
||||
|
||||
import org.servalproject.servaldna.ServalDClient;
|
||||
import org.servalproject.servaldna.ServalDInterfaceException;
|
||||
import org.servalproject.servaldna.meshms.MeshMSConversationList;
|
||||
import org.servalproject.servaldna.ServerControl;
|
||||
import org.servalproject.servaldna.SubscriberId;
|
||||
import org.servalproject.servaldna.meshms.MeshMSConversation;
|
||||
import org.servalproject.servaldna.meshms.MeshMSMessageList;
|
||||
import org.servalproject.servaldna.meshms.MeshMSMessage;
|
||||
import org.servalproject.servaldna.meshms.MeshMSConversationList;
|
||||
import org.servalproject.servaldna.meshms.MeshMSException;
|
||||
import org.servalproject.servaldna.meshms.MeshMSMessage;
|
||||
import org.servalproject.servaldna.meshms.MeshMSMessageList;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class Meshms {
|
||||
|
||||
static void meshms_list_conversations(SubscriberId sid) throws ServalDInterfaceException, IOException, InterruptedException
|
||||
{
|
||||
ServalDClient client = ServalDClient.newServalDClient();
|
||||
ServalDClient client = new ServerControl().getRestfulClient();
|
||||
MeshMSConversationList list = null;
|
||||
try {
|
||||
list = client.meshmsListConversations(sid);
|
||||
@ -64,7 +64,7 @@ public class Meshms {
|
||||
|
||||
static void meshms_list_messages(SubscriberId sid1, SubscriberId sid2) throws ServalDInterfaceException, IOException, InterruptedException
|
||||
{
|
||||
ServalDClient client = ServalDClient.newServalDClient();
|
||||
ServalDClient client = new ServerControl().getRestfulClient();
|
||||
MeshMSMessageList list = null;
|
||||
try {
|
||||
list = client.meshmsListMessages(sid1, sid2);
|
||||
|
@ -32,11 +32,6 @@ setup() {
|
||||
set log.console.level debug \
|
||||
set debug.httpd on
|
||||
create_identities 4
|
||||
configure_servald_server() {
|
||||
add_servald_interface
|
||||
executeOk_servald config \
|
||||
set rhizome.api.restful.users.joe.password bloggs
|
||||
}
|
||||
start_servald_server
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user