20
20
import WebSocketChannel from './ch-websocket' ;
21
21
import NodeChannel from './ch-node' ;
22
22
import { Chunker , Dechunker } from './chunking' ;
23
- import packStreamUtil from './packstream-util' ;
24
- import { alloc } from './buf' ;
25
23
import { newError , PROTOCOL_ERROR } from './../error' ;
26
24
import ChannelConfig from './ch-config' ;
27
25
import urlUtil from './url-util' ;
28
26
import StreamObserver from './stream-observer' ;
29
27
import { ServerVersion , VERSION_3_2_0 } from './server-version' ;
30
28
import Logger from './logger' ;
29
+ import ProtocolHandshaker from './protocol-handshaker' ;
31
30
32
31
let Channel ;
33
32
if ( NodeChannel . available ) {
@@ -41,21 +40,17 @@ else {
41
40
}
42
41
43
42
44
- let
45
43
// Signature bytes for each message type
46
- INIT = 0x01 , // 0000 0001 // INIT <user_agent>
47
- ACK_FAILURE = 0x0E , // 0000 1110 // ACK_FAILURE - unused
48
- RESET = 0x0F , // 0000 1111 // RESET
49
- RUN = 0x10 , // 0001 0000 // RUN <statement> <parameters>
50
- DISCARD_ALL = 0x2F , // 0010 1111 // DISCARD *
51
- PULL_ALL = 0x3F , // 0011 1111 // PULL *
52
- SUCCESS = 0x70 , // 0111 0000 // SUCCESS <metadata>
53
- RECORD = 0x71 , // 0111 0001 // RECORD <value>
54
- IGNORED = 0x7E , // 0111 1110 // IGNORED <metadata>
55
- FAILURE = 0x7F , // 0111 1111 // FAILURE <metadata>
56
-
57
- //sent before version negotiation
58
- MAGIC_PREAMBLE = 0x6060B017 ;
44
+ const INIT = 0x01 ; // 0000 0001 // INIT <user_agent>
45
+ const ACK_FAILURE = 0x0E ; // 0000 1110 // ACK_FAILURE - unused
46
+ const RESET = 0x0F ; // 0000 1111 // RESET
47
+ const RUN = 0x10 ; // 0001 0000 // RUN <statement> <parameters>
48
+ const DISCARD_ALL = 0x2F ; // 0010 1111 // DISCARD *
49
+ const PULL_ALL = 0x3F ; // 0011 1111 // PULL *
50
+ const SUCCESS = 0x70 ; // 0111 0000 // SUCCESS <metadata>
51
+ const RECORD = 0x71 ; // 0111 0001 // RECORD <value>
52
+ const IGNORED = 0x7E ; // 0111 1110 // IGNORED <metadata>
53
+ const FAILURE = 0x7F ; // 0111 1111 // FAILURE <metadata>
59
54
60
55
function NO_OP ( ) { }
61
56
@@ -102,9 +97,11 @@ class Connection {
102
97
this . _chunker = new Chunker ( channel ) ;
103
98
this . _log = log ;
104
99
100
+ const protocolHandshaker = new ProtocolHandshaker ( this . _ch , this . _chunker , this . _disableLosslessIntegers , this . _log ) ;
101
+
105
102
// initially assume that database supports latest Bolt version, create latest packer and unpacker
106
- this . _packer = packStreamUtil . createLatestPacker ( this . _chunker ) ;
107
- this . _unpacker = packStreamUtil . createLatestUnpacker ( disableLosslessIntegers ) ;
103
+ this . _packer = protocolHandshaker . createLatestPacker ( ) ;
104
+ this . _unpacker = protocolHandshaker . createLatestUnpacker ( ) ;
108
105
109
106
this . _currentFailure = null ;
110
107
@@ -116,17 +113,7 @@ class Connection {
116
113
// TODO: Using `onmessage` and `onerror` came from the WebSocket API,
117
114
// it reads poorly and has several annoying drawbacks. Swap to having
118
115
// Channel extend EventEmitter instead, then we can use `on('data',..)`
119
- this . _ch . onmessage = ( buf ) => {
120
- const proposed = buf . readInt32 ( ) ;
121
- if ( proposed == 1 || proposed == 2 ) {
122
- this . _initializeProtocol ( proposed , buf ) ;
123
- } else if ( proposed == 1213486160 ) { //server responded 1213486160 == 0x48545450 == "HTTP"
124
- this . _handleFatalError ( newError ( 'Server responded HTTP. Make sure you are not trying to connect to the http endpoint ' +
125
- '(HTTP defaults to port 7474 whereas BOLT defaults to port 7687)' ) ) ;
126
- } else {
127
- this . _handleFatalError ( newError ( 'Unknown Bolt protocol version: ' + proposed ) ) ;
128
- }
129
- } ;
116
+ this . _ch . onmessage = buffer => this . _initializeProtocol ( buffer , protocolHandshaker ) ;
130
117
131
118
// Listen to connection errors. Important note though;
132
119
// In some cases we will get a channel that is already broken (for instance,
@@ -148,38 +135,31 @@ class Connection {
148
135
this . _log . debug ( `${ this } created towards ${ hostPort } ` ) ;
149
136
}
150
137
151
- let handshake = alloc ( 5 * 4 ) ;
152
- //magic preamble
153
- handshake . writeInt32 ( MAGIC_PREAMBLE ) ;
154
- //proposed versions
155
- handshake . writeInt32 ( 2 ) ;
156
- handshake . writeInt32 ( 1 ) ;
157
- handshake . writeInt32 ( 0 ) ;
158
- handshake . writeInt32 ( 0 ) ;
159
- handshake . reset ( ) ;
160
- this . _ch . write ( handshake ) ;
138
+ protocolHandshaker . writeHandshakeRequest ( ) ;
161
139
}
162
140
163
141
/**
164
142
* Complete protocol initialization.
165
- * @param {number } version the selected protocol version.
166
143
* @param {BaseBuffer } buffer the handshake response buffer.
144
+ * @param {ProtocolHandshaker } protocolHandshaker the handshaker utility.
167
145
* @private
168
146
*/
169
- _initializeProtocol ( version , buffer ) {
170
- if ( this . _log . isDebugEnabled ( ) ) {
171
- this . _log . debug ( `${ this } negotiated protocol version ${ version } ` ) ;
172
- }
147
+ _initializeProtocol ( buffer , protocolHandshaker ) {
148
+ try {
149
+ const { packer, unpacker} = protocolHandshaker . readHandshakeResponse ( buffer ) ;
173
150
174
- // re-create packer and unpacker because version might be lower than we initially assumed
175
- this . _packer = packStreamUtil . createPackerForProtocolVersion ( version , this . _chunker ) ;
176
- this . _unpacker = packStreamUtil . createUnpackerForProtocolVersion ( version , this . _disableLosslessIntegers ) ;
151
+ // re-assign packer and unpacker because version might be lower than we initially assumed
152
+ this . _packer = packer ;
153
+ this . _unpacker = unpacker ;
177
154
178
- // Ok, protocol running. Simply forward all messages to the dechunker
179
- this . _ch . onmessage = buf => this . _dechunker . write ( buf ) ;
155
+ // Ok, protocol running. Simply forward all messages to the dechunker
156
+ this . _ch . onmessage = buf => this . _dechunker . write ( buf ) ;
180
157
181
- if ( buffer . hasRemaining ( ) ) {
182
- this . _dechunker . write ( buffer . readSlice ( buffer . remaining ( ) ) ) ;
158
+ if ( buffer . hasRemaining ( ) ) {
159
+ this . _dechunker . write ( buffer . readSlice ( buffer . remaining ( ) ) ) ;
160
+ }
161
+ } catch ( e ) {
162
+ this . _handleFatalError ( e ) ;
183
163
}
184
164
}
185
165
0 commit comments