Re: working with bits
 
On Apr 18, 5:16 am, Jerry Coffin <jcof...@taeus.com> wrote:
In article <1176864688.919444.214...@n76g2000hsh.googlegroups.com>,
iwasinni...@hotmail.com says...
I am still working on this project (Creating a DNS resolver).  My
programming skills have a lot to be desired.  I need to combine 4
buffers together and then use the sendto() socket command to send the
message to the DNS server.  Here are my buffers.  The message needs to
be a char*.
   unsigned int header_buffer = (ID << 80) | (Flags.Flag << 64) |
(QDCount << 48) | (ANCount << 32) | (NSCount << 16) | ARCount;
I'm not sure what hardware you're working on, but it looks
pretty exotic, if you have over 80 bits in an int.
   unsigned char QNAME;
   unsigned __int16        QTYPE;
   unsigned __int16        QCLASS;
I am at a loss as to how to combine these and then get it converted
into a char* so that I can use sendto().
Typically you'd do something like:
struct name_def {
        unsigned int header_buffer = (ID << 80) | // ...
// (ID << 80)? Really?
        unsigned char QNAME;
        unsigned _int16 QTYPE;
        unsigned _int16 QCLASS;
};
I rather doubt that this would work either.  The compiler will
probably insert some padding between QNAME and QTYPE.  And
whether the internal format of __int16 corresponds to what is
required on the line or not is not at all defined.  (__int16
looks like some old Microsoft stuff.  In which case, he's
probably on an Intel based PC, and the internal format does
*not* correspond to line format.)
In practice, you have to build up a byte buffer, byte by byte,
as I explained in my earlier answer.  And respect the external
format in all cases; QNAME is in fact a string, in the format
one byte length+characters; I suspect that it also has to be
padded to align to either 2 or 4 bytes (but I've not verified in
detail)---if not, QTYPE and QCLASS might be mis-aligned.  At any
rate, QNAME is a variable length field, so there's no way you
can use a struct here, even if all internal fields had the
correct format.
The way I usually handle this sort of thing is with push_back,
into an std::vector<char>; I then consider byte by byte what I
have to insert.  (Alignment can be handled using the % operator
on v.size().)  In some cases, where e.g. I have to insert the
number of bytes in what follows, I'll simply note the current
offset (v.size()), insert a placeholder, and then come back
later and write the actual value.  Finally, I'll write &v[0],
v.size().
Obviously, this requires a fairly good understanding of the
lower levels of what is going on.  I'd say that that is a
pre-requisite, however, for implementing any Internet protocol.
--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34