UNPKG

coap

Version:

A CoAP library for node modelled after 'http'

260 lines 7.44 kB
"use strict"; /* * Copyright (c) 2013-2021 node-coap contributors. * * node-coap is licensed under an MIT +no-false-attribs license. * All rights not explicitly granted in the MIT license are reserved. * See the included LICENSE file for more details. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.genAck = genAck; exports.setOption = setOption; exports.toCode = toCode; exports.packetToMessage = packetToMessage; exports.hasOption = hasOption; exports.getOption = getOption; exports.removeOption = removeOption; exports.parseBlock2 = parseBlock2; exports.createBlock2 = createBlock2; exports.or = or; exports.isOption = isOption; exports.isNumeric = isNumeric; exports.isBoolean = isBoolean; const option_converter_1 = require("./option_converter"); const capitalize_1 = __importDefault(require("capitalize")); const codes = { 0.01: 'GET', 0.02: 'POST', 0.03: 'PUT', 0.04: 'DELETE', 0.05: 'FETCH', 0.06: 'PATCH', 0.07: 'iPATCH' }; function genAck(request) { return { messageId: request.messageId, code: '0.00', options: [], confirmable: false, ack: true, reset: false }; } const optionAliases = { 'Content-Type': 'Content-Format', Etag: 'ETag' }; function setOption(packet, name, values) { var _a, _b, _c, _d; name = capitalize_1.default.words(name); name = (_a = optionAliases[name]) !== null && _a !== void 0 ? _a : name; const optionName = name; if ((0, option_converter_1.isIgnored)(name)) { return; } packet.options = (_b = packet.options) === null || _b === void 0 ? void 0 : _b.filter((option) => { return option.name !== name; }); if (!Array.isArray(values)) { (_c = packet.options) === null || _c === void 0 ? void 0 : _c.push({ name: optionName, value: (0, option_converter_1.toBinary)(name, values) }); } else { for (const value of values) { (_d = packet.options) === null || _d === void 0 ? void 0 : _d.push({ name: optionName, value }); } } } function toCode(code) { if (typeof code === 'string') { return code; } const codeClass = Math.floor(code / 100); const codeDetail = String(code - codeClass * 100).padStart(2, "0"); return `${codeClass}.${codeDetail}`; } function packetToMessage(dest, packet) { var _a; const options = (_a = packet.options) !== null && _a !== void 0 ? _a : []; const paths = []; const queries = []; let query = ''; dest.payload = packet.payload; dest.options = packet.options; dest.code = packet.code; dest.method = codes[dest.code]; dest.headers = {}; for (let i = 0; i < options.length; i++) { const option = options[i]; if (typeof option.name !== 'string') { continue; } if (option.name === 'Uri-Path') { paths.push(option.value); } if (option.name === 'Uri-Query') { queries.push(option.value); } option.value = (0, option_converter_1.fromBinary)(option.name, option.value); if (option.value != null && !Buffer.isBuffer(option.value)) { dest.headers[option.name] = option.value; } } if (dest.headers['Content-Format'] != null) { dest.headers['Content-Type'] = dest.headers['Content-Format']; } query = queries.join('&'); let url = '/' + paths.join('/'); if (query !== '') { url += '?' + query; } dest.url = url; } function hasOption(options, name) { for (const option of options) { if (option.name === name) { return true; } } return null; } /** * get an option value from options * * @param options array of object, in form `{name: value}` * @param name name of the object wanted to retrive * @returns `value`, or null */ function getOption(options, name) { if (options == null) { return null; } for (const option of options) { if (option.name === name) { return option.value; } } return null; } /** * Remove an option value from options * * @param options array of object, in form {name: value} * @param name name of the object wanted to remove * @returns `true` if the option was found and removed */ function removeOption(options, name) { let result = false; options.forEach((option, index) => { if (option.name === name) { options.splice(index, 1); result = true; } }); return result; } /** * Parse an encoded block2 option and return a block state object. * * @param block2Value block2 value buffer * @returns Block state object with `num`, `size`, and `more` flag. * With an invalid block2 value, the function will return `null`. */ function parseBlock2(block2Value) { let num; switch (block2Value.length) { case 0: return { more: 0, size: 0, num: 0 }; case 1: num = block2Value[0] >> 4; break; case 2: num = (block2Value[0] * 256 + block2Value[1]) >> 4; break; case 3: num = (block2Value[0] * 256 * 256 + block2Value[1] * 256 + block2Value[2]) >> 4; break; default: // Block2 is more than 3 bytes return null; } const lastByte = block2Value.slice(-1)[0]; // limit value of size is 1024 (2**(6+4)) if ((lastByte & 7) === 7) { // Block size is bigger than 1024 return null; } const more = (lastByte & 8) >> 3; return { more, num, size: Math.pow(2, (lastByte & 7) + 4) }; } /** * Create buffer for block2 option * * @param requestedBlock Object containing block2 information * @returns Buffer carrying block2 value */ function createBlock2(requestedBlock) { const szx = Math.log(requestedBlock.size) / Math.log(2) - 4; const m = requestedBlock.more; const num = requestedBlock.num; let extraNum; let byte = 0; byte |= szx; byte |= m << 3; byte |= (num & 0xf) << 4; // total num occupy up to 5 octets // num share the higher octet of first byte, and (may) take more 2 bytes for the rest 4 octets if (num <= 0xf) { return Buffer.of(byte); } else if (num <= 0xfff) { extraNum = Buffer.of(num / 16); } else if (num <= 0xfffff) { extraNum = Buffer.alloc(2); extraNum.writeUInt16BE(num >> 4, 0); } else { // too big block2 number return null; } return Buffer.concat([extraNum, Buffer.of(byte)]); } /** * Provide a or function to use with the reduce() Array method * * @param previous * @param current * @returns */ function or(previous, current) { return previous || current; } /** * Provide a function to detect whether an option has a particular name (for its use with filter or map). * * @param optionName * @returns */ function isOption(optionName) { return (option) => { return option.name === optionName; }; } function isNumeric(n) { return !isNaN(parseFloat(n)) && isFinite(n); } function isBoolean(n) { return typeof (n) === 'boolean'; } //# sourceMappingURL=helpers.js.map