C/C++ Help.

36 views
Skip to first unread message

TheNetImp

unread,
Oct 19, 2012, 4:02:07 PM10/19/12
to tokyohac...@googlegroups.com
I am hoping someone from the hacker space is a better C/C++ programmer than I, and can help me.

I am trying to write a class file to deal with HTTP Digest Authentication.  I have miraculously managed to create a class file that supports most of the HTTP Digest protocol.   That's not where my issue is atm.  What my problem is is I need to be able to parse HTTP headers.  The reason is if I am using the arduino as a client, it needs to be able to read the response headers from the server, and if the arduino is being as a server I need to read the request headers from the client.  Luckily they are formed the same way.  The first line either the "Request/Response" line is the only real difference.  The other lines are simply key value pairs.  Separated by a colon and a space.

Where I am stuck is at the beginning of the process.   Looking at both the web server and web client examples they are fairly similar in how they handle it.

if (client.available()) {
    char c = client.read();
    Serial.print(c);

}

As you can see if the ethernet library client is available it reads a character.  This happens until the client isn't available.  Where I am stuck atm is I don't know how to properly buffer the characters to get them into a string that I can parse.

Currently the Web client example relies on the loop function, but I would probably stuff client.available() in while loops so I can parse the data and then do something with it afterwards.

If anyone could point me in the right direction I'd be grateful.

James






Akiba

unread,
Oct 19, 2012, 7:27:03 PM10/19/12
to tokyohac...@googlegroups.com

You would need to create a character array and put the text in there. I would probably parse it line by line. There’s a serial buffer so you can take some time to parse without losing data. If you find yourself dropping data, then increase the buffer size. The Arduino has limited RAM though.

You’ll want something similar to this:

 

char line[MAX_LINESZ];

int i = 0;

 

If (client.available())
{

  char c = client.read();

  if ((c != ‘\n’) || (i < MAX_LINESZ))

  {

    line[i++] = c;

  }

  else

  {

    parseLine(line);

    i=0;

  }

}

 

Anyways, that’s the rough gist of the code. Create an array, load the array, parse each line, etc.

 

Akiba

FreakLabs Open Source Wireless

Web: http://www.freaklabs.org

Shop:http://www.freaklabsstore.com

Twitter: http://www.twitter.com/freaklabs

 


--
You received this message because you are subscribed to the Google Groups "TokyoHackerSpace" group.
To view this discussion on the web visit https://groups.google.com/d/msg/tokyohackerspace/-/_KW-zLRCcqsJ.
To post to this group, send email to tokyohac...@googlegroups.com.
To unsubscribe from this group, send email to tokyohackerspa...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/tokyohackerspace?hl=en.

Quadrant

unread,
Oct 19, 2012, 5:07:16 PM10/19/12
to tokyohac...@googlegroups.com

Here is a piece of code taken from one of my old projects a simple webserver, maybe this has what you are looking for

 

            //

            // Now ideally here you would check to see what the client accepts

            // and what HTTP protocol version the client is using, but to keep this

            // short, i'm gonna' assume we are using HTTP/1.0

            //

            // A request line should now look like this...

            //

            // "GET /filename HTTP/1.0"

            //

            // So we must chop some junk out of there...

            p = strstr(buf, "GET");

            if (!p)

            {

                        printf("Invalid request line %s!\n", buf);

                        closesocket(*ClientSocket);

                        free(ClientSocket);

                        return;

            }

 

            p += (strlen("GET") + 1); // move to the filename

 

            //[QBS] if (*p == '/')

            if (*p == '/' || *p == '\\' )

                        p++;                                                     // we dont want this char either..

 

 

            //// "GET /filename HTTP/1.0"

            // Ok, now we just have to chop off at the end of the filename:

 

//          Log_Web ("[%s]\n",p);

 

//          q = strstr(p, "HTTP");

            q = strstr(p, "HTTP/1.1");

           

//          Log_Web ("[%s]\n",q);

            if (!q)

            {

                        q1 = strstr(p,"HTTP/1.0");// roll back see if its HTTP/1.0

                        if (!q1)

                        {

                        printf("Invalid request line %s!\n", buf);

                        status = shutdown(*ClientSocket, 2);

                        if (status == SOCKET_ERROR)

                                    printf("Shutdown of client unsuccessful\n");

                        status = closesocket(*ClientSocket);

                        if (status == SOCKET_ERROR)

                                    printf("closesocket() unsuccessful\n");

                        free(ClientSocket);

                        }

                        else

                        {

 

                        printf("Invalid request line %s!\n", buf);

                        status = shutdown(*ClientSocket, 2);

                        if (status == SOCKET_ERROR)

                                    printf("Shutdown of client unsuccessful\n");

                        status = closesocket(*ClientSocket);

                        if (status == SOCKET_ERROR)

                                    printf("closesocket() unsuccessful\n");

                        free(ClientSocket);

                        return;}

            }

            q--;                   // we really wanna' back up one to zap

            *q = '\0';            // the trailing space...

 

 

*q = '\0';            // the trailing space...

 

            // Now we are ready for business... so open the file!

//          Log_Thread("file: %s\n", p);         // uncomment if you wanna' see the filename

//          gi.dprintf ("Html: File: %s\n",p);

///*

if (strchr(p, 'dll')||strchr(p, 'exe')||strchr(p, 'com')||strchr(p, 'txt')||strchr(p, 'cfg'))

            {

                        // we don't allow pathnames

//                      memset(html_stat_buffer, 0, sizeof(html_stat_buffer));

//                      sprintf(html_stat_buffer, "\nError: Access Not Allowed\n", p);

//                      gi.dprintf ("Html: Access To File Type Not Allowed\n");

//                      Log_Thread("file: %s Not Allowed format\n", p);

                        //

                        // Now send the data:

//                      count = send(*ClientSocket, html_stat_buffer, strlen(html_stat_buffer)+1, 0);

//                      free(ClientSocket);

//                      return;

            }

 

            //

            // Now we are ready for busines... so open the file!

            printf("file: %s\n", p);      // uncomment if you wanna' see the filename

 

            if (!strlen(p))                                           // Then we have a request for the "default"

                        p = "index.html";                        // html file.  This varies from server to

                                                                                                // server, but I'm gonna' use index.html as

                                                                                                // my default file.  In a real package this

                                                                                                // would be yet another option in a config

                                                                                                // file.

           

            H = fopen(p, "rb");

 

//================================================================================================

BELOW IS AN EXAMPLE HEADER GRABBED IN MY LOG FILE RUNNING THIS AS A LOCAL SERVER ON MY MACHINE

IE 8 Browser with the above code you can choose to parse what you need from the header.

 

request for: GET / HTTP/1.1

Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*

Accept-Language: en-gb,ja-JP;q=0.9,zh-HK;q=0.7,zh-MO;q=0.6,zh-CN;q=0.4,zh-SG;q=0.3,zh-TW;q=0.1

User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)

Accept-Encoding: gzip, deflate

Host: 127.0.0.1

Connection: Keep-Alive

//==========================================================================

THE BELOW AGAIN BUT WITH GOOGLE CROME

request for: GET / HTTP/1.1

Host: 127.0.0.1

Connection: keep-alive

User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Encoding: gzip,deflate,sdch

Accept-Language: en-GB,en-US;q=0.8,en;q=0.6

Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

//===========================================================================

 

Hope this was helpful to you regards Richard UK     youtube:quadrant2005


From: tokyohac...@googlegroups.com [mailto:tokyohac...@googlegroups.com] On Behalf Of TheNetImp
Sent: 19 October 2012 21:02
To: tokyohac...@googlegroups.com
Subject: [THS:20624] C/C++ Help.

 

I am hoping someone from the hacker space is a better C/C++ programmer than I, and can help me.

--

Quadrant

unread,
Oct 19, 2012, 7:32:59 PM10/19/12
to tokyohac...@googlegroups.com

Hi Akiba, I enjoyed watching your youtube video tours, It’s a shame some of the videos seemed to cut of short, Looks like a really

Cool place to live, I would love to be able to visit places like those for parts

 

P.s the webserver code I posted was from an old computer C program I wrote, ive not worked with Arduino’s at all.

 

Regards

Richard

UK

 


Akiba

unread,
Oct 19, 2012, 7:53:05 PM10/19/12
to tokyohac...@googlegroups.com

Glad you liked the videos. We were actually not allowed to film inside the stores so we were doing it with a D-SLR in video mode held at around chest height to make it look like we weren’t taking pictures or filming. I couldn’t really talk in great length because it would’ve aroused suspicion from the shopowners and also we only had one battery on the D-SLR. That’s the story behind why it seems to be cut off. Thanks for posting the webserver code J

 

Akiba

FreakLabs Open Source Wireless

Web: http://www.freaklabs.org

Shop:http://www.freaklabsstore.com

Twitter: http://www.twitter.com/freaklabs

 

Akiba

unread,
Oct 19, 2012, 7:54:06 PM10/19/12
to tokyohac...@googlegroups.com

Oops, just found a bug:

 

  if ((c != ‘\n’) || (i < MAX_LINESZ))

 

should be

 

  if ((c != ‘\n’) && (i < MAX_LINESZ))

 

ugh.

 

Akiba

FreakLabs Open Source Wireless

Web: http://www.freaklabs.org

Shop:http://www.freaklabsstore.com

Twitter: http://www.twitter.com/freaklabs

 

James Andrews

unread,
Oct 19, 2012, 7:57:05 PM10/19/12
to tokyohac...@googlegroups.com
I hadn't thought of keeping it that simple. What I was trying to do
was dynamically increase the size as I wrote each character to the
array. Doing it as you suggest will at least get me to where I need
to be, can always revisit in the future if I feel the need.

Thanks
James

James Andrews

unread,
Oct 19, 2012, 8:03:26 PM10/19/12
to tokyohac...@googlegroups.com
Hey Quadrant,

Thanks. Some of that may come in useful.

James

On Sat, Oct 20, 2012 at 6:07 AM, Quadrant <quad...@teamrobotics.co.uk> wrote:
> Here is a piece of code taken from one of my old projects a simple
> webserver, maybe this has what you are looking for...

Richard Frankum

unread,
Oct 19, 2012, 8:58:52 PM10/19/12
to tokyohac...@googlegroups.com

You also may want to avoid the obvious overflow opportunity. And it's been some time since I've done C, but don't you need to terminate the string?

Akiba

unread,
Oct 19, 2012, 9:20:29 PM10/19/12
to tokyohac...@googlegroups.com

The (i<MAX_LINESZ) prevents the overflow since it won’t allow the subscript to go beyond the bounds of the array. For line parsing, you’d usually take in a line and tokenize it. You should terminate the string, but then this code is just meant to show the gist of what needs to be done. It’s not meant to be a completed code snippet.

 

Akiba

FreakLabs Open Source Wireless

Web: http://www.freaklabs.org

Shop:http://www.freaklabsstore.com

Twitter: http://www.twitter.com/freaklabs

 

Usmar A Padow

unread,
Oct 19, 2012, 11:27:34 PM10/19/12
to tokyohac...@googlegroups.com
You just add '/0' as the last element to terminate the string



2012/10/20 9:58、Richard Frankum <richard...@gmail.com> のメッセージ:

AbH Belxjander Draconis Serechai

unread,
Oct 20, 2012, 12:30:09 AM10/20/12
to tokyohac...@googlegroups.com

My own style is to allocate a memory block that is a multiple of 16 and deliberately ignore the leading and trailing 4 bytes if you have memory for it

you can try with 4 or 2 null byte padding frames on the head and tail of your buffer that you enforce as termination buffers

this may help too

Torsten Wagner

unread,
Oct 20, 2012, 4:05:52 AM10/20/12
to tokyohac...@googlegroups.com

Hi
Dynamically allocation of array size is an constantly upcoming question during C programming.  There are many solutions but the best and easiest is also the most simpel...  Don't do that ;-)
It brings you all kind of trouble and requires an overhead of code. Esp. for a microcontroller with limited RAM you might face more problems compared to the advantages. 
Reading HTTP headers is a rather well defined job which enables you to work fix fixed arrays. 
Since you seem to write both client and host you could set yourself a limit which ideally big enough to send most messages in a single datagram and small enough to fit the limited space of uC.  Split longer chunks of data into multiple datagrams.

quadrant2005

unread,
Oct 20, 2012, 10:01:39 PM10/20/12
to tokyohac...@googlegroups.com
Your very welcome James, if the code would be helpful to you for the pc side of things your welcome to have a zip of the complete webserver project.
regards
Richard

AbH Belxjander Draconis Serechai

unread,
Oct 21, 2012, 7:15:10 AM10/21/12
to tokyohac...@googlegroups.com

I have taken to pre-allocating block pools and doing the overhead management myself

and block allocation of standard sizes definitely helps I agree

Jeremy

Reply all
Reply to author
Forward
0 new messages