EventMachine – how to get client’s IP address

I’m using EventMachine in one of my projects. EM is robust library to handle all dirty stuff related to low level network activities.

However it is not very well documented. You can learn a lot from it’s sources, but I’m not (yet :) I hope) so good to crunch such library in 15 minutes in order to get how to accomplish some simple task. I was googling for help few times, and found very little resources. So I will share my fresh knowledge ;)

My server is UDP based, and implements custom network protocol. At some point I needed to get UDP packets source addresses.

Running such UDP server with EventMachine is quite easy:

EventMachine::run {
   EventMachine::open_datagram_socket $conf[:address], 
                                 $conf[:udp_port], CustomServer
}

module CustomServer
   def receive_data d
      pp get_peername[2,6].unpack "nC4"
   end
end

$conf is hash defined somewhere else with configuration data, value for key :address is string with IP address, and for :udp_port integer with port number to listen on.

CustomServer is a module, which EventMachine::open_datagram_socket mixes in EventMachine::Connection class and instantiate. One of methods from this class is receive_data, which is called for every UDP packet received, with packet payload as argument.

To get sockaddr structure from receive_data method, just call get_peername, which will return string with this structure. To extract just source port number and IP address You need take 6 bytes part starting from byte 3 (2 bytes for port number and 4 bytes for IP address, each octet encoded as a single byte). Example output: [50000, 192, 168, 248, 1] – packet came from 192.168.248.1:50000.

And thats it!

If You are interested in using EM, stay tuned and subscribe to my RSS feed if You haven’t done it already.

Writing tests for Ruby/Tk application

Tk allows to place widgets without explicitly specifying root window. It could become problem if You don’t have this window.

I got basic functionality of my application and then I wanted to develop it further more TDD way, since I anticipated some redesigns on the fly. Having then test suite will help me not break old features.

So I wrote simple tests, happily included tk, test/unit and my code library. I needed to calculate some metrics based on relations between widgets. In my tests in setup I was using something like this, which was taken directly from application code:

$widgets[:wg100] = Widget_100.new :text => 'wg100'
$widgets[:wg100].place :x => 10, :y => 10

As You can see I did not set :parent (line 1) which is OK in most cases. I didn’t expect any problems, since I didn’t wanted to run GUI. I just wanted to run some of my code, which needed widgets to have assigned coordinates.

Unfortunately I ran on strange behavior of Tk library – it was throwing strange errors – like NameError: uninitialized constant LineWidget::TkcLine , from places where I would not suspect (from lines where was no reference to TkcLine).

Reason – missing root window. Ruby/Tk does not force You to set explicitly root window, but it is good habit to always use :parent when creating new widgets. This way You will avoid such stupid mistakes – if I recollect correctly it took me an hour to get what was wrong. Learned hard way ;) Working setup was something like:

$root = TkRoot.new(:title=>'TDD & Tk', :height => 768, :width => 1024)

$widgets[:wg100] = Widget_100.new :text => 'wg100', :parent => $root
$widgets[:wg100].place :x => 10, :y => 10

Of course to run my tests, I didn’t fire up GUI (with Tk.mainloop). Just setup widgets, and do Your tests.