Skip to content

Commit

Permalink
fix: encode 0 in observe option with zero byte length (#345)
Browse files Browse the repository at this point in the history
* fix: encode 0 in observe option with zero bytes

* test: adjust tests to new encoding of observe option
  • Loading branch information
JKRhb committed May 18, 2022
1 parent 412a400 commit 9204024
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 12 deletions.
38 changes: 29 additions & 9 deletions lib/agent.ts
Expand Up @@ -512,15 +512,7 @@ class Agent extends EventEmitter {
}, multicastTimeout)
}

if (typeof (url.observe) === 'number') {
req.setOption('Observe', url.observe)
} else if (typeof (url.observe) === 'string') {
req.setOption('Observe', parseInt(url.observe))
} else if (url.observe === true) {
req.setOption('Observe', 0)
} else {
req.on('response', this._cleanUp.bind(this))
}
this._setObserveOption(req, req.url)

this._requests++

Expand All @@ -529,6 +521,34 @@ class Agent extends EventEmitter {
return req
}

_setObserveOption (req: OutgoingMessage, requestParameters: CoapRequestParams): void {
const observeParameter = requestParameters.observe

if (observeParameter == null) {
req.on('response', this._cleanUp.bind(this))
return
}

// `null` indicates an option value of zero here, encoded with zero length.
// Using `null` avoids issues with some devices that cannot process an
// option value of 0 that is encoded as a byte containing eight zeros.
let observeValue: null | number

if (typeof observeParameter === 'number') {
observeValue = observeParameter === 0 ? null : observeParameter
} else if (typeof observeParameter === 'string') {
observeValue = parseInt(observeParameter)
} else if (observeParameter) {
observeValue = null
} else {
return
}

if (observeValue == null || !isNaN(observeValue)) {
req.setOption('Observe', observeValue)
}
}

abort (req: OutgoingMessage): void {
req.sender.removeAllListeners()
req.sender.reset()
Expand Down
2 changes: 1 addition & 1 deletion models/models.ts
Expand Up @@ -16,7 +16,7 @@ import CoAPServer from '../lib/server'

export declare function requestListener (req: IncomingMessage, res: OutgoingMessage): void

export type OptionValue = string | number | Buffer | Buffer[]
export type OptionValue = null | string | number | Buffer | Buffer[]
export type BlockCacheMap<T> = Map<string, {payload: T, timeoutId: NodeJS.Timeout}>
export type CoapOptions = Partial<Record<OptionName, OptionValue>>

Expand Down
2 changes: 1 addition & 1 deletion test/request.ts
Expand Up @@ -1422,7 +1422,7 @@ describe('request', function () {
server.on('message', (msg, rsinfo) => {
const packet = parse(msg)
expect(packet.options[0].name).to.eql('Observe')
expect(packet.options[0].value).to.eql(Buffer.of(0))
expect(packet.options[0].value).to.eql(Buffer.alloc(0))
done()
})
})
Expand Down
2 changes: 1 addition & 1 deletion test/server.ts
Expand Up @@ -1320,7 +1320,7 @@ describe('Client Identifier', function () {
authenticationHeader = request._packet.options.find(o => o.name === 2109)
}

if (typeof authenticationHeader !== 'undefined') {
if (authenticationHeader?.value != null) {
return `auth:${authenticationHeader.value.toString()}`
}
return `unauth:${request.rsinfo.address}:${request.rsinfo.port}`
Expand Down

0 comments on commit 9204024

Please sign in to comment.