convert service from Bound to Started

Add Origin check for JSOIN-RPC Server
This commit is contained in:
Yaroslav Dmytrotsa 2015-08-04 14:25:04 +03:00
parent 1fd463ce31
commit 1a81061679
5 changed files with 168 additions and 198 deletions

View File

@ -0,0 +1,144 @@
package org.ethereum.android.jsonrpc;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
import com.thetransactioncompany.jsonrpc2.server.Dispatcher;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder;
import io.netty.util.CharsetUtil;
import static io.netty.handler.codec.http.HttpHeaders.Names.ACCESS_CONTROL_ALLOW_HEADERS;
import static io.netty.handler.codec.http.HttpHeaders.Names.ACCESS_CONTROL_ALLOW_ORIGIN;
import static io.netty.handler.codec.http.HttpHeaders.Names.ACCESS_CONTROL_REQUEST_METHOD;
import static io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION;
import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH;
import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
import static io.netty.handler.codec.http.HttpHeaders.Names.VARY;
public class JsonRpcServerHandler extends SimpleChannelInboundHandler<HttpObject> {
private HttpRequest request;
private final StringBuilder responseContent = new StringBuilder();
private HttpPostStandardRequestDecoder decoder;
private String postData;
private boolean isOptions = false;
private Dispatcher dispatcher;
public JsonRpcServerHandler(Dispatcher dispatcher) {
super();
this.dispatcher = dispatcher;
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (decoder != null) {
decoder.destroy();
}
}
@Override
public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest req = this.request = (HttpRequest) msg;
if (request.getMethod().equals(HttpMethod.OPTIONS)) {
isOptions = true;
return;
} else if (!req.getUri().equals("/") || !request.getMethod().equals(HttpMethod.POST)) {
responseContent.append("Hi, how are you?!!");
return;
} else {
decoder = new HttpPostStandardRequestDecoder(new DefaultHttpDataFactory(false), req);
postData = "";
}
}
if (decoder != null) {
if (msg instanceof HttpContent) {
HttpContent chunk = (HttpContent) msg;
decoder.offer(chunk);
postData += chunk.content().toString(0, chunk.content().capacity(), CharsetUtil.UTF_8);
if (chunk instanceof LastHttpContent) {
JSONRPC2Request req = JSONRPC2Request.parse(postData);
JSONRPC2Response resp = dispatcher.process(req, null);
responseContent.append(resp);
writeResponse(ctx);
request = null;
decoder.destroy();
decoder = null;
}
}
} else if (isOptions) {
writeOptionsResponse(ctx);
isOptions = false;
} else {
writeResponse(ctx);
}
}
private void writeResponse(ChannelHandlerContext ctx) {
ByteBuf buf = Unpooled.copiedBuffer(responseContent.toString(), CharsetUtil.UTF_8);
responseContent.setLength(0);
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request.headers().get(CONNECTION))
|| request.getProtocolVersion().equals(HttpVersion.HTTP_1_0)
&& !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request.headers().get(CONNECTION));
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buf);
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
response.headers().set(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
if (!close) {
response.headers().set(CONTENT_LENGTH, buf.readableBytes());
}
ChannelFuture future = ctx.writeAndFlush(response);
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
private void writeOptionsResponse(ChannelHandlerContext ctx) {
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request.headers().get(CONNECTION))
|| request.getProtocolVersion().equals(HttpVersion.HTTP_1_0)
&& !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request.headers().get(CONNECTION));
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
response.headers().set(ACCESS_CONTROL_ALLOW_HEADERS, "Content-Type");
response.headers().set(ACCESS_CONTROL_REQUEST_METHOD, "POST");
response.headers().set(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
response.headers().set(VARY, "Origin");
if (!close) {
response.headers().set(CONTENT_LENGTH, 0);
}
ChannelFuture future = ctx.writeAndFlush(response);
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}

View File

@ -10,34 +10,15 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.HttpObject;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.channel.ChannelFuture;
import org.ethereum.android.jsonrpc.full.filter.FilterManager; import org.ethereum.android.jsonrpc.full.filter.FilterManager;
import org.ethereum.facade.Ethereum; import org.ethereum.facade.Ethereum;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*; import com.thetransactioncompany.jsonrpc2.server.*;
import io.netty.handler.codec.http.HttpHeaders;
import static io.netty.handler.codec.http.HttpHeaders.Names.*;
import org.ethereum.android.jsonrpc.full.method.*; import org.ethereum.android.jsonrpc.full.method.*;
import java.net.InetAddress; import java.net.InetAddress;
import org.ethereum.android.jsonrpc.*;
public final class JsonRpcServer extends org.ethereum.android.jsonrpc.JsonRpcServer{ public final class JsonRpcServer extends org.ethereum.android.jsonrpc.JsonRpcServer{
@ -146,82 +127,7 @@ public final class JsonRpcServer extends org.ethereum.android.jsonrpc.JsonRpcSer
public void initChannel(SocketChannel ch) { public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline(); ChannelPipeline p = ch.pipeline();
p.addLast(new HttpServerCodec()); p.addLast(new HttpServerCodec());
p.addLast(new JsonRpcServerHandler()); p.addLast(new JsonRpcServerHandler(dispatcher));
}
}
class JsonRpcServerHandler extends SimpleChannelInboundHandler<HttpObject> {
private HttpRequest request;
private final StringBuilder responseContent = new StringBuilder();
private HttpPostStandardRequestDecoder decoder;
private String postData;
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (decoder != null) {
decoder.destroy();
}
}
@Override
public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest req = this.request = (HttpRequest) msg;
if (!req.getUri().equals("/") || !request.getMethod().equals(HttpMethod.POST)) {
responseContent.append("Hi, how are you?!!");
return;
} else {
decoder = new HttpPostStandardRequestDecoder(new DefaultHttpDataFactory(false), req);
postData = "";
}
}
if (decoder != null) {
if (msg instanceof HttpContent) {
HttpContent chunk = (HttpContent) msg;
decoder.offer(chunk);
postData += chunk.content().toString(0, chunk.content().capacity(), CharsetUtil.UTF_8);
if (chunk instanceof LastHttpContent) {
JSONRPC2Request req = JSONRPC2Request.parse(postData);
JSONRPC2Response resp = dispatcher.process(req, null);
responseContent.append(resp);
writeResponse(ctx);
request = null;
decoder.destroy();
decoder = null;
}
}
} else {
writeResponse(ctx);
}
}
private void writeResponse(ChannelHandlerContext ctx) {
ByteBuf buf = Unpooled.copiedBuffer(responseContent.toString(), CharsetUtil.UTF_8);
responseContent.setLength(0);
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request.headers().get(CONNECTION))
|| request.getProtocolVersion().equals(HttpVersion.HTTP_1_0)
&& !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request.headers().get(CONNECTION));
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buf);
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
if (!close) {
response.headers().set(CONTENT_LENGTH, buf.readableBytes());
}
ChannelFuture future = ctx.writeAndFlush(response);
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
} }
} }
} }

View File

@ -10,36 +10,16 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.HttpObject;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.channel.ChannelFuture;
import org.ethereum.android.jsonrpc.light.whisper.FilterManager; import org.ethereum.android.jsonrpc.light.whisper.FilterManager;
import org.ethereum.facade.Ethereum; import org.ethereum.facade.Ethereum;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*; import com.thetransactioncompany.jsonrpc2.server.*;
import io.netty.handler.codec.http.HttpHeaders;
import static io.netty.handler.codec.http.HttpHeaders.Names.*;
import org.ethereum.android.jsonrpc.light.method.*; import org.ethereum.android.jsonrpc.light.method.*;
import java.net.InetAddress;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import org.ethereum.android.jsonrpc.*;
public final class JsonRpcServer extends org.ethereum.android.jsonrpc.JsonRpcServer{ public final class JsonRpcServer extends org.ethereum.android.jsonrpc.JsonRpcServer{
@ -123,82 +103,7 @@ public final class JsonRpcServer extends org.ethereum.android.jsonrpc.JsonRpcSer
public void initChannel(SocketChannel ch) { public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline(); ChannelPipeline p = ch.pipeline();
p.addLast(new HttpServerCodec()); p.addLast(new HttpServerCodec());
p.addLast(new JsonRpcServerHandler()); p.addLast(new JsonRpcServerHandler(dispatcher));
}
}
class JsonRpcServerHandler extends SimpleChannelInboundHandler<HttpObject> {
private HttpRequest request;
private final StringBuilder responseContent = new StringBuilder();
private HttpPostStandardRequestDecoder decoder;
private String postData;
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (decoder != null) {
decoder.destroy();
}
}
@Override
public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest req = this.request = (HttpRequest) msg;
if (!req.getUri().equals("/") || !request.getMethod().equals(HttpMethod.POST)) {
responseContent.append("Hi, how are you?!!");
return;
} else {
decoder = new HttpPostStandardRequestDecoder(new DefaultHttpDataFactory(false), req);
postData = "";
}
}
if (decoder != null) {
if (msg instanceof HttpContent) {
HttpContent chunk = (HttpContent) msg;
decoder.offer(chunk);
postData += chunk.content().toString(0, chunk.content().capacity(), CharsetUtil.UTF_8);
if (chunk instanceof LastHttpContent) {
JSONRPC2Request req = JSONRPC2Request.parse(postData);
JSONRPC2Response resp = dispatcher.process(req, null);
responseContent.append(resp);
writeResponse(ctx);
request = null;
decoder.destroy();
decoder = null;
}
}
} else {
writeResponse(ctx);
}
}
private void writeResponse(ChannelHandlerContext ctx) {
ByteBuf buf = Unpooled.copiedBuffer(responseContent.toString(), CharsetUtil.UTF_8);
responseContent.setLength(0);
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request.headers().get(CONNECTION))
|| request.getProtocolVersion().equals(HttpVersion.HTTP_1_0)
&& !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request.headers().get(CONNECTION));
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buf);
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
if (!close) {
response.headers().set(CONTENT_LENGTH, buf.readableBytes());
}
ChannelFuture future = ctx.writeAndFlush(response);
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
} }
} }
} }

View File

@ -104,8 +104,7 @@ public abstract class JsonRpcServerMethod implements RequestHandler {
to = jsToAddress((String) obj.get("to")); to = jsToAddress((String) obj.get("to"));
} }
// default - from ethereumj-studio BigInteger gasPrice = getGasPrice();
BigInteger gasPrice = SZABO.value().multiply(BigInteger.TEN);
if (obj.containsKey("gasPrice") && !((String)obj.get("gasPrice")).equals("")) { if (obj.containsKey("gasPrice") && !((String)obj.get("gasPrice")).equals("")) {
gasPrice = jsToBigInteger((String) obj.get("gasPrice")); gasPrice = jsToBigInteger((String) obj.get("gasPrice"));
} }
@ -205,4 +204,15 @@ public abstract class JsonRpcServerMethod implements RequestHandler {
} }
} }
protected BigInteger getGasPrice() {
ArrayList<Object> params = new ArrayList<Object>();
JSONRPC2Request req = new JSONRPC2Request("eth_gasPrice", params, 1000);
JSONRPC2Response res = getRemoteData(req);
if (res == null || !res.indicatesSuccess()) {
return BigInteger.ZERO;
} else {
return jsToBigInteger(res.getResult().toString());
}
}
} }

View File

@ -117,6 +117,7 @@ public class ServiceConnector {
if (serviceConnection != null) { if (serviceConnection != null) {
Intent intent = new Intent(context, serviceClass); Intent intent = new Intent(context, serviceClass);
context.getApplicationContext().startService(intent);
return context.getApplicationContext().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); return context.getApplicationContext().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
} else { } else {
return false; return false;
@ -129,6 +130,10 @@ public class ServiceConnector {
if (isBound && serviceConnection != null) { if (isBound && serviceConnection != null) {
context.getApplicationContext().unbindService(serviceConnection); context.getApplicationContext().unbindService(serviceConnection);
isBound = false; isBound = false;
/*
Intent intent = new Intent(context, serviceClass);
context.getApplicationContext().stopService(intent);
*/
} }
} }