add: Implementation du interop pour le channel emergency

This commit is contained in:
SeekDaSky 2017-12-07 21:03:06 +01:00
parent 8ba61305cc
commit 294d42a26c
7 changed files with 305 additions and 5 deletions

View File

@ -1,4 +1,4 @@
import kotlinx.coroutines.experimental.async
import Collections.Stack
import org.json.JSONArray
import org.json.JSONObject
import seekdasky.kWebSocket.Client
@ -6,13 +6,12 @@ import seekdasky.kWebSocket.Event
import seekdasky.kWebSocket.Listeners.AsynchronousListener
import seekdasky.kWebSocket.Message.*;
import seekdasky.kWebSocket.Server
import kotlin.test.currentStackTrace
class Channel : AsynchronousListener {
val channelName : String;
var clients : MutableList<Client>;
val messages : Stack<Pair<Client,String>>;
val messages : Stack<Pair<Client, String>>;
val serv : Server;
constructor(serv : Server , chanName : String){

219
src/Channels/Emergency.kt Normal file
View File

@ -0,0 +1,219 @@
package Channels
import Collections.Message
import Collections.Stack
import org.json.JSONArray
import org.json.JSONObject
import seekdasky.kWebSocket.Client
import seekdasky.kWebSocket.Event
import seekdasky.kWebSocket.Listeners.AsynchronousListener
import seekdasky.kWebSocket.Message.buildTextMessage
import seekdasky.kWebSocket.Server
class Emergency : AsynchronousListener {
var clients : MutableList<Client>;
val messages : MutableMap<String,Stack<Pair<String,Message>>>;
val serv : Server;
constructor(serv : Server){
this.clients = mutableListOf();
this.messages = mutableMapOf();
this.serv = serv;
}
override fun filter(c: Client): Boolean {
val regex = "\\/emergency\\/(.*)".toRegex()
val result = regex.findAll(c.URL);
if(result.count() == 1){
return true;
}
return false;
}
override fun processClosed(e: Event) {
this.clients.remove(e.client);
ConnectChannel.notifyDisconnect(e.client);
System.out.println("A client disconnected ("+this.clients.count()+" clients connected)");
}
override fun processConnection(c: Client) {
this.clients.add(c);
val regex = "\\/emergency\\/(.*)".toRegex();
val result = regex.findAll(c.URL).elementAt(0).groups[1]?.value ?: "";
//create stack if not present
if(this.messages[result] == null){
this.messages[result] = Stack( 50);
}
//bind client to channel
if(c.data["emergencyChannel"] == null){
c.data["emergencyChannel"] = result;
}
c.data["IsLogged"] = false;
}
fun manuallyDispatchMessage(channel : String, msg : String, username : String, location : List<Float>){
val message = Message();
message.location = location.toMutableList();
message.message = msg;
message.user = username;
message.timestamp = System.currentTimeMillis() / 1000;
val channelStack = this.messages[channel];
if(channelStack != null){
synchronized(channelStack, {
channelStack.push(Pair(username,message));
})
val array = JSONArray();
array.put(message.toJSON())
val jsonMessage = JSONObject();
jsonMessage.put("error",false);
jsonMessage.put("data",array);
for(c in this.clients){
if(c.data["IsLogged"] == true && c.data["emergencyChannel"] == channel){
c.send(buildTextMessage(jsonMessage.toString()));
}
}
}else if (channel == ""){
//broadcast
for(c in this.messages.values){
synchronized(c,{
c.push(Pair(username,message));
})
}
val array = JSONArray();
array.put(message.toJSON())
val jsonMessage = JSONObject();
jsonMessage.put("error",false);
jsonMessage.put("data",array);
for(c in this.clients){
if(c.data["IsLogged"] == true){
c.send(buildTextMessage(jsonMessage.toString()));
}
}
}
}
override fun processEvent(e: Event) {
System.out.println(e.message.toString());
try{
val json = JSONObject(e.message.getString())
//dead code, should remove it later
if(json.has("close")){
return
}
//si l'utilisateur n'est pas log, on le check
if(e.client.data["IsLogged"] != true){
//json format : {username:xxx}
if(json.has("name") && json.getString("name") != null){
e.client.data["Username"] = json.getString("name");
//if the client correctly identified with the Interop server
if(ConnectChannel.isConnected(e.client)){
//log
System.out.println("Emergency connection ("+this.clients.count()+" clients connected)");
//return OK to the client
e.client.data["IsLogged"] = true;
val jsonLogin = JSONObject();
jsonLogin.put("error",false);
e.client.send(buildTextMessage(jsonLogin.toString()));
//give the client the list of the most recent messages
val array = JSONArray();
val chanMessages = this.messages[e.client.data["emergencyChannel"]];
if(chanMessages != null){
synchronized(chanMessages,{
chanMessages.toList().forEach {
array.put(it.second.toJSON())
}
})
}
//build JSON
val jsonMessage = JSONObject();
jsonMessage.put("error",false);
jsonMessage.put("data",array);
e.client.send(buildTextMessage(jsonMessage.toString()));
}else{
val jsonError = JSONObject();
jsonError.put("error","Invalid credentials");
e.client.send(buildTextMessage(jsonError.toString()));
}
}else{
//tried to access chat without logging in
val jsonError = JSONObject();
jsonError.put("error","You must send your credential before sending anything else");
e.client.send(buildTextMessage(jsonError.toString()));
}
return;
}else if(json.has("message")){
val chanMessages = this.messages[e.client.data["emergencyChannel"]];
val message = Message();
if(chanMessages != null){
message.user = e.client.data["Username"].toString();
message.message = json.getString("message");
var lat = 0F;
var lng = 0F;
//javascript may send float as integer so we double check that
try {
lat = (json.getJSONArray("location")[0] as Double).toFloat();
}catch(e : Exception){
lat = (json.getJSONArray("location")[0] as Integer).toFloat();
}
try {
lng = (json.getJSONArray("location")[1] as Double).toFloat();
}catch(e : Exception){
lng = (json.getJSONArray("location")[1] as Integer).toFloat();
}
message.location = mutableListOf(lat,lng);
synchronized(chanMessages,{
chanMessages.push(Pair(e.client.data["Username"].toString(),message))
});
}
val array = JSONArray();
array.put(message.toJSON())
val jsonMessage = JSONObject();
jsonMessage.put("error",false);
jsonMessage.put("data",array);
for(c in this.clients){
if(c.data["IsLogged"] == true && c.data["emergencyChannel"] == e.client.data["emergencyChannel"]){
c.send(buildTextMessage(jsonMessage.toString()));
}
}
}else{
System.out.println("unknown JSON: "+json.toString());
}
}catch (e : Exception){
//System.out.println("Something went wrong (probably JSON parsing error");
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,27 @@
package Collections
import org.json.JSONObject
import java.lang.System;
class Message {
var user = "";
var message = "";
var timestamp = 0L;
var location = mutableListOf<Float>();
constructor(){
this.timestamp = System.currentTimeMillis() / 1000;
}
fun toJSON() : JSONObject{
val json = JSONObject();
json.put("user",user);
json.put("message",message);
json.put("timestamp",timestamp);
json.put("location",location);
return json;
}
}

View File

@ -1,3 +1,5 @@
package Collections
class Stack<T>(size : Int){
var itCounter = 0;

View File

@ -1,3 +1,4 @@
import Collections.Stack
import org.json.JSONObject
import seekdasky.UTF8Encoding.encode
import seekdasky.kWebSocket.Client
@ -9,14 +10,17 @@ object ConnectChannel : InteropListener {
private var lastGuestIndex = 0;
private val notBoundYet = Stack<Pair<String,String>>(500);
private val notBoundYet = Stack<Pair<String, String>>(500);
private val connected = mutableMapOf<Client, String>();
override fun filter(e: InteropEvent): Boolean {
try{
val json = JSONObject(e.message.string);
return json.has("type") && json.has("name");
return json.has("operation") &&
json.getString("operation") == "Connect" &&
json.has("type") &&
json.has("name");
}catch (e : Exception){
return false
}

View File

@ -0,0 +1,43 @@
package Interop
import Channels.Emergency
import org.json.JSONObject
import seekdasky.kWebSocket.InteropEvent
import seekdasky.kWebSocket.Listeners.InteropListener
class PostMessage : InteropListener {
val emergencyController : Emergency;
constructor(emergency : Emergency){
this.emergencyController = emergency;
}
override fun filter(e: InteropEvent): Boolean {
val json = JSONObject(e.message.string);
return json.has("operation") &&
json.getString("operation") == "PostMessage";
}
override fun processEvent(e: InteropEvent) {
try {
val json = JSONObject(e.message.string);
val location = listOf<Float>((json.getJSONArray("location")[0] as Double).toFloat(), (json.getJSONArray("location")[1] as Double).toFloat());
this.emergencyController.manuallyDispatchMessage(
json.getString("channelName"),
json.getString("message"),
json.getString("username"),
location
)
}catch(e : Exception){
e.printStackTrace()
}
}
}

View File

@ -1,3 +1,5 @@
import Channels.Emergency
import Interop.PostMessage
import seekdasky.kWebSocket.Server
@ -5,7 +7,11 @@ fun main(args: Array<String>){
val server = Server("0.0.0.0",9999,null);
server.startInteropServer("localhost",9998);
val emergencyChannel = Emergency(server);
server.addListener(Channel(server,"/chat"));
server.addListener(emergencyChannel);
server.addInteropListener(PostMessage(emergencyChannel));
server.addInteropListener(ConnectChannel);
server.startServer();