From 810d1e6bfcef701b70c2ee4a56a5476483b79470 Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Wed, 18 Dec 2019 11:47:24 +0100
Subject: [PATCH] First messages exchanged, tokens are cleartext for now.
---
src/client.cr | 35 +++++++++++++++++
src/colors.cr | 5 +++
src/common.cr | 34 +++++++++++++++++
src/json_tests.cr | 14 +++++++
src/main.cr | 97 +++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 185 insertions(+)
create mode 100644 src/client.cr
create mode 100644 src/colors.cr
create mode 100644 src/common.cr
create mode 100644 src/json_tests.cr
create mode 100644 src/main.cr
diff --git a/src/client.cr b/src/client.cr
new file mode 100644
index 0000000..631a8f1
--- /dev/null
+++ b/src/client.cr
@@ -0,0 +1,35 @@
+require "ipc"
+require "json"
+
+require "./common.cr"
+
+client = IPC::Client.new("pong")
+
+token = Token.new 1002, "karchnu"
+authentication_message = AuthenticationMessage.new token
+
+client.send(1.to_u8, authentication_message.to_json)
+
+m = client.read
+# puts "message received: #{m.to_s}"
+# puts "message received payload: #{String.new m.payload}"
+
+response = Response.from_json(String.new m.payload)
+
+if response.mid == authentication_message.mid
+ puts "This is a response for the authentication message"
+else
+ puts "Message IDs from authentication message and its response differ"
+end
+
+client.close
+
+#client.loop do |event|
+# case event
+# when IPC::Event::Message
+# puts "\033[32mthere is a message\033[00m"
+# puts event.message.to_s
+# client.close
+# exit
+# end
+#end
diff --git a/src/colors.cr b/src/colors.cr
new file mode 100644
index 0000000..4c4d49c
--- /dev/null
+++ b/src/colors.cr
@@ -0,0 +1,5 @@
+CRED = "\033[31m"
+CBLUE = "\033[36m"
+CGREEN = "\033[32m"
+CRESET = "\033[00m"
+CORANGE = "\033[33m"
diff --git a/src/common.cr b/src/common.cr
new file mode 100644
index 0000000..71f0ebb
--- /dev/null
+++ b/src/common.cr
@@ -0,0 +1,34 @@
+
+require "uuid"
+
+class Token
+ JSON.mapping({
+ uid: Int32,
+ login: String
+ })
+
+ def initialize(@uid, @login)
+ end
+end
+
+class AuthenticationMessage
+ JSON.mapping({
+ mid: String,
+ token: Token
+ })
+
+ def initialize(@token)
+ @mid = UUID.random.to_s
+ end
+end
+
+class Response
+ JSON.mapping({
+ mid: String,
+ response: String,
+ reason: String?
+ })
+
+ def initialize(@mid, @response, @reason = nil)
+ end
+end
diff --git a/src/json_tests.cr b/src/json_tests.cr
new file mode 100644
index 0000000..0056f15
--- /dev/null
+++ b/src/json_tests.cr
@@ -0,0 +1,14 @@
+require "json"
+
+require "./common.cr"
+
+
+token = Token.new 1002, "karchnu"
+authentication_message = AuthenticationMessage.new token
+
+# TODO, TEST, DEBUG, XXX, FIXME
+pp! authentication_message.to_json
+
+am_from_json = AuthenticationMessage.from_json authentication_message.to_json
+
+pp! am_from_json
diff --git a/src/main.cr b/src/main.cr
new file mode 100644
index 0000000..9d10362
--- /dev/null
+++ b/src/main.cr
@@ -0,0 +1,97 @@
+require "option_parser"
+require "ipc"
+require "json"
+
+require "./colors"
+
+require "./common.cr"
+
+storage_directory = "./storage"
+service_name = "filestorage"
+
+
+OptionParser.parse do |parser|
+ parser.on "-d storage-directory",
+ "--storage-directory storage-directory",
+ "The directory where to put uploaded files." do |opt|
+ storage_directory = opt
+ end
+
+ parser.on "-s service-name", "--service-name service-name", "Service name." do |name|
+ service_name = name
+ end
+
+ parser.on "-h", "--help", "Show this help" do
+ puts parser
+ exit 0
+ end
+end
+
+
+# keep track of connected users
+class User
+ property token : Token
+ def initialize(@token)
+ end
+end
+
+# list of connected users
+# fd => User
+connected_users = Hash(Int32, User).new
+
+service = IPC::SwitchingService.new service_name
+
+service.loop do |event|
+ case event
+ when IPC::Event::Timer
+ puts "#{CORANGE}IPC::Event::Timer#{CRESET}"
+
+ # puts "Disconnected client is: #{client_name}"
+
+ when IPC::Event::Connection
+ puts "#{CBLUE}IPC::Event::Connection: #{event.connection.fd}#{CRESET}"
+
+ when IPC::Event::Disconnection
+ puts "#{CBLUE}IPC::Event::Disconnection: #{event.connection.fd}#{CRESET}"
+
+ connected_users.select! do |fd, user|
+ fd != event.connection.fd
+ end
+
+ when IPC::Event::ExtraSocket
+ puts "#{CRED}IPC::Event::ExtraSocket: should not happen in this service#{CRESET}"
+
+ when IPC::Event::Switch
+ puts "#{CRED}IPC::Event::Switch: should not happen in this service#{CRESET}"
+
+ # IPC::Event::Message has to be the last entry
+ # because ExtraSocket and Switch inherit from Message class
+ when IPC::Event::Message
+ puts "#{CBLUE}IPC::Event::Message#{CRESET}: #{event.connection.fd}"
+
+ # 1. test if the client is already authenticated
+ if user = connected_users[event.connection.fd]?
+ puts "User is connected: #{user.token.login}"
+ else
+ puts "User is not currently connected"
+
+ authentication_message = AuthenticationMessage.from_json(String.new event.message.payload)
+
+ new_user = User.new authentication_message.token
+ connected_users[event.connection.fd] = new_user
+ puts "New user is: #{new_user.token.login}"
+
+ response = Response.new authentication_message.mid, "Ok"
+ event.connection.send 2.to_u8, response.to_json
+ end
+
+
+ # puts "New connected client is: #{client_name}"
+
+ # The first message is the connection.
+ # Users sent their token (JWT) to authenticate.
+ # From the token, we get the user id, its login and a few other parameters (see the authd documentation).
+ else
+ raise "Event type not supported."
+ end
+end