| 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 | (function ExportLibrary(root, factory) { |
| 85 | if(typeof exports === 'object' && typeof module === 'object'){ |
| 86 | module.exports = factory(); |
| 87 | } else if (typeof define === 'function' && define.amd){ |
| 88 | define(factory); |
| 89 | } else if (typeof exports === 'object'){ |
| 90 | exports = factory(); |
| 91 | } else { |
| 92 | if (typeof root.Paho === 'undefined'){ |
| 93 | root.Paho = {}; |
| 94 | } |
| 95 | root.Paho.MQTT = factory(); |
| 96 | } |
| 97 | })(this, function LibraryFactory(){ |
| 98 | |
| 99 | |
| 100 | var PahoMQTT = (function (global) { |
| 101 | |
| 102 | |
| 103 | |
| 104 | |
| 105 | var version = "@VERSION@"; |
| 106 | var buildLevel = "@BUILDLEVEL@"; |
| 107 | |
| 108 | |
| 109 | |
| 110 | |
| 111 | |
| 112 | |
| 113 | var MESSAGE_TYPE = { |
| 114 | CONNECT: 1, |
| 115 | CONNACK: 2, |
| 116 | PUBLISH: 3, |
| 117 | PUBACK: 4, |
| 118 | PUBREC: 5, |
| 119 | PUBREL: 6, |
| 120 | PUBCOMP: 7, |
| 121 | SUBSCRIBE: 8, |
| 122 | SUBACK: 9, |
| 123 | UNSUBSCRIBE: 10, |
| 124 | UNSUBACK: 11, |
| 125 | PINGREQ: 12, |
| 126 | PINGRESP: 13, |
| 127 | DISCONNECT: 14 |
| 128 | }; |
| 129 | |
| 130 | |
| 131 | |
| 132 | |
| 133 | |
| 134 | |
| 135 | |
| 136 | |
| 137 | |
| 138 | |
| 139 | |
| 140 | |
| 141 | |
| 142 | |
| 143 | var validate = function(obj, keys) { |
| 144 | for (var key in obj) { |
| 145 | if (obj.hasOwnProperty(key)) { |
| 146 | if (keys.hasOwnProperty(key)) { |
| 147 | if (typeof obj[key] !== keys[key]) |
| 148 | throw new Error(format(ERROR.INVALID_TYPE, [typeof obj[key], key])); |
| 149 | } else { |
| 150 | var errorStr = "Unknown property, " + key + ". Valid properties are:"; |
| 151 | for (var validKey in keys) |
| 152 | if (keys.hasOwnProperty(validKey)) |
| 153 | errorStr = errorStr+" "+validKey; |
| 154 | throw new Error(errorStr); |
| 155 | } |
| 156 | } |
| 157 | } |
| 158 | }; |
| 159 | |
| 160 | |
| 161 | |
| 162 | |
| 163 | |
| 164 | |
| 165 | |
| 166 | |
| 167 | |
| 168 | var scope = function (f, scope) { |
| 169 | return function () { |
| 170 | return f.apply(scope, arguments); |
| 171 | }; |
| 172 | }; |
| 173 | |
| 174 | |
| 175 | |
| 176 | |
| 177 | |
| 178 | |
| 179 | var ERROR = { |
| 180 | OK: {code:0, text:"AMQJSC0000I OK."}, |
| 181 | CONNECT_TIMEOUT: {code:1, text:"AMQJSC0001E Connect timed out."}, |
| 182 | SUBSCRIBE_TIMEOUT: {code:2, text:"AMQJS0002E Subscribe timed out."}, |
| 183 | UNSUBSCRIBE_TIMEOUT: {code:3, text:"AMQJS0003E Unsubscribe timed out."}, |
| 184 | PING_TIMEOUT: {code:4, text:"AMQJS0004E Ping timed out."}, |
| 185 | INTERNAL_ERROR: {code:5, text:"AMQJS0005E Internal error. Error Message: {0}, Stack trace: {1}"}, |
| 186 | CONNACK_RETURNCODE: {code:6, text:"AMQJS0006E Bad Connack return code:{0} {1}."}, |
| 187 | SOCKET_ERROR: {code:7, text:"AMQJS0007E Socket error:{0}."}, |
| 188 | SOCKET_CLOSE: {code:8, text:"AMQJS0008I Socket closed."}, |
| 189 | MALFORMED_UTF: {code:9, text:"AMQJS0009E Malformed UTF data:{0} {1} {2}."}, |
| 190 | UNSUPPORTED: {code:10, text:"AMQJS0010E {0} is not supported by this browser."}, |
| 191 | INVALID_STATE: {code:11, text:"AMQJS0011E Invalid state {0}."}, |
| 192 | INVALID_TYPE: {code:12, text:"AMQJS0012E Invalid type {0} for {1}."}, |
| 193 | INVALID_ARGUMENT: {code:13, text:"AMQJS0013E Invalid argument {0} for {1}."}, |
| 194 | UNSUPPORTED_OPERATION: {code:14, text:"AMQJS0014E Unsupported operation."}, |
| 195 | INVALID_STORED_DATA: {code:15, text:"AMQJS0015E Invalid data in local storage key={0} value={1}."}, |
| 196 | INVALID_MQTT_MESSAGE_TYPE: {code:16, text:"AMQJS0016E Invalid MQTT message type {0}."}, |
| 197 | MALFORMED_UNICODE: {code:17, text:"AMQJS0017E Malformed Unicode string:{0} {1}."}, |
| 198 | BUFFER_FULL: {code:18, text:"AMQJS0018E Message buffer is full, maximum buffer size: {0}."}, |
| 199 | }; |
| 200 | |
| 201 | |
| 202 | var CONNACK_RC = { |
| 203 | 0:"Connection Accepted", |
| 204 | 1:"Connection Refused: unacceptable protocol version", |
| 205 | 2:"Connection Refused: identifier rejected", |
| 206 | 3:"Connection Refused: server unavailable", |
| 207 | 4:"Connection Refused: bad user name or password", |
| 208 | 5:"Connection Refused: not authorized" |
| 209 | }; |
| 210 | |
| 211 | |
| 212 | |
| 213 | |
| 214 | |
| 215 | |
| 216 | |
| 217 | |
| 218 | var format = function(error, substitutions) { |
| 219 | var text = error.text; |
| 220 | if (substitutions) { |
| 221 | var field,start; |
| 222 | for (var i=0; i<substitutions.length; i++) { |
| 223 | field = "{"+i+"}"; |
| 224 | start = text.indexOf(field); |
| 225 | if(start > 0) { |
| 226 | var part1 = text.substring(0,start); |
| 227 | var part2 = text.substring(start+field.length); |
| 228 | text = part1+substitutions[i]+part2; |
| 229 | } |
| 230 | } |
| 231 | } |
| 232 | return text; |
| 233 | }; |
| 234 | |
| 235 | |
| 236 | var MqttProtoIdentifierv3 = [0x00,0x06,0x4d,0x51,0x49,0x73,0x64,0x70,0x03]; |
| 237 | |
| 238 | var MqttProtoIdentifierv4 = [0x00,0x04,0x4d,0x51,0x54,0x54,0x04]; |
| 239 | |
| 240 | |
| 241 | |
| 242 | |
| 243 | |
| 244 | |
| 245 | |
| 246 | |
| 247 | |
| 248 | |
| 249 | |
| 250 | |
| 251 | |
| 252 | |
| 253 | |
| 254 | |
| 255 | |
| 256 | |
| 257 | |
| 258 | |
| 259 | |
| 260 | |
| 261 | |
| 262 | |
| 263 | |
| 264 | var WireMessage = function (type, options) { |
| 265 | this.type = type; |
| 266 | for (var name in options) { |
| 267 | if (options.hasOwnProperty(name)) { |
| 268 | this[name] = options[name]; |
| 269 | } |
| 270 | } |
| 271 | }; |
| 272 | |
| 273 | WireMessage.prototype.encode = function() { |
| 274 | |
| 275 | var first = ((this.type & 0x0f) << 4); |
| 276 | |
| 277 | |
| 278 | |
| 279 | |
| 280 | |
| 281 | |
| 282 | var remLength = 0; |
| 283 | var topicStrLength = []; |
| 284 | var destinationNameLength = 0; |
| 285 | var willMessagePayloadBytes; |
| 286 | |
| 287 | |
| 288 | if (this.messageIdentifier !== undefined) |
| 289 | remLength += 2; |
| 290 | |
| 291 | switch(this.type) { |
| 292 | |
| 293 | case MESSAGE_TYPE.CONNECT: |
| 294 | switch(this.mqttVersion) { |
| 295 | case 3: |
| 296 | remLength += MqttProtoIdentifierv3.length + 3; |
| 297 | break; |
| 298 | case 4: |
| 299 | remLength += MqttProtoIdentifierv4.length + 3; |
| 300 | break; |
| 301 | } |
| 302 | |
| 303 | remLength += UTF8Length(this.clientId) + 2; |
| 304 | if (this.willMessage !== undefined) { |
| 305 | remLength += UTF8Length(this.willMessage.destinationName) + 2; |
| 306 | |
| 307 | willMessagePayloadBytes = this.willMessage.payloadBytes; |
| 308 | if (!(willMessagePayloadBytes instanceof Uint8Array)) |
| 309 | willMessagePayloadBytes = new Uint8Array(payloadBytes); |
| 310 | remLength += willMessagePayloadBytes.byteLength +2; |
| 311 | } |
| 312 | if (this.userName !== undefined) |
| 313 | remLength += UTF8Length(this.userName) + 2; |
| 314 | if (this.password !== undefined) |
| 315 | remLength += UTF8Length(this.password) + 2; |
| 316 | break; |
| 317 | |
| 318 | |
| 319 | case MESSAGE_TYPE.SUBSCRIBE: |
| 320 | first |= 0x02; |
| 321 | for ( var i = 0; i < this.topics.length; i++) { |
| 322 | topicStrLength[i] = UTF8Length(this.topics[i]); |
| 323 | remLength += topicStrLength[i] + 2; |
| 324 | } |
| 325 | remLength += this.requestedQos.length; |
| 326 | |
| 327 | break; |
| 328 | |
| 329 | case MESSAGE_TYPE.UNSUBSCRIBE: |
| 330 | first |= 0x02; |
| 331 | for ( var i = 0; i < this.topics.length; i++) { |
| 332 | topicStrLength[i] = UTF8Length(this.topics[i]); |
| 333 | remLength += topicStrLength[i] + 2; |
| 334 | } |
| 335 | break; |
| 336 | |
| 337 | case MESSAGE_TYPE.PUBREL: |
| 338 | first |= 0x02; |
| 339 | break; |
| 340 | |
| 341 | case MESSAGE_TYPE.PUBLISH: |
| 342 | if (this.payloadMessage.duplicate) first |= 0x08; |
| 343 | first = first |= (this.payloadMessage.qos << 1); |
| 344 | if (this.payloadMessage.retained) first |= 0x01; |
| 345 | destinationNameLength = UTF8Length(this.payloadMessage.destinationName); |
| 346 | remLength += destinationNameLength + 2; |
| 347 | var payloadBytes = this.payloadMessage.payloadBytes; |
| 348 | remLength += payloadBytes.byteLength; |
| 349 | if (payloadBytes instanceof ArrayBuffer) |
| 350 | payloadBytes = new Uint8Array(payloadBytes); |
| 351 | else if (!(payloadBytes instanceof Uint8Array)) |
| 352 | payloadBytes = new Uint8Array(payloadBytes.buffer); |
| 353 | break; |
| 354 | |
| 355 | case MESSAGE_TYPE.DISCONNECT: |
| 356 | break; |
| 357 | |
| 358 | default: |
| 359 | break; |
| 360 | } |
| 361 | |
| 362 | |
| 363 | |
| 364 | var mbi = encodeMBI(remLength); |
| 365 | var pos = mbi.length + 1; |
| 366 | var buffer = new ArrayBuffer(remLength + pos); |
| 367 | var byteStream = new Uint8Array(buffer); |
| 368 | |
| 369 | |
| 370 | byteStream[0] = first; |
| 371 | byteStream.set(mbi,1); |
| 372 | |
| 373 | |
| 374 | if (this.type == MESSAGE_TYPE.PUBLISH) |
| 375 | pos = writeString(this.payloadMessage.destinationName, destinationNameLength, byteStream, pos); |
| 376 | |
| 377 | |
| 378 | else if (this.type == MESSAGE_TYPE.CONNECT) { |
| 379 | switch (this.mqttVersion) { |
| 380 | case 3: |
| 381 | byteStream.set(MqttProtoIdentifierv3, pos); |
| 382 | pos += MqttProtoIdentifierv3.length; |
| 383 | break; |
| 384 | case 4: |
| 385 | byteStream.set(MqttProtoIdentifierv4, pos); |
| 386 | pos += MqttProtoIdentifierv4.length; |
| 387 | break; |
| 388 | } |
| 389 | var connectFlags = 0; |
| 390 | if (this.cleanSession) |
| 391 | connectFlags = 0x02; |
| 392 | if (this.willMessage !== undefined ) { |
| 393 | connectFlags |= 0x04; |
| 394 | connectFlags |= (this.willMessage.qos<<3); |
| 395 | if (this.willMessage.retained) { |
| 396 | connectFlags |= 0x20; |
| 397 | } |
| 398 | } |
| 399 | if (this.userName !== undefined) |
| 400 | connectFlags |= 0x80; |
| 401 | if (this.password !== undefined) |
| 402 | connectFlags |= 0x40; |
| 403 | byteStream[pos++] = connectFlags; |
| 404 | pos = writeUint16 (this.keepAliveInterval, byteStream, pos); |
| 405 | } |
| 406 | |
| 407 | |
| 408 | if (this.messageIdentifier !== undefined) |
| 409 | pos = writeUint16 (this.messageIdentifier, byteStream, pos); |
| 410 | |
| 411 | switch(this.type) { |
| 412 | case MESSAGE_TYPE.CONNECT: |
| 413 | pos = writeString(this.clientId, UTF8Length(this.clientId), byteStream, pos); |
| 414 | if (this.willMessage !== undefined) { |
| 415 | pos = writeString(this.willMessage.destinationName, UTF8Length(this.willMessage.destinationName), byteStream, pos); |
| 416 | pos = writeUint16(willMessagePayloadBytes.byteLength, byteStream, pos); |
| 417 | byteStream.set(willMessagePayloadBytes, pos); |
| 418 | pos += willMessagePayloadBytes.byteLength; |
| 419 | |
| 420 | } |
| 421 | if (this.userName !== undefined) |
| 422 | pos = writeString(this.userName, UTF8Length(this.userName), byteStream, pos); |
| 423 | if (this.password !== undefined) |
| 424 | pos = writeString(this.password, UTF8Length(this.password), byteStream, pos); |
| 425 | break; |
| 426 | |
| 427 | case MESSAGE_TYPE.PUBLISH: |
| 428 | |
| 429 | byteStream.set(payloadBytes, pos); |
| 430 | |
| 431 | break; |
| 432 | |
| 433 | |
| 434 | |
| 435 | |
| 436 | |
| 437 | |
| 438 | case MESSAGE_TYPE.SUBSCRIBE: |
| 439 | |
| 440 | for (var i=0; i<this.topics.length; i++) { |
| 441 | pos = writeString(this.topics[i], topicStrLength[i], byteStream, pos); |
| 442 | byteStream[pos++] = this.requestedQos[i]; |
| 443 | } |
| 444 | break; |
| 445 | |
| 446 | case MESSAGE_TYPE.UNSUBSCRIBE: |
| 447 | |
| 448 | for (var i=0; i<this.topics.length; i++) |
| 449 | pos = writeString(this.topics[i], topicStrLength[i], byteStream, pos); |
| 450 | break; |
| 451 | |
| 452 | default: |
| 453 | |
| 454 | } |
| 455 | |
| 456 | return buffer; |
| 457 | }; |
| 458 | |
| 459 | function decodeMessage(input,pos) { |
| 460 | var startingPos = pos; |
| 461 | var first = input[pos]; |
| 462 | var type = first >> 4; |
| 463 | var messageInfo = first &= 0x0f; |
| 464 | pos += 1; |
| 465 | |
| 466 | |
| 467 | |
| 468 | |
| 469 | var digit; |
| 470 | var remLength = 0; |
| 471 | var multiplier = 1; |
| 472 | do { |
| 473 | if (pos == input.length) { |
| 474 | return [null,startingPos]; |
| 475 | } |
| 476 | digit = input[pos++]; |
| 477 | remLength += ((digit & 0x7F) * multiplier); |
| 478 | multiplier *= 128; |
| 479 | } while ((digit & 0x80) !== 0); |
| 480 | |
| 481 | var endPos = pos+remLength; |
| 482 | if (endPos > input.length) { |
| 483 | return [null,startingPos]; |
| 484 | } |
| 485 | |
| 486 | var wireMessage = new WireMessage(type); |
| 487 | switch(type) { |
| 488 | case MESSAGE_TYPE.CONNACK: |
| 489 | var connectAcknowledgeFlags = input[pos++]; |
| 490 | if (connectAcknowledgeFlags & 0x01) |
| 491 | wireMessage.sessionPresent = true; |
| 492 | wireMessage.returnCode = input[pos++]; |
| 493 | break; |
| 494 | |
| 495 | case MESSAGE_TYPE.PUBLISH: |
| 496 | var qos = (messageInfo >> 1) & 0x03; |
| 497 | |
| 498 | var len = readUint16(input, pos); |
| 499 | pos += 2; |
| 500 | var topicName = parseUTF8(input, pos, len); |
| 501 | pos += len; |
| 502 | |
| 503 | if (qos > 0) { |
| 504 | wireMessage.messageIdentifier = readUint16(input, pos); |
| 505 | pos += 2; |
| 506 | } |
| 507 | |
| 508 | var message = new Paho.MQTT.Message(input.subarray(pos, endPos)); |
| 509 | if ((messageInfo & 0x01) == 0x01) |
| 510 | message.retained = true; |
| 511 | if ((messageInfo & 0x08) == 0x08) |
| 512 | message.duplicate = true; |
| 513 | message.qos = qos; |
| 514 | message.destinationName = topicName; |
| 515 | wireMessage.payloadMessage = message; |
| 516 | break; |
| 517 | |
| 518 | case MESSAGE_TYPE.PUBACK: |
| 519 | case MESSAGE_TYPE.PUBREC: |
| 520 | case MESSAGE_TYPE.PUBREL: |
| 521 | case MESSAGE_TYPE.PUBCOMP: |
| 522 | case MESSAGE_TYPE.UNSUBACK: |
| 523 | wireMessage.messageIdentifier = readUint16(input, pos); |
| 524 | break; |
| 525 | |
| 526 | case MESSAGE_TYPE.SUBACK: |
| 527 | wireMessage.messageIdentifier = readUint16(input, pos); |
| 528 | pos += 2; |
| 529 | wireMessage.returnCode = input.subarray(pos, endPos); |
| 530 | break; |
| 531 | |
| 532 | default: |
| 533 | break; |
| 534 | } |
| 535 | |
| 536 | return [wireMessage,endPos]; |
| 537 | } |
| 538 | |
| 539 | function writeUint16(input, buffer, offset) { |
| 540 | buffer[offset++] = input >> 8; |
| 541 | buffer[offset++] = input % 256; |
| 542 | return offset; |
| 543 | } |
| 544 | |
| 545 | function writeString(input, utf8Length, buffer, offset) { |
| 546 | offset = writeUint16(utf8Length, buffer, offset); |
| 547 | stringToUTF8(input, buffer, offset); |
| 548 | return offset + utf8Length; |
| 549 | } |
| 550 | |
| 551 | function readUint16(buffer, offset) { |
| 552 | return 256*buffer[offset] + buffer[offset+1]; |
| 553 | } |
| 554 | |
| 555 | |
| 556 | |
| 557 | |
| 558 | |
| 559 | function encodeMBI(number) { |
| 560 | var output = new Array(1); |
| 561 | var numBytes = 0; |
| 562 | |
| 563 | do { |
| 564 | var digit = number % 128; |
| 565 | number = number >> 7; |
| 566 | if (number > 0) { |
| 567 | digit |= 0x80; |
| 568 | } |
| 569 | output[numBytes++] = digit; |
| 570 | } while ( (number > 0) && (numBytes<4) ); |
| 571 | |
| 572 | return output; |
| 573 | } |
| 574 | |
| 575 | |
| 576 | |
| 577 | |
| 578 | |
| 579 | function UTF8Length(input) { |
| 580 | var output = 0; |
| 581 | for (var i = 0; i<input.length; i++) |
| 582 | { |
| 583 | var charCode = input.charCodeAt(i); |
| 584 | if (charCode > 0x7FF) |
| 585 | { |
| 586 | |
| 587 | if (0xD800 <= charCode && charCode <= 0xDBFF) |
| 588 | { |
| 589 | i++; |
| 590 | output++; |
| 591 | } |
| 592 | output +=3; |
| 593 | } |
| 594 | else if (charCode > 0x7F) |
| 595 | output +=2; |
| 596 | else |
| 597 | output++; |
| 598 | } |
| 599 | return output; |
| 600 | } |
| 601 | |
| 602 | |
| 603 | |
| 604 | |
| 605 | |
| 606 | function stringToUTF8(input, output, start) { |
| 607 | var pos = start; |
| 608 | for (var i = 0; i<input.length; i++) { |
| 609 | var charCode = input.charCodeAt(i); |
| 610 | |
| 611 | |
| 612 | if (0xD800 <= charCode && charCode <= 0xDBFF) { |
| 613 | var lowCharCode = input.charCodeAt(++i); |
| 614 | if (isNaN(lowCharCode)) { |
| 615 | throw new Error(format(ERROR.MALFORMED_UNICODE, [charCode, lowCharCode])); |
| 616 | } |
| 617 | charCode = ((charCode - 0xD800)<<10) + (lowCharCode - 0xDC00) + 0x10000; |
| 618 | |
| 619 | } |
| 620 | |
| 621 | if (charCode <= 0x7F) { |
| 622 | output[pos++] = charCode; |
| 623 | } else if (charCode <= 0x7FF) { |
| 624 | output[pos++] = charCode>>6 & 0x1F | 0xC0; |
| 625 | output[pos++] = charCode & 0x3F | 0x80; |
| 626 | } else if (charCode <= 0xFFFF) { |
| 627 | output[pos++] = charCode>>12 & 0x0F | 0xE0; |
| 628 | output[pos++] = charCode>>6 & 0x3F | 0x80; |
| 629 | output[pos++] = charCode & 0x3F | 0x80; |
| 630 | } else { |
| 631 | output[pos++] = charCode>>18 & 0x07 | 0xF0; |
| 632 | output[pos++] = charCode>>12 & 0x3F | 0x80; |
| 633 | output[pos++] = charCode>>6 & 0x3F | 0x80; |
| 634 | output[pos++] = charCode & 0x3F | 0x80; |
| 635 | } |
| 636 | } |
| 637 | return output; |
| 638 | } |
| 639 | |
| 640 | function parseUTF8(input, offset, length) { |
| 641 | var output = ""; |
| 642 | var utf16; |
| 643 | var pos = offset; |
| 644 | |
| 645 | while (pos < offset+length) |
| 646 | { |
| 647 | var byte1 = input[pos++]; |
| 648 | if (byte1 < 128) |
| 649 | utf16 = byte1; |
| 650 | else |
| 651 | { |
| 652 | var byte2 = input[pos++]-128; |
| 653 | if (byte2 < 0) |
| 654 | throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16),""])); |
| 655 | if (byte1 < 0xE0) |
| 656 | utf16 = 64*(byte1-0xC0) + byte2; |
| 657 | else |
| 658 | { |
| 659 | var byte3 = input[pos++]-128; |
| 660 | if (byte3 < 0) |
| 661 | throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), byte3.toString(16)])); |
| 662 | if (byte1 < 0xF0) |
| 663 | utf16 = 4096*(byte1-0xE0) + 64*byte2 + byte3; |
| 664 | else |
| 665 | { |
| 666 | var byte4 = input[pos++]-128; |
| 667 | if (byte4 < 0) |
| 668 | throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), byte3.toString(16), byte4.toString(16)])); |
| 669 | if (byte1 < 0xF8) |
| 670 | utf16 = 262144*(byte1-0xF0) + 4096*byte2 + 64*byte3 + byte4; |
| 671 | else |
| 672 | throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), byte3.toString(16), byte4.toString(16)])); |
| 673 | } |
| 674 | } |
| 675 | } |
| 676 | |
| 677 | if (utf16 > 0xFFFF) |
| 678 | { |
| 679 | utf16 -= 0x10000; |
| 680 | output += String.fromCharCode(0xD800 + (utf16 >> 10)); |
| 681 | utf16 = 0xDC00 + (utf16 & 0x3FF); |
| 682 | } |
| 683 | output += String.fromCharCode(utf16); |
| 684 | } |
| 685 | return output; |
| 686 | } |
| 687 | |
| 688 | |
| 689 | |
| 690 | |
| 691 | |
| 692 | var Pinger = function(client, window, keepAliveInterval) { |
| 693 | this._client = client; |
| 694 | this._window = window; |
| 695 | this._keepAliveInterval = keepAliveInterval*1000; |
| 696 | this.isReset = false; |
| 697 | |
| 698 | var pingReq = new WireMessage(MESSAGE_TYPE.PINGREQ).encode(); |
| 699 | |
| 700 | var doTimeout = function (pinger) { |
| 701 | return function () { |
| 702 | return doPing.apply(pinger); |
| 703 | }; |
| 704 | }; |
| 705 | |
| 706 | |
| 707 | var doPing = function() { |
| 708 | if (!this.isReset) { |
| 709 | this._client._trace("Pinger.doPing", "Timed out"); |
| 710 | this._client._disconnected( ERROR.PING_TIMEOUT.code , format(ERROR.PING_TIMEOUT)); |
| 711 | } else { |
| 712 | this.isReset = false; |
| 713 | this._client._trace("Pinger.doPing", "send PINGREQ"); |
| 714 | this._client.socket.send(pingReq); |
| 715 | this.timeout = this._window.setTimeout(doTimeout(this), this._keepAliveInterval); |
| 716 | } |
| 717 | }; |
| 718 | |
| 719 | this.reset = function() { |
| 720 | this.isReset = true; |
| 721 | this._window.clearTimeout(this.timeout); |
| 722 | if (this._keepAliveInterval > 0) |
| 723 | this.timeout = setTimeout(doTimeout(this), this._keepAliveInterval); |
| 724 | }; |
| 725 | |
| 726 | this.cancel = function() { |
| 727 | this._window.clearTimeout(this.timeout); |
| 728 | }; |
| 729 | }; |
| 730 | |
| 731 | |
| 732 | |
| 733 | |
| 734 | |
| 735 | var Timeout = function(client, window, timeoutSeconds, action, args) { |
| 736 | this._window = window; |
| 737 | if (!timeoutSeconds) |
| 738 | timeoutSeconds = 30; |
| 739 | |
| 740 | var doTimeout = function (action, client, args) { |
| 741 | return function () { |
| 742 | return action.apply(client, args); |
| 743 | }; |
| 744 | }; |
| 745 | this.timeout = setTimeout(doTimeout(action, client, args), timeoutSeconds * 1000); |
| 746 | |
| 747 | this.cancel = function() { |
| 748 | this._window.clearTimeout(this.timeout); |
| 749 | }; |
| 750 | }; |
| 751 | |
| 752 | |
| 753 | |
| 754 | |
| 755 | |
| 756 | |
| 757 | |
| 758 | |
| 759 | |
| 760 | var ClientImpl = function (uri, host, port, path, clientId) { |
| 761 | |
| 762 | if (!("WebSocket" in global && global.WebSocket !== null)) { |
| 763 | throw new Error(format(ERROR.UNSUPPORTED, ["WebSocket"])); |
| 764 | } |
| 765 | if (!("localStorage" in global && global.localStorage !== null)) { |
| 766 | throw new Error(format(ERROR.UNSUPPORTED, ["localStorage"])); |
| 767 | } |
| 768 | if (!("ArrayBuffer" in global && global.ArrayBuffer !== null)) { |
| 769 | throw new Error(format(ERROR.UNSUPPORTED, ["ArrayBuffer"])); |
| 770 | } |
| 771 | this._trace("Paho.MQTT.Client", uri, host, port, path, clientId); |
| 772 | |
| 773 | this.host = host; |
| 774 | this.port = port; |
| 775 | this.path = path; |
| 776 | this.uri = uri; |
| 777 | this.clientId = clientId; |
| 778 | this._wsuri = null; |
| 779 | |
| 780 | |
| 781 | |
| 782 | |
| 783 | |
| 784 | this._localKey=host+":"+port+(path!="/mqtt"?":"+path:"")+":"+clientId+":"; |
| 785 | |
| 786 | |
| 787 | |
| 788 | this._msg_queue = []; |
| 789 | this._buffered_msg_queue = []; |
| 790 | |
| 791 | |
| 792 | this._sentMessages = {}; |
| 793 | |
| 794 | |
| 795 | |
| 796 | this._receivedMessages = {}; |
| 797 | |
| 798 | |
| 799 | |
| 800 | |
| 801 | this._notify_msg_sent = {}; |
| 802 | |
| 803 | |
| 804 | |
| 805 | this._message_identifier = 1; |
| 806 | |
| 807 | |
| 808 | this._sequence = 0; |
| 809 | |
| 810 | |
| 811 | |
| 812 | for (var key in localStorage) |
| 813 | if ( key.indexOf("Sent:"+this._localKey) === 0 || key.indexOf("Received:"+this._localKey) === 0) |
| 814 | this.restore(key); |
| 815 | }; |
| 816 | |
| 817 | |
| 818 | ClientImpl.prototype.host = null; |
| 819 | ClientImpl.prototype.port = null; |
| 820 | ClientImpl.prototype.path = null; |
| 821 | ClientImpl.prototype.uri = null; |
| 822 | ClientImpl.prototype.clientId = null; |
| 823 | |
| 824 | |
| 825 | ClientImpl.prototype.socket = null; |
| 826 | |
| 827 | ClientImpl.prototype.connected = false; |
| 828 | |
| 829 | |
| 830 | |
| 831 | ClientImpl.prototype.maxMessageIdentifier = 65536; |
| 832 | ClientImpl.prototype.connectOptions = null; |
| 833 | ClientImpl.prototype.hostIndex = null; |
| 834 | ClientImpl.prototype.onConnected = null; |
| 835 | ClientImpl.prototype.onConnectionLost = null; |
| 836 | ClientImpl.prototype.onMessageDelivered = null; |
| 837 | ClientImpl.prototype.onMessageArrived = null; |
| 838 | ClientImpl.prototype.traceFunction = null; |
| 839 | ClientImpl.prototype._msg_queue = null; |
| 840 | ClientImpl.prototype._buffered_msg_queue = null; |
| 841 | ClientImpl.prototype._connectTimeout = null; |
| 842 | |
| 843 | ClientImpl.prototype.sendPinger = null; |
| 844 | |
| 845 | ClientImpl.prototype.receivePinger = null; |
| 846 | ClientImpl.prototype._reconnectInterval = 1; |
| 847 | ClientImpl.prototype._reconnecting = false; |
| 848 | ClientImpl.prototype._reconnectTimeout = null; |
| 849 | ClientImpl.prototype.disconnectedPublishing = false; |
| 850 | ClientImpl.prototype.disconnectedBufferSize = 5000; |
| 851 | |
| 852 | ClientImpl.prototype.receiveBuffer = null; |
| 853 | |
| 854 | ClientImpl.prototype._traceBuffer = null; |
| 855 | ClientImpl.prototype._MAX_TRACE_ENTRIES = 100; |
| 856 | |
| 857 | ClientImpl.prototype.connect = function (connectOptions) { |
| 858 | var connectOptionsMasked = this._traceMask(connectOptions, "password"); |
| 859 | this._trace("Client.connect", connectOptionsMasked, this.socket, this.connected); |
| 860 | |
| 861 | if (this.connected) |
| 862 | throw new Error(format(ERROR.INVALID_STATE, ["already connected"])); |
| 863 | if (this.socket) |
| 864 | throw new Error(format(ERROR.INVALID_STATE, ["already connected"])); |
| 865 | |
| 866 | if (this._reconnecting) { |
| 867 | |
| 868 | |
| 869 | this._reconnectTimeout.cancel(); |
| 870 | this._reconnectTimeout = null; |
| 871 | this._reconnecting = false; |
| 872 | } |
| 873 | |
| 874 | this.connectOptions = connectOptions; |
| 875 | this._reconnectInterval = 1; |
| 876 | this._reconnecting = false; |
| 877 | if (connectOptions.uris) { |
| 878 | this.hostIndex = 0; |
| 879 | this._doConnect(connectOptions.uris[0]); |
| 880 | } else { |
| 881 | this._doConnect(this.uri); |
| 882 | } |
| 883 | |
| 884 | }; |
| 885 | |
| 886 | ClientImpl.prototype.subscribe = function (filter, subscribeOptions) { |
| 887 | this._trace("Client.subscribe", filter, subscribeOptions); |
| 888 | |
| 889 | if (!this.connected) |
| 890 | throw new Error(format(ERROR.INVALID_STATE, ["not connected"])); |
| 891 | |
| 892 | var wireMessage = new WireMessage(MESSAGE_TYPE.SUBSCRIBE); |
| 893 | wireMessage.topics=[filter]; |
| 894 | if (subscribeOptions.qos !== undefined) |
| 895 | wireMessage.requestedQos = [subscribeOptions.qos]; |
| 896 | else |
| 897 | wireMessage.requestedQos = [0]; |
| 898 | |
| 899 | if (subscribeOptions.onSuccess) { |
| 900 | wireMessage.onSuccess = function(grantedQos) {subscribeOptions.onSuccess({invocationContext:subscribeOptions.invocationContext,grantedQos:grantedQos});}; |
| 901 | } |
| 902 | |
| 903 | if (subscribeOptions.onFailure) { |
| 904 | wireMessage.onFailure = function(errorCode) {subscribeOptions.onFailure({invocationContext:subscribeOptions.invocationContext,errorCode:errorCode, errorMessage:format(errorCode)});}; |
| 905 | } |
| 906 | |
| 907 | if (subscribeOptions.timeout) { |
| 908 | wireMessage.timeOut = new Timeout(this, window, subscribeOptions.timeout, subscribeOptions.onFailure, |
| 909 | [{invocationContext:subscribeOptions.invocationContext, |
| 910 | errorCode:ERROR.SUBSCRIBE_TIMEOUT.code, |
| 911 | errorMessage:format(ERROR.SUBSCRIBE_TIMEOUT)}]); |
| 912 | } |
| 913 | |
| 914 | |
| 915 | this._requires_ack(wireMessage); |
| 916 | this._schedule_message(wireMessage); |
| 917 | }; |
| 918 | |
| 919 | |
| 920 | ClientImpl.prototype.unsubscribe = function(filter, unsubscribeOptions) { |
| 921 | this._trace("Client.unsubscribe", filter, unsubscribeOptions); |
| 922 | |
| 923 | if (!this.connected) |
| 924 | throw new Error(format(ERROR.INVALID_STATE, ["not connected"])); |
| 925 | |
| 926 | var wireMessage = new WireMessage(MESSAGE_TYPE.UNSUBSCRIBE); |
| 927 | wireMessage.topics = [filter]; |
| 928 | |
| 929 | if (unsubscribeOptions.onSuccess) { |
| 930 | wireMessage.callback = function() {unsubscribeOptions.onSuccess({invocationContext:unsubscribeOptions.invocationContext});}; |
| 931 | } |
| 932 | if (unsubscribeOptions.timeout) { |
| 933 | wireMessage.timeOut = new Timeout(this, window, unsubscribeOptions.timeout, unsubscribeOptions.onFailure, |
| 934 | [{invocationContext:unsubscribeOptions.invocationContext, |
| 935 | errorCode:ERROR.UNSUBSCRIBE_TIMEOUT.code, |
| 936 | errorMessage:format(ERROR.UNSUBSCRIBE_TIMEOUT)}]); |
| 937 | } |
| 938 | |
| 939 | |
| 940 | this._requires_ack(wireMessage); |
| 941 | this._schedule_message(wireMessage); |
| 942 | }; |
| 943 | |
| 944 | ClientImpl.prototype.send = function (message) { |
| 945 | this._trace("Client.send", message); |
| 946 | |
| 947 | wireMessage = new WireMessage(MESSAGE_TYPE.PUBLISH); |
| 948 | wireMessage.payloadMessage = message; |
| 949 | |
| 950 | if (this.connected) { |
| 951 | |
| 952 | |
| 953 | |
| 954 | if (message.qos > 0) { |
| 955 | this._requires_ack(wireMessage); |
| 956 | } else if (this.onMessageDelivered) { |
| 957 | this._notify_msg_sent[wireMessage] = this.onMessageDelivered(wireMessage.payloadMessage); |
| 958 | } |
| 959 | this._schedule_message(wireMessage); |
| 960 | } else { |
| 961 | |
| 962 | |
| 963 | if (this._reconnecting && this.disconnectedPublishing) { |
| 964 | |
| 965 | var messageCount = Object.keys(this._sentMessages).length + this._buffered_msg_queue.length; |
| 966 | if (messageCount > this.disconnectedBufferSize) { |
| 967 | throw new Error(format(ERROR.BUFFER_FULL, [this.disconnectedBufferSize])); |
| 968 | } else { |
| 969 | if (message.qos > 0) { |
| 970 | |
| 971 | this._requires_ack(wireMessage); |
| 972 | } else { |
| 973 | wireMessage.sequence = ++this._sequence; |
| 974 | this._buffered_msg_queue.push(wireMessage); |
| 975 | } |
| 976 | } |
| 977 | } else { |
| 978 | throw new Error(format(ERROR.INVALID_STATE, ["not connected"])); |
| 979 | } |
| 980 | } |
| 981 | }; |
| 982 | |
| 983 | ClientImpl.prototype.disconnect = function () { |
| 984 | this._trace("Client.disconnect"); |
| 985 | |
| 986 | if (this._reconnecting) { |
| 987 | |
| 988 | |
| 989 | this._reconnectTimeout.cancel(); |
| 990 | this._reconnectTimeout = null; |
| 991 | this._reconnecting = false; |
| 992 | } |
| 993 | |
| 994 | if (!this.socket) |
| 995 | throw new Error(format(ERROR.INVALID_STATE, ["not connecting or connected"])); |
| 996 | |
| 997 | wireMessage = new WireMessage(MESSAGE_TYPE.DISCONNECT); |
| 998 | |
| 999 | |
| 1000 | |
| 1001 | |
| 1002 | this._notify_msg_sent[wireMessage] = scope(this._disconnected, this); |
| 1003 | |
| 1004 | this._schedule_message(wireMessage); |
| 1005 | }; |
| 1006 | |
| 1007 | ClientImpl.prototype.getTraceLog = function () { |
| 1008 | if ( this._traceBuffer !== null ) { |
| 1009 | this._trace("Client.getTraceLog", new Date()); |
| 1010 | this._trace("Client.getTraceLog in flight messages", this._sentMessages.length); |
| 1011 | for (var key in this._sentMessages) |
| 1012 | this._trace("_sentMessages ",key, this._sentMessages[key]); |
| 1013 | for (var key in this._receivedMessages) |
| 1014 | this._trace("_receivedMessages ",key, this._receivedMessages[key]); |
| 1015 | |
| 1016 | return this._traceBuffer; |
| 1017 | } |
| 1018 | }; |
| 1019 | |
| 1020 | ClientImpl.prototype.startTrace = function () { |
| 1021 | if ( this._traceBuffer === null ) { |
| 1022 | this._traceBuffer = []; |
| 1023 | } |
| 1024 | this._trace("Client.startTrace", new Date(), version); |
| 1025 | }; |
| 1026 | |
| 1027 | ClientImpl.prototype.stopTrace = function () { |
| 1028 | delete this._traceBuffer; |
| 1029 | }; |
| 1030 | |
| 1031 | ClientImpl.prototype._doConnect = function (wsurl) { |
| 1032 | |
| 1033 | if (this.connectOptions.useSSL) { |
| 1034 | var uriParts = wsurl.split(":"); |
| 1035 | uriParts[0] = "wss"; |
| 1036 | wsurl = uriParts.join(":"); |
| 1037 | } |
| 1038 | this._wsuri = wsurl; |
| 1039 | this.connected = false; |
| 1040 | |
| 1041 | |
| 1042 | |
| 1043 | if (this.connectOptions.mqttVersion < 4) { |
| 1044 | this.socket = new WebSocket(wsurl, ["mqttv3.1"]); |
| 1045 | } else { |
| 1046 | this.socket = new WebSocket(wsurl, ["mqtt"]); |
| 1047 | } |
| 1048 | this.socket.binaryType = 'arraybuffer'; |
| 1049 | this.socket.onopen = scope(this._on_socket_open, this); |
| 1050 | this.socket.onmessage = scope(this._on_socket_message, this); |
| 1051 | this.socket.onerror = scope(this._on_socket_error, this); |
| 1052 | this.socket.onclose = scope(this._on_socket_close, this); |
| 1053 | |
| 1054 | this.sendPinger = new Pinger(this, window, this.connectOptions.keepAliveInterval); |
| 1055 | this.receivePinger = new Pinger(this, window, this.connectOptions.keepAliveInterval); |
| 1056 | if (this._connectTimeout) { |
| 1057 | this._connectTimeout.cancel(); |
| 1058 | this._connectTimeout = null; |
| 1059 | } |
| 1060 | this._connectTimeout = new Timeout(this, window, this.connectOptions.timeout, this._disconnected, [ERROR.CONNECT_TIMEOUT.code, format(ERROR.CONNECT_TIMEOUT)]); |
| 1061 | }; |
| 1062 | |
| 1063 | |
| 1064 | |
| 1065 | |
| 1066 | |
| 1067 | |
| 1068 | |
| 1069 | ClientImpl.prototype._schedule_message = function (message) { |
| 1070 | this._msg_queue.push(message); |
| 1071 | |
| 1072 | if (this.connected) { |
| 1073 | this._process_queue(); |
| 1074 | } |
| 1075 | }; |
| 1076 | |
| 1077 | ClientImpl.prototype.store = function(prefix, wireMessage) { |
| 1078 | var storedMessage = {type:wireMessage.type, messageIdentifier:wireMessage.messageIdentifier, version:1}; |
| 1079 | |
| 1080 | switch(wireMessage.type) { |
| 1081 | case MESSAGE_TYPE.PUBLISH: |
| 1082 | if(wireMessage.pubRecReceived) |
| 1083 | storedMessage.pubRecReceived = true; |
| 1084 | |
| 1085 | |
| 1086 | storedMessage.payloadMessage = {}; |
| 1087 | var hex = ""; |
| 1088 | var messageBytes = wireMessage.payloadMessage.payloadBytes; |
| 1089 | for (var i=0; i<messageBytes.length; i++) { |
| 1090 | if (messageBytes[i] <= 0xF) |
| 1091 | hex = hex+"0"+messageBytes[i].toString(16); |
| 1092 | else |
| 1093 | hex = hex+messageBytes[i].toString(16); |
| 1094 | } |
| 1095 | storedMessage.payloadMessage.payloadHex = hex; |
| 1096 | |
| 1097 | storedMessage.payloadMessage.qos = wireMessage.payloadMessage.qos; |
| 1098 | storedMessage.payloadMessage.destinationName = wireMessage.payloadMessage.destinationName; |
| 1099 | if (wireMessage.payloadMessage.duplicate) |
| 1100 | storedMessage.payloadMessage.duplicate = true; |
| 1101 | if (wireMessage.payloadMessage.retained) |
| 1102 | storedMessage.payloadMessage.retained = true; |
| 1103 | |
| 1104 | |
| 1105 | if ( prefix.indexOf("Sent:") === 0 ) { |
| 1106 | if ( wireMessage.sequence === undefined ) |
| 1107 | wireMessage.sequence = ++this._sequence; |
| 1108 | storedMessage.sequence = wireMessage.sequence; |
| 1109 | } |
| 1110 | break; |
| 1111 | |
| 1112 | default: |
| 1113 | throw Error(format(ERROR.INVALID_STORED_DATA, [key, storedMessage])); |
| 1114 | } |
| 1115 | localStorage.setItem(prefix+this._localKey+wireMessage.messageIdentifier, JSON.stringify(storedMessage)); |
| 1116 | }; |
| 1117 | |
| 1118 | ClientImpl.prototype.restore = function(key) { |
| 1119 | var value = localStorage.getItem(key); |
| 1120 | var storedMessage = JSON.parse(value); |
| 1121 | |
| 1122 | var wireMessage = new WireMessage(storedMessage.type, storedMessage); |
| 1123 | |
| 1124 | switch(storedMessage.type) { |
| 1125 | case MESSAGE_TYPE.PUBLISH: |
| 1126 | |
| 1127 | var hex = storedMessage.payloadMessage.payloadHex; |
| 1128 | var buffer = new ArrayBuffer((hex.length)/2); |
| 1129 | var byteStream = new Uint8Array(buffer); |
| 1130 | var i = 0; |
| 1131 | while (hex.length >= 2) { |
| 1132 | var x = parseInt(hex.substring(0, 2), 16); |
| 1133 | hex = hex.substring(2, hex.length); |
| 1134 | byteStream[i++] = x; |
| 1135 | } |
| 1136 | var payloadMessage = new Paho.MQTT.Message(byteStream); |
| 1137 | |
| 1138 | payloadMessage.qos = storedMessage.payloadMessage.qos; |
| 1139 | payloadMessage.destinationName = storedMessage.payloadMessage.destinationName; |
| 1140 | if (storedMessage.payloadMessage.duplicate) |
| 1141 | payloadMessage.duplicate = true; |
| 1142 | if (storedMessage.payloadMessage.retained) |
| 1143 | payloadMessage.retained = true; |
| 1144 | wireMessage.payloadMessage = payloadMessage; |
| 1145 | |
| 1146 | break; |
| 1147 | |
| 1148 | default: |
| 1149 | throw Error(format(ERROR.INVALID_STORED_DATA, [key, value])); |
| 1150 | } |
| 1151 | |
| 1152 | if (key.indexOf("Sent:"+this._localKey) === 0) { |
| 1153 | wireMessage.payloadMessage.duplicate = true; |
| 1154 | this._sentMessages[wireMessage.messageIdentifier] = wireMessage; |
| 1155 | } else if (key.indexOf("Received:"+this._localKey) === 0) { |
| 1156 | this._receivedMessages[wireMessage.messageIdentifier] = wireMessage; |
| 1157 | } |
| 1158 | }; |
| 1159 | |
| 1160 | ClientImpl.prototype._process_queue = function () { |
| 1161 | var message = null; |
| 1162 | |
| 1163 | var fifo = this._msg_queue.reverse(); |
| 1164 | |
| 1165 | |
| 1166 | while ((message = fifo.pop())) { |
| 1167 | this._socket_send(message); |
| 1168 | |
| 1169 | if (this._notify_msg_sent[message]) { |
| 1170 | this._notify_msg_sent[message](); |
| 1171 | delete this._notify_msg_sent[message]; |
| 1172 | } |
| 1173 | } |
| 1174 | }; |
| 1175 | |
| 1176 | |
| 1177 | |
| 1178 | |
| 1179 | |
| 1180 | |
| 1181 | ClientImpl.prototype._requires_ack = function (wireMessage) { |
| 1182 | var messageCount = Object.keys(this._sentMessages).length; |
| 1183 | if (messageCount > this.maxMessageIdentifier) |
| 1184 | throw Error ("Too many messages:"+messageCount); |
| 1185 | |
| 1186 | while(this._sentMessages[this._message_identifier] !== undefined) { |
| 1187 | this._message_identifier++; |
| 1188 | } |
| 1189 | wireMessage.messageIdentifier = this._message_identifier; |
| 1190 | this._sentMessages[wireMessage.messageIdentifier] = wireMessage; |
| 1191 | if (wireMessage.type === MESSAGE_TYPE.PUBLISH) { |
| 1192 | this.store("Sent:", wireMessage); |
| 1193 | } |
| 1194 | if (this._message_identifier === this.maxMessageIdentifier) { |
| 1195 | this._message_identifier = 1; |
| 1196 | } |
| 1197 | }; |
| 1198 | |
| 1199 | |
| 1200 | |
| 1201 | |
| 1202 | |
| 1203 | ClientImpl.prototype._on_socket_open = function () { |
| 1204 | |
| 1205 | var wireMessage = new WireMessage(MESSAGE_TYPE.CONNECT, this.connectOptions); |
| 1206 | wireMessage.clientId = this.clientId; |
| 1207 | this._socket_send(wireMessage); |
| 1208 | }; |
| 1209 | |
| 1210 | |
| 1211 | |
| 1212 | |
| 1213 | |
| 1214 | ClientImpl.prototype._on_socket_message = function (event) { |
| 1215 | this._trace("Client._on_socket_message", event.data); |
| 1216 | var messages = this._deframeMessages(event.data); |
| 1217 | for (var i = 0; i < messages.length; i+=1) { |
| 1218 | this._handleMessage(messages[i]); |
| 1219 | } |
| 1220 | }; |
| 1221 | |
| 1222 | ClientImpl.prototype._deframeMessages = function(data) { |
| 1223 | var byteArray = new Uint8Array(data); |
| 1224 | var messages = []; |
| 1225 | if (this.receiveBuffer) { |
| 1226 | var newData = new Uint8Array(this.receiveBuffer.length+byteArray.length); |
| 1227 | newData.set(this.receiveBuffer); |
| 1228 | newData.set(byteArray,this.receiveBuffer.length); |
| 1229 | byteArray = newData; |
| 1230 | delete this.receiveBuffer; |
| 1231 | } |
| 1232 | try { |
| 1233 | var offset = 0; |
| 1234 | while(offset < byteArray.length) { |
| 1235 | var result = decodeMessage(byteArray,offset); |
| 1236 | var wireMessage = result[0]; |
| 1237 | offset = result[1]; |
| 1238 | if (wireMessage !== null) { |
| 1239 | messages.push(wireMessage); |
| 1240 | } else { |
| 1241 | break; |
| 1242 | } |
| 1243 | } |
| 1244 | if (offset < byteArray.length) { |
| 1245 | this.receiveBuffer = byteArray.subarray(offset); |
| 1246 | } |
| 1247 | } catch (error) { |
| 1248 | var errorStack = ((error.hasOwnProperty('stack') == 'undefined') ? error.stack.toString() : "No Error Stack Available"); |
| 1249 | this._disconnected(ERROR.INTERNAL_ERROR.code , format(ERROR.INTERNAL_ERROR, [error.message,errorStack])); |
| 1250 | return; |
| 1251 | } |
| 1252 | return messages; |
| 1253 | }; |
| 1254 | |
| 1255 | ClientImpl.prototype._handleMessage = function(wireMessage) { |
| 1256 | |
| 1257 | this._trace("Client._handleMessage", wireMessage); |
| 1258 | |
| 1259 | try { |
| 1260 | switch(wireMessage.type) { |
| 1261 | case MESSAGE_TYPE.CONNACK: |
| 1262 | this._connectTimeout.cancel(); |
| 1263 | if (this._reconnectTimeout) |
| 1264 | this._reconnectTimeout.cancel(); |
| 1265 | |
| 1266 | |
| 1267 | if (this.connectOptions.cleanSession) { |
| 1268 | for (var key in this._sentMessages) { |
| 1269 | var sentMessage = this._sentMessages[key]; |
| 1270 | localStorage.removeItem("Sent:"+this._localKey+sentMessage.messageIdentifier); |
| 1271 | } |
| 1272 | this._sentMessages = {}; |
| 1273 | |
| 1274 | for (var key in this._receivedMessages) { |
| 1275 | var receivedMessage = this._receivedMessages[key]; |
| 1276 | localStorage.removeItem("Received:"+this._localKey+receivedMessage.messageIdentifier); |
| 1277 | } |
| 1278 | this._receivedMessages = {}; |
| 1279 | } |
| 1280 | |
| 1281 | if (wireMessage.returnCode === 0) { |
| 1282 | |
| 1283 | this.connected = true; |
| 1284 | |
| 1285 | |
| 1286 | if (this.connectOptions.uris) |
| 1287 | this.hostIndex = this.connectOptions.uris.length; |
| 1288 | |
| 1289 | } else { |
| 1290 | this._disconnected(ERROR.CONNACK_RETURNCODE.code , format(ERROR.CONNACK_RETURNCODE, [wireMessage.returnCode, CONNACK_RC[wireMessage.returnCode]])); |
| 1291 | break; |
| 1292 | } |
| 1293 | |
| 1294 | |
| 1295 | var sequencedMessages = []; |
| 1296 | for (var msgId in this._sentMessages) { |
| 1297 | if (this._sentMessages.hasOwnProperty(msgId)) |
| 1298 | sequencedMessages.push(this._sentMessages[msgId]); |
| 1299 | } |
| 1300 | |
| 1301 | |
| 1302 | if (this._buffered_msg_queue.length > 0) { |
| 1303 | var msg = null; |
| 1304 | var fifo = this._buffered_msg_queue.reverse(); |
| 1305 | while ((msg = fifo.pop())) { |
| 1306 | sequencedMessages.push(msg); |
| 1307 | if (this.onMessageDelivered) |
| 1308 | this._notify_msg_sent[msg] = this.onMessageDelivered(msg.payloadMessage); |
| 1309 | } |
| 1310 | } |
| 1311 | |
| 1312 | |
| 1313 | var sequencedMessages = sequencedMessages.sort(function(a,b) {return a.sequence - b.sequence;} ); |
| 1314 | for (var i=0, len=sequencedMessages.length; i<len; i++) { |
| 1315 | var sentMessage = sequencedMessages[i]; |
| 1316 | if (sentMessage.type == MESSAGE_TYPE.PUBLISH && sentMessage.pubRecReceived) { |
| 1317 | var pubRelMessage = new WireMessage(MESSAGE_TYPE.PUBREL, {messageIdentifier:sentMessage.messageIdentifier}); |
| 1318 | this._schedule_message(pubRelMessage); |
| 1319 | } else { |
| 1320 | this._schedule_message(sentMessage); |
| 1321 | } |
| 1322 | } |
| 1323 | |
| 1324 | |
| 1325 | |
| 1326 | |
| 1327 | if (this.connectOptions.onSuccess) { |
| 1328 | this.connectOptions.onSuccess({invocationContext:this.connectOptions.invocationContext}); |
| 1329 | } |
| 1330 | |
| 1331 | var reconnected = false; |
| 1332 | if (this._reconnecting) { |
| 1333 | reconnected = true; |
| 1334 | this._reconnectInterval = 1; |
| 1335 | this._reconnecting = false; |
| 1336 | } |
| 1337 | |
| 1338 | |
| 1339 | this._connected(reconnected, this._wsuri); |
| 1340 | |
| 1341 | |
| 1342 | this._process_queue(); |
| 1343 | break; |
| 1344 | |
| 1345 | case MESSAGE_TYPE.PUBLISH: |
| 1346 | this._receivePublish(wireMessage); |
| 1347 | break; |
| 1348 | |
| 1349 | case MESSAGE_TYPE.PUBACK: |
| 1350 | var sentMessage = this._sentMessages[wireMessage.messageIdentifier]; |
| 1351 | |
| 1352 | if (sentMessage) { |
| 1353 | delete this._sentMessages[wireMessage.messageIdentifier]; |
| 1354 | localStorage.removeItem("Sent:"+this._localKey+wireMessage.messageIdentifier); |
| 1355 | if (this.onMessageDelivered) |
| 1356 | this.onMessageDelivered(sentMessage.payloadMessage); |
| 1357 | } |
| 1358 | break; |
| 1359 | |
| 1360 | case MESSAGE_TYPE.PUBREC: |
| 1361 | var sentMessage = this._sentMessages[wireMessage.messageIdentifier]; |
| 1362 | |
| 1363 | if (sentMessage) { |
| 1364 | sentMessage.pubRecReceived = true; |
| 1365 | var pubRelMessage = new WireMessage(MESSAGE_TYPE.PUBREL, {messageIdentifier:wireMessage.messageIdentifier}); |
| 1366 | this.store("Sent:", sentMessage); |
| 1367 | this._schedule_message(pubRelMessage); |
| 1368 | } |
| 1369 | break; |
| 1370 | |
| 1371 | case MESSAGE_TYPE.PUBREL: |
| 1372 | var receivedMessage = this._receivedMessages[wireMessage.messageIdentifier]; |
| 1373 | localStorage.removeItem("Received:"+this._localKey+wireMessage.messageIdentifier); |
| 1374 | |
| 1375 | if (receivedMessage) { |
| 1376 | this._receiveMessage(receivedMessage); |
| 1377 | delete this._receivedMessages[wireMessage.messageIdentifier]; |
| 1378 | } |
| 1379 | |
| 1380 | var pubCompMessage = new WireMessage(MESSAGE_TYPE.PUBCOMP, {messageIdentifier:wireMessage.messageIdentifier}); |
| 1381 | this._schedule_message(pubCompMessage); |
| 1382 | |
| 1383 | |
| 1384 | break; |
| 1385 | |
| 1386 | case MESSAGE_TYPE.PUBCOMP: |
| 1387 | var sentMessage = this._sentMessages[wireMessage.messageIdentifier]; |
| 1388 | delete this._sentMessages[wireMessage.messageIdentifier]; |
| 1389 | localStorage.removeItem("Sent:"+this._localKey+wireMessage.messageIdentifier); |
| 1390 | if (this.onMessageDelivered) |
| 1391 | this.onMessageDelivered(sentMessage.payloadMessage); |
| 1392 | break; |
| 1393 | |
| 1394 | case MESSAGE_TYPE.SUBACK: |
| 1395 | var sentMessage = this._sentMessages[wireMessage.messageIdentifier]; |
| 1396 | if (sentMessage) { |
| 1397 | if(sentMessage.timeOut) |
| 1398 | sentMessage.timeOut.cancel(); |
| 1399 | |
| 1400 | if (wireMessage.returnCode[0] === 0x80) { |
| 1401 | if (sentMessage.onFailure) { |
| 1402 | sentMessage.onFailure(wireMessage.returnCode); |
| 1403 | } |
| 1404 | } else if (sentMessage.onSuccess) { |
| 1405 | sentMessage.onSuccess(wireMessage.returnCode); |
| 1406 | } |
| 1407 | delete this._sentMessages[wireMessage.messageIdentifier]; |
| 1408 | } |
| 1409 | break; |
| 1410 | |
| 1411 | case MESSAGE_TYPE.UNSUBACK: |
| 1412 | var sentMessage = this._sentMessages[wireMessage.messageIdentifier]; |
| 1413 | if (sentMessage) { |
| 1414 | if (sentMessage.timeOut) |
| 1415 | sentMessage.timeOut.cancel(); |
| 1416 | if (sentMessage.callback) { |
| 1417 | sentMessage.callback(); |
| 1418 | } |
| 1419 | delete this._sentMessages[wireMessage.messageIdentifier]; |
| 1420 | } |
| 1421 | |
| 1422 | break; |
| 1423 | |
| 1424 | case MESSAGE_TYPE.PINGRESP: |
| 1425 | |
| 1426 | this.sendPinger.reset(); |
| 1427 | break; |
| 1428 | |
| 1429 | case MESSAGE_TYPE.DISCONNECT: |
| 1430 | |
| 1431 | this._disconnected(ERROR.INVALID_MQTT_MESSAGE_TYPE.code , format(ERROR.INVALID_MQTT_MESSAGE_TYPE, [wireMessage.type])); |
| 1432 | break; |
| 1433 | |
| 1434 | default: |
| 1435 | this._disconnected(ERROR.INVALID_MQTT_MESSAGE_TYPE.code , format(ERROR.INVALID_MQTT_MESSAGE_TYPE, [wireMessage.type])); |
| 1436 | } |
| 1437 | } catch (error) { |
| 1438 | var errorStack = ((error.hasOwnProperty('stack') == 'undefined') ? error.stack.toString() : "No Error Stack Available"); |
| 1439 | this._disconnected(ERROR.INTERNAL_ERROR.code , format(ERROR.INTERNAL_ERROR, [error.message,errorStack])); |
| 1440 | return; |
| 1441 | } |
| 1442 | }; |
| 1443 | |
| 1444 | |
| 1445 | ClientImpl.prototype._on_socket_error = function (error) { |
| 1446 | if (!this._reconnecting) { |
| 1447 | this._disconnected(ERROR.SOCKET_ERROR.code , format(ERROR.SOCKET_ERROR, [error.data])); |
| 1448 | } |
| 1449 | }; |
| 1450 | |
| 1451 | |
| 1452 | ClientImpl.prototype._on_socket_close = function () { |
| 1453 | if (!this._reconnecting) { |
| 1454 | this._disconnected(ERROR.SOCKET_CLOSE.code , format(ERROR.SOCKET_CLOSE)); |
| 1455 | } |
| 1456 | }; |
| 1457 | |
| 1458 | |
| 1459 | ClientImpl.prototype._socket_send = function (wireMessage) { |
| 1460 | |
| 1461 | if (wireMessage.type == 1) { |
| 1462 | var wireMessageMasked = this._traceMask(wireMessage, "password"); |
| 1463 | this._trace("Client._socket_send", wireMessageMasked); |
| 1464 | } |
| 1465 | else this._trace("Client._socket_send", wireMessage); |
| 1466 | |
| 1467 | this.socket.send(wireMessage.encode()); |
| 1468 | |
| 1469 | this.sendPinger.reset(); |
| 1470 | }; |
| 1471 | |
| 1472 | |
| 1473 | ClientImpl.prototype._receivePublish = function (wireMessage) { |
| 1474 | switch(wireMessage.payloadMessage.qos) { |
| 1475 | case "undefined": |
| 1476 | case 0: |
| 1477 | this._receiveMessage(wireMessage); |
| 1478 | break; |
| 1479 | |
| 1480 | case 1: |
| 1481 | var pubAckMessage = new WireMessage(MESSAGE_TYPE.PUBACK, {messageIdentifier:wireMessage.messageIdentifier}); |
| 1482 | this._schedule_message(pubAckMessage); |
| 1483 | this._receiveMessage(wireMessage); |
| 1484 | break; |
| 1485 | |
| 1486 | case 2: |
| 1487 | this._receivedMessages[wireMessage.messageIdentifier] = wireMessage; |
| 1488 | this.store("Received:", wireMessage); |
| 1489 | var pubRecMessage = new WireMessage(MESSAGE_TYPE.PUBREC, {messageIdentifier:wireMessage.messageIdentifier}); |
| 1490 | this._schedule_message(pubRecMessage); |
| 1491 | |
| 1492 | break; |
| 1493 | |
| 1494 | default: |
| 1495 | throw Error("Invaild qos="+wireMmessage.payloadMessage.qos); |
| 1496 | } |
| 1497 | }; |
| 1498 | |
| 1499 | |
| 1500 | ClientImpl.prototype._receiveMessage = function (wireMessage) { |
| 1501 | if (this.onMessageArrived) { |
| 1502 | this.onMessageArrived(wireMessage.payloadMessage); |
| 1503 | } |
| 1504 | }; |
| 1505 | |
| 1506 | |
| 1507 | |
| 1508 | |
| 1509 | |
| 1510 | |
| 1511 | ClientImpl.prototype._connected = function (reconnect, uri) { |
| 1512 | |
| 1513 | if (this.onConnected) |
| 1514 | this.onConnected(reconnect, uri); |
| 1515 | }; |
| 1516 | |
| 1517 | |
| 1518 | |
| 1519 | |
| 1520 | |
| 1521 | |
| 1522 | ClientImpl.prototype._reconnect = function () { |
| 1523 | this._trace("Client._reconnect"); |
| 1524 | if (!this.connected) { |
| 1525 | this._reconnecting = true; |
| 1526 | this.sendPinger.cancel(); |
| 1527 | this.receivePinger.cancel(); |
| 1528 | if (this._reconnectInterval < 128) |
| 1529 | this._reconnectInterval = this._reconnectInterval * 2; |
| 1530 | if (this.connectOptions.uris) { |
| 1531 | this.hostIndex = 0; |
| 1532 | this._doConnect(this.connectOptions.uris[0]); |
| 1533 | } else { |
| 1534 | this._doConnect(this.uri); |
| 1535 | } |
| 1536 | } |
| 1537 | }; |
| 1538 | |
| 1539 | |
| 1540 | |
| 1541 | |
| 1542 | |
| 1543 | |
| 1544 | |
| 1545 | |
| 1546 | ClientImpl.prototype._disconnected = function (errorCode, errorText) { |
| 1547 | this._trace("Client._disconnected", errorCode, errorText); |
| 1548 | |
| 1549 | if (errorCode !== undefined && this._reconnecting) { |
| 1550 | |
| 1551 | this._reconnectTimeout = new Timeout(this, window, this._reconnectInterval, this._reconnect); |
| 1552 | return; |
| 1553 | } |
| 1554 | |
| 1555 | this.sendPinger.cancel(); |
| 1556 | this.receivePinger.cancel(); |
| 1557 | if (this._connectTimeout) { |
| 1558 | this._connectTimeout.cancel(); |
| 1559 | this._connectTimeout = null; |
| 1560 | } |
| 1561 | |
| 1562 | |
| 1563 | this._msg_queue = []; |
| 1564 | this._buffered_msg_queue = []; |
| 1565 | this._notify_msg_sent = {}; |
| 1566 | |
| 1567 | if (this.socket) { |
| 1568 | |
| 1569 | this.socket.onopen = null; |
| 1570 | this.socket.onmessage = null; |
| 1571 | this.socket.onerror = null; |
| 1572 | this.socket.onclose = null; |
| 1573 | if (this.socket.readyState === 1) |
| 1574 | this.socket.close(); |
| 1575 | delete this.socket; |
| 1576 | } |
| 1577 | |
| 1578 | if (this.connectOptions.uris && this.hostIndex < this.connectOptions.uris.length-1) { |
| 1579 | |
| 1580 | this.hostIndex++; |
| 1581 | this._doConnect(this.connectOptions.uris[this.hostIndex]); |
| 1582 | } else { |
| 1583 | |
| 1584 | if (errorCode === undefined) { |
| 1585 | errorCode = ERROR.OK.code; |
| 1586 | errorText = format(ERROR.OK); |
| 1587 | } |
| 1588 | |
| 1589 | |
| 1590 | if (this.connected) { |
| 1591 | this.connected = false; |
| 1592 | |
| 1593 | if (this.onConnectionLost) { |
| 1594 | this.onConnectionLost({errorCode:errorCode, errorMessage:errorText, reconnect:this.connectOptions.reconnect, uri:this._wsuri}); |
| 1595 | } |
| 1596 | if (errorCode !== ERROR.OK.code && this.connectOptions.reconnect) { |
| 1597 | |
| 1598 | this._reconnectInterval = 1; |
| 1599 | this._reconnect(); |
| 1600 | return; |
| 1601 | } |
| 1602 | } else { |
| 1603 | |
| 1604 | if (this.connectOptions.mqttVersion === 4 && this.connectOptions.mqttVersionExplicit === false) { |
| 1605 | this._trace("Failed to connect V4, dropping back to V3"); |
| 1606 | this.connectOptions.mqttVersion = 3; |
| 1607 | if (this.connectOptions.uris) { |
| 1608 | this.hostIndex = 0; |
| 1609 | this._doConnect(this.connectOptions.uris[0]); |
| 1610 | } else { |
| 1611 | this._doConnect(this.uri); |
| 1612 | } |
| 1613 | } else if(this.connectOptions.onFailure) { |
| 1614 | this.connectOptions.onFailure({invocationContext:this.connectOptions.invocationContext, errorCode:errorCode, errorMessage:errorText}); |
| 1615 | } |
| 1616 | } |
| 1617 | } |
| 1618 | }; |
| 1619 | |
| 1620 | |
| 1621 | ClientImpl.prototype._trace = function () { |
| 1622 | |
| 1623 | if (this.traceFunction) { |
| 1624 | for (var i in arguments) |
| 1625 | { |
| 1626 | if (typeof arguments[i] !== "undefined") |
| 1627 | arguments.splice(i, 1, JSON.stringify(arguments[i])); |
| 1628 | } |
| 1629 | var record = Array.prototype.slice.call(arguments).join(""); |
| 1630 | this.traceFunction ({severity: "Debug", message: record }); |
| 1631 | } |
| 1632 | |
| 1633 | |
| 1634 | if ( this._traceBuffer !== null ) { |
| 1635 | for (var i = 0, max = arguments.length; i < max; i++) { |
| 1636 | if ( this._traceBuffer.length == this._MAX_TRACE_ENTRIES ) { |
| 1637 | this._traceBuffer.shift(); |
| 1638 | } |
| 1639 | if (i === 0) this._traceBuffer.push(arguments[i]); |
| 1640 | else if (typeof arguments[i] === "undefined" ) this._traceBuffer.push(arguments[i]); |
| 1641 | else this._traceBuffer.push(" "+JSON.stringify(arguments[i])); |
| 1642 | } |
| 1643 | } |
| 1644 | }; |
| 1645 | |
| 1646 | |
| 1647 | ClientImpl.prototype._traceMask = function (traceObject, masked) { |
| 1648 | var traceObjectMasked = {}; |
| 1649 | for (var attr in traceObject) { |
| 1650 | if (traceObject.hasOwnProperty(attr)) { |
| 1651 | if (attr == masked) |
| 1652 | traceObjectMasked[attr] = "******"; |
| 1653 | else |
| 1654 | traceObjectMasked[attr] = traceObject[attr]; |
| 1655 | } |
| 1656 | } |
| 1657 | return traceObjectMasked; |
| 1658 | }; |
| 1659 | |
| 1660 | |
| 1661 | |
| 1662 | |
| 1663 | |
| 1664 | |
| 1665 | |
| 1666 | |
| 1667 | |
| 1668 | |
| 1669 | |
| 1670 | |
| 1671 | |
| 1672 | |
| 1673 | |
| 1674 | |
| 1675 | |
| 1676 | |
| 1677 | |
| 1678 | |
| 1679 | |
| 1680 | |
| 1681 | |
| 1682 | |
| 1683 | |
| 1684 | |
| 1685 | |
| 1686 | |
| 1687 | |
| 1688 | |
| 1689 | |
| 1690 | |
| 1691 | |
| 1692 | |
| 1693 | |
| 1694 | |
| 1695 | |
| 1696 | |
| 1697 | |
| 1698 | |
| 1699 | |
| 1700 | |
| 1701 | |
| 1702 | |
| 1703 | |
| 1704 | |
| 1705 | |
| 1706 | |
| 1707 | |
| 1708 | |
| 1709 | |
| 1710 | |
| 1711 | |
| 1712 | |
| 1713 | |
| 1714 | |
| 1715 | |
| 1716 | |
| 1717 | |
| 1718 | |
| 1719 | |
| 1720 | |
| 1721 | |
| 1722 | |
| 1723 | |
| 1724 | |
| 1725 | |
| 1726 | |
| 1727 | |
| 1728 | |
| 1729 | |
| 1730 | |
| 1731 | |
| 1732 | |
| 1733 | var Client = function (host, port, path, clientId) { |
| 1734 | |
| 1735 | var uri; |
| 1736 | |
| 1737 | if (typeof host !== "string") |
| 1738 | throw new Error(format(ERROR.INVALID_TYPE, [typeof host, "host"])); |
| 1739 | |
| 1740 | if (arguments.length == 2) { |
| 1741 | |
| 1742 | |
| 1743 | clientId = port; |
| 1744 | uri = host; |
| 1745 | var match = uri.match(/^(wss?):\/\/((\[(.+)\])|([^\/]+?))(:(\d+))?(\/.*)$/); |
| 1746 | if (match) { |
| 1747 | host = match[4]||match[2]; |
| 1748 | port = parseInt(match[7]); |
| 1749 | path = match[8]; |
| 1750 | } else { |
| 1751 | throw new Error(format(ERROR.INVALID_ARGUMENT,[host,"host"])); |
| 1752 | } |
| 1753 | } else { |
| 1754 | if (arguments.length == 3) { |
| 1755 | clientId = path; |
| 1756 | path = "/mqtt"; |
| 1757 | } |
| 1758 | if (typeof port !== "number" || port < 0) |
| 1759 | throw new Error(format(ERROR.INVALID_TYPE, [typeof port, "port"])); |
| 1760 | if (typeof path !== "string") |
| 1761 | throw new Error(format(ERROR.INVALID_TYPE, [typeof path, "path"])); |
| 1762 | |
| 1763 | var ipv6AddSBracket = (host.indexOf(":") !== -1 && host.slice(0,1) !== "[" && host.slice(-1) !== "]"); |
| 1764 | uri = "ws://"+(ipv6AddSBracket?"["+host+"]":host)+":"+port+path; |
| 1765 | } |
| 1766 | |
| 1767 | var clientIdLength = 0; |
| 1768 | for (var i = 0; i<clientId.length; i++) { |
| 1769 | var charCode = clientId.charCodeAt(i); |
| 1770 | if (0xD800 <= charCode && charCode <= 0xDBFF) { |
| 1771 | i++; |
| 1772 | } |
| 1773 | clientIdLength++; |
| 1774 | } |
| 1775 | if (typeof clientId !== "string" || clientIdLength > 65535) |
| 1776 | throw new Error(format(ERROR.INVALID_ARGUMENT, [clientId, "clientId"])); |
| 1777 | |
| 1778 | var client = new ClientImpl(uri, host, port, path, clientId); |
| 1779 | this._getHost = function() { return host; }; |
| 1780 | this._setHost = function() { throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); }; |
| 1781 | |
| 1782 | this._getPort = function() { return port; }; |
| 1783 | this._setPort = function() { throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); }; |
| 1784 | |
| 1785 | this._getPath = function() { return path; }; |
| 1786 | this._setPath = function() { throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); }; |
| 1787 | |
| 1788 | this._getURI = function() { return uri; }; |
| 1789 | this._setURI = function() { throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); }; |
| 1790 | |
| 1791 | this._getClientId = function() { return client.clientId; }; |
| 1792 | this._setClientId = function() { throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); }; |
| 1793 | |
| 1794 | this._getOnConnected = function() { return client.onConnected; }; |
| 1795 | this._setOnConnected = function(newOnConnected) { |
| 1796 | if (typeof newOnConnected === "function") |
| 1797 | client.onConnected = newOnConnected; |
| 1798 | else |
| 1799 | throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnConnected, "onConnected"])); |
| 1800 | }; |
| 1801 | |
| 1802 | this._getDisconnectedPublishing = function() { return client.disconnectedPublishing; }; |
| 1803 | this._setDisconnectedPublishing = function(newDisconnectedPublishing) { |
| 1804 | client.disconnectedPublishing = newDisconnectedPublishing; |
| 1805 | }; |
| 1806 | |
| 1807 | this._getDisconnectedBufferSize = function() { return client.disconnectedBufferSize; }; |
| 1808 | this._setDisconnectedBufferSize = function(newDisconnectedBufferSize) { |
| 1809 | client.disconnectedBufferSize = newDisconnectedBufferSize; |
| 1810 | }; |
| 1811 | |
| 1812 | this._getOnConnectionLost = function() { return client.onConnectionLost; }; |
| 1813 | this._setOnConnectionLost = function(newOnConnectionLost) { |
| 1814 | if (typeof newOnConnectionLost === "function") |
| 1815 | client.onConnectionLost = newOnConnectionLost; |
| 1816 | else |
| 1817 | throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnConnectionLost, "onConnectionLost"])); |
| 1818 | }; |
| 1819 | |
| 1820 | this._getOnMessageDelivered = function() { return client.onMessageDelivered; }; |
| 1821 | this._setOnMessageDelivered = function(newOnMessageDelivered) { |
| 1822 | if (typeof newOnMessageDelivered === "function") |
| 1823 | client.onMessageDelivered = newOnMessageDelivered; |
| 1824 | else |
| 1825 | throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnMessageDelivered, "onMessageDelivered"])); |
| 1826 | }; |
| 1827 | |
| 1828 | this._getOnMessageArrived = function() { return client.onMessageArrived; }; |
| 1829 | this._setOnMessageArrived = function(newOnMessageArrived) { |
| 1830 | if (typeof newOnMessageArrived === "function") |
| 1831 | client.onMessageArrived = newOnMessageArrived; |
| 1832 | else |
| 1833 | throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnMessageArrived, "onMessageArrived"])); |
| 1834 | }; |
| 1835 | |
| 1836 | this._getTrace = function() { return client.traceFunction; }; |
| 1837 | this._setTrace = function(trace) { |
| 1838 | if(typeof trace === "function"){ |
| 1839 | client.traceFunction = trace; |
| 1840 | }else{ |
| 1841 | throw new Error(format(ERROR.INVALID_TYPE, [typeof trace, "onTrace"])); |
| 1842 | } |
| 1843 | }; |
| 1844 | |
| 1845 | |
| 1846 | |
| 1847 | |
| 1848 | |
| 1849 | |
| 1850 | |
| 1851 | |
| 1852 | |
| 1853 | |
| 1854 | |
| 1855 | |
| 1856 | |
| 1857 | |
| 1858 | |
| 1859 | |
| 1860 | |
| 1861 | |
| 1862 | |
| 1863 | |
| 1864 | |
| 1865 | |
| 1866 | |
| 1867 | |
| 1868 | |
| 1869 | |
| 1870 | |
| 1871 | |
| 1872 | |
| 1873 | |
| 1874 | |
| 1875 | |
| 1876 | |
| 1877 | |
| 1878 | |
| 1879 | |
| 1880 | |
| 1881 | |
| 1882 | |
| 1883 | |
| 1884 | |
| 1885 | |
| 1886 | |
| 1887 | |
| 1888 | |
| 1889 | |
| 1890 | |
| 1891 | |
| 1892 | |
| 1893 | |
| 1894 | |
| 1895 | |
| 1896 | |
| 1897 | |
| 1898 | |
| 1899 | |
| 1900 | |
| 1901 | |
| 1902 | |
| 1903 | |
| 1904 | |
| 1905 | |
| 1906 | |
| 1907 | this.connect = function (connectOptions) { |
| 1908 | connectOptions = connectOptions || {} ; |
| 1909 | validate(connectOptions, {timeout:"number", |
| 1910 | userName:"string", |
| 1911 | password:"string", |
| 1912 | willMessage:"object", |
| 1913 | keepAliveInterval:"number", |
| 1914 | cleanSession:"boolean", |
| 1915 | useSSL:"boolean", |
| 1916 | invocationContext:"object", |
| 1917 | onSuccess:"function", |
| 1918 | onFailure:"function", |
| 1919 | hosts:"object", |
| 1920 | ports:"object", |
| 1921 | reconnect:"boolean", |
| 1922 | mqttVersion:"number", |
| 1923 | mqttVersionExplicit:"boolean", |
| 1924 | uris: "object"}); |
| 1925 | |
| 1926 | |
| 1927 | if (connectOptions.keepAliveInterval === undefined) |
| 1928 | connectOptions.keepAliveInterval = 60; |
| 1929 | |
| 1930 | if (connectOptions.mqttVersion > 4 || connectOptions.mqttVersion < 3) { |
| 1931 | throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.mqttVersion, "connectOptions.mqttVersion"])); |
| 1932 | } |
| 1933 | |
| 1934 | if (connectOptions.mqttVersion === undefined) { |
| 1935 | connectOptions.mqttVersionExplicit = false; |
| 1936 | connectOptions.mqttVersion = 4; |
| 1937 | } else { |
| 1938 | connectOptions.mqttVersionExplicit = true; |
| 1939 | } |
| 1940 | |
| 1941 | |
| 1942 | if (connectOptions.password !== undefined && connectOptions.userName === undefined) |
| 1943 | throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.password, "connectOptions.password"])); |
| 1944 | |
| 1945 | if (connectOptions.willMessage) { |
| 1946 | if (!(connectOptions.willMessage instanceof Message)) |
| 1947 | throw new Error(format(ERROR.INVALID_TYPE, [connectOptions.willMessage, "connectOptions.willMessage"])); |
| 1948 | |
| 1949 | |
| 1950 | connectOptions.willMessage.stringPayload = null; |
| 1951 | |
| 1952 | if (typeof connectOptions.willMessage.destinationName === "undefined") |
| 1953 | throw new Error(format(ERROR.INVALID_TYPE, [typeof connectOptions.willMessage.destinationName, "connectOptions.willMessage.destinationName"])); |
| 1954 | } |
| 1955 | if (typeof connectOptions.cleanSession === "undefined") |
| 1956 | connectOptions.cleanSession = true; |
| 1957 | if (connectOptions.hosts) { |
| 1958 | |
| 1959 | if (!(connectOptions.hosts instanceof Array) ) |
| 1960 | throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts, "connectOptions.hosts"])); |
| 1961 | if (connectOptions.hosts.length <1 ) |
| 1962 | throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts, "connectOptions.hosts"])); |
| 1963 | |
| 1964 | var usingURIs = false; |
| 1965 | for (var i = 0; i<connectOptions.hosts.length; i++) { |
| 1966 | if (typeof connectOptions.hosts[i] !== "string") |
| 1967 | throw new Error(format(ERROR.INVALID_TYPE, [typeof connectOptions.hosts[i], "connectOptions.hosts["+i+"]"])); |
| 1968 | if (/^(wss?):\/\/((\[(.+)\])|([^\/]+?))(:(\d+))?(\/.*)$/.test(connectOptions.hosts[i])) { |
| 1969 | if (i === 0) { |
| 1970 | usingURIs = true; |
| 1971 | } else if (!usingURIs) { |
| 1972 | throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts[i], "connectOptions.hosts["+i+"]"])); |
| 1973 | } |
| 1974 | } else if (usingURIs) { |
| 1975 | throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts[i], "connectOptions.hosts["+i+"]"])); |
| 1976 | } |
| 1977 | } |
| 1978 | |
| 1979 | if (!usingURIs) { |
| 1980 | if (!connectOptions.ports) |
| 1981 | throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.ports, "connectOptions.ports"])); |
| 1982 | if (!(connectOptions.ports instanceof Array) ) |
| 1983 | throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.ports, "connectOptions.ports"])); |
| 1984 | if (connectOptions.hosts.length !== connectOptions.ports.length) |
| 1985 | throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.ports, "connectOptions.ports"])); |
| 1986 | |
| 1987 | connectOptions.uris = []; |
| 1988 | |
| 1989 | for (var i = 0; i<connectOptions.hosts.length; i++) { |
| 1990 | if (typeof connectOptions.ports[i] !== "number" || connectOptions.ports[i] < 0) |
| 1991 | throw new Error(format(ERROR.INVALID_TYPE, [typeof connectOptions.ports[i], "connectOptions.ports["+i+"]"])); |
| 1992 | var host = connectOptions.hosts[i]; |
| 1993 | var port = connectOptions.ports[i]; |
| 1994 | |
| 1995 | var ipv6 = (host.indexOf(":") !== -1); |
| 1996 | uri = "ws://"+(ipv6?"["+host+"]":host)+":"+port+path; |
| 1997 | connectOptions.uris.push(uri); |
| 1998 | } |
| 1999 | } else { |
| 2000 | connectOptions.uris = connectOptions.hosts; |
| 2001 | } |
| 2002 | } |
| 2003 | |
| 2004 | client.connect(connectOptions); |
| 2005 | }; |
| 2006 | |
| 2007 | |
| 2008 | |
| 2009 | |
| 2010 | |
| 2011 | |
| 2012 | |
| 2013 | |
| 2014 | |
| 2015 | |
| 2016 | |
| 2017 | |
| 2018 | |
| 2019 | |
| 2020 | |
| 2021 | |
| 2022 | |
| 2023 | |
| 2024 | |
| 2025 | |
| 2026 | |
| 2027 | |
| 2028 | |
| 2029 | |
| 2030 | |
| 2031 | |
| 2032 | |
| 2033 | |
| 2034 | |
| 2035 | |
| 2036 | |
| 2037 | |
| 2038 | |
| 2039 | this.subscribe = function (filter, subscribeOptions) { |
| 2040 | if (typeof filter !== "string") |
| 2041 | throw new Error("Invalid argument:"+filter); |
| 2042 | subscribeOptions = subscribeOptions || {} ; |
| 2043 | validate(subscribeOptions, {qos:"number", |
| 2044 | invocationContext:"object", |
| 2045 | onSuccess:"function", |
| 2046 | onFailure:"function", |
| 2047 | timeout:"number" |
| 2048 | }); |
| 2049 | if (subscribeOptions.timeout && !subscribeOptions.onFailure) |
| 2050 | throw new Error("subscribeOptions.timeout specified with no onFailure callback."); |
| 2051 | if (typeof subscribeOptions.qos !== "undefined" && !(subscribeOptions.qos === 0 || subscribeOptions.qos === 1 || subscribeOptions.qos === 2 )) |
| 2052 | throw new Error(format(ERROR.INVALID_ARGUMENT, [subscribeOptions.qos, "subscribeOptions.qos"])); |
| 2053 | client.subscribe(filter, subscribeOptions); |
| 2054 | }; |
| 2055 | |
| 2056 | |
| 2057 | |
| 2058 | |
| 2059 | |
| 2060 | |
| 2061 | |
| 2062 | |
| 2063 | |
| 2064 | |
| 2065 | |
| 2066 | |
| 2067 | |
| 2068 | |
| 2069 | |
| 2070 | |
| 2071 | |
| 2072 | |
| 2073 | |
| 2074 | |
| 2075 | |
| 2076 | |
| 2077 | |
| 2078 | |
| 2079 | |
| 2080 | |
| 2081 | |
| 2082 | |
| 2083 | |
| 2084 | this.unsubscribe = function (filter, unsubscribeOptions) { |
| 2085 | if (typeof filter !== "string") |
| 2086 | throw new Error("Invalid argument:"+filter); |
| 2087 | unsubscribeOptions = unsubscribeOptions || {} ; |
| 2088 | validate(unsubscribeOptions, {invocationContext:"object", |
| 2089 | onSuccess:"function", |
| 2090 | onFailure:"function", |
| 2091 | timeout:"number" |
| 2092 | }); |
| 2093 | if (unsubscribeOptions.timeout && !unsubscribeOptions.onFailure) |
| 2094 | throw new Error("unsubscribeOptions.timeout specified with no onFailure callback."); |
| 2095 | client.unsubscribe(filter, unsubscribeOptions); |
| 2096 | }; |
| 2097 | |
| 2098 | |
| 2099 | |
| 2100 | |
| 2101 | |
| 2102 | |
| 2103 | |
| 2104 | |
| 2105 | |
| 2106 | |
| 2107 | |
| 2108 | |
| 2109 | |
| 2110 | |
| 2111 | |
| 2112 | |
| 2113 | |
| 2114 | |
| 2115 | |
| 2116 | |
| 2117 | |
| 2118 | |
| 2119 | |
| 2120 | this.send = function (topic,payload,qos,retained) { |
| 2121 | var message ; |
| 2122 | |
| 2123 | if(arguments.length === 0){ |
| 2124 | throw new Error("Invalid argument."+"length"); |
| 2125 | |
| 2126 | }else if(arguments.length == 1) { |
| 2127 | |
| 2128 | if (!(topic instanceof Message) && (typeof topic !== "string")) |
| 2129 | throw new Error("Invalid argument:"+ typeof topic); |
| 2130 | |
| 2131 | message = topic; |
| 2132 | if (typeof message.destinationName === "undefined") |
| 2133 | throw new Error(format(ERROR.INVALID_ARGUMENT,[message.destinationName,"Message.destinationName"])); |
| 2134 | client.send(message); |
| 2135 | |
| 2136 | }else { |
| 2137 | |
| 2138 | message = new Message(payload); |
| 2139 | message.destinationName = topic; |
| 2140 | if(arguments.length >= 3) |
| 2141 | message.qos = qos; |
| 2142 | if(arguments.length >= 4) |
| 2143 | message.retained = retained; |
| 2144 | client.send(message); |
| 2145 | } |
| 2146 | }; |
| 2147 | |
| 2148 | |
| 2149 | |
| 2150 | |
| 2151 | |
| 2152 | |
| 2153 | |
| 2154 | |
| 2155 | |
| 2156 | |
| 2157 | |
| 2158 | |
| 2159 | |
| 2160 | |
| 2161 | |
| 2162 | |
| 2163 | |
| 2164 | |
| 2165 | |
| 2166 | |
| 2167 | |
| 2168 | |
| 2169 | |
| 2170 | |
| 2171 | this.publish = function(topic,payload,qos,retained) { |
| 2172 | console.log("Publising message to: ", topic); |
| 2173 | var message ; |
| 2174 | |
| 2175 | if(arguments.length === 0){ |
| 2176 | throw new Error("Invalid argument."+"length"); |
| 2177 | |
| 2178 | }else if(arguments.length == 1) { |
| 2179 | |
| 2180 | if (!(topic instanceof Message) && (typeof topic !== "string")) |
| 2181 | throw new Error("Invalid argument:"+ typeof topic); |
| 2182 | |
| 2183 | message = topic; |
| 2184 | if (typeof message.destinationName === "undefined") |
| 2185 | throw new Error(format(ERROR.INVALID_ARGUMENT,[message.destinationName,"Message.destinationName"])); |
| 2186 | client.send(message); |
| 2187 | |
| 2188 | }else { |
| 2189 | |
| 2190 | message = new Message(payload); |
| 2191 | message.destinationName = topic; |
| 2192 | if(arguments.length >= 3) |
| 2193 | message.qos = qos; |
| 2194 | if(arguments.length >= 4) |
| 2195 | message.retained = retained; |
| 2196 | client.send(message); |
| 2197 | } |
| 2198 | }; |
| 2199 | |
| 2200 | |
| 2201 | |
| 2202 | |
| 2203 | |
| 2204 | |
| 2205 | |
| 2206 | |
| 2207 | this.disconnect = function () { |
| 2208 | client.disconnect(); |
| 2209 | }; |
| 2210 | |
| 2211 | |
| 2212 | |
| 2213 | |
| 2214 | |
| 2215 | |
| 2216 | |
| 2217 | |
| 2218 | this.getTraceLog = function () { |
| 2219 | return client.getTraceLog(); |
| 2220 | }; |
| 2221 | |
| 2222 | |
| 2223 | |
| 2224 | |
| 2225 | |
| 2226 | |
| 2227 | |
| 2228 | this.startTrace = function () { |
| 2229 | client.startTrace(); |
| 2230 | }; |
| 2231 | |
| 2232 | |
| 2233 | |
| 2234 | |
| 2235 | |
| 2236 | |
| 2237 | |
| 2238 | this.stopTrace = function () { |
| 2239 | client.stopTrace(); |
| 2240 | }; |
| 2241 | |
| 2242 | this.isConnected = function() { |
| 2243 | return client.connected; |
| 2244 | }; |
| 2245 | }; |
| 2246 | |
| 2247 | Client.prototype = { |
| 2248 | get host() { return this._getHost(); }, |
| 2249 | set host(newHost) { this._setHost(newHost); }, |
| 2250 | |
| 2251 | get port() { return this._getPort(); }, |
| 2252 | set port(newPort) { this._setPort(newPort); }, |
| 2253 | |
| 2254 | get path() { return this._getPath(); }, |
| 2255 | set path(newPath) { this._setPath(newPath); }, |
| 2256 | |
| 2257 | get clientId() { return this._getClientId(); }, |
| 2258 | set clientId(newClientId) { this._setClientId(newClientId); }, |
| 2259 | |
| 2260 | get onConnected() { return this._getOnConnected(); }, |
| 2261 | set onConnected(newOnConnected) { this._setOnConnected(newOnConnected); }, |
| 2262 | |
| 2263 | get disconnectedPublishing() { return this._getDisconnectedPublishing(); }, |
| 2264 | set disconnectedPublishing(newDisconnectedPublishing) { this._setDisconnectedPublishing(newDisconnectedPublishing); }, |
| 2265 | |
| 2266 | get disconnectedBufferSize() { return this._getDisconnectedBufferSize(); }, |
| 2267 | set disconnectedBufferSize(newDisconnectedBufferSize) { this._setDisconnectedBufferSize(newDisconnectedBufferSize); }, |
| 2268 | |
| 2269 | get onConnectionLost() { return this._getOnConnectionLost(); }, |
| 2270 | set onConnectionLost(newOnConnectionLost) { this._setOnConnectionLost(newOnConnectionLost); }, |
| 2271 | |
| 2272 | get onMessageDelivered() { return this._getOnMessageDelivered(); }, |
| 2273 | set onMessageDelivered(newOnMessageDelivered) { this._setOnMessageDelivered(newOnMessageDelivered); }, |
| 2274 | |
| 2275 | get onMessageArrived() { return this._getOnMessageArrived(); }, |
| 2276 | set onMessageArrived(newOnMessageArrived) { this._setOnMessageArrived(newOnMessageArrived); }, |
| 2277 | |
| 2278 | get trace() { return this._getTrace(); }, |
| 2279 | set trace(newTraceFunction) { this._setTrace(newTraceFunction); } |
| 2280 | |
| 2281 | }; |
| 2282 | |
| 2283 | |
| 2284 | |
| 2285 | |
| 2286 | |
| 2287 | |
| 2288 | |
| 2289 | |
| 2290 | |
| 2291 | |
| 2292 | |
| 2293 | |
| 2294 | |
| 2295 | |
| 2296 | |
| 2297 | |
| 2298 | |
| 2299 | |
| 2300 | |
| 2301 | |
| 2302 | |
| 2303 | |
| 2304 | |
| 2305 | |
| 2306 | |
| 2307 | |
| 2308 | |
| 2309 | |
| 2310 | |
| 2311 | |
| 2312 | |
| 2313 | |
| 2314 | |
| 2315 | |
| 2316 | |
| 2317 | var Message = function (newPayload) { |
| 2318 | var payload; |
| 2319 | if ( typeof newPayload === "string" || |
| 2320 | newPayload instanceof ArrayBuffer || |
| 2321 | newPayload instanceof Int8Array || |
| 2322 | newPayload instanceof Uint8Array || |
| 2323 | newPayload instanceof Int16Array || |
| 2324 | newPayload instanceof Uint16Array || |
| 2325 | newPayload instanceof Int32Array || |
| 2326 | newPayload instanceof Uint32Array || |
| 2327 | newPayload instanceof Float32Array || |
| 2328 | newPayload instanceof Float64Array |
| 2329 | ) { |
| 2330 | payload = newPayload; |
| 2331 | } else { |
| 2332 | throw (format(ERROR.INVALID_ARGUMENT, [newPayload, "newPayload"])); |
| 2333 | } |
| 2334 | |
| 2335 | this._getPayloadString = function () { |
| 2336 | if (typeof payload === "string") |
| 2337 | return payload; |
| 2338 | else |
| 2339 | return parseUTF8(payload, 0, payload.length); |
| 2340 | }; |
| 2341 | |
| 2342 | this._getPayloadBytes = function() { |
| 2343 | if (typeof payload === "string") { |
| 2344 | var buffer = new ArrayBuffer(UTF8Length(payload)); |
| 2345 | var byteStream = new Uint8Array(buffer); |
| 2346 | stringToUTF8(payload, byteStream, 0); |
| 2347 | |
| 2348 | return byteStream; |
| 2349 | } else { |
| 2350 | return payload; |
| 2351 | } |
| 2352 | }; |
| 2353 | |
| 2354 | var destinationName; |
| 2355 | this._getDestinationName = function() { return destinationName; }; |
| 2356 | this._setDestinationName = function(newDestinationName) { |
| 2357 | if (typeof newDestinationName === "string") |
| 2358 | destinationName = newDestinationName; |
| 2359 | else |
| 2360 | throw new Error(format(ERROR.INVALID_ARGUMENT, [newDestinationName, "newDestinationName"])); |
| 2361 | }; |
| 2362 | |
| 2363 | var qos = 0; |
| 2364 | this._getQos = function() { return qos; }; |
| 2365 | this._setQos = function(newQos) { |
| 2366 | if (newQos === 0 || newQos === 1 || newQos === 2 ) |
| 2367 | qos = newQos; |
| 2368 | else |
| 2369 | throw new Error("Invalid argument:"+newQos); |
| 2370 | }; |
| 2371 | |
| 2372 | var retained = false; |
| 2373 | this._getRetained = function() { return retained; }; |
| 2374 | this._setRetained = function(newRetained) { |
| 2375 | if (typeof newRetained === "boolean") |
| 2376 | retained = newRetained; |
| 2377 | else |
| 2378 | throw new Error(format(ERROR.INVALID_ARGUMENT, [newRetained, "newRetained"])); |
| 2379 | }; |
| 2380 | |
| 2381 | var duplicate = false; |
| 2382 | this._getDuplicate = function() { return duplicate; }; |
| 2383 | this._setDuplicate = function(newDuplicate) { duplicate = newDuplicate; }; |
| 2384 | }; |
| 2385 | |
| 2386 | Message.prototype = { |
| 2387 | get payloadString() { return this._getPayloadString(); }, |
| 2388 | get payloadBytes() { return this._getPayloadBytes(); }, |
| 2389 | |
| 2390 | get destinationName() { return this._getDestinationName(); }, |
| 2391 | set destinationName(newDestinationName) { this._setDestinationName(newDestinationName); }, |
| 2392 | |
| 2393 | get topic() { return this._getDestinationName(); }, |
| 2394 | set topic(newTopic) { this._setDestinationName(newTopic); }, |
| 2395 | |
| 2396 | get qos() { return this._getQos(); }, |
| 2397 | set qos(newQos) { this._setQos(newQos); }, |
| 2398 | |
| 2399 | get retained() { return this._getRetained(); }, |
| 2400 | set retained(newRetained) { this._setRetained(newRetained); }, |
| 2401 | |
| 2402 | get duplicate() { return this._getDuplicate(); }, |
| 2403 | set duplicate(newDuplicate) { this._setDuplicate(newDuplicate); } |
| 2404 | }; |
| 2405 | |
| 2406 | |
| 2407 | return { |
| 2408 | Client: Client, |
| 2409 | Message: Message |
| 2410 | }; |
| 2411 | })(window); |
| 2412 | return PahoMQTT; |
| 2413 | }); |
| 2414 | |