Question

I am using ruby 2.0.0p451 (2014-02-24) [x64-mingw32] and I came across something that previously worked in the 1.9.x version which does not work here. I was wondering if they changed the behavior, or if I am doing something wrong, or if this is a bug.

I am sending a byte down a socket \xFF and I receive it on the other end, but when I try to compare it to itself (which should return true) it does not return the expected output.

Example, I send the string \xFF\x50\x00username\x00555\x00 and I receive it fine on the other end, but when i try to compare the first byte it to itself the conditional behaves wrongly.

Here is some code samples so you can see how I am handling the data (skimmed to relevant code)

class PacketReceiver
  def setpacket( buffer ); @buffer = buffer; end
  def getbyte
    byte = @buffer[0..0]
    @buffer = @buffer[1..-1]
    byte
  end
end

  def parsepacket(packet)
    #@receiver = PacketReceiver.new #defined elsewhere in code
    @receiver.setpacket packet

    return false unless @reciever.getbyte.eql? "\xFF" #the bugged line

    #Everything works beyond this point
    packet_id = @reciever.getbyte 

    case packet_id
      when "\x50"
        return sid_requesting_config
      when "\x51"
        sid_requesting_data_response
      when "\x52"
        sid_keep_alive_response
      else
        puts "failed"
        return false
    end
    return true
  end

In 1.9.X This unless statement was working fine. When debugging the data, the returned data from @receiver.getbyte is indeed "\xFF", but for some reason the eql? comparison is returning false instead of true causing the function to return false. If i remove this byte from the message and remove the check the rest of the code also calling the getbyte method works fine.

Also if I change the byte to "\x55" rather than "\xFF" the conditional unless statement works as it should.

I am not sure what is going on. Is \xFF reserved for something?

Was it helpful?

Solution

I'm guessing that buffer is binary encoded (i.e. buffer.encoding is ASCII-8BIT). That means that this is happening:

c  = @receiver.getbyte # c also has binary encoding
ff = "\xff"            # ff is probably UTF-8
c.eql? ff              # comparing strings in different encodings gives you `false`

Instead, you should be doing simple numeric comparisons:

@receiver.getbyte.getbyte(0) == 255

Or even better, modify getbyte to return an integer.

I think your 1.9.X version was working mostly by accident, you should have been using a simple numeric comparison all along.

Keep in mind that you have bytes in your buffer (such as 0xFF and 0x00) that are not valid in UTF-8 strings so you should keep your buffer in binary. You can use force_encoding on slices of the buffer for the parts that are UTF-8 strings. You might want to look at String#unpack as well.


Note that I'm linking to the Ruby 2.0.0 specific docs to match the Ruby version you're currently using.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top