use of org.xel.util.CountingInputReader in project elastic-core-maven by OrdinaryDude.
the class PeerImpl method send.
@Override
public JSONObject send(final JSONStreamAware request, int maxResponseSize) {
JSONObject response = null;
String log = null;
boolean showLog = false;
HttpURLConnection connection = null;
int communicationLoggingMask = Peers.communicationLoggingMask;
try {
//
if (useWebSocket && !webSocket.isOpen())
useWebSocket = webSocket.startClient(URI.create("ws://" + host + ":" + getPort() + "/nxt"));
//
if (useWebSocket) {
//
// Send the request using the WebSocket session
//
StringWriter wsWriter = new StringWriter(1000);
request.writeJSONString(wsWriter);
String wsRequest = wsWriter.toString();
if (communicationLoggingMask != 0)
log = "WebSocket " + host + ": " + wsRequest;
String wsResponse = webSocket.doPost(wsRequest);
updateUploadedVolume(wsRequest.length());
if (maxResponseSize > 0) {
if ((communicationLoggingMask & Peers.LOGGING_MASK_200_RESPONSES) != 0) {
log += " >>> " + wsResponse;
showLog = true;
}
if (wsResponse.length() > maxResponseSize)
throw new NxtException.NxtIOException("Maximum size exceeded: " + wsResponse.length());
response = (JSONObject) JSONValue.parseWithException(wsResponse);
updateDownloadedVolume(wsResponse.length());
}
} else {
//
// Send the request using HTTP
//
URL url = new URL("http://" + host + ":" + getPort() + "/nxt");
if (communicationLoggingMask != 0)
log = "\"" + url.toString() + "\": " + JSON.toString(request);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setConnectTimeout(Peers.connectTimeout);
connection.setReadTimeout(Peers.readTimeout);
connection.setRequestProperty("Accept-Encoding", "gzip");
connection.setRequestProperty("Content-Type", "text/plain; charset=UTF-8");
try (Writer writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"))) {
CountingOutputWriter cow = new CountingOutputWriter(writer);
request.writeJSONString(cow);
updateUploadedVolume(cow.getCount());
}
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
if (maxResponseSize > 0) {
if ((communicationLoggingMask & Peers.LOGGING_MASK_200_RESPONSES) != 0) {
CountingInputStream cis = new CountingInputStream(connection.getInputStream(), maxResponseSize);
InputStream responseStream = cis;
if ("gzip".equals(connection.getHeaderField("Content-Encoding")))
responseStream = new GZIPInputStream(cis);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int numberOfBytes;
try (InputStream inputStream = responseStream) {
while ((numberOfBytes = inputStream.read(buffer, 0, buffer.length)) > 0) byteArrayOutputStream.write(buffer, 0, numberOfBytes);
}
String responseValue = byteArrayOutputStream.toString("UTF-8");
if (responseValue.length() > 0 && responseStream instanceof GZIPInputStream)
log += String.format("[length: %d, compression ratio: %.2f]", cis.getCount(), (double) cis.getCount() / (double) responseValue.length());
log += " >>> " + responseValue;
showLog = true;
response = (JSONObject) JSONValue.parseWithException(responseValue);
updateDownloadedVolume(responseValue.length());
} else {
InputStream responseStream = connection.getInputStream();
if ("gzip".equals(connection.getHeaderField("Content-Encoding")))
responseStream = new GZIPInputStream(responseStream);
try (Reader reader = new BufferedReader(new InputStreamReader(responseStream, "UTF-8"))) {
CountingInputReader cir = new CountingInputReader(reader, maxResponseSize);
response = (JSONObject) JSONValue.parseWithException(cir);
updateDownloadedVolume(cir.getCount());
}
}
}
} else {
if ((communicationLoggingMask & Peers.LOGGING_MASK_NON200_RESPONSES) != 0) {
log += " >>> Peer responded with HTTP " + connection.getResponseCode() + " code!";
showLog = true;
}
Logger.logDebugMessage("Peer " + host + " responded with HTTP " + connection.getResponseCode());
deactivate();
connection.disconnect();
}
}
//
if (response != null && response.get("error") != null) {
deactivate();
if (Errors.SEQUENCE_ERROR.equals(response.get("error")) && request != Peers.getMyPeerInfoRequest()) {
Logger.logDebugMessage("Sequence error, reconnecting to " + host);
connect();
} else {
Logger.logDebugMessage("Peer " + host + " version " + version + " returned error: " + response.toJSONString() + ", request was: " + JSON.toString(request) + ", disconnecting");
if (connection != null) {
connection.disconnect();
}
}
}
} catch (NxtException.NxtIOException e) {
blacklist(e);
if (connection != null) {
connection.disconnect();
}
} catch (RuntimeException | ParseException | IOException e) {
if (!(e instanceof UnknownHostException || e instanceof SocketTimeoutException || e instanceof SocketException || Errors.END_OF_FILE.equals(e.getMessage()))) {
Logger.logDebugMessage(String.format("Error sending request to peer %s: %s", host, e.getMessage() != null ? e.getMessage() : e.toString()));
}
if ((communicationLoggingMask & Peers.LOGGING_MASK_EXCEPTIONS) != 0) {
log += " >>> " + e.toString();
showLog = true;
}
deactivate();
if (connection != null) {
connection.disconnect();
}
}
if (showLog) {
Logger.logMessage(log + "\n");
}
return response;
}
use of org.xel.util.CountingInputReader in project elastic-core-maven by OrdinaryDude.
the class PeerServlet method process.
/**
* Process the peer request
*
* @param peer Peer
* @param inputReader Input reader
* @return JSON response
*/
private JSONStreamAware process(PeerImpl peer, Reader inputReader) {
//
if (peer.isBlacklisted()) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("error", Errors.BLACKLISTED);
jsonObject.put("cause", peer.getBlacklistingCause());
return jsonObject;
}
Peers.addPeer(peer);
//
try (CountingInputReader cr = new CountingInputReader(inputReader, Peers.MAX_REQUEST_SIZE)) {
JSONObject request = (JSONObject) JSONValue.parseWithException(cr);
peer.updateDownloadedVolume(cr.getCount());
if (request.get("protocol") == null || ((Number) request.get("protocol")).intValue() != 1) {
Logger.logDebugMessage("Unsupported protocol " + request.get("protocol"));
return UNSUPPORTED_PROTOCOL;
}
PeerRequestHandler peerRequestHandler = peerRequestHandlers.get((String) request.get("requestType"));
if (peerRequestHandler == null) {
return UNSUPPORTED_REQUEST_TYPE;
}
if (peer.getState() == Peer.State.DISCONNECTED) {
peer.setState(Peer.State.CONNECTED);
}
if (peer.getVersion() == null && !"getInfo".equals(request.get("requestType"))) {
return SEQUENCE_ERROR;
}
if (!peer.isInbound()) {
if (Peers.hasTooManyInboundPeers()) {
return MAX_INBOUND_CONNECTIONS;
}
Peers.notifyListeners(peer, Peers.Event.ADD_INBOUND);
}
peer.setLastInboundRequest(Nxt.getEpochTime());
if (peerRequestHandler.rejectWhileDownloading()) {
if (blockchainProcessor.isDownloading()) {
return DOWNLOADING;
}
if (Constants.isLightClient) {
return LIGHT_CLIENT;
}
}
return peerRequestHandler.processRequest(request, peer);
} catch (RuntimeException | ParseException | IOException e) {
Logger.logDebugMessage("Error processing POST request: " + e.toString());
peer.blacklist(e);
return error(e);
}
}
Aggregations