Wednesday, August 6, 2008

SL-aware server prototype in ruby...

It's no big doubt that Ruby is a high-level language. Probably opensim svn still has my stupid ruby scripts which pretend to do something with the protocol - in effect just being more or less compact "plugs" for testing.

One of these evenings I did not feel like doing anything productive, so I decided to hack up a prototype packetserver in ruby.

So, the below set of files allows me to "login" (in quotes because the login info is not really checked :) with the viewer.

$ ls -al
total 228
drwxr-xr-x 2 dalien dalien 4096 Aug 6 04:46 .
drwxr-xr-x 12 dalien dalien 4096 Jul 31 22:23 ..
-rw-r--r-- 1 dalien dalien 183208 Jul 28 17:44
-rwxr-xr-x 1 dalien dalien 8629 Jul 28 17:36 login_server.rb
-rwxr-xr-x 1 dalien dalien 14901 Jul 29 04:27 parse_template.rb
-rw-r--r-- 1 dalien dalien 3710 Jul 31 22:27 pkt_server.rb
-rw-r--r-- 1 dalien dalien 1719 Jul 28 21:59 str_hex.rb

The main cleverness is in parse_template.rb, which sucks in the being the message template, and generates a bunch of classes, courtesy of Ruby being an interpreted language, something like this:

t =""); { |x| SLMessage.register_message(x, eval(x.to_ruby)) }

So, this defines a bunch of classes with the exact same names as the messages in the message templates, and allows to write a message handler in a nice and conscise way as a class method for a "client handler" class:

def message(msg)
send_packet_ack(@client_ip, @client_port, msg.sequence)
handler = (msg.class.to_s + "_handler")
if self.respond_to? handler
send(handler, msg)
pp msg

And, as soon as I define a "_handler" method within that class, it gets automagically hooked up! Cool, huh ?
For example, something like this:

def MoneyBalanceRequest_handler(msg)
pkt =
md = pkt.MoneyData[0]
md.AgentID = msg.AgentData[0].AgentID
md.TransactionID = msg.MoneyData[0].TransactionID
md.TransactionSuccess = 1;
md.Description = "Test\00"
md.MoneyBalance = 1234;


where "send_to_client" is again dead simple:

def send_to_client(pkt)
@sock.send(pkt.to_bytes, 0, @client_ip, @client_port)

Oh, and you'll probably be amused with this totally stupid-looking message loop:

def run
print "Started server...\n"
loop {
data, from = @sock.recvfrom(8192)
port = from[1]
host = from[2]
rdr =
msg = SLMessage.from_bytes(rdr)
if msg.class == UseCircuitCode
print "New client connection!\n"
@clients[host.to_s + ":" + port.to_s] =, msg, host, port)
clt = @clients[host.to_s + ":" + port.to_s]
if clt
print "Unknown client:\n";
pp msg

Of course, the CPU usage of all this horrific mess is terrible - given that even the simple members like U32 are objects in themselves, but it's fun nonetheless.

The interesting thing that parse message template + generate the code + dynamically evaluating it (creating message classes) takes around2 seconds - which I think is not too bad.

There is one downside however, the debugging of the autogenerated code is a pain. I need to so how to do it better.

Oh yes, and get rid of the braces in the loop {} construct, they do look ugly and out of place.

Dalien landless, no more sales for primskirtbuilder from me (for now, at least).

heh. appears I'm (finally) out of land where the thing was being sold. Hence, not selling the primskirtbuilder anymore.

The copies should be around, and if you apply a certain effort, you might find a free copy.

The exercise did teach me an interesting lesson - apparently the value of "free" is not really understood nor appreciated, and if you put a decent price tag, people seem to be MORE willing to get it.

The never ending wonders of the human soul... Oh well, they wrote exactly that in the MBA book. It's good to confirm the theory by practice.

Sunday, August 3, 2008

Videos in HD

Videos in HD - and quite a lot of interesting ones. Probably good thing that HD has not hit the masses too much yet...


The glove from Bewegtbildarbeiter on Vimeo.