Skip to content

ildar/tango

 
 

Repository files navigation

About

tango is a small, simple and customizable RPC (remote procedure call) module for Lua.

Its main features are:

  • a generic transparent proxy for call invocations
  • support of remote objects (tables with functions, userdata etc, see tango.ref)
  • a generic dispatch routine for servers
  • several server implementations for different protocols, message formats and event/io frameworks, further called backends
  • several client implementations for different protocols and message formats
  • support NodeMCU-run server, see README-NodeMCU.md for details

Backends included

Tutorial (copas_socket server + socket client)

Greetings!

The greet server code

-- load tango module
local tango = require'tango'
-- define a nice greeting function
greet = function(...)
          print(...)
        end 
-- start listening for client connections        
tango.server.copas_socket.loop{
  port = 12345
}

The client code calling the remote server function greet

-- load tango module
local tango = require'tango'
-- connect to server
local con = tango.client.socket.connect{
   address = 'localhost',
   port = 12345
}
-- call the remote greeting function
con.greet('Hello','Horst')

Access anything?

Since the server exposes the global table _G by default, the client may even directly call print,let the server sleep a bit remotely (os.execute) or calc some stuff (math.sqrt).

-- variable argument count is supported
con.print('I','call','print','myself')
-- any function or variable in the server's _G can be accessed by default
con.os.execute('sleep 1')
con.math.sqrt(4)

One can limit the server exposed functions by specifying a functab like this (to expose only methods of he math table/module):

local tango = require'tango'
-- just pass a table to the functab to limit the access to this table
tango.server.copas_socket.loop{
  port = 12345,
  functab = math
}

As the global table _G is not available any more, the client can only call methods from the math module:

con.sqrt(4)

Remote Variables

Sometimes you need to get some data from the server, as enumaration-like-constants for instance. Easy-peasy!

Let's read the remote table friends from the server

local tango = require'tango'
-- connect to server as usual
local con = tango.client.socket.connect()
-- friends is a remote table but could be of any other type
local friends = con.friends

To change the servers state, just assign a new value as usual:

local tango = require'tango'
local con = tango.client.socket.connect()
-- read the remote variable
local friends = con.friends
-- modify it 
table.insert(friends,'Horst')

If you are worried about security concerns, just do not allow read and/or write access:

local tango = require'tango'
-- write_access and read_access can be set independently
-- accessing variables from the client side will now cause errors.
tango.server.copas_socket.loop{
  write_access = false,
  read_access = false
}

Using classes/tables/objects remotely

Lua progamming language has basic types (e.g. numbers, strings etc.) and object types. The basic types are assigned and passed as values while object type have references. The oject types are: tables, functions, userdata and thread.

Tango provides ways to push and pull values of basic types. But object types are represented by proxy objects (tables) that allows to handle remote objects in most natural ways.

See the examples in spec/ and test_*.lua

Tests

You can run test by the following sh call in the project root directory:

  ./test.lua

tango does not need to be installed.

Client/Server compatibilities

tango.client.sockettango.client.zmq
tango.server.copas_socketX
tango.server.ev_socketX
tango.server.lgi_asyncX
tango.server.nodemcu.netX
tango.server.zmqX

Serialization

tango provides a default (lua-only) table serialization which should meet most common use cases.

Anyhow, the table serialization is neither exceedingly fast nor compact in output or memory consumption. If this is a problem for your application, you can customize the serialization by assigning your serialize/unserialize methods to the clients and servers respectively.

Socket client with customized serialization:

local tango = require'tango'
local cjson = require'cjson'
-- set serialization on the client side
local con = tango.client.socket.connect{
   serialize = cjson.encode,
   unserialize = cjson.decode
}

Copas socket server with customized serialization:

local tango = require'tango'
local cjson = require'cjson'
-- set serialization on the server side
tango.server.copas_socket.loop{
   serialize = cjson.encode,
   unserialize = cjson.decode
}

Some alternatives are:

Requirements

The requirements depend on the desired i/o backend, see the corresponding rockspecs for details.

Installation

With LuaRocks: Directly from the its repository:

 $ sudo luarocks install tango-copas

or tango-complete, which requires lua-zmq and lua-ev (and the corresponding C-libs:

 $ sudo luarocks install tango-complete

or a specific rock from

 $ sudo luarocks install https://raw.github.com/lipp/tango/master/rockspecs/SPECIFIC_ROCKSPEC

Note: luarocks must be >= 2.0.4.1 and requires luasec for doing https requests!

 $ sudo apt-get install libssl-dev
 $ sudo luarocks install luasec

About

A simple and transparent RPC module for Lua.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Lua 100.0%