local_message 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,42 @@
1
+ require 'socket'
2
+
3
+ class LocalMessageClient
4
+
5
+ attr_reader :server, :port, :username, :listen_port
6
+
7
+ def initialize(server_hostname, server_port, user_name)
8
+ @server = server_hostname
9
+ @port = server_port
10
+ @username = user_name
11
+ @listen_port = Random.rand(2000..30_000)
12
+ end
13
+
14
+ def register
15
+ send("@register #{username} #{listen_port}")
16
+ end
17
+
18
+ def send(message)
19
+ socket = TCPSocket.open(server, port)
20
+ sleep 1
21
+ socket.write(message)
22
+ socket.close
23
+ #puts "Waiting for server acknowledgement..."
24
+ #listen
25
+ end
26
+
27
+ def new_listen_port
28
+ @listen_port = Random.rand(1000..30_000)
29
+ end
30
+
31
+ def listen
32
+ #puts "Listening on #{listen_port}..."
33
+ server = TCPServer.open(listen_port)
34
+ client = server.accept
35
+ #puts "Connection open, waiting for message..."
36
+ message = client.read
37
+ client.close
38
+ server.close
39
+ message
40
+ end
41
+
42
+ end
@@ -0,0 +1,130 @@
1
+ require 'socket'
2
+
3
+ class LocalMessageRouter
4
+
5
+ attr_reader :port, :registered_users, :open_ports
6
+
7
+ def initialize(listening_port)
8
+ @port = listening_port
9
+ @registered_users = {}
10
+ @open_ports = []
11
+ end
12
+
13
+ def start
14
+ server = TCPServer.open(port)
15
+ begin
16
+
17
+ puts "Listening on port: #{port}..."
18
+ Thread.start(server.accept) do |client|
19
+ fam, port, hostname, ip = client.peeraddr
20
+ puts "Connection initiated from #{hostname}:#{port}"
21
+ message = client.read
22
+ puts "Message from #{hostname}:#{port}: #{message}"
23
+ puts handle(message, port, ip)
24
+ puts "Closing connection from #{hostname}:#{port}"
25
+ client.close
26
+ end
27
+
28
+ end while true
29
+ end
30
+
31
+ def handle(message, port, ip)
32
+ if register?(message)
33
+ username, port = strip_username_port(message)
34
+ register(username, port.to_i, ip)
35
+ if registered?(username)
36
+ puts "Registered #{username} => #{ip}:#{port}"
37
+ else
38
+ puts "Couldn't register #{username}"
39
+ end
40
+ #send_register_ack(ip, port, username)
41
+ elsif has_recipient?(message)
42
+ recipient = strip_recipient(message)
43
+ sender = username_by_ip(ip)
44
+ forward_message(sender, recipient, message)
45
+ if registered?(recipient)
46
+ #send_ack(ip, port, recipient, message)
47
+ else
48
+ #send_ack(ip, port, recipient, "No such recipient")
49
+ end
50
+ else
51
+ "Message not handled"
52
+ end
53
+ end
54
+
55
+ def register?(message)
56
+ return true if /@register/.match(message)
57
+ false
58
+ end
59
+
60
+ def registered?(username)
61
+ registered_users.has_key?(username)
62
+ end
63
+
64
+ def register(username, port, ip)
65
+ registered_users[username] = LocalMessageUser.new(port, ip)
66
+ end
67
+
68
+ def send_register_ack(hostname, port, username)
69
+ if registered?(username)
70
+ send(hostname, port, "Successfully registered #{username}")
71
+ "Successfully registered #{username}"
72
+ else
73
+ send(hostname, port, "Failed to register #{username}")
74
+ "Failed to register #{username}"
75
+ end
76
+ end
77
+
78
+ def username_by_ip(ip)
79
+ registered_users.values.each do |user|
80
+ return registered_users.key(user) if user.hostname == ip
81
+ end
82
+ end
83
+
84
+ def strip_username_port(message)
85
+ /@register\s+(.+)\s+(\d+)/.match(message)
86
+ [$1, $2]
87
+ end
88
+
89
+ def has_recipient?(message)
90
+ return true if /(@.+)\s+/.match(message)
91
+ false
92
+ end
93
+
94
+ def strip_recipient(message)
95
+ message.split[0].slice(1..-1)
96
+ end
97
+
98
+ def strip_message(message)
99
+ message.split[1..-1].join(" ")
100
+ end
101
+
102
+ def forward_message(sender, recipient, message)
103
+ if registered?(recipient)
104
+ info = registered_users[recipient]
105
+ message_with_sender = "@#{sender} #{strip_message(message)}"
106
+ puts "Sending message to #{recipient}, host: #{info.hostname} port: #{info.port}"
107
+ send(info.hostname, info.port, message_with_sender)
108
+ end
109
+ end
110
+
111
+ def port_open?(port)
112
+ open_ports.include?(port)
113
+ end
114
+
115
+ def send(hostname, port, message)
116
+ Thread.new do
117
+ puts "Sending #{message} to #{hostname}:#{port}"
118
+ socket = TCPSocket.open(hostname, port)
119
+ sleep 1
120
+ socket.write(message)
121
+ socket.close
122
+ end
123
+ end
124
+
125
+ def send_ack(hostname, port, recipient, message)
126
+ send(hostname, port, "Sent #{message} to #{recipient}")
127
+ "Sent #{message} to #{hostname}:#{port}"
128
+ end
129
+
130
+ end
@@ -0,0 +1,22 @@
1
+ class LocalMessageUser
2
+
3
+ attr_reader :port, :hostname
4
+
5
+ def initialize(port_number, host_name)
6
+ @port = port_number
7
+ @hostname = host_name
8
+ end
9
+
10
+ def ==(other)
11
+ hostname == other.hostname
12
+ end
13
+
14
+ def eql?(other)
15
+ self == other
16
+ end
17
+
18
+ def hash
19
+ hostname.hash
20
+ end
21
+
22
+ end
@@ -0,0 +1,3 @@
1
+ require 'local_message/local_message_router'
2
+ require 'local_message/local_message_client'
3
+ require 'local_message/local_message_user'
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: local_message
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Elliot Shiu
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-06 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Routes messages across a local network.
15
+ email: elliot@sandbochs.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/local_message.rb
21
+ - lib/local_message/local_message_router.rb
22
+ - lib/local_message/local_message_client.rb
23
+ - lib/local_message/local_message_user.rb
24
+ homepage: http://www.github.com/sandbochs
25
+ licenses: []
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 1.8.24
45
+ signing_key:
46
+ specification_version: 3
47
+ summary: A message router and client.
48
+ test_files: []