|
8 | 8 | import java.net.*;
|
9 | 9 | import java.nio.file.*;
|
10 | 10 | import java.util.*;
|
| 11 | +import java.util.concurrent.*; |
| 12 | +import java.util.function.*; |
11 | 13 | import java.util.stream.*;
|
12 | 14 |
|
13 | 15 | public class IPFS {
|
@@ -36,6 +38,7 @@ public enum PinType {all, direct, indirect, recursive}
|
36 | 38 | public final File file = new File();
|
37 | 39 | public final Stats stats = new Stats();
|
38 | 40 | public final Name name = new Name();
|
| 41 | + public final Pubsub pubsub = new Pubsub(); |
39 | 42 |
|
40 | 43 | public IPFS(String host, int port) {
|
41 | 44 | this(host, port, "/api/v0/");
|
@@ -217,6 +220,32 @@ public Object gc() throws IOException {
|
217 | 220 | }
|
218 | 221 | }
|
219 | 222 |
|
| 223 | + public class Pubsub { |
| 224 | + public Object ls() throws IOException { |
| 225 | + return retrieveAndParse("pubsub/ls"); |
| 226 | + } |
| 227 | + |
| 228 | + public Object peers() throws IOException { |
| 229 | + return retrieveAndParse("pubsub/peers"); |
| 230 | + } |
| 231 | + |
| 232 | + public Object peers(String topic) throws IOException { |
| 233 | + return retrieveAndParse("pubsub/peers?topic="+topic); |
| 234 | + } |
| 235 | + |
| 236 | + public Object pub(String topic, String data) throws IOException { |
| 237 | + return retrieveAndParse("pubsub/peers?arg="+topic + "&data=" + data); |
| 238 | + } |
| 239 | + |
| 240 | + public Stream<Object> sub(String topic) throws IOException { |
| 241 | + return sub(topic, ForkJoinPool.commonPool()); |
| 242 | + } |
| 243 | + |
| 244 | + public Stream<Object> sub(String topic, ForkJoinPool threadSupplier) throws IOException { |
| 245 | + return retrieveAndParseStream("pubsub/sub?arg="+topic, threadSupplier); |
| 246 | + } |
| 247 | + } |
| 248 | + |
220 | 249 | /* 'ipfs block' is a plumbing command used to manipulate raw ipfs blocks.
|
221 | 250 | */
|
222 | 251 | public class Block {
|
@@ -527,6 +556,12 @@ private Object retrieveAndParse(String path) throws IOException {
|
527 | 556 | return JSONParser.parse(new String(res));
|
528 | 557 | }
|
529 | 558 |
|
| 559 | + private Stream<Object> retrieveAndParseStream(String path, ForkJoinPool executor) throws IOException { |
| 560 | + Queue<byte[]> objects = new LinkedBlockingQueue<>(); |
| 561 | + executor.submit(() -> getObjectStream(path, objects::add)); |
| 562 | + return Stream.generate(() -> JSONParser.parse(new String(objects.poll()))); |
| 563 | + } |
| 564 | + |
530 | 565 | private byte[] retrieve(String path) throws IOException {
|
531 | 566 | URL target = new URL("http", host, port, version + path);
|
532 | 567 | return IPFS.get(target);
|
@@ -554,6 +589,27 @@ private static byte[] get(URL target) throws IOException {
|
554 | 589 | }
|
555 | 590 | }
|
556 | 591 |
|
| 592 | + private void getObjectStream(String path, Consumer<byte[]> processor) { |
| 593 | + byte LINE_FEED = (byte)10; |
| 594 | + |
| 595 | + try { |
| 596 | + InputStream in = retrieveStream(path); |
| 597 | + ByteArrayOutputStream resp = new ByteArrayOutputStream(); |
| 598 | + |
| 599 | + byte[] buf = new byte[4096]; |
| 600 | + int r; |
| 601 | + while ((r = in.read(buf)) >= 0) { |
| 602 | + resp.write(buf, 0, r); |
| 603 | + if (buf[r - 1] == LINE_FEED) { |
| 604 | + processor.accept(resp.toByteArray()); |
| 605 | + resp.reset(); |
| 606 | + } |
| 607 | + } |
| 608 | + } catch (IOException e) { |
| 609 | + e.printStackTrace(); |
| 610 | + } |
| 611 | + } |
| 612 | + |
557 | 613 | private InputStream retrieveStream(String path) throws IOException {
|
558 | 614 | URL target = new URL("http", host, port, version + path);
|
559 | 615 | return IPFS.getStream(target);
|
|
0 commit comments