rubygems-isit19 1.0

Eric Hodel | Thu, 20 Aug 2009 05:26:00 GMT

Lets you figure out if your gems and gems you install might work on 1.9. Uses isitruby19.com as its datastore. Be sure to update the website with your experiences!

Features

  • gem isit19 for checking your installed gems
  • gem install plugin that tells you if your installed gem works on 1.9

Synopsis

$ gem install ZenTest

ZenTest 4.1.4 might work, 100% say 4.1.3 works on 1.9
Update http://isitruby19.com/ZenTest with your experiences!

Successfully installed ZenTest-4.1.4
1 gem installed

Posted in ,  | no comments

Service Discovery Protocols

Eric Hodel | Wed, 19 Aug 2009 21:42:03 GMT

I’ve worked on two different service discovery libraries for ruby, one for SSPD and one for mDNS, and I’d like to share the differences between them with you.

Both SSDP and mDNS are designed to be used with self-configuring networks and to automatically discover and connect to other devices. Both use multicast to advertise and search.

SSPD

The Simple Service Discovery Protocol is used primarily by UPnP for network devices to discover each other. UPnP is designed for consumer electronics and appliances that need to communicate with each other automatically.

The description of SSPD fits on a twelve of pages when written in (relatively) plain English (section 1 in the UPNP Device Architecture). The protocol itself looks much like HTTP and can be implemented largely using simple text processing. (Strangely, SOAP is the higher-level communication layer for UPnP.)

Unfortunately there’s no way for multiple devices to share the same SSPD socket without being designed to work with each other. Since UPnP is focused on simple devices, this fits well with their design goals. Most UPnP devices are routers, media servers, game consoles, televisions, etc. If you built your own router and media server on the same host it will probably be impossible for both devices to show up on the network, nor will you be able to run a media server and media viewer on the same host without the two being designed to work with each other.

mDNS

Multicast DNS is used primarily by Apple and (basically) has a DNS server on each host. Hosts speak the DNS protocol to each other over multicast and have a central daemon that handles communication on the network much like the libc DNS resolver.

Even though there’s plenty of DNS clients around for code reuse, implementing a DNS client form scratch is a large undertaking (my SSDP implementation is around 750 lines with documentation, ruby’s Resolv DNS resolver is around 2200 lines and doesn’t include a server or multicast code). The entirety of the DNS system is spread across several RFCs, not including the documentation for mDNS itself.

Fortunately mDNS libraries provide a daemon for handling network communication and a client library you can use to register and browse for devices (the dnssd gem uses Apple’s DNS Service Discovery API). mDNS is focused on computers rather than devices, so multiple services can all coexist on the same host.

Unfortunately, due to the complexity of mDNS, there’s no single API for applications to use. Apple’s DNS-SD works across multiple platforms including windows. For unix-like operating systems there is also avahi which has a limited dnssd compatibility shim.

Posted in  | no comments

dnssd 1.3

Eric Hodel | Wed, 19 Aug 2009 04:31:00 GMT

DNS Service Discovery (aka Bonjour, MDNS) API for Ruby. Implements browsing, resolving, registration and domain enumeration. Supports avahi’s DNSSD compatibility layer for avahi 0.6.25 or newer.

Changes

  • 4 major enhancements
    • Added DNSSD::Service.get_property
    • Added DNSSD::Service#getaddrinfo
    • Added DNSSD::Service#add_record
    • Added DNSSD::Service#query_record
  • 5 minor enhancements
    • DNSSD::Reply#connect now uses DNSSD::Service#getaddrinfo (faster)
    • DNSSD::Service#register behaves properly when blockless
    • Broke up DNSSD::Reply into specific subclasses
    • Added sample/query_record.rb
    • sample/*.rb work with each other now for clarity of implementation
  • 2 bug fixes
    • Fix hierarchical domains like \.mac\.name.members.mac.com.
    • Fix compilation against avahi 0.6.25

Posted in ,  | no comments

On Ruby C Extensions

Eric Hodel | Tue, 18 Aug 2009 02:07:40 GMT

I’m not a great C coder, but I have implemented, cleaned up and read a few C extensions for Ruby and I’ve got some tips for writing C extensions

C is Bad

The C itself is your biggest enemy when writing C extensions. The more you write the harder it is for you to maintain and the harder it will be for anyone else to improve or fix your code in the future. The closer your C extension code is to the library’s API the better you can use Ruby to glue all the pieces together into a friendly interface.

Ruby is Good

With less C code and more Ruby code you end up a library that’s easier to refactor, adapt and extend. Generic data manipulation, simple math, convenience functions, etc. are all easier to write, test and debug when written in Ruby. There’s no need to recompile between changes, worry about compiler warnings, or fix type errors.

If you’re returning results from an operation, do as much of the work in Ruby as possible. If there are objects that can be created in Ruby create them in Ruby. If you get a struct sockaddr, unpack it on the Ruby side rather than calling the Socket methods from C using rb_funcall. If you’ve got an abstract representation of a flag bitfield, create the object on the Ruby side rather than calling rb_class_new_instance.

Check for what you need

mkmf.rb has loads of functions (dir_config, have_library, have_macro, have_func, have_type, have_struct_member, etc.) for determining whether or not you have everything you need to build your extension. When using these functions be sure to check the result and fail when what you need is missing.

Keep Up-to-date on the Ruby/C API

There’s tons of functions and macros for doing most of you need already built-in to Ruby. README.EXT has the overview, but there’s also ruby.h and intern.h which give you a list of functions you can use.

Use the friendly macros RSTRING_LEN, RSTRING_PTR and friends when playing with String, Array, etc. Use rb_define_alloc_func() with Data_Wrap_Struct(). Use RTEST and NIL_P for checking ruby results. Convert numbers with NUM2ULONG or NUM2INT, etc.

Play Nice with Threads

If you’re performing a blocking IO operation use rb_thread_wait_fd, rb_thread_fd_writable, etc. to keep other threads running. rb_thread_wait_for can be used for polling.

Don’t Repeat Yourself

While it is safe to repeatedly call rb_intern() if you have to invoke rb_funcall or rb_iv_set, it’s easier and prettier to use a static variable set from your Init function. Same for looking up classes using rb_path2class() or rb_define_class_under().

C is bad

It’s worth repeating. Writing C code is hard. Refactoring C code is hard. Debugging C code is hard. Do as little as possible in C and you’ll thank yourself down the road.

Posted in  | 2 comments

dnssd 1.2

Eric Hodel | Thu, 13 Aug 2009 05:45:00 GMT

DNS Service Discovery (aka Bonjour, MDNS) API for Ruby. Implements browsing, resolving, registration and domain enumeration.

Changes:

  • 4 major enhancements
    • DNSSD::Service is now directly instantiable
    • DNSSD.announce which registers a server socket you’ve created
    • DNSSD::Reply.connect which connects to a browsed service
    • Fix asynchronous service shutdown crash
  • 8 minor enhancements
    • DNSSD.resolve now optionally accepts a DNSSD::Reply from DNSSD.browse
    • Use rb_thread_wait_fd instead of custom rb_thread_select code
    • DNSSD::Reply#protocol and DNSSD::Reply#service_name
    • Added missing error classes
    • Added missing InterfaceUnicast constant
    • Improved Documentation
    • Use C constants in ext/dnssd/errors.c
    • Reduced C code in ext/dnssd/service.c for greater control. See DNSSD::Service
  • 4 bug fixes
    • Don’t invoke block on callback if none was provided
    • Remove ext/dnssd/dns_sd.h so the correct header is used
    • DNSSD::NoMemoryError is now raised instead of NoMemError
    • DNSSD::ReferenceUsedError is now correctly named DNSSD::RefusedError

Posted in  | no comments

vi bindings for irb on OS X

Eric Hodel | Tue, 11 Aug 2009 20:56:22 GMT

OS X uses editline(3) instead of readline(3) so ~/.inputrc doesn’t do anything for irb or other tools using readline via the editline wrapper.

Instead, use ~/.editrc:

bind -v
bind \\t rl_complete

Which gives you vi bindings in irb.

Update

Now with tab completion thanks to Curt Sampson from an ancient netbsd-users email!

Posted in ,  | no comments

imap_processor 1.3

Eric Hodel | Wed, 05 Aug 2009 02:38:30 GMT

imap_processor documentation

IMAPProcessor is a client for processing messages on an IMAP server. It provides some basic mechanisms for connecting to an IMAP server, determining capabilities and handling messages.

IMAPProcessor ships with the executables imap_keywords which can query an IMAP server for keywords set on messages in mailboxes, imap_idle which can show new messages in a mailbox and imap_archive which will archive old messages to a new mailbox.

Changes

  • IMAP IDLE support now matches ruby trunk’s support. See Net::IMAP#idle and Net::IMAP#idle_done

Posted in ,  | no comments