refactoring des chanels : classe parente abstraite
This commit is contained in:
parent
c0d3d1d1a5
commit
ecaed684fc
|
@ -0,0 +1,271 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
abstract class AbstractChannel : AsynchronousListener {
|
||||||
|
|
||||||
|
var clients : MutableList<Client>;
|
||||||
|
val messages : MutableMap<String, Stack<Pair<String, Message>>>;
|
||||||
|
val serv : Server;
|
||||||
|
abstract val chanName : String;
|
||||||
|
|
||||||
|
constructor(serv : Server){
|
||||||
|
this.clients = mutableListOf();
|
||||||
|
this.messages = mutableMapOf();
|
||||||
|
this.serv = serv;
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun filter(c: Client): Boolean {
|
||||||
|
val regex = "\\/$chanName\\/(.*)".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 = "\\/$chanName\\/(.*)".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 : Message, operation : String){
|
||||||
|
|
||||||
|
val channelStack = this.messages[channel];
|
||||||
|
|
||||||
|
if(channelStack != null){
|
||||||
|
|
||||||
|
synchronized(channelStack, {
|
||||||
|
channelStack.push(Pair(msg.user,msg));
|
||||||
|
})
|
||||||
|
|
||||||
|
this.dispatchMessage(channel,msg,operation);
|
||||||
|
}else if (channel == ""){
|
||||||
|
//broadcast
|
||||||
|
for(c in this.messages.values){
|
||||||
|
synchronized(c,{
|
||||||
|
c.push(Pair(msg.user,msg));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dispatchMessage(channel,msg,operation);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processEvent(e: Event) {
|
||||||
|
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 = JSONObject();
|
||||||
|
|
||||||
|
val chanMessages = this.messages[e.client.data["emergencyChannel"]];
|
||||||
|
if(chanMessages != null){
|
||||||
|
synchronized(chanMessages,{
|
||||||
|
chanMessages.toList().forEach {
|
||||||
|
array.put(it.second.id,it.second.toJSON())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//build JSON
|
||||||
|
val jsonMessage = JSONObject();
|
||||||
|
jsonMessage.put("error",false);
|
||||||
|
jsonMessage.put("add",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");
|
||||||
|
message.id = "-1";
|
||||||
|
|
||||||
|
var lat : Float;
|
||||||
|
var lng : Float;
|
||||||
|
|
||||||
|
//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);
|
||||||
|
|
||||||
|
if(json.has("type")){
|
||||||
|
message.type = json.getInt("type");
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized(chanMessages,{
|
||||||
|
chanMessages.push(Pair(e.client.data["Username"].toString(),message))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var chanName = "";
|
||||||
|
if(e.client.data["emergencyChannel"] != null){
|
||||||
|
chanName = e.client.data["emergencyChannel"].toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(c in this.clients){
|
||||||
|
this.dispatchMessage(chanName,message,"add");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
System.out.println("unknown JSON: "+json.toString());
|
||||||
|
}
|
||||||
|
}catch (e : Exception){
|
||||||
|
//System.out.println("Something went wrong (probably JSON parsing error");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dispatchMessage(channel: String, message: Message, operation : String){
|
||||||
|
|
||||||
|
val authorizedOperations = listOf<String>("add","upd","del");
|
||||||
|
|
||||||
|
if(!authorizedOperations.contains(operation)){
|
||||||
|
throw Exception("Unauthorized operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
val array = JSONObject();
|
||||||
|
array.put(message.id,message.toJSON())
|
||||||
|
|
||||||
|
val jsonMessage = JSONObject();
|
||||||
|
jsonMessage.put("error",false);
|
||||||
|
|
||||||
|
//all operations must be present but can be empty
|
||||||
|
for (op in authorizedOperations){
|
||||||
|
if(op == operation){
|
||||||
|
jsonMessage.put(op,array);
|
||||||
|
}else{
|
||||||
|
jsonMessage.put(op, JSONArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(c in this.clients){
|
||||||
|
//dispatch message to logged client in the right channel or in any channel if channel is an empty string (broadcast)
|
||||||
|
if(c.data["IsLogged"] == true && ((channel != "" && c.data["emergencyChannel"] == channel) || channel == "")){
|
||||||
|
c.send(buildTextMessage(jsonMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteMessage(id : String){
|
||||||
|
this.messages.keys.forEach {
|
||||||
|
val key = it;
|
||||||
|
val array = this.messages[it];
|
||||||
|
array?.toList()?.forEach{
|
||||||
|
if(it.second.id == id){
|
||||||
|
array.remove(it);
|
||||||
|
val msg = Message()
|
||||||
|
msg.id = id;
|
||||||
|
this.dispatchMessage(key,msg,"del");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateMessage(msg : Message){
|
||||||
|
this.messages.keys.forEach {
|
||||||
|
val key = it;
|
||||||
|
val array = this.messages[it];
|
||||||
|
var index = 0;
|
||||||
|
array?.toList()?.forEach{
|
||||||
|
if(it.second.id == msg.id){
|
||||||
|
msg.user = it.second.user;
|
||||||
|
msg.location = it.second.location;
|
||||||
|
msg.timestamp = it.second.timestamp;
|
||||||
|
array.set(index,Pair(it.first,msg));
|
||||||
|
this.dispatchMessage(key,msg,"upd");
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMessages(chan : String) : MutableList<Pair<String, Message>>{
|
||||||
|
val channel = this.messages[chan]?.toList();
|
||||||
|
val returned = mutableListOf<Pair<String, Message>>()
|
||||||
|
if(channel != null){
|
||||||
|
for (m in channel){
|
||||||
|
returned.add(Pair(m.second.id,m.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return returned;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,265 +1,10 @@
|
||||||
package Channels
|
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
|
import seekdasky.kWebSocket.Server
|
||||||
|
|
||||||
class Emergency : AsynchronousListener {
|
class Emergency : AbstractChannel {
|
||||||
|
|
||||||
var clients : MutableList<Client>;
|
override val chanName = "emergency";
|
||||||
val messages : MutableMap<String,Stack<Pair<String,Message>>>;
|
|
||||||
val serv : Server;
|
|
||||||
|
|
||||||
constructor(serv : Server){
|
constructor(server: Server) : super(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 : Message, operation : String){
|
|
||||||
|
|
||||||
val channelStack = this.messages[channel];
|
|
||||||
|
|
||||||
if(channelStack != null){
|
|
||||||
|
|
||||||
synchronized(channelStack, {
|
|
||||||
channelStack.push(Pair(msg.user,msg));
|
|
||||||
})
|
|
||||||
|
|
||||||
this.dispatchMessage(channel,msg,operation);
|
|
||||||
}else if (channel == ""){
|
|
||||||
//broadcast
|
|
||||||
for(c in this.messages.values){
|
|
||||||
synchronized(c,{
|
|
||||||
c.push(Pair(msg.user,msg));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dispatchMessage(channel,msg,operation);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun processEvent(e: Event) {
|
|
||||||
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 = JSONObject();
|
|
||||||
|
|
||||||
val chanMessages = this.messages[e.client.data["emergencyChannel"]];
|
|
||||||
if(chanMessages != null){
|
|
||||||
synchronized(chanMessages,{
|
|
||||||
chanMessages.toList().forEach {
|
|
||||||
array.put(it.second.id,it.second.toJSON())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//build JSON
|
|
||||||
val jsonMessage = JSONObject();
|
|
||||||
jsonMessage.put("error",false);
|
|
||||||
jsonMessage.put("add",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");
|
|
||||||
message.id = "-1";
|
|
||||||
|
|
||||||
var lat : Float;
|
|
||||||
var lng : Float;
|
|
||||||
|
|
||||||
//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))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var chanName = "";
|
|
||||||
if(e.client.data["emergencyChannel"] != null){
|
|
||||||
chanName = e.client.data["emergencyChannel"].toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(c in this.clients){
|
|
||||||
this.dispatchMessage(chanName,message,"add");
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
System.out.println("unknown JSON: "+json.toString());
|
|
||||||
}
|
|
||||||
}catch (e : Exception){
|
|
||||||
//System.out.println("Something went wrong (probably JSON parsing error");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun dispatchMessage(channel: String,message: Message, operation : String){
|
|
||||||
|
|
||||||
val authorizedOperations = listOf<String>("add","upd","del");
|
|
||||||
|
|
||||||
if(!authorizedOperations.contains(operation)){
|
|
||||||
throw Exception("Unauthorized operation");
|
|
||||||
}
|
|
||||||
|
|
||||||
val array = JSONObject();
|
|
||||||
array.put(message.id,message.toJSON())
|
|
||||||
|
|
||||||
val jsonMessage = JSONObject();
|
|
||||||
jsonMessage.put("error",false);
|
|
||||||
|
|
||||||
//all operations must be present but can be empty
|
|
||||||
for (op in authorizedOperations){
|
|
||||||
if(op == operation){
|
|
||||||
jsonMessage.put(op,array);
|
|
||||||
}else{
|
|
||||||
jsonMessage.put(op,JSONArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(c in this.clients){
|
|
||||||
//dispatch message to logged client in the right channel or in any channel if channel is an empty string (broadcast)
|
|
||||||
if(c.data["IsLogged"] == true && ((channel != "" && c.data["emergencyChannel"] == channel) || channel == "")){
|
|
||||||
c.send(buildTextMessage(jsonMessage.toString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteMessage(id : String){
|
|
||||||
this.messages.keys.forEach {
|
|
||||||
val key = it;
|
|
||||||
val array = this.messages[it];
|
|
||||||
array?.toList()?.forEach{
|
|
||||||
if(it.second.id == id){
|
|
||||||
array.remove(it);
|
|
||||||
val msg = Message()
|
|
||||||
msg.id = id;
|
|
||||||
this.dispatchMessage(key,msg,"del");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateMessage(msg : Message){
|
|
||||||
this.messages.keys.forEach {
|
|
||||||
val key = it;
|
|
||||||
val array = this.messages[it];
|
|
||||||
var index = 0;
|
|
||||||
array?.toList()?.forEach{
|
|
||||||
if(it.second.id == msg.id){
|
|
||||||
msg.user = it.second.user;
|
|
||||||
msg.location = it.second.location;
|
|
||||||
msg.timestamp = it.second.timestamp;
|
|
||||||
array.set(index,Pair(it.first,msg));
|
|
||||||
this.dispatchMessage(key,msg,"upd");
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMessages(chan : String) : MutableList<Pair<String,Message>>{
|
|
||||||
val channel = this.messages[chan]?.toList();
|
|
||||||
val returned = mutableListOf<Pair<String,Message>>()
|
|
||||||
if(channel != null){
|
|
||||||
for (m in channel){
|
|
||||||
returned.add(Pair(m.second.id,m.second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return returned;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,266 +1,11 @@
|
||||||
package Channels
|
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
|
import seekdasky.kWebSocket.Server
|
||||||
|
|
||||||
class Event : AsynchronousListener {
|
class Event : AbstractChannel {
|
||||||
|
|
||||||
var clients : MutableList<Client>;
|
override val chanName = "event";
|
||||||
val messages : MutableMap<String, Stack<Pair<String, Message>>>;
|
|
||||||
val serv : Server;
|
|
||||||
|
|
||||||
constructor(serv : Server){
|
constructor(server: Server) : super(server);
|
||||||
this.clients = mutableListOf();
|
|
||||||
this.messages = mutableMapOf();
|
|
||||||
this.serv = serv;
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun filter(c: Client): Boolean {
|
|
||||||
val regex = "\\/event\\/(.*)".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 = "\\/event\\/(.*)".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 : Message, operation : String){
|
|
||||||
|
|
||||||
val channelStack = this.messages[channel];
|
|
||||||
|
|
||||||
if(channelStack != null){
|
|
||||||
|
|
||||||
synchronized(channelStack, {
|
|
||||||
channelStack.push(Pair(msg.user,msg));
|
|
||||||
})
|
|
||||||
|
|
||||||
this.dispatchMessage(channel,msg,operation);
|
|
||||||
}else if (channel == ""){
|
|
||||||
//broadcast
|
|
||||||
for(c in this.messages.values){
|
|
||||||
synchronized(c,{
|
|
||||||
c.push(Pair(msg.user,msg));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dispatchMessage(channel,msg,operation);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun processEvent(e: Event) {
|
|
||||||
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 = JSONObject();
|
|
||||||
|
|
||||||
val chanMessages = this.messages[e.client.data["emergencyChannel"]];
|
|
||||||
if(chanMessages != null){
|
|
||||||
synchronized(chanMessages,{
|
|
||||||
chanMessages.toList().forEach {
|
|
||||||
array.put(it.second.id,it.second.toJSON())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//build JSON
|
|
||||||
val jsonMessage = JSONObject();
|
|
||||||
jsonMessage.put("error",false);
|
|
||||||
jsonMessage.put("add",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");
|
|
||||||
message.id = "-1";
|
|
||||||
message.type = json.getInt("type");
|
|
||||||
|
|
||||||
var lat : Float;
|
|
||||||
var lng : Float;
|
|
||||||
|
|
||||||
//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))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var chanName = "";
|
|
||||||
if(e.client.data["emergencyChannel"] != null){
|
|
||||||
chanName = e.client.data["emergencyChannel"].toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(c in this.clients){
|
|
||||||
this.dispatchMessage(chanName,message,"add");
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
System.out.println("unknown JSON: "+json.toString());
|
|
||||||
}
|
|
||||||
}catch (e : Exception){
|
|
||||||
//System.out.println("Something went wrong (probably JSON parsing error");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun dispatchMessage(channel: String, message: Message, operation : String){
|
|
||||||
|
|
||||||
val authorizedOperations = listOf<String>("add","upd","del");
|
|
||||||
|
|
||||||
if(!authorizedOperations.contains(operation)){
|
|
||||||
throw Exception("Unauthorized operation");
|
|
||||||
}
|
|
||||||
|
|
||||||
val array = JSONObject();
|
|
||||||
array.put(message.id,message.toJSON())
|
|
||||||
|
|
||||||
val jsonMessage = JSONObject();
|
|
||||||
jsonMessage.put("error",false);
|
|
||||||
|
|
||||||
//all operations must be present but can be empty
|
|
||||||
for (op in authorizedOperations){
|
|
||||||
if(op == operation){
|
|
||||||
jsonMessage.put(op,array);
|
|
||||||
}else{
|
|
||||||
jsonMessage.put(op, JSONArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(c in this.clients){
|
|
||||||
//dispatch message to logged client in the right channel or in any channel if channel is an empty string (broadcast)
|
|
||||||
if(c.data["IsLogged"] == true && ((channel != "" && c.data["emergencyChannel"] == channel) || channel == "")){
|
|
||||||
c.send(buildTextMessage(jsonMessage.toString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteMessage(id : String){
|
|
||||||
this.messages.keys.forEach {
|
|
||||||
val key = it;
|
|
||||||
val array = this.messages[it];
|
|
||||||
array?.toList()?.forEach{
|
|
||||||
if(it.second.id == id){
|
|
||||||
array.remove(it);
|
|
||||||
val msg = Message()
|
|
||||||
msg.id = id;
|
|
||||||
this.dispatchMessage(key,msg,"del");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateMessage(msg : Message){
|
|
||||||
this.messages.keys.forEach {
|
|
||||||
val key = it;
|
|
||||||
val array = this.messages[it];
|
|
||||||
var index = 0;
|
|
||||||
array?.toList()?.forEach{
|
|
||||||
if(it.second.id == msg.id){
|
|
||||||
msg.user = it.second.user;
|
|
||||||
msg.location = it.second.location;
|
|
||||||
msg.timestamp = it.second.timestamp;
|
|
||||||
array.set(index,Pair(it.first,msg));
|
|
||||||
this.dispatchMessage(key,msg,"upd");
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMessages(chan : String) : MutableList<Pair<String,Message>>{
|
|
||||||
val channel = this.messages[chan]?.toList();
|
|
||||||
val returned = mutableListOf<Pair<String,Message>>()
|
|
||||||
if(channel != null){
|
|
||||||
for (m in channel){
|
|
||||||
returned.add(Pair(m.second.id,m.second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return returned;
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue