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.event; 18 19 import com.googlecode.android_scripting.Log; 20 import com.googlecode.android_scripting.SimpleServer; 21 import com.googlecode.android_scripting.jsonrpc.JsonBuilder; 22 23 import java.io.BufferedReader; 24 import java.io.IOException; 25 import java.io.PrintWriter; 26 import java.net.InetSocketAddress; 27 import java.net.Socket; 28 import java.util.Vector; 29 import java.util.concurrent.CountDownLatch; 30 31 import org.json.JSONException; 32 33 /** 34 * An Event Forwarding server that forwards events from the rpc queue in realtime to listener 35 * clients. 36 * 37 */ 38 public class EventServer extends SimpleServer implements EventObserver { 39 private static final Vector<Listener> mListeners = new Vector<Listener>(); 40 private InetSocketAddress address = null; 41 EventServer()42 public EventServer() { 43 this(0); 44 } 45 EventServer(int port)46 public EventServer(int port) { 47 address = startAllInterfaces(port); 48 } 49 getAddress()50 public InetSocketAddress getAddress() { 51 return address; 52 } 53 54 @Override shutdown()55 public void shutdown() { 56 onEventReceived(new Event("sl4a", "{\"shutdown\": \"event-server\"}")); 57 for (Listener listener : mListeners) { 58 mListeners.remove(listener); 59 listener.lock.countDown(); 60 } 61 super.shutdown(); 62 } 63 64 @Override handleConnection(Socket socket)65 protected void handleConnection(Socket socket) throws IOException { 66 Log.d("handle event connection."); 67 Listener l = new Listener(socket); 68 Log.v("Adding EventServer listener " + socket.getPort()); 69 mListeners.add(l); 70 // we are running in the socket accept thread 71 // wait until the event dispatcher gets us the events 72 // or we die, what ever happens first 73 try { 74 l.lock.await(); 75 } catch (InterruptedException e) { 76 e.printStackTrace(); 77 } 78 try { 79 l.sock.close(); 80 } catch (IOException e) { 81 e.printStackTrace(); 82 } 83 Log.v("Ending EventServer listener " + socket.getPort()); 84 } 85 86 @Override onEventReceived(Event event)87 public void onEventReceived(Event event) { 88 Object result = null; 89 try { 90 result = JsonBuilder.build(event); 91 } catch (JSONException e) { 92 return; 93 } 94 95 Log.v("EventServer dispatching " + result); 96 97 for (Listener listener : mListeners) { 98 if (!listener.out.checkError()) { 99 listener.out.write(result + "\n"); 100 listener.out.flush(); 101 } else { 102 // let the socket accept thread we're done 103 mListeners.remove(listener); 104 listener.lock.countDown(); 105 } 106 } 107 } 108 109 private class Listener { 110 private Socket sock; 111 private PrintWriter out; 112 private CountDownLatch lock = new CountDownLatch(1); 113 Listener(Socket l)114 public Listener(Socket l) throws IOException { 115 sock = l; 116 out = new PrintWriter(l.getOutputStream(), true); 117 } 118 } 119 120 @Override handleRPCConnection(Socket sock, Integer UID, BufferedReader reader, PrintWriter writer)121 protected void handleRPCConnection(Socket sock, Integer UID, BufferedReader reader, PrintWriter writer) 122 throws Exception { 123 } 124 } 125