blob: a9841372615702342c65f30531006b6c197a6f12 [file] [log] [blame]
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.android_scripting.jsonrpc;
import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.SimpleServer;
import com.googlecode.android_scripting.rpc.MethodDescriptor;
import com.googlecode.android_scripting.rpc.RpcError;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* A JSON RPC server that forwards RPC calls to a specified receiver object.
*
* @author Damon Kohler (damonkohler@gmail.com)
*/
public class JsonRpcServer extends SimpleServer {
private final RpcReceiverManagerFactory mRpcReceiverManagerFactory;
private final String mHandshake;
/**
* Construct a {@link JsonRpcServer} connected to the provided {@link RpcReceiverManager}.
*
* @param managerFactory
* the {@link RpcReceiverManager} to register with the server
* @param handshake
* the secret handshake required for authorization to use this server
*/
public JsonRpcServer(RpcReceiverManagerFactory managerFactory, String handshake) {
mHandshake = handshake;
mRpcReceiverManagerFactory = managerFactory;
}
@Override
public void shutdown() {
super.shutdown();
// Notify all RPC receiving objects. They may have to clean up some of their state.
for (RpcReceiverManager manager : mRpcReceiverManagerFactory.getRpcReceiverManagers().values()) {
manager.shutdown();
}
}
@Override
protected void handleRPCConnection(Socket sock, Integer UID, BufferedReader reader, PrintWriter writer) throws Exception {
RpcReceiverManager receiverManager = null;
//Log.d("Sock state 3: "+sock.isClosed());
Log.d("UID "+UID);
Log.d("manager map size: "+mRpcReceiverManagerFactory.getRpcReceiverManagers().size());
Log.d("manager map keys: "+mRpcReceiverManagerFactory.getRpcReceiverManagers().keySet());
if(mRpcReceiverManagerFactory.getRpcReceiverManagers().containsKey(UID)) {
Log.d("Look up existing session");
receiverManager = mRpcReceiverManagerFactory.getRpcReceiverManagers().get(UID);
}else{
Log.d("Create a new session");
receiverManager = mRpcReceiverManagerFactory.create(UID);
}
//Log.d("Sock state 4: "+sock.isClosed());
/*RpcReceiverManager receiverManager = mRpcReceiverManagerFactory.create();
BufferedReader reader =
new BufferedReader(new InputStreamReader(socket.getInputStream()), 8192);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);*/
//boolean passedAuthentication = false;
String data;
while ((data = reader.readLine()) != null) {
Log.v("Session " + UID + " Received: " + data);
JSONObject request = new JSONObject(data);
int id = request.getInt("id");
String method = request.getString("method");
JSONArray params = request.getJSONArray("params");
// First RPC must be _authenticate if a handshake was specified.
// if (!passedAuthentication && mHandshake != null) {
// if (!checkHandshake(method, params)) {
// SecurityException exception = new SecurityException("Authentication failed!");
// send(writer, JsonRpcResult.error(id, exception));
// shutdown();
// throw exception;
// }
// passedAuthentication = true;
// send(writer, JsonRpcResult.result(id, true));
// continue;
// }
MethodDescriptor rpc = receiverManager.getMethodDescriptor(method);
if (rpc == null) {
send(writer, JsonRpcResult.error(id, new RpcError("Unknown RPC.")), UID);
continue;
}
try {
send(writer, JsonRpcResult.result(id, rpc.invoke(receiverManager, params)), UID);
} catch (Throwable t) {
Log.e("Invocation error.", t);
send(writer, JsonRpcResult.error(id, t), UID);
}
}
}
private boolean checkHandshake(String method, JSONArray params) throws JSONException {
if (!method.equals("_authenticate") || !mHandshake.equals(params.getString(0))) {
return false;
}
return true;
}
private void send(PrintWriter writer, JSONObject result, int UID) {
writer.write(result + "\n");
writer.flush();
Log.v("Session " + UID + " Sent: " + result);
}
@Override
protected void handleConnection(Socket socket) throws Exception {
}
}