netz 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.
- data/.gitignore +3 -0
- data/README.rdoc +8 -0
- data/Rakefile +22 -0
- data/VERSION +1 -0
- data/lib/netz.rb +7 -0
- data/lib/netz/broadcaster.rb +31 -0
- data/lib/netz/catcher.rb +26 -0
- data/lib/netz/client.rb +137 -0
- data/lib/netz/command.rb +8 -0
- data/lib/netz/command_serializer.rb +13 -0
- data/lib/netz/safe_array.rb +43 -0
- data/netz.gemspec +63 -0
- data/script/run_client.rb +7 -0
- data/script/run_lobby.rb +9 -0
- metadata +135 -0
data/.gitignore
ADDED
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gem|
|
4
|
+
gem.name = "netz"
|
5
|
+
gem.rubyforge_project = "netz"
|
6
|
+
gem.summary = %Q{Networking library for use in games.}
|
7
|
+
gem.description = %Q{P2P Networking library for us in games. }
|
8
|
+
gem.email = "shawn42@gmail.com"
|
9
|
+
gem.homepage = "http://shawn42.github.com/netz"
|
10
|
+
gem.authors = ["Shawn Anderson"]
|
11
|
+
gem.add_development_dependency "rspec"
|
12
|
+
gem.add_development_dependency "jeweler"
|
13
|
+
gem.add_dependency 'gosu'
|
14
|
+
gem.add_dependency 'bundler'
|
15
|
+
gem.test_files = FileList['{spec,test}/**/*.rb']
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
# vim: syntax=Ruby
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/netz.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Netz
|
2
|
+
class Broadcaster
|
3
|
+
attr_accessor :remote_clients, :command_channel
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@remote_clients = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def run
|
10
|
+
Thread.new do
|
11
|
+
loop do
|
12
|
+
command = @command_channel.pop
|
13
|
+
push_to_peers command if command.local?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def push_to_peers(command)
|
19
|
+
# TODO add command buffering?
|
20
|
+
command.extend(CommandSerializer)
|
21
|
+
|
22
|
+
# write to clients
|
23
|
+
msg = command.serialize
|
24
|
+
puts msg
|
25
|
+
@remote_clients.each do |rc|
|
26
|
+
rc.write [msg.length].pack("S")
|
27
|
+
rc.write msg
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/netz/catcher.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Netz
|
2
|
+
class Catcher
|
3
|
+
attr_accessor :remote_clients, :command_channel
|
4
|
+
|
5
|
+
def initialize()
|
6
|
+
@remote_clients = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def run
|
10
|
+
#thread per client?
|
11
|
+
@remote_clients.each do |rc|
|
12
|
+
Thread.new do
|
13
|
+
loop do
|
14
|
+
read_command(rc)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def read_command(remote_client)
|
21
|
+
length = remote_client.recvfrom(2)[0].unpack("S")[0]
|
22
|
+
cmd = CommandSerializer.deserialize(remote_client.recvfrom(length))
|
23
|
+
@command_channel << cmd
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/netz/client.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
|
2
|
+
module Netz
|
3
|
+
module ManagementCommands
|
4
|
+
PEER_CONNECT = 1
|
5
|
+
START = 2
|
6
|
+
end
|
7
|
+
|
8
|
+
class Client
|
9
|
+
include ManagementCommands
|
10
|
+
MANAGEMENT_PORT = 7370
|
11
|
+
INITIAL_PEER_PORT = 7374
|
12
|
+
def initialize
|
13
|
+
@port = INITIAL_PEER_PORT
|
14
|
+
@peers = SafeArray.new
|
15
|
+
Thread.new do
|
16
|
+
setup_management_port
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def start_all
|
21
|
+
setup_with_siblings
|
22
|
+
|
23
|
+
@peers.each do |peer_socket|
|
24
|
+
to_send_address = peer_socket.peeraddr[3].split(":").last
|
25
|
+
puts "STARTING... #{to_send_address}"
|
26
|
+
peer_mng_socket = TCPSocket.new to_send_address, MANAGEMENT_PORT
|
27
|
+
|
28
|
+
peer_mng_socket << [START].pack("C")
|
29
|
+
peer_mng_socket.close
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_peer(peer_socket)
|
34
|
+
@port += 1
|
35
|
+
Thread.new do
|
36
|
+
peer_server = TCPServer.open @port
|
37
|
+
puts "waiting for peer on per-peer port #{@port}"
|
38
|
+
peer = peer_server.accept
|
39
|
+
puts "accepted peer."
|
40
|
+
@peers.push(peer)
|
41
|
+
end
|
42
|
+
#push port, then ip strings
|
43
|
+
peer_socket << [@port].pack("I")
|
44
|
+
peer_socket << [@peers.size].pack("I")
|
45
|
+
@peers.each do |peer_socket|
|
46
|
+
# TODO will this always be peeraddr? or sometime addr depending on Server vs Socket?
|
47
|
+
to_send_address = peer_socket.peeraddr[3].split(":").last
|
48
|
+
peer_socket << [to_send_address.length].pack("I")
|
49
|
+
peer_socket << to_send_address
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def setup_with_siblings
|
54
|
+
puts "setting up siblings"
|
55
|
+
@channel = Queue.new
|
56
|
+
broadcaster = Broadcaster.new
|
57
|
+
broadcaster.command_channel = @channel
|
58
|
+
broadcaster.remote_clients = @peers
|
59
|
+
|
60
|
+
catcher = Catcher.new
|
61
|
+
catcher.command_channel = @channel
|
62
|
+
catcher.remote_clients = @peers
|
63
|
+
|
64
|
+
catcher.run
|
65
|
+
broadcaster.run
|
66
|
+
|
67
|
+
@channel.push Command.new
|
68
|
+
end
|
69
|
+
|
70
|
+
def setup_management_port
|
71
|
+
puts "creating management port on #{MANAGEMENT_PORT}"
|
72
|
+
begin
|
73
|
+
server = TCPServer.open MANAGEMENT_PORT
|
74
|
+
@management_accept_thread = Thread.new do
|
75
|
+
begin
|
76
|
+
loop do
|
77
|
+
puts "management thread trying to accept..."
|
78
|
+
peer = server.accept
|
79
|
+
puts "YAY! peer connected!"
|
80
|
+
|
81
|
+
cmd = peer.recvfrom(1)[0].unpack("C")[0].to_i
|
82
|
+
case cmd
|
83
|
+
when PEER_CONNECT
|
84
|
+
puts "connection from peer #{peer.inspect}"
|
85
|
+
add_peer peer
|
86
|
+
when START
|
87
|
+
puts "got start"
|
88
|
+
setup_with_siblings
|
89
|
+
else
|
90
|
+
puts "unknown cmd"
|
91
|
+
p cmd
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
rescue Exception => ex
|
98
|
+
puts "client failed to open management port: #{ex}"
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def connect_to_peer(ip, port)
|
104
|
+
puts "connecting to peer #{ip}:#{port}"
|
105
|
+
@peers << TCPSocket.new(ip, port)
|
106
|
+
end
|
107
|
+
|
108
|
+
def join(ip)
|
109
|
+
puts "trying to join #{ip}"
|
110
|
+
@joined_peer_ips ||= []
|
111
|
+
@joined_peer_ips << ip
|
112
|
+
peer_accept = TCPSocket.new ip, MANAGEMENT_PORT
|
113
|
+
peer_accept << [PEER_CONNECT].pack("C")
|
114
|
+
|
115
|
+
peer_ips = []
|
116
|
+
join_port = peer_accept.recvfrom(4)[0].unpack("I")[0]
|
117
|
+
puts "got join_port #{join_port}"
|
118
|
+
num_additional_peers = peer_accept.recvfrom(4)[0].unpack("I")[0]
|
119
|
+
puts "got num_additional_peers #{num_additional_peers}"
|
120
|
+
num_additional_peers.times do
|
121
|
+
puts "getting peer ip from stream"
|
122
|
+
ip_length = peer_accept.recvfrom(4)[0].unpack("I")
|
123
|
+
peer_ip = peer_accept.recvfrom(ip_length)[0].unpack("a")
|
124
|
+
peer_ips << peer_ip unless @joined_peer_ips.include? peer_ip
|
125
|
+
end
|
126
|
+
|
127
|
+
connect_to_peer ip, join_port
|
128
|
+
|
129
|
+
peer_accept.close
|
130
|
+
|
131
|
+
peer_ips.each do |pip|
|
132
|
+
join pip
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/lib/netz/command.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'thread'
|
2
|
+
module Netz
|
3
|
+
# a thread safe array class
|
4
|
+
class SafeArray
|
5
|
+
def initialize(items=[])
|
6
|
+
@items = items
|
7
|
+
@mutex = Mutex.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def push(item)
|
11
|
+
@mutex.synchronize {
|
12
|
+
@items.push item
|
13
|
+
}
|
14
|
+
self
|
15
|
+
end
|
16
|
+
alias :<< :push
|
17
|
+
|
18
|
+
def delete(item)
|
19
|
+
@mutex.synchronize {
|
20
|
+
@items.delete item
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def each(&block)
|
25
|
+
@mutex.synchronize {
|
26
|
+
@items.each(&block)
|
27
|
+
}
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def empty?
|
32
|
+
@mutex.synchronize {
|
33
|
+
@items.empty?
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def size
|
38
|
+
@mutex.synchronize {
|
39
|
+
@items.size
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/netz.gemspec
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{netz}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Shawn Anderson"]
|
12
|
+
s.date = %q{2010-10-27}
|
13
|
+
s.description = %q{P2P Networking library for us in games. }
|
14
|
+
s.email = %q{shawn42@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"README.rdoc",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"lib/netz.rb",
|
24
|
+
"lib/netz/broadcaster.rb",
|
25
|
+
"lib/netz/catcher.rb",
|
26
|
+
"lib/netz/client.rb",
|
27
|
+
"lib/netz/command.rb",
|
28
|
+
"lib/netz/command_serializer.rb",
|
29
|
+
"lib/netz/safe_array.rb",
|
30
|
+
"netz.gemspec",
|
31
|
+
"script/run_client.rb",
|
32
|
+
"script/run_lobby.rb"
|
33
|
+
]
|
34
|
+
s.homepage = %q{http://shawn42.github.com/netz}
|
35
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
s.rubyforge_project = %q{netz}
|
38
|
+
s.rubygems_version = %q{1.3.7}
|
39
|
+
s.summary = %q{Networking library for use in games.}
|
40
|
+
|
41
|
+
if s.respond_to? :specification_version then
|
42
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
43
|
+
s.specification_version = 3
|
44
|
+
|
45
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
46
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
47
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
48
|
+
s.add_runtime_dependency(%q<gosu>, [">= 0"])
|
49
|
+
s.add_runtime_dependency(%q<bundler>, [">= 0"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
52
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
53
|
+
s.add_dependency(%q<gosu>, [">= 0"])
|
54
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
55
|
+
end
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
58
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
59
|
+
s.add_dependency(%q<gosu>, [">= 0"])
|
60
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
data/script/run_lobby.rb
ADDED
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: netz
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Shawn Anderson
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-27 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: jeweler
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: gosu
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: bundler
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :runtime
|
76
|
+
version_requirements: *id004
|
77
|
+
description: "P2P Networking library for us in games. "
|
78
|
+
email: shawn42@gmail.com
|
79
|
+
executables: []
|
80
|
+
|
81
|
+
extensions: []
|
82
|
+
|
83
|
+
extra_rdoc_files:
|
84
|
+
- README.rdoc
|
85
|
+
files:
|
86
|
+
- .gitignore
|
87
|
+
- README.rdoc
|
88
|
+
- Rakefile
|
89
|
+
- VERSION
|
90
|
+
- lib/netz.rb
|
91
|
+
- lib/netz/broadcaster.rb
|
92
|
+
- lib/netz/catcher.rb
|
93
|
+
- lib/netz/client.rb
|
94
|
+
- lib/netz/command.rb
|
95
|
+
- lib/netz/command_serializer.rb
|
96
|
+
- lib/netz/safe_array.rb
|
97
|
+
- netz.gemspec
|
98
|
+
- script/run_client.rb
|
99
|
+
- script/run_lobby.rb
|
100
|
+
has_rdoc: true
|
101
|
+
homepage: http://shawn42.github.com/netz
|
102
|
+
licenses: []
|
103
|
+
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options:
|
106
|
+
- --charset=UTF-8
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
hash: 3
|
115
|
+
segments:
|
116
|
+
- 0
|
117
|
+
version: "0"
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
hash: 3
|
124
|
+
segments:
|
125
|
+
- 0
|
126
|
+
version: "0"
|
127
|
+
requirements: []
|
128
|
+
|
129
|
+
rubyforge_project: netz
|
130
|
+
rubygems_version: 1.3.7
|
131
|
+
signing_key:
|
132
|
+
specification_version: 3
|
133
|
+
summary: Networking library for use in games.
|
134
|
+
test_files: []
|
135
|
+
|