@@ -160,13 +160,28 @@ function prepareWebSocketUrl(options, awsAccessId, awsSecretKey, awsSTSToken) {
160
160
awsAccessId , awsSecretKey , options . region , awsServiceName , '' , today , now , options . debug , awsSTSToken ) ;
161
161
}
162
162
163
+ function prepareWebSocketCustomAuthUrl ( options ) {
164
+ var path = '/mqtt' ;
165
+ var hostName = options . host ;
166
+
167
+ // Include the port number in the hostname if it's not
168
+ // the standard wss port (443).
169
+ //
170
+ if ( ! isUndefined ( options . port ) && options . port !== 443 ) {
171
+ hostName = options . host + ':' + options . port ;
172
+ }
173
+
174
+ return 'wss://' + hostName + path ;
175
+ }
176
+
163
177
function arrayEach ( array , iterFunction ) {
164
178
for ( var idx in array ) {
165
179
if ( Object . prototype . hasOwnProperty . call ( array , idx ) ) {
166
180
iterFunction . call ( this , array [ idx ] , parseInt ( idx , 10 ) ) ;
167
181
}
168
182
}
169
- }
183
+ }
184
+
170
185
function getCredentials ( ini ) {
171
186
//Get shared credential function from AWS SDK.
172
187
var map = { } ;
@@ -295,6 +310,8 @@ function DeviceClient(options) {
295
310
var drainingTimer = null ;
296
311
var drainTimeMs = 250 ;
297
312
313
+ //Default keep alive time interval in seconds.
314
+ var defaultKeepalive = 300 ;
298
315
//
299
316
// These properties control the reconnect behavior of the MQTT Client. If
300
317
// the MQTT client becomes disconnected, it will attempt to reconnect after
@@ -342,10 +359,28 @@ function DeviceClient(options) {
342
359
//
343
360
// Validate options, set default reconnect period if not specified.
344
361
//
362
+ var metricPrefix = "?SDK=JavaScript&Version=" ;
363
+ var pjson = require ( '../package.json' ) ;
364
+ var sdkVersion = pjson . version ;
365
+ var defaultUsername = metricPrefix + sdkVersion ;
366
+
345
367
if ( isUndefined ( options ) ||
346
368
Object . keys ( options ) . length === 0 ) {
347
369
throw new Error ( exceptions . INVALID_CONNECT_OPTIONS ) ;
348
370
}
371
+ if ( isUndefined ( options . keepalive ) ) {
372
+ options . keepalive = defaultKeepalive ;
373
+ }
374
+ //
375
+ // Metrics will be enabled by default unless the user explicitly disables it
376
+ //
377
+ if ( isUndefined ( options . enableMetrics ) || options . enableMetrics === true ) {
378
+ if ( isUndefined ( options . username ) ) {
379
+ options . username = defaultUsername ;
380
+ } else {
381
+ options . username += defaultUsername ;
382
+ }
383
+ }
349
384
if ( ! isUndefined ( options . baseReconnectTimeMs ) ) {
350
385
baseReconnectTimeMs = options . baseReconnectTimeMs ;
351
386
}
@@ -373,6 +408,10 @@ function DeviceClient(options) {
373
408
currentReconnectTimeMs = baseReconnectTimeMs ;
374
409
options . reconnectPeriod = currentReconnectTimeMs ;
375
410
options . fastDisconnectDetection = true ;
411
+ //
412
+ //SDK has its own logic to deal with auto resubscribe
413
+ //
414
+ options . resubscribe = false ;
376
415
377
416
//
378
417
// Verify that the reconnection timing parameters make sense.
@@ -414,47 +453,60 @@ function DeviceClient(options) {
414
453
415
454
//read and map certificates
416
455
tlsReader ( options ) ;
417
- } else if ( options . protocol === 'wss' ) {
418
- //
419
- // AWS access id and secret key
420
- // It first check Input options and Environment variables
421
- // If that not available, it will try to load credentials from default credential file
422
- if ( ! isUndefined ( options . accessKeyId ) ) {
423
- awsAccessId = options . accessKeyId ;
424
- } else {
425
- awsAccessId = process . env . AWS_ACCESS_KEY_ID ;
426
- }
427
- if ( ! isUndefined ( options . secretKey ) ) {
428
- awsSecretKey = options . secretKey ;
429
- } else {
430
- awsSecretKey = process . env . AWS_SECRET_ACCESS_KEY ;
431
- }
432
- if ( ! isUndefined ( options . sessionToken ) ) {
433
- awsSTSToken = options . sessionToken ;
434
- } else {
435
- awsSTSToken = process . env . AWS_SESSION_TOKEN ;
436
- }
437
- if ( isUndefined ( awsAccessId ) || isUndefined ( awsSecretKey ) ) {
438
- var filename ;
439
- try {
440
- if ( ! isUndefined ( options . filename ) ) {
441
- filename = options . filename ;
442
- } else {
443
- filename = _loadDefaultFilename ( ) ;
444
- }
445
- var user_profile = options . profile || process . env . AWS_PROFILE || 'default' ;
446
- var creds = getCredentials ( fs . readFileSync ( filename , 'utf-8' ) ) ;
447
- var profile = creds [ user_profile ] ;
448
- awsAccessId = profile . aws_access_key_id ;
449
- awsSecretKey = profile . aws_secret_access_key ;
450
- awsSTSToken = profile . aws_session_token ;
456
+ } else if ( options . protocol === 'wss' || options . protocol === 'wss-custom-auth' ) {
457
+ if ( options . protocol === 'wss' ) {
458
+ //
459
+ // AWS access id and secret key
460
+ // It first check Input options and Environment variables
461
+ // If that not available, it will try to load credentials from default credential file
462
+ if ( ! isUndefined ( options . accessKeyId ) ) {
463
+ awsAccessId = options . accessKeyId ;
464
+ } else {
465
+ awsAccessId = process . env . AWS_ACCESS_KEY_ID ;
466
+ }
467
+ if ( ! isUndefined ( options . secretKey ) ) {
468
+ awsSecretKey = options . secretKey ;
469
+ } else {
470
+ awsSecretKey = process . env . AWS_SECRET_ACCESS_KEY ;
471
+ }
472
+ if ( ! isUndefined ( options . sessionToken ) ) {
473
+ awsSTSToken = options . sessionToken ;
474
+ } else {
475
+ awsSTSToken = process . env . AWS_SESSION_TOKEN ;
476
+ }
477
+ if ( isUndefined ( awsAccessId ) || isUndefined ( awsSecretKey ) ) {
478
+ var filename ;
479
+ try {
480
+ if ( ! isUndefined ( options . filename ) ) {
481
+ filename = options . filename ;
482
+ } else {
483
+ filename = _loadDefaultFilename ( ) ;
484
+ }
485
+ var user_profile = options . profile || process . env . AWS_PROFILE || 'default' ;
486
+ var creds = getCredentials ( fs . readFileSync ( filename , 'utf-8' ) ) ;
487
+ var profile = creds [ user_profile ] ;
488
+ awsAccessId = profile . aws_access_key_id ;
489
+ awsSecretKey = profile . aws_secret_access_key ;
490
+ awsSTSToken = profile . aws_session_token ;
451
491
} catch ( e ) {
452
492
console . log ( e ) ;
453
- console . log ( " Failed to read credentials from " + filename ) ;
493
+ console . log ( ' Failed to read credentials from ' + filename ) ;
454
494
}
495
+ }
496
+ // AWS Access Key ID and AWS Secret Key must be defined
497
+ if ( isUndefined ( awsAccessId ) || ( isUndefined ( awsSecretKey ) ) ) {
498
+ console . log ( 'To connect via WebSocket/SigV4, AWS Access Key ID and AWS Secret Key must be passed either in options or as environment variables; see README.md' ) ;
499
+ throw new Error ( exceptions . INVALID_CONNECT_OPTIONS ) ;
500
+ }
501
+ } else {
502
+ if ( isUndefined ( options . customAuthHeaders ) ) {
503
+ console . log ( 'To authenticate with a custom authorizer, you must provide the required HTTP headers; see README.md' ) ;
504
+ throw new Error ( exceptions . INVALID_CONNECT_OPTIONS ) ;
505
+ }
455
506
}
456
- if ( ! isUndefined ( options . host ) ) {
457
- var pattern = / [ a - z A - Z 0 - 9 ] + \. i o t \. ( [ a - z ] + - [ a - z ] + - [ 0 - 9 ] + ) \. a m a z o n a w s \. .+ / ;
507
+
508
+ if ( ! isUndefined ( options . host ) && isUndefined ( options . region ) ) {
509
+ var pattern = / [ a - z A - Z 0 - 9 ] + \. i o t \. ( [ a - z ] + - [ a - z ] + - [ 0 - 9 ] + ) \. a m a z o n a w s \. .+ / ;
458
510
var region = pattern . exec ( options . host ) ;
459
511
if ( region === null ) {
460
512
console . log ( 'Host endpoint is not valid' ) ;
@@ -463,11 +515,6 @@ function DeviceClient(options) {
463
515
options . region = region [ 1 ] ;
464
516
}
465
517
}
466
- // AWS Access Key ID and AWS Secret Key must be defined
467
- if ( isUndefined ( awsAccessId ) || ( isUndefined ( awsSecretKey ) ) ) {
468
- console . log ( 'To connect via WebSocket/SigV4, AWS Access Key ID and AWS Secret Key must be passed either in options or as environment variables; see README.md' ) ;
469
- throw new Error ( exceptions . INVALID_CONNECT_OPTIONS ) ;
470
- }
471
518
// set port, do not override existing definitions if available
472
519
if ( isUndefined ( options . port ) ) {
473
520
options . port = 443 ;
@@ -480,7 +527,11 @@ function DeviceClient(options) {
480
527
} else {
481
528
options . websocketOptions . protocol = 'mqttv3.1' ;
482
529
}
483
- }
530
+
531
+ if ( options . protocol === 'wss-custom-auth' ) {
532
+ options . websocketOptions . headers = options . customAuthHeaders ;
533
+ }
534
+ }
484
535
485
536
if ( ( ! isUndefined ( options ) ) && ( options . debug === true ) ) {
486
537
console . log ( options ) ;
@@ -556,7 +607,8 @@ function DeviceClient(options) {
556
607
}
557
608
558
609
function _wrapper ( client ) {
559
- if ( options . protocol === 'wss' ) {
610
+ var protocol = options . protocol ;
611
+ if ( protocol === 'wss' ) {
560
612
var url ;
561
613
//
562
614
// If the access id and secret key are available, prepare the URL.
@@ -573,8 +625,15 @@ function DeviceClient(options) {
573
625
}
574
626
575
627
options . url = url ;
628
+ } else if ( protocol === 'wss-custom-auth' ) {
629
+ options . url = prepareWebSocketCustomAuthUrl ( options ) ;
630
+ if ( options . debug === true ) {
631
+ console . log ( 'using websockets custom auth, will connect to \'' + options . url + '\'...' ) ;
632
+ }
633
+ // Treat the request as a standard websocket request from here onwards
634
+ protocol = 'wss' ;
576
635
}
577
- return protocols [ options . protocol ] ( client , options ) ;
636
+ return protocols [ protocol ] ( client , options ) ;
578
637
}
579
638
580
639
var device = new mqtt . MqttClient ( _wrapper , options ) ;
@@ -748,6 +807,12 @@ function DeviceClient(options) {
748
807
device . on ( 'error' , function ( error ) {
749
808
that . emit ( 'error' , error ) ;
750
809
} ) ;
810
+ device . on ( 'packetsend' , function ( packet ) {
811
+ that . emit ( 'packetsend' , packet ) ;
812
+ } ) ;
813
+ device . on ( 'packetreceive' , function ( packet ) {
814
+ that . emit ( 'packetreceive' , packet ) ;
815
+ } ) ;
751
816
device . on ( 'message' , function ( topic , message , packet ) {
752
817
that . emit ( 'message' , topic , message , packet ) ;
753
818
} ) ;
@@ -834,6 +899,15 @@ function DeviceClient(options) {
834
899
awsSecretKey = secretKey ;
835
900
awsSTSToken = sessionToken ;
836
901
} ;
902
+ this . getWebsocketHeaders = function ( ) {
903
+ return options . websocketOptions . headers ;
904
+ } ;
905
+ //
906
+ // Call this function to update the custom auth headers
907
+ //
908
+ this . updateCustomAuthHeaders = function ( newHeaders ) {
909
+ options . websocketOptions . headers = newHeaders ;
910
+ } ;
837
911
//
838
912
// Used for integration testing only
839
913
//
@@ -855,3 +929,4 @@ module.exports.DeviceClient = DeviceClient;
855
929
// Exported for unit testing only
856
930
//
857
931
module . exports . prepareWebSocketUrl = prepareWebSocketUrl ;
932
+ module . exports . prepareWebSocketCustomAuthUrl = prepareWebSocketCustomAuthUrl ;
0 commit comments