About Legs

This is Legs, the little networking doodad somewhat inspired by Camping but not all that much really. It uses a lot of ruby trickery to give you one class, Legs, which can act as a server, a client, or a peer depending on how you use it. Oh, and the protocol it uses is JSON-RPC 1.0, so quite platform and language agnostic. :)

If you give Legs some methods, then anyone you connect to will be able to make calls back to those methods to notify you of things. Otherwise, your instance of legs will only be able to connect out to a legs server and call methods in that server, but not the other way around. If that’s all you need, learning Camping and using http might be a better way to go, as http is a more popular and more standard protocol. :)

To connect to a Legs server running on your own computer

server = Legs.new
 - OR -
server = Legs.new('localhost')

To connect to a remote server

server = Legs.new('web.address.to.server')

To connect to a server on port 1234

server = Legs.new('web.address', 1234)

To create a legs server

Legs.start do
  def callable_method(a, b, c = 'default')
    return "You called with params #{a}, #{b}, and #{c}"
  end
end

sleep # Stops ruby from closing as soon as Legs starts.
# don't put sleep if you're embedding the server in a shoes UI or something.

To add methods to legs, without creating a server

Legs.start(false) do
  def callable_method(a, b, c = 'default')
    return "You called with params #{a}, #{b}, and #{c}"
  end
end

You should do this before creating instances of Legs with Legs.new. Adding methods like this is useful, because the “TCP” network connections Legs makes work in both directions, so if you have some methods, server’s you connect to will be able to call your methods to notify you of events and stuff. If you don’t give it false on that first line, it will start up a server as well, so other instances of Legs can connect in to you, deliciously peery. It’s important to know, though, that the Legs.users only includes connections who connected to you, not outgoing connections you make with Legs.new syntax. You could make your own array of outgoing connections to keep track ot them if you want. :)

Inside of your Legs.start block, there are two magic methods you can use in your code, these are server and caller. server references the Legs server object, which has methods like users and some other stuff you can use to your advantage. The caller method gives you the Legs instance representing that network connection (doesn’t matter if they connected to you or vice versa).

Legs instances, like the one you get from caller, and the array of them you get from server.users have a useful method called meta which gives you a hash you can store whatever you like inside of. Things you might put in there include the user’s name, or if they have any special powers, so you can control which methods they can use and what they can do. Here’s an example: :)

Legs.start do
  def count
    caller.meta[:counter] ||= 0
    caller.meta[:counter] += 1
  end
end

sleep

When you connect to this server, you can call the count method. Each time you call it, it will give you a number, starting with 1 and growing higher each time. Because it stores the ‘counter’ in the caller’s meta hash, if another person connects, they will start out with the number 1 as well. You could connect to this with :)

server = Legs.new('localhost')
puts "#{server.count}, #{server.count}, #{server.count}"

And if you run that script, you should see in your terminal: “1, 2, 3”. That’s pretty much how Legs works. An instance of legs has a few of it’s own special methods: close!, notify!, send!, send_async!, connected?, socket, parent, meta, and send_data!. If you need to actually run a method on your server with one of these names, do: server.send!(:connected?, a_param, another_param) or whatever, and it’ll run that method on the server for you. If you want to let the server know something, but don’t care about the method’s response, or any errors, you can do the same thing with legs.notify!, which will make your program run faster, especially if it’s running through the web. :)

Finally, if you’re making a program for running over the internet, and want to make your app more responsive, you can call methods asyncronously. What this means is that the method won’t return immidiately, but instead will send the request out to your network, and your program will continue to run, and then when the server responds, a block you provide will be run. The block is passed an object, call that object’s result or value method to get the server response, or it will raise an error if the server had an error, so you can use it as though it were a syncronous response. Error is only raised the first time you call it. To do this, just give the thing a block like this: server.some_method { |result| ... do stuff with result.value ... }.