Skip to content

Commit

Permalink
Remove read stdin loop
Browse files Browse the repository at this point in the history
Replaced the Scanner input read loop with upgraded joptsimple
dependency. Cli now takes a single, non-option program argument, runs
it and exits.  Also removed the "stop client" command because there is
no input loop, but shutdown() is called for orderly channel shudown
before the jvm terminates.  Also changed cmd syntax from camel case
to lowercase, mimicking bitcoin-cli.

Configured logback to supress all debug & info level netty output, and
bypassed logback to print results to System.out.
  • Loading branch information
ghubstan committed Mar 27, 2020
1 parent ccde089 commit 94ee49c
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 56 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ configure(subprojects) {
jcsvVersion = '1.4.0'
jetbrainsAnnotationsVersion = '13.0'
jfoenixVersion = '9.0.6'
joptVersion = '5.0.3'
joptVersion = '5.0.4'
jsonsimpleVersion = '1.1.1'
junitVersion = '4.12'
jupiterVersion = '5.3.2'
Expand Down Expand Up @@ -337,6 +337,7 @@ configure(project(':cli')) {

dependencies {
compile project(':proto')
implementation "net.sf.jopt-simple:jopt-simple:$joptVersion"
implementation "com.google.guava:guava:$guavaVersion"
implementation "com.google.protobuf:protobuf-java:$protobufVersion"
implementation("io.grpc:grpc-core:$grpcVersion") {
Expand Down
106 changes: 55 additions & 51 deletions cli/src/main/java/bisq/cli/app/BisqCliMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,22 @@
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

import java.util.ArrayList;
import java.util.Arrays;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;

import java.util.List;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;

import static bisq.cli.app.CommandParser.GETBALANCE;
import static bisq.cli.app.CommandParser.GETVERSION;
import static bisq.cli.app.CommandParser.STOPSERVER;
import static java.lang.String.format;
import static java.lang.System.currentTimeMillis;
import static java.lang.System.exit;
import static java.lang.System.in;
import static java.lang.System.out;

/**
* gRPC client.
Expand All @@ -41,60 +45,28 @@ public class BisqCliMain {

private final ManagedChannel channel;
private final CliCommand cmd;
private final OptionParser cmdParser;

public static void main(String[] args) {
new BisqCliMain("localhost", 8888);
new BisqCliMain("localhost", 8888, args);
}

private BisqCliMain(String host, int port) {
private BisqCliMain(String host, int port, String[] params) {
// Channels are secure by default (via SSL/TLS); for the example disable TLS to avoid needing certificates.
this(ManagedChannelBuilder.forAddress(host, port).usePlaintext().build());

// Simple input scanner
// TODO use some more sophisticated input processing with validation....
try (Scanner scanner = new Scanner(in)) {
while (true) {
long startTs = currentTimeMillis();

String[] tokens = scanner.nextLine().split(" ");
if (tokens.length == 0) {
return;
}
String command = tokens[0];
if (tokens.length > 1) {
List<String> params = new ArrayList<>(Arrays.asList(tokens));
params.remove(0);
}
String result;

switch (command) {
case "getBalance":
long satoshis = cmd.getBalance();
// TODO mimic bitcoin-cli? Depends on an error code: Loading block index... Verifying blocks...
result = satoshis == -1 ? "Server initializing..." : cmd.prettyBalance.apply(satoshis);
break;
case "getVersion":
result = cmd.getVersion();
break;
case "stop":
result = "Shut down client";
try {
shutdown();
} catch (InterruptedException e) {
log.error(e.toString(), e);
}
break;
case "stopServer":
cmd.stopServer();
result = "Server stopped";
break;
default:
result = format("Unknown command '%s'", command);
}

// First response is rather slow (300 ms) but following responses are fast (3-5 ms).
log.info("{}\t{}", result, cmd.responseTime.apply(startTs));
}
long startTs = currentTimeMillis();

String command = parseCommand(params);
String result = runCommand(command);

// First response is rather slow (300 ms) but following responses are fast (3-5 ms).
// log.info("{}\t{}", result, cmd.responseTime.apply(startTs));
out.println(result + "\t" + cmd.responseTime.apply(startTs));

try {
shutdown(); // Orderly channel shutdown
} catch (InterruptedException ignored) {
}
}

Expand All @@ -104,6 +76,38 @@ private BisqCliMain(String host, int port) {
private BisqCliMain(ManagedChannel channel) {
this.channel = channel;
this.cmd = new CliCommand(channel);
this.cmdParser = new CommandParser().configure();
}

private String runCommand(String command) {
final String result;
switch (command) {
case GETBALANCE:
long satoshis = cmd.getBalance();
result = satoshis == -1 ? "Server initializing..." : cmd.prettyBalance.apply(satoshis);
break;
case GETVERSION:
result = cmd.getVersion();
break;
case STOPSERVER:
cmd.stopServer();
result = "Server stopped";
break;
default:
result = format("Unknown command '%s'", command);
}
return result;
}

private String parseCommand(String[] params) {
OptionSpec<String> nonOptions = cmdParser.nonOptions().ofType(String.class);
OptionSet options = cmdParser.parse(params);
List<String> detectedOptions = nonOptions.values(options);
if (detectedOptions.isEmpty()) {
CommandParser.printUsage();
exit(0);
}
return detectedOptions.get(0);
}

private void shutdown() throws InterruptedException {
Expand Down
27 changes: 27 additions & 0 deletions cli/src/main/java/bisq/cli/app/CommandParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package bisq.cli.app;

import joptsimple.OptionParser;

import static java.lang.System.err;

final class CommandParser {

// Option name constants
static final String HELP = "help";
static final String GETBALANCE = "getbalance";
static final String GETVERSION = "getversion";
static final String STOPSERVER = "stopserver";

OptionParser configure() {
OptionParser parser = new OptionParser();
parser.allowsUnrecognizedOptions();
parser.nonOptions(GETBALANCE).ofType(String.class).describedAs("get btc balance");
parser.nonOptions(GETVERSION).ofType(String.class).describedAs("get bisq version");
return parser;
}

static void printUsage() {
err.println("Usage: bisq-cli getbalance | getversion");
}

}
4 changes: 1 addition & 3 deletions cli/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
<appender-ref ref="CONSOLE_APPENDER"/>
</root>

<logger name="io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0" level="WARN"/>
<logger name="io.grpc.netty.shaded.io.netty.util.internal.NativeLibraryLoader" level="WARN"/>
<logger name="io.grpc.netty" level="TRACE"/>
<logger name="io.grpc.netty" level="WARN"/>

</configuration>
2 changes: 1 addition & 1 deletion gradle/witness/gradle-witness.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ dependencyVerification {
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'net.glxn:qrgen:c85d9d8512d91e8ad11fe56259a7825bd50ce0245447e236cf168d1b17591882',
'net.jcip:jcip-annotations:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.sf.jopt-simple:jopt-simple:6f45c00908265947c39221035250024f2caec9a15c1c8cf553ebeecee289f342',
'net.sf.jopt-simple:jopt-simple:df26cc58f235f477db07f753ba5a3ab243ebe5789d9f89ecf68dd62ea9a66c28',
'network.bisq.btcd-cli4j:btcd-cli4j-core:203156fc63dc1202774de9818e4f21149549f79b25d356b08bb0c784be40c0e8',
'network.bisq.btcd-cli4j:btcd-cli4j-daemon:0a2783a851add6e3d8ae899ade48c041b250bfac64b6a4c5f6380ebcdbbe6848',
'org.apache.commons:commons-compress:5f2df1e467825e4cac5996d44890c4201c000b43c0b23cffc0782d28a0beb9b0',
Expand Down

0 comments on commit 94ee49c

Please sign in to comment.