tella_peer 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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 16c65ca7aaf3082cdfe68a61f2b3d5c050525b40
4
+ data.tar.gz: 145be07d6cbde9456ddd57162f31b801e49f3f71
5
+ SHA512:
6
+ metadata.gz: d20d5be39eec0b8eb3f7dc8d9a7e2d109177a08c1ec6bf364f48c8fa4a42036d83112b080c4d9da15a73471beb507c16da550906630bc153d71eb68310267afe
7
+ data.tar.gz: 788468574e3565ad637be6ab43fea5e1d67392401ab4163df3cf7fc35754fc4edfd76b8450a882975dccab408053c1db0fabbee447c605dee543039c1fe2a00a
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ reply.log
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
@@ -0,0 +1 @@
1
+ 2.0.0-p195
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --color
3
+ --debug
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tella_peer.gemspec
4
+ gemspec
5
+
6
+ gem 'uuid'
7
+
8
+ gem 'thor'
9
+
10
+ gem 'debugger'
11
+
12
+ gem 'guard'
13
+ gem 'guard-rspec'
14
+ gem 'terminal-notifier-guard'
15
+
16
+ gem 'rspec'
17
+
18
+ gem 'sinatra'
19
+ gem 'thin'
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Keith Stone
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # TellaPeer
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'tella_peer'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install tella_peer
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tella_peer'
4
+
5
+ require 'json'
6
+ require 'open-uri'
7
+ TellaPeer::Message.ip = open( 'http://jsonip.com/ ' ){ |s| JSON::parse( s.string())['ip'] }.split('.')
8
+
9
+ class Client < Thor
10
+
11
+ desc "start", "Starts the P2P client by connecting to a seed"
12
+ method_option :port, :aliases => "-p", :desc => "Port to run our server on"
13
+ def start(seed = "128.208.2.88:5002")
14
+ debugger
15
+ TellaPeer::Message.port = options[:port]
16
+
17
+ ping_log = {} # Vash.new
18
+ query_log = {}
19
+
20
+ Socket.tcp_server_loop(TellaPeer::Message.ip.join('.'),
21
+ TellaPeer::Message.port) {|sock, client_addrinfo|
22
+ sock.binmode
23
+ #Thread.new {
24
+ begin
25
+ debugger
26
+ message = TellaPeer::Message.unpack(sock, client_addrinfo.ip, client_addrinfo.port)
27
+ ensure
28
+ sock.close
29
+ end
30
+ puts
31
+ #}
32
+ }
33
+
34
+ seed_ip, seed_port = seed.split(':')
35
+
36
+ s = TCPSocket.open(seed_ip, seed_port)
37
+ s.binmode
38
+
39
+ s.write TellaPeer::Ping.new.pack
40
+
41
+ loop do
42
+ message = TellaPeer::Message.unpack(s, seed_ip, seed_port)
43
+ read_message(message)
44
+ end
45
+
46
+ s.close
47
+ end
48
+
49
+ def send_message(message, to: nil)
50
+ message.increment!
51
+ s.write message if message.transmitable?
52
+ end
53
+
54
+ def read_message(message, s)
55
+ if message.kind_of? TellaPeer::Ping
56
+ puts 'Ping'
57
+ if ping_log.keys.include? message.message_id
58
+ # Remove from network
59
+ else
60
+ ping_log[message.message_id] = s
61
+ debugger
62
+ send_message(message.build_reply, to: s)
63
+ # Broadcast
64
+ end
65
+ elsif message.kind_of? TellaPeer::Pong
66
+ puts 'Pong'
67
+ if ping_log.keys.include? message.message_id
68
+ socket = ping_log[message.message_id]
69
+ send_message(message, to: socket)
70
+ else
71
+ # Remove from network
72
+ end
73
+ elsif message.kind_of? TellaPeer::Query
74
+ puts 'Query'
75
+ if query_log.keys.include? message.message_id
76
+ # Remove from network
77
+ else
78
+ query_log[message.message_id] = s
79
+ send_message(message.build_reply, to: s)
80
+ # Broadcast
81
+ end
82
+ elsif message.kind_of? TellaPeer::Reply
83
+ puts 'Reply'
84
+ if query_log.keys.include? message.message_id
85
+ socket = query_log[message.message_id]
86
+ send_message(message, to: socket)
87
+ else
88
+ # Remove from network
89
+ end
90
+ else
91
+ puts 'Unknown message: #{message}'
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tella_peer'
4
+
5
+ class Client < Thor
6
+
7
+ desc "start", "Starts the P2P client by connecting to a seed"
8
+ method_option :port, :aliases => "-p", :desc => "Port to run our server on"
9
+ method_option :ttl, :aliases => "-t", :desc => "Default ttl on new messages"
10
+ method_option :local, :aliases => "-l", :type => :boolean, :desc => "Run the server on localhost"
11
+ method_option :reply, :aliases => "-r", :desc => "String to serve in replys"
12
+ method_option :log_level, :desc => "Log Level"
13
+ method_option :status_page, :type => :boolean, :desc => "Run the status page on 4567"
14
+
15
+ def start(seed = "128.208.2.88:5002")
16
+ process_options(seed)
17
+
18
+ require 'tella_peer/status_page'
19
+
20
+ TellaPeer.start_outbound_sceduler
21
+ TellaPeer.start_connection_builder
22
+
23
+ Socket.tcp_server_loop(TellaPeer::Message.port) {|sock, client_addrinfo|
24
+ c = TellaPeer::Connections.build(
25
+ sock,
26
+ client_addrinfo.ip_address,
27
+ client_addrinfo.ip_port)
28
+ .
29
+ c.watch if c
30
+ }
31
+ end
32
+
33
+ no_commands do
34
+ def process_options(seed)
35
+ TellaPeer::Message.port = options[:port].to_i if options[:port]
36
+ TellaPeer::Message.ttl = options[:ttl].to_i if options[:ttl]
37
+ TellaPeer::Message.ip = open( 'http://jsonip.com/ ' ){ |s| JSON::parse( s.string())['ip'] }.split('.') unless options[:local]
38
+ TellaPeer::Message.text = options[:reply] || options[:port]
39
+
40
+ seed_ip, seed_port = seed.split(':')
41
+ TellaPeer::Connections.seed = [seed_ip, seed_port]
42
+ TellaPeer::Connections.seed_connections
43
+ TellaPeer::Connections.start_time
44
+
45
+ TellaPeer.logger.level = Kernel.const_get("Logger::#{options[:log_level]}") if options[:log_level]
46
+
47
+ TellaPeer.logger.info { "Starting on #{TellaPeer::Message.ip.join('.')}:#{TellaPeer::Message.port}" }
48
+ TellaPeer.logger.info { "Serving: #{TellaPeer::Message.text}" }
49
+ TellaPeer.logger.info { "With ttl: #{TellaPeer::Message.ttl}" }
50
+ TellaPeer.logger.info { "Using seed: #{seed}" }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,67 @@
1
+ require 'socket'
2
+ require 'ruby-debug'
3
+ require "tella_peer/version"
4
+ require 'tella_peer/message_types'
5
+ require 'tella_peer/message'
6
+ require 'tella_peer/ping'
7
+ require 'tella_peer/pong'
8
+ require 'tella_peer/query'
9
+ require 'tella_peer/reply'
10
+ require 'tella_peer/connections'
11
+ require 'tella_peer/connection'
12
+
13
+ require 'json'
14
+ require 'open-uri'
15
+
16
+ require 'logger'
17
+
18
+ module TellaPeer
19
+ def self.logger
20
+ if @logger
21
+ @logger
22
+ else
23
+ @logger = Logger.new(STDOUT)
24
+ @logger
25
+ end
26
+ end
27
+
28
+ def self.start_outbound_sceduler
29
+ Thread.new {
30
+ begin
31
+ count = 0
32
+ loop do
33
+ logger.debug 'Send Ping'
34
+ Connections.ping
35
+ sleep 5
36
+ logger.debug 'Send Query'
37
+ Connections.query
38
+ sleep 5
39
+ Connections.clear_logs if count % 100 == 0
40
+ count += 1
41
+ end
42
+ rescue
43
+ logger.error "Outbound sceduler crashed"
44
+ logger.error $!
45
+ ensure
46
+ logger.warn "Outbound sceduler finished"
47
+ end
48
+ }
49
+ end
50
+
51
+ def self.start_connection_builder
52
+ Thread.new {
53
+ begin
54
+ loop do
55
+ logger.debug 'Building client connections'
56
+ Connections.build_from_connections
57
+ sleep 5
58
+ end
59
+ rescue
60
+ logger.error "Connection builder crashed"
61
+ logger.error $!
62
+ ensure
63
+ logger.warn "Connection builder finished"
64
+ end
65
+ }
66
+ end
67
+ end
@@ -0,0 +1,133 @@
1
+ module TellaPeer
2
+ class Connection < Struct.new(:socket, :remote_ip, :remote_port, :direction)
3
+ attr_accessor :start_time, :text
4
+
5
+ attr_accessor :last_sent, :last_read
6
+
7
+ def initialize(socket, remote_ip, remote_port, direction)
8
+ super(socket, remote_ip, remote_port, direction)
9
+ socket.binmode
10
+ end
11
+
12
+ def watch
13
+ Thread.new do
14
+ self.start_time = Time.now
15
+
16
+ begin
17
+ until socket.closed? do
18
+ message = TellaPeer::Message.unpack(socket, remote_ip, remote_port)
19
+ read_message(message)
20
+ end
21
+ rescue
22
+ logger.debug $!
23
+ ensure
24
+ close_socket
25
+ logger.info "Closed connection to #{key}"
26
+ end
27
+ end
28
+ end
29
+
30
+ def close_socket
31
+ socket.close unless socket.closed?
32
+ Connections.close_connection(key)
33
+ end
34
+
35
+ def key
36
+ "#{remote_ip}:#{remote_port}"
37
+ end
38
+
39
+ def send_message(message, increment: false)
40
+ to ||= socket
41
+ begin
42
+ message.increment! if increment
43
+ if message.transmitable?
44
+ to.write(message.pack)
45
+ Connections.count_message(message.type, :out)
46
+ self.last_sent = message
47
+ end
48
+ rescue
49
+ logger.debug "Write to #{key} failed -- #{$!.message}"
50
+ logger.debug $!.backtrace
51
+ close_socket
52
+ end
53
+ end
54
+
55
+ def read_ping(message)
56
+ if Connections.seen_ping?(message.message_id, from: self)
57
+ no_op(message)
58
+ else
59
+ send_message(message.build_reply)
60
+ Connections.flood(message.increment!, except_to: self)
61
+ end
62
+ end
63
+
64
+ def read_pong(message)
65
+ Connections.add_potential_connection(message.pretty_ip, message.port)
66
+ if connection = Connections.seen_ping?(message.message_id)
67
+ connection.send_message(message)
68
+ else
69
+ no_op(message)
70
+ end
71
+ end
72
+
73
+ def read_query(message)
74
+ if Connections.seen_query?(message.message_id, from: self)
75
+ no_op(message)
76
+ else
77
+ send_message(message.build_reply)
78
+ Connections.flood(message.increment!, except_to: self)
79
+ end
80
+ end
81
+
82
+ def read_reply(message)
83
+ Connections.add_potential_connection(message.pretty_ip, message.port)
84
+ Connections.store_reply(message)
85
+ if connection = Connections.seen_query?(message.message_id)
86
+ connection.send_message(message)
87
+ else
88
+ no_op(message)
89
+ end
90
+ end
91
+
92
+ def read_message(message)
93
+ Connections.count_message(message.type, :in) if message
94
+ logger.debug "Read #{message.class} #{message.message_id}" if message
95
+ if message.kind_of? TellaPeer::Ping
96
+ read_ping message
97
+ elsif message.kind_of? TellaPeer::Pong
98
+ read_pong message
99
+ elsif message.kind_of? TellaPeer::Query
100
+ read_query message
101
+ elsif message.kind_of? TellaPeer::Reply
102
+ read_reply message
103
+ elsif message.nil?
104
+ # Blank message probably a read error
105
+ else
106
+ logger.warn 'Unknown message: #{message}'
107
+ end
108
+ self.last_read = message
109
+ end
110
+
111
+ def logger
112
+ TellaPeer.logger
113
+ end
114
+
115
+ def time_elapsed
116
+ Time.now - start_time
117
+ end
118
+
119
+ def inspect
120
+ {
121
+ remote_ip: remote_ip,
122
+ remote_port: remote_port,
123
+ time_elapsed: time_elapsed,
124
+ text: text,
125
+ direction: direction,
126
+ }.inspect
127
+ end
128
+
129
+ def no_op(message)
130
+ logger.debug "Remove #{message.class} #{message.message_id} from network" if message
131
+ end
132
+ end
133
+ end