netz 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ tags
2
+ pkg
3
+ *.swp
@@ -0,0 +1,8 @@
1
+ = Netz
2
+ http://github.com/shawn42/netz/tree/master
3
+
4
+ == INSTALL
5
+ gem install netz
6
+
7
+ == TODO
8
+ more docs and examples
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'thread'
2
+ require 'socket'
3
+ require 'netz/command'
4
+ require 'netz/broadcaster'
5
+ require 'netz/catcher'
6
+ require 'netz/safe_array'
7
+ require 'netz/client'
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,8 @@
1
+ module Netz
2
+ class Command
3
+ attr_writer :local
4
+ def local?
5
+ @local
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ module Netz
2
+ module CommandSerializer
3
+ def serialize
4
+ self.to_s
5
+ end
6
+
7
+ def self.deserialize(cmd)
8
+ cmd = Command.new
9
+ #cmd.stuff = blah
10
+ cmd
11
+ end
12
+ end
13
+ end
@@ -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
@@ -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
+
@@ -0,0 +1,7 @@
1
+ require 'netz'
2
+
3
+ client = Netz::Client.new
4
+ client.join ARGV.pop
5
+
6
+ puts "client is waiting..."
7
+ gets
@@ -0,0 +1,9 @@
1
+ require 'netz'
2
+
3
+ c = Netz::Client.new
4
+ puts "waiting..."
5
+ gets
6
+ c.start_all
7
+
8
+ puts "DONE.. please continue"
9
+ gets
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
+