neo4j_bolt 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb231b117247cda9063d3d8c7ee9922ebef33a345291a8ea7261ec51a903fe4f
4
- data.tar.gz: f269e02fe8e439f404d211767224866a9d623356c893befa682d19eee31030fe
3
+ metadata.gz: 316d22f20084bb29755e8693c25860bd4d3afa5e5aadce5b89e415bf53157b82
4
+ data.tar.gz: 405c68b29be5578f7859cdc973b956ccb9898a4b7d105cc19b0e31e81c5615b3
5
5
  SHA512:
6
- metadata.gz: dd7b2031de0005b704fef01043f9ca393df3f8d4a79b07d879d348a17cc9b3eeb018b2282f25a31a9e0c691e47280fadde04bc21fc3390253c3f092d16807a2c
7
- data.tar.gz: 698bbc17d5acd365458ada7feea3d802def624bc2052652f34c1c13e75d6d8b3ebd67b20210ce9300b5d0d8aa278f66f0bc514710f5f52119d2ad9db2e8aa5b5
6
+ metadata.gz: 94766bfe86f3487582229ed0d11fa4c2bc813adac23fe1065c5dc026c692e3b82c859978b08d5dfb78915382d224425b7e7f81eb06f620eebb23014d8e4934b9
7
+ data.tar.gz: e144730f9cb75b44450c0dfb3b56d76698c9839e1f54a375c4e7608cb6eb7d6cf70d1544a7065a78d08c4d813387da66ec758bc1749d24037899233c80feb3d7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- neo4j_bolt (0.2.1)
4
+ neo4j_bolt (0.3.0)
5
5
  gli
6
6
  pry
7
7
 
@@ -1,3 +1,3 @@
1
1
  module Neo4jBolt
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/neo4j_bolt.rb CHANGED
@@ -15,15 +15,16 @@ module Neo4jBolt
15
15
  CONSTRAINT_INDEX_PREFIX = 'neo4j_bolt_'
16
16
 
17
17
  module ServerState
18
- DISCONNECTED = 0
19
- CONNECTED = 1
20
- DEFUNCT = 2
21
- READY = 3
22
- STREAMING = 4
23
- TX_READY = 5
24
- TX_STREAMING = 6
25
- FAILED = 7
26
- INTERRUPTED = 8
18
+ DISCONNECTED = 0
19
+ CONNECTED = 1
20
+ DEFUNCT = 2
21
+ READY = 3
22
+ STREAMING = 4
23
+ TX_READY = 5
24
+ TX_STREAMING = 6
25
+ FAILED = 7
26
+ INTERRUPTED = 8
27
+ AUTHENTICATION = 10
27
28
  end
28
29
  SERVER_STATE_LABELS = Hash[ServerState::constants.map { |value| [ServerState::const_get(value), value] }]
29
30
 
@@ -39,6 +40,7 @@ module Neo4jBolt
39
40
  BOLT_PULL = 0x3F
40
41
  BOLT_NODE = 0x4E
41
42
  BOLT_RELATIONSHIP = 0x52
43
+ BOLT_LOGON = 0x6A
42
44
  BOLT_SUCCESS = 0x70
43
45
  BOLT_RECORD = 0x71
44
46
  BOLT_IGNORED = 0x7E
@@ -301,7 +303,7 @@ module Neo4jBolt
301
303
  end
302
304
 
303
305
  def append_token(i)
304
- # STDERR.puts BOLT_MARKER_LABELS[i]
306
+ # STDERR.puts "Appending token: [#{BOLT_MARKER_LABELS[i]}]"
305
307
  append_uint8(i)
306
308
  end
307
309
 
@@ -335,6 +337,7 @@ module Neo4jBolt
335
337
 
336
338
  def append_s(s)
337
339
  s = s.to_s
340
+ # STDERR.puts "Appending string: [#{s}]"
338
341
  if s.bytesize < 16
339
342
  append_uint8(0x80 + s.bytesize)
340
343
  elsif s.bytesize < 0x100
@@ -398,6 +401,7 @@ module Neo4jBolt
398
401
  end
399
402
 
400
403
  def append_dict(d)
404
+ # STDERR.puts "Appending dict: [#{d.to_json}]"
401
405
  if d.size < 16
402
406
  append_uint8(0xA0 + d.size)
403
407
  elsif d.size < 0x100
@@ -439,6 +443,35 @@ module Neo4jBolt
439
443
  end
440
444
 
441
445
  def flush()
446
+ # STDERR.puts "Flushing buffer with #{@buffer.size} bytes..."
447
+
448
+ # offset = 0
449
+ # last_offset = 0
450
+ # while offset < @buffer.size
451
+ # if offset % 16 == 0
452
+ # STDERR.write sprintf('%04x | ', offset)
453
+ # end
454
+ # STDERR.write sprintf("%02x ", @buffer[offset])
455
+ # offset += 1
456
+ # if offset % 16 == 0
457
+ # STDERR.write ' ' * 4
458
+ # (last_offset...offset).each do |i|
459
+ # b = @buffer[i]
460
+ # STDERR.write (b >= 32 && b < 128) ? b.chr : '.'
461
+ # end
462
+ # STDERR.puts
463
+ # last_offset = offset
464
+ # end
465
+ # end
466
+ # (16 - offset + last_offset).times { STDERR.write ' ' }
467
+ # STDERR.write ' ' * 4
468
+ # (last_offset...offset).each do |i|
469
+ # b = @buffer[i]
470
+ # STDERR.write (b >= 32 && b < 128) ? b.chr : '.'
471
+ # end
472
+ # STDERR.puts
473
+
474
+
442
475
  size = @buffer.size
443
476
  offset = 0
444
477
  while size > 0
@@ -602,12 +635,16 @@ module Neo4jBolt
602
635
 
603
636
  def read_response(&block)
604
637
  loop do
638
+ # STDERR.puts "Reading response:"
605
639
  buffer = BoltBuffer.new(@socket)
640
+ # buffer.dump
606
641
  response_dict = parse(buffer)
607
642
  buffer.flush()
643
+ # STDERR.puts "Response marker: #{BOLT_MARKER_LABELS[response_dict[:marker]]}"
644
+ # STDERR.puts response_dict.to_yaml
608
645
  if response_dict[:marker] == BoltMarker::BOLT_FAILURE
609
646
  # STDERR.puts "RESETTING CONNECTION"
610
- append_uint8(0xb1)
647
+ append_uint8(0xb0)
611
648
  append_token(BoltMarker::BOLT_RESET)
612
649
  flush()
613
650
  read_response() do |data|
@@ -627,38 +664,50 @@ module Neo4jBolt
627
664
  end
628
665
 
629
666
  def connect()
630
- # STDERR.write "Connecting to Neo4j via Bolt..."
631
667
  @socket = TCPSocket.new(Neo4jBolt.bolt_host, Neo4jBolt.bolt_port)
632
- # @socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
633
- # @socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE, 50)
634
- # @socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL, 10)
635
- # @socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT, 5)
636
668
  # The line below is important, otherwise we'll have to wait 40ms before every read
637
669
  @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
638
670
  @buffer = []
639
671
  @socket.write("\x60\x60\xB0\x17")
672
+ @socket.write("\x00\x00\x04\x05")
640
673
  @socket.write("\x00\x00\x04\x04")
641
674
  @socket.write("\x00\x00\x00\x00")
642
675
  @socket.write("\x00\x00\x00\x00")
643
- @socket.write("\x00\x00\x00\x00")
644
- version = @socket.read(4).unpack('N').first
645
- if version != 0x00000404
646
- raise "Unable to establish connection to Neo4j using Bolt protocol version 4.4!"
676
+ @bolt_version = @socket.read(4).unpack('V').first >> 16
677
+ # STDERR.puts "Handshake Bolt version: 0x%08x" % @bolt_version
678
+ unless [0x0504, 0x0404].include?(@bolt_version)
679
+ raise "Unable to establish connection to Neo4j using Bolt!"
647
680
  end
648
681
  @state.set(ServerState::CONNECTED)
649
- data = {
650
- :routing => nil,
651
- :scheme => 'none',
652
- :user_agent => 'neo4j_bolt/0.1'
653
- }
654
682
  append_uint8(0xb1)
655
683
  append_token(BoltMarker::BOLT_HELLO)
656
- append_dict(data)
684
+ append_dict({
685
+ :routing => nil,
686
+ :scheme => 'none',
687
+ :user_agent => "neo4j_bolt/#{Neo4jBolt::VERSION}",
688
+ :bolt_agent => {
689
+ :product => "neo4j_bolt/#{Neo4jBolt::VERSION}",
690
+ },
691
+ })
657
692
  flush()
658
693
  read_response() do |data|
659
694
  if data[:marker] == BoltMarker::BOLT_SUCCESS
660
- @state.set(ServerState::READY)
661
- @neo4j_version = data[:data]['server']
695
+ parts = data[:data]['server'].split('/')[1].split('.').map { |x| x.to_i}
696
+ if @bolt_version >= 0x0501
697
+ @state.set(ServerState::AUTHENTICATION)
698
+ append_uint8(0xb1)
699
+ append_token(BoltMarker::BOLT_LOGON)
700
+ append_dict({:scheme => 'none'})
701
+ flush()
702
+ read_response() do |data2|
703
+ @state.set(ServerState::READY)
704
+ if data2[:marker] == BoltMarker::BOLT_SUCCESS
705
+ @state.set(ServerState::READY)
706
+ end
707
+ end
708
+ else
709
+ @state.set(ServerState::READY)
710
+ end
662
711
  elsif data[:marker] == BoltMarker::BOLT_FAILURE
663
712
  @state.set(ServerState::DEFUNCT)
664
713
  else
@@ -671,7 +720,7 @@ module Neo4jBolt
671
720
  end
672
721
 
673
722
  def disconnect()
674
- append_uint8(0xb1)
723
+ append_uint8(0xb0)
675
724
  append_token(BoltMarker::BOLT_GOODBYE)
676
725
  flush()
677
726
  @state.set(ServerState::DEFUNCT)
@@ -708,13 +757,13 @@ module Neo4jBolt
708
757
  raise
709
758
  ensure
710
759
  @transaction -= 1
711
- if @transaction == 0 && @transaction_failed &&
760
+ if @transaction == 0 && @transaction_failed
712
761
  # TODO: Not sure about this, read remaining response but don't block
713
762
  # read_response()
714
- # STDERR.puts "!!! Rolling back transaction !!!"
763
+ # STDERR.puts "!!! Rolling back transaction !!! --- state is #{@state}"
715
764
  if @state == ServerState::TX_READY
716
765
  assert(@state == ServerState::TX_READY)
717
- append_uint8(0xb1)
766
+ append_uint8(0xb0)
718
767
  append_token(BoltMarker::BOLT_ROLLBACK)
719
768
  flush()
720
769
  read_response do |data|
@@ -730,7 +779,7 @@ module Neo4jBolt
730
779
  end
731
780
  end
732
781
  if (@transaction == 0) && (!@transaction_failed)
733
- append_uint8(0xb1)
782
+ append_uint8(0xb0)
734
783
  append_token(BoltMarker::BOLT_COMMIT)
735
784
  flush()
736
785
  read_response() do |data|
@@ -769,7 +818,7 @@ module Neo4jBolt
769
818
  end
770
819
  transaction do
771
820
  assert(@state == ServerState::TX_READY || @state == ServerState::TX_STREAMING || @state == ServerState::FAILED)
772
- append_uint8(0xb1)
821
+ append_uint8(0xb3)
773
822
  append_token(BoltMarker::BOLT_RUN)
774
823
  append_s(query)
775
824
  # Because something might go wrong while filling the buffer with
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neo4j_bolt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Specht
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-10 00:00:00.000000000 Z
11
+ date: 2024-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec