typecasting...

Discussion in 'C++' started by aki, Apr 29, 2007.

  1. aki

    aki Guest

    i am receiving a buffer from network as char pointer.
    char * buffer;
    this is an argument of my function.
    well i want to decode this buffer.
    buffer contain a packet with different fields
    as

    code of size 1 byte contain inter value
    identifier of size 1 byte contain integer value
    and
    length of size 2 byte. contain integer value.

    as struct lcpHeader
    {
    uint8_t code;
    uint8_t identifier;
    uint16_t length;
    };

    i want to access it all fields.
    1) code field

    struct lcpHeader *hdr;
    hdr=(struct lcpHeader*)buffer;

    when i do switch(hdr->code)
    will it give integer value contained in the code....?

    how to access other fielsd?
    i hope i have made clear what i wann do?
    aki, Apr 29, 2007
    #1
    1. Advertising

  2. * aki:
    > i am receiving a buffer from network as char pointer.
    > char * buffer;
    > this is an argument of my function.
    > well i want to decode this buffer.
    > buffer contain a packet with different fields
    > as
    >
    > code of size 1 byte contain inter value
    > identifier of size 1 byte contain integer value
    > and
    > length of size 2 byte. contain integer value.
    >
    > as struct lcpHeader
    > {
    > uint8_t code;
    > uint8_t identifier;
    > uint16_t length;
    > };
    >
    > i want to access it all fields.
    > 1) code field
    >
    > struct lcpHeader *hdr;
    > hdr=(struct lcpHeader*)buffer;
    >
    > when i do switch(hdr->code)
    > will it give integer value contained in the code....?


    Yes. Whether that is what's meant to be interpreted as code is another
    question. That depends on whether your platform-dependent definitions
    correspond to the format of the data.


    > how to access other fielsd?


    Think about how you accessed the code field.


    > i hope i have made clear what i wann do?


    Nope.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Apr 29, 2007
    #2
    1. Advertising

  3. aki wrote:
    > i am receiving a buffer from network as char pointer.
    > char * buffer;
    > this is an argument of my function.
    > well i want to decode this buffer.
    > buffer contain a packet with different fields
    > as
    >
    > code of size 1 byte contain inter value
    > identifier of size 1 byte contain integer value
    > and
    > length of size 2 byte. contain integer value.
    >
    > as struct lcpHeader
    > {
    > uint8_t code;
    > uint8_t identifier;
    > uint16_t length;
    > };
    >
    > i want to access it all fields.
    > 1) code field
    >
    > struct lcpHeader *hdr;
    > hdr=(struct lcpHeader*)buffer;
    >
    > when i do switch(hdr->code)
    > will it give integer value contained in the code....?
    >
    > how to access other fielsd?
    > i hope i have made clear what i wann do?
    >


    Anything coming over the wire needs to be absolutely consistent to avoid
    security problems.

    Before performing the cast, make sure there are enough bytes that have
    been read into the buffer (so you don't depend on uninitialized garbage).


    .... psuedo code shows one way of doing it ...

    // returns negative number indicating the number of bytes short
    // returns a positive number indicating the number of bytes used
    // returns 0 when the packet cannot be parsed

    int decode( const char * buffer, int bytes_read )
    {
    // check there are enough bytes
    if ( sizeof( lcpHeader ) > bytes_read )
    {
    // return a negative number indicating the number of bytes
    // needed before decoding can proceed
    return bytes_read - sizeof( lcpHeader );
    }

    const lcpHeader *hdr = reinterpret_cast< const lcpHeader *>(buffer);

    // need to make sure you correct for endianness
    const uint16_t length = EndianAdjust( hdr->length );

    .... you need to make sure we're using hdr->length correctly here..

    if ( length > bytes_read )
    {
    // still don't have enough bytes
    return bytes_read - length;
    }

    // all the bytes for the packet are now in the buffer ..

    switch ( hdr->code )
    {
    default :
    {
    // unknown code

    ... version issue ? ...
    return 0; // 0 is an error
    }

    case 1 :
    {
    return decode_data_for_code_1(
    buffer + sizeof( * hdr ), length - sizeof( * hdr )
    );
    break;
    }

    }

    // return number of bytes consumed
    return length;
    }

    ..... do the same thing for code 1 ...

    int decode_data_for_code_1( const char * buffer, int bytes_read )
    {
    .....
    }


    It can't be stressed how critical it is to make sure you do not try to
    parse uninitialized data or make any assumptions on the length of the
    data available (i.e. over flow any buffers by assuming the data from the
    wire is smaller that your allocated buffer). You also need to set
    reasonable size limits to data so as not to cripple your protocol but
    also not allow for denial of service attacks.
    Gianni Mariani, Apr 29, 2007
    #3
  4. aki

    ajk Guest

    On 29 Apr 2007 01:28:45 -0700, aki <> wrote:

    >when i do switch(hdr->code)
    >will it give integer value contained in the code....?
    >


    yep

    >how to access other fielsd?


    same way u accessed 'code'

    hdr->identifier
    hdr->length
    ajk, Apr 29, 2007
    #4
  5. aki

    James Kanze Guest

    On Apr 29, 10:28 am, aki <> wrote:
    > i am receiving a buffer from network as char pointer.
    > char * buffer;
    > this is an argument of my function.
    > well i want to decode this buffer.
    > buffer contain a packet with different fields
    > as


    > code of size 1 byte contain inter value


    In what format?

    > identifier of size 1 byte contain integer value


    In what format?

    > and
    > length of size 2 byte. contain integer value.


    In what format?

    > as struct lcpHeader
    > {
    > uint8_t code;
    > uint8_t identifier;
    > uint16_t length;
    > };


    You'll have to extract the individual bytes and reconstruct them
    into whatever struct you want to use. There's no guarantee that
    the internal format of a struct is in any way related to some
    arbitrary network protocol.

    > i want to access it all fields.
    > 1) code field


    > struct lcpHeader *hdr;
    > hdr=(struct lcpHeader*)buffer;


    > when i do switch(hdr->code)
    > will it give integer value contained in the code....?


    Exceptionally, this one probably will, as long as the possible
    values in the code field are in the range [0,128). The one
    guarantee you have about structure layout is that the address of
    the first element is the same as the address of the struct.

    If the code can be negative, or have values greater that or
    equal to 128, you'll have to convert the char to either signed
    or unsigned char.

    > how to access other fielsd?


    By extracting the bytes from the buffer, recombining them to
    form whatever type you want, and assigning the results to the
    field in the struct. Without knowing more about the format,
    it's impossible to say precisely how to do this.

    --
    James Kanze (Gabi Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Apr 29, 2007
    #5
  6. aki

    Default User Guest

    aki wrote:

    > i am receiving a buffer from network as char pointer.


    Pick a language. You multi-posted the same message to comp.lang.c.




    Brian
    Default User, Apr 29, 2007
    #6
  7. aki

    Jim Langston Guest

    "aki" <> wrote in message
    news:...
    >i am receiving a buffer from network as char pointer.
    > char * buffer;
    > this is an argument of my function.
    > well i want to decode this buffer.
    > buffer contain a packet with different fields
    > as
    >
    > code of size 1 byte contain inter value
    > identifier of size 1 byte contain integer value
    > and
    > length of size 2 byte. contain integer value.
    >
    > as struct lcpHeader
    > {
    > uint8_t code;
    > uint8_t identifier;
    > uint16_t length;
    > };
    >
    > i want to access it all fields.
    > 1) code field
    >
    > struct lcpHeader *hdr;
    > hdr=(struct lcpHeader*)buffer;
    >
    > when i do switch(hdr->code)
    > will it give integer value contained in the code....?
    >
    > how to access other fielsd?
    > i hope i have made clear what i wann do?


    Do a sizeof kpHeader and make sure it's 32. It may be different although it
    seems like it may be okay in this instance. I'm talking about padding
    spaces. Lets say, for example, you had a structure:

    struct kpHeader
    {
    uint8_t Code;
    uint32_t Length;
    };

    You might think the sizeof that woudl be 40, but might be suprised that the
    size (on my platform) would be 64. That's why it's generally not a good
    idea to try to cast socket data into a structure as padding may throw it
    off. I do not know if your system is 32 bit aligned, 16 bit, etc...For the
    most part, two bytes followed by a short (16 bit) should fit in 32 bits, but
    there is no guarantee.
    Jim Langston, Apr 30, 2007
    #7
  8. aki

    aki Guest

    On Apr 29, 4:31 pm, Gianni Mariani <> wrote:
    > aki wrote:
    > > i am receiving a buffer from network as char pointer.
    > > char * buffer;
    > > this is an argument of my function.
    > > well i want to decode this buffer.
    > > buffer contain a packet with different fields
    > > as

    >
    > > code of size 1 byte contain inter value
    > > identifier of size 1 byte contain integer value
    > > and
    > > length of size 2 byte. contain integer value.

    >
    > > as struct lcpHeader
    > > {
    > > uint8_t code;
    > > uint8_t identifier;
    > > uint16_t length;
    > > };

    >
    > > i want to access it all fields.
    > > 1) code field

    >
    > > struct lcpHeader *hdr;
    > > hdr=(struct lcpHeader*)buffer;

    >
    > > when i do switch(hdr->code)
    > > will it give integer value contained in the code....?

    >
    > > how to access other fielsd?
    > > i hope i have made clear what i wann do?

    >
    > Anything coming over the wire needs to be absolutely consistent to avoid
    > security problems.
    >
    > Before performing the cast, make sure there are enough bytes that have
    > been read into the buffer (so you don't depend on uninitialized garbage).
    >
    > ... psuedo code shows one way of doing it ...
    >
    > // returns negative number indicating the number of bytes short
    > // returns a positive number indicating the number of bytes used
    > // returns 0 when the packet cannot be parsed
    >
    > int decode( const char * buffer, int bytes_read )
    > {
    > // check there are enough bytes
    > if ( sizeof( lcpHeader ) > bytes_read )
    > {
    > // return a negative number indicating the number of bytes
    > // needed before decoding can proceed
    > return bytes_read - sizeof( lcpHeader );
    > }
    >
    > const lcpHeader *hdr = reinterpret_cast< const lcpHeader *>(buffer);
    >
    > // need to make sure you correct for endianness
    > const uint16_t length = EndianAdjust( hdr->length );
    >
    > .... you need to make sure we're using hdr->length correctly here..
    >
    > if ( length > bytes_read )
    > {
    > // still don't have enough bytes
    > return bytes_read - length;
    > }
    >
    > // all the bytes for the packet are now in the buffer ..
    >
    > switch ( hdr->code )
    > {
    > default :
    > {
    > // unknown code
    >
    > ... version issue ? ...
    > return 0; // 0 is an error
    > }
    >
    > case 1 :
    > {
    > return decode_data_for_code_1(
    > buffer + sizeof( * hdr ), length - sizeof( * hdr )
    > );
    > break;
    > }
    >
    > }
    >
    > // return number of bytes consumed
    > return length;
    >
    > }
    >
    > .... do the same thing for code 1 ...
    >
    > int decode_data_for_code_1( const char * buffer, int bytes_read )
    > {
    > ....
    >
    > }
    >
    > It can't be stressed how critical it is to make sure you do not try to
    > parse uninitialized data or make any assumptions on the length of the
    > data available (i.e. over flow any buffers by assuming the data from the
    > wire is smaller that your allocated buffer). You also need to set
    > reasonable size limits to data so as not to cripple your protocol but
    > also not allow for denial of service attacks.


    thanks for your all comments....

    one thing i missed earlier to write is..
    the buffer i am receiving not only contains lcpHeader but also data
    after that.
    the data field is variable as the data length varies with code field
    of lcpHeader..
    my question is..
    can i do check for enough bytes....
    // check there are enough bytes
    like u HAVE DONE ABOVE...
    as now payload of lcpHeader is not fixed...
    aki, Apr 30, 2007
    #8
  9. aki

    aki Guest

    On Apr 30, 8:31 am, "Jim Langston" <> wrote:
    > "aki" <> wrote in message
    >
    > news:...
    >
    >
    >
    > >i am receiving a buffer from network as char pointer.
    > > char * buffer;
    > > this is an argument of my function.
    > > well i want to decode this buffer.
    > > buffer contain a packet with different fields
    > > as

    >
    > > code of size 1 byte contain inter value
    > > identifier of size 1 byte contain integer value
    > > and
    > > length of size 2 byte. contain integer value.

    >
    > > as struct lcpHeader
    > > {
    > > uint8_t code;
    > > uint8_t identifier;
    > > uint16_t length;
    > > };

    >
    > > i want to access it all fields.
    > > 1) code field

    >
    > > struct lcpHeader *hdr;
    > > hdr=(struct lcpHeader*)buffer;

    >
    > > when i do switch(hdr->code)
    > > will it give integer value contained in the code....?

    >
    > > how to access other fielsd?
    > > i hope i have made clear what i wann do?

    >
    > Do a sizeof kpHeader and make sure it's 32. It may be different although it
    > seems like it may be okay in this instance. I'm talking about padding
    > spaces. Lets say, for example, you had a structure:
    >
    > struct kpHeader
    > {
    > uint8_t Code;
    > uint32_t Length;
    >
    > };
    >
    > You might think the sizeof that woudl be 40, but might be suprised that the
    > size (on my platform) would be 64. That's why it's generally not a good
    > idea to try to cast socket data into a structure as padding may throw it
    > off.

    yes there can be additional padding bits..if required from other
    side...
    but then how can socket data be casted into structures...
    any solution to padding... problem....
    how is then packet data received correctly....


    I do not know if your system is 32 bit aligned, 16 bit, etc...For the
    > most part, two bytes followed by a short (16 bit) should fit in 32 bits, but
    > there is no guarantee.
    aki, Apr 30, 2007
    #9
  10. aki

    James Kanze Guest

    On Apr 30, 12:34 am, "Default User" <> wrote:
    > aki wrote:
    > > i am receiving a buffer from network as char pointer.


    > Pick a language. You multi-posted the same message to comp.lang.c.


    Thanks for pointing that out. That way I can adjust my
    responses, and not get chewed out by the C'ers for suggesting
    e.g. std::vector.:).

    As it happens, he has hit on a question where the basic issues
    are the same in the two languages. C++ tries to be compatible
    with C where POD structures are involved. (For those in clc: in
    C++, a POD ("Plain Ordinary Data") structure corresponds, more
    or less, to the subset of what you could write in C.) The rules
    for padding, etc., are the same. And C++'s rules are exactly
    the same concerning the representation of arithmetic types.
    (Strictly speaking, not quite: the C++ rules correspond to those
    in C90, which is, of course, out of date. But the next version
    of C++ will be compatible with C99, and in practice, I don't
    think it makes a difference here. C99's decision to limit
    integer representations to 1's complement, 2's complement and
    signed magnitude was, I believe, just a recognition that no
    other conforming representations did exist.)


    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Apr 30, 2007
    #10
  11. aki

    James Kanze Guest

    On Apr 30, 5:31 am, "Jim Langston" <> wrote:
    > "aki" <> wrote in message
    > news:...


    > >i am receiving a buffer from network as char pointer. char
    > >* buffer; this is an argument of my function. well i want
    > >to decode this buffer. buffer contain a packet with
    > >different fields as code of size 1 byte contain inter value
    > >identifier of size 1 byte contain integer value and length
    > >of size 2 byte. contain integer value.


    > > as struct lcpHeader
    > > {
    > > uint8_t code;
    > > uint8_t identifier;
    > > uint16_t length;
    > > };


    > > i want to access it all fields.
    > > 1) code field


    > > struct lcpHeader *hdr;
    > > hdr=(struct lcpHeader*)buffer;


    > > when i do switch(hdr->code)
    > > will it give integer value contained in the code....?


    > > how to access other fielsd?
    > > i hope i have made clear what i wann do?


    > Do a sizeof kpHeader and make sure it's 32.


    I don't know of any platform today where this is the case. On
    most platforms, I'd expect a size of 4, but of course, there's
    absolutely no guarantee. (Note that by using the integral types
    from C99, he has ensured 8 bit bytes... and that the code won't
    compile on every platform.)

    > It may be different although it
    > seems like it may be okay in this instance. I'm talking about padding
    > spaces. Lets say, for example, you had a structure:


    > struct kpHeader
    > {
    > uint8_t Code;
    > uint32_t Length;
    > };


    > You might think the sizeof that woudl be 40, but might be suprised that the
    > size (on my platform) would be 64.


    You must have a really exotic machine. On all of my systems
    (PC's and Sparc based, 32 and 64 bits, Windows, Linux and
    Solaris), it's 8.

    > That's why it's generally not a good
    > idea to try to cast socket data into a structure as padding may throw it
    > off. I do not know if your system is 32 bit aligned, 16 bit, etc...For the
    > most part, two bytes followed by a short (16 bit) should fit in 32 bits, but
    > there is no guarantee.


    The alignment is only part of the problem. There's also the
    question of representation of the values. He still has problems
    with regards to byte order, however, and if he tries the above
    for an Internet protocol, on a PC, it won't work.

    The only real solution is to access the buffer one byte at a
    time, and use the individual bytes to build up the target data
    type. For an Internet protocol, a two byte integral field
    starting at offset 2 could be read by:

    (buffer[ 2 ] & 0xFF) << 8 | (buffer[ 1 ] & 0xFF)

    (I generally try to declare such buffers as unsigned char,
    rather than plain char, so as to not need the "& 0xFF" all over
    the place.)

    The correct way to read his structure would be:

    struct lcpHeader
    getHeader(
    unsigned char buffer )
    {
    lcpHeader result = {} ;
    result.code = buffer[ 0 ] ;
    result.identifier = buffer[ 1 ] ;
    result.length = (buffer[ 2 ] << 8) | buffer[ 3 ] ;
    return result ;
    }

    This, of course, supposes that the types in the transmission
    buffer are also unsigned (or at least limited to non-negative
    values), and that the protocol uses the standard Internet
    protocol representations (which is far from universal). It
    works regardless of the size or representation of the internal
    types, and regardless of what padding might have been inserted
    by the compiler.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Apr 30, 2007
    #11
  12. aki

    James Kanze Guest

    On Apr 29, 1:38 pm, ajk <> wrote:
    > On 29 Apr 2007 01:28:45 -0700, aki <> wrote:


    > >when i do switch(hdr->code)
    > >will it give integer value contained in the code....?


    > yep


    Maybe. It will work if the integer value in code is in the
    range [0,128), but only because code is the first element of the
    struct.

    > >how to access other fielsd?


    > same way u accessed 'code'


    > hdr->identifier
    > hdr->length


    No. Neither of these are guaranteed to work. On a PC, at least
    with Internet protocols, the second doesn't work. And all
    depend somewhat on the compiler.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Apr 30, 2007
    #12
  13. aki wrote:
    ....
    > one thing i missed earlier to write is..
    > the buffer i am receiving not only contains lcpHeader but also data
    > after that.
    > the data field is variable as the data length varies with code field
    > of lcpHeader..
    > my question is..
    > can i do check for enough bytes....
    > // check there are enough bytes
    > like u HAVE DONE ABOVE...
    > as now payload of lcpHeader is not fixed...
    >


    That depends on the protocol. If the length in the header is the entire
    length of the message (logical thing to do) then you're all set. Without
    knowing what the protocol is, I can't answer your question.
    Gianni Mariani, Apr 30, 2007
    #13
  14. aki

    Drew Lawson Guest

    In article <>
    aki <> writes:

    >yes there can be additional padding bits..if required from other
    >side...
    >but then how can socket data be casted into structures...
    >any solution to padding... problem....
    >how is then packet data received correctly....


    I'm not sure what answers are portable, but one is to check your
    compiler options to see if there are any that specify how/whether
    data structures are packed. There are certainly some out there
    that allow you to turn off padding, and certain embedded applications
    (like those dealing with raw packet data) often make sure that one
    of them is in use.

    Another method is to keep your byte buffer as a byte buffer and
    look at each "field" explicitly:

    (unit16_t *)(buffer+2)

    As hinted at elsewhere, you still have to adjust for bit/byte/word
    ordering and whether they agree with network order. The last place
    I worked on that sort of stuff had sets of BYTE_SWAP(), etc. macros
    that were built up from compiler macros that (IIRC) indicated the
    local ordering. On some hardware they ended up being no-ops. (This
    was working in C, but in details that I believe are identical in
    C++.)

    If this is a learning project, you can simplify things by using the
    same hardware types on both ends of the wire and just ignoring the
    ordering issue. In my college days, that was easy. All the socket
    connections were going to the same machine we were on.

    --
    |Drew Lawson | If you're not part of the solution |
    | | you're part of the precipitate. |
    |http://www.furrfu.com/ | |
    Drew Lawson, May 1, 2007
    #14
    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. =?Utf-8?B?Smlt?=

    ArrayList typecasting from binary SQL data

    =?Utf-8?B?Smlt?=, Apr 11, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    502
    Bruce Barker
    Apr 11, 2005
  2. Kapil Khosla

    Understanding Typecasting in C++

    Kapil Khosla, Jul 19, 2003, in forum: C++
    Replies:
    3
    Views:
    7,334
    John Harrison
    Jul 20, 2003
  3. Nicolay Korslund
    Replies:
    7
    Views:
    454
    Nicolay Korslund
    Sep 30, 2003
  4. venkatesh
    Replies:
    1
    Views:
    8,111
    lallous
    Dec 6, 2003
  5. Robert Street

    Advanced pointer typecasting

    Robert Street, Feb 20, 2004, in forum: C++
    Replies:
    3
    Views:
    6,933
    Robert Street
    Feb 21, 2004
Loading...

Share This Page