MEChat 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Chat.rb +53 -0
- data/NodeDiscovery.rb +68 -0
- data/bin/chatdsva +6 -0
- data/client.rb +94 -0
- data/lib/MEChat_pb.rb +38 -0
- data/lib/MEChat_services_pb.rb +43 -0
- data/logger.rb +33 -0
- data/main.rb +58 -0
- data/ricart_agrawala.rb +14 -0
- data/server.rb +34 -0
- metadata +151 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3e81b866dee38480b59aa955074aae862729bb58570f5f712cddf9f197c5359f
|
4
|
+
data.tar.gz: 408448930057f827d762744384b41bec7eea5046d25ec3311b9f4608b80a67fd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c3f4f4f96a05311799f72b2ba0a81b2482bcd5495c2f5c1aeb3d9c8bc53d236bcb4377c2bf6757f84c387f9c4097cba4e0fce543a7d57fed5b71bc6602757454
|
7
|
+
data.tar.gz: bef9f54ec1492c3eb3a6543bfb7da6e4403b3709a79d56410c47584e987594b60ea993030d31dc68823d5d6d65dc1c1a9ecf7053fbbd2dca6f7a7eb420a32527
|
data/Chat.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'grpc'
|
3
|
+
require 'MEChat_pb'
|
4
|
+
require 'MEChat_services_pb'
|
5
|
+
require_relative './logger.rb'
|
6
|
+
|
7
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
8
|
+
lib_dir = File.join(this_dir, 'lib')
|
9
|
+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
|
10
|
+
|
11
|
+
class Chat < DistributedChat::ChatService::Service
|
12
|
+
|
13
|
+
def initialize ip,port,node_service
|
14
|
+
@node_service = node_service
|
15
|
+
@ip = ip
|
16
|
+
@port = port
|
17
|
+
@logger = MQTTLogger.new topic: "chat", ip: "#{ip.ip_address}:#{port}"
|
18
|
+
end
|
19
|
+
|
20
|
+
private def send_reply(ip:)
|
21
|
+
chat = DistributedChat::ChatService::Stub.new("#{ip.ip_address}:#{ip.ip_port}", :this_channel_is_insecure)
|
22
|
+
chat.release_critical_section(DistributedChat::Request.new(
|
23
|
+
username: "#{ip.ip_address}:#{ip.ip_port}",
|
24
|
+
message: "Reply",
|
25
|
+
timestamp: $alg.clock
|
26
|
+
))
|
27
|
+
@logger.info "Sent reply to #{ip.ip_address}:#{ip.ip_port}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def send_message(msg, _call)
|
31
|
+
$messages << msg
|
32
|
+
puts "#{msg.username}: #{msg.message}"
|
33
|
+
DistributedChat::Response.new status_code: 0
|
34
|
+
end
|
35
|
+
|
36
|
+
def request_critical_section(req,_call)
|
37
|
+
request = {:ip => Addrinfo.getaddrinfo(req.username.split(":")[0..-2].join(":"),req.username.split(":")[-1].to_i)[0], :message => req}
|
38
|
+
if $crit_section === 0
|
39
|
+
send_reply ip: request[:ip]
|
40
|
+
elsif $crit_section < 2 && request[:message].timestamp < $alg.clock
|
41
|
+
send_reply ip: request[:ip]
|
42
|
+
else
|
43
|
+
$alg.requests << request
|
44
|
+
end
|
45
|
+
DistributedChat::Response.new status_code: 0
|
46
|
+
end
|
47
|
+
|
48
|
+
def release_critical_section(req,_call)
|
49
|
+
$alg.replies << Addrinfo.getaddrinfo(req.username.split(":")[0..-2].join(":"),req.username.split(":")[-1].to_i)[0]
|
50
|
+
$alg.clock = [req.timestamp,$alg.clock].max + 1
|
51
|
+
DistributedChat::Response.new status_code: 0
|
52
|
+
end
|
53
|
+
end
|
data/NodeDiscovery.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'grpc'
|
3
|
+
require 'MEChat_pb'
|
4
|
+
require 'MEChat_services_pb'
|
5
|
+
require_relative './logger.rb'
|
6
|
+
require 'socket'
|
7
|
+
|
8
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
9
|
+
lib_dir = File.join(this_dir, 'lib')
|
10
|
+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
|
11
|
+
|
12
|
+
class NodeInfoEnum
|
13
|
+
def initialize(nodes)
|
14
|
+
@nodes = nodes
|
15
|
+
end
|
16
|
+
|
17
|
+
def each
|
18
|
+
if block_given?
|
19
|
+
@nodes.each do |node|
|
20
|
+
yield DistributedChat::NodeInfo.new(address: node.address, port: node.port)
|
21
|
+
end
|
22
|
+
else
|
23
|
+
enum_for(:each)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
class NodeDiscoveryImpl < DistributedChat::NodeDiscovery::Service
|
28
|
+
|
29
|
+
def initialize ip, port
|
30
|
+
@ip = ip
|
31
|
+
@port = port
|
32
|
+
@logger = MQTTLogger.new topic: "nodediscovery", ip: "#{ip.ip_address}:#{port}"
|
33
|
+
end
|
34
|
+
def register_node(node_info, _call)
|
35
|
+
if $nodes.find { |x| x.address === node_info.address && x.port === node_info.port }
|
36
|
+
@logger.warn node_info.address + ":" + node_info.port.to_s + " already registered"
|
37
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::ALREADY_EXISTS, "Node with ip: " + node_info.address + ":" + node_info.port.to_s + " already registered")
|
38
|
+
else
|
39
|
+
$nodes.push node_info
|
40
|
+
puts node_info.address + ":" + node_info.port.to_s + " joined network"
|
41
|
+
@logger.info "Registered node with ip:" + node_info.address + ":" + node_info.port.to_s
|
42
|
+
end
|
43
|
+
nodes_to_return = $nodes.reject { |x| x.address === node_info.address && x.port === node_info.port }
|
44
|
+
to_remove = []
|
45
|
+
nodes_to_return.each do |node|
|
46
|
+
begin
|
47
|
+
nodediscovery = DistributedChat::NodeDiscovery::Stub.new("#{node.address}:#{node.port}", :this_channel_is_insecure)
|
48
|
+
nodediscovery.register_node(DistributedChat::NodeInfo.new(address: node_info.address, port: node_info.port))
|
49
|
+
rescue GRPC::Unavailable => e
|
50
|
+
to_remove << node
|
51
|
+
end
|
52
|
+
end
|
53
|
+
$nodes -= to_remove
|
54
|
+
nodes_to_return -= to_remove
|
55
|
+
nodes_to_return << DistributedChat::NodeInfo.new(address: @ip.ip_address, port: @port)
|
56
|
+
NodeInfoEnum.new(nodes_to_return).each
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_nodes(req,_call)
|
60
|
+
@logger.info "#{_call.peer[5..-1]} with username #{req.username} requested nodes list"
|
61
|
+
NodeInfoEnum.new($nodes).each
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_nodes_local
|
65
|
+
$nodes
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/bin/chatdsva
ADDED
data/client.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'grpc'
|
3
|
+
require 'MEChat_pb'
|
4
|
+
require 'MEChat_services_pb'
|
5
|
+
require_relative './NodeDiscovery.rb'
|
6
|
+
require_relative './logger.rb'
|
7
|
+
|
8
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
9
|
+
lib_dir = File.join(this_dir, 'lib')
|
10
|
+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
|
11
|
+
|
12
|
+
class Client
|
13
|
+
|
14
|
+
def initialize(ip: Addrinfo)
|
15
|
+
@ip = ip
|
16
|
+
@logger = MQTTLogger.new topic: "chat", ip: "#{ip.ip_address}:#{$port.to_s}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def connect(ip:)
|
20
|
+
nodediscovery = DistributedChat::NodeDiscovery::Stub.new("#{ip.ip_address}:#{ip.ip_port}", :this_channel_is_insecure)
|
21
|
+
nodediscovery.register_node(DistributedChat::NodeInfo.new(address: @ip.ip_address, port: $port)).each do |node|
|
22
|
+
$nodes.push node
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
private def request_critical_section
|
28
|
+
$alg.mutex.synchronize do
|
29
|
+
$alg.clock += 1
|
30
|
+
to_remove = []
|
31
|
+
$nodes.each do |node|
|
32
|
+
begin
|
33
|
+
chat = DistributedChat::ChatService::Stub.new("#{node.address}:#{node.port}", :this_channel_is_insecure)
|
34
|
+
@logger.info "Sent request to #{node.address}:#{node.port}"
|
35
|
+
chat.request_critical_section(DistributedChat::Request.new(
|
36
|
+
username: "#{@ip.ip_address}:#{$port.to_s}",
|
37
|
+
message: "Request",
|
38
|
+
timestamp: $alg.clock
|
39
|
+
))
|
40
|
+
rescue GRPC::Unavailable
|
41
|
+
to_remove << node
|
42
|
+
end
|
43
|
+
end
|
44
|
+
$nodes -= to_remove
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private def send_reply(ip:)
|
49
|
+
chat = DistributedChat::ChatService::Stub.new("#{ip.ip_address}:#{ip.ip_port}", :this_channel_is_insecure)
|
50
|
+
chat.release_critical_section(DistributedChat::Request.new(
|
51
|
+
username: "#{ip.ip_address}:#{ip.ip_port}",
|
52
|
+
message: "Reply",
|
53
|
+
timestamp: $alg.clock
|
54
|
+
))
|
55
|
+
@logger.info "Sent reply to #{ip.ip_address}:#{ip.ip_port}"
|
56
|
+
end
|
57
|
+
|
58
|
+
private def release_critical_section
|
59
|
+
$alg.mutex.synchronize do
|
60
|
+
$alg.requests.each do |request|
|
61
|
+
send_reply(ip: request[:ip])
|
62
|
+
end
|
63
|
+
$alg.requests.clear
|
64
|
+
$alg.replies.clear
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def run
|
69
|
+
new_msg = gets.chomp
|
70
|
+
while new_msg != "exit"
|
71
|
+
$crit_section = 1
|
72
|
+
request_critical_section
|
73
|
+
sleepdur = 0
|
74
|
+
while $alg.replies.length < $nodes.length
|
75
|
+
sleepdur += 0.1
|
76
|
+
@logger.info "#{@ip.ip_address}:#{$port.to_s} waiting for replies"
|
77
|
+
sleep 0.1
|
78
|
+
if sleepdur % 5 == 0
|
79
|
+
puts "Waiting for replies. #{$alg.replies.length}/#{$nodes.length} replies received"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
$crit_section = 2
|
83
|
+
$nodes.each do |node|
|
84
|
+
chat = DistributedChat::ChatService::Stub.new("#{node.address}:#{node.port}", :this_channel_is_insecure)
|
85
|
+
chat.send_message(DistributedChat::Request.new(username: "#{@ip.ip_address}:#{$port.to_s}", message: new_msg, timestamp: $alg.clock))
|
86
|
+
@logger.info "Sent message \"#{new_msg}\" to #{node.address}:#{node.port}"
|
87
|
+
end
|
88
|
+
$messages.push DistributedChat::Request.new(username: "#{@ip.ip_address}:#{$port.to_s}", message: new_msg, timestamp: $alg.clock)
|
89
|
+
release_critical_section
|
90
|
+
$crit_section = 0
|
91
|
+
new_msg = gets.chomp
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/MEChat_pb.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
3
|
+
# source: MEChat.proto
|
4
|
+
|
5
|
+
require 'google/protobuf'
|
6
|
+
|
7
|
+
|
8
|
+
descriptor_data = "\n\x0cMEChat.proto\x12\x10\x64istributed_chat\"?\n\x07Request\x12\x10\n\x08username\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x05\"\x1f\n\x08Response\x12\x13\n\x0bstatus_code\x18\x01 \x01(\x05\"O\n\x08NodeInfo\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0c\n\x04port\x18\x02 \x01(\x05\x12\x16\n\ttimestamp\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0c\n\n_timestamp2\xf5\x01\n\x0b\x43hatService\x12\x44\n\x0bSendMessage\x12\x19.distributed_chat.Request\x1a\x1a.distributed_chat.Response\x12O\n\x16RequestCriticalSection\x12\x19.distributed_chat.Request\x1a\x1a.distributed_chat.Response\x12O\n\x16ReleaseCriticalSection\x12\x19.distributed_chat.Request\x1a\x1a.distributed_chat.Response2\x9e\x01\n\rNodeDiscovery\x12H\n\x0cRegisterNode\x12\x1a.distributed_chat.NodeInfo\x1a\x1a.distributed_chat.NodeInfo0\x01\x12\x43\n\x08GetNodes\x12\x19.distributed_chat.Request\x1a\x1a.distributed_chat.NodeInfo0\x01\x42\t\xaa\x02\x06MEChatb\x06proto3"
|
9
|
+
|
10
|
+
pool = Google::Protobuf::DescriptorPool.generated_pool
|
11
|
+
|
12
|
+
begin
|
13
|
+
pool.add_serialized_file(descriptor_data)
|
14
|
+
rescue TypeError
|
15
|
+
# Compatibility code: will be removed in the next major version.
|
16
|
+
require 'google/protobuf/descriptor_pb'
|
17
|
+
parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
|
18
|
+
parsed.clear_dependency
|
19
|
+
serialized = parsed.class.encode(parsed)
|
20
|
+
file = pool.add_serialized_file(serialized)
|
21
|
+
warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
|
22
|
+
imports = [
|
23
|
+
]
|
24
|
+
imports.each do |type_name, expected_filename|
|
25
|
+
import_file = pool.lookup(type_name).file_descriptor
|
26
|
+
if import_file.name != expected_filename
|
27
|
+
warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
warn "Each proto file must use a consistent fully-qualified name."
|
31
|
+
warn "This will become an error in the next major version."
|
32
|
+
end
|
33
|
+
|
34
|
+
module DistributedChat
|
35
|
+
Request = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("distributed_chat.Request").msgclass
|
36
|
+
Response = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("distributed_chat.Response").msgclass
|
37
|
+
NodeInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("distributed_chat.NodeInfo").msgclass
|
38
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# Source: MEChat.proto for package 'distributed_chat'
|
3
|
+
|
4
|
+
require 'grpc'
|
5
|
+
require 'MEChat_pb'
|
6
|
+
|
7
|
+
module DistributedChat
|
8
|
+
module ChatService
|
9
|
+
class Service
|
10
|
+
|
11
|
+
include ::GRPC::GenericService
|
12
|
+
|
13
|
+
self.marshal_class_method = :encode
|
14
|
+
self.unmarshal_class_method = :decode
|
15
|
+
self.service_name = 'distributed_chat.ChatService'
|
16
|
+
|
17
|
+
# Method to send a message to the chat
|
18
|
+
rpc :SendMessage, ::DistributedChat::Request, ::DistributedChat::Response
|
19
|
+
# Method to request access to the critical section
|
20
|
+
rpc :RequestCriticalSection, ::DistributedChat::Request, ::DistributedChat::Response
|
21
|
+
# Method to release access to the critical section
|
22
|
+
rpc :ReleaseCriticalSection, ::DistributedChat::Request, ::DistributedChat::Response
|
23
|
+
end
|
24
|
+
|
25
|
+
Stub = Service.rpc_stub_class
|
26
|
+
end
|
27
|
+
# Define RPC methods for the distributed chat service
|
28
|
+
module NodeDiscovery
|
29
|
+
class Service
|
30
|
+
|
31
|
+
include ::GRPC::GenericService
|
32
|
+
|
33
|
+
self.marshal_class_method = :encode
|
34
|
+
self.unmarshal_class_method = :decode
|
35
|
+
self.service_name = 'distributed_chat.NodeDiscovery'
|
36
|
+
|
37
|
+
rpc :RegisterNode, ::DistributedChat::NodeInfo, stream(::DistributedChat::NodeInfo)
|
38
|
+
rpc :GetNodes, ::DistributedChat::Request, stream(::DistributedChat::NodeInfo)
|
39
|
+
end
|
40
|
+
|
41
|
+
Stub = Service.rpc_stub_class
|
42
|
+
end
|
43
|
+
end
|
data/logger.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mqtt'
|
4
|
+
|
5
|
+
class MQTTLogger
|
6
|
+
def initialize (topic: String, ip: String)
|
7
|
+
@client = MQTT::Client.new
|
8
|
+
@client.host = 'fireup.studio'
|
9
|
+
@client.connect
|
10
|
+
@topic = topic
|
11
|
+
@ip = ip
|
12
|
+
end
|
13
|
+
|
14
|
+
private def log level, msg
|
15
|
+
@client.publish(@topic, "#{@ip}|#{level}|#{msg}", retain=false)
|
16
|
+
end
|
17
|
+
|
18
|
+
def info msg
|
19
|
+
log "INFO",msg
|
20
|
+
end
|
21
|
+
|
22
|
+
def warn msg
|
23
|
+
log "WARN",msg
|
24
|
+
end
|
25
|
+
|
26
|
+
def error msg
|
27
|
+
log "ERROR",msg
|
28
|
+
end
|
29
|
+
|
30
|
+
def finalize
|
31
|
+
@client.disconnect
|
32
|
+
end
|
33
|
+
end
|
data/main.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'grpc'
|
3
|
+
require 'MEChat_pb'
|
4
|
+
require 'MEChat_services_pb'
|
5
|
+
require_relative './NodeDiscovery.rb'
|
6
|
+
require_relative './server.rb'
|
7
|
+
require_relative './client.rb'
|
8
|
+
require_relative './ricart_agrawala.rb'
|
9
|
+
|
10
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
11
|
+
lib_dir = File.join(this_dir, 'lib')
|
12
|
+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
|
13
|
+
$port = RandomPort::Pool::SINGLETON.acquire
|
14
|
+
$nodes = []
|
15
|
+
$messages = []
|
16
|
+
$crit_section = 0
|
17
|
+
$alg = RicartAgrawala.new
|
18
|
+
|
19
|
+
class Main
|
20
|
+
|
21
|
+
def pick_ip
|
22
|
+
addrs = Socket.ip_address_list.reject( &:ipv4_loopback? )
|
23
|
+
.reject( &:ipv6_loopback? )
|
24
|
+
puts "Please select by which IP to present to other nodes"
|
25
|
+
addrs.each_with_index do |x,i|
|
26
|
+
puts "[#{i}] #{x.ip_address}"
|
27
|
+
end
|
28
|
+
puts "[#{addrs.length}] Manual IP"
|
29
|
+
picked = gets.to_i 10
|
30
|
+
return addrs[picked] unless picked.to_i >= addrs.length
|
31
|
+
Addrinfo.getaddrinfo(gets.chomp,80)[0]
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_other_ip
|
35
|
+
puts "[J]oin network or [C]reate new network?"
|
36
|
+
choice = gets.chomp
|
37
|
+
return Addrinfo.getaddrinfo("224.0.0.1",80)[0] if choice.downcase[0] == "c"
|
38
|
+
puts "Please enter IP of a node in the network you wish to join"
|
39
|
+
ip = gets.chomp
|
40
|
+
puts "Please enter port of a node in the network you wish to join"
|
41
|
+
port = gets.to_i 10
|
42
|
+
Addrinfo.getaddrinfo(ip,port)[0]
|
43
|
+
end
|
44
|
+
|
45
|
+
def main
|
46
|
+
ip = pick_ip
|
47
|
+
connect_ip = get_other_ip
|
48
|
+
server = Thread.new { Server.new(ip: ip).run }
|
49
|
+
if connect_ip.ipv4_multicast?
|
50
|
+
client = Thread.new { Client.new(ip: ip).run }
|
51
|
+
else
|
52
|
+
client = Thread.new { Client.new(ip: ip).connect(ip: connect_ip); Client.new(ip: ip).run }
|
53
|
+
end
|
54
|
+
server.join
|
55
|
+
client.join
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/ricart_agrawala.rb
ADDED
data/server.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'grpc'
|
3
|
+
require 'random-port'
|
4
|
+
require 'MEChat_pb'
|
5
|
+
require 'MEChat_services_pb'
|
6
|
+
require_relative './NodeDiscovery.rb'
|
7
|
+
require_relative './Chat.rb'
|
8
|
+
|
9
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
10
|
+
lib_dir = File.join(this_dir, 'lib')
|
11
|
+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
|
12
|
+
|
13
|
+
class Server
|
14
|
+
def initialize(ip: Addrinfo)
|
15
|
+
@ip = ip
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
|
20
|
+
node_discovery = NodeDiscoveryImpl.new @ip, $port
|
21
|
+
chat = Chat.new @ip,$port,node_discovery
|
22
|
+
|
23
|
+
server = GRPC::RpcServer.new
|
24
|
+
server.add_http2_port("0.0.0.0:#{$port.to_s}", :this_port_is_insecure)
|
25
|
+
server.handle(node_discovery)
|
26
|
+
server.handle(chat)
|
27
|
+
puts "Server side running on " + $port.to_s
|
28
|
+
|
29
|
+
server.run_till_terminated_or_interrupted(['int', 'SIGTERM'])
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Server.new.run
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: MEChat
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lukas Kaufmann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-01-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: grpc
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: multi_json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.13.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.13.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mqtt
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.6.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.6.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: random-port
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.6.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.6.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rbs
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.3.2
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.3.2
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.4'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.4'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: grpc-tools
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.50'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.50'
|
111
|
+
description: SHM Chat app using gRPC and Ricart-Agrawala algorithm
|
112
|
+
email: kaufmlu1@fel.cvut.cz
|
113
|
+
executables:
|
114
|
+
- chatdsva
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- Chat.rb
|
119
|
+
- NodeDiscovery.rb
|
120
|
+
- bin/chatdsva
|
121
|
+
- client.rb
|
122
|
+
- lib/MEChat_pb.rb
|
123
|
+
- lib/MEChat_services_pb.rb
|
124
|
+
- logger.rb
|
125
|
+
- main.rb
|
126
|
+
- ricart_agrawala.rb
|
127
|
+
- server.rb
|
128
|
+
homepage:
|
129
|
+
licenses:
|
130
|
+
- MIT
|
131
|
+
metadata: {}
|
132
|
+
post_install_message:
|
133
|
+
rdoc_options: []
|
134
|
+
require_paths:
|
135
|
+
- lib
|
136
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
requirements: []
|
147
|
+
rubygems_version: 3.4.10
|
148
|
+
signing_key:
|
149
|
+
specification_version: 4
|
150
|
+
summary: gRPC Ruby shared memory chat app
|
151
|
+
test_files: []
|