Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if (!method || !resource || !properties || !body) {
throw new ReferenceError('required parameter is missing');
}
/* Codes_SRS_NODE_DEVICE_AMQP_06_017: [The `sendTwinRequest` method shall throw an `ArgumentError` if the `method` argument is not a string.] */
/* Codes_SRS_NODE_DEVICE_AMQP_06_018: [The `sendTwinRequest` method shall throw an `ArgumentError` if the `resource` argument is not a string.] */
if (!this._isString(method) || !this._isString(resource)) {
throw new errors.ArgumentError('required string parameter is not a string');
}
/* Codes_SRS_NODE_DEVICE_AMQP_06_019: [The `sendTwinRequest` method shall throw an `ArgumentError` if the `properties` argument is not a an object.] */
if (!(properties instanceof Object)) {
throw new errors.ArgumentError('required properties parameter is not an object');
}
let amqpMessage = new AmqpMessage();
amqpMessage.messageAnnotations = {};
amqpMessage.properties = {};
//
// Amqp requires that the resource designation NOT be terminated by a slash. The agnostic twin client was terminating the
// resources with a slash which worked just dandy for MQTT.
//
// We need to cut off a terminating slash. If we cut off a terminating slash and the length of resource is zero then simply
// don't specify a resource.
//
// What if the caller specifies a "//" resource? Don't do that.
//
// So you'll note that in this case "/" sent down will be turned into an empty string. So why not
// simply send down "" to begin with? Because you can't send a falsy parameter.
//
/* Codes_SRS_NODE_DEVICE_AMQP_06_020: [The `method` argument shall be the value of the amqp message `operation` annotation.] */
testSubject.getFeedbackReceiver(function (err, receiver) {
if (err) done(err);
else {
assert.instanceOf(receiver, AmqpReceiver);
done();
}
});
});
constructor(config: Client.Config, baseClient?: BaseAmqpClient) {
super();
this._config = config;
this._amqp = baseClient || new BaseAmqpClient(false, 'azure-iot-device/' + packageJson.version);
this._amqp.setDisconnectHandler((err) => {
debug('disconnected event handler: ' + (err ? err.toString() : 'no error'));
this._fsm.handle('disconnect', () => {
this.emit('disconnect', getTranslatedError(err, 'AMQP client disconnected'));
});
});
this._deviceMethodClient = new AmqpDeviceMethodClient(this._config, this._amqp);
/*Codes_SRS_NODE_DEVICE_AMQP_16_041: [Any `error` event received on any of the links used for device methods shall trigger the emission of an `error` event by the transport, with an argument that is a `MethodsDetachedError` object with the `innerError` property set to that error.]*/
this._deviceMethodClient.on('error', (err) => {
let methodsError = new errors.DeviceMethodsDetachedError('Device Methods AMQP links failed');
methodsError.innerError = err;
this.emit('error', methodsError);
});
this._twinClient = new AmqpTwinClient(this._config, this._amqp);
this._receiver.on('message', (amqpMessage) => {
/*Codes_SRS_NODE_SERVICE_RECEIVER_16_006: [The `ServiceReceiver` class shall convert any `AmqpMessage` received with the `message` event from the `ReceiverLink` object into `Message` objects and emit a `message` event with that newly created `Message` object for argument.]*/
this.emit('message', AmqpMessage.toMessage(amqpMessage));
});
const getTranslatedError = function(err?: Error, message?: string): Error {
if (err instanceof errors.UnauthorizedError || err instanceof errors.NotConnectedError || err instanceof errors.DeviceNotFoundError) {
return err;
}
return translateError(message, err);
};
return function (err?: Error, result?: any): void {
if (err) {
done(translateError(errorMessage, err));
} else {
done(null, result);
}
};
};
this._senderLink.send(requestMessage, (err) => {
if (err) {
delete this._operations[requestMessage.correlation_id];
const translatedError = translateError('registration failure', err);
/*Codes_SRS_NODE_PROVISIONING_AMQP_06_007: [If the `registrationRequest` send request is rejected with an `InternalError` or `ThrottlingError`, the result.status value will be set with `registering` and the callback will be invoked with *no* error object.] */
if ((translatedError instanceof errors.InternalServerError) || ((translatedError as AmqpTransportError) instanceof errors.ThrottlingError)) {
debug('retryable error on registration: ' + err.name);
let retryAfterInMilliseconds: number;
/*Codes_SRS_NODE_PROVISIONING_AMQP_06_009: [If the `registrationRequest` rejection error contains the info property`retry-after`, it will be interpreted as the number of seconds that should elapse before the next attempted operation. Otherwise default.] */
if ((err as any).info && (err as any).info[MessagePropertyNames.retryAfter]) {
retryAfterInMilliseconds = Number(((err as any).info[MessagePropertyNames.retryAfter] as string)) * 1000;
} else {
retryAfterInMilliseconds = this._config.pollingInterval;
}
callback(null, {status: 'registering'}, null, retryAfterInMilliseconds);
} else {
debug('non-retryable error on registration: ' + err.name);
/*Codes_SRS_NODE_PROVISIONING_AMQP_16_011: [The `registrationRequest` method shall call its callback with an error if the transport fails to send the request message.]*/
callback(err);
}
this._deviceMethodClient.detach((detachErr) => {
if (detachErr) {
debug('error detaching methods links: ' + detachErr.toString());
if (!finalError) {
finalError = translateError('error while detaching the methods links when disconnecting', detachErr);
}
} else {
debug('device methods links detached.');
}
callback();
});
}
this._stopC2DListener(err, (detachErr) => {
if (!finalError && detachErr) {
finalError = translateError('error while detaching the D2C link when disconnecting', detachErr);
}
callback();
});
} else {
this._amqp.connect(uri, this._config.x509, (err, connectResult) => {
if (err) {
this._fsm.transition('disconnected', connectCallback, translateError('AMQP Transport: Could not connect', err));
} else {
this._fsm.transition('authenticating', connectCallback, connectResult);
}
});
},