Last active
November 6, 2015 15:03
-
-
Save sirolf2009/242c35c162ae835aa4b7 to your computer and use it in GitHub Desktop.
A rest api based socket server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static spark.Spark.post; | |
import static spark.Spark.get; | |
import java.io.IOException; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Queue; | |
import org.apache.logging.log4j.LogManager; | |
import org.apache.logging.log4j.Logger; | |
import com.google.gson.Gson; | |
import com.google.gson.JsonSyntaxException; | |
import spark.Request; | |
import spark.servlet.SparkApplication; | |
public class Server implements SparkApplication { | |
private static final Logger log = LogManager.getLogger(Server.class); | |
private List<Listener> listeners; | |
private Map<Integer, Connection> connections; | |
private List<Integer> disconnectedConnections; | |
private Gson gson; | |
private Counter counter; | |
public Server() { | |
listeners = new ArrayList<Listener>(); | |
connections = new HashMap<Integer, Connection>(); | |
gson = new Gson(); | |
counter = new Counter(); | |
disconnectedConnections = new ArrayList<Integer>(); | |
} | |
@Override | |
public void init() { | |
post("/push/:ID", (req, res) -> { | |
log.debug(req.params("ID")+" is pushing:\n"+req.body()); | |
new Thread(() -> { | |
for(Listener listener : listeners) { | |
try { | |
listener.received(getConnection(Integer.parseInt(req.params("ID"))), parse(req)); | |
} catch(Exception e) { | |
log.error("Failed to receive new data", e); | |
} | |
} | |
}).start(); | |
return msg("ok"); | |
}); | |
get("/register", (req, res) -> { | |
int ID = counter.next(); | |
Connection connection = new Connection(this, ID); | |
connections.put(ID, connection); | |
log.trace(ID+" registered"); | |
for(Listener listener : listeners) { | |
try { | |
listener.connected(connection); | |
} catch(Exception e) { | |
log.error("Failed to deliver a new connection to a listener"); | |
} | |
} | |
return ID; | |
}); | |
get("/unregister/:ID", (req, res) -> { | |
if(req.params("ID") == null) { | |
log.debug(req.ip()+" unregister without registering"); | |
return "/register for /unregister"; | |
} | |
int ID = -1; | |
try { | |
ID = Integer.parseInt(req.params("ID")); | |
} catch(NumberFormatException e) { | |
log.error(req.params("ID")+" cannot be parsed as an integer"); | |
return "That is not an ID"; | |
} | |
getConnection(ID).close(); | |
return "ok"; | |
}); | |
get("/fetch/:ID", (req, res) -> { | |
if(req.params("ID") == null) { | |
log.debug(req.ip()+" fetched without registering"); | |
return "/register for /fetch"; | |
} | |
int ID = -1; | |
try { | |
ID = Integer.parseInt(req.params("ID")); | |
} catch(NumberFormatException e) { | |
log.error(req.params("ID")+" cannot be parsed as an integer"); | |
return "That is not an ID"; | |
} | |
log.debug(ID+" is fetching updates"); | |
if(disconnectedConnections.contains(ID)) { | |
log.debug(req.params("ID")+" is about to hear that he is disconnected"); | |
disconnectedConnections.remove(new Integer(ID)); | |
res.status(400); | |
} | |
if(getConnection(ID) == null) { | |
log.error(ID+" tried to fetch, but he does not exist"); | |
return "You don't exist"; | |
} | |
String body = getConnection(ID).getMessages(gson); | |
log.debug(ID+" is replied with \n"+body); | |
return body; | |
}); | |
try { | |
new ServerProgram(this); | |
} catch (IOException e) { | |
log.error("Failed to start serverprogram", e); | |
} | |
} | |
//Implemented from kryo | |
public void sendToTCP(int hostConnection, Object object) { | |
if(hostConnection > 0) { | |
log.debug("send "+object+" to "+hostConnection); | |
connections.get(hostConnection).send(object); | |
} | |
} | |
public Connection[] getConnections() { | |
return connections.values().toArray(new Connection[connections.values().size()]); | |
} | |
public void addListener(Listener listener) { | |
log.debug("Adding listener: "+listener); | |
listeners.add(listener); | |
} | |
//No longer implemented from kryo | |
public String msg(String msg) { | |
return gson.toJson(new Message(msg)); | |
} | |
public void close(Connection connection) { | |
for(Listener listener : listeners) { | |
try { | |
listener.disconnected(connection); | |
} catch(Exception e) { | |
log.error("Failed to deliver a disconnect to a listener", e); | |
} | |
} | |
connections.remove(connection.getID()); | |
disconnectedConnections.add(connection.getID()); | |
} | |
public Connection getConnection(int ID) { | |
return connections.get(ID); | |
} | |
public Object parse(Request req) { | |
String body = req.body(); | |
try { | |
return gson.fromJson(body, PacketMessage.Multiplayer.class); | |
} catch(JsonSyntaxException e) {} | |
try { | |
return gson.fromJson(body, PacketMessage.Game.class); | |
} catch(JsonSyntaxException e) {} | |
try { | |
return gson.fromJson(body, PacketMessage.Finish.class); | |
} catch(JsonSyntaxException e) {} | |
try { | |
return gson.fromJson(body, PacketMessage.GameStart.class); | |
} catch(JsonSyntaxException e) {} | |
try { | |
return gson.fromJson(body, PacketMessage.HostSettings.class); | |
} catch(JsonSyntaxException e) {} | |
throw new RuntimeException("Json body is not a known object:\n"+body); | |
} | |
private class Counter { | |
private int i = 0; | |
public int next() { | |
i++; | |
return i; | |
} | |
} | |
private class Message { | |
private String message; | |
public Message(String message) { | |
this.message = message; | |
} | |
} | |
public interface Listener { | |
public void connected(Connection connection); | |
public void received(Connection connection, Object object); | |
public void disconnected(Connection connection); | |
} | |
public class Connection { | |
private int id; | |
private Server server; | |
private Queue<Object> messageQueue; //RabbitMQueue easier variant | |
public Connection(Server server, int id) { | |
setServer(server); | |
setID(id); | |
setMessageQueue(new LinkedList<Object>()); | |
} | |
public Connection() { | |
} | |
public String getMessages(Gson gson) { | |
String messages = gson.toJson(messageQueue); | |
flush(); | |
return messages; | |
} | |
public void send(Object object) { | |
messageQueue.add(object); | |
} | |
public void flush() { | |
messageQueue.clear(); | |
} | |
public void close() { | |
server.close(this); | |
} | |
public int getID() { | |
return id; | |
} | |
public void setID(int id) { | |
this.id = id; | |
} | |
public Server getServer() { | |
return server; | |
} | |
public void setServer(Server server) { | |
this.server = server; | |
} | |
public Queue<Object> getMessageQueue() { | |
return messageQueue; | |
} | |
public void setMessageQueue(Queue<Object> messageQueue) { | |
this.messageQueue = messageQueue; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment