Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Fork of webserverBlinky by
Diff: main.cpp
- Revision:
- 87:9f5ac1fabd95
- Parent:
- 85:53e57ff1cf05
- Child:
- 88:b4a71242837c
--- a/main.cpp Thu Jul 20 01:03:13 2017 +0000 +++ b/main.cpp Fri Jul 21 00:35:24 2017 +0000 @@ -97,11 +97,11 @@ // a structure to keep all our ppp globals in struct pppType { int online; // we hunt for a PPP connection if this is zero - int ident; // our IP ident value + unsigned int ident; // our IP ident value unsigned int seq; // our TCP sequence number int crc; // for calculating IP and TCP CRCs int ledState; // state of LED1 - int httpFrame; + int httpFrameCount; struct { #define RXBUFLEN (1<<14) char buf[RXBUFLEN]; // RXBUFLEN MUST be a power of two because we use & operator for fast wrap-around in ring buffer @@ -139,7 +139,7 @@ ppp.ledState=0; ppp.hdlc.frameFound=0; ppp.hdlc.frameStartIndex=0; - ppp.httpFrame=0; + ppp.httpFrameCount=0; } void led1Toggle() @@ -551,7 +551,7 @@ int nHeader; // byte size of HTTP header int contentLengthStart; // index where HTML starts - ppp.httpFrame++; // increment count of response frames + ppp.httpFrameCount++; // increment the number of frames we have made int rootFetch = strncmp(dataStart, "GET / HTTP/1.1", 14); @@ -572,14 +572,14 @@ // this is where we insert our web page into the buffer n=n+sprintf(n+dataStart,"%s", ourWebPage); } else { - // all other requests get 404 Not Found response a - n=n+sprintf(n+dataStart,"<!DOCTYPE html>"); // html start - n=n+sprintf(n+dataStart,"<title>%06d</title>",ppp.httpFrame); // shortest possible valid frame + // all other requests get 404 Not Found response with a http frame count - nice for debugging + n=n+sprintf(n+dataStart,"<!DOCTYPE html><title>ppp-blinky</title>"); // html start + n=n+sprintf(n+dataStart,"<body>%06d</body>",ppp.httpFrameCount); // body = the http frame count } - while( (n%4)!= 2) - n=n+sprintf(n+dataStart," "); // insert spaces until n is exactly two away from a multiple of four - n=n+sprintf(n+dataStart,"\r\n"); // add the last \r\n sequence - n is now an exact multiple of four + while( (n%4)!= 2) n=n+sprintf(n+dataStart," "); // insert spaces until n is exactly two away from a multiple of four + n=n+sprintf(n+dataStart,"\r\n"); // add the last two characters (\r\n) - n is now an exact multiple of four + #define CONTENTLENGTHSIZE 5 char contentLengthString[CONTENTLENGTHSIZE+1]; snprintf(contentLengthString,CONTENTLENGTHSIZE+1,"%*d",CONTENTLENGTHSIZE,n-nHeader); // print Content-Length with leading spaces and fixed width equal to csize @@ -594,6 +594,8 @@ void tcpHandler() { + // IP header + char * ipPkt = ppp.pkt.buf+4; // ip packet start char * ihl = ipPkt; // bottom 4 bits char * pktLen = ipPkt+2; // 2 bytes @@ -605,30 +607,31 @@ int headerSizeIP = (ihl[0]&0xf)*4; int packetLength = (pktLen[0]<<8)|pktLen[1]; // ip total packet length - char * s = ppp.pkt.buf+4+headerSizeIP; // start of tcp packet - char * srctcp = s + 0; // 2 bytes - char * dsttcp = s + 2; // 2 bytes - char * seqtcp = s + 4; // 4 bytes - char * acktcp = s + 8; // 4 bytes - char * offset = s + 12; // 4 bits - char * flagbitstcp = s + 12; // 9 bits - char * windowsizetcp = s + 14; // 2 bytes - char * checksumtcp = s + 16; // 2 bytes + // TCP header + + char * tcp = ppp.pkt.buf+4+headerSizeIP; // start of tcp packet + char * srctcp = tcp + 0; // 2 bytes + char * dsttcp = tcp + 2; // 2 bytes + char * seqtcp = tcp + 4; // 4 bytes + char * acktcp = tcp + 8; // 4 bytes + char * offset = tcp + 12; // 4 bits + char * flagbitstcp = tcp + 12; // 9 bits + char * windowsizetcp = tcp + 14; // 2 bytes + char * checksumtcp = tcp + 16; // 2 bytes int tcpSize = packetLength - headerSizeIP; int headerSizeTCP = ((offset[0]>>4)&0x0f)*4; // size of tcp header only int protocolIP = protocol[0]; - int flagsTCP = ((flagbitstcp[0]&1)<<8)|flagbitstcp[1]; - - char * dataStart = ppp.pkt.buf + 4 + headerSizeIP + headerSizeTCP; // start of data block after TCP header + char * tcpDataIn = tcp + headerSizeTCP; // start of data block after TCP header int tcpDataSize = tcpSize - headerSizeTCP; // size of data block after TCP header + char * tcpDataOut = tcp + 20; // start of outgoing data unsigned int seq_in = (seqtcp[0]<<24)|(seqtcp[1]<<16)|(seqtcp[2]<<8)|(seqtcp[3]); unsigned int ack_in = (acktcp[0]<<24)|(acktcp[1]<<16)|(acktcp[2]<<8)|(acktcp[3]); unsigned int ack_out = seq_in + tcpDataSize; - unsigned int seq_out = ack_in; // ack_in is their calculation of our current sequence number + unsigned int seq_out = ack_in; // use their version of our current sequence number #define TCP_FLAG_ACK (1<<4) @@ -637,9 +640,19 @@ #define TCP_FLAG_RST (1<<2) #define TCP_FLAG_FIN (1<<0) + // first we shorten the TCP response header to only 20 bytes. + // this means we ignore all TCP option requests + + tcpSize = 20; // shorten total TCP packet size to 20 bytes (no data) + headerSizeTCP = 20; // shorten outgoing TCP header size 20 bytes + offset[0] = (headerSizeTCP/4)<<4; // shorten tcp header size to 20 bytes + packetLength = 40; // shorten total packet size to 40 bytes (20 ip + 20 tcp) + pktLen[1] = 40; // set total packet size to 40 bytes (20 ip + 20 tcp) + pktLen[0] = 0; // set total packet size to 40 bytes (20 ip + 20 tcp) + int dataLen = 0; // most of our responses will have zero TCP data, only a header int flagsOut = TCP_FLAG_ACK; // the default case is an ACK packet - int fastResponse = 0; // normally you wait 200ms before sending a packet but this can make it faster + int flagsTCP = ((flagbitstcp[0]&1)<<8)|flagbitstcp[1]; // the tcp flags we received // A sparse TCP flag interpreter that implements simple TCP connections from a single source // Clients are allowed ONE push packet, after which the link is closed with a FIN flag in the ACK packet @@ -647,32 +660,18 @@ switch ( flagsTCP ) { case TCP_FLAG_SYN: + flagsOut = TCP_FLAG_SYN | TCP_FLAG_ACK; // something wants to connect - acknowledge it + seq_out = seq_in+0x1000U; // create a new sequence number using their sequence as a base ack_out++; // for SYN flag we have to increase the sequence by 1 - // ignore all TCP option requests by shortening the TCP header to 20 bytes - headerSizeTCP = 20; // shorten TCP header size 20 bytes - offset[0] = (headerSizeTCP/4)<<4; // shorten tcp header size to 20 bytes - tcpSize = 20; // shorten total TCP packet size to 20 bytes (no data) - packetLength = 40; // shorten total packet size to 40 bytes (20 ip + 20 tcp) - pktLen[1] = 40; // shorten total packet size to 40 bytes (20 ip + 20 tcp) - flagsOut = TCP_FLAG_SYN | TCP_FLAG_ACK; // something wants to connect - acknowledge it - //ppp.seq = ppp.seq + 10000; // create a new sequence number (normally random) - seq_out = 10+((seq_in+1)/10)*10; //ppp.seq; // create a new sequence number (normally random) break; case TCP_FLAG_ACK | TCP_FLAG_PSH: flagsOut = TCP_FLAG_ACK | TCP_FLAG_FIN; // for every push we answer once AND close the link - fastResponse = 1; // we can respond fast to a push - if ( strncmp(dataStart, "GET ", 4) == 0) { // do we see an http GET command - dataLen = httpResponse(dataStart); // send an http response - while((dataLen %4 ) !=0) { // dataLen must be a multiple of four - dataLen++; // must be a multiple of four - dataStart[dataLen-1]=0; // clear the byte in the buffer - ack_out++; - } + if ( strncmp(tcpDataIn, "GET ", 4) == 0) { // check for an http GET command + dataLen = httpResponse(tcpDataOut); // send an http response } break; case TCP_FLAG_FIN: case TCP_FLAG_FIN | TCP_FLAG_ACK: - case TCP_FLAG_FIN | TCP_FLAG_ACK | TCP_FLAG_PSH: ack_out++; // for FIN flag we always have to increase sequence by 1 break; default: @@ -683,7 +682,7 @@ // The TCP flag handling is now done // Now we have to recalculate all the header sizes, swap IP address/port source and destination, and do the IP and TCP checksums - ppp.ident++; // + ppp.ident++; // get next ident number for our packet ident[0] = ppp.ident>>8; ident[1] = ppp.ident>>0; // insert OUR ident @@ -696,7 +695,7 @@ memcpy(srctcp, dsttcp,2); memcpy(dsttcp, tempHold,2); // swap ip port source/dest - windowsizetcp[0]=2; // ignore window size negotiation + windowsizetcp[0]=4; // ignore window size negotiation windowsizetcp[1]=0; // ignore winodw size negotiation acktcp[0]=ack_out>>24; @@ -726,7 +725,7 @@ // now we have to build the so-called 12-byte TCP "pseudo-header" in front of the TCP header (containing some IP header values) in order to correctly calculate the TCP checksum // this header contains the most important parts of the IP header, i.e. source and destination address, protocol number and data length. - char * pseudoHeader = s-12; // mark the start of the TCP pseudo-header + char * pseudoHeader = tcp-12; // mark the start of the TCP pseudo-header memcpy(tempHold, pseudoHeader, 12); // preserve the 12 bytes of the IP header where the TCP pseudo-Header will be built memcpy( pseudoHeader+0, srcAdr, 8); // IP source and destination addresses from IP header memset( pseudoHeader+8, 0, 1); // reserved, set to zero @@ -741,15 +740,8 @@ unsigned int pseudoHeaderSum=dataCheckSum((unsigned char *)pseudoHeader,tcpSize+12); // calculate the TCP checksum starting at the pseudo-header checksumtcp[0]=pseudoHeaderSum>>8; checksumtcp[1]=pseudoHeaderSum; - memcpy( s-12, tempHold, 12); // restore the 12 bytes that the pseudo-header overwrote + memcpy( tcp-12, tempHold, 12); // restore the 12 bytes that the pseudo-header overwrote - if (fastResponse==1) { - fastResponse=0; // reset and skip 200 ms wait - } else { - // normally, you wait 200 ms before responding to a TCP packet - // remove the wait to respond faster - // wait(0.2); - } sendFrame(); // All preparation complete - send the TCP response dumpHeaderIP(); dumpHeaderTCP();