Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

coap

Package Overview
Dependencies
Maintainers
1
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

coap - npm Package Compare versions

Comparing version 0.6.1 to 0.7.0

examples/blockwise.js

58

lib/agent.js

@@ -22,2 +22,5 @@ /*

, RetrySend = require('./retry_send')
, parseBlock2 = require('./helpers').parseBlock2
, createBlock2 = require('./helpers').createBlock2
, getOption = require('./helpers').getOption
, maxToken = Math.pow(2, 32)

@@ -163,6 +166,54 @@ , maxMessageId = Math.pow(2, 16)

if (req.response)
var block2Buff = getOption(packet.options, 'Block2')
var block2
// if we got blockwise (2) response
if (block2Buff) {
block2 = parseBlock2(block2Buff)
// check for error
if (!block2) {
req.sender.reset()
return req.emit('error', err)
}
}
if (block2) {
// accumulate payload
req._totalPayload = Buffer.concat([req._totalPayload, packet.payload])
if (block2.moreBlock2) {
// increase message id for next request
delete this._msgIdToReq[req._packet.messageId]
req._packet.messageId = that._nextMessageId()
this._msgIdToReq[req._packet.messageId] = req
// next block2 request
var block2Val = createBlock2({
moreBlock2: false,
num: block2.num+1,
size: block2.size
})
if (!block2Val) {
req.sender.reset()
return req.emit('error', err)
}
req.setOption('Block2', block2Val)
req.sender.send(generate(req._packet))
return
}
else {
// get full payload
packet.payload = req._totalPayload
// clear the payload incase of block2
req._totalPayload = new Buffer(0)
}
}
if (req.response) {
// it is an observe request
// and we are already streaming
return req.response.append(packet)
}
else if (block2) {
delete that._tkToReq[req._packet.token.readUInt32BE(0)]
}
else if (!req.url.observe)

@@ -178,4 +229,5 @@ // it is not, so delete the token

})
} else
} else {
response = new IncomingMessage(packet, rsinfo)
}

@@ -264,2 +316,4 @@ req.response = response

req._totalPayload = new Buffer(0)
return req

@@ -266,0 +320,0 @@ }

@@ -118,1 +118,84 @@ /*

}
/*
get an option value from options
options array of object, in form {name: , value}
name name of the object wanted to retrive
return value, or null
*/
module.exports.getOption = function getOption(options, name) {
for (var i in options)
if (options[i].name == name)
return options[i].value
return null
}
/*
parse block2
value block2 value buffer
return object describes block2, {moreBlock2: , num: , size: }
with invalid block2 value, the function return null
*/
module.exports.parseBlock2 = function parseBlock2(block2Value) {
var num
switch (block2Value.length) {
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
}
// limit value of size is 1024 (2**(6+4))
if (block2Value.slice(-1)[0] == 7) {
// Block size is bigger than 1024
return null
}
return {
moreBlock2: (block2Value.slice(-1)[0] & (0x01<<3))? true:false,
num: num,
size: Math.pow(2, (block2Value.slice(-1)[0] & 0x07)+4)
}
}
/*
create buffer for block2 option
requestedBlock object contain block2 infor, e.g. {moreBlock2: true, num: 100, size: 32}
return new Buffer, carry block2 value
*/
module.exports.createBlock2 = function createBlock2(requestedBlock) {
var byte
var szx = Math.log(requestedBlock.size)/Math.log(2) - 4
var m = ((requestedBlock.moreBlock2==true)?0:1)
var num = requestedBlock.num
var extraNum
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) {
extraNum = null
}
else if (num <=0xfff) {
extraNum = new Buffer([num/16])
}
else if (num <=0xfffff) {
extraNum = new Buffer(2)
extraNum.writeUInt16BE(num>>4,0)
}
else {
// too big block2 number
return null
}
return (extraNum)? Buffer.concat([extraNum, new Buffer([byte])]):new Buffer([byte])
}

@@ -50,2 +50,5 @@ /*

// default max packet size
p.maxPacketSize = 1280
module.exports = p

@@ -20,2 +20,5 @@ /*

, RetrySend = require('./retry_send')
, parseBlock2 = require('./helpers').parseBlock2
, createBlock2 = require('./helpers').createBlock2
, getOption = require('./helpers').getOption

@@ -66,2 +69,4 @@ function CoAPServer(options, listener) {

if (listener)

@@ -117,3 +122,3 @@ this.on('request', listener)

, cached = lru.peek(toKey(rsinfo.address, rsinfo.port, packet, true))
, Message = OutgoingMessage
, Message = OutMessage
, that = this

@@ -153,3 +158,3 @@ , request

if (Message === OutgoingMessage) {
if (Message === OutMessage) {
sender.on('error', response.emit.bind(response, 'error'))

@@ -174,2 +179,13 @@ } else {

// if (response instanceof OutMessage) {
response._request = request._packet
// }
// todo:
// should use mem cache to buffer responses
// dont alway bother uper layer, especially when the return is in blockwise (2)
// if (cachedPayload)
// response.end(cachedPayload);
// else
// this.emit('request', request, response)
this.emit('request', request, response)

@@ -187,2 +203,96 @@ }

/*
new out message
inherit from OutgoingMessage
to handle cached answer and blockwise (2)
*/
function OutMessage() {
OutgoingMessage.apply(this, Array.prototype.slice.call(arguments));
}
util.inherits(OutMessage, OutgoingMessage)
// maxBlock2 is in formular 2**(i+4), and must <= 2**(6+4)
var maxBlock2 = Math.pow(2, Math.floor(Math.log(parameters.maxPacketSize)/Math.log(2)))
if (maxBlock2 > Math.pow(2, (6+4)))
maxBlock2 = Math.pow(2, (6+4))
OutMessage.prototype.end= function(payload) {
var that = this
var block2Buff = getOption(this._request.options, 'Block2')
var requestedBlockOption
// if we got blockwise (2) resquest
if (block2Buff) {
requestedBlockOption = parseBlock2(block2Buff)
// bad option
if (!requestedBlockOption) {
that.statusCode = '4.02'
return OutgoingMessage.prototype.end.call(that)
}
}
// if payload is suitable for ONE message, shoot it out
if (!payload ||
((!requestedBlockOption) && (payload.length < parameters.maxPacketSize)))
return OutgoingMessage.prototype.end.call(this, payload)
// for the first request, block2 option may be missed
if (!requestedBlockOption)
requestedBlockOption = {
size: maxBlock2,
num: 0
}
// block2 size should not bigger than maxBlock2
if (requestedBlockOption.size > maxBlock2)
requestedBlockOption.size = maxBlock2
// block number should have limit
// 0 base counter for totalBlock, hence use floor (vs ceil)
var totalBlock = Math.floor(payload.length/requestedBlockOption.size)
var isLastBlock
if (requestedBlockOption.num < totalBlock)
isLastBlock = false
else if (requestedBlockOption.num == totalBlock)
isLastBlock = true
else {
// precondition fail, may request for out of range block
that.statusCode = '4.02'
return OutgoingMessage.prototype.end.call(that)
}
var block2 = createBlock2({
moreBlock2: isLastBlock,
num: requestedBlockOption.num,
size: requestedBlockOption.size
})
if (!block2) {
// this catch never be match,
// since we're gentleman, just handle it
that.statusCode = '4.02'
return OutgoingMessage.prototype.end.call(that)
}
this.setOption('Block2', block2)
this.setOption('ETag', _toETag(payload))
OutgoingMessage.prototype.end.call(this, payload.slice((requestedBlockOption.num)*requestedBlockOption.size, (requestedBlockOption.num+1)*requestedBlockOption.size))
};
/*
calculate id of a payload by xor each 2-byte-block from it
use to generate etag
payload an input buffer, represent payload need to generate id (hash)
id return var, is a buffer(2)
*/
function _toETag(payload) {
var id = new Buffer([0,0])
var i = 0
do {
id[0] ^= payload[i]
id[1] ^= payload[i+1]
i += 2
} while (i<payload.length)
return id
}
module.exports = CoAPServer

4

package.json
{
"name": "coap",
"version": "0.6.1",
"version": "0.7.0",
"description": "A CoAP library for node modelled after 'http'",

@@ -37,6 +37,6 @@ "main": "index.js",

"dependencies": {
"bl": "~0.7.0",
"coap-packet": "~0.1.8",
"bl": "~0.7.0",
"lru-cache": "~2.5.0"
}
}

@@ -28,7 +28,8 @@ node-coap

This library follows the
[draft-18](http://tools.ietf.org/html/draft-ietf-core-coap-18) of the standard.
Moreover, it supports the
[observe-11](http://tools.ietf.org/html/draft-ietf-core-observe-11)
specification.
This library follows:
* [draft-18](http://tools.ietf.org/html/draft-ietf-core-coap-18) of CoAP.
* [observe-11](http://tools.ietf.org/html/draft-ietf-core-observe-11)
for the observe specification.
* [block-14](http://tools.ietf.org/id/draft-ietf-core-block-14.txt) for
the blockwise specification.

@@ -262,4 +263,8 @@ It does not parse the protocol but it use

Also, `'Content-Type'` is aliased to `'Content-Format'` for HTTP
compatibility.
compatibility.gg
Since v0.7.0, this library supports blockwise transfers, you can trigger
them by adding a `req.setOption('Block2', new Buffer([0x2]))` to the
output of [request](#request).
See the

@@ -449,2 +454,3 @@ [spec](http://tools.ietf.org/html/draft-ietf-core-coap-18#section-5.4)

<tr><th align="left">Matteo Collina</th><td><a href="https://github.com/mcollina">GitHub/mcollina</a></td><td><a href="https://twitter.com/matteocollina">Twitter/@matteocollina</a></td></tr>
<tr><th align="left">Nguyen Quoc Dinh</th><td><a href="https://github.com/nqd">GitHub/nqd</a></td><td><a href="https://twitter.com/nqdinh">Twitter/@nqdinh</a></td></tr>
</tbody></table>

@@ -451,0 +457,0 @@

@@ -184,13 +184,2 @@

it('should have res emitting an error if the message is too big', function(done) {
send(generate())
server.on('request', function(req, res) {
res.on('error', function() {
done()
})
res.end(new Buffer(1280))
})
})
it('should expose the options', function(done) {

@@ -197,0 +186,0 @@ var options = [{

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc