All files / node-coap/lib retry_send.js

100% Statements 46/46
100% Branches 18/18
100% Functions 7/7
100% Lines 46/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88                    1x 1x 1x 1x     975x 2x     973x   973x   973x   973x   973x 973x 973x 973x   973x 61x 61x       1x   1x 1408x   1408x   1408x 1408x 1x       1408x 1408x 1347x 1347x     1408x 719x   1408x     1x 1347x     1347x 1347x   1347x 1347x 14x 14x 14x 8x 14x       1x 1237x 1237x     1x  
'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 parameters      = require('./parameters')
  , util            = require('util')
  , EventEmitter    = require('events').EventEmitter
  , parse           = require('coap-packet').parse
 
function RetrySend(sock, port, host, maxRetransmit) {
  if (!(this instanceof RetrySend)) {
    return new RetrySend(sock, port, host, maxRetransmit)
  }
 
  var that    = this
 
  this._sock  = sock
 
  this._port  = port || parameters.coapPort
 
  this._host  = host
 
  this._maxRetransmit = maxRetransmit || parameters.maxRetransmit
  this._sendAttemp = 0
  this._lastMessageId = -1
  this._currentTime = parameters.ackTimeout * (1 + (parameters.ackRandomFactor - 1) * Math.random()) * 1000
 
  this._bOff = function() {
    that._currentTime = that._currentTime * 2
    that._send()
  }
}
 
util.inherits(RetrySend, EventEmitter)
 
RetrySend.prototype._send = function(avoidBackoff) {
  var that = this
 
  this._sock.send(this._message, 0, this._message.length,
                  this._port, this._host, function(err, bytes) {
                    that.emit('sent', err, bytes)
                    if (err) {
                      that.emit('error', err)
                    }
                  })
 
  var messageId = parse(this._message).messageId
  if (messageId != this._lastMessageId) {
    this._lastMessageId = messageId
    this._sendAttemp = 0
  }
 
  if (!avoidBackoff && ++this._sendAttemp <= this._maxRetransmit)
    this._bOffTimer = setTimeout(this._bOff, this._currentTime)
 
  this.emit('sending', this._message)
}
 
RetrySend.prototype.send = function(message, avoidBackoff) {
  var that = this
    , timeout
 
  this._message = message
  this._send(avoidBackoff)
 
  timeout = avoidBackoff ? parameters.maxRTT : parameters.exchangeLifetime
  this._timer = setTimeout(function() {
    var err  = new Error('No reply in ' + timeout + 's')
    err.retransmitTimeout = timeout
    if (!avoidBackoff)
      that.emit('error', err)
    that.emit('timeout', err)
  }, timeout * 1000)
}
 
RetrySend.prototype.reset = function() {
  clearTimeout(this._timer)
  clearTimeout(this._bOffTimer)
}
 
module.exports = RetrySend