From a14606b390e3337a3bd23c1ebc39ed27e13488ed Mon Sep 17 00:00:00 2001 From: jonny rhea Date: Fri, 23 Nov 2018 21:54:27 -0600 Subject: [PATCH 1/7] - added build option for an .so and generation of jni source for java. added some additional functionality to the goclient to test the java daemon - added a gitignore and updated the import paths --- .gitignore | 20 ++++++ Makefile | 41 ++++++++++-- daemon.go | 12 ++++ p2pclient/{ => go}/dht.go | 0 p2pclient/{ => go}/p2pclient.go | 2 +- p2pclient/{ => go}/streams.go | 0 p2pclient/java/p2pd.c | 13 ++++ p2pclient/java/p2pd.java | 18 ++++++ p2pd/main.go | 110 +++++++++++++++++++++++++++++++- test/dht_test.go | 2 +- test/integration_test.go | 2 +- test/mock_daemon.go | 2 +- test/utils.go | 2 +- 13 files changed, 213 insertions(+), 11 deletions(-) create mode 100644 .gitignore rename p2pclient/{ => go}/dht.go (100%) rename p2pclient/{ => go}/p2pclient.go (97%) rename p2pclient/{ => go}/streams.go (100%) create mode 100644 p2pclient/java/p2pd.c create mode 100644 p2pclient/java/p2pd.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a90bd610 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +*.a +*.jnilib +*.o +*.class + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +#misc +p2pclient/java/libp2pd.h +p2pclient/java/p2pd.h diff --git a/Makefile b/Makefile index 74f8ba84..1d9b6899 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,43 @@ -bin: deps +CLASS_PATH = . +CFLAGS = -O2 -fPIC +DIR = p2pclient/java +JAVA_INCLUDES = -I$(JAVA_HOME)/include/darwin -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux +vpath %.class $(CLASS_PATH) + +.DEFAULT_GOAL := go-daemon + +java-daemon: libp2pd.jnilib + +libp2pd.jnilib : libp2pd.o + ld -dylib -flat_namespace -undefined suppress -macosx_version_min 10.13.4 -o $(DIR)/$@ $(DIR)/*.o -L$(DIR) -lp2pd + +libp2pd.o : libp2pd.a + gcc $(CFLAGS) -c $(DIR)/p2pd.c $(JAVA_INCLUDES) -o $(DIR)/$@ + +libp2pd.a: p2pd.h + go build -o $(DIR)/$@ -buildmode=c-archive p2pd/main.go + +p2pd.h : p2pd.class + cd $(DIR) && javac -h $(CLASS_PATH) $*.java + +p2pd.class: go-daemon + cd $(DIR) && javac p2pd.java + +go-daemon: deps go install ./... +deps: gx + gx --verbose install --global + gx-go rewrite + gx: go get github.com/whyrusleeping/gx go get github.com/whyrusleeping/gx-go -deps: gx - gx --verbose install --global - gx-go rewrite +clean: + rm -f p2pclient/java/*.o \ + && rm -f p2pclient/java/*.a \ + && rm -f p2pclient/java/*.jnilib \ + && rm -f p2pclient/java/*.class \ + && rm -f p2pclient/java/*.h + diff --git a/daemon.go b/daemon.go index d0d13b20..63f80ef7 100644 --- a/daemon.go +++ b/daemon.go @@ -4,7 +4,10 @@ import ( "context" "fmt" "net" + "os" + "os/signal" "sync" + "syscall" logging "github.com/ipfs/go-log" libp2p "github.com/libp2p/go-libp2p" @@ -54,6 +57,15 @@ func NewDaemon(ctx context.Context, path string, opts ...libp2p.Option) (*Daemon go d.listen() + sigc := make(chan os.Signal, 1) + signal.Notify(sigc, os.Interrupt, syscall.SIGTERM) + go func(ln net.Listener, c chan os.Signal) { + sig := <-c + fmt.Printf("Caught signal %s: shutting down.", sig) + ln.Close() + os.Exit(0) + }(d.listener, sigc) + return d, nil } diff --git a/p2pclient/dht.go b/p2pclient/go/dht.go similarity index 100% rename from p2pclient/dht.go rename to p2pclient/go/dht.go diff --git a/p2pclient/p2pclient.go b/p2pclient/go/p2pclient.go similarity index 97% rename from p2pclient/p2pclient.go rename to p2pclient/go/p2pclient.go index 263e69d0..5815159e 100644 --- a/p2pclient/p2pclient.go +++ b/p2pclient/go/p2pclient.go @@ -30,7 +30,7 @@ type Client struct { // NewClient creates a new libp2p daemon client, connecting to a daemon // listening on a unix socket at controlPath, and establishing an inbound socket // at listenPath. -func NewClient(controlPath, listenPath string) (*Client, error) { +func NewClient(controlPath string, listenPath string) (*Client, error) { client := &Client{ controlPath: controlPath, listenPath: listenPath, diff --git a/p2pclient/streams.go b/p2pclient/go/streams.go similarity index 100% rename from p2pclient/streams.go rename to p2pclient/go/streams.go diff --git a/p2pclient/java/p2pd.c b/p2pclient/java/p2pd.c new file mode 100644 index 00000000..ad20411c --- /dev/null +++ b/p2pclient/java/p2pd.c @@ -0,0 +1,13 @@ +#include +#include "p2pd.h" +#include "libp2pd.h" + +JNIEXPORT void JNICALL Java_p2pd_startD +(JNIEnv *env, jclass cl){ + startD(); +} + +JNIEXPORT void JNICALL Java_p2pd_stopD +(JNIEnv *env, jclass cl){ + stopD(); +} \ No newline at end of file diff --git a/p2pclient/java/p2pd.java b/p2pclient/java/p2pd.java new file mode 100644 index 00000000..8756686a --- /dev/null +++ b/p2pclient/java/p2pd.java @@ -0,0 +1,18 @@ + +public class p2pd { + public static native void startD(); + public static native void stopD(); + static { + try { + + System.loadLibrary ( "p2pd" ) ; + + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load.\n" + e); + System.exit(1); + } + } + public static void main(String[] args) { + startD(); + } +} \ No newline at end of file diff --git a/p2pd/main.go b/p2pd/main.go index d65344cd..06544fa8 100644 --- a/p2pd/main.go +++ b/p2pd/main.go @@ -1,21 +1,121 @@ package main +import "C" import ( "context" "flag" "fmt" + "io" "log" + "os" "strings" libp2p "github.com/libp2p/go-libp2p" connmgr "github.com/libp2p/go-libp2p-connmgr" p2pd "github.com/libp2p/go-libp2p-daemon" + peer "github.com/libp2p/go-libp2p-peer" ps "github.com/libp2p/go-libp2p-pubsub" quic "github.com/libp2p/go-libp2p-quic-transport" identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" + multiaddr "github.com/multiformats/go-multiaddr" + + "github.com/libp2p/go-libp2p-daemon/p2pclient/go" ) +// ClientConfig defines the configuration options for the client +type ClientConfig struct { + pathd string + pathc string + command string + args []string +} + func main() { + //defined interactions between client and daemon + commands := [...]string{"Identify", "Connect"} + client := flag.Bool("client", false, "run in client mode") + pathd := flag.String("pathd", "/tmp/p2pd.sock", "daemon control socket path") + pathc := flag.String("pathc", "/tmp/p2pc.sock", "client control socket path") + command := flag.String("command", commands[0], "command to send to the daemon") + flag.Parse() + + if *client { + config := ClientConfig{ + pathd: *pathd, + pathc: *pathc, + command: *command, + args: flag.Args(), + } + startC(config) + } else { + startD() + } +} +func startC(config ClientConfig) { + identify.ClientVersion = "p2pc/0.1" + + client, err := p2pclient.NewClient(config.pathd, config.pathc) + + if err != nil { + log.Fatal(err) + } + + if config.command == "Identify" { + id, addrs, err := client.Identify() + if err != nil { + log.Fatal(err) + } + fmt.Printf("Daemon ID: %s\n", id.Pretty()) + fmt.Printf("Peer addresses: %v\n", addrs) + } else if config.command == "Connect" { + id, err := peer.IDB58Decode(config.args[0]) + var addrs []multiaddr.Multiaddr + addrs = make([]multiaddr.Multiaddr, len(config.args[1:])) + for i, arg := range config.args[1:] { + addr, _ := multiaddr.NewMultiaddr(arg) + addrs[i] = addr + } + err = client.Connect(id, addrs) + if err != nil { + fmt.Println(err) + } + + pi, err := client.FindPeer(id) + fmt.Printf("ID: %s has multiaddr: %v", pi.ID, pi.Addrs) + + } else if config.command == "ListenForMessage" { + protos := []string{"/test"} + done := make(chan struct{}) + client.NewStreamHandler(protos, func(info *p2pclient.StreamInfo, conn io.ReadWriteCloser) { + defer conn.Close() + buf := make([]byte, 1024) + _, err := conn.Read(buf) + if err != nil { + fmt.Println(err) + } + fmt.Println(string(buf)) + done <- struct{}{} + }) + select {} + } else if config.command == "SendMessage" { + protos := []string{"/test"} + recipientID, err := peer.IDB58Decode(config.args[0]) + _, conn, err := client.NewStream(recipientID, protos) + if err != nil { + fmt.Println(err) + } + _, err = conn.Write([]byte(config.args[1])) + if err != nil { + fmt.Println(err) + } + + } + + os.Remove(config.pathc) +} + +//export startD +func startD() { identify.ClientVersion = "p2pd/0.1" sock := flag.String("sock", "/tmp/p2pd.sock", "daemon control socket path") @@ -23,8 +123,8 @@ func main() { id := flag.String("id", "", "peer identity; private key file") bootstrap := flag.Bool("b", false, "connects to bootstrap peers and bootstraps the dht if enabled") bootstrapPeers := flag.String("bootstrapPeers", "", "comma separated list of bootstrap peers; defaults to the IPFS DHT peers") - dht := flag.Bool("dht", false, "Enables the DHT in full node mode") - dhtClient := flag.Bool("dhtClient", false, "Enables the DHT in client mode") + dht := flag.Bool("dht", true, "Enables the DHT in full node mode") + dhtClient := flag.Bool("dhtClient", true, "Enables the DHT in client mode") connMgr := flag.Bool("connManager", false, "Enables the Connection Manager") connMgrLo := flag.Int("connLo", 256, "Connection Manager Low Water mark") connMgrHi := flag.Int("connHi", 512, "Connection Manager High Water mark") @@ -126,3 +226,9 @@ func main() { select {} } + +//export stopD +func stopD() { + p, _ := os.FindProcess(os.Getpid()) + p.Signal(os.Interrupt) +} diff --git a/test/dht_test.go b/test/dht_test.go index dfe28cf4..e19aad0b 100644 --- a/test/dht_test.go +++ b/test/dht_test.go @@ -11,7 +11,7 @@ import ( crypto "github.com/libp2p/go-libp2p-crypto" peer "github.com/libp2p/go-libp2p-peer" - "github.com/libp2p/go-libp2p-daemon/p2pclient" + "github.com/libp2p/go-libp2p-daemon/p2pclient/go" pb "github.com/libp2p/go-libp2p-daemon/pb" ) diff --git a/test/integration_test.go b/test/integration_test.go index 4c9eafe1..b9a54c1f 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -6,7 +6,7 @@ import ( "time" "github.com/libp2p/go-libp2p-daemon" - "github.com/libp2p/go-libp2p-daemon/p2pclient" + "github.com/libp2p/go-libp2p-daemon/p2pclient/go" peer "github.com/libp2p/go-libp2p-peer" ma "github.com/multiformats/go-multiaddr" ) diff --git a/test/mock_daemon.go b/test/mock_daemon.go index b9a47391..c901bf78 100644 --- a/test/mock_daemon.go +++ b/test/mock_daemon.go @@ -8,7 +8,7 @@ import ( ggio "github.com/gogo/protobuf/io" "github.com/gogo/protobuf/proto" - "github.com/libp2p/go-libp2p-daemon/p2pclient" + "github.com/libp2p/go-libp2p-daemon/p2pclient/go" pb "github.com/libp2p/go-libp2p-daemon/pb" ) diff --git a/test/utils.go b/test/utils.go index 56bdd74b..c6c4c3cf 100644 --- a/test/utils.go +++ b/test/utils.go @@ -13,7 +13,7 @@ import ( cid "github.com/ipfs/go-cid" crypto "github.com/libp2p/go-libp2p-crypto" p2pd "github.com/libp2p/go-libp2p-daemon" - "github.com/libp2p/go-libp2p-daemon/p2pclient" + "github.com/libp2p/go-libp2p-daemon/p2pclient/go" pb "github.com/libp2p/go-libp2p-daemon/pb" peer "github.com/libp2p/go-libp2p-peer" peertest "github.com/libp2p/go-libp2p-peer/test" From 9543b115a82d429116c50d8b8dd154b189200aea Mon Sep 17 00:00:00 2001 From: jonny rhea Date: Sat, 24 Nov 2018 10:00:31 -0600 Subject: [PATCH 2/7] -split out client into a sep exe called p2pc -mmacosx-version-min flag is now set dynamically -switched from ld to gcc linking command and removed ignore unused errors flag. -prefixed the cgo headers with go- and jni c headers with java- for clarity. -added a conditional check for OS (darwin or linux) so that the build can be customized for either --- Makefile | 65 ++++++++---- daemon.go | 2 +- p2pc/main.go | 104 ++++++++++++++++++ p2pclient/go/p2pclient.go | 2 +- p2pclient/java/java-p2pd.c | 13 +++ p2pclient/java/p2pd.c | 13 --- p2pclient/java/p2pd.java | 7 +- p2pd/main.go | 209 ++++++++++++------------------------- 8 files changed, 235 insertions(+), 180 deletions(-) create mode 100644 p2pc/main.go create mode 100644 p2pclient/java/java-p2pd.c delete mode 100644 p2pclient/java/p2pd.c diff --git a/Makefile b/Makefile index 1d9b6899..542e93b7 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,54 @@ -CLASS_PATH = . +SHELL := /bin/bash +OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') + +ifeq ($(OS), linux) + EXT = so + OS_LFLAGS = + JAVA_HOME = +else ifeq ($(OS), darwin) + EXT = dylib + OS_LFLAGS = -mmacosx-version-min=$(shell defaults read loginwindow SystemVersionStampAsString) -framework CoreFoundation -framework Security + JAVA_HOME = $(shell /usr/libexec/java_home) +endif + +CC = gcc CFLAGS = -O2 -fPIC -DIR = p2pclient/java -JAVA_INCLUDES = -I$(JAVA_HOME)/include/darwin -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux +LFLAGS = $(OS_LFLAGS) -shared + +JAVA_INCLUDES = -I$(JAVA_HOME)/include/$(OS) -I$(JAVA_HOME)/include +CLASS_PATH = . vpath %.class $(CLASS_PATH) +DDIR := p2pd +CDIR := p2pc +JDIR := p2pclient/java +DNAME := p2pd + + .DEFAULT_GOAL := go-daemon -java-daemon: libp2pd.jnilib +java-daemon: lib$(DNAME).$(EXT) + +lib$(DNAME).$(EXT): java-$(DNAME).o go-$(DNAME).a + $(CC) $(LFLAGS) -o $(JDIR)/$@ $(JDIR)/*.o $(JDIR)/*.a -libp2pd.jnilib : libp2pd.o - ld -dylib -flat_namespace -undefined suppress -macosx_version_min 10.13.4 -o $(DIR)/$@ $(DIR)/*.o -L$(DIR) -lp2pd +java-$(DNAME).o: java-$(DNAME).h $(DNAME).class go-$(DNAME).a + $(CC) $(CFLAGS) -c $(JDIR)/java-$(DNAME).c $(JAVA_INCLUDES) -o $(JDIR)/$@ -libp2pd.o : libp2pd.a - gcc $(CFLAGS) -c $(DIR)/p2pd.c $(JAVA_INCLUDES) -o $(DIR)/$@ +go-$(DNAME).a: + go build -o $(JDIR)/$@ -buildmode=c-archive $(DDIR)/main.go -libp2pd.a: p2pd.h - go build -o $(DIR)/$@ -buildmode=c-archive p2pd/main.go +java-$(DNAME).h: + cd $(JDIR) && javac -h $(CLASS_PATH) $(DNAME).java && mv $(DNAME).h $@ -p2pd.h : p2pd.class - cd $(DIR) && javac -h $(CLASS_PATH) $*.java +$(DNAME).class: go-daemon + cd $(JDIR) && javac $(DNAME).java -p2pd.class: go-daemon - cd $(DIR) && javac p2pd.java +go-client: deps + cd $(CDIR) && go install ./... go-daemon: deps - go install ./... + cd $(DDIR) && go install ./... deps: gx gx --verbose install --global @@ -35,9 +59,10 @@ gx: go get github.com/whyrusleeping/gx-go clean: - rm -f p2pclient/java/*.o \ - && rm -f p2pclient/java/*.a \ - && rm -f p2pclient/java/*.jnilib \ - && rm -f p2pclient/java/*.class \ - && rm -f p2pclient/java/*.h + gx-go uw + rm -f $(JDIR)/*.o \ + && rm -f $(JDIR)/*.a \ + && rm -f $(JDIR)/*.$(EXT) \ + && rm -f $(JDIR)/*.class \ + && rm -f $(JDIR)/*.h diff --git a/daemon.go b/daemon.go index 63f80ef7..ad14c8b0 100644 --- a/daemon.go +++ b/daemon.go @@ -61,7 +61,7 @@ func NewDaemon(ctx context.Context, path string, opts ...libp2p.Option) (*Daemon signal.Notify(sigc, os.Interrupt, syscall.SIGTERM) go func(ln net.Listener, c chan os.Signal) { sig := <-c - fmt.Printf("Caught signal %s: shutting down.", sig) + fmt.Printf("Caught signal %s: shutting down.\n", sig) ln.Close() os.Exit(0) }(d.listener, sigc) diff --git a/p2pc/main.go b/p2pc/main.go new file mode 100644 index 00000000..1a2f4066 --- /dev/null +++ b/p2pc/main.go @@ -0,0 +1,104 @@ +package main + +import "C" +import ( + "flag" + "fmt" + "io" + "log" + "os" + + peer "github.com/libp2p/go-libp2p-peer" + identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" + multiaddr "github.com/multiformats/go-multiaddr" + + "github.com/libp2p/go-libp2p-daemon/p2pclient/go" +) + +// ClientConfig defines the configuration options +type ClientConfig struct { + pathd string + pathc string + command string + args []string +} + +func main() { + //defined interactions between client and daemon + commands := [...]string{"Identify", "Connect"} + pathd := flag.String("pathd", "/tmp/p2pd.sock", "daemon control socket path") + pathc := flag.String("pathc", "/tmp/p2pc.sock", "client control socket path") + command := flag.String("command", commands[0], "command to send to the daemon") + flag.Parse() + + config := ClientConfig{ + pathd: *pathd, + pathc: *pathc, + command: *command, + args: flag.Args(), + } + startClient(config) + +} +func startClient(config ClientConfig) { + identify.ClientVersion = "p2pc/0.1" + + client, err := p2pclient.NewClient(config.pathd, config.pathc) + + if err != nil { + log.Fatal(err) + } + + if config.command == "Identify" { + id, addrs, err := client.Identify() + if err != nil { + log.Fatal(err) + } + fmt.Printf("Daemon ID: %s\n", id.Pretty()) + fmt.Printf("Peer addresses: %v\n", addrs) + } else if config.command == "Connect" { + id, err := peer.IDB58Decode(config.args[0]) + var addrs []multiaddr.Multiaddr + addrs = make([]multiaddr.Multiaddr, len(config.args[1:])) + for i, arg := range config.args[1:] { + addr, _ := multiaddr.NewMultiaddr(arg) + addrs[i] = addr + } + err = client.Connect(id, addrs) + if err != nil { + fmt.Println(err) + } + + pi, err := client.FindPeer(id) + fmt.Printf("ID: %s has multiaddr: %v", pi.ID, pi.Addrs) + + } else if config.command == "ListenForMessage" { + protos := []string{"/test"} + done := make(chan struct{}) + client.NewStreamHandler(protos, func(info *p2pclient.StreamInfo, conn io.ReadWriteCloser) { + defer conn.Close() + buf := make([]byte, 1024) + _, err := conn.Read(buf) + if err != nil { + fmt.Println(err) + } + fmt.Println(string(buf)) + done <- struct{}{} + }) + select {} + } else if config.command == "SendMessage" { + protos := []string{"/test"} + recipientID, err := peer.IDB58Decode(config.args[0]) + _, conn, err := client.NewStream(recipientID, protos) + if err != nil { + fmt.Println(err) + } + _, err = conn.Write([]byte(config.args[1])) + if err != nil { + fmt.Println(err) + } + + } + + os.Remove(config.pathc) +} diff --git a/p2pclient/go/p2pclient.go b/p2pclient/go/p2pclient.go index 5815159e..263e69d0 100644 --- a/p2pclient/go/p2pclient.go +++ b/p2pclient/go/p2pclient.go @@ -30,7 +30,7 @@ type Client struct { // NewClient creates a new libp2p daemon client, connecting to a daemon // listening on a unix socket at controlPath, and establishing an inbound socket // at listenPath. -func NewClient(controlPath string, listenPath string) (*Client, error) { +func NewClient(controlPath, listenPath string) (*Client, error) { client := &Client{ controlPath: controlPath, listenPath: listenPath, diff --git a/p2pclient/java/java-p2pd.c b/p2pclient/java/java-p2pd.c new file mode 100644 index 00000000..9a375b9e --- /dev/null +++ b/p2pclient/java/java-p2pd.c @@ -0,0 +1,13 @@ +#include +#include "java-p2pd.h" +#include "go-p2pd.h" + +JNIEXPORT void JNICALL Java_p2pd_startDaemon +(JNIEnv *env, jclass cl){ + startDaemon(); +} + +JNIEXPORT void JNICALL Java_p2pd_stopDaemon +(JNIEnv *env, jclass cl){ + stopDaemon(); +} \ No newline at end of file diff --git a/p2pclient/java/p2pd.c b/p2pclient/java/p2pd.c deleted file mode 100644 index ad20411c..00000000 --- a/p2pclient/java/p2pd.c +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include "p2pd.h" -#include "libp2pd.h" - -JNIEXPORT void JNICALL Java_p2pd_startD -(JNIEnv *env, jclass cl){ - startD(); -} - -JNIEXPORT void JNICALL Java_p2pd_stopD -(JNIEnv *env, jclass cl){ - stopD(); -} \ No newline at end of file diff --git a/p2pclient/java/p2pd.java b/p2pclient/java/p2pd.java index 8756686a..f8e35632 100644 --- a/p2pclient/java/p2pd.java +++ b/p2pclient/java/p2pd.java @@ -1,7 +1,8 @@ +import java.util.Arrays; public class p2pd { - public static native void startD(); - public static native void stopD(); + public static native void startDaemon(); + public static native void stopDaemon(); static { try { @@ -13,6 +14,6 @@ public class p2pd { } } public static void main(String[] args) { - startD(); + startDaemon(); } } \ No newline at end of file diff --git a/p2pd/main.go b/p2pd/main.go index 06544fa8..988e5689 100644 --- a/p2pd/main.go +++ b/p2pd/main.go @@ -5,144 +5,65 @@ import ( "context" "flag" "fmt" - "io" "log" "os" "strings" + "time" libp2p "github.com/libp2p/go-libp2p" connmgr "github.com/libp2p/go-libp2p-connmgr" p2pd "github.com/libp2p/go-libp2p-daemon" - peer "github.com/libp2p/go-libp2p-peer" - ps "github.com/libp2p/go-libp2p-pubsub" quic "github.com/libp2p/go-libp2p-quic-transport" identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" - multiaddr "github.com/multiformats/go-multiaddr" - - "github.com/libp2p/go-libp2p-daemon/p2pclient/go" ) -// ClientConfig defines the configuration options for the client -type ClientConfig struct { - pathd string - pathc string - command string - args []string +// DaemonConfig defines the configuration options +type DaemonConfig struct { + sock *string + quiet *bool + id *string + bootstrap *bool + bootstrapPeers *string + dht *bool + dhtClient *bool + connMgr *bool + connMgrLo *int + connMgrHi *int + connMgrGrace *int + args []string } func main() { - //defined interactions between client and daemon - commands := [...]string{"Identify", "Connect"} - client := flag.Bool("client", false, "run in client mode") - pathd := flag.String("pathd", "/tmp/p2pd.sock", "daemon control socket path") - pathc := flag.String("pathc", "/tmp/p2pc.sock", "client control socket path") - command := flag.String("command", commands[0], "command to send to the daemon") + identify.ClientVersion = "p2pd/0.1" + + config := initConfig() flag.Parse() - if *client { - config := ClientConfig{ - pathd: *pathd, - pathc: *pathc, - command: *command, - args: flag.Args(), - } - startC(config) - } else { - startD() - } + start(config) } -func startC(config ClientConfig) { - identify.ClientVersion = "p2pc/0.1" - - client, err := p2pclient.NewClient(config.pathd, config.pathc) - if err != nil { - log.Fatal(err) +func initConfig() DaemonConfig { + return DaemonConfig{ + sock: flag.String("sock", "/tmp/p2pd.sock", "daemon control socket path"), + quiet: flag.Bool("q", false, "be quiet"), + id: flag.String("id", "", "peer identity; private key file"), + bootstrap: flag.Bool("b", false, "connects to bootstrap peers and bootstraps the dht if enabled"), + bootstrapPeers: flag.String("bootstrapPeers", "", "comma separated list of bootstrap peers; defaults to the IPFS DHT peers"), + dht: flag.Bool("dht", true, "Enables the DHT in full node mode"), + dhtClient: flag.Bool("dhtClient", true, "Enables the DHT in client mode"), + connMgr: flag.Bool("connManager", false, "Enables the Connection Manager"), + connMgrLo: flag.Int("connLo", 256, "Connection Manager Low Water mark"), + connMgrHi: flag.Int("connHi", 512, "Connection Manager High Water mark"), + connMgrGrace: flag.Int("connGrace", 120, "Connection Manager grace period (in seconds)"), + args: flag.Args(), } - - if config.command == "Identify" { - id, addrs, err := client.Identify() - if err != nil { - log.Fatal(err) - } - fmt.Printf("Daemon ID: %s\n", id.Pretty()) - fmt.Printf("Peer addresses: %v\n", addrs) - } else if config.command == "Connect" { - id, err := peer.IDB58Decode(config.args[0]) - var addrs []multiaddr.Multiaddr - addrs = make([]multiaddr.Multiaddr, len(config.args[1:])) - for i, arg := range config.args[1:] { - addr, _ := multiaddr.NewMultiaddr(arg) - addrs[i] = addr - } - err = client.Connect(id, addrs) - if err != nil { - fmt.Println(err) - } - - pi, err := client.FindPeer(id) - fmt.Printf("ID: %s has multiaddr: %v", pi.ID, pi.Addrs) - - } else if config.command == "ListenForMessage" { - protos := []string{"/test"} - done := make(chan struct{}) - client.NewStreamHandler(protos, func(info *p2pclient.StreamInfo, conn io.ReadWriteCloser) { - defer conn.Close() - buf := make([]byte, 1024) - _, err := conn.Read(buf) - if err != nil { - fmt.Println(err) - } - fmt.Println(string(buf)) - done <- struct{}{} - }) - select {} - } else if config.command == "SendMessage" { - protos := []string{"/test"} - recipientID, err := peer.IDB58Decode(config.args[0]) - _, conn, err := client.NewStream(recipientID, protos) - if err != nil { - fmt.Println(err) - } - _, err = conn.Write([]byte(config.args[1])) - if err != nil { - fmt.Println(err) - } - - } - - os.Remove(config.pathc) } -//export startD -func startD() { - identify.ClientVersion = "p2pd/0.1" - - sock := flag.String("sock", "/tmp/p2pd.sock", "daemon control socket path") - quiet := flag.Bool("q", false, "be quiet") - id := flag.String("id", "", "peer identity; private key file") - bootstrap := flag.Bool("b", false, "connects to bootstrap peers and bootstraps the dht if enabled") - bootstrapPeers := flag.String("bootstrapPeers", "", "comma separated list of bootstrap peers; defaults to the IPFS DHT peers") - dht := flag.Bool("dht", true, "Enables the DHT in full node mode") - dhtClient := flag.Bool("dhtClient", true, "Enables the DHT in client mode") - connMgr := flag.Bool("connManager", false, "Enables the Connection Manager") - connMgrLo := flag.Int("connLo", 256, "Connection Manager Low Water mark") - connMgrHi := flag.Int("connHi", 512, "Connection Manager High Water mark") - connMgrGrace := flag.Duration("connGrace", 120, "Connection Manager grace period (in seconds)") - QUIC := flag.Bool("quic", false, "Enables the QUIC transport") - natPortMap := flag.Bool("natPortMap", false, "Enables NAT port mapping") - pubsub := flag.Bool("pubsub", false, "Enables pubsub") - pubsubRouter := flag.String("pubsubRouter", "gossipsub", "Specifies the pubsub router implementation") - pubsubSign := flag.Bool("pubsubSign", true, "Enables pubsub message signing") - pubsubSignStrict := flag.Bool("pubsubSignStrict", false, "Enables pubsub strict signature verification") - gossipsubHeartbeatInterval := flag.Duration("gossipsubHeartbeatInterval", 0, "Specifies the gossipsub heartbeat interval") - gossipsubHeartbeatInitialDelay := flag.Duration("gossipsubHeartbeatInitialDelay", 0, "Specifies the gossipsub initial heartbeat delay") - flag.Parse() - +func start(config DaemonConfig) { var opts []libp2p.Option - if *id != "" { - key, err := p2pd.ReadIdentity(*id) + if *config.id != "" { + key, err := p2pd.ReadIdentity(*config.id) if err != nil { log.Fatal(err) } @@ -150,8 +71,8 @@ func startD() { opts = append(opts, libp2p.Identity(key)) } - if *connMgr { - cm := connmgr.NewConnManager(*connMgrLo, *connMgrHi, *connMgrGrace) + if *config.connMgr { + cm := connmgr.NewConnManager(*config.connMgrLo, *config.connMgrHi, time.Duration(*config.connMgrGrace)) opts = append(opts, libp2p.ConnectionManager(cm)) } @@ -176,47 +97,32 @@ func startD() { log.Fatal(err) } - if *pubsub { - if *gossipsubHeartbeatInterval > 0 { - ps.GossipSubHeartbeatInterval = *gossipsubHeartbeatInterval - } - - if *gossipsubHeartbeatInitialDelay > 0 { - ps.GossipSubHeartbeatInitialDelay = *gossipsubHeartbeatInitialDelay - } - - err = d.EnablePubsub(*pubsubRouter, *pubsubSign, *pubsubSignStrict) - if err != nil { - log.Fatal(err) - } - } - - if *dht || *dhtClient { - err = d.EnableDHT(*dhtClient) + if *config.dht || *config.dhtClient { + err = d.EnableDHT(*config.dhtClient) if err != nil { log.Fatal(err) } } - if *bootstrapPeers != "" { - p2pd.BootstrapPeers = strings.Split(*bootstrapPeers, ",") + if *config.bootstrapPeers != "" { + p2pd.BootstrapPeers = strings.Split(*config.bootstrapPeers, ",") } - if *bootstrap { + if *config.bootstrap { err = d.Bootstrap() if err != nil { log.Fatal(err) } } - if !*quiet { - fmt.Printf("Control socket: %s\n", *sock) + if !*config.quiet { + fmt.Printf("Control socket: %s\n", *config.sock) fmt.Printf("Peer ID: %s\n", d.ID().Pretty()) fmt.Printf("Peer Addrs:\n") for _, addr := range d.Addrs() { fmt.Printf("%s\n", addr.String()) } - if *bootstrap && *bootstrapPeers != "" { + if *config.bootstrap && *config.bootstrapPeers != "" { fmt.Printf("Bootstrap peers:\n") for _, p := range p2pd.BootstrapPeers { fmt.Printf("%s\n", p) @@ -227,8 +133,27 @@ func startD() { select {} } -//export stopD -func stopD() { +func updateConfig(config, defaultConfig DaemonConfig) DaemonConfig { + //Add fields to config that are found in defaultConfig, but missing from config + config = defaultConfig //TODO temp hack + return config +} + +//export startDaemon +func startDaemon() { + //1. pass in config from Java->C->Go StartDaemon() + //Not implemented + //2. call initConfig() to create default config + defaultConfig := initConfig() + //3. call updateConfig(defaultConfig) to replace default config options with configs passed from Java + config := defaultConfig //TODO: temp hack + config = updateConfig(config, defaultConfig) + //3. call start(config) + start(config) +} + +//export stopDaemon +func stopDaemon() { p, _ := os.FindProcess(os.Getpid()) p.Signal(os.Interrupt) } From 8a90bc7821ce06a4afbe149ad5cf52e1c7e7a383 Mon Sep 17 00:00:00 2001 From: jonny rhea Date: Wed, 28 Nov 2018 02:42:08 -0600 Subject: [PATCH 3/7] - added c scaffolding code for java client. added sep targets for client builds in Makefile. - finished passing all CL args from so to Go. remove domain socket on client fail. --- Makefile | 35 +++++++++++-------- p2pc/main.go | 71 +++++++++++++++++++++++--------------- p2pclient/java/java-p2pc.c | 16 +++++++++ p2pclient/java/java-p2pd.c | 17 ++++++--- p2pclient/java/p2pc.java | 21 +++++++++++ p2pclient/java/p2pd.java | 13 ++++--- p2pd/main.go | 42 +++++++++++----------- 7 files changed, 141 insertions(+), 74 deletions(-) create mode 100644 p2pclient/java/java-p2pc.c create mode 100644 p2pclient/java/p2pc.java diff --git a/Makefile b/Makefile index 542e93b7..997be84c 100644 --- a/Makefile +++ b/Makefile @@ -19,30 +19,35 @@ JAVA_INCLUDES = -I$(JAVA_HOME)/include/$(OS) -I$(JAVA_HOME)/include CLASS_PATH = . vpath %.class $(CLASS_PATH) -DDIR := p2pd -CDIR := p2pc -JDIR := p2pclient/java -DNAME := p2pd +DDIR = p2pd +CDIR = p2pc +JDIR = p2pclient/java +DNAME = p2pd +CNAME = p2pc +.PHONY : all java-daemon java-client go-client go-daemon deps gx clean +.DEFAULT_GOAL : go-daemon -.DEFAULT_GOAL := go-daemon +all: go-daemon go-client java-daemon java-client java-daemon: lib$(DNAME).$(EXT) -lib$(DNAME).$(EXT): java-$(DNAME).o go-$(DNAME).a - $(CC) $(LFLAGS) -o $(JDIR)/$@ $(JDIR)/*.o $(JDIR)/*.a +java-client: lib$(CNAME).$(EXT) -java-$(DNAME).o: java-$(DNAME).h $(DNAME).class go-$(DNAME).a - $(CC) $(CFLAGS) -c $(JDIR)/java-$(DNAME).c $(JAVA_INCLUDES) -o $(JDIR)/$@ +lib%.$(EXT): java-%.o go-%.a + $(CC) $(LFLAGS) -o $(JDIR)/$@ $(JDIR)/$(firstword $^) $(JDIR)/$(lastword $^) -go-$(DNAME).a: - go build -o $(JDIR)/$@ -buildmode=c-archive $(DDIR)/main.go +java-%.o: go-%.a java-%.h %.class + $(CC) $(CFLAGS) -c $(JDIR)/java-$*.c $(JAVA_INCLUDES) -o $(JDIR)/$@ -java-$(DNAME).h: - cd $(JDIR) && javac -h $(CLASS_PATH) $(DNAME).java && mv $(DNAME).h $@ +go-%.a: + go build -o $(JDIR)/$@ -buildmode=c-archive $*/main.go -$(DNAME).class: go-daemon - cd $(JDIR) && javac $(DNAME).java +java-%.h: + cd $(JDIR) && javac -h $(CLASS_PATH) $*.java && mv $*.h $@ + +%.class: deps + cd $(JDIR) && javac $*.java go-client: deps cd $(CDIR) && go install ./... diff --git a/p2pc/main.go b/p2pc/main.go index 1a2f4066..9aba0694 100644 --- a/p2pc/main.go +++ b/p2pc/main.go @@ -7,6 +7,7 @@ import ( "io" "log" "os" + "strings" peer "github.com/libp2p/go-libp2p-peer" identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" @@ -17,46 +18,51 @@ import ( // ClientConfig defines the configuration options type ClientConfig struct { - pathd string - pathc string - command string + pathd *string + pathc *string + command *string args []string } func main() { - //defined interactions between client and daemon - commands := [...]string{"Identify", "Connect"} - pathd := flag.String("pathd", "/tmp/p2pd.sock", "daemon control socket path") - pathc := flag.String("pathc", "/tmp/p2pc.sock", "client control socket path") - command := flag.String("command", commands[0], "command to send to the daemon") - flag.Parse() + identify.ClientVersion = "p2pc/0.1" + config := initialize() + start(config) +} +func initialize() ClientConfig { config := ClientConfig{ - pathd: *pathd, - pathc: *pathc, - command: *command, - args: flag.Args(), + pathd: flag.String("pathd", "/tmp/p2pd.sock", "daemon control socket path"), + pathc: flag.String("pathc", "/tmp/p2pc.sock", "client control socket path"), + command: flag.String("command", "Identify", "command to send to the daemon"), } - startClient(config) - + flag.Parse() + config.args = flag.Args() + // delete control socket if it already exists + if _, err := os.Stat(*config.pathc); !os.IsNotExist(err) { + err = os.Remove(*config.pathc) + if err != nil { + log.Fatal(err) + } + } + return config } -func startClient(config ClientConfig) { - identify.ClientVersion = "p2pc/0.1" - client, err := p2pclient.NewClient(config.pathd, config.pathc) +func start(config ClientConfig) { + client, err := p2pclient.NewClient(*config.pathd, *config.pathc) if err != nil { log.Fatal(err) } - if config.command == "Identify" { + if *config.command == "Identify" { id, addrs, err := client.Identify() if err != nil { log.Fatal(err) } fmt.Printf("Daemon ID: %s\n", id.Pretty()) fmt.Printf("Peer addresses: %v\n", addrs) - } else if config.command == "Connect" { + } else if *config.command == "Connect" { id, err := peer.IDB58Decode(config.args[0]) var addrs []multiaddr.Multiaddr addrs = make([]multiaddr.Multiaddr, len(config.args[1:])) @@ -66,13 +72,13 @@ func startClient(config ClientConfig) { } err = client.Connect(id, addrs) if err != nil { - fmt.Println(err) + log.Fatal(err) } pi, err := client.FindPeer(id) fmt.Printf("ID: %s has multiaddr: %v", pi.ID, pi.Addrs) - } else if config.command == "ListenForMessage" { + } else if *config.command == "ListenForMessage" { protos := []string{"/test"} done := make(chan struct{}) client.NewStreamHandler(protos, func(info *p2pclient.StreamInfo, conn io.ReadWriteCloser) { @@ -80,25 +86,36 @@ func startClient(config ClientConfig) { buf := make([]byte, 1024) _, err := conn.Read(buf) if err != nil { - fmt.Println(err) + log.Fatal(err) } fmt.Println(string(buf)) done <- struct{}{} }) select {} - } else if config.command == "SendMessage" { + } else if *config.command == "SendMessage" { protos := []string{"/test"} recipientID, err := peer.IDB58Decode(config.args[0]) _, conn, err := client.NewStream(recipientID, protos) if err != nil { - fmt.Println(err) + log.Fatal(err) } _, err = conn.Write([]byte(config.args[1])) if err != nil { - fmt.Println(err) + log.Fatal(err) } } - os.Remove(config.pathc) + os.Remove(*config.pathc) +} + +//export startClient +func startClient(args *C.char) { + //replace default config options with configs passed from external source + argsGoString := C.GoString(args) + argsArray := strings.Split(argsGoString, "|") + os.Args = argsArray + //call initialize() to get config + config := initialize() + start(config) } diff --git a/p2pclient/java/java-p2pc.c b/p2pclient/java/java-p2pc.c new file mode 100644 index 00000000..1b7aac3a --- /dev/null +++ b/p2pclient/java/java-p2pc.c @@ -0,0 +1,16 @@ +#include +#include "java-p2pc.h" +#include "go-p2pc.h" + +JNIEXPORT void JNICALL Java_p2pc_startClient (JNIEnv *jenv, jclass jcls, jstring jarg1){ + char *arg1 = (char *) 0 ; + (void)jenv; + (void)jcls; + arg1 = 0; + if (jarg1) { + arg1 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg1, 0); + if (!arg1) return ; + } + startClient(arg1); + if (arg1) (*jenv)->ReleaseStringUTFChars(jenv, jarg1, (const char *)arg1); +} \ No newline at end of file diff --git a/p2pclient/java/java-p2pd.c b/p2pclient/java/java-p2pd.c index 9a375b9e..ba2980c7 100644 --- a/p2pclient/java/java-p2pd.c +++ b/p2pclient/java/java-p2pd.c @@ -2,12 +2,19 @@ #include "java-p2pd.h" #include "go-p2pd.h" -JNIEXPORT void JNICALL Java_p2pd_startDaemon -(JNIEnv *env, jclass cl){ - startDaemon(); +JNIEXPORT void JNICALL Java_p2pd_startDaemon (JNIEnv *jenv, jclass jcls, jstring jarg1){ + char *arg1 = (char *) 0 ; + (void)jenv; + (void)jcls; + arg1 = 0; + if (jarg1) { + arg1 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg1, 0); + if (!arg1) return ; + } + startDaemon(arg1); + if (arg1) (*jenv)->ReleaseStringUTFChars(jenv, jarg1, (const char *)arg1); } -JNIEXPORT void JNICALL Java_p2pd_stopDaemon -(JNIEnv *env, jclass cl){ +JNIEXPORT void JNICALL Java_p2pd_stopDaemon (JNIEnv *jenv, jclass jcls){ stopDaemon(); } \ No newline at end of file diff --git a/p2pclient/java/p2pc.java b/p2pclient/java/p2pc.java new file mode 100644 index 00000000..c4bb3332 --- /dev/null +++ b/p2pclient/java/p2pc.java @@ -0,0 +1,21 @@ +public class p2pc { + private static final String NAME = "p2pc"; + public static native void startClient(String arg1); + static { + try { + + System.loadLibrary ( NAME ) ; + + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load.\n" + e); + System.exit(1); + } + } + public static void main(String[] args) { + String parsedArgs = NAME; + if( args.length > 0 ){ + parsedArgs += "|" + String.join("|", args); + } + startClient(parsedArgs); + } +} \ No newline at end of file diff --git a/p2pclient/java/p2pd.java b/p2pclient/java/p2pd.java index f8e35632..4a55f918 100644 --- a/p2pclient/java/p2pd.java +++ b/p2pclient/java/p2pd.java @@ -1,12 +1,11 @@ - -import java.util.Arrays; public class p2pd { - public static native void startDaemon(); + private static final String NAME = "p2pd"; + public static native void startDaemon(String arg1); public static native void stopDaemon(); static { try { - System.loadLibrary ( "p2pd" ) ; + System.loadLibrary ( NAME ) ; } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load.\n" + e); @@ -14,6 +13,10 @@ public class p2pd { } } public static void main(String[] args) { - startDaemon(); + String parsedArgs = NAME; + if( args.length > 0 ){ + parsedArgs += "|" + String.join("|", args); + } + startDaemon(parsedArgs); } } \ No newline at end of file diff --git a/p2pd/main.go b/p2pd/main.go index 988e5689..5f2b7070 100644 --- a/p2pd/main.go +++ b/p2pd/main.go @@ -35,15 +35,12 @@ type DaemonConfig struct { func main() { identify.ClientVersion = "p2pd/0.1" - - config := initConfig() - flag.Parse() - + config := initialize() start(config) } -func initConfig() DaemonConfig { - return DaemonConfig{ +func initialize() DaemonConfig { + config := DaemonConfig{ sock: flag.String("sock", "/tmp/p2pd.sock", "daemon control socket path"), quiet: flag.Bool("q", false, "be quiet"), id: flag.String("id", "", "peer identity; private key file"), @@ -55,8 +52,17 @@ func initConfig() DaemonConfig { connMgrLo: flag.Int("connLo", 256, "Connection Manager Low Water mark"), connMgrHi: flag.Int("connHi", 512, "Connection Manager High Water mark"), connMgrGrace: flag.Int("connGrace", 120, "Connection Manager grace period (in seconds)"), - args: flag.Args(), } + flag.Parse() + config.args = flag.Args() + // delete control socket if it already exists + if _, err := os.Stat(*config.sock); !os.IsNotExist(err) { + err = os.Remove(*config.sock) + if err != nil { + log.Fatal(err) + } + } + return config } func start(config DaemonConfig) { @@ -133,22 +139,14 @@ func start(config DaemonConfig) { select {} } -func updateConfig(config, defaultConfig DaemonConfig) DaemonConfig { - //Add fields to config that are found in defaultConfig, but missing from config - config = defaultConfig //TODO temp hack - return config -} - //export startDaemon -func startDaemon() { - //1. pass in config from Java->C->Go StartDaemon() - //Not implemented - //2. call initConfig() to create default config - defaultConfig := initConfig() - //3. call updateConfig(defaultConfig) to replace default config options with configs passed from Java - config := defaultConfig //TODO: temp hack - config = updateConfig(config, defaultConfig) - //3. call start(config) +func startDaemon(args *C.char) { + //replace default config options with configs passed from external source + argsGoString := C.GoString(args) + argsArray := strings.Split(argsGoString, "|") + os.Args = argsArray + //call initialize() to get config + config := initialize() start(config) } From 7b2356fe50ff5bb4c12f7a077750a40dbad3e74a Mon Sep 17 00:00:00 2001 From: jonny rhea Date: Wed, 28 Nov 2018 16:34:23 -0600 Subject: [PATCH 4/7] - build now works on linux --- Makefile | 11 +++++------ p2pc/main.go | 37 +++++++++++++++++++++++++++++++------ p2pd/main.go | 14 ++++++++++---- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 997be84c..822a4c31 100644 --- a/Makefile +++ b/Makefile @@ -4,17 +4,16 @@ OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') ifeq ($(OS), linux) EXT = so OS_LFLAGS = - JAVA_HOME = else ifeq ($(OS), darwin) EXT = dylib OS_LFLAGS = -mmacosx-version-min=$(shell defaults read loginwindow SystemVersionStampAsString) -framework CoreFoundation -framework Security - JAVA_HOME = $(shell /usr/libexec/java_home) endif CC = gcc CFLAGS = -O2 -fPIC LFLAGS = $(OS_LFLAGS) -shared +JAVA_HOME = $(shell java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home' | sed 's/\s*java.home = //') JAVA_INCLUDES = -I$(JAVA_HOME)/include/$(OS) -I$(JAVA_HOME)/include CLASS_PATH = . vpath %.class $(CLASS_PATH) @@ -28,7 +27,7 @@ CNAME = p2pc .PHONY : all java-daemon java-client go-client go-daemon deps gx clean .DEFAULT_GOAL : go-daemon -all: go-daemon go-client java-daemon java-client +all: deps go-daemon go-client java-daemon java-client java-daemon: lib$(DNAME).$(EXT) @@ -46,13 +45,13 @@ go-%.a: java-%.h: cd $(JDIR) && javac -h $(CLASS_PATH) $*.java && mv $*.h $@ -%.class: deps +%.class: cd $(JDIR) && javac $*.java -go-client: deps +go-client: cd $(CDIR) && go install ./... -go-daemon: deps +go-daemon: cd $(DDIR) && go install ./... deps: gx diff --git a/p2pc/main.go b/p2pc/main.go index 9aba0694..eef39568 100644 --- a/p2pc/main.go +++ b/p2pc/main.go @@ -24,6 +24,25 @@ type ClientConfig struct { args []string } +type Command int + +const ( + Identify Command = 0 + Connect Command = 1 + ListenForMessage Command = 2 + SendMessage Command = 3 +) + +func (c Command) String() string { + commands := [...]string{ + "Identify", + "Connect", + "ListenForMessage", + "SendMessage", + } + return commands[c] +} + func main() { identify.ClientVersion = "p2pc/0.1" config := initialize() @@ -49,20 +68,25 @@ func initialize() ClientConfig { } func start(config ClientConfig) { + client, err := p2pclient.NewClient(*config.pathd, *config.pathc) + defer os.Remove(*config.pathc) if err != nil { log.Fatal(err) } - if *config.command == "Identify" { + switch *config.command { + + case Identify.String(): id, addrs, err := client.Identify() if err != nil { log.Fatal(err) } fmt.Printf("Daemon ID: %s\n", id.Pretty()) fmt.Printf("Peer addresses: %v\n", addrs) - } else if *config.command == "Connect" { + + case Connect.String(): id, err := peer.IDB58Decode(config.args[0]) var addrs []multiaddr.Multiaddr addrs = make([]multiaddr.Multiaddr, len(config.args[1:])) @@ -78,7 +102,7 @@ func start(config ClientConfig) { pi, err := client.FindPeer(id) fmt.Printf("ID: %s has multiaddr: %v", pi.ID, pi.Addrs) - } else if *config.command == "ListenForMessage" { + case ListenForMessage.String(): protos := []string{"/test"} done := make(chan struct{}) client.NewStreamHandler(protos, func(info *p2pclient.StreamInfo, conn io.ReadWriteCloser) { @@ -92,7 +116,8 @@ func start(config ClientConfig) { done <- struct{}{} }) select {} - } else if *config.command == "SendMessage" { + + case SendMessage.String(): protos := []string{"/test"} recipientID, err := peer.IDB58Decode(config.args[0]) _, conn, err := client.NewStream(recipientID, protos) @@ -104,9 +129,9 @@ func start(config ClientConfig) { log.Fatal(err) } - } + default: - os.Remove(*config.pathc) + } } //export startClient diff --git a/p2pd/main.go b/p2pd/main.go index 5f2b7070..cf0aabfc 100644 --- a/p2pd/main.go +++ b/p2pd/main.go @@ -12,9 +12,10 @@ import ( libp2p "github.com/libp2p/go-libp2p" connmgr "github.com/libp2p/go-libp2p-connmgr" - p2pd "github.com/libp2p/go-libp2p-daemon" quic "github.com/libp2p/go-libp2p-quic-transport" identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" + + p2pd "github.com/libp2p/go-libp2p-daemon" ) // DaemonConfig defines the configuration options @@ -30,6 +31,8 @@ type DaemonConfig struct { connMgrLo *int connMgrHi *int connMgrGrace *int + QUIC *bool + natPortMap *bool args []string } @@ -52,6 +55,8 @@ func initialize() DaemonConfig { connMgrLo: flag.Int("connLo", 256, "Connection Manager Low Water mark"), connMgrHi: flag.Int("connHi", 512, "Connection Manager High Water mark"), connMgrGrace: flag.Int("connGrace", 120, "Connection Manager grace period (in seconds)"), + QUIC: flag.Bool("quic", false, "Enables the QUIC transport"), + natPortMap: flag.Bool("natPortMap", false, "Enables NAT port mapping"), } flag.Parse() config.args = flag.Args() @@ -82,7 +87,7 @@ func start(config DaemonConfig) { opts = append(opts, libp2p.ConnectionManager(cm)) } - if *QUIC { + if *config.QUIC { opts = append(opts, libp2p.DefaultTransports, libp2p.Transport(quic.NewTransport), @@ -94,11 +99,12 @@ func start(config DaemonConfig) { )) } - if *natPortMap { + if *config.natPortMap { opts = append(opts, libp2p.NATPortMap()) } - d, err := p2pd.NewDaemon(context.Background(), *sock, opts...) + d, err := p2pd.NewDaemon(context.Background(), *config.sock, opts...) + if err != nil { log.Fatal(err) } From 73b95252902972c48adba236ada925fe2ae73424 Mon Sep 17 00:00:00 2001 From: jonny rhea Date: Sun, 9 Dec 2018 13:39:04 -0600 Subject: [PATCH 5/7] using /bin/sh in Makefile and removed printf in favor of Debugf in daemon.go --- Makefile | 2 +- daemon.go | 2 +- p2pd/main.go | 85 +++++++++++++++++++++++++++++++++------------------- 3 files changed, 57 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 822a4c31..13aff827 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SHELL := /bin/bash +SHELL := /bin/sh OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') ifeq ($(OS), linux) diff --git a/daemon.go b/daemon.go index ad14c8b0..3736bd94 100644 --- a/daemon.go +++ b/daemon.go @@ -61,7 +61,7 @@ func NewDaemon(ctx context.Context, path string, opts ...libp2p.Option) (*Daemon signal.Notify(sigc, os.Interrupt, syscall.SIGTERM) go func(ln net.Listener, c chan os.Signal) { sig := <-c - fmt.Printf("Caught signal %s: shutting down.\n", sig) + log.Debugf("Caught signal %s: shutting down.\n", sig) ln.Close() os.Exit(0) }(d.listener, sigc) diff --git a/p2pd/main.go b/p2pd/main.go index cf0aabfc..033f5d1d 100644 --- a/p2pd/main.go +++ b/p2pd/main.go @@ -12,28 +12,33 @@ import ( libp2p "github.com/libp2p/go-libp2p" connmgr "github.com/libp2p/go-libp2p-connmgr" + p2pd "github.com/libp2p/go-libp2p-daemon" + ps "github.com/libp2p/go-libp2p-pubsub" quic "github.com/libp2p/go-libp2p-quic-transport" identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" - - p2pd "github.com/libp2p/go-libp2p-daemon" ) // DaemonConfig defines the configuration options type DaemonConfig struct { - sock *string - quiet *bool - id *string - bootstrap *bool - bootstrapPeers *string - dht *bool - dhtClient *bool - connMgr *bool - connMgrLo *int - connMgrHi *int - connMgrGrace *int - QUIC *bool - natPortMap *bool - args []string + sock *string + quiet *bool + id *string + bootstrap *bool + bootstrapPeers *string + dht *bool + dhtClient *bool + connMgr *bool + connMgrLo *int + connMgrHi *int + connMgrGrace *int + QUIC *bool + natPortMap *bool + pubsub *bool + pubsubRouter *bool + pubsubSign *bool + pubsubSignStrict *bool + gossipsubHeartbeatInterval *int + gossipsubHeartbeatInitialDelay *int } func main() { @@ -44,19 +49,25 @@ func main() { func initialize() DaemonConfig { config := DaemonConfig{ - sock: flag.String("sock", "/tmp/p2pd.sock", "daemon control socket path"), - quiet: flag.Bool("q", false, "be quiet"), - id: flag.String("id", "", "peer identity; private key file"), - bootstrap: flag.Bool("b", false, "connects to bootstrap peers and bootstraps the dht if enabled"), - bootstrapPeers: flag.String("bootstrapPeers", "", "comma separated list of bootstrap peers; defaults to the IPFS DHT peers"), - dht: flag.Bool("dht", true, "Enables the DHT in full node mode"), - dhtClient: flag.Bool("dhtClient", true, "Enables the DHT in client mode"), - connMgr: flag.Bool("connManager", false, "Enables the Connection Manager"), - connMgrLo: flag.Int("connLo", 256, "Connection Manager Low Water mark"), - connMgrHi: flag.Int("connHi", 512, "Connection Manager High Water mark"), - connMgrGrace: flag.Int("connGrace", 120, "Connection Manager grace period (in seconds)"), - QUIC: flag.Bool("quic", false, "Enables the QUIC transport"), - natPortMap: flag.Bool("natPortMap", false, "Enables NAT port mapping"), + sock: flag.String("sock", "/tmp/p2pd.sock", "daemon control socket path"), + quiet: flag.Bool("q", false, "be quiet"), + id: flag.String("id", "", "peer identity; private key file"), + bootstrap: flag.Bool("b", false, "connects to bootstrap peers and bootstraps the dht if enabled"), + bootstrapPeers: flag.String("bootstrapPeers", "", "comma separated list of bootstrap peers; defaults to the IPFS DHT peers"), + dht: flag.Bool("dht", true, "Enables the DHT in full node mode"), + dhtClient: flag.Bool("dhtClient", true, "Enables the DHT in client mode"), + connMgr: flag.Bool("connManager", false, "Enables the Connection Manager"), + connMgrLo: flag.Int("connLo", 256, "Connection Manager Low Water mark"), + connMgrHi: flag.Int("connHi", 512, "Connection Manager High Water mark"), + connMgrGrace: flag.Int("connGrace", 120, "Connection Manager grace period (in seconds)"), + QUIC: flag.Bool("quic", false, "Enables the QUIC transport"), + natPortMap: flag.Bool("natPortMap", false, "Enables NAT port mapping"), + pubsub: flag.Bool("pubsub", false, "Enables pubsub"), + pubsubRouter: flag.String("pubsubRouter", "gossipsub", "Specifies the pubsub router implementation"), + pubsubSign: flag.Bool("pubsubSign", true, "Enables pubsub message signing"), + pubsubSignStrict: flag.Bool("pubsubSignStrict", false, "Enables pubsub strict signature verification"), + gossipsubHeartbeatInterval: flag.Int("gossipsubHeartbeatInterval", 0, "Specifies the gossipsub heartbeat interval"), + gossipsubHeartbeatInitialDelay: flag.Int("gossipsubHeartbeatInitialDelay", 0, "Specifies the gossipsub initial heartbeat delay"), } flag.Parse() config.args = flag.Args() @@ -104,11 +115,25 @@ func start(config DaemonConfig) { } d, err := p2pd.NewDaemon(context.Background(), *config.sock, opts...) - if err != nil { log.Fatal(err) } + if *config.pubsub { + if *config.gossipsubHeartbeatInterval > 0 { + ps.GossipSubHeartbeatInterval = time.Duration(*config.gossipsubHeartbeatInterval) + } + + if *config.gossipsubHeartbeatInitialDelay > 0 { + ps.GossipSubHeartbeatInitialDelay = time.Duration(*config.gossipsubHeartbeatInitialDelay) + } + + err = d.EnablePubsub(*config.pubsubRouter, *config.pubsubSign, *config.pubsubSignStrict) + if err != nil { + log.Fatal(err) + } + } + if *config.dht || *config.dhtClient { err = d.EnableDHT(*config.dhtClient) if err != nil { From a18dc15d873e0c101c67e888ccb424455a3ba0f9 Mon Sep 17 00:00:00 2001 From: jonny rhea Date: Sun, 9 Dec 2018 17:54:12 -0600 Subject: [PATCH 6/7] Project restructuring. Java code is now for example purposes. Made bindings folder for all Makefile and code related to langage bindings --- Makefile | 54 +----- bindings/Makefile | 46 +++++ .../java => bindings/java/examples}/p2pc.java | 0 .../java => bindings/java/examples}/p2pd.java | 0 bindings/java/examples/peerDemo.sh | 9 + {p2pclient => bindings}/java/java-p2pc.c | 3 +- bindings/java/java-p2pc.h | 14 ++ {p2pclient => bindings}/java/java-p2pd.c | 3 +- bindings/java/java-p2pd.h | 16 ++ bindings/main.go | 29 +++ config.mk | 13 ++ p2pc/main.go | 135 +------------- p2pclient/{go => }/dht.go | 0 p2pclient/p2pc.go | 135 ++++++++++++++ p2pclient/{go => }/p2pclient.go | 0 p2pclient/{go => }/streams.go | 0 p2pd.go | 176 ++++++++++++++++++ p2pd/main.go | 174 +---------------- 18 files changed, 460 insertions(+), 347 deletions(-) create mode 100644 bindings/Makefile rename {p2pclient/java => bindings/java/examples}/p2pc.java (100%) rename {p2pclient/java => bindings/java/examples}/p2pd.java (100%) create mode 100755 bindings/java/examples/peerDemo.sh rename {p2pclient => bindings}/java/java-p2pc.c (91%) create mode 100644 bindings/java/java-p2pc.h rename {p2pclient => bindings}/java/java-p2pd.c (92%) create mode 100644 bindings/java/java-p2pd.h create mode 100644 bindings/main.go create mode 100644 config.mk rename p2pclient/{go => }/dht.go (100%) create mode 100644 p2pclient/p2pc.go rename p2pclient/{go => }/p2pclient.go (100%) rename p2pclient/{go => }/streams.go (100%) create mode 100644 p2pd.go diff --git a/Makefile b/Makefile index 13aff827..bdf6ef00 100644 --- a/Makefile +++ b/Makefile @@ -1,52 +1,20 @@ SHELL := /bin/sh -OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') -ifeq ($(OS), linux) - EXT = so - OS_LFLAGS = -else ifeq ($(OS), darwin) - EXT = dylib - OS_LFLAGS = -mmacosx-version-min=$(shell defaults read loginwindow SystemVersionStampAsString) -framework CoreFoundation -framework Security -endif - -CC = gcc -CFLAGS = -O2 -fPIC -LFLAGS = $(OS_LFLAGS) -shared - -JAVA_HOME = $(shell java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home' | sed 's/\s*java.home = //') -JAVA_INCLUDES = -I$(JAVA_HOME)/include/$(OS) -I$(JAVA_HOME)/include -CLASS_PATH = . -vpath %.class $(CLASS_PATH) - -DDIR = p2pd -CDIR = p2pc -JDIR = p2pclient/java -DNAME = p2pd -CNAME = p2pc +include config.mk .PHONY : all java-daemon java-client go-client go-daemon deps gx clean .DEFAULT_GOAL : go-daemon -all: deps go-daemon go-client java-daemon java-client - -java-daemon: lib$(DNAME).$(EXT) - -java-client: lib$(CNAME).$(EXT) - -lib%.$(EXT): java-%.o go-%.a - $(CC) $(LFLAGS) -o $(JDIR)/$@ $(JDIR)/$(firstword $^) $(JDIR)/$(lastword $^) - -java-%.o: go-%.a java-%.h %.class - $(CC) $(CFLAGS) -c $(JDIR)/java-$*.c $(JAVA_INCLUDES) -o $(JDIR)/$@ +all: deps go-daemon go-client go-bindings java-daemon java-client -go-%.a: - go build -o $(JDIR)/$@ -buildmode=c-archive $*/main.go +java-daemon: + cd $(BDIR) && make $@ -java-%.h: - cd $(JDIR) && javac -h $(CLASS_PATH) $*.java && mv $*.h $@ +java-client: + cd $(BDIR) && make $@ -%.class: - cd $(JDIR) && javac $*.java +go-bindings: + cd $(BDIR) && make $@ go-client: cd $(CDIR) && go install ./... @@ -64,9 +32,5 @@ gx: clean: gx-go uw - rm -f $(JDIR)/*.o \ - && rm -f $(JDIR)/*.a \ - && rm -f $(JDIR)/*.$(EXT) \ - && rm -f $(JDIR)/*.class \ - && rm -f $(JDIR)/*.h + cd $(BDIR) && make $@ diff --git a/bindings/Makefile b/bindings/Makefile new file mode 100644 index 00000000..d4b24568 --- /dev/null +++ b/bindings/Makefile @@ -0,0 +1,46 @@ +SHELL := /bin/sh + +include ../config.mk + +CC = gcc +CFLAGS = -O2 -fPIC +LFLAGS = $(OS_LFLAGS) -shared + +JAVA_HOME = $(shell java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home' | sed 's/\s*java.home = //' | sed 's/\/jre//') +JAVA_INCLUDES = -I$(JAVA_HOME)/include/$(OS) -I$(JAVA_HOME)/include +CLASS_PATH = . +vpath %.class $(CLASS_PATH) + +DNAME = p2pd +CNAME = p2pc + +.PHONY : java-daemon java-client go-bindings clean + +java-daemon: lib$(DNAME).$(EXT) $(DNAME).class + +java-client: lib$(CNAME).$(EXT) $(CNAME).class + +go-bindings: java-$(DNAME).o java-$(CNAME).o go-p2p.a + $(CC) $(LFLAGS) -o libp2p.$(EXT) $^ + +lib%.$(EXT): java-%.o go-%.a + $(CC) $(LFLAGS) -o $@ $^ + +java-%.o: go-%.a + $(CC) $(CFLAGS) -c java/java-$*.c $(JAVA_INCLUDES) -o $@ + +go-p2p.a: + go build -o $@ -buildmode=c-archive main.go + +go-%.a: + go build -o $@ -buildmode=c-archive ../$*/main.go + +%.class: + cd java/examples && javac $*.java && mv $@ ../../$@ + +clean: + rm -f *.o \ + && rm -f *.a \ + && rm -f *.$(EXT) \ + && rm -f *.class \ + && rm -f *.h diff --git a/p2pclient/java/p2pc.java b/bindings/java/examples/p2pc.java similarity index 100% rename from p2pclient/java/p2pc.java rename to bindings/java/examples/p2pc.java diff --git a/p2pclient/java/p2pd.java b/bindings/java/examples/p2pd.java similarity index 100% rename from p2pclient/java/p2pd.java rename to bindings/java/examples/p2pd.java diff --git a/bindings/java/examples/peerDemo.sh b/bindings/java/examples/peerDemo.sh new file mode 100755 index 00000000..552865b3 --- /dev/null +++ b/bindings/java/examples/peerDemo.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +tmux new-session -d -s foo 'p2pd' +tmux split-window -v -t 0 'cd ../../ && java p2pd --sock=/tmp/p2pd2.sock' +tmux split-window -h 'sleep 1 && cd ../../ && java p2pc --pathc=/tmp/p2c2.sock --pathd=/tmp/p2pd2.sock --command=ListenForMessage' +tmux split-window -v -t 1 '/bin/bash' +tmux select-layout tile +tmux rename-window 'the dude abides' +tmux attach-session -d \ No newline at end of file diff --git a/p2pclient/java/java-p2pc.c b/bindings/java/java-p2pc.c similarity index 91% rename from p2pclient/java/java-p2pc.c rename to bindings/java/java-p2pc.c index 1b7aac3a..ab7f8f17 100644 --- a/p2pclient/java/java-p2pc.c +++ b/bindings/java/java-p2pc.c @@ -1,6 +1,5 @@ -#include #include "java-p2pc.h" -#include "go-p2pc.h" +#include "../go-p2pc.h" JNIEXPORT void JNICALL Java_p2pc_startClient (JNIEnv *jenv, jclass jcls, jstring jarg1){ char *arg1 = (char *) 0 ; diff --git a/bindings/java/java-p2pc.h b/bindings/java/java-p2pc.h new file mode 100644 index 00000000..9ca71345 --- /dev/null +++ b/bindings/java/java-p2pc.h @@ -0,0 +1,14 @@ +#include + +#ifndef _Included_p2pc +#define _Included_p2pc +#ifdef __cplusplus +extern "C" { +#endif + +JNIEXPORT void JNICALL Java_p2pc_startClient (JNIEnv *, jclass, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/p2pclient/java/java-p2pd.c b/bindings/java/java-p2pd.c similarity index 92% rename from p2pclient/java/java-p2pd.c rename to bindings/java/java-p2pd.c index ba2980c7..e13c0f6b 100644 --- a/p2pclient/java/java-p2pd.c +++ b/bindings/java/java-p2pd.c @@ -1,6 +1,5 @@ -#include #include "java-p2pd.h" -#include "go-p2pd.h" +#include "../go-p2pd.h" JNIEXPORT void JNICALL Java_p2pd_startDaemon (JNIEnv *jenv, jclass jcls, jstring jarg1){ char *arg1 = (char *) 0 ; diff --git a/bindings/java/java-p2pd.h b/bindings/java/java-p2pd.h new file mode 100644 index 00000000..9f72450a --- /dev/null +++ b/bindings/java/java-p2pd.h @@ -0,0 +1,16 @@ +#include + +#ifndef _Included_p2pd +#define _Included_p2pd +#ifdef __cplusplus +extern "C" { +#endif + +JNIEXPORT void JNICALL Java_p2pd_startDaemon (JNIEnv *, jclass, jstring); + +JNIEXPORT void JNICALL Java_p2pd_stopDaemon (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bindings/main.go b/bindings/main.go new file mode 100644 index 00000000..4e0d9f80 --- /dev/null +++ b/bindings/main.go @@ -0,0 +1,29 @@ +package main + +import "C" +import ( + p2pd "github.com/libp2p/go-libp2p-daemon" + p2pc "github.com/libp2p/go-libp2p-daemon/p2pclient" +) + +func main() { +} + +//export startClient +func startClient(args *C.char) { + argsGoString := C.GoString(args) + config := p2pc.ProcessArgs(&argsGoString) + p2pc.Start(config) +} + +//export startDaemon +func startDaemon(args *C.char) { + argsGoString := C.GoString(args) + config := p2pd.ProcessArgs(&argsGoString) + p2pd.Start(config) +} + +//export stopDaemon +func stopDaemon() { + p2pd.Stop() +} diff --git a/config.mk b/config.mk new file mode 100644 index 00000000..7248e120 --- /dev/null +++ b/config.mk @@ -0,0 +1,13 @@ +OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') + +ifeq ($(OS), linux) + EXT = so + OS_LFLAGS = +else ifeq ($(OS), darwin) + EXT = dylib + OS_LFLAGS = -mmacosx-version-min=$(shell defaults read loginwindow SystemVersionStampAsString) -framework CoreFoundation -framework Security +endif + +DDIR = p2pd +CDIR = p2pc +BDIR = bindings \ No newline at end of file diff --git a/p2pc/main.go b/p2pc/main.go index eef39568..1cdb19de 100644 --- a/p2pc/main.go +++ b/p2pc/main.go @@ -2,145 +2,20 @@ package main import "C" import ( - "flag" - "fmt" - "io" - "log" - "os" - "strings" - - peer "github.com/libp2p/go-libp2p-peer" identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" - multiaddr "github.com/multiformats/go-multiaddr" - - "github.com/libp2p/go-libp2p-daemon/p2pclient/go" -) - -// ClientConfig defines the configuration options -type ClientConfig struct { - pathd *string - pathc *string - command *string - args []string -} - -type Command int -const ( - Identify Command = 0 - Connect Command = 1 - ListenForMessage Command = 2 - SendMessage Command = 3 + p2pc "github.com/libp2p/go-libp2p-daemon/p2pclient" ) -func (c Command) String() string { - commands := [...]string{ - "Identify", - "Connect", - "ListenForMessage", - "SendMessage", - } - return commands[c] -} - func main() { identify.ClientVersion = "p2pc/0.1" - config := initialize() - start(config) -} - -func initialize() ClientConfig { - config := ClientConfig{ - pathd: flag.String("pathd", "/tmp/p2pd.sock", "daemon control socket path"), - pathc: flag.String("pathc", "/tmp/p2pc.sock", "client control socket path"), - command: flag.String("command", "Identify", "command to send to the daemon"), - } - flag.Parse() - config.args = flag.Args() - // delete control socket if it already exists - if _, err := os.Stat(*config.pathc); !os.IsNotExist(err) { - err = os.Remove(*config.pathc) - if err != nil { - log.Fatal(err) - } - } - return config -} - -func start(config ClientConfig) { - - client, err := p2pclient.NewClient(*config.pathd, *config.pathc) - defer os.Remove(*config.pathc) - - if err != nil { - log.Fatal(err) - } - - switch *config.command { - - case Identify.String(): - id, addrs, err := client.Identify() - if err != nil { - log.Fatal(err) - } - fmt.Printf("Daemon ID: %s\n", id.Pretty()) - fmt.Printf("Peer addresses: %v\n", addrs) - - case Connect.String(): - id, err := peer.IDB58Decode(config.args[0]) - var addrs []multiaddr.Multiaddr - addrs = make([]multiaddr.Multiaddr, len(config.args[1:])) - for i, arg := range config.args[1:] { - addr, _ := multiaddr.NewMultiaddr(arg) - addrs[i] = addr - } - err = client.Connect(id, addrs) - if err != nil { - log.Fatal(err) - } - - pi, err := client.FindPeer(id) - fmt.Printf("ID: %s has multiaddr: %v", pi.ID, pi.Addrs) - - case ListenForMessage.String(): - protos := []string{"/test"} - done := make(chan struct{}) - client.NewStreamHandler(protos, func(info *p2pclient.StreamInfo, conn io.ReadWriteCloser) { - defer conn.Close() - buf := make([]byte, 1024) - _, err := conn.Read(buf) - if err != nil { - log.Fatal(err) - } - fmt.Println(string(buf)) - done <- struct{}{} - }) - select {} - - case SendMessage.String(): - protos := []string{"/test"} - recipientID, err := peer.IDB58Decode(config.args[0]) - _, conn, err := client.NewStream(recipientID, protos) - if err != nil { - log.Fatal(err) - } - _, err = conn.Write([]byte(config.args[1])) - if err != nil { - log.Fatal(err) - } - - default: - - } + config := p2pc.Initialize() + p2pc.Start(config) } //export startClient func startClient(args *C.char) { - //replace default config options with configs passed from external source argsGoString := C.GoString(args) - argsArray := strings.Split(argsGoString, "|") - os.Args = argsArray - //call initialize() to get config - config := initialize() - start(config) + config := p2pc.ProcessArgs(&argsGoString) + p2pc.Start(config) } diff --git a/p2pclient/go/dht.go b/p2pclient/dht.go similarity index 100% rename from p2pclient/go/dht.go rename to p2pclient/dht.go diff --git a/p2pclient/p2pc.go b/p2pclient/p2pc.go new file mode 100644 index 00000000..e1943a44 --- /dev/null +++ b/p2pclient/p2pc.go @@ -0,0 +1,135 @@ +package p2pclient + +import "C" +import ( + "flag" + "fmt" + "io" + "os" + "strings" + + peer "github.com/libp2p/go-libp2p-peer" + multiaddr "github.com/multiformats/go-multiaddr" +) + +// ClientConfig defines the configuration options +type ClientConfig struct { + pathd *string + pathc *string + command *string + args []string +} + +type Command int + +const ( + Identify Command = 0 + Connect Command = 1 + ListenForMessage Command = 2 + SendMessage Command = 3 +) + +func (c Command) String() string { + commands := [...]string{ + "Identify", + "Connect", + "ListenForMessage", + "SendMessage", + } + return commands[c] +} + +func Initialize() ClientConfig { + config := ClientConfig{ + pathd: flag.String("pathd", "/tmp/p2pd.sock", "daemon control socket path"), + pathc: flag.String("pathc", "/tmp/p2pc.sock", "client control socket path"), + command: flag.String("command", "Identify", "command to send to the daemon"), + } + flag.Parse() + config.args = flag.Args() + // delete control socket if it already exists + if _, err := os.Stat(*config.pathc); !os.IsNotExist(err) { + err = os.Remove(*config.pathc) + if err != nil { + log.Fatal(err) + } + } + return config +} + +func Start(config ClientConfig) { + + client, err := NewClient(*config.pathd, *config.pathc) + defer os.Remove(*config.pathc) + + if err != nil { + log.Fatal(err) + } + + switch *config.command { + + case Identify.String(): + id, addrs, err := client.Identify() + if err != nil { + log.Fatal(err) + } + fmt.Printf("Daemon ID: %s\n", id.Pretty()) + fmt.Printf("Peer addresses: %v\n", addrs) + + case Connect.String(): + id, err := peer.IDB58Decode(config.args[0]) + var addrs []multiaddr.Multiaddr + addrs = make([]multiaddr.Multiaddr, len(config.args[1:])) + for i, arg := range config.args[1:] { + addr, _ := multiaddr.NewMultiaddr(arg) + addrs[i] = addr + } + err = client.Connect(id, addrs) + if err != nil { + log.Fatal(err) + } + + pi, err := client.FindPeer(id) + fmt.Printf("ID: %s has multiaddr: %v", pi.ID, pi.Addrs) + + case ListenForMessage.String(): + fmt.Println("Listening...") + protos := []string{"/test"} + done := make(chan struct{}) + client.NewStreamHandler(protos, func(info *StreamInfo, conn io.ReadWriteCloser) { + defer conn.Close() + buf := make([]byte, 1024) + _, err := conn.Read(buf) + if err != nil { + log.Fatal(err) + } + fmt.Println(string(buf)) + done <- struct{}{} + }) + select {} + + case SendMessage.String(): + protos := []string{"/test"} + recipientID, err := peer.IDB58Decode(config.args[0]) + _, conn, err := client.NewStream(recipientID, protos) + if err != nil { + log.Fatal(err) + } + _, err = conn.Write([]byte(config.args[1])) + if err != nil { + log.Fatal(err) + } + + default: + + } +} + +func ProcessArgs(args *string) ClientConfig { + //replace default config options with configs passed from external source + argsArray := strings.Split(*args, "|") + os.Args = argsArray + //call initialize() to get config + config := Initialize() + return config +} diff --git a/p2pclient/go/p2pclient.go b/p2pclient/p2pclient.go similarity index 100% rename from p2pclient/go/p2pclient.go rename to p2pclient/p2pclient.go diff --git a/p2pclient/go/streams.go b/p2pclient/streams.go similarity index 100% rename from p2pclient/go/streams.go rename to p2pclient/streams.go diff --git a/p2pd.go b/p2pd.go new file mode 100644 index 00000000..2dd30678 --- /dev/null +++ b/p2pd.go @@ -0,0 +1,176 @@ +package p2pd + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "time" + + libp2p "github.com/libp2p/go-libp2p" + connmgr "github.com/libp2p/go-libp2p-connmgr" + ps "github.com/libp2p/go-libp2p-pubsub" + quic "github.com/libp2p/go-libp2p-quic-transport" +) + +// DaemonConfig defines the configuration options +type DaemonConfig struct { + sock *string + quiet *bool + id *string + bootstrap *bool + bootstrapPeers *string + dht *bool + dhtClient *bool + connMgr *bool + connMgrLo *int + connMgrHi *int + connMgrGrace *int + QUIC *bool + natPortMap *bool + pubsub *bool + pubsubRouter *string + pubsubSign *bool + pubsubSignStrict *bool + gossipsubHeartbeatInterval *int + gossipsubHeartbeatInitialDelay *int + args []string +} + +func Initialize() DaemonConfig { + config := DaemonConfig{ + sock: flag.String("sock", "/tmp/p2pd.sock", "daemon control socket path"), + quiet: flag.Bool("q", false, "be quiet"), + id: flag.String("id", "", "peer identity; private key file"), + bootstrap: flag.Bool("b", false, "connects to bootstrap peers and bootstraps the dht if enabled"), + bootstrapPeers: flag.String("bootstrapPeers", "", "comma separated list of bootstrap peers; defaults to the IPFS DHT peers"), + dht: flag.Bool("dht", true, "Enables the DHT in full node mode"), + dhtClient: flag.Bool("dhtClient", true, "Enables the DHT in client mode"), + connMgr: flag.Bool("connManager", false, "Enables the Connection Manager"), + connMgrLo: flag.Int("connLo", 256, "Connection Manager Low Water mark"), + connMgrHi: flag.Int("connHi", 512, "Connection Manager High Water mark"), + connMgrGrace: flag.Int("connGrace", 120, "Connection Manager grace period (in seconds)"), + QUIC: flag.Bool("quic", false, "Enables the QUIC transport"), + natPortMap: flag.Bool("natPortMap", false, "Enables NAT port mapping"), + pubsub: flag.Bool("pubsub", false, "Enables pubsub"), + pubsubRouter: flag.String("pubsubRouter", "gossipsub", "Specifies the pubsub router implementation"), + pubsubSign: flag.Bool("pubsubSign", true, "Enables pubsub message signing"), + pubsubSignStrict: flag.Bool("pubsubSignStrict", false, "Enables pubsub strict signature verification"), + gossipsubHeartbeatInterval: flag.Int("gossipsubHeartbeatInterval", 0, "Specifies the gossipsub heartbeat interval"), + gossipsubHeartbeatInitialDelay: flag.Int("gossipsubHeartbeatInitialDelay", 0, "Specifies the gossipsub initial heartbeat delay"), + } + flag.Parse() + config.args = flag.Args() + // delete control socket if it already exists + if _, err := os.Stat(*config.sock); !os.IsNotExist(err) { + err = os.Remove(*config.sock) + if err != nil { + log.Fatal(err) + } + } + return config +} + +func Start(config DaemonConfig) { + var opts []libp2p.Option + + if *config.id != "" { + key, err := ReadIdentity(*config.id) + if err != nil { + log.Fatal(err) + } + + opts = append(opts, libp2p.Identity(key)) + } + + if *config.connMgr { + cm := connmgr.NewConnManager(*config.connMgrLo, *config.connMgrHi, time.Duration(*config.connMgrGrace)) + opts = append(opts, libp2p.ConnectionManager(cm)) + } + + if *config.QUIC { + opts = append(opts, + libp2p.DefaultTransports, + libp2p.Transport(quic.NewTransport), + libp2p.ListenAddrStrings( + "/ip4/0.0.0.0/tcp/0", + "/ip4/0.0.0.0/udp/0/quic", + "/ip6/::1/tcp/0", + "/ip6/::1/udp/0/quic", + )) + } + + if *config.natPortMap { + opts = append(opts, libp2p.NATPortMap()) + } + + d, err := NewDaemon(context.Background(), *config.sock, opts...) + if err != nil { + log.Fatal(err) + } + + if *config.pubsub { + if *config.gossipsubHeartbeatInterval > 0 { + ps.GossipSubHeartbeatInterval = time.Duration(*config.gossipsubHeartbeatInterval) + } + + if *config.gossipsubHeartbeatInitialDelay > 0 { + ps.GossipSubHeartbeatInitialDelay = time.Duration(*config.gossipsubHeartbeatInitialDelay) + } + + err = d.EnablePubsub(*config.pubsubRouter, *config.pubsubSign, *config.pubsubSignStrict) + if err != nil { + log.Fatal(err) + } + } + + if *config.dht || *config.dhtClient { + err = d.EnableDHT(*config.dhtClient) + if err != nil { + log.Fatal(err) + } + } + + if *config.bootstrapPeers != "" { + BootstrapPeers = strings.Split(*config.bootstrapPeers, ",") + } + + if *config.bootstrap { + err = d.Bootstrap() + if err != nil { + log.Fatal(err) + } + } + + if !*config.quiet { + fmt.Printf("Control socket: %s\n", *config.sock) + fmt.Printf("Peer ID: %s\n", d.ID().Pretty()) + fmt.Printf("Peer Addrs:\n") + for _, addr := range d.Addrs() { + fmt.Printf("%s\n", addr.String()) + } + if *config.bootstrap && *config.bootstrapPeers != "" { + fmt.Printf("Bootstrap peers:\n") + for _, p := range BootstrapPeers { + fmt.Printf("%s\n", p) + } + } + } + + select {} +} + +func Stop() { + p, _ := os.FindProcess(os.Getpid()) + p.Signal(os.Interrupt) +} + +func ProcessArgs(args *string) DaemonConfig { + //replace default config options with configs passed from external source + argsArray := strings.Split(*args, "|") + os.Args = argsArray + //call initialize() to get config + config := Initialize() + return config +} diff --git a/p2pd/main.go b/p2pd/main.go index 033f5d1d..3efc0e82 100644 --- a/p2pd/main.go +++ b/p2pd/main.go @@ -2,187 +2,25 @@ package main import "C" import ( - "context" - "flag" - "fmt" - "log" - "os" - "strings" - "time" + identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" - libp2p "github.com/libp2p/go-libp2p" - connmgr "github.com/libp2p/go-libp2p-connmgr" p2pd "github.com/libp2p/go-libp2p-daemon" - ps "github.com/libp2p/go-libp2p-pubsub" - quic "github.com/libp2p/go-libp2p-quic-transport" - identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" ) -// DaemonConfig defines the configuration options -type DaemonConfig struct { - sock *string - quiet *bool - id *string - bootstrap *bool - bootstrapPeers *string - dht *bool - dhtClient *bool - connMgr *bool - connMgrLo *int - connMgrHi *int - connMgrGrace *int - QUIC *bool - natPortMap *bool - pubsub *bool - pubsubRouter *bool - pubsubSign *bool - pubsubSignStrict *bool - gossipsubHeartbeatInterval *int - gossipsubHeartbeatInitialDelay *int -} - func main() { identify.ClientVersion = "p2pd/0.1" - config := initialize() - start(config) -} - -func initialize() DaemonConfig { - config := DaemonConfig{ - sock: flag.String("sock", "/tmp/p2pd.sock", "daemon control socket path"), - quiet: flag.Bool("q", false, "be quiet"), - id: flag.String("id", "", "peer identity; private key file"), - bootstrap: flag.Bool("b", false, "connects to bootstrap peers and bootstraps the dht if enabled"), - bootstrapPeers: flag.String("bootstrapPeers", "", "comma separated list of bootstrap peers; defaults to the IPFS DHT peers"), - dht: flag.Bool("dht", true, "Enables the DHT in full node mode"), - dhtClient: flag.Bool("dhtClient", true, "Enables the DHT in client mode"), - connMgr: flag.Bool("connManager", false, "Enables the Connection Manager"), - connMgrLo: flag.Int("connLo", 256, "Connection Manager Low Water mark"), - connMgrHi: flag.Int("connHi", 512, "Connection Manager High Water mark"), - connMgrGrace: flag.Int("connGrace", 120, "Connection Manager grace period (in seconds)"), - QUIC: flag.Bool("quic", false, "Enables the QUIC transport"), - natPortMap: flag.Bool("natPortMap", false, "Enables NAT port mapping"), - pubsub: flag.Bool("pubsub", false, "Enables pubsub"), - pubsubRouter: flag.String("pubsubRouter", "gossipsub", "Specifies the pubsub router implementation"), - pubsubSign: flag.Bool("pubsubSign", true, "Enables pubsub message signing"), - pubsubSignStrict: flag.Bool("pubsubSignStrict", false, "Enables pubsub strict signature verification"), - gossipsubHeartbeatInterval: flag.Int("gossipsubHeartbeatInterval", 0, "Specifies the gossipsub heartbeat interval"), - gossipsubHeartbeatInitialDelay: flag.Int("gossipsubHeartbeatInitialDelay", 0, "Specifies the gossipsub initial heartbeat delay"), - } - flag.Parse() - config.args = flag.Args() - // delete control socket if it already exists - if _, err := os.Stat(*config.sock); !os.IsNotExist(err) { - err = os.Remove(*config.sock) - if err != nil { - log.Fatal(err) - } - } - return config -} - -func start(config DaemonConfig) { - var opts []libp2p.Option - - if *config.id != "" { - key, err := p2pd.ReadIdentity(*config.id) - if err != nil { - log.Fatal(err) - } - - opts = append(opts, libp2p.Identity(key)) - } - - if *config.connMgr { - cm := connmgr.NewConnManager(*config.connMgrLo, *config.connMgrHi, time.Duration(*config.connMgrGrace)) - opts = append(opts, libp2p.ConnectionManager(cm)) - } - - if *config.QUIC { - opts = append(opts, - libp2p.DefaultTransports, - libp2p.Transport(quic.NewTransport), - libp2p.ListenAddrStrings( - "/ip4/0.0.0.0/tcp/0", - "/ip4/0.0.0.0/udp/0/quic", - "/ip6/::1/tcp/0", - "/ip6/::1/udp/0/quic", - )) - } - - if *config.natPortMap { - opts = append(opts, libp2p.NATPortMap()) - } - - d, err := p2pd.NewDaemon(context.Background(), *config.sock, opts...) - if err != nil { - log.Fatal(err) - } - - if *config.pubsub { - if *config.gossipsubHeartbeatInterval > 0 { - ps.GossipSubHeartbeatInterval = time.Duration(*config.gossipsubHeartbeatInterval) - } - - if *config.gossipsubHeartbeatInitialDelay > 0 { - ps.GossipSubHeartbeatInitialDelay = time.Duration(*config.gossipsubHeartbeatInitialDelay) - } - - err = d.EnablePubsub(*config.pubsubRouter, *config.pubsubSign, *config.pubsubSignStrict) - if err != nil { - log.Fatal(err) - } - } - - if *config.dht || *config.dhtClient { - err = d.EnableDHT(*config.dhtClient) - if err != nil { - log.Fatal(err) - } - } - - if *config.bootstrapPeers != "" { - p2pd.BootstrapPeers = strings.Split(*config.bootstrapPeers, ",") - } - - if *config.bootstrap { - err = d.Bootstrap() - if err != nil { - log.Fatal(err) - } - } - - if !*config.quiet { - fmt.Printf("Control socket: %s\n", *config.sock) - fmt.Printf("Peer ID: %s\n", d.ID().Pretty()) - fmt.Printf("Peer Addrs:\n") - for _, addr := range d.Addrs() { - fmt.Printf("%s\n", addr.String()) - } - if *config.bootstrap && *config.bootstrapPeers != "" { - fmt.Printf("Bootstrap peers:\n") - for _, p := range p2pd.BootstrapPeers { - fmt.Printf("%s\n", p) - } - } - } - - select {} + config := p2pd.Initialize() + p2pd.Start(config) } //export startDaemon func startDaemon(args *C.char) { - //replace default config options with configs passed from external source argsGoString := C.GoString(args) - argsArray := strings.Split(argsGoString, "|") - os.Args = argsArray - //call initialize() to get config - config := initialize() - start(config) + config := p2pd.ProcessArgs(&argsGoString) + p2pd.Start(config) } //export stopDaemon func stopDaemon() { - p, _ := os.FindProcess(os.Getpid()) - p.Signal(os.Interrupt) + p2pd.Stop() } From aa4e06c9ec47a3c23201d013cac53efc6bbb4fd0 Mon Sep 17 00:00:00 2001 From: jonny rhea Date: Mon, 10 Dec 2018 07:44:59 -0600 Subject: [PATCH 7/7] fixed package references to p2pclient in tests --- test/dht_test.go | 2 +- test/integration_test.go | 2 +- test/mock_daemon.go | 2 +- test/utils.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/dht_test.go b/test/dht_test.go index e19aad0b..dfe28cf4 100644 --- a/test/dht_test.go +++ b/test/dht_test.go @@ -11,7 +11,7 @@ import ( crypto "github.com/libp2p/go-libp2p-crypto" peer "github.com/libp2p/go-libp2p-peer" - "github.com/libp2p/go-libp2p-daemon/p2pclient/go" + "github.com/libp2p/go-libp2p-daemon/p2pclient" pb "github.com/libp2p/go-libp2p-daemon/pb" ) diff --git a/test/integration_test.go b/test/integration_test.go index b9a54c1f..4c9eafe1 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -6,7 +6,7 @@ import ( "time" "github.com/libp2p/go-libp2p-daemon" - "github.com/libp2p/go-libp2p-daemon/p2pclient/go" + "github.com/libp2p/go-libp2p-daemon/p2pclient" peer "github.com/libp2p/go-libp2p-peer" ma "github.com/multiformats/go-multiaddr" ) diff --git a/test/mock_daemon.go b/test/mock_daemon.go index c901bf78..b9a47391 100644 --- a/test/mock_daemon.go +++ b/test/mock_daemon.go @@ -8,7 +8,7 @@ import ( ggio "github.com/gogo/protobuf/io" "github.com/gogo/protobuf/proto" - "github.com/libp2p/go-libp2p-daemon/p2pclient/go" + "github.com/libp2p/go-libp2p-daemon/p2pclient" pb "github.com/libp2p/go-libp2p-daemon/pb" ) diff --git a/test/utils.go b/test/utils.go index c6c4c3cf..56bdd74b 100644 --- a/test/utils.go +++ b/test/utils.go @@ -13,7 +13,7 @@ import ( cid "github.com/ipfs/go-cid" crypto "github.com/libp2p/go-libp2p-crypto" p2pd "github.com/libp2p/go-libp2p-daemon" - "github.com/libp2p/go-libp2p-daemon/p2pclient/go" + "github.com/libp2p/go-libp2p-daemon/p2pclient" pb "github.com/libp2p/go-libp2p-daemon/pb" peer "github.com/libp2p/go-libp2p-peer" peertest "github.com/libp2p/go-libp2p-peer/test"