Connection.java
net.minecraft.server.jsonrpc.Connection
信息
- 全限定名:net.minecraft.server.jsonrpc.Connection
- 类型:public class
- 包:net.minecraft.server.jsonrpc
- 源码路径:src/main/java/net/minecraft/server/jsonrpc/Connection.java
- 起始行号:L40
- 继承:SimpleChannelInboundHandler
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L41 - 说明:
TODO
- 类型:
-
CONNECTION_ID_COUNTER- 类型:
AtomicInteger - 修饰符:
private static final - 源码定位:
L42 - 说明:
TODO
- 类型:
-
jsonRpcLogger- 类型:
JsonRpcLogger - 修饰符:
private final - 源码定位:
L43 - 说明:
TODO
- 类型:
-
clientInfo- 类型:
ClientInfo - 修饰符:
private final - 源码定位:
L44 - 说明:
TODO
- 类型:
-
managementServer- 类型:
ManagementServer - 修饰符:
private final - 源码定位:
L45 - 说明:
TODO
- 类型:
-
channel- 类型:
Channel - 修饰符:
private final - 源码定位:
L46 - 说明:
TODO
- 类型:
-
minecraftApi- 类型:
MinecraftApi - 修饰符:
private final - 源码定位:
L47 - 说明:
TODO
- 类型:
-
transactionId- 类型:
AtomicInteger - 修饰符:
private final - 源码定位:
L48 - 说明:
TODO
- 类型:
-
pendingRequests- 类型:
Int2ObjectMap<PendingRpcRequest<?>> - 修饰符:
private final - 源码定位:
L49 - 说明:
TODO
- 类型:
内部类/嵌套类型
- 无
构造器
public Connection(Channel channel, ManagementServer managementServer, MinecraftApi minecraftApi, JsonRpcLogger jsonrpcLogger) @ L51
- 构造器名:Connection
- 源码定位:L51
- 修饰符:public
参数:
- channel: Channel
- managementServer: ManagementServer
- minecraftApi: MinecraftApi
- jsonrpcLogger: JsonRpcLogger
说明:
TODO
方法
下面的方法块按源码顺序生成。
public void tick() @ L59
- 方法名:tick
- 源码定位:L59
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void channelActive(ChannelHandlerContext ctx) @ L79
- 方法名:channelActive
- 源码定位:L79
- 返回类型:void
- 修饰符:public
参数:
- ctx: ChannelHandlerContext
说明:
TODO
public void channelInactive(ChannelHandlerContext ctx) @ L86
- 方法名:channelInactive
- 源码定位:L86
- 返回类型:void
- 修饰符:public
参数:
- ctx: ChannelHandlerContext
说明:
TODO
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) @ L93
- 方法名:exceptionCaught
- 源码定位:L93
- 返回类型:void
- 修饰符:public
参数:
- ctx: ChannelHandlerContext
- cause: Throwable
说明:
TODO
protected void channelRead0(ChannelHandlerContext channelHandlerContext, JsonElement jsonElement) @ L103
- 方法名:channelRead0
- 源码定位:L103
- 返回类型:void
- 修饰符:protected
参数:
- channelHandlerContext: ChannelHandlerContext
- jsonElement: JsonElement
说明:
TODO
private JsonArray handleBatchRequest(List<JsonElement> batchRequests) @ L116
- 方法名:handleBatchRequest
- 源码定位:L116
- 返回类型:JsonArray
- 修饰符:private
参数:
- batchRequests: List
说明:
TODO
public void sendNotification(Holder.Reference<?extends OutgoingRpcMethod<Void,?>> method) @ L122
- 方法名:sendNotification
- 源码定位:L122
- 返回类型:void
- 修饰符:public
参数:
- method: Holder.Reference>
说明:
TODO
public <Params> void sendNotification(Holder.Reference<?extends OutgoingRpcMethod<Params,?>> method, Params params) @ L126
- 方法名:sendNotification
- 源码定位:L126
- 返回类型:
void - 修饰符:public
参数:
- method: Holder.Reference>
- params: Params
说明:
TODO
public <Result> CompletableFuture<Result> sendRequest(Holder.Reference<?extends OutgoingRpcMethod<Void,Result>> method) @ L130
- 方法名:sendRequest
- 源码定位:L130
- 返回类型:
CompletableFuture - 修饰符:public
参数:
- method: Holder.Reference<?extends OutgoingRpcMethod<Void,Result>>
说明:
TODO
public <Params,Result> CompletableFuture<Result> sendRequest(Holder.Reference<?extends OutgoingRpcMethod<Params,Result>> method, Params params) @ L134
- 方法名:sendRequest
- 源码定位:L134
- 返回类型:<Params,Result> CompletableFuture
- 修饰符:public
参数:
- method: Holder.Reference<?extends OutgoingRpcMethod<Params,Result>>
- params: Params
说明:
TODO
private <Params,Result> CompletableFuture<Result> sendRequest(Holder.Reference<?extends OutgoingRpcMethod<Params,?extends Result>> method, Params params, boolean expectReply) @ L138
- 方法名:sendRequest
- 源码定位:L138
- 返回类型:<Params,Result> CompletableFuture
- 修饰符:private
参数:
- method: Holder.Reference<?extends OutgoingRpcMethod<Params,?extends Result>>
- params: Params
- expectReply: boolean
说明:
TODO
JsonObject handleJsonObject(JsonObject jsonObject) @ L156
- 方法名:handleJsonObject
- 源码定位:L156
- 返回类型:JsonObject
- 修饰符:package-private
参数:
- jsonObject: JsonObject
说明:
TODO
private static boolean isValidRequestId(JsonElement id) @ L187
- 方法名:isValidRequestId
- 源码定位:L187
- 返回类型:boolean
- 修饰符:private static
参数:
- id: JsonElement
说明:
TODO
private static boolean isValidResponseId(JsonElement id) @ L191
- 方法名:isValidResponseId
- 源码定位:L191
- 返回类型:boolean
- 修饰符:private static
参数:
- id: JsonElement
说明:
TODO
private JsonObject handleIncomingRequest(JsonElement id, String method, JsonElement params) @ L195
- 方法名:handleIncomingRequest
- 源码定位:L195
- 返回类型:JsonObject
- 修饰符:private
参数:
- id: JsonElement
- method: String
- params: JsonElement
说明:
TODO
public JsonElement dispatchIncomingRequest(String method, JsonElement params) @ L217
- 方法名:dispatchIncomingRequest
- 源码定位:L217
- 返回类型:JsonElement
- 修饰符:public
参数:
- method: String
- params: JsonElement
说明:
TODO
private void handleRequestResponse(int id, JsonElement result) @ L241
- 方法名:handleRequestResponse
- 源码定位:L241
- 返回类型:void
- 修饰符:private
参数:
- id: int
- result: JsonElement
说明:
TODO
private JsonObject handleError(JsonElement id, JsonObject error) @ L250
- 方法名:handleError
- 源码定位:L250
- 返回类型:JsonObject
- 修饰符:private
参数:
- id: JsonElement
- error: JsonObject
说明:
TODO
代码
public class Connection extends SimpleChannelInboundHandler<JsonElement> {
private static final Logger LOGGER = LogUtils.getLogger();
private static final AtomicInteger CONNECTION_ID_COUNTER = new AtomicInteger(0);
private final JsonRpcLogger jsonRpcLogger;
private final ClientInfo clientInfo;
private final ManagementServer managementServer;
private final Channel channel;
private final MinecraftApi minecraftApi;
private final AtomicInteger transactionId = new AtomicInteger();
private final Int2ObjectMap<PendingRpcRequest<?>> pendingRequests = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
public Connection(Channel channel, ManagementServer managementServer, MinecraftApi minecraftApi, JsonRpcLogger jsonrpcLogger) {
this.clientInfo = ClientInfo.of(CONNECTION_ID_COUNTER.incrementAndGet());
this.managementServer = managementServer;
this.minecraftApi = minecraftApi;
this.channel = channel;
this.jsonRpcLogger = jsonrpcLogger;
}
public void tick() {
long time = Util.getMillis();
this.pendingRequests
.int2ObjectEntrySet()
.removeIf(
entry -> {
boolean timedOut = entry.getValue().timedOut(time);
if (timedOut) {
entry.getValue()
.resultFuture()
.completeExceptionally(
new ReadTimeoutException("RPC method " + entry.getValue().method().key().identifier() + " timed out waiting for response")
);
}
return timedOut;
}
);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
this.jsonRpcLogger.log(this.clientInfo, "Management connection opened for {}", this.channel.remoteAddress());
super.channelActive(ctx);
this.managementServer.onConnected(this);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
this.jsonRpcLogger.log(this.clientInfo, "Management connection closed for {}", this.channel.remoteAddress());
super.channelInactive(ctx);
this.managementServer.onDisconnected(this);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause.getCause() instanceof JsonParseException) {
this.channel.writeAndFlush(JsonRPCErrors.PARSE_ERROR.createWithUnknownId(cause.getMessage()));
} else {
super.exceptionCaught(ctx, cause);
this.channel.close().awaitUninterruptibly();
}
}
protected void channelRead0(ChannelHandlerContext channelHandlerContext, JsonElement jsonElement) {
if (jsonElement.isJsonObject()) {
JsonObject response = this.handleJsonObject(jsonElement.getAsJsonObject());
if (response != null) {
this.channel.writeAndFlush(response);
}
} else if (jsonElement.isJsonArray()) {
this.channel.writeAndFlush(this.handleBatchRequest(jsonElement.getAsJsonArray().asList()));
} else {
this.channel.writeAndFlush(JsonRPCErrors.INVALID_REQUEST.createWithUnknownId(null));
}
}
private JsonArray handleBatchRequest(List<JsonElement> batchRequests) {
JsonArray batchResponses = new JsonArray();
batchRequests.stream().map(batchEntry -> this.handleJsonObject(batchEntry.getAsJsonObject())).filter(Objects::nonNull).forEach(batchResponses::add);
return batchResponses;
}
public void sendNotification(Holder.Reference<? extends OutgoingRpcMethod<Void, ?>> method) {
this.sendRequest(method, null, false);
}
public <Params> void sendNotification(Holder.Reference<? extends OutgoingRpcMethod<Params, ?>> method, Params params) {
this.sendRequest(method, params, false);
}
public <Result> CompletableFuture<Result> sendRequest(Holder.Reference<? extends OutgoingRpcMethod<Void, Result>> method) {
return this.sendRequest(method, null, true);
}
public <Params, Result> CompletableFuture<Result> sendRequest(Holder.Reference<? extends OutgoingRpcMethod<Params, Result>> method, Params params) {
return this.sendRequest(method, params, true);
}
@Contract("_,_,false->null;_,_,true->!null")
private <Params, Result> @Nullable CompletableFuture<Result> sendRequest(
Holder.Reference<? extends OutgoingRpcMethod<Params, ? extends Result>> method, @Nullable Params params, boolean expectReply
) {
List<JsonElement> jsonParams = params != null ? List.of(Objects.requireNonNull(method.value().encodeParams(params))) : List.of();
if (expectReply) {
CompletableFuture<Result> future = new CompletableFuture<>();
int id = this.transactionId.incrementAndGet();
long time = Util.timeSource.get(TimeUnit.MILLISECONDS);
this.pendingRequests.put(id, new PendingRpcRequest<>(method, future, time + 5000L));
this.channel.writeAndFlush(JsonRPCUtils.createRequest(id, method.key().identifier(), jsonParams));
return future;
} else {
this.channel.writeAndFlush(JsonRPCUtils.createRequest(null, method.key().identifier(), jsonParams));
return null;
}
}
@VisibleForTesting
@Nullable JsonObject handleJsonObject(JsonObject jsonObject) {
try {
JsonElement id = JsonRPCUtils.getRequestId(jsonObject);
String method = JsonRPCUtils.getMethodName(jsonObject);
JsonElement result = JsonRPCUtils.getResult(jsonObject);
JsonElement params = JsonRPCUtils.getParams(jsonObject);
JsonObject error = JsonRPCUtils.getError(jsonObject);
if (method != null && result == null && error == null) {
return id != null && !isValidRequestId(id)
? JsonRPCErrors.INVALID_REQUEST.createWithUnknownId("Invalid request id - only String, Number and NULL supported")
: this.handleIncomingRequest(id, method, params);
} else if (method == null && result != null && error == null && id != null) {
if (isValidResponseId(id)) {
this.handleRequestResponse(id.getAsInt(), result);
} else {
LOGGER.warn("Received respose {} with id {} we did not request", result, id);
}
return null;
} else {
return method == null && result == null && error != null
? this.handleError(id, error)
: JsonRPCErrors.INVALID_REQUEST.createWithoutData(Objects.requireNonNullElse(id, JsonNull.INSTANCE));
}
} catch (Exception var7) {
LOGGER.error("Error while handling rpc request", (Throwable)var7);
return JsonRPCErrors.INTERNAL_ERROR.createWithUnknownId("Unknown error handling request - check server logs for stack trace");
}
}
private static boolean isValidRequestId(JsonElement id) {
return id.isJsonNull() || GsonHelper.isNumberValue(id) || GsonHelper.isStringValue(id);
}
private static boolean isValidResponseId(JsonElement id) {
return GsonHelper.isNumberValue(id);
}
private @Nullable JsonObject handleIncomingRequest(@Nullable JsonElement id, String method, @Nullable JsonElement params) {
boolean sendResponse = id != null;
try {
JsonElement result = this.dispatchIncomingRequest(method, params);
return result != null && sendResponse ? JsonRPCUtils.createSuccessResult(id, result) : null;
} catch (InvalidParameterJsonRpcException var6) {
LOGGER.debug("Invalid parameter invocation {}: {}, {}", method, params, var6.getMessage());
return sendResponse ? JsonRPCErrors.INVALID_PARAMS.create(id, var6.getMessage()) : null;
} catch (EncodeJsonRpcException var7) {
LOGGER.error("Failed to encode json rpc response {}: {}", method, var7.getMessage());
return sendResponse ? JsonRPCErrors.INTERNAL_ERROR.create(id, var7.getMessage()) : null;
} catch (InvalidRequestJsonRpcException var8) {
return sendResponse ? JsonRPCErrors.INVALID_REQUEST.create(id, var8.getMessage()) : null;
} catch (MethodNotFoundJsonRpcException var9) {
return sendResponse ? JsonRPCErrors.METHOD_NOT_FOUND.create(id, var9.getMessage()) : null;
} catch (Exception var10) {
LOGGER.error("Error while dispatching rpc method {}", method, var10);
return sendResponse ? JsonRPCErrors.INTERNAL_ERROR.createWithoutData(id) : null;
}
}
public @Nullable JsonElement dispatchIncomingRequest(String method, @Nullable JsonElement params) {
Identifier identifier = Identifier.tryParse(method);
if (identifier == null) {
throw new InvalidRequestJsonRpcException("Failed to parse method value: " + method);
} else {
Optional<IncomingRpcMethod<?, ?>> incomingRpcMethod = BuiltInRegistries.INCOMING_RPC_METHOD.getOptional(identifier);
if (incomingRpcMethod.isEmpty()) {
throw new MethodNotFoundJsonRpcException("Method not found: " + method);
} else if (incomingRpcMethod.get().attributes().runOnMainThread()) {
try {
return this.minecraftApi.<JsonElement>submit(() -> incomingRpcMethod.get().apply(this.minecraftApi, params, this.clientInfo)).join();
} catch (CompletionException var8) {
if (var8.getCause() instanceof RuntimeException re) {
throw re;
} else {
throw var8;
}
}
} else {
return incomingRpcMethod.get().apply(this.minecraftApi, params, this.clientInfo);
}
}
}
private void handleRequestResponse(int id, JsonElement result) {
PendingRpcRequest<?> request = this.pendingRequests.remove(id);
if (request == null) {
LOGGER.warn("Received unknown response (id: {}): {}", id, result);
} else {
request.accept(result);
}
}
private @Nullable JsonObject handleError(@Nullable JsonElement id, JsonObject error) {
if (id != null && isValidResponseId(id)) {
PendingRpcRequest<?> request = this.pendingRequests.remove(id.getAsInt());
if (request != null) {
request.resultFuture().completeExceptionally(new RemoteRpcErrorException(id, error));
}
}
LOGGER.error("Received error (id: {}): {}", id, error);
return null;
}
}引用的其他类
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/返回值
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Identifier.tryParse()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
JsonRPCUtils.createRequest(), JsonRPCUtils.createSuccessResult(), JsonRPCUtils.getError(), JsonRPCUtils.getMethodName(), JsonRPCUtils.getParams(), JsonRPCUtils.getRequestId(), JsonRPCUtils.getResult()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
字段
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
字段/方法调用 - 关联成员:
ClientInfo.of()
- 引用位置:
-
InvalidRequestJsonRpcException
- 引用位置:
构造调用 - 关联成员:
InvalidRequestJsonRpcException()
- 引用位置:
-
MethodNotFoundJsonRpcException
- 引用位置:
构造调用 - 关联成员:
MethodNotFoundJsonRpcException()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
RemoteRpcErrorException()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
GsonHelper.isNumberValue(), GsonHelper.isStringValue()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Util.getMillis()
- 引用位置: