package edu.uncc.cs.watsonsim;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import org.java_websocket.WebSocket;
import org.java_websocket.WebSocketImpl;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import org.json.simple.JSONObject;
/**
* A simple WebSocketServer implementation. Keeps track of a "chatroom".
*/
public class WebsocketFrontend extends WebSocketServer {
private static final int CORES
= Runtime.getRuntime().availableProcessors();
private final ExecutorService es = Executors.newWorkStealingPool();
private final BlockingQueue<DefaultPipeline> free_pipes =
new ArrayBlockingQueue<DefaultPipeline>(CORES);
/**
* Create the frontend, populating pipelines
* @param address
*/
public WebsocketFrontend( InetSocketAddress address ) {
super( address );
for (int i=0; i < CORES; i++) {
free_pipes.offer(new DefaultPipeline());
}
}
public WebsocketFrontend( int port ) throws UnknownHostException {
super( new InetSocketAddress( port ) );
}
@Override
public void onOpen( WebSocket conn, ClientHandshake handshake ) {
// nothing interesting
}
@Override
public void onClose( WebSocket conn, int code, String reason, boolean remote ) {
}
private void send(WebSocket conn, String flag, Object message) {
JSONObject jo = new JSONObject();
jo.put("flag", flag);
jo.put("message", message);
conn.send(jo.toJSONString());
}
/**
* Wrapper for allocating a pipe and asking something of it.
* @return The answers
*/
private List<Answer> ask(WebSocket conn, String qtext) {
System.out.println("waiting on " + qtext);
DefaultPipeline pipe = new DefaultPipeline();
System.out.println("Asking " + qtext);
if (pipe != null) {
List<Answer> answers = pipe.ask(new Question(qtext), a -> send(conn, "log", a));
List<JSONObject> json = answers
.stream()
.map(a -> a.toJSON())
.collect(Collectors.toList());
send(conn, "result", json);
}
// Give up silently? (Not sure what's better here)
return Collections.emptyList();
}
@Override
/**
* Respond to a question like "ask:blahblah"
*/
public void onMessage( WebSocket conn, String message ) {
System.out.println(message);
String[] parts = message.split(":", 2);
System.out.println(Arrays.toString(parts));
if (parts.length == 2) {
String type = parts[0];
String content = parts[1];
switch (type) {
case "ask":
es.submit(() -> ask(conn, content));
break;
}
}
}
/*@Override
public void onFragment( WebSocket conn, Framedata fragment ) {
System.out.println( "received fragment: " + fragment );
}*/
public static void main( String[] args ) throws InterruptedException , IOException {
WebSocketImpl.DEBUG = true;
int port = 8887; // 843 flash policy port
try {
port = Integer.parseInt( args[ 0 ] );
} catch ( Exception ex ) {
}
WebsocketFrontend s = new WebsocketFrontend( port );
s.start();
System.out.println( "Watsonsim Question Server active on : "
+ s.getPort() );
BufferedReader sysin = new BufferedReader( new InputStreamReader( System.in ) );
while ( true ) {
String in = sysin.readLine();
if( in.equals( "exit" ) ) {
s.stop();
break;
}
}
}
@Override
public void onError( WebSocket conn, Exception ex ) {
ex.printStackTrace();
if( conn != null ) {
// some errors like port binding failed may not be assignable to a specific websocket
}
}
}