Home | History | Annotate | Download | only in jsonrpc
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.googlecode.android_scripting.jsonrpc;
     18 
     19 import java.io.BufferedReader;
     20 import java.io.PrintWriter;
     21 import java.net.Socket;
     22 import java.util.Map;
     23 
     24 import org.json.JSONArray;
     25 import org.json.JSONObject;
     26 
     27 import com.googlecode.android_scripting.Log;
     28 import com.googlecode.android_scripting.SimpleServer;
     29 import com.googlecode.android_scripting.rpc.MethodDescriptor;
     30 import com.googlecode.android_scripting.rpc.RpcError;
     31 
     32 /**
     33  * A JSON RPC server that forwards RPC calls to a specified receiver object.
     34  *
     35  */
     36 public class JsonRpcServer extends SimpleServer {
     37     private final RpcReceiverManagerFactory mRpcReceiverManagerFactory;
     38 
     39     // private final String mHandshake;
     40 
     41     /**
     42      * Construct a {@link JsonRpcServer} connected to the provided {@link RpcReceiverManager}.
     43      *
     44      * @param managerFactory the {@link RpcReceiverManager} to register with the server
     45      * @param handshake the secret handshake required for authorization to use this server
     46      */
     47     public JsonRpcServer(RpcReceiverManagerFactory managerFactory, String handshake) {
     48         // mHandshake = handshake;
     49         mRpcReceiverManagerFactory = managerFactory;
     50     }
     51 
     52     @Override
     53     public void shutdown() {
     54         super.shutdown();
     55         // Notify all RPC receiving objects. They may have to clean up some of their state.
     56         for (RpcReceiverManager manager : mRpcReceiverManagerFactory.getRpcReceiverManagers()
     57                 .values()) {
     58             manager.shutdown();
     59         }
     60     }
     61 
     62     @Override
     63     protected void handleRPCConnection(Socket sock, Integer UID, BufferedReader reader,
     64             PrintWriter writer) throws Exception {
     65         RpcReceiverManager receiverManager = null;
     66         Map<Integer, RpcReceiverManager> mgrs = mRpcReceiverManagerFactory.getRpcReceiverManagers();
     67         synchronized (mgrs) {
     68             Log.d("UID " + UID);
     69             Log.d("manager map keys: "
     70                     + mRpcReceiverManagerFactory.getRpcReceiverManagers().keySet());
     71             if (mgrs.containsKey(UID)) {
     72                 Log.d("Look up existing session");
     73                 receiverManager = mgrs.get(UID);
     74             } else {
     75                 Log.d("Create a new session");
     76                 receiverManager = mRpcReceiverManagerFactory.create(UID);
     77             }
     78         }
     79         // boolean passedAuthentication = false;
     80         String data;
     81         while ((data = reader.readLine()) != null) {
     82             Log.v("Session " + UID + " Received: " + data);
     83             JSONObject request = new JSONObject(data);
     84             int id = request.getInt("id");
     85             String method = request.getString("method");
     86             JSONArray params = request.getJSONArray("params");
     87 
     88             MethodDescriptor rpc = receiverManager.getMethodDescriptor(method);
     89             if (rpc == null) {
     90                 send(writer, JsonRpcResult.error(id, new RpcError("Unknown RPC: " + method)), UID);
     91                 continue;
     92             }
     93             try {
     94                 send(writer, JsonRpcResult.result(id, rpc.invoke(receiverManager, params)), UID);
     95             } catch (Throwable t) {
     96                 Log.e("Invocation error.", t);
     97                 send(writer, JsonRpcResult.error(id, t), UID);
     98             }
     99         }
    100     }
    101 
    102     private void send(PrintWriter writer, JSONObject result, int UID) {
    103         writer.write(result + "\n");
    104         writer.flush();
    105         Log.v("Session " + UID + " Sent: " + result);
    106     }
    107 
    108     @Override
    109     protected void handleConnection(Socket socket) throws Exception {
    110     }
    111 }
    112