rethinkdb 2.2.0.4 → 2.3.0.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
- data/lib/exc.rb +14 -13
- data/lib/func.rb +2 -0
- data/lib/net.rb +201 -26
- data/lib/ql2.pb.rb +4 -0
- data/lib/shim.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3cc46a96063b3b943304398afd307176d3847889
|
4
|
+
data.tar.gz: e0f277c7d8ca4c0d7ac3405cad9c2fadb65d2026
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c6fbddd6d2063eab25468fcedcab36c97f06fbca90bb8eaf55b5d0f22fcd99e36f6dc658e42963226c073696a066b7392b93717b5e82a0de3c08a707af41282
|
7
|
+
data.tar.gz: 6827ef687ed5a9e09c61320a4bf6f77918403a155890c475f9d34279a8f455697fdce4069c69f3c4c4f0bd35d44974f9514607e799be2fbe7dc8f718d74f7447
|
data/lib/exc.rb
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
module RethinkDB
|
2
|
-
|
2
|
+
RqlError = ReqlError = Class.new(RuntimeError)
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
RqlRuntimeError = ReqlRuntimeError = Class.new(ReqlError)
|
5
|
+
RqlInternalError = ReqlInternalError = Class.new(ReqlRuntimeError)
|
6
|
+
RqlResourceLimitError = ReqlResourceLimitError = Class.new(ReqlRuntimeError)
|
7
|
+
RqlQueryLogicError = ReqlQueryLogicError = Class.new(ReqlRuntimeError)
|
8
|
+
RqlNonExistenceError = ReqlNonExistenceError = Class.new(ReqlQueryLogicError)
|
9
|
+
RqlAvailabilityError = ReqlAvailabilityError = Class.new(ReqlRuntimeError)
|
10
|
+
RqlOpFailedError = ReqlOpFailedError = Class.new(ReqlAvailabilityError)
|
11
|
+
RqlOpIndeterminateError = ReqlOpIndeterminateError = Class.new(ReqlAvailabilityError)
|
12
|
+
RqlUserError = ReqlUserError = Class.new(ReqlRuntimeError)
|
13
|
+
ReqlPermissionError = Class.new(ReqlRuntimeError)
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
RqlDriverError = ReqlDriverError = Class.new(ReqlError)
|
16
|
+
RqlAuthError = ReqlAuthError = Class.new(ReqlDriverError)
|
17
|
+
RqlCompileError = ReqlCompileError = Class.new(ReqlError)
|
17
18
|
ReqlServerCompileError = Class.new(ReqlCompileError)
|
18
19
|
ReqlDriverCompileError = Class.new(ReqlCompileError)
|
19
20
|
end
|
data/lib/func.rb
CHANGED
@@ -22,6 +22,7 @@ module RethinkDB
|
|
22
22
|
:insert => 1,
|
23
23
|
:delete => -1,
|
24
24
|
:reduce => -1,
|
25
|
+
:fold => -1,
|
25
26
|
:between => 2,
|
26
27
|
:table => -1,
|
27
28
|
:table_create => -1,
|
@@ -34,6 +35,7 @@ module RethinkDB
|
|
34
35
|
:during => -1,
|
35
36
|
:orderby => -1,
|
36
37
|
:order_by => -1,
|
38
|
+
:union => -1,
|
37
39
|
:group => -1,
|
38
40
|
:iso8601 => -1,
|
39
41
|
:index_create => -1,
|
data/lib/net.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'openssl'
|
1
3
|
require 'monitor'
|
4
|
+
require 'pp' # This is needed for pretty_inspect
|
2
5
|
require 'set'
|
6
|
+
require 'securerandom'
|
3
7
|
require 'socket'
|
4
8
|
require 'thread'
|
5
9
|
require 'timeout'
|
6
|
-
require 'pp' # This is needed for pretty_inspect
|
7
|
-
require 'openssl'
|
8
10
|
|
9
11
|
module RethinkDB
|
10
12
|
module Faux_Abort
|
@@ -456,6 +458,7 @@ module RethinkDB
|
|
456
458
|
|
457
459
|
class Connection
|
458
460
|
include OpenSSL
|
461
|
+
|
459
462
|
def auto_reconnect(x=true)
|
460
463
|
@auto_reconnect = x
|
461
464
|
self
|
@@ -474,7 +477,13 @@ module RethinkDB
|
|
474
477
|
@host = opts[:host] || "localhost"
|
475
478
|
@port = (opts[:port] || 28015).to_i
|
476
479
|
@default_db = opts[:db]
|
477
|
-
@
|
480
|
+
@user = opts[:user] || "admin"
|
481
|
+
@user = @user.gsub("=", "=3D").gsub(",","=2C")
|
482
|
+
if opts[:password] && opts[:auth_key]
|
483
|
+
raise ReqlDriverError, "Cannot specify both a password and an auth key."
|
484
|
+
end
|
485
|
+
@password = opts[:password] || opts[:auth_key] || ""
|
486
|
+
@nonce = SecureRandom.base64(18)
|
478
487
|
@timeout = opts[:timeout].to_i
|
479
488
|
@timeout = 20 if @timeout <= 0
|
480
489
|
@ssl_opts = opts[:ssl] || {}
|
@@ -490,6 +499,13 @@ module RethinkDB
|
|
490
499
|
end
|
491
500
|
attr_reader :host, :port, :default_db, :conn_id
|
492
501
|
|
502
|
+
def client_port
|
503
|
+
is_open() ? @socket.addr[1] : nil
|
504
|
+
end
|
505
|
+
def client_address
|
506
|
+
is_open() ? @socket.addr[3] : nil
|
507
|
+
end
|
508
|
+
|
493
509
|
def new_token
|
494
510
|
@token_cnt_mutex.synchronize{@token_cnt += 1}
|
495
511
|
end
|
@@ -576,10 +592,11 @@ module RethinkDB
|
|
576
592
|
@mon.synchronize {
|
577
593
|
written = 0
|
578
594
|
while written < packet.length
|
579
|
-
# Supposedly slice will not copy the array if it goes all
|
580
|
-
# We use IO::syswrite here rather than
|
581
|
-
#
|
582
|
-
# Reference:
|
595
|
+
# Supposedly slice will not copy the array if it goes all
|
596
|
+
# the way to the end We use IO::syswrite here rather than
|
597
|
+
# IO::write because of incompatibilities in JRuby regarding
|
598
|
+
# filling up the TCP send buffer. Reference:
|
599
|
+
# https://github.com/rethinkdb/rethinkdb/issues/3795
|
583
600
|
written += @socket.syswrite(packet.slice(written, packet.length))
|
584
601
|
end
|
585
602
|
}
|
@@ -645,7 +662,8 @@ module RethinkDB
|
|
645
662
|
end
|
646
663
|
|
647
664
|
@@last = nil
|
648
|
-
@@magic_number = VersionDummy::Version::
|
665
|
+
@@magic_number = VersionDummy::Version::V1_0
|
666
|
+
@@protocol_version = 0
|
649
667
|
@@wire_protocol = VersionDummy::Protocol::JSON
|
650
668
|
|
651
669
|
def debug_socket; @socket; end
|
@@ -814,6 +832,180 @@ module RethinkDB
|
|
814
832
|
note_data(token, data)
|
815
833
|
end
|
816
834
|
|
835
|
+
def rcv_json
|
836
|
+
response = ""
|
837
|
+
while response[-1..-1] != "\0"
|
838
|
+
response += @socket.read_exn(1, @timeout)
|
839
|
+
end
|
840
|
+
begin
|
841
|
+
res = JSON.parse(response[0...-1])
|
842
|
+
if !res['success']
|
843
|
+
msg = "Handshake error (#{res})."
|
844
|
+
ecode = res['error_code']
|
845
|
+
if ecode && ecode >= 10 && ecode <= 20
|
846
|
+
msg = res['error'] if res['error'].to_s != ""
|
847
|
+
raise ReqlAuthError, msg
|
848
|
+
else
|
849
|
+
raise ReqlDriverError, msg
|
850
|
+
end
|
851
|
+
end
|
852
|
+
rescue Exception => e
|
853
|
+
if !e.class.ancestors.include?(ReqlDriverError)
|
854
|
+
raise ReqlDriverError, "Connection closed by server (#{e})."
|
855
|
+
else
|
856
|
+
raise e
|
857
|
+
end
|
858
|
+
end
|
859
|
+
return res
|
860
|
+
end
|
861
|
+
|
862
|
+
def send_json(x)
|
863
|
+
send(x.to_json + "\0")
|
864
|
+
end
|
865
|
+
|
866
|
+
def check_version(server_info)
|
867
|
+
if server_info['min_protocol_version'] > @@protocol_version ||
|
868
|
+
server_info['max_protocol_version'] < @@protocol_version
|
869
|
+
raise ReqlDriverError, "Version mismatch: Driver uses #{@@protocol_version} "+
|
870
|
+
"but server accepts "+
|
871
|
+
"[#{server_info['min_version']}, #{server_info['max_version']}]."
|
872
|
+
end
|
873
|
+
end
|
874
|
+
|
875
|
+
def check_nonce(server_nonce, nonce)
|
876
|
+
if !server_nonce.start_with?(nonce)
|
877
|
+
raise ReqlDriverError, "Invalid nonce #{server_nonce} received from server."
|
878
|
+
end
|
879
|
+
end
|
880
|
+
|
881
|
+
@@fast_auth_func = lambda {|*args|
|
882
|
+
digest = OpenSSL::Digest::SHA256.new
|
883
|
+
OpenSSL::PKCS5.pbkdf2_hmac(*args, digest.digest_length, digest)
|
884
|
+
}
|
885
|
+
@@slow_auth_func = lambda {|password, salt, iter|
|
886
|
+
mac = OpenSSL::HMAC.new(password, OpenSSL::Digest::SHA256.new)
|
887
|
+
acc = t = mac.update(salt + "\0\0\0\1").digest
|
888
|
+
mac.reset
|
889
|
+
(iter-1).times{acc = xor(acc, t = mac.update(t).digest); mac.reset}
|
890
|
+
res = acc
|
891
|
+
}
|
892
|
+
@@auth_func = @@fast_auth_func
|
893
|
+
@@auth_func_mutex = Mutex.new
|
894
|
+
|
895
|
+
@@auth_cache = {}
|
896
|
+
@@auth_cache_mutex = Mutex.new
|
897
|
+
|
898
|
+
def pbkdf2_hmac_sha256(*args)
|
899
|
+
auth_func = res = nil
|
900
|
+
@@auth_cache_mutex.synchronize {
|
901
|
+
res = @@auth_cache[args]
|
902
|
+
return res if res
|
903
|
+
}
|
904
|
+
|
905
|
+
@@auth_func_mutex.synchronize {
|
906
|
+
auth_func = @@auth_func
|
907
|
+
}
|
908
|
+
begin
|
909
|
+
res = auth_func.call(*args)
|
910
|
+
rescue NotImplementedError => e
|
911
|
+
if auth_func != @@slow_auth_func
|
912
|
+
@@auth_func_mutex.synchronize {
|
913
|
+
auth_func = @@auth_func = @@slow_auth_func
|
914
|
+
}
|
915
|
+
res = auth_func.call(*args)
|
916
|
+
else
|
917
|
+
raise e
|
918
|
+
end
|
919
|
+
end
|
920
|
+
|
921
|
+
@@auth_cache_mutex.synchronize {
|
922
|
+
@@auth_cache[args] = res
|
923
|
+
}
|
924
|
+
return res
|
925
|
+
end
|
926
|
+
|
927
|
+
def hmac(*args)
|
928
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, *args)
|
929
|
+
end
|
930
|
+
|
931
|
+
def sha256(str)
|
932
|
+
OpenSSL::Digest.digest("SHA256", str)
|
933
|
+
end
|
934
|
+
|
935
|
+
def self.xor(str1, str2)
|
936
|
+
out = str1.dup
|
937
|
+
out.bytesize.times {|i|
|
938
|
+
out.setbyte(i, out.getbyte(i) ^ str2.getbyte(i))
|
939
|
+
}
|
940
|
+
return out
|
941
|
+
end
|
942
|
+
|
943
|
+
def const_eq(a, b)
|
944
|
+
return false if a.size != b.size
|
945
|
+
residue = 0
|
946
|
+
a.unpack('C*').zip(b.unpack('C*')).each{|x,y|
|
947
|
+
residue |= (x ^ y)
|
948
|
+
}
|
949
|
+
return residue == 0
|
950
|
+
end
|
951
|
+
|
952
|
+
def check_server_signature_claim(server_signature_claim, server_signature)
|
953
|
+
if !const_eq(server_signature_claim, server_signature)
|
954
|
+
sig1 = Base64.strict_encode64(server_signature_claim)
|
955
|
+
sig2 = Base64.strict_encode64(server_signature)
|
956
|
+
raise ReqlAuthError, "Server signature #{sig1} does "+
|
957
|
+
"not match expected signature #{sig2}."
|
958
|
+
end
|
959
|
+
end
|
960
|
+
|
961
|
+
def do_handshake
|
962
|
+
begin
|
963
|
+
send([@@magic_number].pack('L<'))
|
964
|
+
client_first_message_bare = "n=#{@user},r=#{@nonce}"
|
965
|
+
send_json({ protocol_version: @@protocol_version,
|
966
|
+
authentication_method: "SCRAM-SHA-256",
|
967
|
+
authentication: "n,,#{client_first_message_bare}" })
|
968
|
+
|
969
|
+
server_version_msg = rcv_json
|
970
|
+
check_version(server_version_msg)
|
971
|
+
|
972
|
+
auth_resp = rcv_json
|
973
|
+
server_first_message = auth_resp['authentication']
|
974
|
+
|
975
|
+
fields = Hash[server_first_message.split(',').map{|x| x.split('=', 2)}]
|
976
|
+
server_nonce = fields['r']
|
977
|
+
|
978
|
+
client_final_message_without_proof = "c=biws,r=#{server_nonce}"
|
979
|
+
auth_message = "#{client_first_message_bare},#{server_first_message},"+
|
980
|
+
client_final_message_without_proof
|
981
|
+
check_nonce(server_nonce, @nonce)
|
982
|
+
salt = Base64.decode64(fields['s'])
|
983
|
+
iter = fields['i'].to_i
|
984
|
+
|
985
|
+
salted_password = pbkdf2_hmac_sha256(@password, salt, iter)
|
986
|
+
|
987
|
+
client_key = hmac(salted_password, "Client Key")
|
988
|
+
stored_key = sha256(client_key)
|
989
|
+
client_signature = hmac(stored_key, auth_message)
|
990
|
+
client_proof = Connection::xor(client_key, client_signature)
|
991
|
+
cproof_64 = Base64.strict_encode64(client_proof)
|
992
|
+
|
993
|
+
msg = "#{client_final_message_without_proof},p=#{cproof_64}"
|
994
|
+
send_json({authentication: msg})
|
995
|
+
|
996
|
+
sig_resp = rcv_json
|
997
|
+
fields = Hash[sig_resp['authentication'].split(',').map{|x| x.split('=', 2)}]
|
998
|
+
server_signature_claim = Base64::decode64(fields['v'])
|
999
|
+
server_key = hmac(salted_password, "Server Key")
|
1000
|
+
server_signature = hmac(server_key, auth_message)
|
1001
|
+
check_server_signature_claim(server_signature_claim, server_signature)
|
1002
|
+
rescue ReqlError => e
|
1003
|
+
raise e
|
1004
|
+
rescue Exception => e
|
1005
|
+
raise ReqlDriverError, "Error during handshake: #{e.inspect} #{e.backtrace}"
|
1006
|
+
end
|
1007
|
+
end
|
1008
|
+
|
817
1009
|
def start_listener
|
818
1010
|
class << @socket
|
819
1011
|
def maybe_timeout(sec=nil, &b)
|
@@ -829,24 +1021,7 @@ module RethinkDB
|
|
829
1021
|
}
|
830
1022
|
end
|
831
1023
|
end
|
832
|
-
|
833
|
-
@auth_key + [@@wire_protocol].pack('L<'))
|
834
|
-
response = ""
|
835
|
-
while response[-1..-1] != "\0"
|
836
|
-
response += @socket.read_exn(1, @timeout)
|
837
|
-
end
|
838
|
-
response = response[0...-1]
|
839
|
-
if response == "SUCCESS"
|
840
|
-
# do nothing
|
841
|
-
elsif response == "ERROR: Incorrect authorization key.\n"
|
842
|
-
raise ReqlAuthError, "Incorrect authorization key."
|
843
|
-
else
|
844
|
-
raise ReqlRuntimeError, "Server dropped connection with message: \"#{response}\""
|
845
|
-
end
|
846
|
-
|
847
|
-
if @listener
|
848
|
-
raise ReqlDriverError, "Internal driver error, listener already started."
|
849
|
-
end
|
1024
|
+
do_handshake
|
850
1025
|
@listener = Thread.new {
|
851
1026
|
while true
|
852
1027
|
begin
|
data/lib/ql2.pb.rb
CHANGED
@@ -8,6 +8,7 @@ module RethinkDB
|
|
8
8
|
V0_2 = 1915781601
|
9
9
|
V0_3 = 1601562686
|
10
10
|
V0_4 = 1074539808
|
11
|
+
V1_0 = 885177795
|
11
12
|
end
|
12
13
|
|
13
14
|
module Protocol
|
@@ -59,6 +60,7 @@ module RethinkDB
|
|
59
60
|
OP_FAILED = 4100000
|
60
61
|
OP_INDETERMINATE = 4200000
|
61
62
|
USER = 5000000
|
63
|
+
PERMISSION_ERROR = 6000000
|
62
64
|
end
|
63
65
|
|
64
66
|
module ResponseNote
|
@@ -140,6 +142,7 @@ module RethinkDB
|
|
140
142
|
BETWEEN = 182
|
141
143
|
REDUCE = 37
|
142
144
|
MAP = 38
|
145
|
+
FOLD = 187
|
143
146
|
FILTER = 39
|
144
147
|
CONCAT_MAP = 40
|
145
148
|
ORDER_BY = 41
|
@@ -176,6 +179,7 @@ module RethinkDB
|
|
176
179
|
RECONFIGURE = 176
|
177
180
|
REBALANCE = 179
|
178
181
|
SYNC = 138
|
182
|
+
GRANT = 188
|
179
183
|
INDEX_CREATE = 75
|
180
184
|
INDEX_DROP = 76
|
181
185
|
INDEX_LIST = 77
|
data/lib/shim.rb
CHANGED
@@ -72,6 +72,7 @@ module RethinkDB
|
|
72
72
|
when re::OP_FAILED then raise ReqlOpFailedError, r['r'][0]
|
73
73
|
when re::OP_INDETERMINATE then raise ReqlOpIndeterminateError, r['r'][0]
|
74
74
|
when re::USER then raise ReqlUserError, r['r'][0]
|
75
|
+
when re::PERMISSION_ERROR then raise ReqlPermissionError, r['r'][0]
|
75
76
|
else raise ReqlRuntimeError, r['r'][0]
|
76
77
|
end
|
77
78
|
when rt::COMPILE_ERROR then raise ReqlServerCompileError, r['r'][0]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rethinkdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- RethinkDB Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|