Reputation: 33
I'm writing code for an http server on an embedded target. I want to parse the raw HTTP packet I am receiving for its' content length. My problem arises from the fact that I don't know how many bytes the content length is. For example,
//Content-Length is 4 characters
Content-Length: 1000
//Content-Length is 2 characters
Content-Length: 20
My code is:
(buf is a char array with the contents of the http data, pLength is a char *)
pLength = strstr(buf, lenTok);
//advance pointer past "Content-Length: " to point to data
if (pLength != NULL)
pLength = (pLength + 16);
int length = 0;
for (int i = 0; i < /*length of Content-Length:*/; i++)
{
length = length * 10;
length = length + (pLength[i] - '0');
}
I know my code works because for now I have put a hard coded value in the loop iterator condition. I just need to be able to determine it at run time.
EDIT: Would it be safe to keep reading characters until \r is found?
Upvotes: 2
Views: 5395
Reputation: 1159
One way to solve this is to simply start counting from after the fixed-length string "Content-Length: " until you find either whitespace or a null byte (in some rare conditions).
#define INITIAL_LENGTH (16) /* Length of the string "Content-Length: " */
if (pLength == NULL)
return /* or whatever */
else
pLength += INITIAL_LENGTH
int length;
for(length = 0; *pLength != 0 && *pLength != '\n'; ++pLength)
length++;
pLength -= length; /* Now it points right after Content-Length: */
/* Now you have the length */
Upvotes: 1
Reputation: 34839
Each line in the header ends with a CR/LF pair per section 3 of RFC7230. In section 3.2.4 of the same document, it says that "a field value might be preceded and/or followed by optional whitespace". Therefore to parse the content-length successfully, your code must skip any leading whitespace, then process digits until a whitespace character is found. In other words
int i;
int count = 0;
int length = 0;
for ( i = 0; isspace( pLength[i] ); i++ )
{
// skip leading whitespace
}
for ( count = 1; !isspace( pLength[i] ); i++, count++ )
{
if ( count > 9 || !isdigit( pLength[i] ) )
{
// some sort of error handling is needed here
}
length = length * 10;
length = length + (pLength[i] - '0');
}
Note that checking for count > 9
limits the content-length to 999,999,999. Adjust as necessary for your application. For example, you can support larger numbers if int
is 64-bits. On the other hand, maybe you only want to support smaller lengths, in which case you could limit the number of digits to a smaller value.
Upvotes: 2