gossiperl_client 0.1.0

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,52 @@
1
+ # encoding: ascii-8bit
2
+ require 'socket'
3
+ module Gossiperl
4
+ module Client
5
+ module Transport
6
+ class Udp < Gossiperl::Client::Resolution
7
+
8
+ field :worker, Gossiperl::Client::OverlayWorker
9
+ field :socket, UDPSocket, nil
10
+ field :recv_buf_size, Fixnum, 16777216
11
+
12
+ field :serializer, Gossiperl::Client::Serialization::Serializer
13
+ field :encryption, Gossiperl::Client::Encryption::Aes256
14
+
15
+ def initialize worker
16
+ self.worker = worker
17
+ self.serializer = Gossiperl::Client::Serialization::Serializer.new
18
+ self.encryption = Gossiperl::Client::Encryption::Aes256.new( self.worker.options[:symkey].to_s )
19
+ end
20
+
21
+ def handle &block
22
+ worker = Thread.new ({ :proto => self, :block => block }) do |args|
23
+ begin
24
+ args[:proto].socket = UDPSocket.new
25
+ args[:proto].socket.bind '127.0.0.1', args[:proto].worker.options[:client_port]
26
+ while args[:proto].worker.working
27
+ begin
28
+ data, address = args[:proto].socket.recvfrom args[:proto].recv_buf_size
29
+ decrypted = args[:proto].encryption.decrypt(data)
30
+ deserialized = args[:proto].serializer.deserialize(decrypted)
31
+ args[:block].call deserialized
32
+ rescue Exception => ex
33
+ args[:block].call({ :error => ex })
34
+ end
35
+ end
36
+ self.socket.close unless self.socket.nil?
37
+ args[:proto].worker.logger.debug("Stopping UDP services for client #{args[:proto].worker.options[:client_name]}.")
38
+ rescue Exception => e
39
+ args[:proto].worker.logger.error("Could not bind UDP service for client #{args[:proto].worker.options[:client_name]}.")
40
+ end
41
+ end
42
+ end
43
+
44
+ def send digest
45
+ serialized = self.serializer.serialize digest
46
+ encrypted = self.encryption.encrypt serialized
47
+ self.socket.send encrypted, 0, '127.0.0.1', self.worker.options[:overlay_port]
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: ascii-8bit
2
+ module Gossiperl
3
+ module Client
4
+ module Util
5
+
6
+ class Validation
7
+
8
+ def self.validate_connect options
9
+ raise ArgumentError.new('Options must be a Hash.') unless options.kind_of?(Hash)
10
+ [ :overlay_name, :client_name, :client_secret, :overlay_port, :client_port, :symkey ].each {|opt|
11
+ raise ArgumentError.new("Required option #{opt} missing.") unless options.has_key?(opt)
12
+ }
13
+ [ :overlay_name, :client_name, :client_secret, :symkey ].each {|str_opt|
14
+ raise TypeError.new("Option #{str_opt} must be a String or Symbol.") unless [String, Symbol].include?( options[str_opt].class )
15
+ }
16
+ [ :overlay_port, :client_port ].each {|fixnum_opt|
17
+ raise TypeError.new("Option #{str_opt} must be a Fixnum.") unless [Fixnum].include?( options[fixnum_opt].class )
18
+ }
19
+ if options.has_key?(:thrift_window) and not options[:thrift_window].is_a?(Fixnum)
20
+ raise TypeError.new('Option thrift_window has to be a Fixnum.')
21
+ end
22
+ if options.has_key?(:logger) and not options[:logger].kind_of?(Logger)
23
+ raise TypeError.new('Option logger must be an instance of Logger.')
24
+ end
25
+ end
26
+
27
+ def self.validate_event_types event_types
28
+ event_types.each {|et|
29
+ raise TypeError.new("Event type #{et.inspect} must be a String or Symbol.") unless [String, Symbol].include?( et.class )
30
+ }
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: ascii-8bit
2
+ module Gossiperl
3
+ module Client
4
+ module Version
5
+ VERSION = '0.1.0'
6
+ MAJOR, MINOR, TINY = VERSION.split('.')
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,63 @@
1
+ # encoding: ascii-8bit
2
+ require "#{File.expand_path(File.dirname(__FILE__))}/../lib/gossiperl_client/requirements.rb"
3
+ Shindo.tests('[Gossiperl] connect process') do
4
+
5
+ @supervisor = Gossiperl::Client::Supervisor.new
6
+ @options = {
7
+ :overlay_name => :gossiper_overlay_remote,
8
+ :overlay_port => 6666,
9
+ :client_port => 54321,
10
+ :client_name => :'ruby-client',
11
+ :client_secret => :'ruby-client-secret',
12
+ :symkey => :v3JElaRswYgxOt4b }
13
+ @subscriptions = [ :member_in, :digestForwardableTest ]
14
+
15
+ tests('success') do
16
+
17
+ tests('connect goes to connected').returns(true) do
18
+ Thread.new(@supervisor) do |sup|
19
+ sup.connect( @options ) do |event|
20
+ if event[:event] == :connected
21
+ self.logger.info "Connected to overlay #{event[:options][:overlay_name]}..."
22
+ elsif event[:event] == :disconnected
23
+ self.logger.info "Disconnected from overlay #{event[:options][:overlay_name]}..."
24
+ elsif event[:event] == :subscribed
25
+ self.logger.info "Received subscription confirmation for #{event[:details][:types]}"
26
+ elsif event[:event] == :unsubscribed
27
+ self.logger.info "Received unsubscription confirmation for #{event[:details][:types]}"
28
+ elsif event[:event] == :event
29
+ self.logger.info "Received member related event #{event[:details][:type]} for member #{event[:details][:member]}."
30
+ elsif event[:event] == :forwarded_ack
31
+ self.logger.info "Received confirmation of forwarded message. Message ID: #{event[:details][:reply_id]}"
32
+ elsif event[:event] == :forwarded
33
+ self.logger.info "Received forwarded digest #{event[:digest]} of type #{event[:digest_type]}"
34
+ elsif event[:event] == :failed
35
+ self.logger.info "Received an error from the client. Reason: #{event[:error]}."
36
+ end
37
+ end
38
+ end
39
+ sleep 3
40
+ @supervisor.state( @options[:overlay_name] ) == :connected
41
+ end
42
+
43
+ tests('subscribe').returns(true) do
44
+ result = @supervisor.subscribe( @options[:overlay_name], @subscriptions ) == @subscriptions
45
+ sleep 3
46
+ result
47
+ end
48
+
49
+ tests('unsubscribe').returns(true) do
50
+ result = @supervisor.unsubscribe( @options[:overlay_name], @subscriptions ) == []
51
+ sleep 3
52
+ result
53
+ end
54
+
55
+ tests('disconnect').returns(true) do
56
+ @supervisor.disconnect( @options[:overlay_name] )
57
+ sleep 1.5
58
+ @supervisor.connections == {}
59
+ end
60
+
61
+ end
62
+
63
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: ascii-8bit
2
+ require "#{File.expand_path(File.dirname(__FILE__))}/../lib/gossiperl_client/requirements.rb"
3
+ Shindo.tests('[Thrift] Serialize / deserialize') do
4
+
5
+ @digest = digest = ::Gossiperl::Client::Thrift::Digest.new
6
+ @digest.name = "test-client"
7
+ @digest.port = 54321
8
+ @digest.heartbeat = Time.now.to_i
9
+ @digest.secret = "test-client-secret"
10
+ @digest.id = "test-digest-id"
11
+
12
+ @enc_key = "SomeEncryptionKe"
13
+
14
+ tests('success') do
15
+
16
+ tests('serialize / deserialize').returns(true) do
17
+ envelope = Gossiperl::Client::Serialization::Serializer.new.serialize(@digest)
18
+ read = Gossiperl::Client::Serialization::Serializer.new.deserialize(envelope)
19
+ read.id == @digest.id
20
+ end
21
+
22
+ tests('encrypt / decrypt').returns(true) do
23
+ envelope = Gossiperl::Client::Serialization::Serializer.new.serialize(@digest)
24
+ encrypted = Gossiperl::Client::Encryption::Aes256.new(@enc_key).encrypt(envelope)
25
+ decrypted = Gossiperl::Client::Encryption::Aes256.new(@enc_key).decrypt(encrypted)
26
+ read = Gossiperl::Client::Serialization::Serializer.new.deserialize(decrypted)
27
+ read.id == @digest.id
28
+ end
29
+
30
+ tests('serialize / deserialize arbitrary').returns(true) do
31
+ serializer = Gossiperl::Client::Serialization::Serializer.new
32
+ serialized_data = serializer.serialize_arbitrary :digestForwardableTest, {
33
+ :string_property => { :value => "some string",
34
+ :type => :string,
35
+ :field_id => 1 },
36
+ :some_port => { :value => 1234567890,
37
+ :type => :i32,
38
+ :field_id => 2 },
39
+ }
40
+ true
41
+ end
42
+
43
+ end
44
+
45
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: !binary |-
3
+ Z29zc2lwZXJsX2NsaWVudA==
4
+ version: !ruby/object:Gem::Version
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - !binary |-
9
+ UmFkIEdydWNoYWxza2k=
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-12-15 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: !binary |-
17
+ dGhyaWZ0
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - !binary |-
21
+ Pj0=
22
+ - !ruby/object:Gem::Version
23
+ version: 0.9.2.0
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - !binary |-
29
+ Pj0=
30
+ - !ruby/object:Gem::Version
31
+ version: 0.9.2.0
32
+ - !ruby/object:Gem::Dependency
33
+ name: !binary |-
34
+ c2hpbmRv
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ description: !binary |-
48
+ V29yayB3aXRoIGdvc3NpcGVybCBmcm9tIFJ1Ynku
49
+ email:
50
+ - !binary |-
51
+ cmFkZWtAZ3J1Y2hhbHNraS5jb20=
52
+ executables: []
53
+ extensions: []
54
+ extra_rdoc_files: []
55
+ files:
56
+ - !binary |-
57
+ R2VtZmlsZQ==
58
+ - !binary |-
59
+ UkVBRE1FLm1k
60
+ - !binary |-
61
+ TElDRU5TRQ==
62
+ - !binary |-
63
+ bGliL2dvc3NpcGVybF9jbGllbnQucmI=
64
+ - !binary |-
65
+ bGliL2dvc3NpcGVybF9jbGllbnQvZW5jcnlwdGlvbi9hZXMyNTYucmI=
66
+ - !binary |-
67
+ bGliL2dvc3NpcGVybF9jbGllbnQvc2VyaWFsaXphdGlvbi9zZXJpYWxpemVy
68
+ LnJi
69
+ - !binary |-
70
+ bGliL2dvc3NpcGVybF9jbGllbnQvdGhyaWZ0L2dvc3NpcGVybF9jb25zdGFu
71
+ dHMucmI=
72
+ - !binary |-
73
+ bGliL2dvc3NpcGVybF9jbGllbnQvdGhyaWZ0L2dvc3NpcGVybF90eXBlcy5y
74
+ Yg==
75
+ - !binary |-
76
+ bGliL2dvc3NpcGVybF9jbGllbnQvdHJhbnNwb3J0L3VkcC5yYg==
77
+ - !binary |-
78
+ bGliL2dvc3NpcGVybF9jbGllbnQvdXRpbC92YWxpZGF0aW9uLnJi
79
+ - !binary |-
80
+ bGliL2dvc3NpcGVybF9jbGllbnQvaGVhZGVycy5yYg==
81
+ - !binary |-
82
+ bGliL2dvc3NpcGVybF9jbGllbnQvbWVzc2FnaW5nLnJi
83
+ - !binary |-
84
+ bGliL2dvc3NpcGVybF9jbGllbnQvb3ZlcmxheV93b3JrZXIucmI=
85
+ - !binary |-
86
+ bGliL2dvc3NpcGVybF9jbGllbnQvcmVxdWlyZW1lbnRzLnJi
87
+ - !binary |-
88
+ bGliL2dvc3NpcGVybF9jbGllbnQvcmVzb2x1dGlvbi5yYg==
89
+ - !binary |-
90
+ bGliL2dvc3NpcGVybF9jbGllbnQvc3RhdGUucmI=
91
+ - !binary |-
92
+ bGliL2dvc3NpcGVybF9jbGllbnQvc3VwZXJ2aXNvci5yYg==
93
+ - !binary |-
94
+ bGliL2dvc3NpcGVybF9jbGllbnQvdmVyc2lvbi5yYg==
95
+ - !binary |-
96
+ Z29zc2lwZXJsX2NsaWVudC5nZW1zcGVj
97
+ - !binary |-
98
+ dGVzdHMvcHJvY2Vzc190ZXN0cy5yYg==
99
+ - !binary |-
100
+ dGVzdHMvdGhyaWZ0X3Rlc3RzLnJi
101
+ homepage: !binary |-
102
+ aHR0cHM6Ly9naXRodWIuY29tL3JhZGVrZy9nb3NzaXBlcmwtY2xpZW50LXJ1
103
+ Ynk=
104
+ licenses: []
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - !binary |-
110
+ bGli
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.1.5
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: !binary |-
127
+ R29zc2lwZXJsIFJ1YnkgY2xpZW50
128
+ test_files: []
129
+ has_rdoc: false