electrum-client/lib/client.js
2017-07-10 17:27:21 +09:00

117 lines
3.2 KiB
JavaScript

'use strict'
const EventEmitter = require('events').EventEmitter;
const tls = require('tls');
const net = require('net');
const util = require('./util');
class MessageParser{
constructor(callback){
this.buffer = ''
this.callback = callback
}
run(chunk){
this.buffer += chunk
while(true){
const res = util.recursiveParser(0, this.buffer, this.callback)
this.buffer = res.buffer
if(res.code === 0){
break;
}
}
}
}
const getSocket = (protocol, options) => {
switch(protocol){
case 'tcp':
return new net.Socket();
case 'tls':
case 'ssl':
return new tls.TLSSocket(options);
}
throw new Error('unknown protocol')
}
class Client{
constructor(port, host, protocol = 'tcp', options = void 0){
this.port = port
this.host = host
this.hostname = [host, port].join(':')
this.callback_message_queue = {}
this.id = 0;
this.mp = new MessageParser((body, n) => {
this.onMessageRecv(JSON.parse(body));
});
this.subscribe = new EventEmitter()
const conn = this.conn = getSocket(protocol, options);
conn.setEncoding('utf8')
conn.setKeepAlive(true, 0)
conn.setNoDelay(true)
conn.on('connect', () => {
})
conn.on('close', () => {
Object.keys(this.callback_message_queue).forEach((key) => {
this.callback_message_queue[key](new Error('close connect'))
delete this.callback_message_queue[key]
})
const list = [
'server.peers.subscribe',
'blockchain.numblocks.subscribe',
'blockchain.headers.subscribe',
'blockchain.address.subscribe'
]
list.forEach(event => this.subscribe.removeAllListeners(event))
})
conn.on('data', (chunk) => {
this.mp.run(chunk)
})
conn.on('end', () => {
})
}
connect(){
return new Promise((resolve, reject) => {
this.conn.connect(this.port, this.host, () => {
resolve()
})
})
}
close(){
this.conn.end();
this.conn.destroy();
}
onMessageRecv(msg){
if(msg instanceof Array){
; // don't support batch request
} else {
if(msg.id !== void 0){
const callback = this.callback_message_queue[msg.id]
if(callback){
delete this.callback_message_queue[msg.id]
if(msg.error){
callback(msg.error)
}else{
callback(null, msg.result)
}
}
}else{
this.subscribe.emit(msg.method, msg.params)
}
}
}
request(method, params){
return new Promise((resolve, reject) => {
const id = ++this.id;
const content = util.makeRequest(method, params, id);
this.callback_message_queue[id] = util.createPromiseResult(resolve, reject);
this.conn.write(content + '\n');
})
}
}
module.exports = Client