diff options
author | Trumeet <yuuta@yuuta.moe> | 2021-03-27 16:01:37 -0700 |
---|---|---|
committer | Trumeet <yuuta@yuuta.moe> | 2021-03-27 16:01:37 -0700 |
commit | 6166ddaf522f01ccc2e7c65ec98f7e48fa061c9b (patch) | |
tree | ef2edac5eff0088f6080bc9f87482270905c801d | |
parent | 2ee583fb60ae79a7d1a0ab971cc0eafa488bd079 (diff) | |
download | dn42peering-6166ddaf522f01ccc2e7c65ec98f7e48fa061c9b.tar dn42peering-6166ddaf522f01ccc2e7c65ec98f7e48fa061c9b.tar.gz dn42peering-6166ddaf522f01ccc2e7c65ec98f7e48fa061c9b.tar.bz2 dn42peering-6166ddaf522f01ccc2e7c65ec98f7e48fa061c9b.zip |
feat(central): move gRPC logic into a separate verticle and fix shutdown issuesv1.7
12 files changed, 708 insertions, 75 deletions
diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 6620e8f..7480914 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -48,6 +48,14 @@ </processorPath> <module name="dn42peering.central.main" /> </profile> + <profile name="Gradle Imported" enabled="true"> + <outputRelativeToContentRoot value="true" /> + <processorPath useClasspath="false"> + <entry name="$USER_HOME$/.local/share/gradle/caches/modules-2/files-2.1/io.vertx/vertx-codegen/4.0.3/416429ea05c4c43afcf4104ab488bda10f43ba87/vertx-codegen-4.0.3-processor.jar" /> + <entry name="$USER_HOME$/.local/share/gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-core/2.11.3/c2351800432bdbdd8284c3f5a7f0782a352aa84a/jackson-core-2.11.3.jar" /> + </processorPath> + <module name="dn42peering.rpc-common.main" /> + </profile> </annotationProcessing> <bytecodeTargetLevel target="1.8" /> </component> diff --git a/central/src/main/java/moe/yuuta/dn42peering/Main.java b/central/src/main/java/moe/yuuta/dn42peering/Main.java index 595cb30..5fa6690 100644 --- a/central/src/main/java/moe/yuuta/dn42peering/Main.java +++ b/central/src/main/java/moe/yuuta/dn42peering/Main.java @@ -8,6 +8,7 @@ import moe.yuuta.dn42peering.asn.ASNVerticle; import moe.yuuta.dn42peering.node.NodeVerticle; import moe.yuuta.dn42peering.peer.PeerVerticle; import moe.yuuta.dn42peering.portal.HTTPPortalVerticle; +import moe.yuuta.dn42peering.provision.ProvisionVerticle; import moe.yuuta.dn42peering.whois.WhoisVerticle; import javax.annotation.Nonnull; @@ -40,6 +41,7 @@ public class Main { Future.<String>future(f -> vertx.deployVerticle(WhoisVerticle.class.getName(), options, f)), Future.<String>future(f -> vertx.deployVerticle(ASNVerticle.class.getName(), options, f)), Future.<String>future(f -> vertx.deployVerticle(NodeVerticle.class.getName(), options, f)), + Future.<String>future(f -> vertx.deployVerticle(ProvisionVerticle.class.getName(), options, f)), Future.<String>future(f -> vertx.deployVerticle(HTTPPortalVerticle.class.getName(), options, f)) ).onComplete(res -> { if (res.succeeded()) { diff --git a/central/src/main/java/moe/yuuta/dn42peering/manage/ManageHandler.java b/central/src/main/java/moe/yuuta/dn42peering/manage/ManageHandler.java index d2d66a3..5127df0 100644 --- a/central/src/main/java/moe/yuuta/dn42peering/manage/ManageHandler.java +++ b/central/src/main/java/moe/yuuta/dn42peering/manage/ManageHandler.java @@ -27,9 +27,8 @@ import io.vertx.json.schema.SchemaParser; import io.vertx.json.schema.SchemaRouter; import io.vertx.json.schema.SchemaRouterOptions; import io.vertx.json.schema.common.dsl.ObjectSchemaBuilder; -import moe.yuuta.dn42peering.agent.proto.BGPRequest; -import moe.yuuta.dn42peering.agent.proto.VertxAgentGrpc; -import moe.yuuta.dn42peering.agent.proto.WGRequest; +import moe.yuuta.dn42peering.provision.BGPRequestCommon; +import moe.yuuta.dn42peering.provision.WGRequestCommon; import moe.yuuta.dn42peering.asn.IASNService; import moe.yuuta.dn42peering.jaba.Pair; import moe.yuuta.dn42peering.node.INodeService; @@ -40,6 +39,7 @@ import moe.yuuta.dn42peering.peer.ProvisionStatus; import moe.yuuta.dn42peering.portal.FormException; import moe.yuuta.dn42peering.portal.HTTPException; import moe.yuuta.dn42peering.portal.ISubRouter; +import moe.yuuta.dn42peering.provision.IProvisionRemoteService; import moe.yuuta.dn42peering.whois.IWhoisService; import moe.yuuta.dn42peering.whois.WhoisObject; import org.apache.commons.validator.routines.InetAddressValidator; @@ -64,6 +64,7 @@ public class ManageHandler implements ISubRouter { final IWhoisService whoisService = IWhoisService.createProxy(vertx, IWhoisService.ADDRESS); final IPeerService peerService = IPeerService.createProxy(vertx); final INodeService nodeService = INodeService.createProxy(vertx); + final IProvisionRemoteService provisionService = IProvisionRemoteService.create(vertx); final TemplateEngine engine = FreeMarkerTemplateEngine.create(vertx, "ftlh"); final Router router = Router.router(vertx); @@ -209,7 +210,7 @@ public class ManageHandler implements ISubRouter { .setStatusCode(303) .putHeader("Location", "/manage") .end(); - provisionPeer(vertx, nodeService, peer).onComplete(ar -> + provisionPeer(nodeService, provisionService, peer).onComplete(ar -> this.handleProvisionResult(peerService, peer, ar)); }) .onFailure(err -> { @@ -382,7 +383,7 @@ public class ManageHandler implements ISubRouter { .end(); final Peer existingPeer = pair.a; final Peer inPeer = pair.b; - reloadPeer(vertx, nodeService, existingPeer, inPeer).onComplete(ar -> + reloadPeer(nodeService, provisionService, existingPeer, inPeer).onComplete(ar -> this.handleProvisionResult(peerService, inPeer, ar)); }) .onFailure(err -> { @@ -435,7 +436,7 @@ public class ManageHandler implements ISubRouter { } return Future.succeededFuture(peer); }) - .compose(peer -> unprovisionPeer(vertx, nodeService, peer)) + .compose(peer -> unprovisionPeer(nodeService, provisionService, peer)) .compose(_v -> Future.<Void>future(f -> peerService.deletePeer(asn, id, f))) .onSuccess(_id -> ctx.response() .setStatusCode(303) @@ -961,8 +962,8 @@ public class ManageHandler implements ISubRouter { } @Nonnull - private Future<Void> reloadPeer(@Nonnull Vertx vertx, - @Nonnull INodeService nodeService, + private Future<Void> reloadPeer(@Nonnull INodeService nodeService, + @Nonnull IProvisionRemoteService provisionService, @Nonnull Peer existingPeer, @Nonnull Peer inPeer) { // Check if we can reload on the fly. // Otherwise, we can only deprovision and provision. @@ -1004,33 +1005,37 @@ public class ManageHandler implements ISubRouter { return Future.succeededFuture(node); }) .compose(node -> { - final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(node.toChannel(vertx)); switch (existingPeer.getType()) { case WIREGUARD: - return stub.reloadWG( - inPeer.toWGRequest().setNode(node.toRPCNode()).build() - ).compose(wgReply -> Future.succeededFuture(new Pair<>(node, wgReply.getDevice()))); + final WGRequestCommon wgReq = inPeer.toWGRequest(); + wgReq.setNode(node.toRPCNode()); + return Future.<String>future(f -> provisionService.reloadWG( + node.toRPCNode(), + wgReq, + f) + ).compose(device -> Future.succeededFuture(new Pair<>(node, device))); default: throw new UnsupportedOperationException("Bug: Unknown type."); } }) .compose(pair -> { - final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(pair.a.toChannel(vertx)); - return stub.reloadBGP(inPeer.toBGPRequest() - .setNode(pair.a.toRPCNode()) - .setDevice(pair.b) - .build()) - .compose(reply -> Future.succeededFuture(null)); + final BGPRequestCommon bgpReq = inPeer.toBGPRequest(); + bgpReq.setNode(pair.a.toRPCNode()); + bgpReq.setDevice(pair.b); + return Future.future(f -> provisionService.reloadBGP( + pair.a.toRPCNode(), + bgpReq, + f)); }); } else { - future = unprovisionPeer(vertx, nodeService, existingPeer) - .compose(f -> provisionPeer(vertx, nodeService, inPeer)); + future = unprovisionPeer(nodeService, provisionService, existingPeer) + .compose(f -> provisionPeer(nodeService, provisionService, inPeer)); } return future; } - private Future<Void> unprovisionPeer(@Nonnull Vertx vertx, - @Nonnull INodeService nodeService, + private Future<Void> unprovisionPeer(@Nonnull INodeService nodeService, + @Nonnull IProvisionRemoteService provisionService, @Nonnull Peer existingPeer) { return Future.<Node>future(f -> nodeService.getNode(existingPeer.getNode(), f)) .compose(node -> { @@ -1040,27 +1045,43 @@ public class ManageHandler implements ISubRouter { return Future.succeededFuture(node); }) .compose(node -> { - final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(node.toChannel(vertx)); switch (existingPeer.getType()) { case WIREGUARD: - return stub.deleteWG(WGRequest.newBuilder().setId(existingPeer.getId()).build()) - .compose(wgReply -> Future.succeededFuture(node)); + return Future.<Void>future(f -> provisionService.deleteWG( + node.toRPCNode(), + new WGRequestCommon(null, + (long)existingPeer.getId(), + null, + null, + null, + null, + null, + null, + null), + f)) + .compose(res -> Future.succeededFuture(node)); default: throw new UnsupportedOperationException("Bug: Unknown type."); } }) .compose(node -> { - final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(node.toChannel(vertx)); - return stub.deleteBGP(BGPRequest.newBuilder().setId(existingPeer.getId()) - .build()) - .compose(reply -> Future.succeededFuture(null)); + return Future.future(f -> provisionService.deleteBGP( + node.toRPCNode(), + new BGPRequestCommon(null, + (long)existingPeer.getId(), + null, + null, + null, + null, + null), + f)); }) ; } @Nonnull - private Future<Void> provisionPeer(@Nonnull Vertx vertx, - @Nonnull INodeService nodeService, + private Future<Void> provisionPeer(@Nonnull INodeService nodeService, + @Nonnull IProvisionRemoteService provisionService, @Nonnull Peer inPeer) { return Future.<Node>future(f -> nodeService.getNode(inPeer.getNode(), f)) .compose(node -> { @@ -1070,23 +1091,27 @@ public class ManageHandler implements ISubRouter { return Future.succeededFuture(node); }) .compose(node -> { - final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(node.toChannel(vertx)); switch (inPeer.getType()) { case WIREGUARD: - return stub.provisionWG( - inPeer.toWGRequest().setNode(node.toRPCNode()).build() - ).compose(wgReply -> Future.succeededFuture(new Pair<>(node, wgReply.getDevice()))); + final WGRequestCommon wgReq = inPeer.toWGRequest(); + wgReq.setNode(node.toRPCNode()); + return Future.<String>future(f -> provisionService.provisionWG( + node.toRPCNode(), + wgReq, + f) + ).compose(device -> Future.succeededFuture(new Pair<>(node, device))); default: throw new UnsupportedOperationException("Bug: Unknown type."); } }) .compose(pair -> { - final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(pair.a.toChannel(vertx)); - return stub.provisionBGP(inPeer.toBGPRequest() - .setNode(pair.a.toRPCNode()) - .setDevice(pair.b) - .build()) - .compose(reply -> Future.succeededFuture(null)); + final BGPRequestCommon bgpReq = inPeer.toBGPRequest(); + bgpReq.setNode(pair.a.toRPCNode()); + bgpReq.setDevice(pair.b); + return Future.future(f -> provisionService.provisionBGP( + pair.a.toRPCNode(), + bgpReq, + f)); }); } diff --git a/central/src/main/java/moe/yuuta/dn42peering/node/Node.java b/central/src/main/java/moe/yuuta/dn42peering/node/Node.java index 5135947..250930f 100644 --- a/central/src/main/java/moe/yuuta/dn42peering/node/Node.java +++ b/central/src/main/java/moe/yuuta/dn42peering/node/Node.java @@ -11,6 +11,7 @@ import io.vertx.sqlclient.templates.annotations.Column; import io.vertx.sqlclient.templates.annotations.ParametersMapped; import io.vertx.sqlclient.templates.annotations.RowMapped; import io.vertx.sqlclient.templates.annotations.TemplateParameter; +import moe.yuuta.dn42peering.provision.NodeCommon; import moe.yuuta.dn42peering.peer.Peer; import javax.annotation.Nonnull; @@ -107,21 +108,13 @@ public class Node { @GenIgnore @Nonnull - public moe.yuuta.dn42peering.agent.proto.Node toRPCNode() { - return moe.yuuta.dn42peering.agent.proto.Node.newBuilder() - .setId(id) - .setIpv4(dn42Ip4) - .setIpv6(dn42Ip6) - .setIpv6NonLL(dn42Ip6NonLL) - .build(); - } - - @GenIgnore - @Nonnull - public ManagedChannel toChannel(@Nonnull Vertx vertx) { - return VertxChannelBuilder.forAddress(vertx, internalIp, internalPort) - .usePlaintext() - .build(); + public NodeCommon toRPCNode() { + return new NodeCommon(id, + dn42Ip4, + dn42Ip6, + dn42Ip6NonLL, + internalIp, + internalPort); } // BEGIN GETTER / SETTER diff --git a/central/src/main/java/moe/yuuta/dn42peering/peer/Peer.java b/central/src/main/java/moe/yuuta/dn42peering/peer/Peer.java index e7f31fa..b54f4e0 100644 --- a/central/src/main/java/moe/yuuta/dn42peering/peer/Peer.java +++ b/central/src/main/java/moe/yuuta/dn42peering/peer/Peer.java @@ -10,8 +10,8 @@ import io.vertx.sqlclient.templates.annotations.Column; import io.vertx.sqlclient.templates.annotations.ParametersMapped; import io.vertx.sqlclient.templates.annotations.RowMapped; import io.vertx.sqlclient.templates.annotations.TemplateParameter; -import moe.yuuta.dn42peering.agent.proto.BGPRequest; -import moe.yuuta.dn42peering.agent.proto.WGRequest; +import moe.yuuta.dn42peering.provision.BGPRequestCommon; +import moe.yuuta.dn42peering.provision.WGRequestCommon; import javax.annotation.Nonnull; import java.io.IOException; @@ -193,26 +193,29 @@ public class Peer { } @GenIgnore - public WGRequest.Builder toWGRequest() { - return WGRequest.newBuilder() - .setId(getId()) - .setListenPort(Integer.parseInt(calcWireGuardPort())) - .setEndpoint(getWgEndpoint() == null && getWgEndpointPort() == null ? "" : String.format("%s:%d", getWgEndpoint(), getWgEndpointPort())) - .setPeerPubKey(getWgPeerPubkey()) - .setSelfPrivKey(getWgSelfPrivKey()) - .setSelfPresharedSecret(getWgPresharedSecret()) - .setPeerIPv4(getIpv4()) - .setPeerIPv6(getIpv6() == null ? "" : getIpv6()); + public WGRequestCommon toWGRequest() { + return new WGRequestCommon( + null, + (long)id, + Integer.parseInt(calcWireGuardPort()), + wgEndpoint == null && wgEndpointPort == null ? "" : + String.format("%s:%d", getWgEndpoint(), getWgEndpointPort()), + wgPeerPubkey, + wgSelfPrivKey, + wgPresharedSecret, + ipv4, + ipv6 == null ? "" : ipv6); } @GenIgnore - public BGPRequest.Builder toBGPRequest() { - return BGPRequest.newBuilder() - .setId(getId()) - .setAsn(getAsn()) - .setIpv4(getIpv4()) - .setIpv6(getIpv6() == null ? "" : getIpv6()) - .setMpbgp(isMpbgp()); + public BGPRequestCommon toBGPRequest() { + return new BGPRequestCommon(null, + (long)id, + asn, + mpbgp, + ipv4, + ipv6 == null ? "" : ipv6, + null); } // START GETTERS / SETTERS diff --git a/central/src/main/java/moe/yuuta/dn42peering/provision/BGPRequestCommon.java b/central/src/main/java/moe/yuuta/dn42peering/provision/BGPRequestCommon.java new file mode 100644 index 0000000..8ca9ea2 --- /dev/null +++ b/central/src/main/java/moe/yuuta/dn42peering/provision/BGPRequestCommon.java @@ -0,0 +1,127 @@ +package moe.yuuta.dn42peering.provision; + +import io.vertx.codegen.annotations.DataObject; +import io.vertx.core.json.JsonObject; +import moe.yuuta.dn42peering.agent.proto.BGPRequest; + +import javax.annotation.Nonnull; + +@DataObject +public class BGPRequestCommon { + private NodeCommon node; + private Long id; + private String asn; + private Boolean mpbgp; + private String ipv4; + private String ipv6; + private String device; + + public BGPRequestCommon(NodeCommon node, + Long id, + String asn, + Boolean mpbgp, + String ipv4, + String ipv6, + String device) { + this.node = node; + this.id = id; + this.asn = asn; + this.mpbgp = mpbgp; + this.ipv4 = ipv4; + this.ipv6 = ipv6; + this.device = device; + } + + public BGPRequestCommon(@Nonnull JsonObject json) { + if(json.getValue("node") != null) this.node = new NodeCommon(json.getJsonObject("node")); + if(json.getValue("id") != null) this.id = json.getLong("id"); + this.asn = json.getString("asn"); + if(json.getValue("mpbgp") != null) this.mpbgp = json.getBoolean("mpbgp"); + this.ipv4 = json.getString("ipv4"); + this.ipv6 = json.getString("ipv6"); + this.device = json.getString("device"); + } + + @Nonnull + public JsonObject toJson() { + return new JsonObject() + .put("node", node == null ? null : node.toJson()) + .put("id", id) + .put("asn", asn) + .put("mpbgp", mpbgp) + .put("ipv4", ipv4) + .put("ipv6", ipv6) + .put("device", device); + } + + @Nonnull + public BGPRequest toGRPC() { + final BGPRequest.Builder builder = BGPRequest.newBuilder(); + if(node != null) builder.setNode(node.toGRPC()); + if(id != null) builder.setId(id); + if(asn != null) builder.setAsn(asn); + if(mpbgp != null) builder.setMpbgp(mpbgp); + if(ipv4 != null) builder.setIpv4(ipv4); + if(ipv6 != null) builder.setIpv6(ipv6); + if(device != null) builder.setDevice(device); + return builder.build(); + } + + // Getters & Setters + + public NodeCommon getNode() { + return node; + } + + public void setNode(NodeCommon node) { + this.node = node; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getAsn() { + return asn; + } + + public void setAsn(String asn) { + this.asn = asn; + } + + public Boolean getMpbgp() { + return mpbgp; + } + + public void setMpbgp(Boolean mpbgp) { + this.mpbgp = mpbgp; + } + + public String getIpv4() { + return ipv4; + } + + public void setIpv4(String ipv4) { + this.ipv4 = ipv4; + } + + public String getIpv6() { + return ipv6; + } + + public void setIpv6(String ipv6) { + this.ipv6 = ipv6; + } + + public String getDevice() { + return device; + } + + public void setDevice(String device) { + this.device = device; + } +} diff --git a/central/src/main/java/moe/yuuta/dn42peering/provision/IProvisionRemoteService.java b/central/src/main/java/moe/yuuta/dn42peering/provision/IProvisionRemoteService.java new file mode 100644 index 0000000..ace1c54 --- /dev/null +++ b/central/src/main/java/moe/yuuta/dn42peering/provision/IProvisionRemoteService.java @@ -0,0 +1,56 @@ +package moe.yuuta.dn42peering.provision; + +import io.vertx.codegen.annotations.Fluent; +import io.vertx.codegen.annotations.ProxyGen; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.Vertx; +import moe.yuuta.dn42peering.node.Node; + +import javax.annotation.Nonnull; + +@ProxyGen +public interface IProvisionRemoteService { + String ADDRESS = IProvisionRemoteService.class.getName(); + + @Nonnull + static IProvisionRemoteService create(@Nonnull Vertx vertx) { + return new IProvisionRemoteServiceVertxEBProxy(vertx, ADDRESS); + } + + @Fluent + @Nonnull + IProvisionRemoteService provisionBGP(@Nonnull NodeCommon node, + @Nonnull BGPRequestCommon request, + @Nonnull Handler<AsyncResult<Void>> handler); + + @Fluent + @Nonnull + IProvisionRemoteService reloadBGP(@Nonnull NodeCommon node, + @Nonnull BGPRequestCommon request, + @Nonnull Handler<AsyncResult<Void>> handler); + + @Fluent + @Nonnull + IProvisionRemoteService deleteBGP(@Nonnull NodeCommon node, + @Nonnull BGPRequestCommon request, + @Nonnull Handler<AsyncResult<Void>> handler); + + @Fluent + @Nonnull + IProvisionRemoteService provisionWG(@Nonnull NodeCommon node, + @Nonnull WGRequestCommon request, + @Nonnull Handler<AsyncResult<String>> handler); + + @Fluent + @Nonnull + IProvisionRemoteService reloadWG(@Nonnull NodeCommon node, + @Nonnull WGRequestCommon request, + @Nonnull Handler<AsyncResult<String>> handler); + + @Fluent + @Nonnull + IProvisionRemoteService deleteWG(@Nonnull NodeCommon node, + @Nonnull WGRequestCommon request, + @Nonnull Handler<AsyncResult<Void>> handler); +} diff --git a/central/src/main/java/moe/yuuta/dn42peering/provision/NodeCommon.java b/central/src/main/java/moe/yuuta/dn42peering/provision/NodeCommon.java new file mode 100644 index 0000000..316965c --- /dev/null +++ b/central/src/main/java/moe/yuuta/dn42peering/provision/NodeCommon.java @@ -0,0 +1,112 @@ +package moe.yuuta.dn42peering.provision; + +import io.vertx.codegen.annotations.DataObject; +import io.vertx.core.json.JsonObject; +import moe.yuuta.dn42peering.agent.proto.Node; + +import javax.annotation.Nonnull; + +@DataObject +public class NodeCommon { + private Long id; + private String ipv4; + private String ipv6; + private String ipv6NonLL; + private String internalIp; + private int internalPort; + + public NodeCommon(long id, + @Nonnull String ipv4, + @Nonnull String ipv6, + @Nonnull String ipv6NonLL, + @Nonnull String internalIp, + @Nonnull Integer internalPort) { + this.id = id; + this.ipv4 = ipv4; + this.ipv6 = ipv6; + this.ipv6NonLL = ipv6NonLL; + this.internalIp = internalIp; + this.internalPort = internalPort; + } + + public NodeCommon(@Nonnull JsonObject json) { + if(json.getValue("id") != null) this.id = json.getLong("id"); + else this.id = null; + this.ipv4 = json.getString("ipv4"); + this.ipv6 = json.getString("ipv6"); + this.ipv6NonLL = json.getString("ipv6_non_ll"); + this.internalIp = json.getString("internal_ip"); + if(json.getValue("internal_port") != null) this.internalPort = json.getInteger("internal_port"); + } + + @Nonnull + public JsonObject toJson() { + return new JsonObject() + .put("id", id) + .put("ipv4", ipv4) + .put("ipv6", ipv6) + .put("ipv6_non_ll", ipv6NonLL) + .put("internal_ip", internalIp) + .put("internal_port", internalPort); + } + + @Nonnull + public Node toGRPC() { + final Node.Builder builder = Node.newBuilder() + .setIpv4(ipv4) + .setIpv6(ipv6) + .setIpv6NonLL(ipv6NonLL); + if(id != null) builder.setId(id); + return builder.build(); + } + + // Getters & Getters + + public Long getId() { + return id; + } + + public String getIpv4() { + return ipv4; + } + + public String getIpv6() { + return ipv6; + } + + public String getIpv6NonLL() { + return ipv6NonLL; + } + + public void setId(Long id) { + this.id = id; + } + + public void setIpv4(String ipv4) { + this.ipv4 = ipv4; + } + + public void setIpv6(String ipv6) { + this.ipv6 = ipv6; + } + + public void setIpv6NonLL(String ipv6NonLL) { + this.ipv6NonLL = ipv6NonLL; + } + + String getInternalIp() { + return internalIp; + } + + void setInternalIp(String internalIp) { + this.internalIp = internalIp; + } + + int getInternalPort() { + return internalPort; + } + + void setInternalPort(int internalPort) { + this.internalPort = internalPort; + } +} diff --git a/central/src/main/java/moe/yuuta/dn42peering/provision/ProvisionRemoteServiceImpl.java b/central/src/main/java/moe/yuuta/dn42peering/provision/ProvisionRemoteServiceImpl.java new file mode 100644 index 0000000..a642326 --- /dev/null +++ b/central/src/main/java/moe/yuuta/dn42peering/provision/ProvisionRemoteServiceImpl.java @@ -0,0 +1,107 @@ +package moe.yuuta.dn42peering.provision; + +import io.grpc.ManagedChannel; +import io.vertx.core.*; +import io.vertx.grpc.VertxChannelBuilder; +import moe.yuuta.dn42peering.agent.proto.VertxAgentGrpc; +import moe.yuuta.dn42peering.node.Node; + +import javax.annotation.Nonnull; + +class ProvisionRemoteServiceImpl implements IProvisionRemoteService { + private final Vertx vertx; + + ProvisionRemoteServiceImpl(@Nonnull Vertx vertx) { + this.vertx = vertx; + } + + private @Nonnull ManagedChannel toChannel(@Nonnull NodeCommon node) { + return VertxChannelBuilder.forAddress(vertx, node.getInternalIp(), node.getInternalPort()) + .usePlaintext() + .build(); + } + + @Nonnull + @Override + public IProvisionRemoteService provisionBGP(@Nonnull NodeCommon node, + @Nonnull BGPRequestCommon request, + @Nonnull Handler<AsyncResult<Void>> handler) { + final ManagedChannel channel = toChannel(node); + final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(channel); + stub.provisionBGP(request.toGRPC()) + .<Void>compose(reply -> Future.succeededFuture(null)) + .onComplete(res -> channel.shutdown()) + .onComplete(handler); + return this; + } + + @Nonnull + @Override + public IProvisionRemoteService reloadBGP(@Nonnull NodeCommon node, + @Nonnull BGPRequestCommon request, + @Nonnull Handler<AsyncResult<Void>> handler) { + final ManagedChannel channel = toChannel(node); + final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(channel); + stub.reloadBGP(request.toGRPC()) + .<Void>compose(reply -> Future.succeededFuture(null)) + .onComplete(res -> channel.shutdown()) + .onComplete(handler); + return this; + } + + @Nonnull + @Override + public IProvisionRemoteService deleteBGP(@Nonnull NodeCommon node, + @Nonnull BGPRequestCommon request, + @Nonnull Handler<AsyncResult<Void>> handler) { + final ManagedChannel channel = toChannel(node); + final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(channel); + stub.deleteBGP(request.toGRPC()) + .<Void>compose(reply -> Future.succeededFuture(null)) + .onComplete(res -> channel.shutdown()) + .onComplete(handler); + return this; + } + + @Nonnull + @Override + public IProvisionRemoteService provisionWG(@Nonnull NodeCommon node, + @Nonnull WGRequestCommon request, + @Nonnull Handler<AsyncResult<String>> handler) { + final ManagedChannel channel = toChannel(node); + final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(channel); + stub.provisionWG(request.toGRPC()) + .compose(wgReply -> Future.succeededFuture(wgReply.getDevice())) + .onComplete(res -> channel.shutdown()) + .onComplete(handler); + return this; + } + + @Nonnull + @Override + public IProvisionRemoteService reloadWG(@Nonnull NodeCommon node, + @Nonnull WGRequestCommon request, + @Nonnull Handler<AsyncResult<String>> handler) { + final ManagedChannel channel = toChannel(node); + final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(channel); + stub.reloadWG(request.toGRPC()) + .compose(wgReply -> Future.succeededFuture(wgReply.getDevice())) + .onComplete(res -> channel.shutdown()) + .onComplete(handler); + return this; + } + + @Nonnull + @Override + public IProvisionRemoteService deleteWG(@Nonnull NodeCommon node, + @Nonnull WGRequestCommon request, + @Nonnull Handler<AsyncResult<Void>> handler) { + final ManagedChannel channel = toChannel(node); + final VertxAgentGrpc.AgentVertxStub stub = VertxAgentGrpc.newVertxStub(channel); + stub.deleteWG(request.toGRPC()) + .<Void>compose(wgReply -> Future.succeededFuture(null)) + .onComplete(res -> channel.shutdown()) + .onComplete(handler); + return this; + } +} diff --git a/central/src/main/java/moe/yuuta/dn42peering/provision/ProvisionVerticle.java b/central/src/main/java/moe/yuuta/dn42peering/provision/ProvisionVerticle.java new file mode 100644 index 0000000..7d2772f --- /dev/null +++ b/central/src/main/java/moe/yuuta/dn42peering/provision/ProvisionVerticle.java @@ -0,0 +1,41 @@ +package moe.yuuta.dn42peering.provision; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.core.eventbus.MessageConsumer; +import io.vertx.core.impl.logging.Logger; +import io.vertx.core.impl.logging.LoggerFactory; +import io.vertx.core.json.JsonObject; +import io.vertx.serviceproxy.ServiceBinder; + +public class ProvisionVerticle extends AbstractVerticle { + private final Logger logger = LoggerFactory.getLogger(getClass().getSimpleName()); + + private MessageConsumer<JsonObject> consumer; + + @Override + public void start(Promise<Void> startPromise) throws Exception { + consumer = new ServiceBinder(vertx) + .setAddress(IProvisionRemoteService.ADDRESS) + .register(IProvisionRemoteService.class, new ProvisionRemoteServiceImpl(vertx)); + consumer.completionHandler(ar -> { + if(ar.succeeded()) { + startPromise.complete(); + } else { + startPromise.fail(ar.cause()); + } + }); + } + + @Override + public void stop(Promise<Void> stopPromise) throws Exception { + Future.future(f -> consumer.unregister(ar -> { + if(ar.succeeded()) f.complete(); + else f.fail(ar.cause()); + })).onComplete(ar -> { + if(ar.succeeded()) stopPromise.complete(); + else stopPromise.fail(ar.cause()); + }); + } +} diff --git a/central/src/main/java/moe/yuuta/dn42peering/provision/WGRequestCommon.java b/central/src/main/java/moe/yuuta/dn42peering/provision/WGRequestCommon.java new file mode 100644 index 0000000..d4694b6 --- /dev/null +++ b/central/src/main/java/moe/yuuta/dn42peering/provision/WGRequestCommon.java @@ -0,0 +1,155 @@ +package moe.yuuta.dn42peering.provision; + +import io.vertx.codegen.annotations.DataObject; +import io.vertx.core.json.JsonObject; +import moe.yuuta.dn42peering.agent.proto.WGRequest; + +import javax.annotation.Nonnull; + +@DataObject +public class WGRequestCommon { + private NodeCommon node; + private Long id; + private Integer listenPort; + private String endpoint; + private String peerPubKey; + private String selfPrivKey; + private String selfPresharedSecret; + private String peerIPv4; + private String peerIPv6; + + public WGRequestCommon(NodeCommon node, + Long id, + Integer listenPort, + String endpoint, + String peerPubKey, + String selfPrivKey, + String selfPresharedSecret, + String peerIPv4, + String peerIPv6) { + this.node = node; + this.id = id; + this.listenPort = listenPort; + this.endpoint = endpoint; + this.peerPubKey = peerPubKey; + this.selfPrivKey = selfPrivKey; + this.selfPresharedSecret = selfPresharedSecret; + this.peerIPv4 = peerIPv4; + this.peerIPv6 = peerIPv6; + } + + public WGRequestCommon(@Nonnull JsonObject json) { + if(json.getValue("node") != null) this.node = new NodeCommon(json.getJsonObject("node")); + if(json.getValue("id") != null) this.id = json.getLong("id"); + if(json.getValue("listen_port") != null) this.listenPort = json.getInteger("listen_port"); + this.endpoint = json.getString("endpoint"); + this.peerPubKey = json.getString("peer_public_key"); + this.selfPrivKey = json.getString("self_private_key"); + this.selfPresharedSecret = json.getString("self_preshared_secret"); + this.peerIPv4 = json.getString("peer_ipv4"); + this.peerIPv6 = json.getString("peer_ipv6"); + } + + @Nonnull + public JsonObject toJson() { + return new JsonObject() + .put("node", node == null ? null : node.toJson()) + .put("id", id) + .put("listen_port", listenPort) + .put("endpoint", endpoint) + .put("peer_public_key", peerPubKey) + .put("self_private_key", selfPrivKey) + .put("self_preshared_secret", selfPresharedSecret) + .put("peer_ipv4", peerIPv4) + .put("peer_ipv6", peerIPv6); + } + + @Nonnull + public WGRequest toGRPC() { + final WGRequest.Builder builder = WGRequest.newBuilder(); + if(node != null) builder.setNode(node.toGRPC()); + if(id != null) builder.setId(id); + if(listenPort != null) builder.setListenPort(listenPort); + if(endpoint != null) builder.setEndpoint(endpoint); + if(peerPubKey != null) builder.setPeerPubKey(peerPubKey); + if(selfPrivKey != null) builder.setSelfPrivKey(selfPrivKey); + if(selfPresharedSecret != null) builder.setSelfPresharedSecret(selfPresharedSecret); + if(peerIPv4 != null) builder.setPeerIPv4(peerIPv4); + if(peerIPv6 != null) builder.setPeerIPv6(peerIPv6); + return builder.build(); + } + + // Getters & Setters + + public NodeCommon getNode() { + return node; + } + + public void setNode(NodeCommon node) { + this.node = node; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Integer getListenPort() { + return listenPort; + } + + public void setListenPort(Integer listenPort) { + this.listenPort = listenPort; + } + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + public String getPeerPubKey() { + return peerPubKey; + } + + public void setPeerPubKey(String peerPubKey) { + this.peerPubKey = peerPubKey; + } + + public String getSelfPrivKey() { + return selfPrivKey; + } + + public void setSelfPrivKey(String selfPrivKey) { + this.selfPrivKey = selfPrivKey; + } + + public String getSelfPresharedSecret() { + return selfPresharedSecret; + } + + public void setSelfPresharedSecret(String selfPresharedSecret) { + this.selfPresharedSecret = selfPresharedSecret; + } + + public String getPeerIPv4() { + return peerIPv4; + } + + public void setPeerIPv4(String peerIPv4) { + this.peerIPv4 = peerIPv4; + } + + public String getPeerIPv6() { + return peerIPv6; + } + + public void setPeerIPv6(String peerIPv6) { + this.peerIPv6 = peerIPv6; + } +} diff --git a/central/src/main/java/moe/yuuta/dn42peering/provision/package-info.java b/central/src/main/java/moe/yuuta/dn42peering/provision/package-info.java new file mode 100644 index 0000000..22b72c9 --- /dev/null +++ b/central/src/main/java/moe/yuuta/dn42peering/provision/package-info.java @@ -0,0 +1,4 @@ +@ModuleGen(groupPackage = "moe.yuuta.dn42peering.provision", name = "provision") +package moe.yuuta.dn42peering.provision; + +import io.vertx.codegen.annotations.ModuleGen;
\ No newline at end of file |