UPnP – Ruby Wrapper

[EDIT:This has been released as gem. check the code page]

[Continues: UPnP Integration]

After some testing i wrote an UPnP class to wrap the UPNP library for a more friendly and usable interface.
The wrapper class can be found on the same code repository.

I have added a nice feature too, adding the discovery of UPnP devices as a thread on object creation, to let it probe the network without bothering the class user. But this lead me into troubles… the thread that was going to probe the network made ruby wait until it is completed, even if it has to wait on a socket… digging for the threading implementation of ruby i finally got where the problem was.
Ruby uses green thread, cooperative user threads… that was the problem.. every thread has to tell which other thread is the next. But what happens if it remains blocked on a system call? it simply makes the whole ruby machine to wait … fortunately ruby 2.0 should solve this problem, requiring that the threads must be operative system threads.

 

The Initializer allows you to choose how much time should the implementation wait for an UPnP answer from the network, and if the network probing thread must be launched. Remember that the object must be initialized with a discoverIGD call, except if you let the thread start.
Initialization functions

  • initialize(max_wait=1000,autodiscover=true)
  • discoverIGD()

IP functions

  • getLanIP()
  • getRouterIP()
  • getExternalIP()

Router info

  • getStatusInfo()
  • getConnectionTypeInfo()

Traffic info

  • getTotalBytesSent()
  • getTotalBytesReceived()
  • getTotalPacketsSent()
  • getTotalPacketsReceived()
  • getMaxLinkBitrates()

Mappings

  • getPortMappings()
  • getPortMapping(nport,proto)
  • addPortMapping(nport,lport,client,desc,proto)
  • deletePortMapping(nport,proto)

The port numbers may be passed as integer or string, and they are always returned as integer (lib miniupnp works only with strings). All the errors are managed through exceptions.
In fact there is a nice thing about ruby threading, the exceptions that occour in a thread are received by the thread that calls join on the thread. Due to this, the first method you’ll call (except for your ip and router ip functions), if the autosearch feature is enabled, will return the exception, if any, from the detect thread.
Uh, i was just about to forget this. nport is the net port, and lport is the lan port.
This is a simple example that will print each mapping in the router. The call to getPortMappings will wait until the discover thread has finished searching a router.

require 'upnp'
u = UPNP.new()
u.getPortMappings.each {|m| puts m.to_s}

 

 [EDIT:This has been released as gem. check the code page]

Advertisements

, ,

  1. #1 by roger ruby gems rdocs on July 21, 2009 - 8:39 pm

    Nice! I had thought of writing upnp code by hand but wrapping a C library is even easier :)
    =r

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: