github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/sdk/javascript/messaging/stream.js (about) 1 /** 2 * Copyright 2016 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * ------------------------------------------------------------------------------ 16 */ 17 18 'use strict' 19 20 const crypto = require('crypto') 21 const uuid = require('uuid/v4') 22 const zmq = require('zeromq') 23 24 const assert = require('assert') 25 26 const { Message } = require('../protobuf') 27 const Deferred = require('./deferred') 28 const { ValidatorConnectionError } = require('../processor/exceptions') 29 30 const _encodeMessage = (messageType, correlationId, content) => { 31 assert( 32 typeof messageType === 'number', 33 `messageType must be a number; was ${messageType}` 34 ) 35 assert( 36 typeof correlationId === 'string', 37 `correlationId must be a string; was ${correlationId}` 38 ) 39 assert( 40 content !== undefined || content !== null, 41 'content must not be null or undefined' 42 ) 43 assert( 44 Buffer.isBuffer(content), 45 `content must be a buffer; was ${ 46 content.constructor ? content.constructor.name : typeof content 47 }` 48 ) 49 50 return Message.encode({ 51 messageType, 52 correlationId, 53 content 54 }).finish() 55 } 56 57 const _generateId = () => 58 crypto.createHash('sha256') 59 .update(uuid()) 60 .digest('hex') 61 62 class Stream { 63 constructor (url) { 64 this._url = url 65 66 this._initial_connection = true 67 } 68 69 connect (onConnectCb) { 70 if (this._onConnectCb) { 71 console.log(`Attempting to reconnect to ${this._url}`) 72 } 73 74 this._onConnectCb = onConnectCb 75 76 this._futures = {} 77 this._socket = zmq.socket('dealer') 78 this._socket.setsockopt('identity', Buffer.from(uuid(), 'utf8')) 79 this._socket.on('connect', () => { 80 console.log(`Connected to ${this._url}`) 81 onConnectCb() 82 }) 83 this._socket.on('disconnect', (fd, endpoint) => this._handleDisconnect()) 84 this._socket.monitor(250, 0) 85 this._socket.connect(this._url) 86 87 this._initial_connection = false 88 } 89 90 close () { 91 this._socket.setsockopt(zmq.ZMQ_LINGER, 0) 92 this._socket.unmonitor() 93 this._socket.close() 94 this._socket = null 95 } 96 97 _handleDisconnect () { 98 console.log(`Disconnected from ${this._url}`) 99 this.close() 100 Object.keys(this._futures).forEach((correlationId) => { 101 this._futures[correlationId].reject( 102 new ValidatorConnectionError('The connection to the validator was lost') 103 ) 104 }) 105 106 this.connect(this._onConnectCb) 107 } 108 109 send (type, content) { 110 if (this._socket) { 111 const correlationId = _generateId() 112 let deferred = new Deferred() 113 this._futures[correlationId] = deferred 114 115 try { 116 this._socket.send(_encodeMessage(type, correlationId, content)) 117 } catch (e) { 118 delete this._futures[correlationId] 119 return Promise.reject(e) 120 } 121 122 return deferred.promise 123 .then(result => { 124 delete this._futures[correlationId] 125 return result 126 }) 127 .catch(err => { 128 delete this._futures[correlationId] 129 throw err 130 }) 131 } else { 132 let err = null 133 if (this._initial_connection) { 134 err = new Error('Must call `connect` before calling `send`') 135 } else { 136 err = new ValidatorConnectionError( 137 'The connection to the validator was lost' 138 ) 139 } 140 141 return Promise.reject(err) 142 } 143 } 144 145 sendBack (type, correlationId, content) { 146 if (this._socket) { 147 this._socket.send(_encodeMessage(type, correlationId, content)) 148 } 149 } 150 151 onReceive (cb) { 152 this._socket.on('message', buffer => { 153 let message = Message.decode(buffer) 154 if (this._futures[message.correlationId]) { 155 this._futures[message.correlationId].resolve(message.content) 156 } else { 157 process.nextTick(() => cb(message)) 158 } 159 }) 160 } 161 } 162 163 module.exports = { Stream }