rethinkdb 2.2.0.4 → 2.3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|