www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - string ~ ubyte

reply Bob Cowdery <bob bobcowdery.plus.com> writes:
Hi
I'm implementing a web sockets server as part of the UI for my
application. It's almost working but the connection closes on me just
after the handshake. I'm pretty sure the handshake response I'm sending
is incorrect.

This is the last bit of the code (I've missed ot the bit that creates
the parts as I think that is ok):

        // Create the challenge response
        // The response is formed by a concatenation of
        // part_1 + part_2 + key (where parts are 32 bit integers and
key is 8 bytes)
        // The parts must be in big endian order and the whole forms a
128 bit value
        // The response is then the MD5 hash of this value
        writeln("Creating response");
        auto response = new ubyte[16];
        response[0] = part_1 & 0xFF;
        response[1] = (part_1 >> 8) & 0xFF;
        response[2] = (part_1 >> 16) & 0xFF;
        response[3] = (part_1 >> 24) & 0xFF;
        response[4] = part_2 & 0xFF;
        response[5] = (part_2 >> 8) & 0xFF;
        response[6] = (part_2 >> 16) & 0xFF;
        response[7] = (part_2 >> 24) & 0xFF;
        foreach(i, value; key) {
            response[i+8] = value;
        }

        // Create an MD5 hash of the result.
        ubyte digest[16];
        sum(digest, response);

        // Send the handshake
        writeln("Handshake sending: ", handshake ~ digestToString(digest));
        this.sock.send(handshake ~ digestToString(digest));

The result of running gives me a handshake respose of:

        Creating response
        Handshake sending: HTTP/1.1 101 Web Socket Protocol Handshake
        Upgrade: WebSocket
        Connection: Upgrade
        WebSocket-Origin: http://localhost:9000
        WebSocket-Location: ws://localhost:9999/
        Sec-Websocket-Origin: http://localhost:9000
        Sec-Websocket-Location: ws://localhost:9999/
       
        5C368EF0F874025639911E2BC5F01412

This all looks good except the string at the end (the digest) which has
32 characters whereas I think the client is expecting 16. I'm guessing
the string is created as UTF16. Is there a way to get this to be 16
characters?

bob
Oct 31 2010
parent reply div0 <div0 sourceforge.net> writes:
On 31/10/2010 11:36, Bob Cowdery wrote:
 Hi
 I'm implementing a web sockets server as part of the UI for my
 application. It's almost working but the connection closes on me just
 after the handshake. I'm pretty sure the handshake response I'm sending
 is incorrect.

 This is the last bit of the code (I've missed ot the bit that creates
 the parts as I think that is ok):

          // Create the challenge response
          // The response is formed by a concatenation of
          // part_1 + part_2 + key (where parts are 32 bit integers and
 key is 8 bytes)
          // The parts must be in big endian order and the whole forms a
 128 bit value
          // The response is then the MD5 hash of this value
          writeln("Creating response");
          auto response = new ubyte[16];
          response[0] = part_1&  0xFF;
          response[1] = (part_1>>  8)&  0xFF;
          response[2] = (part_1>>  16)&  0xFF;
          response[3] = (part_1>>  24)&  0xFF;
          response[4] = part_2&  0xFF;
          response[5] = (part_2>>  8)&  0xFF;
          response[6] = (part_2>>  16)&  0xFF;
          response[7] = (part_2>>  24)&  0xFF;
          foreach(i, value; key) {
              response[i+8] = value;
          }

          // Create an MD5 hash of the result.
          ubyte digest[16];
          sum(digest, response);

          // Send the handshake
          writeln("Handshake sending: ", handshake ~ digestToString(digest));
          this.sock.send(handshake ~ digestToString(digest));

 The result of running gives me a handshake respose of:

          Creating response
          Handshake sending: HTTP/1.1 101 Web Socket Protocol Handshake
          Upgrade: WebSocket
          Connection: Upgrade
          WebSocket-Origin: http://localhost:9000
          WebSocket-Location: ws://localhost:9999/
          Sec-Websocket-Origin: http://localhost:9000
          Sec-Websocket-Location: ws://localhost:9999/

          5C368EF0F874025639911E2BC5F01412

 This all looks good except the string at the end (the digest) which has
 32 characters whereas I think the client is expecting 16. I'm guessing
 the string is created as UTF16. Is there a way to get this to be 16
 characters?

 bob
If the client is expecting 16 bytes, then it wants the response in binary. You're converting it to hex text which is why you've got twice as many characters as you are expecting. just remove the digestToString bit and send the raw ubyte array. You may or may not need to reverse the md5 as well. Not sure if Endianess applies to a md5. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Oct 31 2010
parent Bob Cowdery <bob bobcowdery.plus.com> writes:
On 31/10/2010 13:13, div0 wrote:
 On 31/10/2010 11:36, Bob Cowdery wrote:
 Hi
 I'm implementing a web sockets server as part of the UI for my
 application. It's almost working but the connection closes on me just
 after the handshake. I'm pretty sure the handshake response I'm sending
 is incorrect.

 This is the last bit of the code (I've missed ot the bit that creates
 the parts as I think that is ok):

          // Create the challenge response
          // The response is formed by a concatenation of
          // part_1 + part_2 + key (where parts are 32 bit integers and
 key is 8 bytes)
          // The parts must be in big endian order and the whole forms a
 128 bit value
          // The response is then the MD5 hash of this value
          writeln("Creating response");
          auto response = new ubyte[16];
          response[0] = part_1&  0xFF;
          response[1] = (part_1>>  8)&  0xFF;
          response[2] = (part_1>>  16)&  0xFF;
          response[3] = (part_1>>  24)&  0xFF;
          response[4] = part_2&  0xFF;
          response[5] = (part_2>>  8)&  0xFF;
          response[6] = (part_2>>  16)&  0xFF;
          response[7] = (part_2>>  24)&  0xFF;
          foreach(i, value; key) {
              response[i+8] = value;
          }

          // Create an MD5 hash of the result.
          ubyte digest[16];
          sum(digest, response);

          // Send the handshake
          writeln("Handshake sending: ", handshake ~
 digestToString(digest));
          this.sock.send(handshake ~ digestToString(digest));

 The result of running gives me a handshake respose of:

          Creating response
          Handshake sending: HTTP/1.1 101 Web Socket Protocol Handshake
          Upgrade: WebSocket
          Connection: Upgrade
          WebSocket-Origin: http://localhost:9000
          WebSocket-Location: ws://localhost:9999/
          Sec-Websocket-Origin: http://localhost:9000
          Sec-Websocket-Location: ws://localhost:9999/

          5C368EF0F874025639911E2BC5F01412

 This all looks good except the string at the end (the digest) which has
 32 characters whereas I think the client is expecting 16. I'm guessing
 the string is created as UTF16. Is there a way to get this to be 16
 characters?

 bob
If the client is expecting 16 bytes, then it wants the response in binary. You're converting it to hex text which is why you've got twice as many characters as you are expecting. just remove the digestToString bit and send the raw ubyte array. You may or may not need to reverse the md5 as well. Not sure if Endianess applies to a md5.
Thanks. If I do : this.sock.send(cast(ubyte[])handshake ~ digest); it looks better but stil closes the connection. I guess I will have to look at the protocol spec again and see if I can figure what I'm doing wrong. bob
Oct 31 2010