{"id":18962266,"url":"https://github.com/lipp/tango","last_synced_at":"2025-04-19T11:53:00.253Z","repository":{"id":138884872,"uuid":"1599896","full_name":"lipp/tango","owner":"lipp","description":"A simple and transparent RPC module for Lua.","archived":false,"fork":false,"pushed_at":"2012-03-12T21:02:03.000Z","size":225,"stargazers_count":54,"open_issues_count":2,"forks_count":12,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-16T04:45:54.565Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lipp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-04-11T16:33:27.000Z","updated_at":"2024-06-08T09:45:02.000Z","dependencies_parsed_at":"2023-03-13T23:31:34.980Z","dependency_job_id":null,"html_url":"https://github.com/lipp/tango","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipp%2Ftango","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipp%2Ftango/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipp%2Ftango/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipp%2Ftango/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lipp","download_url":"https://codeload.github.com/lipp/tango/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249688745,"owners_count":21311288,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T14:15:47.467Z","updated_at":"2025-04-19T11:53:00.234Z","avatar_url":"https://github.com/lipp.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"About\n=======\n\ntango is a small, simple and customizable RPC (remote procedure call)\nmodule for Lua.\n\nIts main features are:\n\n* a generic transparent\n  [proxy](https://github.com/lipp/tango/tree/master/tango/proxy.lua)\n  for call invocations\n* support of remote objects (tables with functions, userdata etc, see tango.ref)\n* a generic [dispatch](https://github.com/lipp/tango/tree/master/tango/dispatch.lua) routine for servers\n* several server implementations for different protocols, message formats and event/io\nframeworks, further called backends\n* several client implementations for different protocols and message formats\n\n\nBackends included\n---------------------\n\n* copas  \n* [lua-zmq](https://github.com/Neopallium/lua-zmq)\n* [lua-ev](https://github.com/brimworks/lua-ev)\n\nTutorial (copas_socket server +  socket client)\n============================\n\nGreetings!\n----------\n\nThe greet server code \n\n```lua\n-- load tango module\nlocal tango = require'tango'\n-- define a nice greeting function\ngreet = function(...)\n          print(...)\n        end \n-- start listening for client connections        \ntango.server.copas_socket.loop{\n  port = 12345\n}\n```\n\nThe client code calling the remote server function `greet`\n      \n```lua\n-- load tango module\nlocal tango = require'tango'\n-- connect to server\nlocal con = tango.client.socket.connect{\n   address = 'localhost',\n   port = 12345\n}\n-- call the remote greeting function\ncon.greet('Hello','Horst')\n```\n\nAccess anything?\n----------------\n\nSince the server exposes the global table `_G` per default, the client may even\ndirectly call `print`,let the server sleep a bit remotely\n(`os.execute`) or calc some stuff (`math.sqrt`).\n\n```lua\n-- variable argument count is supported\ncon.print('I','call','print','myself')\n-- any function or variable in the server's _G can be accessed by default        \ncon.os.execute('sleep 1')\ncon.math.sqrt(4)\n```\n\nOne can limit the server exposed functions by specifying a `functab`\nlike this (to expose only methods of he math table/module):\n\n```lua\nlocal tango = require'tango'\n-- just pass a table to the functab to limit the access to this table\ntango.server.copas_socket.loop{\n  port = 12345,\n  functab = math\n}\n```\n\nAs the global table `_G` is not available any more, the client can\nonly call methods from the math module:\n\n```lua\ncon.sqrt(4)\n```\n\nRemote Variables\n-----------------\n\nSometimes you need to get some data from the server, as\nenumaration-like-constants for instance. Instead of creating a mess of\nremote getters and setters, just treat the value of interest as a\nfunction...\n\nLet's read the remote table friends from the server\n\n```lua\nlocal tango = require'tango'\n-- connect to server as usual\nlocal con = tango.client.socket.connect()\n-- friends is a remote table but could be of any other type\nlocal friends = con.friends()\n```\n\nTo change the servers state, just pass the new value as\nargument:\n\n```lua\nlocal tango = require'tango'\nlocal con = tango.client.socket.connect()\n-- read the remote variable\nlocal friends = con.friends()\n-- modify it \ntable.insert(friends,'Horst')\n-- and write back the new value\nclient.friends(friends)\n```\n\nIf you are worried about security concerns, just do not allow\nread and/or write access:\n\n```lua\nlocal tango = require'tango'\n-- write_access and read_access can be set independently\n-- accessing variables from the client side will now cause errors.\ntango.server.copas_socket.loop{\n  write_access = false,\n  read_access = false\n}\n```\n\nUsing classes/tables/objects remotely (tango.ref)\n-----------------------------------------\n\nEven if Lua does not come with a class model, semi-object-oriented\nprogramming is broadly used via the semicolon operator, e.g.:\n\n```lua\n-- assume you open a pipe locally\nlocal p = io.popen('ls')\n-- and read some stuff from it, ... note the : operator\nlocal line = p:read('*l')\n...\np:close()\n```\n\nTo allow such construct remotely via tango, one has to use the\n`tango.ref`:\n\n```lua\nlocal con = tango.client.socket.connect()\n-- pass in the remote function and all arguments required (optionally)\nlocal p = tango.ref(con.io.popen,'ls')\n-- now proceed as if p was a local object\nlocal line = p:read('*l')\n...\np:close()\n-- unref it locally to let the server release it\ntango.unref(p)\n```\n\nThis may seem a bit awkward, but it is certainly less hassle, then\nwriting non-object-oriented counterparts on the server side.\n\n\nTests\n=====\n\nYou can run test by the following sh call in the *project root*\ndirectory:\n\n      ./test.lua\n\ntango does not need to be installed.\n\nClient/Server compatibilities\n-----------------------------\n\n\u003ctable border=\"1\"\u003e               \n        \u003ctr\u003e\n                \u003cth\u003e\u003c/th\u003e\u003cth\u003etango.client.socket\u003c/th\u003e\u003cth\u003etango.client.zmq\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n                \u003cth\u003etango.server.copas_socket\u003c/th\u003e\u003cth\u003eX\u003c/th\u003e\u003cth\u003e\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n                \u003cth\u003etango.server.ev_socket\u003c/th\u003e\u003cth\u003eX\u003c/th\u003e\u003cth\u003e\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n                \u003cth\u003etango.server.zmq\u003c/th\u003e\u003cth\u003e\u003c/th\u003e\u003cth\u003eX\u003c/th\u003e\n        \u003c/tr\u003e\n\u003c/table\u003e\n\n\nSerialization\n-------------\ntango provides a default (lua-only) table serialization which should\nmeet most common use cases.\n\nAnyhow, the table serialization is neither exceedingly fast nor\ncompact in output or memory consumption. If this is a problem for your application, you can\ncustomize the serialization by assigning your serialize/unserialize\nmethods to the clients and servers respectively.\n\nSocket client with customized serialization:\n\n```lua\nlocal tango = require'tango'\nlocal cjson = require'cjson'\n-- set serialization on the client side\nlocal con = tango.client.socket.connect{\n   serialize = cjson.encode,\n   unserialize = cjson.decode\n}\n```\n\nCopas socket server with customized serialization:\n\n```lua\nlocal tango = require'tango'\nlocal cjson = require'cjson'\n-- set serialization on the server side\ntango.server.copas_socket.loop{\n   serialize = cjson.encode,\n   unserialize = cjson.decode\n}\n```\n\nSome alternatives are:\n\n* [lua-marshal](https://github.com/richardhundt/lua-marshal)\n* [lua-cjson](http://www.kyne.com.au/~mark/software/lua-cjson.php)\n* [luabins](https://github.com/agladysh/luabins)\n* [luatexts](https://github.com/agladysh/luatexts)\n\nRequirements\n------------\n\nThe requirements depend on the desired i/o backend, see the\ncorresponding [rockspecs](https://github.com/lipp/tango/tree/master/rockspecs) for details.\n\n\nInstallation\n-------------\nWith LuaRocks:\nDirectly from the its repository:\n\n     $ sudo luarocks install tango-copas\n    \nor tango-complete, which requires lua-zmq and lua-ev (and the\ncorresponding C-libs:\n\n     $ sudo luarocks install tango-complete\n\nor a specific rock from \n\n     $ sudo luarocks install https://raw.github.com/lipp/tango/master/rockspecs/SPECIFIC_ROCKSPEC\n\nNote: [luarocks](http://www.luarocks.org) must be \u003e= 2.0.4.1 and requires luasec for doing https requests!\n\n     $ sudo apt-get install libssl-dev\n     $ sudo luarocks install luasec\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flipp%2Ftango","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flipp%2Ftango","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flipp%2Ftango/lists"}