[ANN] BitStruct

Discussion in 'Ruby' started by Joel VanderWerf, Oct 10, 2005.

  1. (Exerpt from the docs at the project page,
    http://redshift.sourceforge.net/bit-struct/.)

    = BitStruct

    Class for packed binary data stored in ruby Strings. BitStruct
    accessors, generated from user declared fields, use pack/unpack to treat
    substrings as fields with a specified portable format.

    Field types include

    * signed and unsigned integer (1..8 bits, or 16 or 32 bits)

    * fixed point, with arbitrary scale factor

    * fixed length character array

    * null-terminated character array for printable text

    * octets (hex and decimal representation options; useful for IP and MAC
    addrs)

    * float

    * nested BitStruct

    * free-form "rest" field (e.g., for the variable-size payload of a packet)

    == Uses

    BitStruct is useful for defining packets used in network protocols. This
    is especially useful for raw IP--see examples/ping-recv.rb. All
    multibyte numeric fields are stored in network order (though this could
    be different for user-defined field classes).

    BitStruct is most efficient when your data is primarily treated as a
    binary string, and only secondarily treated as a data structure. (For
    instance, you are routing packets from one socket to another, possibly
    looking at one or two fields as it passes through or munging some
    headers.) If accessor operations are a bottleneck, a better approach is
    to define a class that wraps an array and uses pack/unpack when the
    object needs to behave like a binary string.

    == Example

    An IP packet can be defined and used like this:

    require 'bit-struct'

    class IP < BitStruct
    unsigned :ip_v, 4, "Version"
    unsigned :ip_hl, 4, "Header length"
    unsigned :ip_tos, 8, "TOS"
    unsigned :ip_len, 16, "Length"
    unsigned :ip_id, 16, "ID"
    unsigned :ip_off, 16, "Frag offset"
    unsigned :ip_ttl, 8, "TTL"
    unsigned :ip_p, 8, "Protocol"
    unsigned :ip_sum, 16, "Checksum"
    octets :ip_src, 32, "Source addr"
    octets :ip_dst, 32, "Dest addr"
    rest :body, "Body of message"

    note " rest is application defined message body"

    initial_value.ip_v = 4
    initial_value.ip_hl = 5
    end

    ip = IP.new
    ip.ip_tos = 0
    ip.ip_len = 0
    ip.ip_id = 0
    ip.ip_off = 0
    ip.ip_ttl = 255
    ip.ip_p = 255
    ip.ip_sum = 0
    ip.ip_src = "192.168.1.4"
    ip.ip_dst = "192.168.1.255"
    ip.body = "This is the payload text."
    ip.ip_len = ip.length

    puts ip.inspect
    puts "-"*50
    puts ip.inspect_detailed
    puts "-"*50
    puts ip.body
    puts "-"*50
    puts IP.describe

    (Note that you can also construct an IP packet by passing a string to
    new, or by passing a hash of <tt>field,value</tt> pairs, or by providing
    a block that is yielded the new BitStruct.)

    The output of this fragment is:

    #<IP ip_v=4, ip_hl=5, ip_tos=0, ip_len=45, ip_id=0, ip_off=0,
    ip_ttl=255, ip_p=255, ip_sum=0, ip_src="192.168.1.4",
    ip_dst="192.168.1.255">
    --------------------------------------------------
    IP:
    Version = 4
    Header length = 5
    TOS = 0
    Length = 45
    ID = 0
    Frag offset = 0
    TTL = 255
    Protocol = 255
    Checksum = 0
    Source addr = "192.168.1.4"
    Dest addr = "192.168.1.255"
    --------------------------------------------------
    This is the payload text.
    --------------------------------------------------

    Description of IP Packet:
    byte: type name [size] description
    ----------------------------------------------------------------------
    @0: unsigned ip_v [ 4b] Version
    @0: unsigned ip_hl [ 4b] Header length
    @1: unsigned ip_tos [ 8b] TOS
    @2: unsigned ip_len [ 16b] Length
    @4: unsigned ip_id [ 16b] ID
    @6: unsigned ip_off [ 16b] Frag offset
    @8: unsigned ip_ttl [ 8b] TTL
    @9: unsigned ip_p [ 8b] Protocol
    @10: unsigned ip_sum [ 16b] Checksum
    @12: octets ip_src [ 32b] Source addr
    @16: octets ip_dst [ 32b] Dest addr
    rest is application defined message body

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Oct 10, 2005
    #1
    1. Advertising

  2. Someone asked offline about block-based initialization, and BitStruct
    supports that, as well as hash-based and string-based. Here are the
    variants:

    ip1 = IP.new
    ip1.ip_tos = 0
    ip1.ip_len = 0
    ip1.ip_id = 0
    ip1.ip_off = 0
    ip1.ip_ttl = 255
    ip1.ip_p = 255
    ip1.ip_sum = 0
    ip1.ip_src = "192.168.1.4"
    ip1.ip_dst = "192.168.1.255"
    ip1.body = "This is the payload text."
    ip1.ip_len = ip1.length

    ip2 = IP.new do |ip|
    ip.ip_tos = 0
    ip.ip_len = 0
    ip.ip_id = 0
    ip.ip_off = 0
    ip.ip_ttl = 255
    ip.ip_p = 255
    ip.ip_sum = 0
    ip.ip_src = "192.168.1.4"
    ip.ip_dst = "192.168.1.255"
    ip.body = "This is the payload text."
    ip.ip_len = ip.length
    end

    ip3 = IP.new(
    :ip_tos => 0,
    :ip_len => 0,
    :ip_id => 0,
    :ip_off => 0,
    :ip_ttl => 255,
    :ip_p => 255,
    :ip_sum => 0,
    :ip_src => "192.168.1.4",
    :ip_dst => "192.168.1.255",
    :body => "This is the payload text."
    ) do |ip|
    ip.ip_len = ip.length
    end

    ip4 = IP.new(ip1) # Construct from a BitStruct (or String)

    Btw, if you've ever wanted to write ping in ruby, check out ping-recv.rb
    in the example dir.

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Oct 10, 2005
    #2
    1. Advertising

  3. Joel VanderWerf

    Morgan Guest

    [I really wish I knew how to make eudora do attribution lines automatically...]

    Joel VanderWerf wrote:

    >(Exerpt from the docs at the project page,
    >http://redshift.sourceforge.net/bit-struct/.)
    >
    >= BitStruct



    Looks pretty interesting. I do have one question though.

    I've got a project I've been thinking about doing a project that would
    benefit from the use of arrays of two-bit unsigned integers, of
    unknown-at-time-of-coding but probably large size. Which will also
    need to be shoved across sockets occaisionally. Is there a convenient
    way to make a structure like this using BitStruct?

    -Morgan.

    "Ginger ale. And leave the bottle."




    --
    No virus found in this outgoing message.
    Checked by AVG Anti-Virus.
    Version: 7.0.344 / Virus Database: 267.12.1/136 - Release Date: 10/15/2005
     
    Morgan, Oct 17, 2005
    #3
  4. Morgan wrote:
    > [I really wish I knew how to make eudora do attribution lines
    > automatically...]
    >
    > Joel VanderWerf wrote:
    >
    >> (Exerpt from the docs at the project page,
    >> http://redshift.sourceforge.net/bit-struct/.)
    >>
    >> = BitStruct

    >
    >
    >
    > Looks pretty interesting. I do have one question though.
    >
    > I've got a project I've been thinking about doing a project that would
    > benefit from the use of arrays of two-bit unsigned integers, of
    > unknown-at-time-of-coding but probably large size. Which will also
    > need to be shoved across sockets occaisionally. Is there a convenient
    > way to make a structure like this using BitStruct?


    Not yet. I haven't needed variable sized arrays of anything except
    chars. For now, if you want to get something working quickly, you're
    probably better off with String#[] (i.e. slice) and some bit arithmetic
    (which is just what BitStruct does anyway). Or use a C extension. (You
    can take a look at unsigned-field.rb for how to set up masks and so on,
    but it's nothing special.)

    Maybe someone else can pipe up if there is a way to do this with Ruby/DL
    or something else?

    It would be great if ruby had a built-in method (or a standard lib
    extension) for doing bit-wise slice operations (and other bit-oriented
    string operations)...

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Oct 18, 2005
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mike Sampson [MSFT]

    [ANN]: NNTP Server slow downs.

    Mike Sampson [MSFT], Oct 7, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    421
    Mike Sampson [MSFT]
    Oct 7, 2003
  2. Mike Sampson [MSFT]

    [ANN]: NNTP Server slow downs.

    Mike Sampson [MSFT], Dec 6, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    508
    Mike Sampson [MSFT]
    Dec 6, 2003
  3. Michael Livsey
    Replies:
    3
    Views:
    436
    Michael Livsey
    May 27, 2004
  4. Chuck Remes

    BitStruct technique

    Chuck Remes, May 14, 2009, in forum: Ruby
    Replies:
    3
    Views:
    150
    Chuck Remes
    May 16, 2009
  5. Jaikanth Krishnaswamy

    BitStruct-28bit-Ruby Beginner

    Jaikanth Krishnaswamy, Nov 22, 2010, in forum: Ruby
    Replies:
    3
    Views:
    218
    Michael Bruschkewitz
    Dec 2, 2010
Loading...

Share This Page