UNPKG

gatt-ip-js

Version:

GATT-IP library is A simple javascript protocol to connect any Bluetooth Smart (GATT) Device to the IP network

117 lines (106 loc) 4.1 kB
var ee = require('./event-emitter'); var C = require('./constants').C; var ApplicationError = require('./../errors').ApplicationError; var id = 1; var hackAlert1Sent = false; var hackAlert2Sent = false; function MessageContext(processor, msg, userContext, timeoutMs) { this.msg = msg; this.userContext = userContext; if ('undefined' == typeof msg.id) { msg.id = Number(id++).toString(); } this.id = msg.id; if (!timeoutMs) { timeoutMs = C.DEFAULT_MESSAGE_TIMEOUT_MS; } var self = this; this.timeout = setTimeout(function () { delete self.timeout; console.warn("Timeout occurred for message", JSON.stringify(msg)); processor.emit('error', new ApplicationError("Timed out : "+ JSON.stringify(msg)), self.userContext.cb); }, timeoutMs ); } function MessageProcessor() { ee.instantiateEmitter(this); var self = this; var pendingMessages = {}; /** * Registers a message with ID and callback into the message queue so that we can correspond it when we get the callback and and then invoke the callback * @param msg Message to send * @param userContext an arbitrary context that will be stored and returned when the response is received * @param timeoutMs Optional timeout for the message response to be received * @returns {*} */ this.register = function (msg, userContext, timeoutMs) { if (Object.keys(pendingMessages).length > C.MAX_PENDING_MESSAGES) { throw new ApplicationError("Message queue is full", msg); } var entry = new MessageContext(self, msg, userContext, timeoutMs); pendingMessages[entry.id] = entry; return entry.msg; }; this.hasMessage = function (msgId) { var entry = pendingMessages['' + msgId]; return !!entry; }; this.onMessageReceived = function (msg) { var entry; if (msg.params && msg.params.id) { console.warn("HACK ALERT: ID is in params!?!"); msg.id = msg.params.id; } if (msg.id) { entry = pendingMessages['' + msg.id]; } if (!entry) { if (!msg.id) { if (msg.result == C.kMessage) { if (!hackAlert1Sent) { hackAlert1Sent = true; console.warn("HACK ALERT: Hacking the authenticate message"); } msg.id = '1'; entry = pendingMessages['1']; } else { self.emit('indication', msg); return; } } else { if (msg.result == C.kScanForPeripherals && msg.params && msg.params.bb) { if (!hackAlert2Sent) { hackAlert2Sent = true; console.warn("HACK ALERT: Scan response has an ID"); } self.emit('indication', msg); return; } self.emit('request', msg); return; } } if (entry.timeout) { clearTimeout(entry.timeout); } delete pendingMessages[msg.id]; self.emit('response', msg, entry.userContext, entry.msg); }; this.flushRequests = function (filter) { for (var i in pendingMessages) { if (pendingMessages.hasOwnProperty(i)) { var entry = pendingMessages[i]; // if filter is not passed, or if filter invocation returns true if (!filter || filter(entry.userContext)) { if (entry.timeout) { clearTimeout(entry.timeout); } delete pendingMessages[i]; } } } } } ee.makeEmitter(MessageProcessor); module.exports.MessageProcessor = MessageProcessor;