Skip to content

Commit

Permalink
Merge branch 'master' into jurajpiar/no_dns_for_find_node
Browse files Browse the repository at this point in the history
  • Loading branch information
jurajpiar authored Apr 3, 2024
2 parents 1354af3 + d1c155a commit 4fb6f63
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 17 deletions.
50 changes: 44 additions & 6 deletions rskj-core/src/main/java/co/rsk/rpc/netty/JsonRpcCustomServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,27 @@
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.googlecode.jsonrpc4j.JsonResponse;
import com.googlecode.jsonrpc4j.JsonRpcBasicServer;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

import static co.rsk.jsonrpc.JsonRpcError.METHOD_NOT_FOUND;

public class JsonRpcCustomServer extends JsonRpcBasicServer {
public static final String METHOD_NOT_FOUND_MSG = "method not found";
private final List<ModuleDescription> modules;
private final Set<String> methodNames;
private final ObjectMapper objectMapper;

public JsonRpcCustomServer(final Object handler, final Class<?> remoteInterface, List<ModuleDescription> modules) {
super(new ObjectMapper(), handler, remoteInterface);
public JsonRpcCustomServer(final Object handler, final Class<?> remoteInterface, List<ModuleDescription> modules, ObjectMapper objetMapper) {
super(objetMapper, handler, remoteInterface);
this.modules = new ArrayList<>(modules);
this.methodNames = extractMethodNames(remoteInterface);
this.objectMapper = objetMapper;
}

@Override
Expand All @@ -44,7 +52,12 @@ protected JsonResponse handleJsonNodeRequest(final JsonNode node) throws JsonPar
return super.handleJsonNodeRequest(node);
}

String method = Optional.ofNullable(node.get("method")).map(JsonNode::asText).orElse("");
String method = Optional.ofNullable(node.get(METHOD)).map(JsonNode::asText).orElse("");

if(!methodNames.contains(method)) {
Object requestId = node.get(ID);
return buildError(requestId, METHOD_NOT_FOUND, METHOD_NOT_FOUND_MSG);
}

String[] methodParts = method.split("_");
JsonResponse response;
Expand Down Expand Up @@ -82,4 +95,29 @@ private long getTimeout(String moduleName, String methodName) {
}
return moduleDescription.getTimeout(methodName);
}

private Set<String> extractMethodNames(Class<?> remoteInterface) {
if (remoteInterface == null) {
return Collections.emptySet();
}

return Arrays.stream(remoteInterface.getMethods())
.map(Method::getName)
.collect(Collectors.toSet());
}

private JsonResponse buildError(Object id, int errorCode, String errorMessage) {
ObjectNode response = objectMapper.createObjectNode();
response.put(JSONRPC, VERSION);
if(id != null) {
response.set(ID, objectMapper.valueToTree(id));
}
ObjectNode error = objectMapper.createObjectNode();
error.put(ERROR_CODE, errorCode);
error.put(ERROR_MESSAGE, errorMessage);

response.set(ERROR, error);
return new JsonResponse(response, errorCode);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public class JsonRpcWeb3ServerHandler extends SimpleChannelInboundHandler<ByteBu
private final int maxResponseSize;

public JsonRpcWeb3ServerHandler(Web3 service, JsonRpcWeb3ServerProperties jsonRpcWeb3ServerProperties) {
this.jsonRpcServer = new JsonRpcCustomServer(service, service.getClass(), jsonRpcWeb3ServerProperties.getRpcModules());
this.jsonRpcServer = new JsonRpcCustomServer(service, service.getClass(), jsonRpcWeb3ServerProperties.getRpcModules(), mapper);
List<JsonRpcInterceptor> interceptors = new ArrayList<>();
interceptors.add(new JsonRpcRequestValidatorInterceptor(jsonRpcWeb3ServerProperties.getMaxBatchRequestsSize()));
jsonRpcServer.setInterceptorList(interceptors);
Expand Down Expand Up @@ -107,8 +107,6 @@ protected void channelRead0(ChannelHandlerContext ctx, ByteBufHolder request) th
int errorCode = ErrorResolver.JsonError.CUSTOM_SERVER_ERROR_LOWER;
responseContent = buildErrorContent(errorCode, unexpectedErrorMsg);
responseCode = errorCode;
} finally {
ReflectionUtil.clearCache();
}

ctx.fireChannelRead(new Web3Result(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class JsonRPCParamValidationTest {
@BeforeEach
void setUp() {
handler = mock(Web3EthModule.class);
this.jsonRpcServer = new JsonRpcCustomServer(handler, handler.getClass(), Collections.emptyList());
this.jsonRpcServer = new JsonRpcCustomServer(handler, handler.getClass(), Collections.emptyList(), objectMapper);
jsonRpcServer.setErrorResolver(new MultipleErrorResolver(new RskErrorResolver(), AnnotationsErrorResolver.INSTANCE, DefaultErrorResolver.INSTANCE));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void testHandleJsonNodeRequest() throws Exception {
JsonNode request = objectMapper.readTree(FIRST_METHOD_REQUEST);
String response = "test_method_response";
Web3Test handler = mock(Web3Test.class);
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, modules);
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, modules, objectMapper);

when(handler.test_first(anyString())).thenReturn(response);

Expand All @@ -72,7 +72,7 @@ void testHandleJsonNodeRequest_WithResponseLimit() throws Exception {
Web3Test handler = mock(Web3Test.class);
//expected response would be {"jsonrpc":"2.0","id":1,"result":"test_method_response"} with 56 bytes
ResponseSizeLimitContext.createResponseSizeContext(55);
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, modules);
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, modules, objectMapper);

when(handler.test_first(anyString())).thenReturn(response);

Expand All @@ -83,7 +83,7 @@ void testHandleJsonNodeRequest_WithResponseLimit() throws Exception {
void testHandleJsonNodeRequest_WithMethodModule() throws Exception {
JsonNode request = objectMapper.readTree(SECOND_METHOD_REQUEST);
Web3Test handler = mock(Web3Test.class);
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, getModulesWithMethodTimeout(0, 125));
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, getModulesWithMethodTimeout(0, 125), objectMapper);
String response = "test_method_response";

when(handler.test_second("param", "param2")).thenAnswer(invocation -> {
Expand All @@ -99,7 +99,7 @@ void testHandleJsonNodeRequest_WithMethodModule() throws Exception {
void testHandleJsonNodeRequest_WithMethodTimeout() throws Exception {
JsonNode request = objectMapper.readTree(SECOND_METHOD_REQUEST);
Web3Test handler = mock(Web3Test.class);
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, getModulesWithMethodTimeout(125, 0));
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, getModulesWithMethodTimeout(125, 0), objectMapper);

when(handler.test_second(anyString(), anyString())).thenAnswer(invocation -> {
waitFor(150);
Expand All @@ -113,7 +113,7 @@ void testHandleJsonNodeRequest_WithMethodTimeout() throws Exception {
void testHandleJsonNodeRequest_methodTimeoutOverModule() throws Exception {
JsonNode request = objectMapper.readTree(SECOND_METHOD_REQUEST);
Web3Test handler = mock(Web3Test.class);
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, getModulesWithMethodTimeout(500, 100));
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, getModulesWithMethodTimeout(500, 100), objectMapper);
String response = "test_method_response";

when(handler.test_second("param", "param2")).thenAnswer(invocation -> {
Expand Down Expand Up @@ -158,7 +158,7 @@ void testHandleJsonNodeRequest_WithMethodTimeout_BatchRequest_OK() throws Except
JsonNode request = objectMapper.readTree(jsonRequest);
Web3Test handler = mock(Web3Test.class);

jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, getModulesWithMethodTimeout(timeoutPerMethod, 0));
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, getModulesWithMethodTimeout(timeoutPerMethod, 0), objectMapper);

when(handler.test_second(anyString(), anyString())).thenAnswer(invocation -> {
waitFor(sleepTimePerRequest);
Expand Down Expand Up @@ -198,7 +198,7 @@ void testHandleJsonNodeRequest_WithMethodTimeout_BatchRequest_FAIL() throws Exce
JsonNode request = objectMapper.readTree(jsonRequest);
Web3Test handler = mock(Web3Test.class);

jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, getModulesWithMethodTimeout(timeoutPerMethod, 0));
jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, getModulesWithMethodTimeout(timeoutPerMethod, 0), objectMapper);

when(handler.test_second(anyString(), anyString())).thenAnswer(invocation -> {
waitFor(sleepTimePerRequest);
Expand All @@ -209,6 +209,25 @@ void testHandleJsonNodeRequest_WithMethodTimeout_BatchRequest_FAIL() throws Exce
verify(handler, times(1)).test_second(anyString(), anyString());
}

@Test
void sendingRequestWithNonDeclaredMethodShouldFail() throws Exception {
String jsonRequest = " {\n" +
" \"jsonrpc\": \"2.0\",\n" +
" \"method\": \"invalid_method\",\n" +
" \"params\": [],\n" +
" \"id\": 1\n" +
" }";

String expectedResponse = "{\"jsonrpc\":\"2.0\",\"id\":1,\"error\":{\"code\":-32601,\"message\":\"method not found\"}}";
JsonNode request = objectMapper.readTree(jsonRequest);
Web3Test handler = mock(Web3Test.class);

jsonRpcCustomServer = new JsonRpcCustomServer(handler, Web3Test.class, modules, objectMapper);

JsonResponse actualResponse = jsonRpcCustomServer.handleJsonNodeRequest(request);
assertEquals(expectedResponse, actualResponse.getResponse().toString());
}


public interface Web3Test {
String test_first(String param1);
Expand Down

0 comments on commit 4fb6f63

Please sign in to comment.