mongodb 4.2.0 → 4.3.1
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.
- package/README.md +2 -2
- package/lib/admin.js +3 -3
- package/lib/admin.js.map +1 -1
- package/lib/bson.js +16 -14
- package/lib/bson.js.map +1 -1
- package/lib/bulk/common.js +7 -7
- package/lib/bulk/common.js.map +1 -1
- package/lib/bulk/ordered.js +1 -1
- package/lib/bulk/ordered.js.map +1 -1
- package/lib/bulk/unordered.js +1 -1
- package/lib/bulk/unordered.js.map +1 -1
- package/lib/change_stream.js +6 -7
- package/lib/change_stream.js.map +1 -1
- package/lib/cmap/auth/auth_provider.js.map +1 -1
- package/lib/cmap/auth/gssapi.js +3 -3
- package/lib/cmap/auth/gssapi.js.map +1 -1
- package/lib/cmap/auth/mongo_credentials.js +24 -26
- package/lib/cmap/auth/mongo_credentials.js.map +1 -1
- package/lib/cmap/auth/mongocr.js +2 -2
- package/lib/cmap/auth/mongocr.js.map +1 -1
- package/lib/cmap/auth/mongodb_aws.js +6 -6
- package/lib/cmap/auth/mongodb_aws.js.map +1 -1
- package/lib/cmap/auth/plain.js +1 -1
- package/lib/cmap/auth/plain.js.map +1 -1
- package/lib/cmap/auth/providers.js +21 -0
- package/lib/cmap/auth/providers.js.map +1 -0
- package/lib/cmap/auth/scram.js +4 -4
- package/lib/cmap/auth/scram.js.map +1 -1
- package/lib/cmap/auth/x509.js +1 -1
- package/lib/cmap/auth/x509.js.map +1 -1
- package/lib/cmap/command_monitoring_events.js +3 -2
- package/lib/cmap/command_monitoring_events.js.map +1 -1
- package/lib/cmap/commands.js +20 -11
- package/lib/cmap/commands.js.map +1 -1
- package/lib/cmap/connect.js +119 -31
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js +36 -35
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +19 -30
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/message_stream.js +3 -3
- package/lib/cmap/message_stream.js.map +1 -1
- package/lib/cmap/stream_description.js +4 -4
- package/lib/cmap/stream_description.js.map +1 -1
- package/lib/cmap/wire_protocol/compression.js +2 -1
- package/lib/cmap/wire_protocol/compression.js.map +1 -1
- package/lib/cmap/wire_protocol/shared.js +4 -3
- package/lib/cmap/wire_protocol/shared.js.map +1 -1
- package/lib/collection.js +45 -47
- package/lib/collection.js.map +1 -1
- package/lib/connection_string.js +48 -23
- package/lib/connection_string.js.map +1 -1
- package/lib/constants.js +113 -1
- package/lib/constants.js.map +1 -1
- package/lib/cursor/abstract_cursor.js +10 -7
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/cursor/aggregation_cursor.js +1 -1
- package/lib/cursor/aggregation_cursor.js.map +1 -1
- package/lib/cursor/find_cursor.js +1 -1
- package/lib/cursor/find_cursor.js.map +1 -1
- package/lib/db.js +23 -13
- package/lib/db.js.map +1 -1
- package/lib/deps.js +0 -1
- package/lib/deps.js.map +1 -1
- package/lib/encrypter.js +12 -4
- package/lib/encrypter.js.map +1 -1
- package/lib/error.js +47 -24
- package/lib/error.js.map +1 -1
- package/lib/gridfs/download.js +1 -1
- package/lib/gridfs/download.js.map +1 -1
- package/lib/gridfs/index.js +3 -3
- package/lib/gridfs/index.js.map +1 -1
- package/lib/gridfs/upload.js +3 -2
- package/lib/gridfs/upload.js.map +1 -1
- package/lib/index.js +81 -81
- package/lib/index.js.map +1 -1
- package/lib/logger.js +1 -1
- package/lib/logger.js.map +1 -1
- package/lib/mongo_client.js +5 -5
- package/lib/mongo_client.js.map +1 -1
- package/lib/mongo_types.js.map +1 -1
- package/lib/operations/add_user.js +3 -3
- package/lib/operations/add_user.js.map +1 -1
- package/lib/operations/aggregate.js +1 -1
- package/lib/operations/aggregate.js.map +1 -1
- package/lib/operations/bulk_write.js.map +1 -1
- package/lib/operations/collections.js +1 -1
- package/lib/operations/collections.js.map +1 -1
- package/lib/operations/command.js +5 -6
- package/lib/operations/command.js.map +1 -1
- package/lib/operations/common_functions.js.map +1 -1
- package/lib/operations/connect.js +4 -13
- package/lib/operations/connect.js.map +1 -1
- package/lib/operations/count.js +1 -1
- package/lib/operations/count.js.map +1 -1
- package/lib/operations/count_documents.js.map +1 -1
- package/lib/operations/create_collection.js +3 -2
- package/lib/operations/create_collection.js.map +1 -1
- package/lib/operations/delete.js +3 -3
- package/lib/operations/delete.js.map +1 -1
- package/lib/operations/distinct.js +3 -3
- package/lib/operations/distinct.js.map +1 -1
- package/lib/operations/drop.js +1 -1
- package/lib/operations/drop.js.map +1 -1
- package/lib/operations/estimated_document_count.js +2 -2
- package/lib/operations/estimated_document_count.js.map +1 -1
- package/lib/operations/eval.js +2 -2
- package/lib/operations/eval.js.map +1 -1
- package/lib/operations/execute_operation.js +15 -9
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/find.js +5 -5
- package/lib/operations/find.js.map +1 -1
- package/lib/operations/find_and_modify.js +2 -2
- package/lib/operations/find_and_modify.js.map +1 -1
- package/lib/operations/get_more.js +28 -0
- package/lib/operations/get_more.js.map +1 -0
- package/lib/operations/indexes.js +4 -4
- package/lib/operations/indexes.js.map +1 -1
- package/lib/operations/insert.js +3 -3
- package/lib/operations/insert.js.map +1 -1
- package/lib/operations/is_capped.js +1 -1
- package/lib/operations/is_capped.js.map +1 -1
- package/lib/operations/list_collections.js +3 -3
- package/lib/operations/list_collections.js.map +1 -1
- package/lib/operations/list_databases.js +1 -1
- package/lib/operations/list_databases.js.map +1 -1
- package/lib/operations/map_reduce.js +4 -3
- package/lib/operations/map_reduce.js.map +1 -1
- package/lib/operations/operation.js +3 -2
- package/lib/operations/operation.js.map +1 -1
- package/lib/operations/options_operation.js +1 -1
- package/lib/operations/options_operation.js.map +1 -1
- package/lib/operations/profiling_level.js +1 -1
- package/lib/operations/profiling_level.js.map +1 -1
- package/lib/operations/remove_user.js +1 -1
- package/lib/operations/remove_user.js.map +1 -1
- package/lib/operations/rename.js +3 -3
- package/lib/operations/rename.js.map +1 -1
- package/lib/operations/run_command.js +1 -1
- package/lib/operations/run_command.js.map +1 -1
- package/lib/operations/set_profiling_level.js +2 -2
- package/lib/operations/set_profiling_level.js.map +1 -1
- package/lib/operations/stats.js +1 -1
- package/lib/operations/stats.js.map +1 -1
- package/lib/operations/update.js +2 -2
- package/lib/operations/update.js.map +1 -1
- package/lib/operations/validate_collection.js +1 -1
- package/lib/operations/validate_collection.js.map +1 -1
- package/lib/read_preference.js +15 -5
- package/lib/read_preference.js.map +1 -1
- package/lib/sdam/events.js +4 -4
- package/lib/sdam/monitor.js +19 -18
- package/lib/sdam/monitor.js.map +1 -1
- package/lib/sdam/server.js +24 -31
- package/lib/sdam/server.js.map +1 -1
- package/lib/sdam/server_description.js +38 -38
- package/lib/sdam/server_description.js.map +1 -1
- package/lib/sdam/server_selection.js +19 -3
- package/lib/sdam/server_selection.js.map +1 -1
- package/lib/sdam/srv_polling.js +2 -2
- package/lib/sdam/srv_polling.js.map +1 -1
- package/lib/sdam/topology.js +32 -62
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sdam/topology_description.js +3 -3
- package/lib/sdam/topology_description.js.map +1 -1
- package/lib/sessions.js +13 -28
- package/lib/sessions.js.map +1 -1
- package/lib/transactions.js +1 -1
- package/lib/transactions.js.map +1 -1
- package/lib/utils.js +46 -15
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +145 -61
- package/mongodb.ts34.d.ts +173 -60
- package/package.json +29 -28
- package/src/admin.ts +9 -9
- package/src/bson.ts +26 -17
- package/src/bulk/common.ts +22 -23
- package/src/bulk/ordered.ts +4 -4
- package/src/bulk/unordered.ts +5 -5
- package/src/change_stream.ts +31 -28
- package/src/cmap/auth/auth_provider.ts +3 -3
- package/src/cmap/auth/gssapi.ts +8 -8
- package/src/cmap/auth/mongo_credentials.ts +11 -15
- package/src/cmap/auth/mongocr.ts +3 -2
- package/src/cmap/auth/mongodb_aws.ts +10 -11
- package/src/cmap/auth/plain.ts +1 -1
- package/src/cmap/auth/providers.ts +21 -0
- package/src/cmap/auth/scram.ts +9 -9
- package/src/cmap/auth/x509.ts +3 -3
- package/src/cmap/command_monitoring_events.ts +4 -3
- package/src/cmap/commands.ts +30 -19
- package/src/cmap/connect.ts +161 -37
- package/src/cmap/connection.ts +83 -63
- package/src/cmap/connection_pool.ts +39 -39
- package/src/cmap/connection_pool_events.ts +1 -1
- package/src/cmap/message_stream.ts +9 -8
- package/src/cmap/stream_description.ts +5 -5
- package/src/cmap/wire_protocol/compression.ts +4 -3
- package/src/cmap/wire_protocol/shared.ts +10 -9
- package/src/collection.ts +114 -95
- package/src/connection_string.ts +66 -29
- package/src/constants.ts +122 -0
- package/src/cursor/abstract_cursor.ts +21 -22
- package/src/cursor/aggregation_cursor.ts +6 -6
- package/src/cursor/find_cursor.ts +2 -2
- package/src/db.ts +44 -33
- package/src/deps.ts +3 -1
- package/src/encrypter.ts +12 -3
- package/src/error.ts +52 -24
- package/src/gridfs/download.ts +10 -8
- package/src/gridfs/index.ts +11 -11
- package/src/gridfs/upload.ts +13 -10
- package/src/index.ts +204 -199
- package/src/logger.ts +2 -1
- package/src/mongo_client.ts +46 -32
- package/src/mongo_types.ts +119 -21
- package/src/operations/add_user.ts +7 -6
- package/src/operations/aggregate.ts +5 -5
- package/src/operations/bulk_write.ts +5 -5
- package/src/operations/collections.ts +2 -2
- package/src/operations/command.ts +15 -9
- package/src/operations/common_functions.ts +4 -4
- package/src/operations/connect.ts +4 -14
- package/src/operations/count.ts +4 -4
- package/src/operations/count_documents.ts +3 -3
- package/src/operations/create_collection.ts +7 -6
- package/src/operations/delete.ts +5 -5
- package/src/operations/distinct.ts +4 -4
- package/src/operations/drop.ts +4 -4
- package/src/operations/estimated_document_count.ts +5 -5
- package/src/operations/eval.ts +5 -5
- package/src/operations/execute_operation.ts +21 -13
- package/src/operations/find.ts +14 -14
- package/src/operations/find_and_modify.ts +7 -7
- package/src/operations/get_more.ts +49 -0
- package/src/operations/indexes.ts +16 -16
- package/src/operations/insert.ts +9 -9
- package/src/operations/is_capped.ts +3 -3
- package/src/operations/list_collections.ts +6 -6
- package/src/operations/list_databases.ts +4 -4
- package/src/operations/map_reduce.ts +10 -9
- package/src/operations/operation.ts +5 -4
- package/src/operations/options_operation.ts +3 -3
- package/src/operations/profiling_level.ts +4 -4
- package/src/operations/remove_user.ts +4 -4
- package/src/operations/rename.ts +6 -6
- package/src/operations/run_command.ts +3 -3
- package/src/operations/set_profiling_level.ts +6 -5
- package/src/operations/stats.ts +4 -4
- package/src/operations/update.ts +10 -10
- package/src/operations/validate_collection.ts +4 -4
- package/src/read_preference.ts +18 -7
- package/src/sdam/common.ts +2 -2
- package/src/sdam/events.ts +5 -5
- package/src/sdam/monitor.ts +29 -32
- package/src/sdam/server.ts +64 -62
- package/src/sdam/server_description.ts +41 -48
- package/src/sdam/server_selection.ts +21 -3
- package/src/sdam/srv_polling.ts +3 -2
- package/src/sdam/topology.ts +71 -89
- package/src/sdam/topology_description.ts +5 -5
- package/src/sessions.ts +31 -48
- package/src/transactions.ts +4 -4
- package/src/utils.ts +69 -33
- package/lib/cmap/auth/defaultAuthProviders.js +0 -30
- package/lib/cmap/auth/defaultAuthProviders.js.map +0 -1
- package/src/cmap/auth/defaultAuthProviders.ts +0 -32
package/src/cmap/commands.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { BSONSerializeOptions, Document, Long } from '../bson';
|
|
2
2
|
import * as BSON from '../bson';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import type { Long, Document, BSONSerializeOptions } from '../bson';
|
|
3
|
+
import { MongoInvalidArgumentError, MongoRuntimeError } from '../error';
|
|
4
|
+
import { ReadPreference } from '../read_preference';
|
|
6
5
|
import type { ClientSession } from '../sessions';
|
|
6
|
+
import { databaseNamespace } from '../utils';
|
|
7
7
|
import type { CommandOptions } from './connection';
|
|
8
|
-
import {
|
|
8
|
+
import { OP_GETMORE, OP_KILL_CURSORS, OP_MSG, OP_QUERY } from './wire_protocol/constants';
|
|
9
9
|
|
|
10
10
|
// Incrementing request id
|
|
11
11
|
let _requestId = 0;
|
|
12
12
|
|
|
13
13
|
// Query flags
|
|
14
14
|
const OPTS_TAILABLE_CURSOR = 2;
|
|
15
|
-
const
|
|
15
|
+
const OPTS_SECONDARY = 4;
|
|
16
16
|
const OPTS_OPLOG_REPLAY = 8;
|
|
17
17
|
const OPTS_NO_CURSOR_TIMEOUT = 16;
|
|
18
18
|
const OPTS_AWAIT_DATA = 32;
|
|
@@ -41,7 +41,7 @@ export interface OpQueryOptions extends CommandOptions {
|
|
|
41
41
|
ignoreUndefined?: boolean;
|
|
42
42
|
maxBsonSize?: number;
|
|
43
43
|
checkKeys?: boolean;
|
|
44
|
-
|
|
44
|
+
secondaryOk?: boolean;
|
|
45
45
|
|
|
46
46
|
requestId?: number;
|
|
47
47
|
moreToCome?: boolean;
|
|
@@ -67,7 +67,7 @@ export class Query {
|
|
|
67
67
|
checkKeys: boolean;
|
|
68
68
|
batchSize: number;
|
|
69
69
|
tailable: boolean;
|
|
70
|
-
|
|
70
|
+
secondaryOk: boolean;
|
|
71
71
|
oplogReplay: boolean;
|
|
72
72
|
noCursorTimeout: boolean;
|
|
73
73
|
awaitData: boolean;
|
|
@@ -112,7 +112,7 @@ export class Query {
|
|
|
112
112
|
|
|
113
113
|
// Flags
|
|
114
114
|
this.tailable = false;
|
|
115
|
-
this.
|
|
115
|
+
this.secondaryOk = typeof options.secondaryOk === 'boolean' ? options.secondaryOk : false;
|
|
116
116
|
this.oplogReplay = false;
|
|
117
117
|
this.noCursorTimeout = false;
|
|
118
118
|
this.awaitData = false;
|
|
@@ -146,8 +146,8 @@ export class Query {
|
|
|
146
146
|
flags |= OPTS_TAILABLE_CURSOR;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
if (this.
|
|
150
|
-
flags |=
|
|
149
|
+
if (this.secondaryOk) {
|
|
150
|
+
flags |= OPTS_SECONDARY;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
if (this.oplogReplay) {
|
|
@@ -837,22 +837,24 @@ export class BinMsg {
|
|
|
837
837
|
const promoteValues = options.promoteValues ?? this.opts.promoteValues;
|
|
838
838
|
const promoteBuffers = options.promoteBuffers ?? this.opts.promoteBuffers;
|
|
839
839
|
const bsonRegExp = options.bsonRegExp ?? this.opts.bsonRegExp;
|
|
840
|
+
const validation = this.parseBsonSerializationOptions(options);
|
|
840
841
|
|
|
841
842
|
// Set up the options
|
|
842
|
-
const
|
|
843
|
+
const bsonOptions: BSONSerializeOptions = {
|
|
843
844
|
promoteLongs,
|
|
844
845
|
promoteValues,
|
|
845
846
|
promoteBuffers,
|
|
846
|
-
bsonRegExp
|
|
847
|
-
|
|
847
|
+
bsonRegExp,
|
|
848
|
+
validation
|
|
849
|
+
// Due to the strictness of the BSON libraries validation option we need this cast
|
|
850
|
+
} as BSONSerializeOptions & { validation: { utf8: { writeErrors: boolean } } };
|
|
848
851
|
|
|
849
852
|
while (this.index < this.data.length) {
|
|
850
853
|
const payloadType = this.data.readUInt8(this.index++);
|
|
851
854
|
if (payloadType === 0) {
|
|
852
855
|
const bsonSize = this.data.readUInt32LE(this.index);
|
|
853
856
|
const bin = this.data.slice(this.index, this.index + bsonSize);
|
|
854
|
-
this.documents.push(raw ? bin : BSON.deserialize(bin,
|
|
855
|
-
|
|
857
|
+
this.documents.push(raw ? bin : BSON.deserialize(bin, bsonOptions));
|
|
856
858
|
this.index += bsonSize;
|
|
857
859
|
} else if (payloadType === 1) {
|
|
858
860
|
// It was decided that no driver makes use of payload type 1
|
|
@@ -865,12 +867,21 @@ export class BinMsg {
|
|
|
865
867
|
if (this.documents.length === 1 && documentsReturnedIn != null && raw) {
|
|
866
868
|
const fieldsAsRaw: Document = {};
|
|
867
869
|
fieldsAsRaw[documentsReturnedIn] = true;
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
const doc = BSON.deserialize(this.documents[0] as Buffer, _options);
|
|
870
|
+
bsonOptions.fieldsAsRaw = fieldsAsRaw;
|
|
871
|
+
const doc = BSON.deserialize(this.documents[0] as Buffer, bsonOptions);
|
|
871
872
|
this.documents = [doc];
|
|
872
873
|
}
|
|
873
874
|
|
|
874
875
|
this.parsed = true;
|
|
875
876
|
}
|
|
877
|
+
|
|
878
|
+
parseBsonSerializationOptions({ enableUtf8Validation }: BSONSerializeOptions): {
|
|
879
|
+
utf8: { writeErrors: false } | false;
|
|
880
|
+
} {
|
|
881
|
+
if (enableUtf8Validation === false) {
|
|
882
|
+
return { utf8: false };
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
return { utf8: { writeErrors: false } };
|
|
886
|
+
}
|
|
876
887
|
}
|
package/src/cmap/connect.ts
CHANGED
|
@@ -1,29 +1,54 @@
|
|
|
1
|
+
import type { Socket, SocketConnectOpts } from 'net';
|
|
1
2
|
import * as net from 'net';
|
|
3
|
+
import { SocksClient } from 'socks';
|
|
4
|
+
import type { ConnectionOptions as TLSConnectionOpts, TLSSocket } from 'tls';
|
|
2
5
|
import * as tls from 'tls';
|
|
3
|
-
|
|
6
|
+
|
|
7
|
+
import type { Document } from '../bson';
|
|
8
|
+
import { Int32 } from '../bson';
|
|
9
|
+
import { LEGACY_HELLO_COMMAND } from '../constants';
|
|
4
10
|
import {
|
|
5
|
-
MongoNetworkError,
|
|
6
|
-
MongoNetworkTimeoutError,
|
|
7
11
|
AnyError,
|
|
8
12
|
MongoCompatibilityError,
|
|
9
13
|
MongoInvalidArgumentError,
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
MongoNetworkError,
|
|
15
|
+
MongoNetworkTimeoutError,
|
|
16
|
+
MongoRuntimeError,
|
|
17
|
+
MongoServerError
|
|
12
18
|
} from '../error';
|
|
13
|
-
import { AUTH_PROVIDERS, AuthMechanism } from './auth/defaultAuthProviders';
|
|
14
|
-
import { AuthContext } from './auth/auth_provider';
|
|
15
|
-
import { makeClientMetadata, ClientMetadata, Callback, CallbackWithType, ns } from '../utils';
|
|
16
19
|
import {
|
|
17
|
-
|
|
20
|
+
Callback,
|
|
21
|
+
CallbackWithType,
|
|
22
|
+
ClientMetadata,
|
|
23
|
+
HostAddress,
|
|
24
|
+
makeClientMetadata,
|
|
25
|
+
ns
|
|
26
|
+
} from '../utils';
|
|
27
|
+
import { AuthContext, AuthProvider } from './auth/auth_provider';
|
|
28
|
+
import { GSSAPI } from './auth/gssapi';
|
|
29
|
+
import { MongoCR } from './auth/mongocr';
|
|
30
|
+
import { MongoDBAWS } from './auth/mongodb_aws';
|
|
31
|
+
import { Plain } from './auth/plain';
|
|
32
|
+
import { AuthMechanism } from './auth/providers';
|
|
33
|
+
import { ScramSHA1, ScramSHA256 } from './auth/scram';
|
|
34
|
+
import { X509 } from './auth/x509';
|
|
35
|
+
import { Connection, ConnectionOptions, CryptoConnection } from './connection';
|
|
36
|
+
import {
|
|
18
37
|
MAX_SUPPORTED_SERVER_VERSION,
|
|
19
|
-
|
|
20
|
-
MIN_SUPPORTED_SERVER_VERSION
|
|
38
|
+
MAX_SUPPORTED_WIRE_VERSION,
|
|
39
|
+
MIN_SUPPORTED_SERVER_VERSION,
|
|
40
|
+
MIN_SUPPORTED_WIRE_VERSION
|
|
21
41
|
} from './wire_protocol/constants';
|
|
22
|
-
import type { Document } from '../bson';
|
|
23
|
-
import { Int32 } from '../bson';
|
|
24
42
|
|
|
25
|
-
|
|
26
|
-
|
|
43
|
+
const AUTH_PROVIDERS = new Map<AuthMechanism | string, AuthProvider>([
|
|
44
|
+
[AuthMechanism.MONGODB_AWS, new MongoDBAWS()],
|
|
45
|
+
[AuthMechanism.MONGODB_CR, new MongoCR()],
|
|
46
|
+
[AuthMechanism.MONGODB_GSSAPI, new GSSAPI()],
|
|
47
|
+
[AuthMechanism.MONGODB_PLAIN, new Plain()],
|
|
48
|
+
[AuthMechanism.MONGODB_SCRAM_SHA1, new ScramSHA1()],
|
|
49
|
+
[AuthMechanism.MONGODB_SCRAM_SHA256, new ScramSHA256()],
|
|
50
|
+
[AuthMechanism.MONGODB_X509, new X509()]
|
|
51
|
+
]);
|
|
27
52
|
|
|
28
53
|
const FAKE_MONGODB_SERVICE_ID =
|
|
29
54
|
typeof process.env.FAKE_MONGODB_SERVICE_ID === 'string' &&
|
|
@@ -33,7 +58,7 @@ const FAKE_MONGODB_SERVICE_ID =
|
|
|
33
58
|
export type Stream = Socket | TLSSocket;
|
|
34
59
|
|
|
35
60
|
export function connect(options: ConnectionOptions, callback: Callback<Connection>): void {
|
|
36
|
-
makeConnection(options, (err, socket) => {
|
|
61
|
+
makeConnection({ ...options, existingSocket: undefined }, (err, socket) => {
|
|
37
62
|
if (err || !socket) {
|
|
38
63
|
return callback(err);
|
|
39
64
|
}
|
|
@@ -46,15 +71,15 @@ export function connect(options: ConnectionOptions, callback: Callback<Connectio
|
|
|
46
71
|
});
|
|
47
72
|
}
|
|
48
73
|
|
|
49
|
-
function checkSupportedServer(
|
|
74
|
+
function checkSupportedServer(hello: Document, options: ConnectionOptions) {
|
|
50
75
|
const serverVersionHighEnough =
|
|
51
|
-
|
|
52
|
-
(typeof
|
|
53
|
-
|
|
76
|
+
hello &&
|
|
77
|
+
(typeof hello.maxWireVersion === 'number' || hello.maxWireVersion instanceof Int32) &&
|
|
78
|
+
hello.maxWireVersion >= MIN_SUPPORTED_WIRE_VERSION;
|
|
54
79
|
const serverVersionLowEnough =
|
|
55
|
-
|
|
56
|
-
(typeof
|
|
57
|
-
|
|
80
|
+
hello &&
|
|
81
|
+
(typeof hello.minWireVersion === 'number' || hello.minWireVersion instanceof Int32) &&
|
|
82
|
+
hello.minWireVersion <= MAX_SUPPORTED_WIRE_VERSION;
|
|
58
83
|
|
|
59
84
|
if (serverVersionHighEnough) {
|
|
60
85
|
if (serverVersionLowEnough) {
|
|
@@ -62,13 +87,13 @@ function checkSupportedServer(ismaster: Document, options: ConnectionOptions) {
|
|
|
62
87
|
}
|
|
63
88
|
|
|
64
89
|
const message = `Server at ${options.hostAddress} reports minimum wire version ${JSON.stringify(
|
|
65
|
-
|
|
90
|
+
hello.minWireVersion
|
|
66
91
|
)}, but this version of the Node.js Driver requires at most ${MAX_SUPPORTED_WIRE_VERSION} (MongoDB ${MAX_SUPPORTED_SERVER_VERSION})`;
|
|
67
92
|
return new MongoCompatibilityError(message);
|
|
68
93
|
}
|
|
69
94
|
|
|
70
95
|
const message = `Server at ${options.hostAddress} reports maximum wire version ${
|
|
71
|
-
JSON.stringify(
|
|
96
|
+
JSON.stringify(hello.maxWireVersion) ?? 0
|
|
72
97
|
}, but this version of the Node.js Driver requires at least ${MIN_SUPPORTED_WIRE_VERSION} (MongoDB ${MIN_SUPPORTED_SERVER_VERSION})`;
|
|
73
98
|
return new MongoCompatibilityError(message);
|
|
74
99
|
}
|
|
@@ -122,9 +147,9 @@ function performInitialHandshake(
|
|
|
122
147
|
return;
|
|
123
148
|
}
|
|
124
149
|
|
|
125
|
-
if ('isWritablePrimary' in response) {
|
|
126
|
-
// Provide
|
|
127
|
-
response.
|
|
150
|
+
if (!('isWritablePrimary' in response)) {
|
|
151
|
+
// Provide hello-style response document.
|
|
152
|
+
response.isWritablePrimary = response[LEGACY_HELLO_COMMAND];
|
|
128
153
|
}
|
|
129
154
|
|
|
130
155
|
if (response.helloOk) {
|
|
@@ -155,8 +180,8 @@ function performInitialHandshake(
|
|
|
155
180
|
// NOTE: This is metadata attached to the connection while porting away from
|
|
156
181
|
// handshake being done in the `Server` class. Likely, it should be
|
|
157
182
|
// relocated, or at very least restructured.
|
|
158
|
-
conn.
|
|
159
|
-
conn.
|
|
183
|
+
conn.hello = response;
|
|
184
|
+
conn.lastHelloMS = new Date().getTime() - start;
|
|
160
185
|
|
|
161
186
|
if (!response.arbiterOnly && credentials) {
|
|
162
187
|
// store the response on auth context
|
|
@@ -185,6 +210,9 @@ function performInitialHandshake(
|
|
|
185
210
|
}
|
|
186
211
|
|
|
187
212
|
export interface HandshakeDocument extends Document {
|
|
213
|
+
/**
|
|
214
|
+
* @deprecated Use hello instead
|
|
215
|
+
*/
|
|
188
216
|
ismaster?: boolean;
|
|
189
217
|
hello?: boolean;
|
|
190
218
|
helloOk?: boolean;
|
|
@@ -200,7 +228,7 @@ function prepareHandshakeDocument(authContext: AuthContext, callback: Callback<H
|
|
|
200
228
|
const { serverApi } = authContext.connection;
|
|
201
229
|
|
|
202
230
|
const handshakeDoc: HandshakeDocument = {
|
|
203
|
-
[serverApi?.version ? 'hello' :
|
|
231
|
+
[serverApi?.version ? 'hello' : LEGACY_HELLO_COMMAND]: true,
|
|
204
232
|
helloOk: true,
|
|
205
233
|
client: options.metadata || makeClientMetadata(options),
|
|
206
234
|
compression: compressors,
|
|
@@ -289,7 +317,9 @@ function parseConnectOptions(options: ConnectionOptions): SocketConnectOpts {
|
|
|
289
317
|
}
|
|
290
318
|
}
|
|
291
319
|
|
|
292
|
-
|
|
320
|
+
type MakeConnectionOptions = ConnectionOptions & { existingSocket?: Stream };
|
|
321
|
+
|
|
322
|
+
function parseSslOptions(options: MakeConnectionOptions): TLSConnectionOpts {
|
|
293
323
|
const result: TLSConnectionOpts = parseConnectOptions(options);
|
|
294
324
|
// Merge in valid SSL options
|
|
295
325
|
for (const name of LEGAL_TLS_SOCKET_OPTIONS) {
|
|
@@ -298,6 +328,10 @@ function parseSslOptions(options: ConnectionOptions): TLSConnectionOpts {
|
|
|
298
328
|
}
|
|
299
329
|
}
|
|
300
330
|
|
|
331
|
+
if (options.existingSocket) {
|
|
332
|
+
result.socket = options.existingSocket;
|
|
333
|
+
}
|
|
334
|
+
|
|
301
335
|
// Set default sni servername to be the same as host
|
|
302
336
|
if (result.servername == null && result.host && !net.isIP(result.host)) {
|
|
303
337
|
result.servername = result.host;
|
|
@@ -310,17 +344,21 @@ const SOCKET_ERROR_EVENT_LIST = ['error', 'close', 'timeout', 'parseError'] as c
|
|
|
310
344
|
type ErrorHandlerEventName = typeof SOCKET_ERROR_EVENT_LIST[number] | 'cancel';
|
|
311
345
|
const SOCKET_ERROR_EVENTS = new Set(SOCKET_ERROR_EVENT_LIST);
|
|
312
346
|
|
|
313
|
-
function makeConnection(
|
|
347
|
+
function makeConnection(
|
|
348
|
+
options: MakeConnectionOptions,
|
|
349
|
+
_callback: CallbackWithType<AnyError, Stream>
|
|
350
|
+
) {
|
|
314
351
|
const useTLS = options.tls ?? false;
|
|
315
352
|
const keepAlive = options.keepAlive ?? true;
|
|
316
353
|
const socketTimeoutMS = options.socketTimeoutMS ?? Reflect.get(options, 'socketTimeout') ?? 0;
|
|
317
354
|
const noDelay = options.noDelay ?? true;
|
|
318
|
-
const
|
|
355
|
+
const connectTimeoutMS = options.connectTimeoutMS ?? 30000;
|
|
319
356
|
const rejectUnauthorized = options.rejectUnauthorized ?? true;
|
|
320
357
|
const keepAliveInitialDelay =
|
|
321
358
|
((options.keepAliveInitialDelay ?? 120000) > socketTimeoutMS
|
|
322
359
|
? Math.round(socketTimeoutMS / 2)
|
|
323
360
|
: options.keepAliveInitialDelay) ?? 120000;
|
|
361
|
+
const existingSocket = options.existingSocket;
|
|
324
362
|
|
|
325
363
|
let socket: Stream;
|
|
326
364
|
const callback: Callback<Stream> = function (err, ret) {
|
|
@@ -331,18 +369,34 @@ function makeConnection(options: ConnectionOptions, _callback: CallbackWithType<
|
|
|
331
369
|
_callback(err, ret);
|
|
332
370
|
};
|
|
333
371
|
|
|
372
|
+
if (options.proxyHost != null) {
|
|
373
|
+
// Currently, only Socks5 is supported.
|
|
374
|
+
return makeSocks5Connection(
|
|
375
|
+
{
|
|
376
|
+
...options,
|
|
377
|
+
connectTimeoutMS // Should always be present for Socks5
|
|
378
|
+
},
|
|
379
|
+
callback
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
|
|
334
383
|
if (useTLS) {
|
|
335
384
|
const tlsSocket = tls.connect(parseSslOptions(options));
|
|
336
385
|
if (typeof tlsSocket.disableRenegotiation === 'function') {
|
|
337
386
|
tlsSocket.disableRenegotiation();
|
|
338
387
|
}
|
|
339
388
|
socket = tlsSocket;
|
|
389
|
+
} else if (existingSocket) {
|
|
390
|
+
// In the TLS case, parseSslOptions() sets options.socket to existingSocket,
|
|
391
|
+
// so we only need to handle the non-TLS case here (where existingSocket
|
|
392
|
+
// gives us all we need out of the box).
|
|
393
|
+
socket = existingSocket;
|
|
340
394
|
} else {
|
|
341
395
|
socket = net.createConnection(parseConnectOptions(options));
|
|
342
396
|
}
|
|
343
397
|
|
|
344
398
|
socket.setKeepAlive(keepAlive, keepAliveInitialDelay);
|
|
345
|
-
socket.setTimeout(
|
|
399
|
+
socket.setTimeout(connectTimeoutMS);
|
|
346
400
|
socket.setNoDelay(noDelay);
|
|
347
401
|
|
|
348
402
|
const connectEvent = useTLS ? 'secureConnect' : 'connect';
|
|
@@ -381,10 +435,80 @@ function makeConnection(options: ConnectionOptions, _callback: CallbackWithType<
|
|
|
381
435
|
options.cancellationToken.once('cancel', cancellationHandler);
|
|
382
436
|
}
|
|
383
437
|
|
|
384
|
-
|
|
438
|
+
if (existingSocket) {
|
|
439
|
+
process.nextTick(connectHandler);
|
|
440
|
+
} else {
|
|
441
|
+
socket.once(connectEvent, connectHandler);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function makeSocks5Connection(options: MakeConnectionOptions, callback: Callback<Stream>) {
|
|
446
|
+
const hostAddress = HostAddress.fromHostPort(
|
|
447
|
+
options.proxyHost ?? '', // proxyHost is guaranteed to set here
|
|
448
|
+
options.proxyPort ?? 1080
|
|
449
|
+
);
|
|
450
|
+
|
|
451
|
+
// First, connect to the proxy server itself:
|
|
452
|
+
makeConnection(
|
|
453
|
+
{
|
|
454
|
+
...options,
|
|
455
|
+
hostAddress,
|
|
456
|
+
tls: false,
|
|
457
|
+
proxyHost: undefined
|
|
458
|
+
},
|
|
459
|
+
(err, rawSocket) => {
|
|
460
|
+
if (err) {
|
|
461
|
+
return callback(err);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const destination = parseConnectOptions(options) as net.TcpNetConnectOpts;
|
|
465
|
+
if (typeof destination.host !== 'string' || typeof destination.port !== 'number') {
|
|
466
|
+
return callback(
|
|
467
|
+
new MongoInvalidArgumentError('Can only make Socks5 connections to TCP hosts')
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Then, establish the Socks5 proxy connection:
|
|
472
|
+
SocksClient.createConnection(
|
|
473
|
+
{
|
|
474
|
+
existing_socket: rawSocket,
|
|
475
|
+
timeout: options.connectTimeoutMS,
|
|
476
|
+
command: 'connect',
|
|
477
|
+
destination: {
|
|
478
|
+
host: destination.host,
|
|
479
|
+
port: destination.port
|
|
480
|
+
},
|
|
481
|
+
proxy: {
|
|
482
|
+
// host and port are ignored because we pass existing_socket
|
|
483
|
+
host: 'iLoveJavaScript',
|
|
484
|
+
port: 0,
|
|
485
|
+
type: 5,
|
|
486
|
+
userId: options.proxyUsername || undefined,
|
|
487
|
+
password: options.proxyPassword || undefined
|
|
488
|
+
}
|
|
489
|
+
},
|
|
490
|
+
(err: AnyError, info: { socket: Stream }) => {
|
|
491
|
+
if (err) {
|
|
492
|
+
return callback(connectionFailureError('error', err));
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Finally, now treat the resulting duplex stream as the
|
|
496
|
+
// socket over which we send and receive wire protocol messages:
|
|
497
|
+
makeConnection(
|
|
498
|
+
{
|
|
499
|
+
...options,
|
|
500
|
+
existingSocket: info.socket,
|
|
501
|
+
proxyHost: undefined
|
|
502
|
+
},
|
|
503
|
+
callback
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
);
|
|
385
509
|
}
|
|
386
510
|
|
|
387
|
-
function connectionFailureError(type:
|
|
511
|
+
function connectionFailureError(type: ErrorHandlerEventName, err: Error) {
|
|
388
512
|
switch (type) {
|
|
389
513
|
case 'error':
|
|
390
514
|
return new MongoNetworkError(err);
|