mirror of
https://gitee.com/BDWare/agent-backend
synced 2025-01-09 17:34:13 +00:00
support doip-cluster
This commit is contained in:
parent
3f4d154d2b
commit
94f1b6dc7d
14
build.gradle
14
build.gradle
@ -40,17 +40,17 @@ dependencies {
|
||||
implementation 'io.grpc:grpc-all:1.43.1'
|
||||
implementation 'org.apache.velocity:velocity-engine-core:2.3'
|
||||
implementation 'com.nimbusds:nimbus-jose-jwt:9.10'
|
||||
implementation 'org.bdware.doip:doip-sdk:1.3.9'
|
||||
implementation 'org.bdware.doip:doip-audit-tool:1.2.2'
|
||||
implementation 'org.bdware.doip:bdosclient:0.0.2'
|
||||
implementation 'org.bdware.doip:doip-sdk:1.4.2'
|
||||
implementation 'org.bdware.doip:doip-audit-tool:1.2.6'
|
||||
implementation 'org.bdware.doip:bdosclient:0.0.3'
|
||||
implementation fileTree(dir: 'lib', include: '*.jar')
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
implementation 'io.netty:netty-tcnative-boringssl-static:2.0.59.Final'
|
||||
implementation 'io.netty:netty-tcnative-boringssl-static:2.0.59.Final-linux-aarch_64-fedora'
|
||||
// implementation 'io.netty:netty-tcnative-boringssl-static:2.0.59.Final'
|
||||
// implementation 'io.netty:netty-tcnative-boringssl-static:2.0.59.Final'
|
||||
// implementation 'io.netty:netty-tcnative-boringssl-static:2.0.59.Final'
|
||||
// implementation 'io.netty:netty-tcnative-boringssl-static:2.0.59.Final'
|
||||
// implementation 'io.netty:netty-tcnative-boringssl-static:2.0.59.Final'
|
||||
// implementation 'io.netty:netty-tcnative-boringssl-static:2.0.59.Final'
|
||||
// implementation 'io.netty:netty-tcnative-boringssl-static:2.0.59.Final'
|
||||
// implementation 'io.netty:netty-tcnative-boringssl-static:2.0.59.Final'
|
||||
}
|
||||
|
||||
compileJava {
|
||||
|
@ -15,6 +15,7 @@ import io.netty.util.TimerTask;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.ContractManager;
|
||||
import org.bdware.sc.ContractMeta;
|
||||
import org.bdware.sc.YJSPacker;
|
||||
import org.bdware.sc.bean.Contract;
|
||||
import org.bdware.sc.bean.ContractExecType;
|
||||
@ -135,10 +136,11 @@ public class FileActions {
|
||||
request.protocolVersion(),
|
||||
OK,
|
||||
Unpooled.wrappedBuffer(
|
||||
"{\"status\":\"false\",\"data\":\"Missing argument!\"}"
|
||||
"{\"status\":\"false\",\"data\":\"Missing argument, please check: path, fileName, isPrivate, order, count, pubKey, sign!\"}"
|
||||
.getBytes()));
|
||||
|
||||
ChannelFuture f = ctx.write(fullResponse);
|
||||
|
||||
ChannelFuture f = addCrossOriginHeaderAndWrite(ctx, fullResponse);
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
@ -236,7 +238,7 @@ public class FileActions {
|
||||
"{\"status\":\"false\",\"data\":\"Permission denied!\"}"
|
||||
.getBytes()));
|
||||
|
||||
ChannelFuture f = ctx.write(fullResponse);
|
||||
ChannelFuture f = addCrossOriginHeaderAndWrite(ctx, fullResponse);
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
@ -249,16 +251,47 @@ public class FileActions {
|
||||
new HttpPostRequestDecoder(new DefaultHttpDataFactory(true), request);
|
||||
httpDecoder.setDiscardThreshold(0);
|
||||
File dir;
|
||||
boolean isPrivate =
|
||||
transformedParam.containsKey("isPrivate")
|
||||
&& Boolean.parseBoolean(transformedParam.get("isPrivate"));
|
||||
// TODO verify signature and
|
||||
|
||||
if (isPrivate) {
|
||||
String pub = "/" + transformedParam.get("pubKey");
|
||||
dir = new File(GlobalConf.instance.projectDir + "/private" + pub, dirName);
|
||||
if (transformedParam.containsKey("contractID")) {
|
||||
String contractID = transformedParam.get("contractID");
|
||||
ContractMeta meta = CMActions.manager.statusRecorder.getContractMeta(contractID);
|
||||
if (meta == null) {
|
||||
DefaultFullHttpResponse fullResponse =
|
||||
new DefaultFullHttpResponse(
|
||||
request.protocolVersion(),
|
||||
OK,
|
||||
Unpooled.wrappedBuffer(
|
||||
"{\"status\":\"false\",\"data\":\"no such contract!\"}"
|
||||
.getBytes()));
|
||||
ChannelFuture f = addCrossOriginHeaderAndWrite(ctx, fullResponse);
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
if (!meta.contract.getOwner().equals(pubkey)) {
|
||||
DefaultFullHttpResponse fullResponse =
|
||||
new DefaultFullHttpResponse(
|
||||
request.protocolVersion(),
|
||||
OK,
|
||||
Unpooled.wrappedBuffer(
|
||||
"{\"status\":\"false\",\"data\":\"not owner!\"}"
|
||||
.getBytes()));
|
||||
ChannelFuture f = addCrossOriginHeaderAndWrite(ctx, fullResponse);
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
dir = new File(GlobalConf.instance.getDBPath(), meta.getName());
|
||||
dir = new File(dir, dirName);
|
||||
if (!dir.exists()) dir.mkdirs();
|
||||
} else {
|
||||
dir = new File(GlobalConf.instance.publicDir, dirName);
|
||||
boolean isPrivate =
|
||||
transformedParam.containsKey("isPrivate")
|
||||
&& Boolean.parseBoolean(transformedParam.get("isPrivate"));
|
||||
// TODO verify signature and
|
||||
if (isPrivate) {
|
||||
String pub = "/" + transformedParam.get("pubKey");
|
||||
dir = new File(GlobalConf.instance.projectDir + "/private" + pub, dirName);
|
||||
} else {
|
||||
dir = new File(GlobalConf.instance.publicDir, dirName);
|
||||
}
|
||||
}
|
||||
if (!dir.isDirectory()) {
|
||||
dir = dir.getParentFile();
|
||||
@ -273,7 +306,7 @@ public class FileActions {
|
||||
"{\"status\":\"false\",\"data\":\"FileName illegal!\"}"
|
||||
.getBytes()));
|
||||
|
||||
ChannelFuture f = ctx.write(fullResponse);
|
||||
ChannelFuture f = addCrossOriginHeaderAndWrite(ctx, fullResponse);
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
@ -309,7 +342,9 @@ public class FileActions {
|
||||
boolean isDebug =
|
||||
transformedParam.containsKey("isDebug")
|
||||
&& Boolean.parseBoolean(transformedParam.get("isDebug"));
|
||||
String doi = unzipIfYpk(target, dir, isDebug);
|
||||
String doi = null;
|
||||
if (target.getParentFile().getParentFile().equals(new File(GlobalConf.instance.privateDir)))
|
||||
doi = unzipIfYpk(target, dir, isDebug);
|
||||
if (null != doi) {
|
||||
retStr = retStr.replaceFirst("null", doi);
|
||||
}
|
||||
@ -317,11 +352,16 @@ public class FileActions {
|
||||
DefaultFullHttpResponse fullResponse =
|
||||
new DefaultFullHttpResponse(
|
||||
request.protocolVersion(), OK, Unpooled.wrappedBuffer(retStr.getBytes()));
|
||||
fullResponse.headers().add("Access-Control-Allow-Origin", "*");
|
||||
ChannelFuture f = ctx.write(fullResponse);
|
||||
ChannelFuture f = addCrossOriginHeaderAndWrite(ctx, fullResponse);
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
|
||||
private static ChannelFuture addCrossOriginHeaderAndWrite(ChannelHandlerContext ctx, DefaultFullHttpResponse fullResponse) {
|
||||
fullResponse.headers().add("Access-Control-Allow-Origin", "*");
|
||||
fullResponse.headers().add("Access-Control-Allow-Methods", "*");
|
||||
return ctx.write(fullResponse);
|
||||
}
|
||||
|
||||
public static String geneRandomID() {
|
||||
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
Random random = new Random();
|
||||
|
@ -126,7 +126,7 @@ public class BCOManager {
|
||||
}
|
||||
|
||||
private File getYpkFile(YPKInfo ypkInfo) {
|
||||
File f = new File(bcodir, ypkInfo.ypkName);
|
||||
File f = new File(bcodir, ypkInfo.pkgName);
|
||||
if (ypkInfo.version != null)
|
||||
f = new File(f, ypkInfo.version);
|
||||
f = new File(f, ypkInfo.md5 + ".ypk");
|
||||
|
@ -104,7 +104,7 @@ public class ContractRepositoryHandler extends RepositoryHandlerBase implements
|
||||
c.setType(ContractExecType.valueOf(digitalObject.attributes.get("contractExecType").getAsString()));
|
||||
else c.setType(ContractExecType.Sole);
|
||||
if (digitalObject.attributes.has("shardingId"))
|
||||
c.setType(ContractExecType.valueOf(digitalObject.attributes.get("shardingId").getAsString()));
|
||||
c.setShardingId(Integer.valueOf(digitalObject.attributes.get("shardingId").getAsString()));
|
||||
else c.setShardingId(-1);
|
||||
c.setScript(path);
|
||||
c.setOwner(doipMessage.credential.getSigner());
|
||||
|
@ -19,19 +19,20 @@ import org.bdware.server.GlobalConf;
|
||||
import org.bdware.server.action.CMActions;
|
||||
import org.zz.gmhelper.SM2KeyPair;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ContractRepositoryMain {
|
||||
private static final Logger LOGGER = LogManager.getLogger(ContractRepositoryMain.class);
|
||||
static AuditDoipServer currentServer;
|
||||
static LocalDoipFrowarder forwarder;
|
||||
static final String repoType = "BDRepo";
|
||||
|
||||
public static void start() {
|
||||
try {
|
||||
LOGGER.info("DOIPServer, start" + new Gson().toJson(GlobalConf.instance.doaConf));
|
||||
String url = GlobalConf.instance.doaConf.doipAddress;
|
||||
forwarder = new LocalDoipFrowarder();
|
||||
if (url == null || GlobalConf.instance.doaConf.repoDoid.isEmpty()) {
|
||||
LOGGER.warn("missing args, failed to start! url:" + url + " doid:" + GlobalConf.instance.doaConf.repoDoid);
|
||||
return;
|
||||
@ -60,22 +61,22 @@ public class ContractRepositoryMain {
|
||||
String id = message.header.parameters.id;
|
||||
id = id.replaceAll(".*/", "");
|
||||
ContractMeta meta = CMActions.manager.statusRecorder.getContractMeta(id);
|
||||
builder.addAttributes("port", meta.contract.getDoipPort());
|
||||
DoipMessage ret;
|
||||
if (message.credential != null && message.credential.getSigner() != null) {
|
||||
if (signer.verifyMessage(message)) {
|
||||
ret = builder.create();
|
||||
} else {
|
||||
DoipMessageFactory.DoipMessageBuilder builder2 = new DoipMessageFactory.DoipMessageBuilder();
|
||||
DoipMessageFactory.DoipMessageBuilder resp = builder2.createResponse(DoipResponseCode.UnAuth_Client, message);
|
||||
resp.setBody("verify failed".getBytes(StandardCharsets.UTF_8));
|
||||
ret = resp.create();
|
||||
}
|
||||
signer.signMessage(ret);
|
||||
} else {
|
||||
if (enableDelegate(meta)) {
|
||||
LOGGER.info("delegate:" + message.requestID);
|
||||
|
||||
//if port is near cmhttp server port
|
||||
builder.addAttributes("port", meta.contract.getDoipPort());
|
||||
DoipMessage ret;
|
||||
ret = builder.create();
|
||||
if (message.credential != null && message.credential.getSigner() != null) {
|
||||
signer.signMessage(ret);
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
LOGGER.info("forward:" + message.requestID);
|
||||
return forwarder.forward(meta, message);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -97,4 +98,10 @@ public class ContractRepositoryMain {
|
||||
LOGGER.warn("load doip config exception!");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean enableDelegate(ContractMeta meta) {
|
||||
int port = meta.contract.getDoipPort();
|
||||
int delta = Integer.valueOf(GlobalConf.instance.ipPort.split(":")[1]) - port;
|
||||
return Math.abs(delta) < 200;
|
||||
}
|
||||
}
|
||||
|
58
src/main/java/org/bdware/server/doip/LocalDoipFrowarder.java
Normal file
58
src/main/java/org/bdware/server/doip/LocalDoipFrowarder.java
Normal file
@ -0,0 +1,58 @@
|
||||
package org.bdware.server.doip;
|
||||
|
||||
import org.bdware.doip.codec.doipMessage.DoipMessage;
|
||||
import org.bdware.doip.codec.doipMessage.DoipMessageFactory;
|
||||
import org.bdware.doip.codec.doipMessage.DoipResponseCode;
|
||||
import org.bdware.doip.endpoint.client.ClientConfig;
|
||||
import org.bdware.doip.endpoint.client.DoipClientImpl;
|
||||
import org.bdware.doip.endpoint.client.DoipMessageCallback;
|
||||
import org.bdware.sc.ContractMeta;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class LocalDoipFrowarder {
|
||||
Map<Integer, DoipClientImpl> connections;
|
||||
|
||||
public LocalDoipFrowarder() {
|
||||
connections = new HashMap<>();
|
||||
}
|
||||
|
||||
public DoipMessage forward(ContractMeta meta, DoipMessage message) {
|
||||
DoipClientImpl connection;
|
||||
try {
|
||||
if (connections.containsKey(meta.contract.getDoipPort())) {
|
||||
connection = connections.get(meta.contract.getDoipPort());
|
||||
} else {
|
||||
connection = new DoipClientImpl();
|
||||
connection.connect(ClientConfig.fromUrl("tcp://127.0.0.1:" + meta.contract.getDoipPort()));
|
||||
connections.put(meta.contract.getDoipPort(), connection);
|
||||
}
|
||||
if (!connection.isConnected()) connection.reconnect();
|
||||
DoipMessage[] result = new DoipMessage[1];
|
||||
connection.sendRawMessage(message, new DoipMessageCallback() {
|
||||
@Override
|
||||
public void onResult(DoipMessage msg) {
|
||||
synchronized (result) {
|
||||
result[0] = msg;
|
||||
result.notify();
|
||||
}
|
||||
}
|
||||
});
|
||||
synchronized (result) {
|
||||
if (result[0] == null)
|
||||
result.wait(30000L);
|
||||
}
|
||||
return result[0];
|
||||
} catch (Exception e) {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
|
||||
builder.createResponse(DoipResponseCode.UnKnownError, message);
|
||||
builder.setBody(bo.toByteArray());
|
||||
return builder.create();
|
||||
}
|
||||
}
|
||||
}
|
@ -87,7 +87,11 @@ public class DOIPOverHttpHandler {
|
||||
sendListContractProcess(arg, ctx);
|
||||
return;
|
||||
case Retrieve:
|
||||
sendAssets(arg, ctx);
|
||||
if (arg.has("__public") && arg.get("__public").getAsBoolean()) {
|
||||
sendPublicFiles(arg, ctx);
|
||||
} else {
|
||||
sendAssets(arg, ctx);
|
||||
}
|
||||
return;
|
||||
case RetrieveYPK:
|
||||
sendYpk(arg, ctx, request);
|
||||
@ -163,6 +167,45 @@ public class DOIPOverHttpHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
private void sendPublicFiles(JsonObject arg, ChannelHandlerContext ctx) throws Exception {
|
||||
ContractMeta meta =
|
||||
CMActions.manager.statusRecorder.getContractMeta(
|
||||
arg.get("contractID").getAsString());
|
||||
if (meta == null) {
|
||||
HttpFileHandleAdapter.sendError(ctx, HttpResponseStatus.NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
String path = arg.get("argument").getAsString();
|
||||
File dir = new File("./ContractDB", meta.getName());
|
||||
File toSend = new File(dir, path);
|
||||
FileInputStream fin;
|
||||
try {
|
||||
if (!toSend.exists() || toSend.isDirectory()) {
|
||||
HttpFileHandleAdapter.sendError(ctx, HttpResponseStatus.NOT_FOUND);
|
||||
return;
|
||||
} else
|
||||
fin = new FileInputStream(toSend);
|
||||
} catch (Exception e) {
|
||||
HttpFileHandleAdapter.sendError(ctx, HttpResponseStatus.NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.OK);
|
||||
HttpFileHandleAdapter.appendContentType(path, response.headers());
|
||||
ctx.write(response);
|
||||
ChannelFuture future = ctx.writeAndFlush(new ChunkedStream(fin));
|
||||
future.addListener(
|
||||
new GenericFutureListener<Future<? super Void>>() {
|
||||
@Override
|
||||
public void operationComplete(Future<? super Void> arg0) throws Exception {
|
||||
ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
|
||||
fin.close();
|
||||
}
|
||||
});
|
||||
// 写入文件尾部
|
||||
future.addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
|
||||
private void sendAssets(JsonObject arg, ChannelHandlerContext ctx) throws Exception {
|
||||
ContractMeta meta =
|
||||
CMActions.manager.statusRecorder.getContractMeta(
|
||||
@ -225,7 +268,6 @@ public class DOIPOverHttpHandler {
|
||||
}
|
||||
|
||||
private void injectExtraArgs(JsonObject transformedParam, String fulluri) {
|
||||
|
||||
String[] data = fulluri.split("/");
|
||||
String contractIDOrName = data[2];
|
||||
String uris[] = URLDecoder.decode(fulluri).split("\\?");
|
||||
@ -253,7 +295,8 @@ public class DOIPOverHttpHandler {
|
||||
transformedParam.addProperty("contractID", data[2].replaceAll("\\?.*$", ""));
|
||||
if (data.length > 3) {
|
||||
String assetPath = data[3];
|
||||
if (assetPath.equals("assets")) {
|
||||
transformedParam.remove("__public");
|
||||
if (assetPath.equals("assets") && !fulluri.contains("..")) {
|
||||
transformedParam.addProperty("operation", Operations.Retrieve.val);
|
||||
int index = data[0].length() + data[1].length() + data[2].length() + 2;
|
||||
String path = fulluri.substring(index);
|
||||
@ -261,6 +304,12 @@ public class DOIPOverHttpHandler {
|
||||
if (path.equals("/assets/"))
|
||||
path += "index.html";
|
||||
transformedParam.addProperty("argument", path);
|
||||
} else if (assetPath.equals("public") && !fulluri.contains("..")) {
|
||||
transformedParam.addProperty("operation", Operations.Retrieve.val);
|
||||
int index = data[0].length() + data[1].length() + data[2].length() + 2;
|
||||
String path = fulluri.substring(index);
|
||||
transformedParam.addProperty("argument", path);
|
||||
transformedParam.addProperty("__public", true);
|
||||
}
|
||||
if (assetPath.startsWith("ypk?")) {
|
||||
transformedParam.addProperty("operation", Operations.RetrieveYPK.val);
|
||||
|
Loading…
Reference in New Issue
Block a user