coronet 0.0.1 → 0.0.2
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/Coronet.gemspec +1 -1
- data/README.md +43 -24
- data/Rakefile +6 -0
- data/lib/coronet.rb +2 -2
- data/lib/coronet/listener.rb +5 -9
- data/lib/coronet/mediator.rb +59 -33
- data/lib/coronet/message_format/xml_message_format.rb +7 -3
- data/lib/coronet/protocol.rb +10 -5
- data/lib/coronet/support/echo_server.rb +1 -0
- data/lib/coronet/support/request_reply_server.rb +29 -0
- data/lib/coronet/transport_mechanism/base.rb +3 -13
- data/lib/coronet/transport_mechanism/length_prefixed_tcp_transport.rb +12 -19
- data/lib/coronet/version.rb +3 -0
- data/spec/coronet/listener.spec +2 -2
- data/spec/coronet/mediator.spec +106 -44
- data/spec/coronet/message_format/base.spec +2 -2
- data/spec/coronet/protocol.spec +1 -1
- data/spec/coronet/transport_mechanism/base.spec +4 -2
- data/test/example.rb +14 -0
- metadata +5 -5
- data/lib/Coronet/version.rb +0 -3
- data/lib/coronet/transformation_rule.rb +0 -16
- data/spec/coronet/transformation_rule.spec +0 -29
data/Coronet.gemspec
CHANGED
data/README.md
CHANGED
@@ -20,7 +20,7 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
Coronet requires the definition of message formats, transports, service entry/end-points and mediation
|
23
|
+
Coronet requires the definition of message formats, transports, service entry/end-points and mediation patterns. Once these are defined, it is straightforward to construct a message-transformation and mediation service using Coronet.
|
24
24
|
|
25
25
|
### Message Formats
|
26
26
|
|
@@ -43,11 +43,6 @@ Eventually there should be mappers which can transform hash keys.
|
|
43
43
|
end
|
44
44
|
|
45
45
|
|
46
|
-
### Transformation Rules
|
47
|
-
|
48
|
-
*Transformation rules* adapt one message format to another. Eventually this may support
|
49
|
-
manipulation/mapping of key names.
|
50
|
-
|
51
46
|
### Transport Mechanisms
|
52
47
|
|
53
48
|
*Transport mechanisms* encapsulate functional requirements for message transport to
|
@@ -75,27 +70,51 @@ being transformed, transported to remote endpoints, the responses gathered,
|
|
75
70
|
transformation rules applied, and the initiating actor (client) being sent
|
76
71
|
the transformed response.
|
77
72
|
|
78
|
-
##
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
73
|
+
## Examples
|
74
|
+
|
75
|
+
Specifying explicit constructors for clarity, here is perhaps the most verbose
|
76
|
+
way to setup a mediation framework with Coronet. The example below starts a mediation service
|
77
|
+
listening on $mediation_port for XML messages over binary-length-prefixed TCP,
|
78
|
+
transforms these messages to YAML, and mediates them to a remote host listening
|
79
|
+
at $host_port.
|
80
|
+
|
81
|
+
class SimpleMediator < Mediator
|
82
|
+
with_listener Listener.new($mediator_port,
|
83
|
+
Protocol.new(
|
84
|
+
MessageFormat::XmlMessageFormat.new,
|
85
|
+
TransportMechanism::LengthPrefixedTcpTransport.new))
|
86
|
+
|
87
|
+
for_endpoint RemoteEndpoint.new('localhost', $host_port,
|
88
|
+
Protocol.new(
|
89
|
+
MessageFormat::YamlMessageFormat.new,
|
90
|
+
TransportMechanism::LengthPrefixedTcpTransport.new))
|
91
|
+
end
|
92
|
+
|
93
|
+
# to launch the service, just call the class method 'start_listening'
|
94
|
+
SimpleMediator.start_listening
|
85
95
|
|
86
|
-
|
87
|
-
|
88
|
-
yml = Coronet::MessageFormat::YamlMessageFormat.new
|
96
|
+
The following example makes fuller use of the built-in DSL, and is accordingly
|
97
|
+
much less verbose. The same mediation service is created:
|
89
98
|
|
90
|
-
|
91
|
-
|
92
|
-
|
99
|
+
class SimpleMediatorUsingDSL < Mediator
|
100
|
+
listener $mediator_port, xml_via_tcp
|
101
|
+
endpoint 'localhost', $host_port, yaml_via_tcp
|
102
|
+
end
|
103
|
+
|
104
|
+
You can provide custom processing instructions to the mediation framework. For
|
105
|
+
instance, you might want to log every request/response pattern to the database;
|
106
|
+
or simply keep track of how many messages you've processed. Here is an example
|
107
|
+
of utilizing these callbacks:
|
108
|
+
|
109
|
+
class SimpleMediatorWithCallbacks < SimpleMediatorUsingDSL
|
110
|
+
preprocess do |req|
|
111
|
+
# do something with request object 'req'
|
112
|
+
end
|
113
|
+
|
114
|
+
postprocess do |req, rsp|
|
115
|
+
# do something with request and response objects 'req' and 'rsp'
|
116
|
+
end
|
93
117
|
end
|
94
|
-
|
95
|
-
mediator.start
|
96
|
-
|
97
|
-
|
98
|
-
|
99
118
|
|
100
119
|
## Contributing
|
101
120
|
|
data/Rakefile
CHANGED
data/lib/coronet.rb
CHANGED
data/lib/coronet/listener.rb
CHANGED
@@ -2,24 +2,20 @@ module Coronet
|
|
2
2
|
class Listener < GServer
|
3
3
|
attr_accessor :port
|
4
4
|
attr_accessor :protocol
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :mediator_klass
|
6
6
|
|
7
|
-
def initialize(port, protocol
|
7
|
+
def initialize(port, protocol) #, mediator_klass) #callback=nil)
|
8
8
|
@port = port
|
9
9
|
@protocol = protocol
|
10
|
-
@callback = callback
|
11
|
-
|
12
|
-
# start listening on port
|
13
10
|
super(port)
|
14
11
|
end
|
15
12
|
|
13
|
+
def uses_mediator_class(mediator_klass); @mediator_klass = mediator_klass; end
|
14
|
+
|
16
15
|
def serve(io)
|
17
16
|
request = @protocol.read(io)
|
18
|
-
|
19
|
-
response = callback.call(request)
|
20
|
-
puts "--- listener got response: #{response}"
|
17
|
+
response = @mediator_klass.handle(request)
|
21
18
|
@protocol.write(response, io)
|
22
|
-
# io.close
|
23
19
|
end
|
24
20
|
end
|
25
21
|
end
|
data/lib/coronet/mediator.rb
CHANGED
@@ -1,43 +1,69 @@
|
|
1
1
|
module Coronet
|
2
2
|
class Mediator
|
3
|
-
attr_accessor :listener, :remote_endpoint
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
def using_endpoint(remote_endpoint)
|
19
|
-
@remote_endpoint = remote_endpoint
|
20
|
-
self
|
4
|
+
# proxy start/stop to dedicated listener
|
5
|
+
def self.start_listener; @@listener.start; end
|
6
|
+
def self.stop_listener; @@listener.stop; end
|
7
|
+
def self.listen(&block)
|
8
|
+
unless block_given?
|
9
|
+
start_listener
|
10
|
+
else
|
11
|
+
start_listener
|
12
|
+
block.call
|
13
|
+
stop_listener
|
14
|
+
end
|
21
15
|
end
|
22
16
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
17
|
+
def self.handle(request)
|
18
|
+
if defined? @@preprocess_handler
|
19
|
+
@@preprocess_handler.call(request)
|
20
|
+
end
|
21
|
+
|
22
|
+
response = @@remote_endpoint.transmit(request)
|
23
|
+
|
24
|
+
if defined? @@postprocess_handler
|
25
|
+
@@postprocess_handler.call(request, response)
|
26
|
+
end
|
27
|
+
|
28
|
+
return response
|
33
29
|
end
|
34
|
-
|
35
|
-
# proxy start/stop to listener
|
36
|
-
def start; @listener.start; end
|
37
|
-
def stop; @listener.stop; end
|
38
30
|
|
39
|
-
|
40
|
-
|
31
|
+
# DSL support
|
32
|
+
class << self
|
33
|
+
# callbacks
|
34
|
+
def preprocess(&block); puts "--- pre-handler assigned"; @@preprocess_handler = block; end
|
35
|
+
def postprocess(&block); puts "--- post-handler assigned"; @@postprocess_handler = block; end
|
36
|
+
|
37
|
+
# mediation config
|
38
|
+
def with_listener(listener)
|
39
|
+
@@listener = listener
|
40
|
+
@@listener.uses_mediator_class(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
def listener(port, proto)
|
44
|
+
with_listener(Listener.new(port, proto))
|
45
|
+
end
|
46
|
+
|
47
|
+
def for_endpoint(remote_endpoint)
|
48
|
+
@@remote_endpoint = remote_endpoint
|
49
|
+
end
|
50
|
+
|
51
|
+
def endpoint(host, port, proto)
|
52
|
+
for_endpoint(RemoteEndpoint.new(host, port, proto))
|
53
|
+
end
|
54
|
+
|
55
|
+
# message formats
|
56
|
+
def yaml; MessageFormat::YamlMessageFormat.new; end
|
57
|
+
def xml; MessageFormat::XmlMessageFormat.new; end
|
58
|
+
|
59
|
+
# xport
|
60
|
+
def length_prefixed_tcp; TransportMechanism::LengthPrefixedTcpTransport.new; end
|
61
|
+
|
62
|
+
# protocol
|
63
|
+
def protocol(format, transport); Protocol.new(format, transport); end
|
64
|
+
|
65
|
+
def yaml_via_tcp; protocol(yaml, length_prefixed_tcp); end
|
66
|
+
def xml_via_tcp; protocol(xml, length_prefixed_tcp); end
|
41
67
|
end
|
42
68
|
|
43
69
|
end
|
@@ -3,12 +3,16 @@ module Coronet
|
|
3
3
|
class XmlMessageFormat < Base
|
4
4
|
# transform xml string to hash
|
5
5
|
def unpack(xml_str)
|
6
|
-
|
6
|
+
# puts "--- xml message format attempting to unpack: #{xml_str}"
|
7
|
+
unpacked = XmlSimple.xml_in(xml_str, forcearray: false, keeproot: true)
|
8
|
+
unpacked = unpacked['opt'] if unpacked.has_key? 'opt'
|
9
|
+
# puts "--- unpacked: #{unpacked}"
|
10
|
+
unpacked
|
7
11
|
end
|
8
12
|
|
9
13
|
# transform hash to xml string
|
10
|
-
def pack(hash)
|
11
|
-
XmlSimple.xml_out(hash, noattr: true, rootname:
|
14
|
+
def pack(hash, root='opt')
|
15
|
+
XmlSimple.xml_out(hash, noattr: true, rootname: root).strip!
|
12
16
|
end
|
13
17
|
end
|
14
18
|
end
|
data/lib/coronet/protocol.rb
CHANGED
@@ -9,21 +9,26 @@ module Coronet
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def read(io)
|
12
|
-
packed =
|
13
|
-
unpacked =
|
14
|
-
|
12
|
+
# packed =
|
13
|
+
# unpacked =
|
14
|
+
@message_format.unpack(@transport_mechanism.read(io))
|
15
|
+
# unpacked
|
15
16
|
end
|
16
17
|
|
17
18
|
def write(data, io)
|
18
|
-
|
19
|
-
@transport_mechanism.write(packed, io)
|
19
|
+
@transport_mechanism.write(@message_format.pack(data), io)
|
20
20
|
end
|
21
21
|
|
22
22
|
def transmit(request, host, port)
|
23
|
+
# puts "=== opening connection to #{host}:#{port}"
|
23
24
|
io = @transport_mechanism.open(host,port)
|
25
|
+
# puts "--- writing #{request} to #{host}:#{port}"
|
24
26
|
write(request, io)
|
27
|
+
# puts "=== reading response from #{host}:#{port}"
|
25
28
|
response = read(io)
|
29
|
+
# puts "--- closing socket to #{host}:#{port}"
|
26
30
|
@transport_mechanism.close(io)
|
31
|
+
# puts "=== returning response #{response} from #{host}:#{port}"
|
27
32
|
response
|
28
33
|
end
|
29
34
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Coronet
|
2
|
+
module Support
|
3
|
+
|
4
|
+
class RequestReplyServer < GServer
|
5
|
+
def initialize(port=12345, format=MessageFormat::YamlMessageFormat.new, *args)
|
6
|
+
super(port, *args)
|
7
|
+
@tcp = TransportMechanism::LengthPrefixedTcpTransport.new
|
8
|
+
@format = format
|
9
|
+
@count = 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def serve(io)
|
13
|
+
packed_request = @tcp.read(io)
|
14
|
+
request = @format.unpack(packed_request)
|
15
|
+
response = handle(request)
|
16
|
+
packed_response = @format.pack(response)
|
17
|
+
@tcp.write(packed_response, io)
|
18
|
+
end
|
19
|
+
|
20
|
+
def handle(request)
|
21
|
+
@count += 1
|
22
|
+
# puts "--- mock host handling request #{@count}: #{request}"
|
23
|
+
request['hello'] = 'client' if request.has_key? 'hello'
|
24
|
+
request
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -4,24 +4,14 @@ module Coronet
|
|
4
4
|
include Contractual::Interface
|
5
5
|
|
6
6
|
must :open, :host, :port
|
7
|
-
must :write, :data
|
8
|
-
must :read
|
9
|
-
must :close
|
10
|
-
|
11
|
-
# attr_accessor :host, :port
|
12
|
-
# attr_accessor :io
|
13
|
-
|
14
|
-
# def initialize #(host, port)
|
15
|
-
# @host = host
|
16
|
-
# @port = port
|
17
|
-
# end
|
7
|
+
must :write, :data, :io
|
8
|
+
must :read, :io
|
9
|
+
must :close, :io
|
18
10
|
|
19
11
|
def transmit(data, io)
|
20
|
-
# io = open(host, port)
|
21
12
|
write(data, io)
|
22
13
|
response = read(io)
|
23
14
|
close(io)
|
24
|
-
|
25
15
|
response
|
26
16
|
end
|
27
17
|
end
|
@@ -8,21 +8,25 @@ module Coronet
|
|
8
8
|
class LengthPrefixedTcpTransport < Base
|
9
9
|
attr_accessor :tcp_socket
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
# n.b., for four bytes, can just use 4/'N'
|
12
|
+
LENGTH_HEADER_BYTES = 2
|
13
|
+
LENGTH_HEADER_STORAGE_CLASS = "n"
|
14
|
+
|
15
|
+
def open(host, port); TCPSocket.open(host, port); end
|
14
16
|
|
15
17
|
def read(io)
|
16
|
-
length_header = io.read(
|
17
|
-
p length_header
|
18
|
-
length = length_header.unpack(
|
18
|
+
length_header = io.read(LENGTH_HEADER_BYTES)
|
19
|
+
# p length_header
|
20
|
+
length = length_header.unpack(LENGTH_HEADER_STORAGE_CLASS).first
|
21
|
+
# puts "--- TCP READ #{length}"
|
22
|
+
|
19
23
|
io.read(length)
|
20
24
|
end
|
21
25
|
|
22
26
|
def write(data, io)
|
27
|
+
# puts "--- TCP WRITE #{data}"
|
23
28
|
length = data.size
|
24
|
-
prefix =
|
25
|
-
|
29
|
+
prefix = [length].pack(LENGTH_HEADER_STORAGE_CLASS)
|
26
30
|
io.print(prefix)
|
27
31
|
io.print(data)
|
28
32
|
end
|
@@ -30,17 +34,6 @@ module Coronet
|
|
30
34
|
def close(io)
|
31
35
|
io.close
|
32
36
|
end
|
33
|
-
|
34
|
-
private
|
35
|
-
def to_byte_array(num)
|
36
|
-
result = Array.new
|
37
|
-
begin
|
38
|
-
result << (num & 0xff)
|
39
|
-
num >>= 8
|
40
|
-
end until (num == 0 || num == -1) && (result.last[7] == num[7])
|
41
|
-
result.reverse
|
42
|
-
end
|
43
|
-
|
44
37
|
end
|
45
38
|
end
|
46
39
|
end
|
data/spec/coronet/listener.spec
CHANGED
@@ -17,7 +17,6 @@ module Coronet
|
|
17
17
|
|
18
18
|
module Echo
|
19
19
|
def self.handle(request)
|
20
|
-
# puts "--- echo server handling request: #{request}"
|
21
20
|
request
|
22
21
|
end
|
23
22
|
end
|
@@ -28,7 +27,8 @@ module Coronet
|
|
28
27
|
xml = MessageFormat::XmlMessageFormat.new
|
29
28
|
xml_via_tcp = Protocol.new(xml, tcp)
|
30
29
|
|
31
|
-
echo_listener = Listener.new(12345, xml_via_tcp
|
30
|
+
echo_listener = Listener.new(12345, xml_via_tcp)
|
31
|
+
echo_listener.uses_mediator_class(Echo)
|
32
32
|
echo_listener.start
|
33
33
|
|
34
34
|
msg = { 'hello' => 'world' }
|
data/spec/coronet/mediator.spec
CHANGED
@@ -3,7 +3,7 @@ require 'gserver'
|
|
3
3
|
require 'contractual'
|
4
4
|
require 'xmlsimple'
|
5
5
|
|
6
|
-
require 'coronet/support/
|
6
|
+
require 'coronet/support/request_reply_server'
|
7
7
|
|
8
8
|
require 'coronet/message_format/base'
|
9
9
|
require 'coronet/message_format/xml_message_format'
|
@@ -14,68 +14,130 @@ require 'coronet/transport_mechanism/length_prefixed_tcp_transport'
|
|
14
14
|
|
15
15
|
require 'coronet/protocol'
|
16
16
|
require 'coronet/listener'
|
17
|
-
require 'coronet/transformation_rule'
|
18
17
|
require 'coronet/remote_endpoint'
|
19
18
|
|
20
19
|
require 'coronet/mediator'
|
21
20
|
|
22
21
|
module Coronet
|
23
22
|
|
23
|
+
include TransportMechanism
|
24
|
+
include MessageFormat
|
25
|
+
include Support
|
26
|
+
|
27
|
+
$mediator_port, $host_port = 10000, 10001
|
28
|
+
|
24
29
|
describe Mediator, "mediates between clients and servers" do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
tcp = TransportMechanism::LengthPrefixedTcpTransport.new
|
29
|
-
|
30
|
-
xml = MessageFormat::XmlMessageFormat.new
|
31
|
-
yml = MessageFormat::YamlMessageFormat.new
|
32
|
-
|
33
|
-
xml_via_tcp = Protocol.new(xml, tcp)
|
34
|
-
yml_via_tcp = Protocol.new(yml, tcp)
|
35
|
-
|
36
|
-
xml_to_yml = TransformationRule.new(xml, yml)
|
37
|
-
|
38
|
-
listener = Listener.new(10000, xml_via_tcp)
|
39
|
-
|
40
|
-
echo_server = Support::EchoServer.new(10001)
|
41
|
-
echo_server_endpoint = RemoteEndpoint.new('localhost', 10001, yml_via_tcp)
|
42
|
-
|
43
|
-
mediator = Mediator.new listener: listener, endpoint: echo_server_endpoint # , xml_to_yml)
|
44
|
-
|
45
|
-
echo_server.start
|
46
|
-
mediator.start
|
47
|
-
|
48
|
-
msg = { 'hello' => 'world' }
|
49
|
-
xml_via_tcp.transmit(msg, 'localhost', 10000).should == msg
|
30
|
+
|
31
|
+
before :each do
|
32
|
+
@xml_over_tcp = Protocol.new(XmlMessageFormat.new, LengthPrefixedTcpTransport.new)
|
50
33
|
|
51
|
-
|
52
|
-
|
34
|
+
@request = { 'hello' => 'server' }
|
35
|
+
@expected_response = { 'hello' => 'client' }
|
53
36
|
end
|
54
37
|
|
55
|
-
|
38
|
+
# after :each do
|
39
|
+
# end
|
40
|
+
|
41
|
+
it "adapts protocols" do
|
56
42
|
|
57
|
-
|
58
|
-
|
59
|
-
|
43
|
+
class SimpleMediator < Mediator
|
44
|
+
with_listener Listener.new($mediator_port,
|
45
|
+
Protocol.new(
|
46
|
+
MessageFormat::XmlMessageFormat.new,
|
47
|
+
TransportMechanism::LengthPrefixedTcpTransport.new))
|
48
|
+
|
49
|
+
for_endpoint RemoteEndpoint.new('localhost', $host_port,
|
50
|
+
Protocol.new(
|
51
|
+
MessageFormat::YamlMessageFormat.new,
|
52
|
+
TransportMechanism::LengthPrefixedTcpTransport.new))
|
53
|
+
end
|
60
54
|
|
61
|
-
|
62
|
-
|
63
|
-
|
55
|
+
host = RequestReplyServer.new($host_port, YamlMessageFormat.new)
|
56
|
+
host.start
|
57
|
+
SimpleMediator.listen do
|
58
|
+
|
59
|
+
@xml_over_tcp.transmit(@request, 'localhost', $mediator_port).should == @expected_response
|
64
60
|
end
|
61
|
+
host.stop
|
62
|
+
end
|
63
|
+
|
64
|
+
it "supports a simple DSL" do
|
65
65
|
|
66
|
-
|
66
|
+
class SimpleMediatorUsingDSL < Mediator
|
67
|
+
listener $mediator_port, xml_via_tcp
|
68
|
+
endpoint 'localhost', $host_port, yaml_via_tcp
|
69
|
+
end
|
67
70
|
|
68
|
-
|
69
|
-
|
71
|
+
host = RequestReplyServer.new($host_port, YamlMessageFormat.new)
|
72
|
+
host.start
|
70
73
|
|
71
|
-
|
72
|
-
|
74
|
+
SimpleMediatorUsingDSL.listen do
|
75
|
+
@xml_over_tcp.transmit(@request, 'localhost', $mediator_port).should == @expected_response
|
76
|
+
end
|
77
|
+
host.stop
|
78
|
+
end
|
79
|
+
|
80
|
+
it "handles callbacks" do
|
73
81
|
|
74
|
-
|
82
|
+
|
83
|
+
$preprocess_invoked, $postprocess_invoked = false, false
|
84
|
+
class SimpleMediatorWithCallbacks < SimpleMediatorUsingDSL
|
85
|
+
preprocess do |req|
|
86
|
+
$preprocess_invoked = true
|
87
|
+
end
|
88
|
+
|
89
|
+
postprocess do |req, rsp|
|
90
|
+
$postprocess_invoked = true
|
91
|
+
end
|
92
|
+
end
|
75
93
|
|
76
|
-
|
77
|
-
|
94
|
+
host = RequestReplyServer.new($host_port, YamlMessageFormat.new)
|
95
|
+
host.start
|
96
|
+
SimpleMediatorWithCallbacks.listen do
|
97
|
+
@xml_over_tcp.transmit(@request, 'localhost', $mediator_port).should == @expected_response
|
98
|
+
end
|
99
|
+
host.stop
|
100
|
+
$preprocess_invoked.should == true
|
101
|
+
$postprocess_invoked.should == true
|
102
|
+
end
|
103
|
+
|
104
|
+
it "supports concurrent request handling" do
|
78
105
|
|
106
|
+
class SimpleMediatorWithLogging < SimpleMediatorUsingDSL
|
107
|
+
postprocess do |req, rsp|
|
108
|
+
# puts "--- request #{req} got response #{rsp}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
host = RequestReplyServer.new($host_port, YamlMessageFormat.new)
|
113
|
+
host.start
|
114
|
+
SimpleMediatorWithLogging.listen do
|
115
|
+
|
116
|
+
|
117
|
+
client_count = 2
|
118
|
+
message_count = 3
|
119
|
+
|
120
|
+
clients = []
|
121
|
+
(1..client_count).each do |n|
|
122
|
+
client = Thread.new do
|
123
|
+
message_count.times do |index|
|
124
|
+
msg = { 'hello' => 'server', 'client' => n, 'index' => index }
|
125
|
+
xml_over_tcp = Protocol.new(XmlMessageFormat.new, LengthPrefixedTcpTransport.new)
|
126
|
+
# puts "--- client #{n} about to transmit message #{msg}"
|
127
|
+
response = xml_over_tcp.transmit(msg, 'localhost', $mediator_port)
|
128
|
+
# puts "--- client #{n} got response #{response}"
|
129
|
+
response['hello'].should == 'client'
|
130
|
+
response['client'].to_i.should == n
|
131
|
+
response['index'].to_i.should == index
|
132
|
+
sleep 0.1
|
133
|
+
end
|
134
|
+
end
|
135
|
+
clients << client
|
136
|
+
|
137
|
+
end
|
138
|
+
clients.each { |client| client.join }
|
139
|
+
end
|
140
|
+
host.stop
|
79
141
|
end
|
80
142
|
end
|
81
143
|
end
|
@@ -22,12 +22,12 @@ module Coronet
|
|
22
22
|
|
23
23
|
it "should handle xml" do
|
24
24
|
@xml.unpack(@xml_data).should == { 'hello' => 'world' }
|
25
|
-
@xml.pack(@xml.unpack(@xml_data)).should == @xml_data
|
25
|
+
@xml.pack(@xml.unpack(@xml_data), nil).should == @xml_data
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should handle transforming yml to xml (and vice versa)" do
|
29
29
|
@xml.unpack(@xml_data).should == @yml.unpack(@yml_data)
|
30
|
-
@xml.pack(@yml.unpack(@yml_data)).should == @xml_data
|
30
|
+
@xml.pack(@yml.unpack(@yml_data), nil).should == @xml_data
|
31
31
|
@yml.pack(@xml.unpack(@xml_data)).should == @yml_data
|
32
32
|
end
|
33
33
|
end
|
data/spec/coronet/protocol.spec
CHANGED
@@ -22,7 +22,7 @@ module Coronet
|
|
22
22
|
xml = MessageFormat::XmlMessageFormat.new
|
23
23
|
xml_via_tcp = Protocol.new(xml, tcp)
|
24
24
|
|
25
|
-
msg = { 'hello' => 'world' }
|
25
|
+
msg = { 'hello' => 'world', 'whats' => 'up' }
|
26
26
|
xml_via_tcp.transmit(msg, 'localhost', 12345).should == msg
|
27
27
|
|
28
28
|
echo.stop
|
@@ -12,11 +12,13 @@ module Coronet
|
|
12
12
|
describe Base, "encapsulates transport-layer functionality" do
|
13
13
|
it "supports interaction with remote services" do
|
14
14
|
echo = Support::EchoServer.new(12345)
|
15
|
-
tcp = LengthPrefixedTcpTransport.new
|
15
|
+
tcp = LengthPrefixedTcpTransport.new
|
16
16
|
|
17
17
|
echo.start
|
18
18
|
io = tcp.open('localhost', 12345)
|
19
|
-
|
19
|
+
msg = "data" *1250
|
20
|
+
# p msg
|
21
|
+
tcp.transmit(msg, io).should == msg
|
20
22
|
echo.stop
|
21
23
|
end
|
22
24
|
end
|
data/test/example.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'coronet'
|
2
|
+
|
3
|
+
tcp = Coronet::TransportMechanism::LengthPrefixedTcpTransport.new
|
4
|
+
xml = Coronet::MessageFormat::XmlMessageFormat.new
|
5
|
+
yml = Coronet::MessageFormat::YamlMessageFormat.new
|
6
|
+
|
7
|
+
|
8
|
+
#
|
9
|
+
# mediator = Coronet::Mediator.new do
|
10
|
+
# local xml, tcp, 10000
|
11
|
+
# remote yml, tcp, 'localhost', 10001
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# mediator.start
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coronet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-27 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Coronet is a simple protocol adaption framework
|
15
15
|
email:
|
@@ -24,7 +24,6 @@ files:
|
|
24
24
|
- LICENSE
|
25
25
|
- README.md
|
26
26
|
- Rakefile
|
27
|
-
- lib/Coronet/version.rb
|
28
27
|
- lib/coronet.rb
|
29
28
|
- lib/coronet/listener.rb
|
30
29
|
- lib/coronet/mediator.rb
|
@@ -34,17 +33,18 @@ files:
|
|
34
33
|
- lib/coronet/protocol.rb
|
35
34
|
- lib/coronet/remote_endpoint.rb
|
36
35
|
- lib/coronet/support/echo_server.rb
|
37
|
-
- lib/coronet/
|
36
|
+
- lib/coronet/support/request_reply_server.rb
|
38
37
|
- lib/coronet/transport_mechanism/base.rb
|
39
38
|
- lib/coronet/transport_mechanism/length_prefixed_tcp_transport.rb
|
39
|
+
- lib/coronet/version.rb
|
40
40
|
- spec/coronet/listener.spec
|
41
41
|
- spec/coronet/mediator.spec
|
42
42
|
- spec/coronet/message_format/base.spec
|
43
43
|
- spec/coronet/protocol.spec
|
44
44
|
- spec/coronet/remote_endpoint.spec
|
45
|
-
- spec/coronet/transformation_rule.spec
|
46
45
|
- spec/coronet/transport_mechanism/base.spec
|
47
46
|
- spec/coronet_spec.rb
|
47
|
+
- test/example.rb
|
48
48
|
homepage:
|
49
49
|
licenses: []
|
50
50
|
post_install_message:
|
data/lib/Coronet/version.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module Coronet
|
2
|
-
class TransformationRule
|
3
|
-
attr_accessor :in, :out
|
4
|
-
|
5
|
-
def initialize(incoming, outgoing)
|
6
|
-
@in = incoming
|
7
|
-
@out = outgoing
|
8
|
-
end
|
9
|
-
|
10
|
-
def apply(message)
|
11
|
-
@in.transform(message, @out)
|
12
|
-
end
|
13
|
-
|
14
|
-
def inverse; TransformationRule.new(@out, @in); end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'contractual'
|
2
|
-
require 'xmlsimple'
|
3
|
-
require 'psych'
|
4
|
-
|
5
|
-
require 'coronet/message_format/base'
|
6
|
-
require 'coronet/message_format/xml_message_format'
|
7
|
-
require 'coronet/message_format/yaml_message_format'
|
8
|
-
|
9
|
-
require 'coronet/transformation_rule'
|
10
|
-
|
11
|
-
module Coronet
|
12
|
-
describe TransformationRule, "transforms messages into other formats" do
|
13
|
-
before :each do
|
14
|
-
@yml, @xml = MessageFormat::YamlMessageFormat.new, MessageFormat::XmlMessageFormat.new
|
15
|
-
@yml_data = "---\nhello: world\n"
|
16
|
-
@xml_data = "<hello>world</hello>"
|
17
|
-
end
|
18
|
-
|
19
|
-
it "transforms xml to yml" do
|
20
|
-
rule = TransformationRule.new(@xml, @yml)
|
21
|
-
rule.apply(@xml_data).should == @yml_data
|
22
|
-
end
|
23
|
-
|
24
|
-
it "transforms yml to xml" do
|
25
|
-
rule = TransformationRule.new(@yml, @xml)
|
26
|
-
rule.apply(@yml_data).should == @xml_data
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|