ccrpc 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
 - checksums.yaml.gz.sig +0 -0
 - data/README.md +10 -9
 - data/lib/ccrpc/escape.rb +1 -1
 - data/lib/ccrpc/rpc_connection.rb +188 -53
 - data/lib/ccrpc/version.rb +1 -1
 - data.tar.gz.sig +0 -0
 - metadata +25 -26
 - metadata.gz.sig +0 -0
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: a3f1a9ac22e449534ede2f1d3f94efcc11becf3d65d7e868ce1f6334f580ba54
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 70a5849b9f6594090a5069b13d566b39cf53baf69bf5ee743ead1fa56d7bd1a3
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 31e497800794295aafed95c1f75b8d2cc866aff6255d94914f0377eb04d7ad3a0009da355bc6f240466a25cd5131de46a56d8845c345f4a67b8896303e79a5e2
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: c457015d25201324c856a7fea9b0bc3ccdc0b5a1f9819f7c0758e45f27f3cf4c732b4028fa3e8f9af955a2e14319bde9c6ff6da9e3a3cae09b3cc560e8109520
         
     | 
    
        checksums.yaml.gz.sig
    CHANGED
    
    | 
         Binary file 
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,15 +1,16 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # Ccrpc - A  
     | 
| 
      
 1 
     | 
    
         
            +
            # Ccrpc - A minimalist RPC library for Ruby
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            Features:
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            *  
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            * Simple human readable wire protocol and optionally a faster binary protocol
         
     | 
| 
      
 6 
     | 
    
         
            +
            * Works on arbitrary IO like objects (Pipes, Sockets, STDIN, STDOUT, OpenSSL) even Windows CR/LF converting IOs
         
     | 
| 
       6 
7 
     | 
    
         
             
            * No object definitions - only plain string transfers (so no issues with undefined classes or garbage collection like in DRb)
         
     | 
| 
       7 
8 
     | 
    
         
             
            * Each call transfers a function name and a list of parameters in form of a Hash<String=>String>
         
     | 
| 
       8 
9 
     | 
    
         
             
            * Each response equally transfers a list of parameters
         
     | 
| 
       9 
     | 
    
         
            -
            * Similar to closures, it's possible to respond to a particular call as a call_back
         
     | 
| 
       10 
     | 
    
         
            -
            * Fully asynchronous, either by use of multiple threads or by using lazy_answers 
     | 
| 
      
 10 
     | 
    
         
            +
            * Similar to closures, it's possible to respond to a particular call as a `call_back`
         
     | 
| 
      
 11 
     | 
    
         
            +
            * Fully asynchronous, either by use of multiple threads or by using `lazy_answers`, so that arbitrary calls in both directions can be mixed simultaneously without blocking each other
         
     | 
| 
       11 
12 
     | 
    
         
             
            * Fully thread safe, but doesn't use additional internal threads
         
     | 
| 
       12 
     | 
    
         
            -
            * Each call_back arrives in the thread of the caller
         
     | 
| 
      
 13 
     | 
    
         
            +
            * Each `call_back` arrives in the thread of the caller
         
     | 
| 
       13 
14 
     | 
    
         
             
            * Only dedicated functions can be called (not arbitrary as in DRb)
         
     | 
| 
       14 
15 
     | 
    
         
             
            * No dependencies
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
         @@ -72,7 +73,7 @@ The following example invokes the call in the opposite direction, from the subpr 
     | 
|
| 
       72 
73 
     | 
    
         
             
                require 'ccrpc'
         
     | 
| 
       73 
74 
     | 
    
         
             
                # Create the receiver side of the connection
         
     | 
| 
       74 
75 
     | 
    
         
             
                # Use a copy of STDOUT because...
         
     | 
| 
       75 
     | 
    
         
            -
                rpc = Ccrpc::RpcConnection.new(STDIN, STDOUT.dup)
         
     | 
| 
      
 76 
     | 
    
         
            +
                rpc = Ccrpc::RpcConnection.new(STDIN.binmode, STDOUT.dup.binmode)
         
     | 
| 
       76 
77 
     | 
    
         
             
                # .. STDOUT is now redirected to STDERR, so that pp prints to STDERR
         
     | 
| 
       77 
78 
     | 
    
         
             
                STDOUT.reopen(STDERR)
         
     | 
| 
       78 
79 
     | 
    
         
             
                # Call function "hello" with param {"who" => "world"}
         
     | 
| 
         @@ -84,10 +85,10 @@ The following example invokes the call in the opposite direction, from the subpr 
     | 
|
| 
       84 
85 
     | 
    
         
             
              tf.write(code)
         
     | 
| 
       85 
86 
     | 
    
         
             
              tf.flush
         
     | 
| 
       86 
87 
     | 
    
         
             
              # Execute the temp file in a subprocess
         
     | 
| 
       87 
     | 
    
         
            -
              io = IO.popen(['ruby', tf.path], " 
     | 
| 
      
 88 
     | 
    
         
            +
              io = IO.popen(['ruby', tf.path], "wb+")
         
     | 
| 
       88 
89 
     | 
    
         | 
| 
       89 
90 
     | 
    
         
             
              # Create the caller side of the connection
         
     | 
| 
       90 
     | 
    
         
            -
              rpc = Ccrpc::RpcConnection.new(io, io)
         
     | 
| 
      
 91 
     | 
    
         
            +
              rpc = Ccrpc::RpcConnection.new(io, io, protocol: :binary)
         
     | 
| 
       91 
92 
     | 
    
         
             
              # Wait for calls
         
     | 
| 
       92 
93 
     | 
    
         
             
              rpc.call do |call|
         
     | 
| 
       93 
94 
     | 
    
         
             
                # Print the received call data to STDERR
         
     | 
    
        data/lib/ccrpc/escape.rb
    CHANGED
    
    | 
         @@ -5,7 +5,7 @@ module Ccrpc 
     | 
|
| 
       5 
5 
     | 
    
         
             
              module Escape
         
     | 
| 
       6 
6 
     | 
    
         
             
                def self.escape(data)
         
     | 
| 
       7 
7 
     | 
    
         
             
                  data = data.b if data.frozen? || data.encoding != Encoding::BINARY
         
     | 
| 
       8 
     | 
    
         
            -
                  data.gsub(/([\a\r\n\t\\])/n){ "\\x" + $1. 
     | 
| 
      
 8 
     | 
    
         
            +
                  data.gsub(/([\a\r\n\t\\])/n){ "\\x" + $1.unpack1("H2") }
         
     | 
| 
       9 
9 
     | 
    
         
             
                end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
                def self.unescape(data)
         
     | 
    
        data/lib/ccrpc/rpc_connection.rb
    CHANGED
    
    | 
         @@ -76,8 +76,11 @@ class RpcConnection 
     | 
|
| 
       76 
76 
     | 
    
         
             
              end
         
     | 
| 
       77 
77 
     | 
    
         | 
| 
       78 
78 
     | 
    
         
             
              CallbackReceiver = Struct.new :meth, :callbacks
         
     | 
| 
      
 79 
     | 
    
         
            +
              ReceivedCallData = Struct.new :cbfunc, :id, :recv_id
         
     | 
| 
       79 
80 
     | 
    
         | 
| 
      
 81 
     | 
    
         
            +
              # The kind of +IO+ object used to receive calls and answers. Set by {initialize}.
         
     | 
| 
       80 
82 
     | 
    
         
             
              attr_accessor :read_io
         
     | 
| 
      
 83 
     | 
    
         
            +
              # The kind of +IO+ object used to send calls and answers. Set by {initialize}.
         
     | 
| 
       81 
84 
     | 
    
         
             
              attr_accessor :write_io
         
     | 
| 
       82 
85 
     | 
    
         | 
| 
       83 
86 
     | 
    
         
             
              # Create a RPC connection
         
     | 
| 
         @@ -88,11 +91,28 @@ class RpcConnection 
     | 
|
| 
       88 
91 
     | 
    
         
             
              #    If enabled the return value of #call is always a Ccrpc::Promise object.
         
     | 
| 
       89 
92 
     | 
    
         
             
              #    It behaves like an ordinary +nil+ or Hash object, but the actual IO blocking operation is delayed to the first method call on the Promise object.
         
     | 
| 
       90 
93 
     | 
    
         
             
              #    See {#call} for more description.
         
     | 
| 
       91 
     | 
    
         
            -
               
     | 
| 
      
 94 
     | 
    
         
            +
              # @param [Symbol] protocol   Select the protocol which is used to send calls.
         
     | 
| 
      
 95 
     | 
    
         
            +
              #    * The +:text+ protocol is the classic default.
         
     | 
| 
      
 96 
     | 
    
         
            +
              #    * The +:binary+ protocol is faster, but not so readable for human.
         
     | 
| 
      
 97 
     | 
    
         
            +
              #    * The +:prefer_binary+ is the same as :binary, but with an initial round-trip to check that the other end is binary-capable (means ccrpc >= 0.5).
         
     | 
| 
      
 98 
     | 
    
         
            +
              #    The protocol used to receive calls is selected by the *protocol* option on the other end.
         
     | 
| 
      
 99 
     | 
    
         
            +
              #    A connection could use different protocols for both directions, although this has no advantage.
         
     | 
| 
      
 100 
     | 
    
         
            +
              def initialize(read_io, write_io, lazy_answers: false, protocol: :text)
         
     | 
| 
       92 
101 
     | 
    
         
             
                super()
         
     | 
| 
       93 
102 
     | 
    
         | 
| 
       94 
103 
     | 
    
         
             
                @read_io = read_io
         
     | 
| 
       95 
104 
     | 
    
         
             
                @write_io = write_io
         
     | 
| 
      
 105 
     | 
    
         
            +
                @read_binary = false
         
     | 
| 
      
 106 
     | 
    
         
            +
                @write_binary = case protocol
         
     | 
| 
      
 107 
     | 
    
         
            +
                  when :binary
         
     | 
| 
      
 108 
     | 
    
         
            +
                    true
         
     | 
| 
      
 109 
     | 
    
         
            +
                  when :text, :only_text # only_text is to simulate ccrpc-0.4.0 peer
         
     | 
| 
      
 110 
     | 
    
         
            +
                    false
         
     | 
| 
      
 111 
     | 
    
         
            +
                  when :prefer_binary
         
     | 
| 
      
 112 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 113 
     | 
    
         
            +
                  else
         
     | 
| 
      
 114 
     | 
    
         
            +
                    raise ArgumentError, "invalid protocol: #{protocol.inspect}"
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
       96 
116 
     | 
    
         
             
                if lazy_answers
         
     | 
| 
       97 
117 
     | 
    
         
             
                  require 'ccrpc/lazy'
         
     | 
| 
       98 
118 
     | 
    
         
             
                  alias maybe_lazy do_lazy
         
     | 
| 
         @@ -104,27 +124,100 @@ class RpcConnection 
     | 
|
| 
       104 
124 
     | 
    
         
             
                  @write_io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
         
     | 
| 
       105 
125 
     | 
    
         
             
                end
         
     | 
| 
       106 
126 
     | 
    
         | 
| 
       107 
     | 
    
         
            -
                # A random number as start call ID is not technically required, but makes transferred data more readable.
         
     | 
| 
       108 
     | 
    
         
            -
                @id = rand(1000)
         
     | 
| 
       109 
127 
     | 
    
         
             
                @id_mutex = Mutex.new
         
     | 
| 
       110 
128 
     | 
    
         
             
                @read_mutex = Mutex.new
         
     | 
| 
       111 
129 
     | 
    
         
             
                @write_mutex = Mutex.new
         
     | 
| 
       112 
130 
     | 
    
         
             
                @answers = {}
         
     | 
| 
       113 
131 
     | 
    
         
             
                @receivers = {}
         
     | 
| 
       114 
132 
     | 
    
         
             
                @answers_mutex = Mutex.new
         
     | 
| 
      
 133 
     | 
    
         
            +
                @proto_ack_mutex = Mutex.new
         
     | 
| 
       115 
134 
     | 
    
         
             
                @new_answer = ConditionVariable.new
         
     | 
| 
       116 
135 
     | 
    
         | 
| 
       117 
136 
     | 
    
         
             
                @read_enum = Enumerator.new do |y|
         
     | 
| 
       118 
137 
     | 
    
         
             
                  begin
         
     | 
| 
       119 
138 
     | 
    
         
             
                    while @read_enum
         
     | 
| 
       120 
     | 
    
         
            -
                       
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
      
 139 
     | 
    
         
            +
                      if @read_binary
         
     | 
| 
      
 140 
     | 
    
         
            +
                        t = @read_io.read(1)&.getbyte(0)
         
     | 
| 
      
 141 
     | 
    
         
            +
                        # p @read_io=>t
         
     | 
| 
      
 142 
     | 
    
         
            +
                        case t
         
     | 
| 
      
 143 
     | 
    
         
            +
                          when 1
         
     | 
| 
      
 144 
     | 
    
         
            +
                            keysize, valsize = @read_io.read(8).unpack("NN")
         
     | 
| 
      
 145 
     | 
    
         
            +
                            key = @read_io.read(keysize).force_encoding(Encoding::UTF_8)
         
     | 
| 
      
 146 
     | 
    
         
            +
                            value = @read_io.read(valsize).force_encoding(Encoding::UTF_8)
         
     | 
| 
      
 147 
     | 
    
         
            +
                            y << [key, value]
         
     | 
| 
      
 148 
     | 
    
         
            +
                          when 2
         
     | 
| 
      
 149 
     | 
    
         
            +
                            id, funcsize = @read_io.read(8).unpack("NN")
         
     | 
| 
      
 150 
     | 
    
         
            +
                            func = @read_io.read(funcsize)
         
     | 
| 
      
 151 
     | 
    
         
            +
                            y << ReceivedCallData.new(func.force_encoding(Encoding::UTF_8), id)
         
     | 
| 
      
 152 
     | 
    
         
            +
                          when 3
         
     | 
| 
      
 153 
     | 
    
         
            +
                            id, recv_id, funcsize = @read_io.read(12).unpack("NNN")
         
     | 
| 
      
 154 
     | 
    
         
            +
                            func = @read_io.read(funcsize)
         
     | 
| 
      
 155 
     | 
    
         
            +
                            y << ReceivedCallData.new(func.force_encoding(Encoding::UTF_8), id, recv_id)
         
     | 
| 
      
 156 
     | 
    
         
            +
                          when 4
         
     | 
| 
      
 157 
     | 
    
         
            +
                            id = @read_io.read(4).unpack1("N")
         
     | 
| 
      
 158 
     | 
    
         
            +
                            y << id
         
     | 
| 
      
 159 
     | 
    
         
            +
                          when 79 # "O"
         
     | 
| 
      
 160 
     | 
    
         
            +
                            l = @read_io.read(6)
         
     | 
| 
      
 161 
     | 
    
         
            +
                            unless l == "\tK\n\a1\n"
         
     | 
| 
      
 162 
     | 
    
         
            +
                              raise InvalidResponse, "invalid binary response #{l.inspect}"
         
     | 
| 
      
 163 
     | 
    
         
            +
                            end
         
     | 
| 
      
 164 
     | 
    
         
            +
                            y << ["O", "K"]
         
     | 
| 
      
 165 
     | 
    
         
            +
                            y << 1
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                          when NilClass
         
     | 
| 
      
 168 
     | 
    
         
            +
                            # connection closed
         
     | 
| 
      
 169 
     | 
    
         
            +
                            break
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                          else
         
     | 
| 
      
 172 
     | 
    
         
            +
                            raise InvalidResponse, "invalid binary response #{t.inspect}"
         
     | 
| 
      
 173 
     | 
    
         
            +
                        end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                      else
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                        l = @read_io.gets&.force_encoding(Encoding::BINARY)
         
     | 
| 
      
 178 
     | 
    
         
            +
                        # p @read_io=>l
         
     | 
| 
      
 179 
     | 
    
         
            +
                        case
         
     | 
| 
      
 180 
     | 
    
         
            +
                          when l=="\r\0\a1\n" && protocol != :only_text
         
     | 
| 
      
 181 
     | 
    
         
            +
                            @read_binary = true
         
     | 
| 
      
 182 
     | 
    
         
            +
                          when l=="\r\1\a1\n" && protocol != :only_text
         
     | 
| 
      
 183 
     | 
    
         
            +
                            @read_binary = true
         
     | 
| 
      
 184 
     | 
    
         
            +
                            send_answer({O: :K}, 1)
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                          when l=~/\A([^\t\a\n]+)\t(.*?)\r?\n\z/mn
         
     | 
| 
      
 187 
     | 
    
         
            +
                            # received key/value pair used for either callback parameters or return values
         
     | 
| 
      
 188 
     | 
    
         
            +
                            y << [Escape.unescape($1).force_encoding(Encoding::UTF_8), Escape.unescape($2.force_encoding(Encoding::UTF_8))]
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
                          when l=~/\A([^\t\a\n]+)(?:\a(\d+))?(?:\a(\d+))?\r?\n\z/mn
         
     | 
| 
      
 191 
     | 
    
         
            +
                            # received callback
         
     | 
| 
      
 192 
     | 
    
         
            +
                            y << ReceivedCallData.new(Escape.unescape($1.force_encoding(Encoding::UTF_8)), $2&.to_i, $3&.to_i)
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                          when l=~/\A\a(\d+)\r?\n\z/mn
         
     | 
| 
      
 195 
     | 
    
         
            +
                            # received return event
         
     | 
| 
      
 196 
     | 
    
         
            +
                            y << $1.to_i
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                          when l.nil?
         
     | 
| 
      
 199 
     | 
    
         
            +
                            # connection closed
         
     | 
| 
      
 200 
     | 
    
         
            +
                            break
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                          else
         
     | 
| 
      
 203 
     | 
    
         
            +
                            raise InvalidResponse, "invalid text response #{l.inspect}"
         
     | 
| 
      
 204 
     | 
    
         
            +
                        end
         
     | 
| 
      
 205 
     | 
    
         
            +
                      end
         
     | 
| 
       123 
206 
     | 
    
         
             
                    end
         
     | 
| 
       124 
207 
     | 
    
         
             
                  rescue => err
         
     | 
| 
       125 
208 
     | 
    
         
             
                    y << err
         
     | 
| 
       126 
209 
     | 
    
         
             
                  end
         
     | 
| 
       127 
210 
     | 
    
         
             
                end
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                if @write_binary == true # immediate binary mode
         
     | 
| 
      
 213 
     | 
    
         
            +
                  # Use ID 1 for proto change request to have a fixed string over the wire
         
     | 
| 
      
 214 
     | 
    
         
            +
                  register_call("\r", 1)
         
     | 
| 
      
 215 
     | 
    
         
            +
                  @write_io.write "\r\0\a1\n"
         
     | 
| 
      
 216 
     | 
    
         
            +
                  @write_io.flush
         
     | 
| 
      
 217 
     | 
    
         
            +
                end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                # A random number as start call ID is not technically required, but makes transferred data more readable.
         
     | 
| 
      
 220 
     | 
    
         
            +
                @id = rand(1000) + 1
         
     | 
| 
       128 
221 
     | 
    
         
             
              end
         
     | 
| 
       129 
222 
     | 
    
         | 
| 
       130 
223 
     | 
    
         
             
              private def do_lazy(&block)
         
     | 
| 
         @@ -134,11 +227,11 @@ class RpcConnection 
     | 
|
| 
       134 
227 
     | 
    
         
             
                yield
         
     | 
| 
       135 
228 
     | 
    
         
             
              end
         
     | 
| 
       136 
229 
     | 
    
         | 
| 
       137 
     | 
    
         
            -
              # Disable reception of data from the read_io object.
         
     | 
| 
      
 230 
     | 
    
         
            +
              # Disable reception of data from the {read_io} object.
         
     | 
| 
       138 
231 
     | 
    
         
             
              #
         
     | 
| 
       139 
     | 
    
         
            -
              # This function doesn't close the IO objects.
         
     | 
| 
      
 232 
     | 
    
         
            +
              # This function doesn't close the +IO+ objects.
         
     | 
| 
       140 
233 
     | 
    
         
             
              # A waiting reception is not aborted by this call.
         
     | 
| 
       141 
     | 
    
         
            -
              # It can be aborted by calling IO#close on the underlying read_io and write_io objects.
         
     | 
| 
      
 234 
     | 
    
         
            +
              # It can be aborted by calling +IO#close+ on the underlying {read_io} and {write_io} objects.
         
     | 
| 
       142 
235 
     | 
    
         
             
              def detach
         
     | 
| 
       143 
236 
     | 
    
         
             
                @read_enum = nil
         
     | 
| 
       144 
237 
     | 
    
         
             
              end
         
     | 
| 
         @@ -146,9 +239,9 @@ class RpcConnection 
     | 
|
| 
       146 
239 
     | 
    
         
             
              # Do a RPC call and/or wait for a RPC call from the other side.
         
     | 
| 
       147 
240 
     | 
    
         
             
              #
         
     | 
| 
       148 
241 
     | 
    
         
             
              # {#call} must be called with either a function name (and optional parameters) or with a block or with both.
         
     | 
| 
       149 
     | 
    
         
            -
              # If  
     | 
| 
       150 
     | 
    
         
            -
              # If  
     | 
| 
       151 
     | 
    
         
            -
              # If  
     | 
| 
      
 242 
     | 
    
         
            +
              # * If called with a function name, the block on the other end of the RPC connection is called with that function name.
         
     | 
| 
      
 243 
     | 
    
         
            +
              # * If called with a block only, than it receives these kind of calls, which are called anonymous callbacks.
         
     | 
| 
      
 244 
     | 
    
         
            +
              # * If called with a function name and a block, then the RPC function on the other side is called and it is possible to call back to this dedicated block by invoking {Call#call_back} .
         
     | 
| 
       152 
245 
     | 
    
         
             
              #
         
     | 
| 
       153 
246 
     | 
    
         
             
              # @param func [String, Symbol]  The RPC function to be called on the other side.
         
     | 
| 
       154 
247 
     | 
    
         
             
              #   The other side must wait for calls through {#call} without arguments but with a block.
         
     | 
| 
         @@ -165,9 +258,9 @@ class RpcConnection 
     | 
|
| 
       165 
258 
     | 
    
         
             
              #   This type of answers can be enabled by +RpcConnection#new(lazy_answers: true)+
         
     | 
| 
       166 
259 
     | 
    
         
             
              #   The Promise object is returned as soon as the RPC call is sent and a callback receiver is registered, but before waiting for the corresponding answer.
         
     | 
| 
       167 
260 
     | 
    
         
             
              #   This way several calls can be send in parallel without using threads.
         
     | 
| 
       168 
     | 
    
         
            -
              #   As soon as  
     | 
| 
       169 
     | 
    
         
            -
              #    
     | 
| 
       170 
     | 
    
         
            -
              #   It is recommended to use Promise#itself to trigger waiting for call answers or callbacks (although any other method triggers waiting as well).
         
     | 
| 
      
 261 
     | 
    
         
            +
              #   As soon as any method is called on the Promise object, this method is blocked until the RPC answer was received.
         
     | 
| 
      
 262 
     | 
    
         
            +
              #   When the RPC answer has been received, the Promise object then behaves like an ordinary Hash object or +nil+ in case of connection end.
         
     | 
| 
      
 263 
     | 
    
         
            +
              #   It is recommended to use +Promise#itself+ to trigger explicit waiting for call answers or callbacks (although any other method triggers waiting as well).
         
     | 
| 
       171 
264 
     | 
    
         
             
              # @return [NilClass] Waiting for further answers was stopped gracefully by either returning +[hash, true]+ from the block or because the connection was closed.
         
     | 
| 
       172 
265 
     | 
    
         
             
              def call(func=nil, params={}, &block)
         
     | 
| 
       173 
266 
     | 
    
         
             
                call_intern(func, params, &block)
         
     | 
| 
         @@ -175,15 +268,16 @@ class RpcConnection 
     | 
|
| 
       175 
268 
     | 
    
         | 
| 
       176 
269 
     | 
    
         
             
              protected
         
     | 
| 
       177 
270 
     | 
    
         | 
| 
       178 
     | 
    
         
            -
              def  
     | 
| 
       179 
     | 
    
         
            -
                id  
     | 
| 
      
 271 
     | 
    
         
            +
              def register_call(func, id, &block)
         
     | 
| 
      
 272 
     | 
    
         
            +
                id ||= next_id if func
         
     | 
| 
       180 
273 
     | 
    
         | 
| 
       181 
274 
     | 
    
         
             
                @answers_mutex.synchronize do
         
     | 
| 
       182 
     | 
    
         
            -
                  @receivers[id] = CallbackReceiver.new(block_given? ? nil : caller[ 
     | 
| 
      
 275 
     | 
    
         
            +
                  @receivers[id] = CallbackReceiver.new(block_given? ? nil : caller[4], [])
         
     | 
| 
       183 
276 
     | 
    
         
             
                end
         
     | 
| 
      
 277 
     | 
    
         
            +
                id
         
     | 
| 
      
 278 
     | 
    
         
            +
              end
         
     | 
| 
       184 
279 
     | 
    
         | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
       186 
     | 
    
         
            -
             
     | 
| 
      
 280 
     | 
    
         
            +
              def wait_for_return(id, &block)
         
     | 
| 
       187 
281 
     | 
    
         
             
                maybe_lazy do
         
     | 
| 
       188 
282 
     | 
    
         
             
                  @answers_mutex.synchronize do
         
     | 
| 
       189 
283 
     | 
    
         
             
                    res = loop do
         
     | 
| 
         @@ -191,6 +285,7 @@ class RpcConnection 
     | 
|
| 
       191 
285 
     | 
    
         
             
                      if cb=@receivers[id].callbacks.shift
         
     | 
| 
       192 
286 
     | 
    
         
             
                        @answers_mutex.unlock
         
     | 
| 
       193 
287 
     | 
    
         
             
                        begin
         
     | 
| 
      
 288 
     | 
    
         
            +
                          # invoke the user block
         
     | 
| 
       194 
289 
     | 
    
         
             
                          rets, exit = yield(cb)
         
     | 
| 
       195 
290 
     | 
    
         
             
                          if rets
         
     | 
| 
       196 
291 
     | 
    
         
             
                            cb.answer = rets
         
     | 
| 
         @@ -229,47 +324,88 @@ class RpcConnection 
     | 
|
| 
       229 
324 
     | 
    
         
             
                end
         
     | 
| 
       230 
325 
     | 
    
         
             
              end
         
     | 
| 
       231 
326 
     | 
    
         | 
| 
      
 327 
     | 
    
         
            +
              def call_intern(func, params={}, recv_id=nil, &block)
         
     | 
| 
      
 328 
     | 
    
         
            +
                id = register_call(func, nil, &block)
         
     | 
| 
      
 329 
     | 
    
         
            +
                send_call(func, params, id, recv_id) if func
         
     | 
| 
      
 330 
     | 
    
         
            +
                wait_for_return(id, &block)
         
     | 
| 
      
 331 
     | 
    
         
            +
              end
         
     | 
| 
      
 332 
     | 
    
         
            +
             
     | 
| 
       232 
333 
     | 
    
         
             
              def next_id
         
     | 
| 
       233 
334 
     | 
    
         
             
                @id_mutex.synchronize do
         
     | 
| 
       234 
335 
     | 
    
         
             
                  @id = (@id + 1) & 0xffffffff
         
     | 
| 
       235 
336 
     | 
    
         
             
                end
         
     | 
| 
       236 
337 
     | 
    
         
             
              end
         
     | 
| 
       237 
338 
     | 
    
         | 
| 
       238 
     | 
    
         
            -
              def  
     | 
| 
      
 339 
     | 
    
         
            +
              def wait_for_proto_ack
         
     | 
| 
      
 340 
     | 
    
         
            +
                @proto_ack_mutex.synchronize do
         
     | 
| 
      
 341 
     | 
    
         
            +
                  if @write_binary.nil? # acknowledge text/binary mode
         
     | 
| 
      
 342 
     | 
    
         
            +
                    register_call("\r", 1)
         
     | 
| 
      
 343 
     | 
    
         
            +
                    @write_mutex.synchronize do
         
     | 
| 
      
 344 
     | 
    
         
            +
                      @write_io.write "\r\1\a1\n"
         
     | 
| 
      
 345 
     | 
    
         
            +
                      @write_io.flush
         
     | 
| 
      
 346 
     | 
    
         
            +
                    end
         
     | 
| 
      
 347 
     | 
    
         
            +
                    # wait until protocol is acknowledged
         
     | 
| 
      
 348 
     | 
    
         
            +
                    res = wait_for_return(1)
         
     | 
| 
      
 349 
     | 
    
         
            +
                    if res == {"O" => "K"}
         
     | 
| 
      
 350 
     | 
    
         
            +
                      @write_binary = true
         
     | 
| 
      
 351 
     | 
    
         
            +
                    else
         
     | 
| 
      
 352 
     | 
    
         
            +
                      @write_binary = false
         
     | 
| 
      
 353 
     | 
    
         
            +
                    end
         
     | 
| 
      
 354 
     | 
    
         
            +
                  end
         
     | 
| 
      
 355 
     | 
    
         
            +
                end
         
     | 
| 
      
 356 
     | 
    
         
            +
              end
         
     | 
| 
      
 357 
     | 
    
         
            +
             
     | 
| 
      
 358 
     | 
    
         
            +
              def send_call_or_answer(params)
         
     | 
| 
       239 
359 
     | 
    
         
             
                to_send = String.new
         
     | 
| 
       240 
360 
     | 
    
         
             
                @write_mutex.synchronize do
         
     | 
| 
       241 
361 
     | 
    
         
             
                  params.compact.each do |key, value|
         
     | 
| 
       242 
     | 
    
         
            -
                     
     | 
| 
       243 
     | 
    
         
            -
             
     | 
| 
      
 362 
     | 
    
         
            +
                    if @write_binary
         
     | 
| 
      
 363 
     | 
    
         
            +
                      k = key.to_s
         
     | 
| 
      
 364 
     | 
    
         
            +
                      v = value.to_s
         
     | 
| 
      
 365 
     | 
    
         
            +
                      to_send << [1, k.bytesize, v.bytesize, k, v].pack("CNNa*a*")
         
     | 
| 
      
 366 
     | 
    
         
            +
                    else
         
     | 
| 
      
 367 
     | 
    
         
            +
                      to_send << Escape.escape(key.to_s) << "\t" <<
         
     | 
| 
      
 368 
     | 
    
         
            +
                          Escape.escape(value.to_s) << "\n"
         
     | 
| 
      
 369 
     | 
    
         
            +
                    end
         
     | 
| 
       244 
370 
     | 
    
         
             
                    if to_send.bytesize > 9999
         
     | 
| 
       245 
371 
     | 
    
         
             
                      @write_io.write to_send
         
     | 
| 
       246 
372 
     | 
    
         
             
                      to_send = String.new
         
     | 
| 
       247 
373 
     | 
    
         
             
                    end
         
     | 
| 
       248 
374 
     | 
    
         
             
                  end
         
     | 
| 
       249 
     | 
    
         
            -
                  to_send 
     | 
| 
       250 
     | 
    
         
            -
                  to_send 
     | 
| 
       251 
     | 
    
         
            -
                  @write_io.write(to_send << "\n")
         
     | 
| 
      
 375 
     | 
    
         
            +
                  yield(to_send)
         
     | 
| 
      
 376 
     | 
    
         
            +
                  @write_io.write(to_send)
         
     | 
| 
       252 
377 
     | 
    
         
             
                  @write_io.flush
         
     | 
| 
       253 
378 
     | 
    
         
             
                end
         
     | 
| 
       254 
379 
     | 
    
         
             
                after_write
         
     | 
| 
       255 
380 
     | 
    
         
             
              end
         
     | 
| 
       256 
381 
     | 
    
         | 
| 
       257 
     | 
    
         
            -
              def  
     | 
| 
       258 
     | 
    
         
            -
                 
     | 
| 
       259 
     | 
    
         
            -
                 
     | 
| 
       260 
     | 
    
         
            -
                   
     | 
| 
       261 
     | 
    
         
            -
                     
     | 
| 
       262 
     | 
    
         
            -
             
     | 
| 
       263 
     | 
    
         
            -
             
     | 
| 
       264 
     | 
    
         
            -
             
     | 
| 
       265 
     | 
    
         
            -
                      to_send  
     | 
| 
      
 382 
     | 
    
         
            +
              def send_call(func, params, id, recv_id)
         
     | 
| 
      
 383 
     | 
    
         
            +
                wait_for_proto_ack unless recv_id
         
     | 
| 
      
 384 
     | 
    
         
            +
                send_call_or_answer(params) do |to_send|
         
     | 
| 
      
 385 
     | 
    
         
            +
                  if @write_binary
         
     | 
| 
      
 386 
     | 
    
         
            +
                    f = func.to_s
         
     | 
| 
      
 387 
     | 
    
         
            +
                    if recv_id
         
     | 
| 
      
 388 
     | 
    
         
            +
                      to_send << [3, id, recv_id, f.bytesize, f].pack("CNNNa*")
         
     | 
| 
      
 389 
     | 
    
         
            +
                    else
         
     | 
| 
      
 390 
     | 
    
         
            +
                      to_send << [2, id, f.bytesize, f].pack("CNNa*")
         
     | 
| 
       266 
391 
     | 
    
         
             
                    end
         
     | 
| 
      
 392 
     | 
    
         
            +
                  else
         
     | 
| 
      
 393 
     | 
    
         
            +
                    to_send << Escape.escape(func.to_s) << "\a#{id}"
         
     | 
| 
      
 394 
     | 
    
         
            +
                    to_send << "\a#{recv_id}" if recv_id
         
     | 
| 
      
 395 
     | 
    
         
            +
                    to_send << "\n"
         
     | 
| 
      
 396 
     | 
    
         
            +
                  end
         
     | 
| 
      
 397 
     | 
    
         
            +
                end
         
     | 
| 
      
 398 
     | 
    
         
            +
              end
         
     | 
| 
      
 399 
     | 
    
         
            +
             
     | 
| 
      
 400 
     | 
    
         
            +
              def send_answer(answer, id)
         
     | 
| 
      
 401 
     | 
    
         
            +
                send_call_or_answer(answer) do |to_send|
         
     | 
| 
      
 402 
     | 
    
         
            +
                  if @write_binary
         
     | 
| 
      
 403 
     | 
    
         
            +
                    to_send << [4, id].pack("CN")
         
     | 
| 
      
 404 
     | 
    
         
            +
                  else
         
     | 
| 
      
 405 
     | 
    
         
            +
                    to_send << "\a#{id}" if id
         
     | 
| 
      
 406 
     | 
    
         
            +
                    to_send << "\n"
         
     | 
| 
       267 
407 
     | 
    
         
             
                  end
         
     | 
| 
       268 
     | 
    
         
            -
                  to_send << "\a#{id}" if id
         
     | 
| 
       269 
     | 
    
         
            -
                  @write_io.write(to_send << "\n")
         
     | 
| 
       270 
     | 
    
         
            -
                  @write_io.flush
         
     | 
| 
       271 
408 
     | 
    
         
             
                end
         
     | 
| 
       272 
     | 
    
         
            -
                after_write
         
     | 
| 
       273 
409 
     | 
    
         
             
              end
         
     | 
| 
       274 
410 
     | 
    
         | 
| 
       275 
411 
     | 
    
         
             
              def receive_answers
         
     | 
| 
         @@ -278,27 +414,25 @@ class RpcConnection 
     | 
|
| 
       278 
414 
     | 
    
         
             
                  case l
         
     | 
| 
       279 
415 
     | 
    
         
             
                    when Exception
         
     | 
| 
       280 
416 
     | 
    
         
             
                      raise l
         
     | 
| 
       281 
     | 
    
         
            -
                    when /\A([^\t\a\n]+)\t(.*?)\r?\n\z/mn
         
     | 
| 
       282 
     | 
    
         
            -
                      # received key/value pair used for either callback parameters or return values
         
     | 
| 
       283 
     | 
    
         
            -
                      rets[Escape.unescape($1).force_encoding(Encoding::UTF_8)] ||= Escape.unescape($2.force_encoding(Encoding::UTF_8))
         
     | 
| 
       284 
417 
     | 
    
         | 
| 
       285 
     | 
    
         
            -
                    when  
     | 
| 
       286 
     | 
    
         
            -
                       
     | 
| 
       287 
     | 
    
         
            -
                      cbfunc, id, recv_id = $1, $2&.to_i, $3&.to_i
         
     | 
| 
      
 418 
     | 
    
         
            +
                    when Array
         
     | 
| 
      
 419 
     | 
    
         
            +
                      rets[l[0]] ||= l[1]
         
     | 
| 
       288 
420 
     | 
    
         | 
| 
       289 
     | 
    
         
            -
             
     | 
| 
      
 421 
     | 
    
         
            +
                    when ReceivedCallData
         
     | 
| 
      
 422 
     | 
    
         
            +
                      # received callback
         
     | 
| 
      
 423 
     | 
    
         
            +
                      callback = Call.new(self, l.cbfunc.to_sym, rets, l.id)
         
     | 
| 
       290 
424 
     | 
    
         | 
| 
       291 
425 
     | 
    
         
             
                      @answers_mutex.synchronize do
         
     | 
| 
       292 
     | 
    
         
            -
                        receiver = @receivers[recv_id]
         
     | 
| 
      
 426 
     | 
    
         
            +
                        receiver = @receivers[l.recv_id]
         
     | 
| 
       293 
427 
     | 
    
         | 
| 
       294 
428 
     | 
    
         
             
                        if !receiver
         
     | 
| 
       295 
     | 
    
         
            -
                          if recv_id
         
     | 
| 
       296 
     | 
    
         
            -
                            raise NoCallbackDefined, "call_back to #{cbfunc.inspect} was received, but corresponding call returned already"
         
     | 
| 
      
 429 
     | 
    
         
            +
                          if l.recv_id
         
     | 
| 
      
 430 
     | 
    
         
            +
                            raise NoCallbackDefined, "call_back to #{l.cbfunc.inspect} was received, but corresponding call returned already"
         
     | 
| 
       297 
431 
     | 
    
         
             
                          else
         
     | 
| 
       298 
     | 
    
         
            -
                            raise NoCallbackDefined, "call to #{cbfunc.inspect} was received, but there is no #{self.class}#call running"
         
     | 
| 
      
 432 
     | 
    
         
            +
                            raise NoCallbackDefined, "call to #{l.cbfunc.inspect} was received, but there is no #{self.class}#call running"
         
     | 
| 
       299 
433 
     | 
    
         
             
                          end
         
     | 
| 
       300 
434 
     | 
    
         
             
                        elsif meth=receiver.meth
         
     | 
| 
       301 
     | 
    
         
            -
                          raise NoCallbackDefined, "call_back to #{cbfunc.inspect} was received, but corresponding call was called without a block in #{meth}"
         
     | 
| 
      
 435 
     | 
    
         
            +
                          raise NoCallbackDefined, "call_back to #{l.cbfunc.inspect} was received, but corresponding call was called without a block in #{meth}"
         
     | 
| 
       302 
436 
     | 
    
         
             
                        end
         
     | 
| 
       303 
437 
     | 
    
         | 
| 
       304 
438 
     | 
    
         
             
                        receiver.callbacks << callback
         
     | 
| 
         @@ -306,9 +440,10 @@ class RpcConnection 
     | 
|
| 
       306 
440 
     | 
    
         
             
                      end
         
     | 
| 
       307 
441 
     | 
    
         
             
                      return
         
     | 
| 
       308 
442 
     | 
    
         | 
| 
       309 
     | 
    
         
            -
                    when  
     | 
| 
      
 443 
     | 
    
         
            +
                    when Integer
         
     | 
| 
       310 
444 
     | 
    
         
             
                      # received return event
         
     | 
| 
       311 
     | 
    
         
            -
                      id =  
     | 
| 
      
 445 
     | 
    
         
            +
                      id = l
         
     | 
| 
      
 446 
     | 
    
         
            +
             
     | 
| 
       312 
447 
     | 
    
         
             
                      @answers_mutex.synchronize do
         
     | 
| 
       313 
448 
     | 
    
         
             
                        @answers[id] = rets
         
     | 
| 
       314 
449 
     | 
    
         
             
                        @new_answer.broadcast
         
     | 
    
        data/lib/ccrpc/version.rb
    CHANGED
    
    
    
        data.tar.gz.sig
    CHANGED
    
    | 
         Binary file 
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,37 +1,38 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: ccrpc
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.5.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Lars Kanis
         
     | 
| 
       8 
     | 
    
         
            -
            autorequire:
         
     | 
| 
       9 
8 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
9 
     | 
    
         
             
            cert_chain:
         
     | 
| 
       11 
10 
     | 
    
         
             
            - |
         
     | 
| 
       12 
11 
     | 
    
         
             
              -----BEGIN CERTIFICATE-----
         
     | 
| 
       13 
     | 
    
         
            -
               
     | 
| 
       14 
     | 
    
         
            -
               
     | 
| 
       15 
     | 
    
         
            -
               
     | 
| 
       16 
     | 
    
         
            -
               
     | 
| 
       17 
     | 
    
         
            -
               
     | 
| 
       18 
     | 
    
         
            -
               
     | 
| 
       19 
     | 
    
         
            -
               
     | 
| 
       20 
     | 
    
         
            -
               
     | 
| 
       21 
     | 
    
         
            -
               
     | 
| 
       22 
     | 
    
         
            -
               
     | 
| 
       23 
     | 
    
         
            -
               
     | 
| 
       24 
     | 
    
         
            -
               
     | 
| 
       25 
     | 
    
         
            -
               
     | 
| 
       26 
     | 
    
         
            -
               
     | 
| 
       27 
     | 
    
         
            -
               
     | 
| 
       28 
     | 
    
         
            -
               
     | 
| 
       29 
     | 
    
         
            -
               
     | 
| 
       30 
     | 
    
         
            -
               
     | 
| 
       31 
     | 
    
         
            -
               
     | 
| 
       32 
     | 
    
         
            -
               
     | 
| 
      
 12 
     | 
    
         
            +
              MIIEBDCCAmygAwIBAgIBAzANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB1sYXJz
         
     | 
| 
      
 13 
     | 
    
         
            +
              L0RDPWdyZWl6LXJlaW5zZG9yZi9EQz1kZTAeFw0yNDEyMjkxOTU2NTZaFw0yNTEy
         
     | 
| 
      
 14 
     | 
    
         
            +
              MjkxOTU2NTZaMCgxJjAkBgNVBAMMHWxhcnMvREM9Z3JlaXotcmVpbnNkb3JmL0RD
         
     | 
| 
      
 15 
     | 
    
         
            +
              PWRlMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwum6Y1KznfpzXOT/
         
     | 
| 
      
 16 
     | 
    
         
            +
              mZgJTBbxZuuZF49Fq3K0WA67YBzNlDv95qzSp7V/7Ek3NCcnT7G+2kSuhNo1FhdN
         
     | 
| 
      
 17 
     | 
    
         
            +
              eSDO/moYebZNAcu3iqLsuzuULXPLuoU0GsMnVMqV9DZPh7cQHE5EBZ7hlzDBK7k/
         
     | 
| 
      
 18 
     | 
    
         
            +
              8nBMvR0mHo77kIkapHc26UzVq/G0nKLfDsIHXVylto3PjzOumjG6GhmFN4r3cP6e
         
     | 
| 
      
 19 
     | 
    
         
            +
              SDfl1FSeRYVpt4kmQULz/zdSaOH3AjAq7PM2Z91iGwQvoUXMANH2v89OWjQO/NHe
         
     | 
| 
      
 20 
     | 
    
         
            +
              JMNDFsmHK/6Ji4Kk48Z3TyscHQnipAID5GhS1oD21/WePdj7GhmbF5gBzkV5uepd
         
     | 
| 
      
 21 
     | 
    
         
            +
              eJQPgWGwrQW/Z2oPjRuJrRofzWfrMWqbOahj9uth6WSxhNexUtbjk6P8emmXOJi5
         
     | 
| 
      
 22 
     | 
    
         
            +
              chQPnWX+N3Gj+jjYxqTFdwT7Mj3pv1VHa+aNUbqSPpvJeDyxRIuo9hvzDaBHb/Cg
         
     | 
| 
      
 23 
     | 
    
         
            +
              9qRVcm8a96n4t7y2lrX1oookY6bkBaxWOMtWlqIprq8JZXM9AgMBAAGjOTA3MAkG
         
     | 
| 
      
 24 
     | 
    
         
            +
              A1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQ4h1tIyvdUWtMI739xMzTR
         
     | 
| 
      
 25 
     | 
    
         
            +
              7EfMFzANBgkqhkiG9w0BAQsFAAOCAYEAoZZWzNV2XXaoSmvyamSSN+Wt/Ia+DNrU
         
     | 
| 
      
 26 
     | 
    
         
            +
              2pc3kMEqykH6l1WiVPszr6HavQ//2I2UcSRSS5AGDdiSXcfyFmHtMBdtJHhTPcn7
         
     | 
| 
      
 27 
     | 
    
         
            +
              4DLliB0szpvwG+ltGD8PI8eWkLaTQeFzs+0QCTavgKV+Zw56Q0J5zZvHHUMrLkUD
         
     | 
| 
      
 28 
     | 
    
         
            +
              qhwKjdTdkrRTn9Sqi0BrIRRZGTUDdrt8qoWm35aES5arKZzytgrRD/kXfFW2LCg0
         
     | 
| 
      
 29 
     | 
    
         
            +
              FzgTKibR4/3g8ph94kQLg/D2SMlVPkQ3ECi036mZxDC2n8V6u3rDkG5923wmrRZB
         
     | 
| 
      
 30 
     | 
    
         
            +
              J6cqz475Q8HYORQCB68OPzkWMfC7mBo3vpSsIqRoNs1FE4FJu4FGwZG8fBSrDC4H
         
     | 
| 
      
 31 
     | 
    
         
            +
              bZe+GtyS3e2SMjgT65zp35gLO9I7MquzYN9P6V2u1iBpTycchk5z9R1ghxzZSBT8
         
     | 
| 
      
 32 
     | 
    
         
            +
              DrkJ9tVlPQtJB0LqT0tvBap4upnwT1xYq721b5dwH6AF4Pi6iz/dc5vnq1/MH8bV
         
     | 
| 
      
 33 
     | 
    
         
            +
              8VbbBzzeE7MsvgkP3sHlLmY8PtuyViJ8
         
     | 
| 
       33 
34 
     | 
    
         
             
              -----END CERTIFICATE-----
         
     | 
| 
       34 
     | 
    
         
            -
            date:  
     | 
| 
      
 35 
     | 
    
         
            +
            date: 1980-01-02 00:00:00.000000000 Z
         
     | 
| 
       35 
36 
     | 
    
         
             
            dependencies: []
         
     | 
| 
       36 
37 
     | 
    
         
             
            description: Simple bidirectional and thread safe RPC protocol. Works on arbitrary
         
     | 
| 
       37 
38 
     | 
    
         
             
              Ruby IO objects.
         
     | 
| 
         @@ -63,7 +64,6 @@ licenses: 
     | 
|
| 
       63 
64 
     | 
    
         
             
            metadata:
         
     | 
| 
       64 
65 
     | 
    
         
             
              homepage_uri: https://github.com/larskanis/ccrpc
         
     | 
| 
       65 
66 
     | 
    
         
             
              documentation_uri: https://rubydoc.info/gems/ccrpc
         
     | 
| 
       66 
     | 
    
         
            -
            post_install_message:
         
     | 
| 
       67 
67 
     | 
    
         
             
            rdoc_options: []
         
     | 
| 
       68 
68 
     | 
    
         
             
            require_paths:
         
     | 
| 
       69 
69 
     | 
    
         
             
            - lib
         
     | 
| 
         @@ -78,8 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       78 
78 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       79 
79 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       80 
80 
     | 
    
         
             
            requirements: []
         
     | 
| 
       81 
     | 
    
         
            -
            rubygems_version: 3. 
     | 
| 
       82 
     | 
    
         
            -
            signing_key:
         
     | 
| 
      
 81 
     | 
    
         
            +
            rubygems_version: 3.6.9
         
     | 
| 
       83 
82 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       84 
83 
     | 
    
         
             
            summary: Simple bidirectional RPC protocol
         
     | 
| 
       85 
84 
     | 
    
         
             
            test_files: []
         
     | 
    
        metadata.gz.sig
    CHANGED
    
    | 
         Binary file 
     |