Added jsonrpc server.

This commit is contained in:
Adrian Tiberius 2015-06-08 14:51:03 +02:00
parent 48df2ae587
commit b3afe42f38
5 changed files with 469 additions and 228 deletions

View File

@ -9,6 +9,7 @@ import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.os.Build;
import org.ethereum.android.EthereumManager;
@ -46,7 +47,15 @@ public class MainActivity extends ActionBarActivity {
//StrictMode.enableDefaults();
new PostTask().execute();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
new PostTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
new PostTask().execute();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
new JsonRpcTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
new JsonRpcTask().execute();
}
@Override
@ -115,4 +124,36 @@ public class MainActivity extends ActionBarActivity {
super.onPostExecute(result);
}
}
// The definition of our task class
private class JsonRpcTask extends AsyncTask<Context, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(Context... params) {
Log.v(TAG, "444");
try {
ethereumManager.startJsonRpc();
} catch (Exception e) {
}
Log.v(TAG, "555");
return "done";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.v(TAG, values[0].toString());
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
}

View File

@ -57,4 +57,6 @@ dependencies {
compile "org.iq80.leveldb:leveldb:0.7"
compile 'org.slf4j:slf4j-android:1.7.12'
compile 'javax.persistence:persistence-api:1.0.2'
compile group: 'com.thetransactioncompany', name: 'jsonrpc2-server', version: '1.11'
}

View File

@ -9,6 +9,7 @@ import org.ethereum.facade.Ethereum;
import org.ethereum.listener.EthereumListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.ethereum.android.jsonrpc.JsonRpcServer;
public class EthereumManager {
@ -16,6 +17,8 @@ public class EthereumManager {
public static Ethereum ethereum = null;
private JsonRpcServer jsonRpcServer;
public EthereumManager(Context context) {
System.setProperty("sun.arch.data.model", "32");
@ -23,6 +26,8 @@ public class EthereumManager {
ethereum = DaggerEthereumComponent.builder()
.ethereumModule(new EthereumModule(context))
.build().ethereum();
jsonRpcServer = new JsonRpcServer(ethereum);
}
public void start() {
@ -47,4 +52,9 @@ public class EthereumManager {
ethereum.addListener(listener);
}
public void startJsonRpc() throws Exception {
jsonRpcServer.start();
}
}

View File

@ -0,0 +1,159 @@
package org.ethereum.android.jsonrpc;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
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.facade.Ethereum;
import com.thetransactioncompany.jsonrpc2.*;
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.method.*;
public final class JsonRpcServer {
static final int PORT = 8545;
private Ethereum ethereum;
private Dispatcher dispatcher;
public JsonRpcServer(Ethereum ethereum) {
this.ethereum = ethereum;
this.dispatcher = new Dispatcher();
this.dispatcher.register(new eth_coinbase(this.ethereum));
}
public void start() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.SO_BACKLOG, 1024);
// b.localAddress(InetAddress.getLocalHost(), PORT);
b.localAddress(PORT);
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new JsonRpcServerInitializer());
Channel ch = b.bind().sync().channel();
ch.closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
class JsonRpcServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast(new HttpServerCodec());
p.addLast(new JsonRpcServerHandler());
}
}
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

@ -0,0 +1,29 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.facade.Ethereum;
public class eth_coinbase implements RequestHandler {
private String name = "";
private Ethereum ethereum;
public eth_coinbase(Ethereum ethereum) {
this.ethereum = ethereum;
name = this.getClass().getSimpleName();
}
public String[] handledRequests() {
return new String[]{name};
}
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals(name)) {
//TODO: place business logic here
return null;
} else {
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
}
}
}