Skip to content

The Ruckus Object Model

tqbf edited this page Sep 13, 2010 · 8 revisions

Beware things with object models, but having said that:

Ruckus::Parsel

Everything in a Ruckus packet is a kind of Ruckus::Parsel. Ruckus::Parsel bears the same relationship to a packet that a DOM node bears to a web page loaded in a browser.

Yes, “Parsel” is a silly name.

All Parsels have a couple basic methods:

  • Parsel#out (unfortunately, a.k.a. Parsel#to_s) marshals them into strings so you can blit them onto the network.
  • Parsel#in (a.k.a. Parsel#capture) reads the contents of a string into a Parsel, returning the remainder of the string
  • Parsel#visit allows you to traverse all the descendant nodes of a Parsel (usually a Structure).
  • Parsel#each_matching_selector yields each Parsel in a packet matching a CSS-style selector.

Different kinds of Parsels have different properties. For instance, integers have an :endian property. Strings have a :unicode property. Properties are exposed as instance attributes.

Every Parsel has a &#58value property, which is how you set and read the actual value of the object. The “value” of Number for instance is going to be a basic Ruby Numeric object you can do math on.

Ruckus::Number

Most things in packets are numbers of some form. Ruckus tries to represent all of them. There’s two ways to slice them up: by properties and by subclasses. First, the various Ruckus::Number properties:

  • :width – How many bits wide is the number? Ruckus can handle whatever. A flag in packet is best modeled in Ruckus as a 1-bit-wide number. 17-bit-wide numbers work fine. So do 100 bit numbers.
  • :endian – Either :big (MIPS, Internet) or :little (Microsoft, X86) - a.k.a. :ass_backwards.
  • :ascii – True or false: is this a binary number or a text number?
  • :radix – If it’s a text number, is it decimal (10, the default), hex (16), or something funkier?

Mix and match, collect all four, or try one of these great flavor combos:

  • Le8, Le16, Le32 – or H16 (and so on), Uint16Le (and so on). For no good reason, “Half” and “Halfword” are synonyms for Le16 – little endian integers.
  • Be8, Be16 – or N8, N16 – or Uint16Be – or “Short” (16 bits) and “Long” (32 bits) – big-endian integers.
  • Byte is an 8 bit number.
  • Bit is a 1 bit number.
  • Nybble is a 4 bit number.
  • Decimal is a 32 bit (by default) decimal text number.

Ruckus::Str

When things in packets aren’t numbers, they’re strings. Also, when you don’t know what the format of something inside a packet you’re reverse-engineering is, it’s just a string.

So that our names don’t collide with Ruby’s when we import the whole Ruckus namespace for convience, strings are Ruckus::Str objects. Ruckus::Str objects are, of course, Parsel descendants. Like Numbers, they have properties:

  • :size – What is the absolute size of this string? If you set the size of a Str to 10, and the value to “foo”, it will be padded when you render it.
  • :min – What’s the minimum size of the string?
  • :max – What’s the maximum size of the string?
  • :padding – If the string is padded, what should the padding character be? By default, it’s \x00.
  • :pad_to – To what alignment should this string be padded?
  • :unicode – Is the string UTF-16-LE Unicode formatted? (We use “Unicode” the way Microsoft does).
  • :nul_terminated – Does the string always have a NUL byte at the end?

Ruckus::Blob

When things aren’t simply a string or a number, they’re somehow a combination of strings and/or numbers. A Ruckus::Blob is a heterogenous array of Parsels.

When a Ruckus::Blob is rendered with Blob#out, it creates an output string containing the renderings of each of its members, in order. A Ruckus::Blob populated with template Parsels can used with Blob#in to parse a collection of different types, in order.

Obviously, Blobs can contain other Blobs. Blob doesn’t care. Nested Blobs implement tree traversal, like a DOM tree.

Ruckus::Structure

Most of the time, when a protocol frame is really a bag of numbers and strings in a particular order, you don’t simply want to put them in a bag; you want named access to each of the fields. Ruckus::Structure is a layer over Ruckus::Blob that gives structure-style named access to each element (now “field”) of a blob.

Structures are most of what you do with Ruckus; they’re described here.

Clone this wiki locally