All Projects → ssb-js → muxrpc

ssb-js / muxrpc

Licence: MIT license
lightweight multiplexed rpc

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to muxrpc

metacom
RPC communication protocol for Metarhia stack 🔌
Stars: ✭ 42 (-56.25%)
Mutual labels:  protocol, rpc
ws-promise
A tiny, Promise-based WebSocket protocol allowing request-response usage in ECMAScript
Stars: ✭ 20 (-79.17%)
Mutual labels:  protocol, rpc
Getty
a netty like asynchronous network I/O library based on tcp/udp/websocket; a bidirectional RPC framework based on JSON/Protobuf; a microservice framework based on zookeeper/etcd
Stars: ✭ 532 (+454.17%)
Mutual labels:  rpc, codec
spring-boot-protocol
springboot功能扩充-netty动态协议,可以支持各种网络协议的动态切换(单端口支持多个网络协议).支持mmap,sendfile零拷贝,http请求批量聚合
Stars: ✭ 68 (-29.17%)
Mutual labels:  protocol, rpc
Jstp
Fast RPC for browser and Node.js based on TCP, WebSocket, and MDSF
Stars: ✭ 132 (+37.5%)
Mutual labels:  protocol, rpc
Erpc
An efficient, extensible and easy-to-use RPC framework.
Stars: ✭ 2,274 (+2268.75%)
Mutual labels:  protocol, rpc
sirdez
Glorious Binary Serialization and Deserialization for TypeScript.
Stars: ✭ 20 (-79.17%)
Mutual labels:  protocol, rpc
Sharer
Arduino & .NET serial communication library to read/write variables and remote call functions using the Sharer protocol. Works on Windows, Linux and MacOS.
Stars: ✭ 21 (-78.12%)
Mutual labels:  protocol, rpc
Mu Scala
Mu is a purely functional library for building RPC endpoint based services with support for RPC and HTTP/2
Stars: ✭ 266 (+177.08%)
Mutual labels:  protocol, rpc
Dop
JavaScript implementation for Distributed Object Protocol
Stars: ✭ 163 (+69.79%)
Mutual labels:  protocol, rpc
Ttrpc
GRPC for low-memory environments
Stars: ✭ 236 (+145.83%)
Mutual labels:  protocol, rpc
doteasy.rpc
Inspired by microservices, a lightweight framework that looks like a rabbit, based on NET Core 2.0 Standard 2 core library
Stars: ✭ 62 (-35.42%)
Mutual labels:  rpc
rmp-rpc
a msgpack-rpc rust library based on tokio
Stars: ✭ 45 (-53.12%)
Mutual labels:  rpc
stream-list-updater
Automation for updating an index of live George Floyd protest streams
Stars: ✭ 15 (-84.37%)
Mutual labels:  streams
micro-service-practice
OpenStack+Docker+RestAPI+OAuth/HMAC+RabbitMQ/ZMQ+OpenResty/HAProxy/Nginx/APIGateway+Bootstrap/AngularJS+Ansible+K8S/Mesos/Marathon构建/探索微服务最佳实践。
Stars: ✭ 25 (-73.96%)
Mutual labels:  rpc
JNQD
Learning-based Just-noticeable-quantization-distortion Model for perceptual video coding
Stars: ✭ 21 (-78.12%)
Mutual labels:  codec
jigsaw-rpc
jigsaw-rpc is an RPC framework written in TypeScript under Node.js
Stars: ✭ 14 (-85.42%)
Mutual labels:  rpc
SuperSimpleTcp
Simple wrapper for TCP client and server in C# with SSL support
Stars: ✭ 263 (+173.96%)
Mutual labels:  rpc
frodo
A code generator that turns plain old Go services into RPC-enabled (micro)services with robust HTTP APIs.
Stars: ✭ 21 (-78.12%)
Mutual labels:  rpc
libnvc
Easy way to embed (neo)vim in your application
Stars: ✭ 32 (-66.67%)
Mutual labels:  rpc

muxrpc

combined rpc and multiplexing, with pull-streams.

build status

motivation

muxrpc aims to provide remote access to any reasonable node.js api remotely. this means it supports both streaming and async operations. pull-streams are used.

It may seem at first that it would be logically cleaner to separate this into two concerns, multiplexing and request-response. Indeed, we did just that in multilevel combining mux-demux and rpc-stream however, I realized that multiplexing depends on adding framing to incoming messages, and so does rpc. If rpc is implemented as another layer on top of multiplexing, then the rpc messages end up with a second layer of framing too. By implementing one protocol that supports both streams and rpc, we were able to have both features with only a single layer of framing.

example

const MRPC = require('muxrpc')
const pull = require('pull-stream')
const toPull = require('stream-to-pull-stream')

//we need a manifest of methods we wish to expose.
const manifest = {
  //async is a normal async function
  hello: 'async',

  //source is a pull-stream (readable)
  stuff: 'source'

  //TODO: sink and duplex pull-streams
}

//the actual methods which the server exposes
const api = {
  hello(name, cb) {
    cb(null, 'hello, ' + name + '!')
  },
  stuff() {
    return pull.values([1, 2, 3, 4, 5])
  }
}

//pass the manifests into the constructor, and then pass the local api object you are wrapping
//(if there is a local api)
const client = MRPC(manifest, null) () //MRPC (remoteManifest, localManifest) (localApi)
const server = MRPC(null, manifest) (api)

now set up a server, and connect to it...

const net = require('net')

net.createServer(stream => {
  stream = toPull.duplex(stream) //turn into a pull-stream
  //connect the output of the net stream to the muxrpc stream
  //and then output of the muxrpc stream to the net stream
  pull(stream, server.createStream(), stream)
}).listen(8080)
//connect a pair of duplex streams together.

const stream = toPull.duplex(net.connect(8080))

const onClose = () => {
  console.log('connected to muxrpc server')
}

pull(stream, client.createStream(onClose), stream)

// Now you can call methods like this.
client.hello('world', function (err, value) {
  if(err) throw err
  console.log(value)
  // hello, world!
})

// Alternatively, you can use the promise syntax.
client.hello('world').then((value) => {
  console.log(value)
})

pull(client.stuff(), pull.drain(console.log))
// 1
// 2
// 3
// 4
// 5

protocol

As indicated by the name, muxrpc combines both multiplexing and rpc (remote procedure call, i.e. request-response). The protocol is described in details in rpc protocol section of the protocol guide

Api: createMuxrpc (remoteManifest, localManifest, localApi, id, perms, codec, legacy) => rpc

remoteManifest the manifest expected on the remote end of this connection. localManifest the manifest of the methods we are exposing locally. localApi the actual methods we are exposing - this is on object with function with call types that match the manifest.

id a string identifing the remote identity. muxrpc only knows the name of it's friend but not it's own name.

perms a permissions object with {test: function (path, type, args) {} } function.

codec stream encoding. defaults to packet-stream-codec

legacy engage legacy mode.

rpc

an EventEmitter containing proxies for all the methods defined in your manifest, as well as the following:

  • stream
  • createStream method, only if legacy mode
  • id (string, the id of the remote)
  • _emit emit an event locally.
  • closed a boolean, wether the instance is closed.
  • close an async method to close this connection, will end the rpc.stream

And every method provided in the manifest. If a method in the manifest has the same name as a built in, the built in will override the manifest, and you will not be able to call that remove method.

Manifest

muxrpc works with async functions, sync functions, and pull-streams. But that javascript is dynamic, we need to tell muxrpc what sort of method should be at what api, that is what the "mainfest" is for. The manifest is simply an object mapping a key to one of the strings "sync" "async" "source" "sink" or "duplex", or a nested manifest.

{
  foo: 'async',        //a function with a callback.
  bar: 'sync',         //a function that returns a value
                       //(note this is converted to an async function for the client)
  allTheFoos: 'source' //a source pull-stream (aka, readable)
  writeFoos: 'sink',   //a sink pull-stream (aka, writable)
  fooPhone: 'duplex',  //a duplex pull-stream

  //create nested objects like this:
  bar: {
    ...
  }
}

Permissions

muxrpc includes a helper module for defining permissions. it implements a simple allow/deny list to define permissions for a given connection.

var Permissions = require('muxrpc/permissions')

var manifest = {
  foo: 'async',
  bar: 'async',
  auth: 'async'
}

//set initial settings
var perms = Perms({allow: ['auth']})

var rpc = muxrpc(null /* no remote manifest */, manifest, serializer)({
  foo: function (val, cb) {
    cb(null, {okay: 'foo'})
  },
  bar: function (val, cb) {
    cb(null, {okay: 'bar'})
  },
  auth: function (pass) {
    //implement an auth function that sets the permissions,
    //using allow or deny lists.

    if(pass === 'whatever')
      perms({deny: ['bar']}) //allow everything except "bar"
    else if(pass === 's3cr3tz')
      perms({}) //allow everything!!!
    else return cb(new Error('ACCESS DENIED'))

    //else we ARE authorized.
    cb(null, 'ACCESS GRANTED')
  }
}, perms) //pass the perms object to the second argument of the constructor.

//Get a stream to connect to the remote. As in the above example!
var ss = rpc.createStream()

bootstrapping - automatically loading the remote manifest.

Sometimes you don't know the remote manifest yet. If you pass a callback instead of remoteManifest, then an async method manifest is called on the remote, which should return a manifest. This then used as the remote manifest and the callback is called.

var manifest = { hello: 'sync', manifest: 'sync' }

var alice = Muxrpc(null, manifest)({
  hello: function (message) {
    if(this._emit) this._emit('hello', message)
    console.log(`${this.id} received ${message}`)
    return `${message} to you too`
  },
  manifest: function () {
    return manifest
  }
})


var bob = Muxrpc(function (err, manifest) {
  if (err) throw err

  // Bob now knows Alice's API
  console.log(manifest) // => { hello: 'sync', manifest: 'sync' }

  bob.hello('aloha', (err, val) => {
    if (err) throw err
    console.log(val) // => "aloha to you too"
  })
})()

var bobStream = bob.createStream()

alice.id = 'alice'
bob.id = 'bob'

pull(
  bobStream,
  alice.createStream(),
  bobStream
)

License

MIT

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].