CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I can't understand what`s happening in this code! Help!

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
stoyanoff



Joined: 20 Jul 2011
Posts: 375

View user's profile Send private message

I can't understand what`s happening in this code! Help!
PostPosted: Tue Dec 20, 2011 3:51 am     Reply with quote

The function must calculate the checksum value of TCP package:
Code:

WORD csum(void *dp, WORD count)
{
register LWORD total=0L;
register WORD n, *p, carries;
n = count / 2;
p = (WORD *)dp;
while (n--)
total += *p++;
if (count & 1)
total += *(BYTE *)p;
while ((carries=(WORD)(total>>16))!=0)
total = (total & 0xffffL) + carries;
return((WORD)total);
}

I can't understand how exactly it happens.
In theory I know how to calculate checksum. May be the style of the author is different then main or I just have less experience. I can`t understand what`s happening in rows like
Code:
total += *(BYTE *)p;

or
Code:
 while ((carries=(WORD)(total>>16))!=0)

Can someone explain this function to me? I don't want to know how to calculate a checksum. I just want to know how it's done in this function.
Thanks a lot!!!!
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Dec 20, 2011 4:30 am     Reply with quote

Assumptions:

BYTE is unsigned 8 bit int
WORD is unsigned 16 bit int
LWORD is unsigned 32 bit int

Code:

WORD csum(void *dp, WORD count)
{
    register LWORD total=0L;        // Initial result to zero
    register WORD n, *p, carries;   // declare 16 bit temporaries, including p: pointer to WORD.

    n = count / 2;                  // n is count of ?WORDs, so is half count of probable BYTES... maybe.
    p = (WORD *)dp;                 // p is copy of void* pointer cast to word *. Presumably the input data is in WORDs.
   while (n--)                      // count down while n is not zero.
        total += *p++;              // Add WORD p is pointing to to total and increment p to point to the next WORD. Possible problem: Does C assume total is an operand for purposes of casting? If not then total cannot exceed 65535. Safer to explicitly cast as in total += (LWORD)*p++;
    // At this stage we've added all the WORDs. Deal with any left over BYTE.
    if (count & 1)                  // If count is odd... (note this is a bit wise and, NOT logical and: &&)
        total += *(BYTE *)p;        //...add byte p is pointing to to total. This treats the data 16 bit WORDS. Note there's no increment here. Not needed as its not part of the main loop above. {} would have helped to make that clearer.
    while ((carries=(WORD)(total>>16))!=0)  //  Assign the upper word of the total to carries and while its not zero...

    total = (total & 0xffffL) + carries;    // ...add it into the lower WORD. This is so called end-around carrying. The while is needed in case adding the carries causes a second carry.
    return((WORD)total);            // return the lower WORD of the result. Which appears to be an end-around sum of 24 bit values preloaded with zero.
}


Does that help?

RF Developer
stoyanoff



Joined: 20 Jul 2011
Posts: 375

View user's profile Send private message

PostPosted: Tue Dec 20, 2011 5:44 am     Reply with quote

Thanks a lot! I think I understood it. I though this is a function for calculating only TCP/IP packages checksum, but it`s universal. The TCP/IP has 8 bytes which must be add. The author of this code had add extra parameter(count) so the function could calculate checksum of any kind of packages.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Dec 20, 2011 6:02 am     Reply with quote

stoyanoff wrote:
Thanks a lot! I think I understood it. I though this is a function for calculating only TCP/IP packages checksum, but it`s universal. The TCP/IP has 8 bytes which must be add. The author of this code had add extra parameter(count) so the function could calculate checksum of any kind of packages.


No, this definitely does a *16 bit* end-around checksum ONLY, in other words the TCP & IP protocols' one's compliment checksum. It doesn't do 8 bit two's complement or even 16 bit two compliment summation, or any other variant. They are all different again. There is no "universal" checksum, any more than there is a "universal" CRC which is even more complicated. The principle may be the same, but details, such as preload and end-around, result width all make the checksums different.

RF Developer
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Tue Dec 20, 2011 6:22 am     Reply with quote

Just a couple of comments to do to do with the addressing...:
Code:

WORD csum(void *dp, WORD count)
{
    register LWORD total=0L;        // Initial result to zero
    register WORD n, *p, carries;   // declare 16 bit temporaries, including p: pointer to WORD.

    n = count / 2;                  // n is count of bytes, so need half this if
    //Using words
    p = (WORD *)dp;            // Just means _we_ are going to work with the
    //pointer as if it is to words - hence the half count
   while (n--)                      // count down while n is not zero.
        total += *p++;              // Add WORD p is pointing to to total and increment p to point to the next WORD. Possible problem: Does C assume total is an operand for purposes of casting? If not then total cannot exceed 65535. Safer to explicitly cast as in total += (LWORD)*p++;
    // At this stage we've added all the WORDs. Deal with any left over BYTE.
    if (count & 1)                  // If count is odd... (note this is a bit wise and, NOT logical and: &&)
        total += *(BYTE *)p;        //...add byte p is pointing to to total. This treats the data 16 bit WORDS. Note there's no increment here. Not needed as its not part of the main loop above. {} would have helped to make that clearer.
    //Remember p has already been incremented to point to the next word
    //(p++ in the loop) - increment _after_ use.
    while ((carries=(WORD)(total>>16))!=0)  //  Assign the upper word of the total to carries and while its not zero...

    total = (total & 0xffffL) + carries;    // ...add it into the lower WORD. This is so called end-around carrying. The while is needed in case adding the carries causes a second carry.
    return((WORD)total);            // return the lower WORD of the result. Which appears to be an end-around sum of 24 bit values preloaded with zero.
}
//Um. Just the 16bit end around sum, not 24bit.


Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group